source: rtems/cpukit/score/src/threadq.c @ 7f6a24ab

4.104.114.84.95
Last change on this file since 7f6a24ab was 7f6a24ab, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 28, 1995 at 3:30:29 PM

Added unused priority ceiling parameter to rtems_semaphore_create.

Rearranged code to created thread handler routines to initialize,
start, restart, and "close/delete" a thread.

Made internal threads their own object class. This now uses the
thread support routines for starting and initializing a thread.

Insured deleted tasks are freed to the Inactive pool associated with the
correct Information block.

Added an RTEMS API specific data area to the thread control block.

Beginnings of removing the word "rtems" from the core.

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