source: rtems/cpukit/score/src/threadq.c @ 3a4ae6c

4.104.114.84.95
Last change on this file since 3a4ae6c was 3a4ae6c, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 11, 1995 at 7:35:39 PM

The word "RTEMS" almost completely removed from the core.

Configuration Table Template file added and all tests
modified to use this. All gvar.h and conftbl.h files
removed from test directories.

Configuration parameter maximum_devices added.

Core semaphore and mutex handlers added and RTEMS API Semaphore
Manager updated to reflect this.

Initialization sequence changed to invoke API specific initialization
routines. Initialization tasks table now owned by RTEMS Tasks Manager.

Added user extension for post-switch.

Utilized user extensions to implement API specific functionality
like signal dispatching.

Added extensions to the System Initialization Thread so that an
API can register a function to be invoked while the system
is being initialized. These are largely equivalent to the
pre-driver and post-driver hooks.

Added the Modules file oar-go32_p5, modified oar-go32, and modified
the file make/custom/go32.cfg to look at an environment varable which
determines what CPU model is being used.

All BSPs updated to reflect named devices and clock driver's IOCTL
used by the Shared Memory Driver. Also merged clock isr into
main file and removed ckisr.c where possible.

Updated spsize to reflect new and moved variables.

Makefiles for the executive source and include files updated to show
break down of files into Core, RTEMS API, and Neither.

Header and inline files installed into subdirectory based on whether
logically in the Core or a part of the RTEMS API.

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