source: rtems/cpukit/score/src/threadqenqueuepriority.c @ bd029d87

4.8
Last change on this file since bd029d87 was 96d0b64, checked in by Joel Sherrill <joel.sherrill@…>, on 03/05/07 at 21:01:40

2007-03-05 Joel Sherrill <joel@…>

PR 1222/cpukit

  • score/Makefile.am, score/include/rtems/score/coremutex.h, score/include/rtems/score/threadq.h, score/inline/rtems/score/coremutex.inl, score/src/coremsgsubmit.c, score/src/coremutexsurrender.c, score/src/threadchangepriority.c, score/src/threadclearstate.c, score/src/threadhandler.c, score/src/threadinitialize.c, score/src/threadqdequeuefifo.c, score/src/threadqdequeuepriority.c, score/src/threadqenqueue.c, score/src/threadqenqueuefifo.c, score/src/threadqenqueuepriority.c, score/src/threadqextractfifo.c, score/src/threadqextractpriority.c, score/src/threadsetstate.c: Enhance so that when the prioirity of a thread that is blocked on a priority based thread queue is changed, that its placement in the queue is reevaluated based upon the new priority. This enhancement includes modifications to the SuperCore? as well as new test cases.
  • score/src/threadqrequeue.c: New file.
  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 *  Thread Queue Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989-1999.
6 *  On-Line Applications Research Corporation (OAR).
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.rtems.com/license/LICENSE.
11 *
12 *  $Id$
13 */
14
15#if HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <rtems/system.h>
20#include <rtems/score/chain.h>
21#include <rtems/score/isr.h>
22#include <rtems/score/object.h>
23#include <rtems/score/states.h>
24#include <rtems/score/thread.h>
25#include <rtems/score/threadq.h>
26#include <rtems/score/tqdata.h>
27
28/*PAGE
29 *
30 *  _Thread_queue_Enqueue_priority
31 *
32 *  This routine places a blocked thread on a priority thread queue.
33 *
34 *  Input parameters:
35 *    the_thread_queue - pointer to threadq
36 *    thread           - thread to insert
37 *
38 *  Output parameters: NONE
39 *
40 *  INTERRUPT LATENCY:
41 *    forward less than
42 *    forward equal
43 */
44
45void _Thread_queue_Enqueue_priority(
46  Thread_queue_Control *the_thread_queue,
47  Thread_Control       *the_thread
48)
49{
50  Priority_Control     search_priority;
51  Thread_Control      *search_thread;
52  ISR_Level            level;
53  Chain_Control       *header;
54  uint32_t             header_index;
55  Chain_Node          *the_node;
56  Chain_Node          *next_node;
57  Chain_Node          *previous_node;
58  Chain_Node          *search_node;
59  Priority_Control     priority;
60  States_Control       block_state;
61  Thread_queue_States  sync_state;
62
63  _Chain_Initialize_empty( &the_thread->Wait.Block2n );
64
65  priority     = the_thread->current_priority;
66  header_index = _Thread_queue_Header_number( priority );
67  header       = &the_thread_queue->Queues.Priority[ header_index ];
68  block_state  = the_thread_queue->state;
69
70  if ( _Thread_queue_Is_reverse_search( priority ) )
71    goto restart_reverse_search;
72
73restart_forward_search:
74  search_priority = PRIORITY_MINIMUM - 1;
75  _ISR_Disable( level );
76  search_thread = (Thread_Control *) header->first;
77  while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
78    search_priority = search_thread->current_priority;
79    if ( priority <= search_priority )
80      break;
81
82#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
83    search_thread = (Thread_Control *) search_thread->Object.Node.next;
84    if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
85      break;
86    search_priority = search_thread->current_priority;
87    if ( priority <= search_priority )
88      break;
89#endif
90    _ISR_Flash( level );
91    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
92      _ISR_Enable( level );
93      goto restart_forward_search;
94    }
95    search_thread =
96       (Thread_Control *)search_thread->Object.Node.next;
97  }
98
99  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
100    goto synchronize;
101
102  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
103
104  if ( priority == search_priority )
105    goto equal_priority;
106
107  search_node   = (Chain_Node *) search_thread;
108  previous_node = search_node->previous;
109  the_node      = (Chain_Node *) the_thread;
110
111  the_node->next         = search_node;
112  the_node->previous     = previous_node;
113  previous_node->next    = the_node;
114  search_node->previous  = the_node;
115  the_thread->Wait.queue = the_thread_queue;
116  _ISR_Enable( level );
117  return;
118
119restart_reverse_search:
120  search_priority     = PRIORITY_MAXIMUM + 1;
121
122  _ISR_Disable( level );
123  search_thread = (Thread_Control *) header->last;
124  while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
125    search_priority = search_thread->current_priority;
126    if ( priority >= search_priority )
127      break;
128#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
129    search_thread = (Thread_Control *) search_thread->Object.Node.previous;
130    if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
131      break;
132    search_priority = search_thread->current_priority;
133    if ( priority >= search_priority )
134      break;
135#endif
136    _ISR_Flash( level );
137    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
138      _ISR_Enable( level );
139      goto restart_reverse_search;
140    }
141    search_thread = (Thread_Control *)
142                         search_thread->Object.Node.previous;
143  }
144
145  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
146    goto synchronize;
147
148  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
149
150  if ( priority == search_priority )
151    goto equal_priority;
152
153  search_node = (Chain_Node *) search_thread;
154  next_node   = search_node->next;
155  the_node    = (Chain_Node *) the_thread;
156
157  the_node->next          = next_node;
158  the_node->previous      = search_node;
159  search_node->next       = the_node;
160  next_node->previous    = the_node;
161  the_thread->Wait.queue = the_thread_queue;
162  _ISR_Enable( level );
163  return;
164
165equal_priority:               /* add at end of priority group */
166  search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
167  previous_node = search_node->previous;
168  the_node      = (Chain_Node *) the_thread;
169
170  the_node->next         = search_node;
171  the_node->previous     = previous_node;
172  previous_node->next    = the_node;
173  search_node->previous  = the_node;
174  the_thread->Wait.queue = the_thread_queue;
175  _ISR_Enable( level );
176  return;
177
178synchronize:
179
180  sync_state = the_thread_queue->sync_state;
181  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
182
183  switch ( sync_state ) {
184    case THREAD_QUEUE_SYNCHRONIZED:
185      /*
186       *  This should never happen.  It indicates that someone did not
187       *  enter a thread queue critical section.
188       */
189      break;
190
191    case THREAD_QUEUE_NOTHING_HAPPENED:
192      /*
193       *  This should never happen.  All of this was dealt with above.
194       */
195      break;
196
197    case THREAD_QUEUE_TIMEOUT:
198      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
199      the_thread->Wait.queue = NULL;
200      _ISR_Enable( level );
201      break;
202
203    case THREAD_QUEUE_SATISFIED:
204      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
205        _Watchdog_Deactivate( &the_thread->Timer );
206        the_thread->Wait.queue = NULL;
207        _ISR_Enable( level );
208        (void) _Watchdog_Remove( &the_thread->Timer );
209      } else
210        _ISR_Enable( level );
211      break;
212  }
213
214  /*
215   *  Global objects with thread queue's should not be operated on from an
216   *  ISR.  But the sync code still must allow short timeouts to be processed
217   *  correctly.
218   */
219
220  _Thread_Unblock( the_thread );
221
222#if defined(RTEMS_MULTIPROCESSING)
223  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
224    _Thread_MP_Free_proxy( the_thread );
225#endif
226}
Note: See TracBrowser for help on using the repository browser.