source: rtems/c/src/exec/score/src/threadq.c @ dfbfa2b0

4.104.114.84.95
Last change on this file since dfbfa2b0 was dfbfa2b0, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 2, 1999 at 8:36:11 PM

Split threadq.c into multiple files.

  • Property mode set to 100644
File size: 26.0 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_Initialize
28 *
29 *  This routine initializes the specified threadq.
30 *
31 *  Input parameters:
32 *    the_thread_queue      - pointer to a threadq header
33 *    the_class             - class of the object to which this belongs
34 *    discipline            - queueing discipline
35 *    state                 - state of waiting threads
36 *    proxy_extract_callout - MP specific callout
37 *    timeout_status        - return on a timeout
38 *
39 *  Output parameters: NONE
40 */
41
42void _Thread_queue_Initialize(
43  Thread_queue_Control         *the_thread_queue,
44  Objects_Classes               the_class,
45  Thread_queue_Disciplines      the_discipline,
46  States_Control                state,
47  Thread_queue_Extract_callout  proxy_extract_callout,
48  unsigned32                    timeout_status
49)
50{
51  unsigned32 index;
52
53  _Thread_queue_Extract_table[ the_class ] = proxy_extract_callout;
54
55  the_thread_queue->state          = state;
56  the_thread_queue->discipline     = the_discipline;
57  the_thread_queue->timeout_status = timeout_status;
58  the_thread_queue->sync_state     = THREAD_QUEUE_SYNCHRONIZED;
59
60  switch ( the_discipline ) {
61    case THREAD_QUEUE_DISCIPLINE_FIFO:
62      _Chain_Initialize_empty( &the_thread_queue->Queues.Fifo );
63      break;
64    case THREAD_QUEUE_DISCIPLINE_PRIORITY:
65      for( index=0 ;
66           index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
67           index++)
68        _Chain_Initialize_empty( &the_thread_queue->Queues.Priority[index] );
69      break;
70  }
71
72}
73#if 0
74
75/*PAGE
76 *
77 *  _Thread_queue_Enqueue
78 *
79 *  This routine blocks a thread, places it on a thread, and optionally
80 *  starts a timeout timer.
81 *
82 *  Input parameters:
83 *    the_thread_queue - pointer to threadq
84 *    timeout          - interval to wait
85 *
86 *  Output parameters: NONE
87 *
88 *  INTERRUPT LATENCY:
89 *    only case
90 */
91
92void _Thread_queue_Enqueue(
93  Thread_queue_Control *the_thread_queue,
94  Watchdog_Interval     timeout
95)
96{
97  Thread_Control *the_thread;
98
99  the_thread = _Thread_Executing;
100
101#if defined(RTEMS_MULTIPROCESSING)
102  if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
103    the_thread = _Thread_MP_Allocate_proxy( the_thread_queue->state );
104  else
105#endif
106    _Thread_Set_state( the_thread, the_thread_queue->state );
107
108  if ( timeout ) {
109    _Watchdog_Initialize(
110       &the_thread->Timer,
111       _Thread_queue_Timeout,
112       the_thread->Object.id,
113       NULL
114    );
115
116    _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
117  }
118
119  switch( the_thread_queue->discipline ) {
120    case THREAD_QUEUE_DISCIPLINE_FIFO:
121      _Thread_queue_Enqueue_fifo( the_thread_queue, the_thread, timeout );
122      break;
123    case THREAD_QUEUE_DISCIPLINE_PRIORITY:
124      _Thread_queue_Enqueue_priority( the_thread_queue, the_thread, timeout );
125      break;
126  }
127}
128
129/*PAGE
130 *
131 *  _Thread_queue_Dequeue
132 *
133 *  This routine removes a thread from the specified threadq.  If the
134 *  threadq discipline is FIFO, it unblocks a thread, and cancels its
135 *  timeout timer.  Priority discipline is processed elsewhere.
136 *
137 *  Input parameters:
138 *    the_thread_queue - pointer to threadq
139 *
140 *  Output parameters:
141 *    returns - thread dequeued or NULL
142 *
143 *  INTERRUPT LATENCY:
144 *    check sync
145 */
146
147Thread_Control *_Thread_queue_Dequeue(
148  Thread_queue_Control *the_thread_queue
149)
150{
151  Thread_Control *the_thread;
152
153  switch ( the_thread_queue->discipline ) {
154    case THREAD_QUEUE_DISCIPLINE_FIFO:
155      the_thread = _Thread_queue_Dequeue_fifo( the_thread_queue );
156      break;
157    case THREAD_QUEUE_DISCIPLINE_PRIORITY:
158      the_thread = _Thread_queue_Dequeue_priority( the_thread_queue );
159      break;
160    default:              /* this is only to prevent warnings */
161      the_thread = NULL;
162      break;
163  }
164
165  return( the_thread );
166}
167
168/*PAGE
169 *
170 *  _Thread_queue_Extract_with_proxy
171 *
172 *  This routine extracts the_thread from the_thread_queue
173 *  and insures that if there is a proxy for this task on
174 *  another node, it is also dealt with.
175 *
176 *  XXX
177 */
178 
179boolean _Thread_queue_Extract_with_proxy(
180  Thread_Control       *the_thread
181)
182{
183  States_Control                state;
184  Objects_Classes               the_class;
185  Thread_queue_Extract_callout  proxy_extract_callout;
186
187  state = the_thread->current_state;
188
189  if ( _States_Is_waiting_on_thread_queue( state ) ) {
190    if ( _States_Is_waiting_for_rpc_reply( state ) &&
191         _States_Is_locally_blocked( state ) ) {
192
193      the_class = _Objects_Get_class( the_thread->Wait.id );
194
195      proxy_extract_callout = _Thread_queue_Extract_table[ the_class ];
196
197      if ( proxy_extract_callout )
198        (*proxy_extract_callout)( the_thread );
199    }
200    _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
201
202    return TRUE;
203  }
204  return FALSE;
205}
206
207/*PAGE
208 *
209 *  _Thread_queue_Extract
210 *
211 *  This routine removes a specific thread from the specified threadq,
212 *  deletes any timeout, and unblocks the thread.
213 *
214 *  Input parameters:
215 *    the_thread_queue - pointer to a threadq header
216 *    the_thread       - pointer to a thread control block
217 *
218 *  Output parameters: NONE
219 *
220 *  INTERRUPT LATENCY: NONE
221 */
222
223void _Thread_queue_Extract(
224  Thread_queue_Control *the_thread_queue,
225  Thread_Control       *the_thread
226)
227{
228  switch ( the_thread_queue->discipline ) {
229    case THREAD_QUEUE_DISCIPLINE_FIFO:
230      _Thread_queue_Extract_fifo( the_thread_queue, the_thread );
231      break;
232    case THREAD_QUEUE_DISCIPLINE_PRIORITY:
233      _Thread_queue_Extract_priority( the_thread_queue, the_thread );
234      break;
235   }
236}
237
238/*PAGE
239 *
240 *  _Thread_queue_Flush
241 *
242 *  This kernel routine flushes the given thread queue.
243 *
244 *  Input parameters:
245 *    the_thread_queue       - pointer to threadq to be flushed
246 *    remote_extract_callout - pointer to routine which extracts a remote thread
247 *    status                 - status to return to the thread
248 *
249 *  Output parameters:  NONE
250 */
251
252void _Thread_queue_Flush(
253  Thread_queue_Control       *the_thread_queue,
254  Thread_queue_Flush_callout  remote_extract_callout,
255  unsigned32                  status
256)
257{
258  Thread_Control *the_thread;
259
260  while ( (the_thread = _Thread_queue_Dequeue( the_thread_queue )) ) {
261#if defined(RTEMS_MULTIPROCESSING)
262    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
263      ( *remote_extract_callout )( the_thread );
264    else
265#endif
266      the_thread->Wait.return_code = status;
267  }
268}
269
270/*PAGE
271 *
272 *  _Thread_queue_First
273 *
274 *  This routines returns a pointer to the first thread on the
275 *  specified threadq.
276 *
277 *  Input parameters:
278 *    the_thread_queue - pointer to thread queue
279 *
280 *  Output parameters:
281 *    returns - first thread or NULL
282 */
283
284Thread_Control *_Thread_queue_First(
285  Thread_queue_Control *the_thread_queue
286)
287{
288  Thread_Control *the_thread;
289
290  switch ( the_thread_queue->discipline ) {
291    case THREAD_QUEUE_DISCIPLINE_FIFO:
292      the_thread = _Thread_queue_First_fifo( the_thread_queue );
293      break;
294    case THREAD_QUEUE_DISCIPLINE_PRIORITY:
295      the_thread = _Thread_queue_First_priority( the_thread_queue );
296      break;
297    default:              /* this is only to prevent warnings */
298      the_thread = NULL;
299      break;
300  }
301
302  return the_thread;
303}
304
305/*PAGE
306 *
307 *  _Thread_queue_Timeout
308 *
309 *  This routine processes a thread which timeouts while waiting on
310 *  a thread queue. It is called by the watchdog handler.
311 *
312 *  Input parameters:
313 *    id - thread id
314 *
315 *  Output parameters: NONE
316 */
317
318void _Thread_queue_Timeout(
319  Objects_Id  id,
320  void       *ignored
321)
322{
323  Thread_Control       *the_thread;
324  Thread_queue_Control *the_thread_queue;
325  Objects_Locations     location;
326
327  the_thread = _Thread_Get( id, &location );
328  switch ( location ) {
329    case OBJECTS_ERROR:
330    case OBJECTS_REMOTE:  /* impossible */
331      break;
332    case OBJECTS_LOCAL:
333      the_thread_queue = the_thread->Wait.queue;
334
335      /*
336       *  If the_thread_queue is not synchronized, then it is either
337       *  "nothing happened", "timeout", or "satisfied".   If the_thread
338       *  is the executing thread, then it is in the process of blocking
339       *  and it is the thread which is responsible for the synchronization
340       *  process.
341       *
342       *  If it is not satisfied, then it is "nothing happened" and
343       *  this is the "timeout" transition.  After a request is satisfied,
344       *  a timeout is not allowed to occur.
345       */
346
347      if ( the_thread_queue->sync_state != THREAD_QUEUE_SYNCHRONIZED &&
348           _Thread_Is_executing( the_thread ) ) {
349        if ( the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED )
350          the_thread_queue->sync_state = THREAD_QUEUE_TIMEOUT;
351      } else {
352        the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
353        _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
354      }
355      _Thread_Unnest_dispatch();
356      break;
357  }
358}
359
360/*PAGE
361 *
362 *  _Thread_queue_Enqueue_fifo
363 *
364 *  This routine blocks a thread, places it on a thread, and optionally
365 *  starts a timeout timer.
366 *
367 *  Input parameters:
368 *    the_thread_queue - pointer to threadq
369 *    the_thread       - pointer to the thread to block
370 *    timeout          - interval to wait
371 *
372 *  Output parameters: NONE
373 *
374 *  INTERRUPT LATENCY:
375 *    only case
376 */
377
378void _Thread_queue_Enqueue_fifo (
379  Thread_queue_Control *the_thread_queue,
380  Thread_Control       *the_thread,
381  Watchdog_Interval    timeout
382)
383{
384  ISR_Level            level;
385  Thread_queue_States  sync_state;
386
387  _ISR_Disable( level );
388
389  sync_state = the_thread_queue->sync_state;
390  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
391
392  switch ( sync_state ) {
393    case THREAD_QUEUE_SYNCHRONIZED:
394      /*
395       *  This should never happen.  It indicates that someone did not
396       *  enter a thread queue critical section.
397       */
398      break;
399
400    case THREAD_QUEUE_NOTHING_HAPPENED:
401      _Chain_Append_unprotected(
402        &the_thread_queue->Queues.Fifo,
403        &the_thread->Object.Node
404      );
405      _ISR_Enable( level );
406      return;
407
408    case THREAD_QUEUE_TIMEOUT:
409      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
410      _ISR_Enable( level );
411      break;
412
413    case THREAD_QUEUE_SATISFIED:
414      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
415        _Watchdog_Deactivate( &the_thread->Timer );
416        _ISR_Enable( level );
417        (void) _Watchdog_Remove( &the_thread->Timer );
418      } else
419        _ISR_Enable( level );
420      break;
421  }
422
423  /*
424   *  Global objects with thread queue's should not be operated on from an
425   *  ISR.  But the sync code still must allow short timeouts to be processed
426   *  correctly.
427   */
428
429  _Thread_Unblock( the_thread );
430
431#if defined(RTEMS_MULTIPROCESSING)
432  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
433    _Thread_MP_Free_proxy( the_thread );
434#endif
435
436}
437
438/*PAGE
439 *
440 *  _Thread_queue_Dequeue_fifo
441 *
442 *  This routine removes a thread from the specified threadq.
443 *
444 *  Input parameters:
445 *    the_thread_queue - pointer to threadq
446 *
447 *  Output parameters:
448 *    returns - thread dequeued or NULL
449 *
450 *  INTERRUPT LATENCY:
451 *    check sync
452 *    FIFO
453 */
454
455Thread_Control *_Thread_queue_Dequeue_fifo(
456  Thread_queue_Control *the_thread_queue
457)
458{
459  ISR_Level              level;
460  Thread_Control *the_thread;
461
462  _ISR_Disable( level );
463  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
464
465    the_thread = (Thread_Control *)
466       _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
467
468    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
469      _ISR_Enable( level );
470      _Thread_Unblock( the_thread );
471    } else {
472      _Watchdog_Deactivate( &the_thread->Timer );
473      _ISR_Enable( level );
474      (void) _Watchdog_Remove( &the_thread->Timer );
475      _Thread_Unblock( the_thread );
476    }
477
478#if defined(RTEMS_MULTIPROCESSING)
479    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
480      _Thread_MP_Free_proxy( the_thread );
481#endif
482
483    return the_thread;
484  }
485
486  switch ( the_thread_queue->sync_state ) {
487    case THREAD_QUEUE_SYNCHRONIZED:
488    case THREAD_QUEUE_SATISFIED:
489      _ISR_Enable( level );
490      return NULL;
491
492    case THREAD_QUEUE_NOTHING_HAPPENED:
493    case THREAD_QUEUE_TIMEOUT:
494      the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
495      _ISR_Enable( level );
496      return _Thread_Executing;
497  }
498  return NULL;                /* this is only to prevent warnings */
499}
500
501/*PAGE
502 *
503 *  _Thread_queue_Extract_fifo
504 *
505 *  This routine removes a specific thread from the specified threadq,
506 *  deletes any timeout, and unblocks the thread.
507 *
508 *  Input parameters:
509 *    the_thread_queue - pointer to a threadq header
510 *    the_thread       - pointer to the thread to block
511 *
512 *  Output parameters: NONE
513 *
514 *  INTERRUPT LATENCY:
515 *    EXTRACT_FIFO
516 */
517
518void _Thread_queue_Extract_fifo(
519  Thread_queue_Control *the_thread_queue,
520  Thread_Control       *the_thread
521)
522{
523  ISR_Level level;
524
525  _ISR_Disable( level );
526
527  if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
528    _ISR_Enable( level );
529    return;
530  }
531
532  _Chain_Extract_unprotected( &the_thread->Object.Node );
533
534  if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
535    _ISR_Enable( level );
536  } else {
537    _Watchdog_Deactivate( &the_thread->Timer );
538    _ISR_Enable( level );
539    (void) _Watchdog_Remove( &the_thread->Timer );
540  }
541
542  _Thread_Unblock( the_thread );
543
544#if defined(RTEMS_MULTIPROCESSING)
545  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
546    _Thread_MP_Free_proxy( the_thread );
547#endif
548 
549}
550
551/*PAGE
552 *
553 *  _Thread_queue_First_fifo
554 *
555 *  This routines returns a pointer to the first thread on the
556 *  specified threadq.
557 *
558 *  Input parameters:
559 *    the_thread_queue - pointer to threadq
560 *
561 *  Output parameters:
562 *    returns - first thread or NULL
563 */
564
565Thread_Control *_Thread_queue_First_fifo(
566  Thread_queue_Control *the_thread_queue
567)
568{
569  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
570    return (Thread_Control *) the_thread_queue->Queues.Fifo.first;
571
572  return NULL;
573}
574
575/*PAGE
576 *
577 *  _Thread_queue_Enqueue_priority
578 *
579 *  This routine blocks a thread, places it on a thread, and optionally
580 *  starts a timeout timer.
581 *
582 *  Input parameters:
583 *    the_thread_queue - pointer to threadq
584 *    thread           - thread to insert
585 *    timeout          - timeout interval in ticks
586 *
587 *  Output parameters: NONE
588 *
589 *  INTERRUPT LATENCY:
590 *    forward less than
591 *    forward equal
592 */
593
594void _Thread_queue_Enqueue_priority(
595  Thread_queue_Control *the_thread_queue,
596  Thread_Control       *the_thread,
597  Watchdog_Interval     timeout
598)
599{
600  Priority_Control     search_priority;
601  Thread_Control      *search_thread;
602  ISR_Level            level;
603  Chain_Control       *header;
604  unsigned32           header_index;
605  Chain_Node          *the_node;
606  Chain_Node          *next_node;
607  Chain_Node          *previous_node;
608  Chain_Node          *search_node;
609  Priority_Control     priority;
610  States_Control       block_state;
611  Thread_queue_States  sync_state;
612
613  _Chain_Initialize_empty( &the_thread->Wait.Block2n );
614
615  priority     = the_thread->current_priority;
616  header_index = _Thread_queue_Header_number( priority );
617  header       = &the_thread_queue->Queues.Priority[ header_index ];
618  block_state  = the_thread_queue->state;
619
620  if ( _Thread_queue_Is_reverse_search( priority ) )
621    goto restart_reverse_search;
622
623restart_forward_search:
624  search_priority = PRIORITY_MINIMUM - 1;
625  _ISR_Disable( level );
626  search_thread = (Thread_Control *) header->first;
627  while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
628    search_priority = search_thread->current_priority;
629    if ( priority <= search_priority )
630      break;
631
632#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
633    search_thread = (Thread_Control *) search_thread->Object.Node.next;
634    if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
635      break;
636    search_priority = search_thread->current_priority;
637    if ( priority <= search_priority )
638      break;
639#endif
640    _ISR_Flash( level );
641    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
642      _ISR_Enable( level );
643      goto restart_forward_search;
644    }
645    search_thread =
646       (Thread_Control *)search_thread->Object.Node.next;
647  }
648
649  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
650    goto synchronize;
651
652  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
653
654  if ( priority == search_priority )
655    goto equal_priority;
656
657  search_node   = (Chain_Node *) search_thread;
658  previous_node = search_node->previous;
659  the_node      = (Chain_Node *) the_thread;
660
661  the_node->next        = search_node;
662  the_node->previous    = previous_node;
663  previous_node->next   = the_node;
664  search_node->previous = the_node;
665  _ISR_Enable( level );
666  return;
667
668restart_reverse_search:
669  search_priority     = PRIORITY_MAXIMUM + 1;
670
671  _ISR_Disable( level );
672  search_thread = (Thread_Control *) header->last;
673  while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
674    search_priority = search_thread->current_priority;
675    if ( priority >= search_priority )
676      break;
677#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
678    search_thread = (Thread_Control *) search_thread->Object.Node.previous;
679    if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
680      break;
681    search_priority = search_thread->current_priority;
682    if ( priority >= search_priority )
683      break;
684#endif
685    _ISR_Flash( level );
686    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
687      _ISR_Enable( level );
688      goto restart_reverse_search;
689    }
690    search_thread = (Thread_Control *)
691                         search_thread->Object.Node.previous;
692  }
693
694  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
695    goto synchronize;
696
697  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
698
699  if ( priority == search_priority )
700    goto equal_priority;
701
702  search_node = (Chain_Node *) search_thread;
703  next_node   = search_node->next;
704  the_node    = (Chain_Node *) the_thread;
705
706  the_node->next      = next_node;
707  the_node->previous  = search_node;
708  search_node->next   = the_node;
709  next_node->previous = the_node;
710  _ISR_Enable( level );
711  return;
712
713equal_priority:               /* add at end of priority group */
714  search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
715  previous_node = search_node->previous;
716  the_node      = (Chain_Node *) the_thread;
717
718  the_node->next        = search_node;
719  the_node->previous    = previous_node;
720  previous_node->next   = the_node;
721  search_node->previous = the_node;
722  _ISR_Enable( level );
723  return;
724
725synchronize:
726
727  sync_state = the_thread_queue->sync_state;
728  the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
729
730  switch ( sync_state ) {
731    case THREAD_QUEUE_SYNCHRONIZED:
732      /*
733       *  This should never happen.  It indicates that someone did not
734       *  enter a thread queue critical section.
735       */
736      break;
737 
738    case THREAD_QUEUE_NOTHING_HAPPENED:
739      /*
740       *  This should never happen.  All of this was dealt with above.
741       */
742      break;
743 
744    case THREAD_QUEUE_TIMEOUT:
745      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
746      _ISR_Enable( level );
747      break;
748 
749    case THREAD_QUEUE_SATISFIED:
750      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
751        _Watchdog_Deactivate( &the_thread->Timer );
752        _ISR_Enable( level );
753        (void) _Watchdog_Remove( &the_thread->Timer );
754      } else
755        _ISR_Enable( level );
756      break;
757  }
758 
759  /*
760   *  Global objects with thread queue's should not be operated on from an
761   *  ISR.  But the sync code still must allow short timeouts to be processed
762   *  correctly.
763   */
764 
765  _Thread_Unblock( the_thread );
766 
767#if defined(RTEMS_MULTIPROCESSING)
768  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
769    _Thread_MP_Free_proxy( the_thread );
770#endif
771}
772
773/*PAGE
774 *
775 *  _Thread_queue_Dequeue_priority
776 *
777 *  This routine removes a thread from the specified PRIORITY based
778 *  threadq, unblocks it, and cancels its timeout timer.
779 *
780 *  Input parameters:
781 *    the_thread_queue - pointer to thread queue
782 *
783 *  Output parameters:
784 *    returns - thread dequeued or NULL
785 *
786 *  INTERRUPT LATENCY:
787 *    only case
788 */
789
790Thread_Control *_Thread_queue_Dequeue_priority(
791  Thread_queue_Control *the_thread_queue
792)
793{
794  unsigned32      index;
795  ISR_Level       level;
796  Thread_Control *the_thread = NULL;  /* just to remove warnings */
797  Thread_Control *new_first_thread;
798  Chain_Node     *new_first_node;
799  Chain_Node     *new_second_node;
800  Chain_Node     *last_node;
801  Chain_Node     *next_node;
802  Chain_Node     *previous_node;
803
804  _ISR_Disable( level );
805  for( index=0 ;
806       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
807       index++ ) {
808    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
809      the_thread = (Thread_Control *)
810                    the_thread_queue->Queues.Priority[ index ].first;
811      goto dequeue;
812    }
813  }
814
815  switch ( the_thread_queue->sync_state ) {
816    case THREAD_QUEUE_SYNCHRONIZED:
817    case THREAD_QUEUE_SATISFIED:
818      _ISR_Enable( level );
819      return NULL;
820
821    case THREAD_QUEUE_NOTHING_HAPPENED:
822    case THREAD_QUEUE_TIMEOUT:
823      the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
824      _ISR_Enable( level );
825      return _Thread_Executing;
826  }
827
828dequeue:
829  new_first_node   = the_thread->Wait.Block2n.first;
830  new_first_thread = (Thread_Control *) new_first_node;
831  next_node        = the_thread->Object.Node.next;
832  previous_node    = the_thread->Object.Node.previous;
833
834  if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
835    last_node       = the_thread->Wait.Block2n.last;
836    new_second_node = new_first_node->next;
837
838    previous_node->next      = new_first_node;
839    next_node->previous      = new_first_node;
840    new_first_node->next     = next_node;
841    new_first_node->previous = previous_node;
842
843    if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
844                                                /* > two threads on 2-n */
845      new_second_node->previous =
846                _Chain_Head( &new_first_thread->Wait.Block2n );
847
848      new_first_thread->Wait.Block2n.first = new_second_node;
849      new_first_thread->Wait.Block2n.last  = last_node;
850
851      last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
852    }
853  } else {
854    previous_node->next = next_node;
855    next_node->previous = previous_node;
856  }
857
858  if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
859    _ISR_Enable( level );
860    _Thread_Unblock( the_thread );
861  } else {
862    _Watchdog_Deactivate( &the_thread->Timer );
863    _ISR_Enable( level );
864    (void) _Watchdog_Remove( &the_thread->Timer );
865    _Thread_Unblock( the_thread );
866  }
867
868#if defined(RTEMS_MULTIPROCESSING)
869  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
870    _Thread_MP_Free_proxy( the_thread );
871#endif
872  return( the_thread );
873}
874
875/*PAGE
876 *
877 *  _Thread_queue_Extract_priority
878 *
879 *  This routine removes a specific thread from the specified threadq,
880 *  deletes any timeout, and unblocks the thread.
881 *
882 *  Input parameters:
883 *    the_thread_queue - pointer to a threadq header
884 *    the_thread       - pointer to a thread control block
885 *
886 *  Output parameters: NONE
887 *
888 *  INTERRUPT LATENCY:
889 *    EXTRACT_PRIORITY
890 */
891
892void _Thread_queue_Extract_priority(
893  Thread_queue_Control *the_thread_queue,
894  Thread_Control       *the_thread
895)
896{
897  ISR_Level              level;
898  Chain_Node     *the_node;
899  Chain_Node     *next_node;
900  Chain_Node     *previous_node;
901  Thread_Control *new_first_thread;
902  Chain_Node     *new_first_node;
903  Chain_Node     *new_second_node;
904  Chain_Node     *last_node;
905
906  the_node = (Chain_Node *) the_thread;
907  _ISR_Disable( level );
908  if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
909    next_node     = the_node->next;
910    previous_node = the_node->previous;
911
912    if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
913      new_first_node   = the_thread->Wait.Block2n.first;
914      new_first_thread = (Thread_Control *) new_first_node;
915      last_node        = the_thread->Wait.Block2n.last;
916      new_second_node  = new_first_node->next;
917
918      previous_node->next      = new_first_node;
919      next_node->previous      = new_first_node;
920      new_first_node->next     = next_node;
921      new_first_node->previous = previous_node;
922
923      if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
924                                          /* > two threads on 2-n */
925        new_second_node->previous =
926                  _Chain_Head( &new_first_thread->Wait.Block2n );
927        new_first_thread->Wait.Block2n.first = new_second_node;
928
929        new_first_thread->Wait.Block2n.last = last_node;
930        last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
931      }
932    } else {
933      previous_node->next = next_node;
934      next_node->previous = previous_node;
935    }
936
937    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
938      _ISR_Enable( level );
939      _Thread_Unblock( the_thread );
940    } else {
941      _Watchdog_Deactivate( &the_thread->Timer );
942      _ISR_Enable( level );
943      (void) _Watchdog_Remove( &the_thread->Timer );
944      _Thread_Unblock( the_thread );
945    }
946
947#if defined(RTEMS_MULTIPROCESSING)
948    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
949      _Thread_MP_Free_proxy( the_thread );
950#endif
951  }
952  else
953    _ISR_Enable( level );
954}
955
956/*PAGE
957 *
958 *  _Thread_queue_First_priority
959 *
960 *  This routines returns a pointer to the first thread on the
961 *  specified threadq.
962 *
963 *  Input parameters:
964 *    the_thread_queue - pointer to thread queue
965 *
966 *  Output parameters:
967 *    returns - first thread or NULL
968 */
969
970Thread_Control *_Thread_queue_First_priority (
971  Thread_queue_Control *the_thread_queue
972)
973{
974  unsigned32 index;
975
976  for( index=0 ;
977       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
978       index++ ) {
979    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
980      return (Thread_Control *)
981        the_thread_queue->Queues.Priority[ index ].first;
982  }
983  return NULL;
984}
985#endif
Note: See TracBrowser for help on using the repository browser.