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

4.104.114.84.95
Last change on this file since f00a0522 was f00a0522, checked in by Joel Sherrill <joel.sherrill@…>, on 02/01/96 at 21:54:40

synchronization state bugs address

  • Property mode set to 100644
File size: 24.2 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  the_thread_queue->sync = FALSE;
370
371  switch ( the_thread_queue->sync_state ) {
372    case THREAD_QUEUE_NOTHING_HAPPENED:
373      _Chain_Append_unprotected(
374        &the_thread_queue->Queues.Fifo,
375        &the_thread->Object.Node
376      );
377      _ISR_Enable( level );
378      return;
379
380    case THREAD_QUEUE_TIMEOUT:
381      the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
382      _ISR_Enable( level );
383      break;
384
385    case THREAD_QUEUE_SATISFIED:
386      if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
387        _Watchdog_Deactivate( &the_thread->Timer );
388        _ISR_Enable( level );
389        (void) _Watchdog_Remove( &the_thread->Timer );
390      } else
391        _ISR_Enable( level );
392      break;
393  }
394
395  /*
396   *  Global objects with thread queue's should not be operated on from an
397   *  ISR.  But the sync code still must allow short timeouts to be processed
398   *  correctly.
399   */
400
401  _Thread_Unblock( the_thread );
402
403  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
404    _Thread_MP_Free_proxy( the_thread );
405
406}
407
408/*PAGE
409 *
410 *  _Thread_queue_Dequeue_fifo
411 *
412 *  This routine removes a thread from the specified threadq.
413 *
414 *  Input parameters:
415 *    the_thread_queue - pointer to threadq
416 *
417 *  Output parameters:
418 *    returns - thread dequeued or NULL
419 *
420 *  INTERRUPT LATENCY:
421 *    check sync
422 *    FIFO
423 */
424
425Thread_Control *_Thread_queue_Dequeue_fifo(
426  Thread_queue_Control *the_thread_queue
427)
428{
429  ISR_Level              level;
430  Thread_Control *the_thread;
431
432  _ISR_Disable( level );
433  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
434
435    the_thread = (Thread_Control *)
436       _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
437
438    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
439      _ISR_Enable( level );
440      _Thread_Unblock( the_thread );
441    } else {
442      _Watchdog_Deactivate( &the_thread->Timer );
443      _ISR_Enable( level );
444      (void) _Watchdog_Remove( &the_thread->Timer );
445      _Thread_Unblock( the_thread );
446    }
447
448    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
449      _Thread_MP_Free_proxy( the_thread );
450
451    return the_thread;
452  } else if ( the_thread_queue->sync &&
453              the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED ) {
454    the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
455    _ISR_Enable( level );
456    return _Thread_Executing;
457  } else {
458    _ISR_Enable( level );
459    return NULL;
460  }
461}
462
463/*PAGE
464 *
465 *  _Thread_queue_Extract_fifo
466 *
467 *  This routine removes a specific thread from the specified threadq,
468 *  deletes any timeout, and unblocks the thread.
469 *
470 *  Input parameters:
471 *    the_thread_queue - pointer to a threadq header
472 *    the_thread       - pointer to the thread to block
473 *
474 *  Output parameters: NONE
475 *
476 *  INTERRUPT LATENCY:
477 *    EXTRACT_FIFO
478 */
479
480void _Thread_queue_Extract_fifo(
481  Thread_queue_Control *the_thread_queue,
482  Thread_Control       *the_thread
483)
484{
485  ISR_Level level;
486
487  _ISR_Disable( level );
488
489  if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
490    _ISR_Enable( level );
491    return;
492  }
493
494  _Chain_Extract_unprotected( &the_thread->Object.Node );
495
496  if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
497    _ISR_Enable( level );
498  } else {
499    _Watchdog_Deactivate( &the_thread->Timer );
500    _ISR_Enable( level );
501    (void) _Watchdog_Remove( &the_thread->Timer );
502  }
503
504  _Thread_Unblock( the_thread );
505
506  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
507    _Thread_MP_Free_proxy( the_thread );
508 
509}
510
511/*PAGE
512 *
513 *  _Thread_queue_First_fifo
514 *
515 *  This routines returns a pointer to the first thread on the
516 *  specified threadq.
517 *
518 *  Input parameters:
519 *    the_thread_queue - pointer to threadq
520 *
521 *  Output parameters:
522 *    returns - first thread or NULL
523 */
524
525Thread_Control *_Thread_queue_First_fifo(
526  Thread_queue_Control *the_thread_queue
527)
528{
529  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
530    return (Thread_Control *) the_thread_queue->Queues.Fifo.first;
531
532  return NULL;
533}
534
535/*PAGE
536 *
537 *  _Thread_queue_Enqueue_priority
538 *
539 *  This routine blocks a thread, places it on a thread, and optionally
540 *  starts a timeout timer.
541 *
542 *  Input parameters:
543 *    the_thread_queue - pointer to threadq
544 *    thread           - thread to insert
545 *    timeout          - timeout interval in ticks
546 *
547 *  Output parameters: NONE
548 *
549 *  INTERRUPT LATENCY:
550 *    forward less than
551 *    forward equal
552 */
553
554void _Thread_queue_Enqueue_priority(
555  Thread_queue_Control *the_thread_queue,
556  Thread_Control       *the_thread,
557  Watchdog_Interval     timeout
558)
559{
560  Priority_Control  search_priority;
561  Thread_Control   *search_thread;
562  ISR_Level         level;
563  Chain_Control    *header;
564  unsigned32        header_index;
565  Chain_Node       *the_node;
566  Chain_Node       *next_node;
567  Chain_Node       *previous_node;
568  Chain_Node       *search_node;
569  Priority_Control  priority;
570  States_Control    block_state;
571
572  _Chain_Initialize_empty( &the_thread->Wait.Block2n );
573
574  priority     = the_thread->current_priority;
575  header_index = _Thread_queue_Header_number( priority );
576  header       = &the_thread_queue->Queues.Priority[ header_index ];
577  block_state  = the_thread_queue->state;
578
579  if ( _Thread_queue_Is_reverse_search( priority ) )
580    goto restart_reverse_search;
581
582restart_forward_search:
583  search_priority = PRIORITY_MINIMUM - 1;
584  _ISR_Disable( level );
585  search_thread = (Thread_Control *) header->first;
586  while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
587    search_priority = search_thread->current_priority;
588    if ( priority <= search_priority )
589      break;
590
591#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
592    search_thread = (Thread_Control *) search_thread->Object.Node.next;
593    if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
594      break;
595    search_priority = search_thread->current_priority;
596    if ( priority <= search_priority )
597      break;
598#endif
599    _ISR_Flash( level );
600    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
601      _ISR_Enable( level );
602      goto restart_forward_search;
603    }
604    search_thread =
605       (Thread_Control *)search_thread->Object.Node.next;
606  }
607
608  the_thread_queue->sync = FALSE;
609
610  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
611    goto syncronize;
612
613  if ( priority == search_priority )
614    goto equal_priority;
615
616  search_node   = (Chain_Node *) search_thread;
617  previous_node = search_node->previous;
618  the_node      = (Chain_Node *) the_thread;
619
620  the_node->next        = search_node;
621  the_node->previous    = previous_node;
622  previous_node->next   = the_node;
623  search_node->previous = the_node;
624  _ISR_Enable( level );
625  return;
626
627restart_reverse_search:
628  search_priority     = PRIORITY_MAXIMUM + 1;
629
630  _ISR_Disable( level );
631  search_thread = (Thread_Control *) header->last;
632  while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
633    search_priority = search_thread->current_priority;
634    if ( priority >= search_priority )
635      break;
636#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
637    search_thread = (Thread_Control *) search_thread->Object.Node.previous;
638    if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
639      break;
640    search_priority = search_thread->current_priority;
641    if ( priority >= search_priority )
642      break;
643#endif
644    _ISR_Flash( level );
645    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
646      _ISR_Enable( level );
647      goto restart_reverse_search;
648    }
649    search_thread = (Thread_Control *)
650                         search_thread->Object.Node.previous;
651  }
652
653  the_thread_queue->sync = FALSE;
654
655  if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
656    goto syncronize;
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    the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
765    _ISR_Enable( level );
766    return _Thread_Executing;
767  }
768
769  _ISR_Enable( level );
770  return NULL;
771
772dequeue:
773  new_first_node   = the_thread->Wait.Block2n.first;
774  new_first_thread = (Thread_Control *) new_first_node;
775  next_node        = the_thread->Object.Node.next;
776  previous_node    = the_thread->Object.Node.previous;
777
778  if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
779    last_node       = the_thread->Wait.Block2n.last;
780    new_second_node = new_first_node->next;
781
782    previous_node->next      = new_first_node;
783    next_node->previous      = new_first_node;
784    new_first_node->next     = next_node;
785    new_first_node->previous = previous_node;
786
787    if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
788                                                /* > two threads on 2-n */
789      new_second_node->previous =
790                _Chain_Head( &new_first_thread->Wait.Block2n );
791
792      new_first_thread->Wait.Block2n.first = new_second_node;
793      new_first_thread->Wait.Block2n.last  = last_node;
794
795      last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
796    }
797  } else {
798    previous_node->next = next_node;
799    next_node->previous = previous_node;
800  }
801
802  if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
803    _ISR_Enable( level );
804    _Thread_Unblock( the_thread );
805  } else {
806    _Watchdog_Deactivate( &the_thread->Timer );
807    _ISR_Enable( level );
808    (void) _Watchdog_Remove( &the_thread->Timer );
809    _Thread_Unblock( the_thread );
810  }
811
812  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
813    _Thread_MP_Free_proxy( the_thread );
814  return( the_thread );
815}
816
817/*PAGE
818 *
819 *  _Thread_queue_Extract_priority
820 *
821 *  This routine removes a specific thread from the specified threadq,
822 *  deletes any timeout, and unblocks the thread.
823 *
824 *  Input parameters:
825 *    the_thread_queue - pointer to a threadq header
826 *    the_thread       - pointer to a thread control block
827 *
828 *  Output parameters: NONE
829 *
830 *  INTERRUPT LATENCY:
831 *    EXTRACT_PRIORITY
832 */
833
834void _Thread_queue_Extract_priority(
835  Thread_queue_Control *the_thread_queue,
836  Thread_Control       *the_thread
837)
838{
839  ISR_Level              level;
840  Chain_Node     *the_node;
841  Chain_Node     *next_node;
842  Chain_Node     *previous_node;
843  Thread_Control *new_first_thread;
844  Chain_Node     *new_first_node;
845  Chain_Node     *new_second_node;
846  Chain_Node     *last_node;
847
848  the_node = (Chain_Node *) the_thread;
849  _ISR_Disable( level );
850  if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
851    next_node     = the_node->next;
852    previous_node = the_node->previous;
853
854    if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
855      new_first_node   = the_thread->Wait.Block2n.first;
856      new_first_thread = (Thread_Control *) new_first_node;
857      last_node        = the_thread->Wait.Block2n.last;
858      new_second_node  = new_first_node->next;
859
860      previous_node->next      = new_first_node;
861      next_node->previous      = new_first_node;
862      new_first_node->next     = next_node;
863      new_first_node->previous = previous_node;
864
865      if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
866                                          /* > two threads on 2-n */
867        new_second_node->previous =
868                  _Chain_Head( &new_first_thread->Wait.Block2n );
869        new_first_thread->Wait.Block2n.first = new_second_node;
870
871        new_first_thread->Wait.Block2n.last = last_node;
872        last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
873      }
874    } else {
875      previous_node->next = next_node;
876      next_node->previous = previous_node;
877    }
878
879    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
880      _ISR_Enable( level );
881      _Thread_Unblock( the_thread );
882    } else {
883      _Watchdog_Deactivate( &the_thread->Timer );
884      _ISR_Enable( level );
885      (void) _Watchdog_Remove( &the_thread->Timer );
886      _Thread_Unblock( the_thread );
887    }
888
889    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
890      _Thread_MP_Free_proxy( the_thread );
891  }
892  else
893    _ISR_Enable( level );
894}
895
896/*PAGE
897 *
898 *  _Thread_queue_First_priority
899 *
900 *  This routines returns a pointer to the first thread on the
901 *  specified threadq.
902 *
903 *  Input parameters:
904 *    the_thread_queue - pointer to thread queue
905 *
906 *  Output parameters:
907 *    returns - first thread or NULL
908 */
909
910Thread_Control *_Thread_queue_First_priority (
911  Thread_queue_Control *the_thread_queue
912)
913{
914  unsigned32 index;
915
916  for( index=0 ;
917       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
918       index++ ) {
919    if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
920      return (Thread_Control *)
921        the_thread_queue->Queues.Priority[ index ].first;
922  }
923  return NULL;
924}
Note: See TracBrowser for help on using the repository browser.