source: rtems/cpukit/score/src/threadq.c @ 5e9b32b

4.104.114.84.95
Last change on this file since 5e9b32b was 5e9b32b, checked in by Joel Sherrill <joel.sherrill@…>, on 09/26/95 at 19:27:15

posix support initially added

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