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

4.104.114.84.95
Last change on this file since f26145b was a8eed23, checked in by Ralf Corsepius <ralf.corsepius@…>, on 01/27/05 at 05:57:05

Include config.h.

  • Property mode set to 100644
File size: 6.3 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 blocks a thread, places it on a thread, and optionally
33 *  starts a timeout timer.
34 *
35 *  Input parameters:
36 *    the_thread_queue - pointer to threadq
37 *    thread           - thread to insert
38 *    timeout          - timeout interval in ticks
39 *
40 *  Output parameters: NONE
41 *
42 *  INTERRUPT LATENCY:
43 *    forward less than
44 *    forward equal
45 */
46
47void _Thread_queue_Enqueue_priority(
48  Thread_queue_Control *the_thread_queue,
49  Thread_Control       *the_thread,
50  Watchdog_Interval     timeout
51)
52{
53  Priority_Control     search_priority;
54  Thread_Control      *search_thread;
55  ISR_Level            level;
56  Chain_Control       *header;
57  uint32_t             header_index;
58  Chain_Node          *the_node;
59  Chain_Node          *next_node;
60  Chain_Node          *previous_node;
61  Chain_Node          *search_node;
62  Priority_Control     priority;
63  States_Control       block_state;
64  Thread_queue_States  sync_state;
65
66  _Chain_Initialize_empty( &the_thread->Wait.Block2n );
67
68  priority     = the_thread->current_priority;
69  header_index = _Thread_queue_Header_number( priority );
70  header       = &the_thread_queue->Queues.Priority[ header_index ];
71  block_state  = the_thread_queue->state;
72
73  if ( _Thread_queue_Is_reverse_search( priority ) )
74    goto restart_reverse_search;
75
76restart_forward_search:
77  search_priority = PRIORITY_MINIMUM - 1;
78  _ISR_Disable( level );
79  search_thread = (Thread_Control *) header->first;
80  while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
81    search_priority = search_thread->current_priority;
82    if ( priority <= search_priority )
83      break;
84
85#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
86    search_thread = (Thread_Control *) search_thread->Object.Node.next;
87    if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
88      break;
89    search_priority = search_thread->current_priority;
90    if ( priority <= search_priority )
91      break;
92#endif
93    _ISR_Flash( level );
94    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
95      _ISR_Enable( level );
96      goto restart_forward_search;
97    }
98    search_thread =
99       (Thread_Control *)search_thread->Object.Node.next;
100  }
101
102  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
103    goto synchronize;
104
105  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
106
107  if ( priority == search_priority )
108    goto equal_priority;
109
110  search_node   = (Chain_Node *) search_thread;
111  previous_node = search_node->previous;
112  the_node      = (Chain_Node *) the_thread;
113
114  the_node->next        = search_node;
115  the_node->previous    = previous_node;
116  previous_node->next   = the_node;
117  search_node->previous = the_node;
118  _ISR_Enable( level );
119  return;
120
121restart_reverse_search:
122  search_priority     = PRIORITY_MAXIMUM + 1;
123
124  _ISR_Disable( level );
125  search_thread = (Thread_Control *) header->last;
126  while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
127    search_priority = search_thread->current_priority;
128    if ( priority >= search_priority )
129      break;
130#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
131    search_thread = (Thread_Control *) search_thread->Object.Node.previous;
132    if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
133      break;
134    search_priority = search_thread->current_priority;
135    if ( priority >= search_priority )
136      break;
137#endif
138    _ISR_Flash( level );
139    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
140      _ISR_Enable( level );
141      goto restart_reverse_search;
142    }
143    search_thread = (Thread_Control *)
144                         search_thread->Object.Node.previous;
145  }
146
147  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
148    goto synchronize;
149
150  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
151
152  if ( priority == search_priority )
153    goto equal_priority;
154
155  search_node = (Chain_Node *) search_thread;
156  next_node   = search_node->next;
157  the_node    = (Chain_Node *) the_thread;
158
159  the_node->next      = next_node;
160  the_node->previous  = search_node;
161  search_node->next   = the_node;
162  next_node->previous = the_node;
163  _ISR_Enable( level );
164  return;
165
166equal_priority:               /* add at end of priority group */
167  search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
168  previous_node = search_node->previous;
169  the_node      = (Chain_Node *) the_thread;
170
171  the_node->next        = search_node;
172  the_node->previous    = previous_node;
173  previous_node->next   = the_node;
174  search_node->previous = the_node;
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      _ISR_Enable( level );
200      break;
201
202    case THREAD_QUEUE_SATISFIED:
203      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
204        _Watchdog_Deactivate( &the_thread->Timer );
205        _ISR_Enable( level );
206        (void) _Watchdog_Remove( &the_thread->Timer );
207      } else
208        _ISR_Enable( level );
209      break;
210  }
211
212  /*
213   *  Global objects with thread queue's should not be operated on from an
214   *  ISR.  But the sync code still must allow short timeouts to be processed
215   *  correctly.
216   */
217
218  _Thread_Unblock( the_thread );
219
220#if defined(RTEMS_MULTIPROCESSING)
221  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
222    _Thread_MP_Free_proxy( the_thread );
223#endif
224}
Note: See TracBrowser for help on using the repository browser.