source: rtems/cpukit/score/src/threadq.c @ 97e2729d

4.104.114.84.95
Last change on this file since 97e2729d was 97e2729d, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 23, 1998 at 5:38:09 PM

Added --disable-multiprocessing flag and modified a lot of files to make
it work.

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