Changeset 494c2e3 in rtems


Ignore:
Timestamp:
Apr 1, 2014, 9:48:59 AM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
1a6093d
Parents:
f570b071
git-author:
Sebastian Huber <sebastian.huber@…> (04/01/14 09:48:59)
git-committer:
Sebastian Huber <sebastian.huber@…> (04/03/14 09:13:26)
Message:

score: Move priority bit map to scheduler instance

Delete global variables _Priority_Major_bit_map and _Priority_Bit_map.
This makes it possible to use multiple priority scheduler instances for
example with clustered/partitioned scheduling on SMP.

Files:
2 deleted
22 edited

Legend:

Unmodified
Added
Removed
  • cpukit/sapi/include/confdefs.h

    rf570b071 r494c2e3  
    677677  #define CONFIGURE_MEMORY_FOR_SCHEDULER ( \
    678678    _Configure_From_workspace( \
    679       ((CONFIGURE_MAXIMUM_PRIORITY+1) * sizeof(Chain_Control)) ) \
    680   )
    681   #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
    682     _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) )
    683 #endif
    684 
    685 /*
    686  * If the Deterministic Priority SMP Scheduler is selected, then configure for
    687  * it.
    688  */
    689 #if defined(CONFIGURE_SCHEDULER_PRIORITY_SMP)
    690   #include <rtems/score/schedulerprioritysmp.h>
    691   #define CONFIGURE_SCHEDULER_ENTRY_POINTS SCHEDULER_PRIORITY_SMP_ENTRY_POINTS
    692 
    693   /**
    694    * This defines the memory used by the priority scheduler.
    695    */
    696   #define CONFIGURE_MEMORY_FOR_SCHEDULER ( \
    697     _Configure_From_workspace( \
    698       sizeof(Scheduler_SMP_Control) +  \
     679      sizeof(Scheduler_priority_Control) +  \
    699680      ((CONFIGURE_MAXIMUM_PRIORITY) * sizeof(Chain_Control)) ) \
    700681  )
     
    704685
    705686/*
     687 * If the Deterministic Priority SMP Scheduler is selected, then configure for
     688 * it.
     689 */
     690#if defined(CONFIGURE_SCHEDULER_PRIORITY_SMP)
     691  #include <rtems/score/schedulerprioritysmp.h>
     692  #define CONFIGURE_SCHEDULER_ENTRY_POINTS SCHEDULER_PRIORITY_SMP_ENTRY_POINTS
     693
     694  /**
     695   * This defines the memory used by the priority scheduler.
     696   */
     697  #define CONFIGURE_MEMORY_FOR_SCHEDULER ( \
     698    _Configure_From_workspace( \
     699      sizeof(Scheduler_priority_SMP_Control) +  \
     700      ((CONFIGURE_MAXIMUM_PRIORITY) * sizeof(Chain_Control)) ) \
     701  )
     702  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
     703    _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) )
     704#endif
     705
     706/*
    706707 * If the Simple Priority Scheduler is selected, then configure for it.
    707708 */
     
    732733   */
    733734  #define CONFIGURE_MEMORY_FOR_SCHEDULER ( \
    734     _Configure_From_workspace( sizeof( Scheduler_SMP_Control ) ) \
     735    _Configure_From_workspace( sizeof( Scheduler_simple_SMP_Control ) ) \
    735736  )
    736737  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER (0)
  • cpukit/score/Makefile.am

    rf570b071 r494c2e3  
    128128libscore_a_SOURCES += src/schedulerprioritysmp.c
    129129libscore_a_SOURCES += src/schedulersimplesmp.c
    130 libscore_a_SOURCES += src/schedulersmpstartidle.c
    131130libscore_a_SOURCES += src/smp.c
    132131libscore_a_SOURCES += src/cpuset.c
     
    192191## SCHEDULER_C_FILES
    193192libscore_a_SOURCES += src/log2table.c
    194 libscore_a_SOURCES += src/prioritybitmap.c
    195193libscore_a_SOURCES += src/scheduler.c
    196194libscore_a_SOURCES += src/schedulerdefaultallocatefree.c
  • cpukit/score/include/rtems/score/prioritybitmap.h

    rf570b071 r494c2e3  
    3838 */
    3939
     40typedef struct {
     41  /**
     42   * @brief Each sixteen bit entry in this word is associated with one of the
     43   * sixteen entries in the bit map.
     44   */
     45  Priority_bit_map_Word major_bit_map;
     46
     47  /**
     48   * @brief Each bit in the bit map indicates whether or not there are threads
     49   * ready at a particular priority.
     50   *
     51   * The mapping of individual priority levels to particular bits is processor
     52   * dependent as is the value of each bit used to indicate that threads are
     53   * ready at that priority.
     54   */
     55  Priority_bit_map_Word bit_map[ 16 ];
     56} Priority_bit_map_Control;
     57
    4058/**
    4159 *  The following record defines the information associated with
  • cpukit/score/include/rtems/score/prioritybitmapimpl.h

    rf570b071 r494c2e3  
    2323#include <rtems/score/priority.h>
    2424
     25#include <string.h>
     26
    2527#ifdef __cplusplus
    2628extern "C" {
     
    3133 */
    3234/**@{**/
    33 
    34 /*
    35  * The Priority_bit_map_Word variables are instantiated only
    36  * if using the bit map handler.
    37  */
    38 
    39 /**
    40  *  Each sixteen bit entry in this array is associated with one of
    41  *  the sixteen entries in the Priority Bit map.
    42  */
    43 extern volatile Priority_bit_map_Word _Priority_Major_bit_map;
    44 
    45 /** Each bit in the Priority Bitmap indicates whether or not there are
    46  *  threads ready at a particular priority.  The mapping of
    47  *  individual priority levels to particular bits is processor
    48  *  dependent as is the value of each bit used to indicate that
    49  *  threads are ready at that priority.
    50  */
    51 extern Priority_bit_map_Word
    52                _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT;
    5335
    5436#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE )
     
    189171#endif
    190172
     173RTEMS_INLINE_ROUTINE void _Priority_bit_map_Initialize(
     174  Priority_bit_map_Control *bit_map
     175)
     176{
     177  memset( bit_map, 0, sizeof( *bit_map ) );
     178}
     179
    191180/**
    192181 * Priority Queue implemented by bit map
    193182 */
    194183
    195 /**
    196  *  This is the minor bit map.
    197  */
    198 extern Priority_bit_map_Word _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT;
    199 
    200 /**
    201  * This routine uses the_priority_map to update the priority
    202  * bit maps to indicate that a thread has been readied.
    203  */
    204 
    205184RTEMS_INLINE_ROUTINE void _Priority_bit_map_Add (
    206   Priority_bit_map_Information *the_priority_map
    207 )
    208 {
    209   *the_priority_map->minor |= the_priority_map->ready_minor;
    210   _Priority_Major_bit_map  |= the_priority_map->ready_major;
    211 }
    212 
    213 /**
    214  * This routine uses the_priority_map to update the priority
    215  * bit maps to indicate that a thread has been removed from the
    216  * ready state.
    217  */
     185  Priority_bit_map_Control     *bit_map,
     186  Priority_bit_map_Information *bit_map_info
     187)
     188{
     189  *bit_map_info->minor |= bit_map_info->ready_minor;
     190  bit_map->major_bit_map |= bit_map_info->ready_major;
     191}
    218192
    219193RTEMS_INLINE_ROUTINE void _Priority_bit_map_Remove (
    220   Priority_bit_map_Information *the_priority_map
    221 )
    222 {
    223   *the_priority_map->minor &= the_priority_map->block_minor;
    224   if ( *the_priority_map->minor == 0 )
    225     _Priority_Major_bit_map &= the_priority_map->block_major;
    226 }
    227 
    228 /**
    229  * This function returns the priority of the highest priority
    230  * ready thread.
    231  */
    232 
    233 RTEMS_INLINE_ROUTINE Priority_Control _Priority_bit_map_Get_highest( void )
     194  Priority_bit_map_Control     *bit_map,
     195  Priority_bit_map_Information *bit_map_info
     196)
     197{
     198  *bit_map_info->minor &= bit_map_info->block_minor;
     199  if ( *bit_map_info->minor == 0 )
     200    bit_map->major_bit_map &= bit_map_info->block_major;
     201}
     202
     203RTEMS_INLINE_ROUTINE Priority_Control _Priority_bit_map_Get_highest(
     204  const Priority_bit_map_Control *bit_map
     205)
    234206{
    235207  Priority_bit_map_Word minor;
    236208  Priority_bit_map_Word major;
    237209
    238   _Bitfield_Find_first_bit( _Priority_Major_bit_map, major );
    239   _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor );
     210  /* Avoid problems with some inline ASM statements */
     211  Priority_bit_map_Word tmp;
     212
     213  tmp = bit_map->major_bit_map;
     214  _Bitfield_Find_first_bit( tmp, major );
     215
     216  tmp = bit_map->bit_map[ major ];
     217  _Bitfield_Find_first_bit( tmp, minor );
    240218
    241219  return (_Priority_Bits_index( major ) << 4) +
     
    243221}
    244222
    245 RTEMS_INLINE_ROUTINE bool _Priority_bit_map_Is_empty( void )
    246 {
    247   return _Priority_Major_bit_map == 0;
    248 }
    249 
    250 /**
    251  * This routine initializes the_priority_map so that it
    252  * contains the information necessary to manage a thread
    253  * at new_priority.
    254  */
     223RTEMS_INLINE_ROUTINE bool _Priority_bit_map_Is_empty(
     224  const Priority_bit_map_Control *bit_map
     225)
     226{
     227  return bit_map->major_bit_map == 0;
     228}
    255229
    256230RTEMS_INLINE_ROUTINE void _Priority_bit_map_Initialize_information(
    257   Priority_bit_map_Information *the_priority_map,
    258   Priority_Control      new_priority
     231  Priority_bit_map_Control     *bit_map,
     232  Priority_bit_map_Information *bit_map_info,
     233  Priority_Control              new_priority
    259234)
    260235{
     
    266241  minor = _Priority_Minor( new_priority );
    267242
    268   the_priority_map->minor =
    269     &_Priority_Bit_map[ _Priority_Bits_index(major) ];
     243  bit_map_info->minor = &bit_map->bit_map[ _Priority_Bits_index( major ) ];
    270244
    271245  mask = _Priority_Mask( major );
    272   the_priority_map->ready_major = mask;
     246  bit_map_info->ready_major = mask;
    273247  /* Add _Priority_Mask_invert to non-generic bitfield then change this code. */
    274   the_priority_map->block_major = (Priority_bit_map_Word)(~((uint32_t)mask));
     248  bit_map_info->block_major = (Priority_bit_map_Word)(~((uint32_t)mask));
    275249
    276250  mask = _Priority_Mask( minor );
    277   the_priority_map->ready_minor = mask;
     251  bit_map_info->ready_minor = mask;
    278252  /* Add _Priority_Mask_invert to non-generic bitfield then change this code. */
    279   the_priority_map->block_minor = (Priority_bit_map_Word)(~((uint32_t)mask));
     253  bit_map_info->block_minor = (Priority_bit_map_Word)(~((uint32_t)mask));
    280254}
    281255
  • cpukit/score/include/rtems/score/schedulerpriority.h

    rf570b071 r494c2e3  
    5757  }
    5858
     59typedef struct {
     60  /**
     61   * @brief Bit map to indicate non-empty ready queues.
     62   */
     63  Priority_bit_map_Control Bit_map;
     64
     65  /**
     66   * @brief One ready queue per priority level.
     67   */
     68  Chain_Control Ready[ 1 ];
     69} Scheduler_priority_Control;
     70
    5971/**
    6072 * Per-thread data related to the _Scheduler_PRIORITY scheduling policy.
  • cpukit/score/include/rtems/score/schedulerpriorityimpl.h

    rf570b071 r494c2e3  
    3636/**@{**/
    3737
    38 RTEMS_INLINE_ROUTINE Chain_Control *
    39 _Scheduler_priority_Get_ready_queues( void )
    40 {
    41   return ( Chain_Control * ) _Scheduler.information;
     38RTEMS_INLINE_ROUTINE Scheduler_priority_Control *
     39  _Scheduler_priority_Instance( void )
     40{
     41  return _Scheduler.information;
    4242}
    4343
     
    4545 * @brief Ready queue initialization.
    4646 *
    47  * This routine initializes @a the_ready_queue for priority-based scheduling.
     47 * This routine initializes @a ready_queues for priority-based scheduling.
    4848 */
    4949RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_initialize(
     
    6969 * This routine puts @a the_thread on to the priority-based ready queue.
    7070 *
    71  * @param[in] the_thread is a pointer to the thread
     71 * @param[in] the_thread The thread to enqueue.
     72 * @param[in] bit_map The priority bit map of the scheduler instance.
    7273 */
    7374RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_enqueue(
    74   Thread_Control                  *the_thread
     75  Thread_Control           *the_thread,
     76  Priority_bit_map_Control *bit_map
    7577)
    7678{
     
    8082
    8183  _Chain_Append_unprotected( ready_chain, &the_thread->Object.Node );
    82   _Priority_bit_map_Add( &sched_info_of_thread->Priority_map );
     84  _Priority_bit_map_Add( bit_map, &sched_info_of_thread->Priority_map );
    8385}
    8486
     
    9092 * at its priority level.
    9193 *
    92  * @param[in] the_thread is a pointer to the thread.
     94 * @param[in] the_thread The thread to enqueue.
     95 * @param[in] bit_map The priority bit map of the scheduler instance.
    9396 */
    9497RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_enqueue_first(
    95   Thread_Control                   *the_thread
     98  Thread_Control           *the_thread,
     99  Priority_bit_map_Control *bit_map
    96100)
    97101{
     
    101105
    102106  _Chain_Prepend_unprotected( ready_chain, &the_thread->Object.Node );
    103   _Priority_bit_map_Add( &sched_info_of_thread->Priority_map );
     107  _Priority_bit_map_Add( bit_map, &sched_info_of_thread->Priority_map );
    104108}
    105109
     
    110114 * priority-based ready queue.
    111115 *
    112  * @param[in] the_thread is a pointer to the thread.
     116 * @param[in] the_thread The thread to extract.
     117 * @param[in] bit_map The priority bit map of the scheduler instance.
    113118 */
    114119RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_extract(
    115   Thread_Control        *the_thread
     120  Thread_Control           *the_thread,
     121  Priority_bit_map_Control *bit_map
    116122)
    117123{
     
    122128  if ( _Chain_Has_only_one_node( ready_chain ) ) {
    123129    _Chain_Initialize_empty( ready_chain );
    124     _Priority_bit_map_Remove( &sched_info_of_thread->Priority_map );
     130    _Priority_bit_map_Remove( bit_map, &sched_info_of_thread->Priority_map );
    125131  } else {
    126132    _Chain_Extract_unprotected( &the_thread->Object.Node );
     
    128134}
    129135
     136RTEMS_INLINE_ROUTINE void _Scheduler_priority_Extract_body(
     137  Thread_Control *the_thread
     138)
     139{
     140  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     141
     142  _Scheduler_priority_Ready_queue_extract( the_thread, &scheduler->Bit_map );
     143}
     144
    130145/**
    131146 * @brief Return a pointer to the first thread.
    132147 *
    133  * This routines returns a pointer to the first thread on @a the_ready_queue.
    134  *
    135  * @param[in] the_ready_queue - pointer to thread queue
     148 * This routines returns a pointer to the first thread on @a ready_queues.
     149 *
     150 * @param[in] bit_map The priority bit map of the scheduler instance.
     151 * @param[in] ready_queues The ready queues of the scheduler instance.
    136152 *
    137153 * @return This method returns the first thread or NULL
    138154 */
    139155RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_priority_Ready_queue_first(
    140   Chain_Control       *the_ready_queue
    141 )
    142 {
    143   Priority_Control index = _Priority_bit_map_Get_highest();
    144 
    145   return (Thread_Control *) _Chain_First( &the_ready_queue[ index ] );
     156  Priority_bit_map_Control *bit_map,
     157  Chain_Control            *ready_queues
     158)
     159{
     160  Priority_Control index = _Priority_bit_map_Get_highest( bit_map );
     161
     162  return (Thread_Control *) _Chain_First( &ready_queues[ index ] );
    146163}
    147164
     
    179196)
    180197{
    181   Chain_Control *ready_queues = _Scheduler_priority_Get_ready_queues();
    182   Thread_Control *heir = _Scheduler_priority_Ready_queue_first( ready_queues );
     198  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     199  Thread_Control *heir = _Scheduler_priority_Ready_queue_first(
     200    &scheduler->Bit_map,
     201    &scheduler->Ready[ 0 ]
     202  );
    183203
    184204  ( void ) thread;
     
    188208
    189209RTEMS_INLINE_ROUTINE void _Scheduler_priority_Update_body(
    190   Thread_Control *thread,
    191   Chain_Control *ready_queues
     210  Thread_Control           *thread,
     211  Priority_bit_map_Control *bit_map,
     212  Chain_Control            *ready_queues
    192213)
    193214{
     
    199220
    200221  _Priority_bit_map_Initialize_information(
     222    bit_map,
    201223    &sched_info_of_thread->Priority_map,
    202224    thread->current_priority
  • cpukit/score/include/rtems/score/schedulerprioritysmp.h

    rf570b071 r494c2e3  
    6767    _Scheduler_default_Release_job, \
    6868    _Scheduler_default_Tick, \
    69     _Scheduler_SMP_Start_idle \
     69    _Scheduler_priority_SMP_Start_idle \
    7070  }
    7171
     
    8686void _Scheduler_priority_SMP_Yield( Thread_Control *thread );
    8787
     88void _Scheduler_priority_SMP_Start_idle(
     89  Thread_Control *thread,
     90  Per_CPU_Control *cpu
     91);
     92
    8893/** @} */
    8994
  • cpukit/score/include/rtems/score/schedulersimplesmp.h

    rf570b071 r494c2e3  
    6969    _Scheduler_default_Release_job, \
    7070    _Scheduler_default_Tick, \
    71     _Scheduler_SMP_Start_idle \
     71    _Scheduler_simple_smp_Start_idle \
    7272  }
    7373
     
    8686void _Scheduler_simple_smp_Schedule( Thread_Control *thread );
    8787
     88void _Scheduler_simple_smp_Start_idle(
     89  Thread_Control *thread,
     90  Per_CPU_Control *cpu
     91);
     92
    8893/** @} */
    8994
  • cpukit/score/include/rtems/score/schedulersmp.h

    rf570b071 r494c2e3  
    88
    99/*
    10  * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
     10 * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
    1111 *
    1212 *  embedded brains GmbH
     
    2626#include <rtems/score/chain.h>
    2727#include <rtems/score/percpu.h>
     28#include <rtems/score/prioritybitmap.h>
    2829#include <rtems/score/thread.h>
    2930
     
    4142
    4243typedef struct {
    43   Chain_Control scheduled;
    44   Chain_Control ready[ 1 ];
     44  Chain_Control Scheduled;
    4545} Scheduler_SMP_Control;
    4646
    47 void _Scheduler_SMP_Start_idle(
    48   Thread_Control *thread,
    49   Per_CPU_Control *cpu
    50 );
     47typedef struct {
     48  Scheduler_SMP_Control Base;
     49  Chain_Control         Ready;
     50} Scheduler_simple_SMP_Control;
     51
     52typedef struct {
     53  Scheduler_SMP_Control    Base;
     54  Priority_bit_map_Control Bit_map;
     55  Chain_Control            Ready[ 1 ];
     56} Scheduler_priority_SMP_Control;
    5157
    5258/** @} */
  • cpukit/score/include/rtems/score/schedulersmpimpl.h

    rf570b071 r494c2e3  
    88
    99/*
    10  * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
     10 * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
    1111 *
    1212 *  embedded brains GmbH
     
    5858);
    5959
    60 static inline Scheduler_SMP_Control *_Scheduler_SMP_Instance( void )
    61 {
    62   return _Scheduler.information;
     60static inline void _Scheduler_SMP_Initialize(
     61  Scheduler_SMP_Control *self
     62)
     63{
     64  _Chain_Initialize_empty( &self->Scheduled );
    6365}
    6466
     
    110112{
    111113  Thread_Control *lowest_ready = NULL;
    112   Chain_Control *scheduled = &self->scheduled;
     114  Chain_Control *scheduled = &self->Scheduled;
    113115
    114116  if ( !_Chain_Is_empty( scheduled ) ) {
     
    245247{
    246248  _Chain_Insert_ordered_unprotected(
    247     &self->scheduled,
     249    &self->Scheduled,
    248250    &thread->Object.Node,
    249251    _Scheduler_simple_Insert_priority_lifo_order
     
    257259{
    258260  _Chain_Insert_ordered_unprotected(
    259     &self->scheduled,
     261    &self->Scheduled,
    260262    &thread->Object.Node,
    261263    _Scheduler_simple_Insert_priority_fifo_order
     
    263265}
    264266
     267static inline void _Scheduler_SMP_Start_idle(
     268  Scheduler_SMP_Control *self,
     269  Thread_Control *thread,
     270  Per_CPU_Control *cpu
     271)
     272{
     273  thread->is_scheduled = true;
     274  _Thread_Set_CPU( thread, cpu );
     275  _Chain_Append_unprotected( &self->Scheduled, &thread->Object.Node );
     276}
     277
    265278/** @} */
    266279
  • cpukit/score/src/schedulerpriority.c

    rf570b071 r494c2e3  
    2424void _Scheduler_priority_Initialize(void)
    2525{
    26   /* allocate ready queue structures */
    27   Chain_Control *ready_queues = _Workspace_Allocate_or_fatal_error(
    28     ((size_t) PRIORITY_MAXIMUM + 1) * sizeof(Chain_Control)
     26  Scheduler_priority_Control *self = _Workspace_Allocate_or_fatal_error(
     27    sizeof( *self ) + PRIORITY_MAXIMUM * sizeof( Chain_Control )
    2928  );
    3029
    31   _Scheduler_priority_Ready_queue_initialize( ready_queues );
     30  _Priority_bit_map_Initialize( &self->Bit_map );
     31  _Scheduler_priority_Ready_queue_initialize( &self->Ready[ 0 ] );
    3232
    33   _Scheduler.information = ready_queues;
     33  _Scheduler.information = self;
    3434}
  • cpukit/score/src/schedulerpriorityblock.c

    rf570b071 r494c2e3  
    2323#include <rtems/score/schedulerpriorityimpl.h>
    2424
    25 void _Scheduler_priority_Block(
    26   Thread_Control   *the_thread
    27 )
     25void _Scheduler_priority_Block( Thread_Control *the_thread )
    2826{
    2927  _Scheduler_Generic_block(
    30     _Scheduler_priority_Ready_queue_extract,
     28    _Scheduler_priority_Extract_body,
    3129    _Scheduler_priority_Schedule_body,
    3230    the_thread
  • cpukit/score/src/schedulerpriorityenqueue.c

    rf570b071 r494c2e3  
    2525)
    2626{
    27    _Scheduler_priority_Ready_queue_enqueue( the_thread );
     27  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     28
     29  _Scheduler_priority_Ready_queue_enqueue( the_thread, &scheduler->Bit_map );
    2830}
  • cpukit/score/src/schedulerpriorityenqueuefirst.c

    rf570b071 r494c2e3  
    2525)
    2626{
    27   _Scheduler_priority_Ready_queue_enqueue_first( the_thread );
     27  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     28
     29  _Scheduler_priority_Ready_queue_enqueue_first(
     30    the_thread,
     31    &scheduler->Bit_map
     32  );
    2833}
    2934
  • cpukit/score/src/schedulerpriorityextract.c

    rf570b071 r494c2e3  
    2222#include <rtems/score/schedulerpriorityimpl.h>
    2323
    24 void _Scheduler_priority_Extract(
    25   Thread_Control      *the_thread
    26 )
     24void _Scheduler_priority_Extract( Thread_Control *the_thread )
    2725{
    28   _Scheduler_priority_Ready_queue_extract( the_thread );
     26  _Scheduler_priority_Extract_body( the_thread );
    2927}
  • cpukit/score/src/schedulerprioritysmp.c

    rf570b071 r494c2e3  
    88
    99/*
    10  * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
     10 * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
    1111 *
    1212 *  embedded brains GmbH
     
    3030#include <rtems/score/wkspace.h>
    3131
     32static Scheduler_priority_SMP_Control *_Scheduler_priority_SMP_Instance( void )
     33{
     34  return _Scheduler.information;
     35}
     36
     37static Scheduler_priority_SMP_Control *
     38_Scheduler_priority_SMP_Self_from_SMP_base( Scheduler_SMP_Control *base )
     39{
     40  return (Scheduler_priority_SMP_Control *)
     41    ( (char *) base
     42      - offsetof( Scheduler_priority_SMP_Control, Base ) );
     43}
     44
    3245void _Scheduler_priority_SMP_Initialize( void )
    3346{
    34   Scheduler_SMP_Control *self = _Workspace_Allocate_or_fatal_error(
     47  Scheduler_priority_SMP_Control *self = _Workspace_Allocate_or_fatal_error(
    3548    sizeof( *self ) + PRIORITY_MAXIMUM * sizeof( Chain_Control )
    3649  );
    3750
    38   _Chain_Initialize_empty( &self->scheduled );
    39   _Scheduler_priority_Ready_queue_initialize( &self->ready[ 0 ] );
     51  _Scheduler_SMP_Initialize( &self->Base );
     52  _Priority_bit_map_Initialize( &self->Bit_map );
     53  _Scheduler_priority_Ready_queue_initialize( &self->Ready[ 0 ] );
    4054
    4155  _Scheduler.information = self;
     
    4458void _Scheduler_priority_SMP_Update( Thread_Control *thread )
    4559{
    46   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
    47 
    48   _Scheduler_priority_Update_body( thread, &self->ready[ 0 ] );
     60  Scheduler_priority_SMP_Control *self = _Scheduler_priority_SMP_Instance();
     61
     62  _Scheduler_priority_Update_body(
     63    thread,
     64    &self->Bit_map,
     65    &self->Ready[ 0 ]
     66  );
    4967}
    5068
    5169static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
    52   Scheduler_SMP_Control *self
    53 )
    54 {
     70  Scheduler_SMP_Control *base
     71)
     72{
     73  Scheduler_priority_SMP_Control *self =
     74    _Scheduler_priority_SMP_Self_from_SMP_base( base );
    5575  Thread_Control *highest_ready = NULL;
    5676
    57   if ( !_Priority_bit_map_Is_empty() ) {
    58     highest_ready = _Scheduler_priority_Ready_queue_first( &self->ready[ 0 ] );
     77  if ( !_Priority_bit_map_Is_empty( &self->Bit_map ) ) {
     78    highest_ready = _Scheduler_priority_Ready_queue_first(
     79      &self->Bit_map,
     80      &self->Ready[ 0 ]
     81    );
    5982  }
    6083
     
    6386
    6487static void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
    65   Scheduler_SMP_Control *self,
     88  Scheduler_SMP_Control *base,
    6689  Thread_Control *scheduled_to_ready
    6790)
    6891{
     92  Scheduler_priority_SMP_Control *self =
     93    _Scheduler_priority_SMP_Self_from_SMP_base( base );
     94
    6995  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
    70   _Scheduler_priority_Ready_queue_enqueue_first( scheduled_to_ready );
     96  _Scheduler_priority_Ready_queue_enqueue_first(
     97    scheduled_to_ready,
     98    &self->Bit_map
     99  );
    71100}
    72101
    73102static void _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
    74   Scheduler_SMP_Control *self,
     103  Scheduler_SMP_Control *base,
    75104  Thread_Control *ready_to_scheduled
    76105)
    77106{
    78   _Scheduler_priority_Ready_queue_extract( ready_to_scheduled );
     107  Scheduler_priority_SMP_Control *self =
     108    _Scheduler_priority_SMP_Self_from_SMP_base( base );
     109
     110  _Scheduler_priority_Ready_queue_extract(
     111    ready_to_scheduled,
     112    &self->Bit_map
     113  );
    79114  _Scheduler_simple_Insert_priority_fifo(
    80     &self->scheduled,
     115    &self->Base.Scheduled,
    81116    ready_to_scheduled
    82117  );
     
    84119
    85120static void _Scheduler_priority_SMP_Insert_ready_lifo(
    86   Scheduler_SMP_Control *self,
     121  Scheduler_SMP_Control *base,
    87122  Thread_Control *thread
    88123)
    89124{
    90   _Scheduler_priority_Ready_queue_enqueue( thread );
     125  Scheduler_priority_SMP_Control *self =
     126    _Scheduler_priority_SMP_Self_from_SMP_base( base );
     127
     128  _Scheduler_priority_Ready_queue_enqueue( thread, &self->Bit_map );
    91129}
    92130
    93131static void _Scheduler_priority_SMP_Insert_ready_fifo(
    94   Scheduler_SMP_Control *self,
     132  Scheduler_SMP_Control *base,
    95133  Thread_Control *thread
    96134)
    97135{
    98   _Scheduler_priority_Ready_queue_enqueue_first( thread );
     136  Scheduler_priority_SMP_Control *self =
     137    _Scheduler_priority_SMP_Self_from_SMP_base( base );
     138
     139  _Scheduler_priority_Ready_queue_enqueue_first( thread, &self->Bit_map );
    99140}
    100141
    101142static void _Scheduler_priority_SMP_Do_extract(
    102   Scheduler_SMP_Control *self,
     143  Scheduler_SMP_Control *base,
    103144  Thread_Control *thread
    104145)
    105146{
     147  Scheduler_priority_SMP_Control *self =
     148    _Scheduler_priority_SMP_Self_from_SMP_base( base );
    106149  bool is_scheduled = thread->is_scheduled;
    107 
    108   ( void ) self;
    109150
    110151  thread->is_in_the_air = is_scheduled;
     
    114155    _Chain_Extract_unprotected( &thread->Object.Node );
    115156  } else {
    116     _Scheduler_priority_Ready_queue_extract( thread );
     157    _Scheduler_priority_Ready_queue_extract( thread, &self->Bit_map );
    117158  }
    118159}
     
    120161void _Scheduler_priority_SMP_Block( Thread_Control *thread )
    121162{
    122   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     163  Scheduler_priority_SMP_Control *self = _Scheduler_priority_SMP_Instance();
    123164
    124165  _Scheduler_SMP_Block(
    125     self,
     166    &self->Base,
    126167    thread,
    127168    _Scheduler_priority_SMP_Do_extract,
     
    153194void _Scheduler_priority_SMP_Enqueue_lifo( Thread_Control *thread )
    154195{
    155   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     196  Scheduler_priority_SMP_Control *self = _Scheduler_priority_SMP_Instance();
    156197
    157198  _Scheduler_priority_SMP_Enqueue_ordered(
    158     self,
     199    &self->Base,
    159200    thread,
    160201    _Scheduler_simple_Insert_priority_lifo_order,
     
    166207void _Scheduler_priority_SMP_Enqueue_fifo( Thread_Control *thread )
    167208{
    168   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     209  Scheduler_priority_SMP_Control *self = _Scheduler_priority_SMP_Instance();
    169210
    170211  _Scheduler_priority_SMP_Enqueue_ordered(
    171     self,
     212    &self->Base,
    172213    thread,
    173214    _Scheduler_simple_Insert_priority_fifo_order,
     
    179220void _Scheduler_priority_SMP_Extract( Thread_Control *thread )
    180221{
    181   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     222  Scheduler_priority_SMP_Control *self = _Scheduler_priority_SMP_Instance();
    182223
    183224  _Scheduler_SMP_Extract(
    184     self,
     225    &self->Base,
    185226    thread,
    186227    _Scheduler_priority_SMP_Do_extract
     
    202243void _Scheduler_priority_SMP_Schedule( Thread_Control *thread )
    203244{
    204   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     245  Scheduler_priority_SMP_Control *self = _Scheduler_priority_SMP_Instance();
    205246
    206247  _Scheduler_SMP_Schedule(
    207     self,
     248    &self->Base,
    208249    thread,
    209250    _Scheduler_priority_SMP_Get_highest_ready,
     
    211252  );
    212253}
     254
     255void _Scheduler_priority_SMP_Start_idle(
     256  Thread_Control *thread,
     257  Per_CPU_Control *cpu
     258)
     259{
     260  Scheduler_priority_SMP_Control *self = _Scheduler_priority_SMP_Instance();
     261
     262  _Scheduler_SMP_Start_idle( &self->Base, thread, cpu );
     263}
  • cpukit/score/src/schedulerpriorityunblock.c

    rf570b071 r494c2e3  
    2727)
    2828{
    29   _Scheduler_priority_Ready_queue_enqueue(the_thread);
     29  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     30
     31  _Scheduler_priority_Ready_queue_enqueue( the_thread, &scheduler->Bit_map );
    3032
    3133  /* TODO: flash critical section? */
  • cpukit/score/src/schedulerpriorityupdate.c

    rf570b071 r494c2e3  
    2626)
    2727{
    28   Chain_Control *ready_queues = _Scheduler_priority_Get_ready_queues();
     28  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
    2929
    30   _Scheduler_priority_Update_body( the_thread, ready_queues );
     30  _Scheduler_priority_Update_body(
     31    the_thread,
     32    &scheduler->Bit_map,
     33    &scheduler->Ready[ 0 ]
     34  );
    3135}
  • cpukit/score/src/schedulersimplesmp.c

    rf570b071 r494c2e3  
    88
    99/*
    10  * Copyright (c) 2013 embedded brains GmbH.
     10 * Copyright (c) 2013-2014 embedded brains GmbH.
    1111 *
    1212 * The license and distribution terms for this file may be
     
    2323#include <rtems/score/wkspace.h>
    2424
     25static Scheduler_simple_SMP_Control *_Scheduler_simple_SMP_Instance( void )
     26{
     27  return _Scheduler.information;
     28}
     29
     30static Scheduler_simple_SMP_Control *
     31_Scheduler_simple_SMP_Self_from_SMP_base( Scheduler_SMP_Control *base )
     32{
     33  return (Scheduler_simple_SMP_Control *)
     34    ( (char *) base - offsetof( Scheduler_simple_SMP_Control, Base ) );
     35}
     36
    2537void _Scheduler_simple_smp_Initialize( void )
    2638{
    27   Scheduler_SMP_Control *self =
     39  Scheduler_simple_SMP_Control *self =
    2840    _Workspace_Allocate_or_fatal_error( sizeof( *self ) );
    2941
    30   _Chain_Initialize_empty( &self->ready[ 0 ] );
    31   _Chain_Initialize_empty( &self->scheduled );
     42  _Scheduler_SMP_Initialize( &self->Base );
     43  _Chain_Initialize_empty( &self->Ready );
    3244
    3345  _Scheduler.information = self;
     
    3547
    3648static Thread_Control *_Scheduler_simple_smp_Get_highest_ready(
    37   Scheduler_SMP_Control *self
    38 )
    39 {
     49  Scheduler_SMP_Control *base
     50)
     51{
     52  Scheduler_simple_SMP_Control *self =
     53    _Scheduler_simple_SMP_Self_from_SMP_base( base );
    4054  Thread_Control *highest_ready = NULL;
    41   Chain_Control *ready = &self->ready[ 0 ];
     55  Chain_Control *ready = &self->Ready;
    4256
    4357  if ( !_Chain_Is_empty( ready ) ) {
     
    4963
    5064static void _Scheduler_simple_smp_Move_from_scheduled_to_ready(
    51   Scheduler_SMP_Control *self,
     65  Scheduler_SMP_Control *base,
    5266  Thread_Control *scheduled_to_ready
    5367)
    5468{
     69  Scheduler_simple_SMP_Control *self =
     70    _Scheduler_simple_SMP_Self_from_SMP_base( base );
     71
    5572  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
    5673  _Scheduler_simple_Insert_priority_lifo(
    57     &self->ready[ 0 ],
     74    &self->Ready,
    5875    scheduled_to_ready
    5976  );
     
    6178
    6279static void _Scheduler_simple_smp_Move_from_ready_to_scheduled(
    63   Scheduler_SMP_Control *self,
     80  Scheduler_SMP_Control *base,
    6481  Thread_Control *ready_to_scheduled
    6582)
     
    6784  _Chain_Extract_unprotected( &ready_to_scheduled->Object.Node );
    6885  _Scheduler_simple_Insert_priority_fifo(
    69     &self->scheduled,
     86    &base->Scheduled,
    7087    ready_to_scheduled
    7188  );
     
    7390
    7491static void _Scheduler_simple_smp_Insert_ready_lifo(
    75   Scheduler_SMP_Control *self,
     92  Scheduler_SMP_Control *base,
    7693  Thread_Control *thread
    7794)
    7895{
     96  Scheduler_simple_SMP_Control *self =
     97    _Scheduler_simple_SMP_Self_from_SMP_base( base );
     98
    7999  _Chain_Insert_ordered_unprotected(
    80     &self->ready[ 0 ],
     100    &self->Ready,
    81101    &thread->Object.Node,
    82102    _Scheduler_simple_Insert_priority_lifo_order
     
    85105
    86106static void _Scheduler_simple_smp_Insert_ready_fifo(
    87   Scheduler_SMP_Control *self,
     107  Scheduler_SMP_Control *base,
    88108  Thread_Control *thread
    89109)
    90110{
     111  Scheduler_simple_SMP_Control *self =
     112    _Scheduler_simple_SMP_Self_from_SMP_base( base );
     113
    91114  _Chain_Insert_ordered_unprotected(
    92     &self->ready[ 0 ],
     115    &self->Ready,
    93116    &thread->Object.Node,
    94117    _Scheduler_simple_Insert_priority_fifo_order
     
    97120
    98121static void _Scheduler_simple_smp_Do_extract(
    99   Scheduler_SMP_Control *self,
     122  Scheduler_SMP_Control *base,
    100123  Thread_Control *thread
    101124)
    102125{
    103   ( void ) self;
     126  (void) base;
    104127
    105128  thread->is_in_the_air = thread->is_scheduled;
     
    111134void _Scheduler_simple_smp_Block( Thread_Control *thread )
    112135{
    113   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     136  Scheduler_simple_SMP_Control *self = _Scheduler_simple_SMP_Instance();
    114137
    115138  _Scheduler_SMP_Block(
    116     self,
     139    &self->Base,
    117140    thread,
    118141    _Scheduler_simple_smp_Do_extract,
     
    123146
    124147static void _Scheduler_simple_smp_Enqueue_ordered(
    125   Scheduler_SMP_Control *self,
     148  Scheduler_SMP_Control *base,
    126149  Thread_Control *thread,
    127150  Chain_Node_order order,
     
    131154{
    132155  _Scheduler_SMP_Enqueue_ordered(
    133     self,
     156    base,
    134157    thread,
    135158    order,
     
    144167void _Scheduler_simple_smp_Enqueue_priority_lifo( Thread_Control *thread )
    145168{
    146   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     169  Scheduler_simple_SMP_Control *self = _Scheduler_simple_SMP_Instance();
    147170
    148171  _Scheduler_simple_smp_Enqueue_ordered(
    149     self,
     172    &self->Base,
    150173    thread,
    151174    _Scheduler_simple_Insert_priority_lifo_order,
     
    157180void _Scheduler_simple_smp_Enqueue_priority_fifo( Thread_Control *thread )
    158181{
    159   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     182  Scheduler_simple_SMP_Control *self = _Scheduler_simple_SMP_Instance();
    160183
    161184  _Scheduler_simple_smp_Enqueue_ordered(
    162     self,
     185    &self->Base,
    163186    thread,
    164187    _Scheduler_simple_Insert_priority_fifo_order,
     
    170193void _Scheduler_simple_smp_Extract( Thread_Control *thread )
    171194{
    172   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     195  Scheduler_simple_SMP_Control *self = _Scheduler_simple_SMP_Instance();
    173196
    174197  _Scheduler_SMP_Extract(
    175     self,
     198    &self->Base,
    176199    thread,
    177200    _Scheduler_simple_smp_Do_extract
     
    193216void _Scheduler_simple_smp_Schedule( Thread_Control *thread )
    194217{
    195   Scheduler_SMP_Control *self = _Scheduler_SMP_Instance();
     218  Scheduler_simple_SMP_Control *self = _Scheduler_simple_SMP_Instance();
    196219
    197220  _Scheduler_SMP_Schedule(
    198     self,
     221    &self->Base,
    199222    thread,
    200223    _Scheduler_simple_smp_Get_highest_ready,
     
    202225  );
    203226}
     227
     228void _Scheduler_simple_smp_Start_idle(
     229  Thread_Control *thread,
     230  Per_CPU_Control *cpu
     231)
     232{
     233  Scheduler_simple_SMP_Control *self = _Scheduler_simple_SMP_Instance();
     234
     235  _Scheduler_SMP_Start_idle( &self->Base, thread, cpu );
     236}
  • testsuites/sptests/spsize/size.c

    rf570b071 r494c2e3  
    8686
    8787/* Priority scheduling uninitialized (globals) consumption */
    88 #define SCHEDULER_OVHD     ((sizeof _Scheduler)              + \
    89                            (sizeof _Priority_Major_bit_map) + \
    90                            (sizeof _Priority_Bit_map))
     88#define SCHEDULER_OVHD      (sizeof _Scheduler)
    9189
    9290/* Priority scheduling per-thread consumption. Gets
     
    10199 */
    102100#define SCHEDULER_WKSP_SIZE  \
    103     ((RTEMS_MAXIMUM_PRIORITY + 1) * sizeof(Chain_Control ))
     101    (sizeof(Scheduler_priority_Control) + \
     102     RTEMS_MAXIMUM_PRIORITY * sizeof(Chain_Control ))
    104103/****** END OF MEMORY USAGE OF DEFAULT PRIORITY SCHEDULER ******/
    105104
  • testsuites/tmtests/tm26/task1.c

    rf570b071 r494c2e3  
    2020#include <timesys.h>
    2121
     22#include <rtems/score/schedulerpriorityimpl.h>
    2223#include <rtems/rtems/semimpl.h>
    2324
     
    371372)
    372373{
    373   Chain_Control   *ready_queues;
     374  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
    374375
    375376  thread_dispatch_no_fp_time = benchmark_timer_read();
     
    379380  Middle_tcb   = _Thread_Get_executing();
    380381
    381   ready_queues      = (Chain_Control *) _Scheduler.information;
    382382  set_thread_executing(
    383     (Thread_Control *) _Chain_First(&ready_queues[LOW_PRIORITY])
     383    (Thread_Control *) _Chain_First(&scheduler->Ready[LOW_PRIORITY])
    384384  );
    385385
     
    404404)
    405405{
    406   Thread_Control *executing;
    407   Chain_Control  *ready_queues;
    408 
    409   ready_queues      = (Chain_Control *) _Scheduler.information;
     406  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     407  Thread_Control             *executing;
    410408
    411409  context_switch_no_fp_time = benchmark_timer_read();
     
    425423
    426424  set_thread_executing(
    427     (Thread_Control *) _Chain_First(&ready_queues[FP1_PRIORITY])
     425    (Thread_Control *) _Chain_First(&scheduler->Ready[FP1_PRIORITY])
    428426  );
    429427
     
    448446)
    449447{
    450   Chain_Control   *ready_queues;
    451   Thread_Control  *executing;
     448  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     449  Thread_Control             *executing;
    452450  FP_DECLARE;
    453451
     
    456454  executing = _Thread_Get_executing();
    457455
    458   ready_queues      = (Chain_Control *) _Scheduler.information;
    459456  set_thread_executing(
    460     (Thread_Control *) _Chain_First(&ready_queues[FP2_PRIORITY])
     457    (Thread_Control *) _Chain_First(&scheduler->Ready[FP2_PRIORITY])
    461458  );
    462459
     
    484481  executing = _Thread_Get_executing();
    485482
    486   ready_queues      = (Chain_Control *) _Scheduler.information;
    487483  set_thread_executing(
    488     (Thread_Control *) _Chain_First(&ready_queues[FP2_PRIORITY])
     484    (Thread_Control *) _Chain_First(&scheduler->Ready[FP2_PRIORITY])
    489485  );
    490486
     
    505501)
    506502{
    507   Chain_Control  *ready_queues;
    508   Thread_Control *executing;
     503  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
     504  Thread_Control             *executing;
    509505  FP_DECLARE;
    510506
     
    513509  executing = _Thread_Get_executing();
    514510
    515   ready_queues      = (Chain_Control *) _Scheduler.information;
    516511  set_thread_executing(
    517     (Thread_Control *) _Chain_First(&ready_queues[FP1_PRIORITY])
     512    (Thread_Control *) _Chain_First(&scheduler->Ready[FP1_PRIORITY])
    518513  );
    519514
  • testsuites/tmtests/tm27/task1.c

    rf570b071 r494c2e3  
    2121#include "system.h"
    2222
     23#include <rtems/score/schedulerpriorityimpl.h>
    2324#include <bsp.h>
    2425
     
    102103)
    103104{
     105  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
    104106#if defined(RTEMS_SMP)
    105107  rtems_interrupt_level level;
    106108#endif
    107   Chain_Control   *ready_queues;
    108109
    109110  Install_tm27_vector( Isr_handler );
     
    186187#endif
    187188
    188   ready_queues      = (Chain_Control *) _Scheduler.information;
    189189  _Thread_Executing =
    190         (Thread_Control *) _Chain_First(&ready_queues[LOW_PRIORITY]);
     190        (Thread_Control *) _Chain_First(&scheduler->Ready[LOW_PRIORITY]);
    191191
    192192  _Thread_Dispatch_necessary = 1;
     
    220220)
    221221{
     222  Scheduler_priority_Control *scheduler = _Scheduler_priority_Instance();
    222223#if defined(RTEMS_SMP)
    223224  rtems_interrupt_level level;
    224225#endif
    225   Chain_Control   *ready_queues;
    226226
    227227#if (MUST_WAIT_FOR_INTERRUPT == 1)
     
    256256#endif
    257257
    258   ready_queues      = (Chain_Control *) _Scheduler.information;
    259258  _Thread_Executing =
    260         (Thread_Control *) _Chain_First(&ready_queues[LOW_PRIORITY]);
     259        (Thread_Control *) _Chain_First(&scheduler->Ready[LOW_PRIORITY]);
    261260
    262261  _Thread_Dispatch_necessary = 1;
Note: See TracChangeset for help on using the changeset viewer.