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

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

Added new synchronization algorithm.

  • Property mode set to 100644
File size: 24.1 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_ACTIVATE_NOW
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( 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 ( _Objects_Is_local_id( the_thread->Object.id ) )
262      the_thread->Wait.return_code = status;
263    else
264      ( *remote_extract_callout )( the_thread );
265  }
266}
267
268/*PAGE
269 *
270 *  _Thread_queue_First
271 *
272 *  This routines returns a pointer to the first thread on the
273 *  specified threadq.
274 *
275 *  Input parameters:
276 *    the_thread_queue - pointer to thread queue
277 *
278 *  Output parameters:
279 *    returns - first thread or NULL
280 */
281
282Thread_Control *_Thread_queue_First(
283  Thread_queue_Control *the_thread_queue
284)
285{
286  Thread_Control *the_thread;
287
288  switch ( the_thread_queue->discipline ) {
289    case THREAD_QUEUE_DISCIPLINE_FIFO:
290      the_thread = _Thread_queue_First_fifo( the_thread_queue );
291      break;
292    case THREAD_QUEUE_DISCIPLINE_PRIORITY:
293      the_thread = _Thread_queue_First_priority( the_thread_queue );
294      break;
295    default:              /* this is only to prevent warnings */
296      the_thread = NULL;
297      break;
298  }
299
300  return the_thread;
301}
302
303/*PAGE
304 *
305 *  _Thread_queue_Timeout
306 *
307 *  This routine processes a thread which timeouts while waiting on
308 *  a thread queue. It is called by the watchdog handler.
309 *
310 *  Input parameters:
311 *    id - thread id
312 *
313 *  Output parameters: NONE
314 */
315
316void _Thread_queue_Timeout(
317  Objects_Id  id,
318  void       *ignored
319)
320{
321  Thread_Control       *the_thread;
322  Thread_queue_Control *the_thread_queue;
323  Objects_Locations     location;
324
325  the_thread = _Thread_Get( id, &location );
326  switch ( location ) {
327    case OBJECTS_ERROR:
328    case OBJECTS_REMOTE:  /* impossible */
329      break;
330    case OBJECTS_LOCAL:
331      the_thread_queue = the_thread->Wait.queue;
332
333      if ( the_thread_queue->sync == TRUE && _Thread_Is_executing(the_thread)) {
334        if ( the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED )
335          the_thread_queue->sync_state = THREAD_QUEUE_TIMEOUT;
336      } else {
337        the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
338        _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
339      }
340      _Thread_Unnest_dispatch();
341      break;
342  }
343}
344
345/*PAGE
346 *
347 *  _Thread_queue_Enqueue_fifo
348 *
349 *  This routine blocks a thread, places it on a thread, and optionally
350 *  starts a timeout timer.
351 *
352 *  Input parameters:
353 *    the_thread_queue - pointer to threadq
354 *    the_thread       - pointer to the thread to block
355 *    timeout          - interval to wait
356 *
357 *  Output parameters: NONE
358 *
359 *  INTERRUPT LATENCY:
360 *    only case
361 */
362
363void _Thread_queue_Enqueue_fifo (
364  Thread_queue_Control *the_thread_queue,
365  Thread_Control       *the_thread,
366  Watchdog_Interval    timeout
367)
368{
369  ISR_Level level;
370
371  _ISR_Disable( level );
372
373  switch ( the_thread_queue->sync_state ) {
374    case THREAD_QUEUE_NOTHING_HAPPENED:
375      the_thread_queue->sync = FALSE;
376      _Chain_Append_unprotected(
377        &the_thread_queue->Queues.Fifo,
378        &the_thread->Object.Node
379      );
380      _ISR_Enable( level );
381      return;
382
383    case THREAD_QUEUE_TIMEOUT:
384      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
385      _ISR_Enable( level );
386      break;
387
388    case THREAD_QUEUE_SATISFIED:
389      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
390        _Watchdog_Deactivate( &the_thread->Timer );
391        _ISR_Enable( level );
392        (void) _Watchdog_Remove( &the_thread->Timer );
393      } else
394        _ISR_Enable( level );
395      break;
396  }
397
398  /*
399   *  Global objects with thread queue's should not be operated on from an
400   *  ISR.  But the sync code still must allow short timeouts to be processed
401   *  correctly.
402   */
403
404  _Thread_Unblock( the_thread );
405
406  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
407    _Thread_MP_Free_proxy( the_thread );
408
409}
410
411/*PAGE
412 *
413 *  _Thread_queue_Dequeue_fifo
414 *
415 *  This routine removes a thread from the specified threadq.
416 *
417 *  Input parameters:
418 *    the_thread_queue - pointer to threadq
419 *
420 *  Output parameters:
421 *    returns - thread dequeued or NULL
422 *
423 *  INTERRUPT LATENCY:
424 *    check sync
425 *    FIFO
426 */
427
428Thread_Control *_Thread_queue_Dequeue_fifo(
429  Thread_queue_Control *the_thread_queue
430)
431{
432  ISR_Level              level;
433  Thread_Control *the_thread;
434
435  _ISR_Disable( level );
436  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
437
438    the_thread = (Thread_Control *)
439       _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
440
441    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
442      _ISR_Enable( level );
443      _Thread_Unblock( the_thread );
444    } else {
445      _Watchdog_Deactivate( &the_thread->Timer );
446      _ISR_Enable( level );
447      (void) _Watchdog_Remove( &the_thread->Timer );
448      _Thread_Unblock( the_thread );
449    }
450
451    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
452      _Thread_MP_Free_proxy( the_thread );
453
454    return the_thread;
455  } else if ( the_thread_queue->sync ) {
456    the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
457    _ISR_Enable( level );
458    return _Thread_Executing;
459  } else {
460    _ISR_Enable( level );
461    return NULL;
462  }
463}
464
465/*PAGE
466 *
467 *  _Thread_queue_Extract_fifo
468 *
469 *  This routine removes a specific thread from the specified threadq,
470 *  deletes any timeout, and unblocks the thread.
471 *
472 *  Input parameters:
473 *    the_thread_queue - pointer to a threadq header
474 *    the_thread       - pointer to the thread to block
475 *
476 *  Output parameters: NONE
477 *
478 *  INTERRUPT LATENCY:
479 *    EXTRACT_FIFO
480 */
481
482void _Thread_queue_Extract_fifo(
483  Thread_queue_Control *the_thread_queue,
484  Thread_Control       *the_thread
485)
486{
487  ISR_Level level;
488
489  _ISR_Disable( level );
490
491  if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
492    _ISR_Enable( level );
493    return;
494  }
495
496  _Chain_Extract_unprotected( &the_thread->Object.Node );
497
498  if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
499    _ISR_Enable( level );
500  } else {
501    _Watchdog_Deactivate( &the_thread->Timer );
502    _ISR_Enable( level );
503    (void) _Watchdog_Remove( &the_thread->Timer );
504  }
505
506  _Thread_Unblock( the_thread );
507
508  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
509    _Thread_MP_Free_proxy( the_thread );
510 
511}
512
513/*PAGE
514 *
515 *  _Thread_queue_First_fifo
516 *
517 *  This routines returns a pointer to the first thread on the
518 *  specified threadq.
519 *
520 *  Input parameters:
521 *    the_thread_queue - pointer to threadq
522 *
523 *  Output parameters:
524 *    returns - first thread or NULL
525 */
526
527Thread_Control *_Thread_queue_First_fifo(
528  Thread_queue_Control *the_thread_queue
529)
530{
531  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
532    return (Thread_Control *) the_thread_queue->Queues.Fifo.first;
533
534  return NULL;
535}
536
537/*PAGE
538 *
539 *  _Thread_queue_Enqueue_priority
540 *
541 *  This routine blocks a thread, places it on a thread, and optionally
542 *  starts a timeout timer.
543 *
544 *  Input parameters:
545 *    the_thread_queue - pointer to threadq
546 *    thread           - thread to insert
547 *    timeout          - timeout interval in ticks
548 *
549 *  Output parameters: NONE
550 *
551 *  INTERRUPT LATENCY:
552 *    forward less than
553 *    forward equal
554 */
555
556void _Thread_queue_Enqueue_priority(
557  Thread_queue_Control *the_thread_queue,
558  Thread_Control       *the_thread,
559  Watchdog_Interval     timeout
560)
561{
562  Priority_Control  search_priority;
563  Thread_Control   *search_thread;
564  ISR_Level         level;
565  Chain_Control    *header;
566  unsigned32        header_index;
567  Chain_Node       *the_node;
568  Chain_Node       *next_node;
569  Chain_Node       *previous_node;
570  Chain_Node       *search_node;
571  Priority_Control  priority;
572  States_Control    block_state;
573
574  _Chain_Initialize_empty( &the_thread->Wait.Block2n );
575
576  priority     = the_thread->current_priority;
577  header_index = _Thread_queue_Header_number( priority );
578  header       = &the_thread_queue->Queues.Priority[ header_index ];
579  block_state  = the_thread_queue->state;
580
581  if ( _Thread_queue_Is_reverse_search( priority ) )
582    goto restart_reverse_search;
583
584restart_forward_search:
585  search_priority = PRIORITY_MINIMUM - 1;
586  _ISR_Disable( level );
587  search_thread = (Thread_Control *) header->first;
588  while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
589    search_priority = search_thread->current_priority;
590    if ( priority <= search_priority )
591      break;
592
593#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
594    search_thread = (Thread_Control *) search_thread->Object.Node.next;
595    if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
596      break;
597    search_priority = search_thread->current_priority;
598    if ( priority <= search_priority )
599      break;
600#endif
601    _ISR_Flash( level );
602    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
603      _ISR_Enable( level );
604      goto restart_forward_search;
605    }
606    search_thread =
607       (Thread_Control *)search_thread->Object.Node.next;
608  }
609  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
610    goto syncronize;
611
612  the_thread_queue->sync = FALSE;
613
614  if ( priority == search_priority )
615    goto equal_priority;
616
617  search_node   = (Chain_Node *) search_thread;
618  previous_node = search_node->previous;
619  the_node      = (Chain_Node *) the_thread;
620
621  the_node->next        = search_node;
622  the_node->previous    = previous_node;
623  previous_node->next   = the_node;
624  search_node->previous = the_node;
625  _ISR_Enable( level );
626  return;
627
628restart_reverse_search:
629  search_priority     = PRIORITY_MAXIMUM + 1;
630
631  _ISR_Disable( level );
632  search_thread = (Thread_Control *) header->last;
633  while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
634    search_priority = search_thread->current_priority;
635    if ( priority >= search_priority )
636      break;
637#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
638    search_thread = (Thread_Control *) search_thread->Object.Node.previous;
639    if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
640      break;
641    search_priority = search_thread->current_priority;
642    if ( priority >= search_priority )
643      break;
644#endif
645    _ISR_Flash( level );
646    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
647      _ISR_Enable( level );
648      goto restart_reverse_search;
649    }
650    search_thread = (Thread_Control *)
651                         search_thread->Object.Node.previous;
652  }
653  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
654    goto syncronize;
655
656  the_thread_queue->sync = FALSE;
657
658  if ( priority == search_priority )
659    goto equal_priority;
660
661  search_node = (Chain_Node *) search_thread;
662  next_node   = search_node->next;
663  the_node    = (Chain_Node *) the_thread;
664
665  the_node->next      = next_node;
666  the_node->previous  = search_node;
667  search_node->next   = the_node;
668  next_node->previous = the_node;
669  _ISR_Enable( level );
670  return;
671
672equal_priority:               /* add at end of priority group */
673  search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
674  previous_node = search_node->previous;
675  the_node      = (Chain_Node *) the_thread;
676
677  the_node->next        = search_node;
678  the_node->previous    = previous_node;
679  previous_node->next   = the_node;
680  search_node->previous = the_node;
681  _ISR_Enable( level );
682  return;
683
684syncronize:
685
686  switch ( the_thread_queue->sync_state ) {
687    case THREAD_QUEUE_NOTHING_HAPPENED:
688      /*
689       *  All of this was dealt with above.  This should never happen.
690       */
691      break;
692 
693    case THREAD_QUEUE_TIMEOUT:
694      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
695      _ISR_Enable( level );
696      break;
697 
698    case THREAD_QUEUE_SATISFIED:
699      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
700        _Watchdog_Deactivate( &the_thread->Timer );
701        _ISR_Enable( level );
702        (void) _Watchdog_Remove( &the_thread->Timer );
703      } else
704        _ISR_Enable( level );
705      break;
706  }
707 
708  /*
709   *  Global objects with thread queue's should not be operated on from an
710   *  ISR.  But the sync code still must allow short timeouts to be processed
711   *  correctly.
712   */
713 
714  _Thread_Unblock( the_thread );
715 
716  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
717    _Thread_MP_Free_proxy( the_thread );
718}
719
720/*PAGE
721 *
722 *  _Thread_queue_Dequeue_priority
723 *
724 *  This routine removes a thread from the specified PRIORITY based
725 *  threadq, unblocks it, and cancels its timeout timer.
726 *
727 *  Input parameters:
728 *    the_thread_queue - pointer to thread queue
729 *
730 *  Output parameters:
731 *    returns - thread dequeued or NULL
732 *
733 *  INTERRUPT LATENCY:
734 *    only case
735 */
736
737Thread_Control *_Thread_queue_Dequeue_priority(
738  Thread_queue_Control *the_thread_queue
739)
740{
741  unsigned32             index;
742  ISR_Level              level;
743  Thread_Control *the_thread;
744  Thread_Control *new_first_thread;
745  Chain_Node     *new_first_node;
746  Chain_Node     *new_second_node;
747  Chain_Node     *last_node;
748  Chain_Node     *next_node;
749  Chain_Node     *previous_node;
750
751  _ISR_Disable( level );
752  for( index=0 ;
753       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
754       index++ ) {
755    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
756      the_thread = (Thread_Control *)
757                    the_thread_queue->Queues.Priority[ index ].first;
758      goto dequeue;
759    }
760  }
761
762  if ( the_thread_queue->sync ) {
763    the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
764    _ISR_Enable( level );
765    return _Thread_Executing;
766  }
767
768  _ISR_Enable( level );
769  return NULL;
770
771dequeue:
772  new_first_node   = the_thread->Wait.Block2n.first;
773  new_first_thread = (Thread_Control *) new_first_node;
774  next_node        = the_thread->Object.Node.next;
775  previous_node    = the_thread->Object.Node.previous;
776
777  if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
778    last_node       = the_thread->Wait.Block2n.last;
779    new_second_node = new_first_node->next;
780
781    previous_node->next      = new_first_node;
782    next_node->previous      = new_first_node;
783    new_first_node->next     = next_node;
784    new_first_node->previous = previous_node;
785
786    if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
787                                                /* > two threads on 2-n */
788      new_second_node->previous =
789                _Chain_Head( &new_first_thread->Wait.Block2n );
790
791      new_first_thread->Wait.Block2n.first = new_second_node;
792      new_first_thread->Wait.Block2n.last  = last_node;
793
794      last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
795    }
796  } else {
797    previous_node->next = next_node;
798    next_node->previous = previous_node;
799  }
800
801  if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
802    _ISR_Enable( level );
803    _Thread_Unblock( the_thread );
804  } else {
805    _Watchdog_Deactivate( &the_thread->Timer );
806    _ISR_Enable( level );
807    (void) _Watchdog_Remove( &the_thread->Timer );
808    _Thread_Unblock( the_thread );
809  }
810
811  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
812    _Thread_MP_Free_proxy( the_thread );
813  return( the_thread );
814}
815
816/*PAGE
817 *
818 *  _Thread_queue_Extract_priority
819 *
820 *  This routine removes a specific thread from the specified threadq,
821 *  deletes any timeout, and unblocks the thread.
822 *
823 *  Input parameters:
824 *    the_thread_queue - pointer to a threadq header
825 *    the_thread       - pointer to a thread control block
826 *
827 *  Output parameters: NONE
828 *
829 *  INTERRUPT LATENCY:
830 *    EXTRACT_PRIORITY
831 */
832
833void _Thread_queue_Extract_priority(
834  Thread_queue_Control *the_thread_queue,
835  Thread_Control       *the_thread
836)
837{
838  ISR_Level              level;
839  Chain_Node     *the_node;
840  Chain_Node     *next_node;
841  Chain_Node     *previous_node;
842  Thread_Control *new_first_thread;
843  Chain_Node     *new_first_node;
844  Chain_Node     *new_second_node;
845  Chain_Node     *last_node;
846
847  the_node = (Chain_Node *) the_thread;
848  _ISR_Disable( level );
849  if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
850    next_node     = the_node->next;
851    previous_node = the_node->previous;
852
853    if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
854      new_first_node   = the_thread->Wait.Block2n.first;
855      new_first_thread = (Thread_Control *) new_first_node;
856      last_node        = the_thread->Wait.Block2n.last;
857      new_second_node  = new_first_node->next;
858
859      previous_node->next      = new_first_node;
860      next_node->previous      = new_first_node;
861      new_first_node->next     = next_node;
862      new_first_node->previous = previous_node;
863
864      if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
865                                          /* > two threads on 2-n */
866        new_second_node->previous =
867                  _Chain_Head( &new_first_thread->Wait.Block2n );
868        new_first_thread->Wait.Block2n.first = new_second_node;
869
870        new_first_thread->Wait.Block2n.last = last_node;
871        last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
872      }
873    } else {
874      previous_node->next = next_node;
875      next_node->previous = previous_node;
876    }
877
878    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
879      _ISR_Enable( level );
880      _Thread_Unblock( the_thread );
881    } else {
882      _Watchdog_Deactivate( &the_thread->Timer );
883      _ISR_Enable( level );
884      (void) _Watchdog_Remove( &the_thread->Timer );
885      _Thread_Unblock( the_thread );
886    }
887
888    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
889      _Thread_MP_Free_proxy( the_thread );
890  }
891  else
892    _ISR_Enable( level );
893}
894
895/*PAGE
896 *
897 *  _Thread_queue_First_priority
898 *
899 *  This routines returns a pointer to the first thread on the
900 *  specified threadq.
901 *
902 *  Input parameters:
903 *    the_thread_queue - pointer to thread queue
904 *
905 *  Output parameters:
906 *    returns - first thread or NULL
907 */
908
909Thread_Control *_Thread_queue_First_priority (
910  Thread_queue_Control *the_thread_queue
911)
912{
913  unsigned32 index;
914
915  for( index=0 ;
916       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
917       index++ ) {
918    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
919      return (Thread_Control *)
920        the_thread_queue->Queues.Priority[ index ].first;
921  }
922  return NULL;
923}
Note: See TracBrowser for help on using the repository browser.