source: rtems-docs/porting/priority_bitmap.rst @ 12dccfe

5
Last change on this file since 12dccfe was 12dccfe, checked in by Sebastian Huber <sebastian.huber@…>, on 01/09/19 at 15:14:05

Remove superfluous "All rights reserved."

  • Property mode set to 100644
File size: 7.4 KB
Line 
1.. comment SPDX-License-Identifier: CC-BY-SA-4.0
2
3.. Copyright (C) 1988, 2002 On-Line Applications Research Corporation (OAR)
4
5Priority Bitmap Manipulation
6############################
7
8Introduction
9============
10
11The RTEMS chain of ready tasks is implemented as an array of FIFOs with
12each priority having its own FIFO.  This makes it very efficient to
13determine the first and last ready task at each priority.  In addition,
14blocking a task only requires appending the task to the end of the FIFO
15for its priority rather than a lengthy search down a single chain of all
16ready tasks.  This works extremely well except for one problem.  When the
17currently executing task blocks, there may be no easy way to determine
18what is the next most important ready task.  If the blocking task was the
19only ready task at its priority, then RTEMS must search all of the FIFOs
20in the ready chain to determine the highest priority with a ready task.
21
22RTEMS uses a bitmap array to efficiently solve this problem.  The state of
23each bit in the priority map bit array indicates whether or not there is a
24ready task at that priority.  The bit array can be efficiently searched to
25determine the highest priority ready task.  This family of data type and
26routines is used to maintain and search the bit map array.
27
28When manipulating the bitmap array, RTEMS internally divides the 8 bits
29of the task priority into "major" and "minor" components.  The most
30significant 4 bits are the major component, while the least significant
31are the minor component.  The major component of a priority value is
32used to determine which 16-bit wide entry in the``_Priority_Bit_map``
33array is associated with this priority.  Each element in the
34``_Priority_Bit_map`` array has a bit in the ``_Priority_Major_bit_map``
35associated with it.  That bit is cleared when all of the bits in a
36particular``_Priority_Bit_map`` array entry are zero.
37
38The minor component of a priority is used to determine
39specifically which bit in ``_Priority_Bit_map[major]``
40indicates whether or not there is a ready to execute task
41at the priority.
42
43_Priority_bit_map_Control Type
44==============================
45
46The ``_Priority_Bit_map_Control`` type is the fundamental data type of the
47priority bit map array used to determine which priorities have ready
48tasks.  This type may be either 16 or 32 bits wide although only the 16
49least significant bits will be used.  The data type is based upon what is
50the most efficient type for this CPU to manipulate.  For example, some
51CPUs have bit scan instructions that only operate on a particular size of
52data.  In this case, this type will probably be defined to work with this
53instruction.
54
55Find First Bit Routine
56======================
57
58The _CPU_Bitfield_Find_first_bit routine sets _output to the bit number of
59the first bit set in ``_value``.  ``_value`` is of CPU dependent type``Priority_bit_map_Control``.  A stub version of this routine is as follows:
60
61.. code-block:: c
62
63    #define _CPU_Bitfield_Find_first_bit( _value, _output ) \
64    { \
65      (_output) = 0;   /* do something to prevent warnings */ \
66    }
67
68There are a number of variables in using a "find first bit" type
69instruction.
70
71#. What happens when run on a value of zero?
72
73#. Bits may be numbered from MSB to LSB or vice-versa.
74
75#. The numbering may be zero or one based.
76
77#. The "find first bit" instruction may search from MSB or LSB.
78
79RTEMS guarantees that (1) will never happen so it is not a concern.
80Cases (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
81_CPU_Priority_bits_index().  These three form a set of routines which must
82logically operate together.  Bits in the ``_value`` are set and cleared based
83on masks built by CPU_Priority_mask().  The basic major and minor values
84calculated by _Priority_Major() and _Priority_Minor() are "massaged" by
85_CPU_Priority_bits_index() to properly range between the values returned
86by the "find first bit" instruction.  This makes it possible for
87_Priority_Get_highest() to calculate the major and directly index into the
88minor table.  This mapping is necessary to ensure that 0 (a high priority
89major/minor) is the first bit found.
90
91This entire "find first bit" and mapping process depends heavily on the
92manner in which a priority is broken into a major and minor components
93with the major being the 4 MSB of a priority and minor the 4 LSB.  Thus (0
94<< 4) + 0 corresponds to priority 0 - the highest priority.  And (15 <<
954) + 14 corresponds to priority 254 - the next to the lowest priority.
96
97If your CPU does not have a "find first bit" instruction, then there are
98ways to make do without it.  Here are a handful of ways to implement this
99in software:
100
101- a series of 16 bit test instructions
102
103- a "binary search using if's"
104
105- the following algorithm based upon a 16 entry lookup table.  In this
106  pseudo-code, bit_set_table[16] has values which indicate the first
107  bit set:
108
109  .. code-block:: c
110
111      _number = 0 if _value > 0x00ff
112      _value >>=8
113      _number = 8;
114      if _value > 0x0000f
115        _value >=8
116        _number += 4
117        _number += bit_set_table[ _value ]
118
119The following illustrates how the CPU_USE_GENERIC_BITFIELD_CODE macro may
120be so the port can use the generic implementation of this bitfield code.
121This can be used temporarily during the porting process to avoid writing
122these routines until the end.  This results in a functional although lower
123performance port.  This is perfectly acceptable during development and
124testing phases.
125
126.. code-block:: c
127
128    #define CPU_USE_GENERIC_BITFIELD_CODE TRUE
129    #define CPU_USE_GENERIC_BITFIELD_DATA TRUE
130
131Eventually, CPU specific implementations of these routines are usually
132written since they dramatically impact the performance of blocking
133operations.  However they may take advantage of instructions which are not
134available on all models in the CPU family.  In this case, one might find
135something like this stub example did:
136
137.. code-block:: c
138
139    #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
140      #define _CPU_Bitfield_Find_first_bit( _value, _output ) \
141      { \
142        (_output) = 0;   /* do something to prevent warnings */ \
143      }
144    #endif
145
146Build Bit Field Mask
147====================
148
149The _CPU_Priority_Mask routine builds the mask that corresponds to the bit
150fields searched by _CPU_Bitfield_Find_first_bit().  See the discussion of
151that routine for more details.
152
153The following is a typical implementation when the
154_CPU_Bitfield_Find_first_bit searches for the most significant bit set:
155
156.. code-block:: c
157
158    #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
159      #define _CPU_Priority_Mask( _bit_number ) \
160        ( 1 << (_bit_number) )
161    #endif
162
163Bit Scan Support
164================
165
166The ``_CPU_Priority_bits_index`` routine translates the bit numbers
167returned by ``_CPU_Bitfield_Find_first_bit()`` into something
168suitable for use as a major or minor component of a priority.
169The find first bit routine may number the bits in a
170way that is difficult to map into the major and minor components
171of the priority.  For example, when finding the first bit set in
172the value 0x8000, a CPU may indicate that bit 15 or 16 is set
173based on whether the least significant bit is "zero" or "one".
174Similarly, a CPU may only scan 32-bit values and consider the
175most significant bit to be bit zero or one.  In this case, this
176would be bit 16 or 17.
177
178This routine allows that unwieldy form to be converted
179into a normalized form that is easier to process and use
180as an index.
181
182.. code-block:: c
183
184    #if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
185      #define _CPU_Priority_bits_index( _priority ) \
186        (_priority)
187    #endif
Note: See TracBrowser for help on using the repository browser.