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

4.104.114.84.95
Last change on this file since dfbfa2b0 was dfbfa2b0, checked in by Joel Sherrill <joel.sherrill@…>, on 11/02/99 at 20:36:11

Split threadq.c into multiple files.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 *  Thread Queue Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989-1998.
6 *  On-Line Applications Research Corporation (OAR).
7 *  Copyright assigned to U.S. Government, 1994.
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.OARcorp.com/rtems/license.html.
12 *
13 *  $Id$
14 */
15
16#include <rtems/system.h>
17#include <rtems/score/chain.h>
18#include <rtems/score/isr.h>
19#include <rtems/score/object.h>
20#include <rtems/score/states.h>
21#include <rtems/score/thread.h>
22#include <rtems/score/threadq.h>
23#include <rtems/score/tqdata.h>
24
25/*PAGE
26 *
27 *  _Thread_queue_Enqueue_priority
28 *
29 *  This routine blocks a thread, places it on a thread, and optionally
30 *  starts a timeout timer.
31 *
32 *  Input parameters:
33 *    the_thread_queue - pointer to threadq
34 *    thread           - thread to insert
35 *    timeout          - timeout interval in ticks
36 *
37 *  Output parameters: NONE
38 *
39 *  INTERRUPT LATENCY:
40 *    forward less than
41 *    forward equal
42 */
43
44void _Thread_queue_Enqueue_priority(
45  Thread_queue_Control *the_thread_queue,
46  Thread_Control       *the_thread,
47  Watchdog_Interval     timeout
48)
49{
50  Priority_Control     search_priority;
51  Thread_Control      *search_thread;
52  ISR_Level            level;
53  Chain_Control       *header;
54  unsigned32           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  _ISR_Enable( level );
116  return;
117
118restart_reverse_search:
119  search_priority     = PRIORITY_MAXIMUM + 1;
120
121  _ISR_Disable( level );
122  search_thread = (Thread_Control *) header->last;
123  while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
124    search_priority = search_thread->current_priority;
125    if ( priority >= search_priority )
126      break;
127#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
128    search_thread = (Thread_Control *) search_thread->Object.Node.previous;
129    if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
130      break;
131    search_priority = search_thread->current_priority;
132    if ( priority >= search_priority )
133      break;
134#endif
135    _ISR_Flash( level );
136    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
137      _ISR_Enable( level );
138      goto restart_reverse_search;
139    }
140    search_thread = (Thread_Control *)
141                         search_thread->Object.Node.previous;
142  }
143
144  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
145    goto synchronize;
146
147  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
148
149  if ( priority == search_priority )
150    goto equal_priority;
151
152  search_node = (Chain_Node *) search_thread;
153  next_node   = search_node->next;
154  the_node    = (Chain_Node *) the_thread;
155
156  the_node->next      = next_node;
157  the_node->previous  = search_node;
158  search_node->next   = the_node;
159  next_node->previous = the_node;
160  _ISR_Enable( level );
161  return;
162
163equal_priority:               /* add at end of priority group */
164  search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
165  previous_node = search_node->previous;
166  the_node      = (Chain_Node *) the_thread;
167
168  the_node->next        = search_node;
169  the_node->previous    = previous_node;
170  previous_node->next   = the_node;
171  search_node->previous = the_node;
172  _ISR_Enable( level );
173  return;
174
175synchronize:
176
177  sync_state = the_thread_queue->sync_state;
178  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
179
180  switch ( sync_state ) {
181    case THREAD_QUEUE_SYNCHRONIZED:
182      /*
183       *  This should never happen.  It indicates that someone did not
184       *  enter a thread queue critical section.
185       */
186      break;
187 
188    case THREAD_QUEUE_NOTHING_HAPPENED:
189      /*
190       *  This should never happen.  All of this was dealt with above.
191       */
192      break;
193 
194    case THREAD_QUEUE_TIMEOUT:
195      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
196      _ISR_Enable( level );
197      break;
198 
199    case THREAD_QUEUE_SATISFIED:
200      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
201        _Watchdog_Deactivate( &the_thread->Timer );
202        _ISR_Enable( level );
203        (void) _Watchdog_Remove( &the_thread->Timer );
204      } else
205        _ISR_Enable( level );
206      break;
207  }
208 
209  /*
210   *  Global objects with thread queue's should not be operated on from an
211   *  ISR.  But the sync code still must allow short timeouts to be processed
212   *  correctly.
213   */
214 
215  _Thread_Unblock( the_thread );
216 
217#if defined(RTEMS_MULTIPROCESSING)
218  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
219    _Thread_MP_Free_proxy( the_thread );
220#endif
221}
222
Note: See TracBrowser for help on using the repository browser.