source: rtems/cpukit/score/src/threadq.c @ 8d0b7d96

4.104.114.84.95
Last change on this file since 8d0b7d96 was 8d0b7d96, checked in by Joel Sherrill <joel.sherrill@…>, on 12/01/95 at 22:03:55

Insert mode argument to _Watchdog_Insert removed. Now are watchdog timers
are automatically activated upon insertion.

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