source: rtems/cpukit/score/src/threadq.c @ ac7d5ef0

4.104.114.84.95
Last change on this file since ac7d5ef0 was ac7d5ef0, checked in by Joel Sherrill <joel.sherrill@…>, on May 11, 1995 at 5:39:37 PM

Initial revision

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