source: rtems/cpukit/score/src/threadrestart.c @ c3105894

5
Last change on this file since c3105894 was c3105894, checked in by Sebastian Huber <sebastian.huber@…>, on 10/19/17 at 11:47:57

score: Move thread queue timeout handling

Update #3117.
Update #3182.

  • Property mode set to 100644
File size: 17.9 KB
RevLine 
[f7f1d77]1/**
2 * @file
[05df0a8]3 *
[f7f1d77]4 * @brief Restart Thread
5 * @ingroup ScoreThread
6 */
7
8/*
[08311cc3]9 *  COPYRIGHT (c) 1989-1999.
[05df0a8]10 *  On-Line Applications Research Corporation (OAR).
11 *
[9949d8a7]12 *  Copyright (c) 2014, 2016 embedded brains GmbH.
[1b1be254]13 *
[05df0a8]14 *  The license and distribution terms for this file may be
[dcf3687]15 *  found in the file LICENSE in this distribution or at
[c499856]16 *  http://www.rtems.org/license/LICENSE.
[05df0a8]17 */
18
[a8eed23]19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
[5618c37a]23#include <rtems/score/threadimpl.h>
[1b1be254]24#include <rtems/score/apimutex.h>
25#include <rtems/score/assert.h>
26#include <rtems/score/chainimpl.h>
27#include <rtems/score/isrlock.h>
28#include <rtems/score/schedulerimpl.h>
29#include <rtems/score/sysstate.h>
[dcd5e26]30#include <rtems/score/threadqimpl.h>
[3be0c9a]31#include <rtems/score/userextimpl.h>
[dcd5e26]32#include <rtems/score/watchdogimpl.h>
[1b1be254]33#include <rtems/score/wkspace.h>
34
[232147dd]35#define THREAD_JOIN_TQ_OPERATIONS &_Thread_queue_Operations_priority
36
[6e4f929]37static void _Thread_Life_action_handler(
38  Thread_Control   *executing,
39  Thread_Action    *action,
40  ISR_lock_Context *lock_context
41);
42
[1b1be254]43typedef struct {
44  Chain_Control Chain;
45  ISR_lock_Control Lock;
46} Thread_Zombie_control;
47
48static Thread_Zombie_control _Thread_Zombies = {
49  .Chain = CHAIN_INITIALIZER_EMPTY( _Thread_Zombies.Chain ),
50  .Lock = ISR_LOCK_INITIALIZER( "thread zombies" )
51};
52
[300f6a48]53static void _Thread_Raise_real_priority(
[900d337f]54  Thread_Control   *the_thread,
[300f6a48]55  Priority_Control  priority
[900d337f]56)
57{
[300f6a48]58  Thread_queue_Context queue_context;
[900d337f]59
[5b6c290]60  _Thread_queue_Context_initialize( &queue_context );
[c09db57]61  _Thread_queue_Context_clear_priority_updates( &queue_context );
[5b6c290]62  _Thread_Wait_acquire( the_thread, &queue_context );
[900d337f]63
[300f6a48]64  if ( priority < the_thread->Real_priority.priority ) {
65    _Thread_Priority_change(
66      the_thread,
67      &the_thread->Real_priority,
68      priority,
69      false,
70      &queue_context
71    );
72  }
[900d337f]73
[300f6a48]74  _Thread_Wait_release( the_thread, &queue_context );
75  _Thread_Priority_update( &queue_context );
[7023d82c]76}
77
[232147dd]78typedef struct {
[631b3c8]79  Thread_queue_Context  Base;
[54550e04]80#if defined(RTEMS_POSIX_API)
[631b3c8]81  void                 *exit_value;
[54550e04]82#endif
[631b3c8]83} Thread_Join_context;
[232147dd]84
[54550e04]85#if defined(RTEMS_POSIX_API)
86static Thread_Control *_Thread_Join_flush_filter(
[631b3c8]87  Thread_Control       *the_thread,
88  Thread_queue_Queue   *queue,
89  Thread_queue_Context *queue_context
[54550e04]90)
91{
[631b3c8]92  Thread_Join_context *join_context;
[54550e04]93
[631b3c8]94  join_context = (Thread_Join_context *) queue_context;
[54550e04]95
[631b3c8]96  the_thread->Wait.return_argument = join_context->exit_value;
[54550e04]97
98  return the_thread;
99}
100#endif
101
[232147dd]102static void _Thread_Wake_up_joining_threads( Thread_Control *the_thread )
103{
[631b3c8]104  Thread_Join_context join_context;
[232147dd]105
[54550e04]106#if defined(RTEMS_POSIX_API)
[631b3c8]107  join_context.exit_value = the_thread->Life.exit_value;
[54550e04]108#endif
109
[0e1d11f3]110  _Thread_queue_Context_initialize( &join_context.Base );
[114e408]111  _Thread_queue_Acquire( &the_thread->Join_queue, &join_context.Base );
[232147dd]112  _Thread_queue_Flush_critical(
113    &the_thread->Join_queue.Queue,
114    THREAD_JOIN_TQ_OPERATIONS,
[54550e04]115#if defined(RTEMS_POSIX_API)
116    _Thread_Join_flush_filter,
117#else
[232147dd]118    _Thread_queue_Flush_default_filter,
[54550e04]119#endif
[631b3c8]120    &join_context.Base
[232147dd]121  );
122}
123
[4b3251a]124static void _Thread_Add_to_zombie_chain( Thread_Control *the_thread )
[1b1be254]125{
[232147dd]126  ISR_lock_Context       lock_context;
127  Thread_Zombie_control *zombies;
[1b1be254]128
[4b3251a]129  zombies = &_Thread_Zombies;
130  _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
131  _Chain_Append_unprotected( &zombies->Chain, &the_thread->Object.Node );
132  _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context );
133}
134
135static void _Thread_Make_zombie( Thread_Control *the_thread )
136{
[47d2464]137#if defined(RTEMS_SCORE_THREAD_ENABLE_RESOURCE_COUNT)
[6c7caa1a]138  if ( _Thread_Owns_resources( the_thread ) ) {
[3a659b04]139    _Internal_error( INTERNAL_ERROR_RESOURCE_IN_USE );
[3f5f2ce]140  }
[47d2464]141#endif
[3f5f2ce]142
[a92989a]143  _Objects_Close(
144    _Objects_Get_information_id( the_thread->Object.id ),
145    &the_thread->Object
146  );
147
[1b1be254]148  _Thread_Set_state( the_thread, STATES_ZOMBIE );
149  _Thread_queue_Extract_with_proxy( the_thread );
[03b900d]150  _Thread_Timer_remove( the_thread );
[1b1be254]151
[4b3251a]152  /*
153   * Add the thread to the thread zombie chain before we wake up joining
154   * threads, so that they are able to clean up the thread immediately.  This
155   * matters for SMP configurations.
156   */
157  _Thread_Add_to_zombie_chain( the_thread );
158
159  _Thread_Wake_up_joining_threads( the_thread );
[1b1be254]160}
161
162static void _Thread_Free( Thread_Control *the_thread )
163{
[d7665823]164  Thread_Information *information = (Thread_Information *)
165    _Objects_Get_information_id( the_thread->Object.id );
166
[1b1be254]167  _User_extensions_Thread_delete( the_thread );
[709f38a]168  _User_extensions_Destroy_iterators( the_thread );
[5eaf0e7]169  _ISR_lock_Destroy( &the_thread->Keys.Lock );
[df2177ab]170  _Scheduler_Node_destroy(
[2dd098a]171    _Thread_Scheduler_get_home( the_thread ),
[7f742432]172    _Thread_Scheduler_get_home_node( the_thread )
[df2177ab]173  );
[90de3001]174  _ISR_lock_Destroy( &the_thread->Timer.Lock );
[1b1be254]175
176  /*
177   *  The thread might have been FP.  So deal with that.
178   */
179#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
180#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
181  if ( _Thread_Is_allocated_fp( the_thread ) )
182    _Thread_Deallocate_fp();
183#endif
184
185  _Workspace_Free( the_thread->Start.fp_context );
186#endif
187
[d7665823]188  _Freechain_Put(
189    &information->Free_thread_queue_heads,
190    the_thread->Wait.spare_heads
191  );
192
[1b1be254]193  /*
194   *  Free the rest of the memory associated with this task
195   *  and set the associated pointers to NULL for safety.
196   */
197  _Thread_Stack_Free( the_thread );
198
199  _Workspace_Free( the_thread->Start.tls_area );
200
[57947f1]201#if defined(RTEMS_SMP)
[07a32d19]202  _ISR_lock_Destroy( &the_thread->Scheduler.Lock );
[1fcac5ad]203  _ISR_lock_Destroy( &the_thread->Wait.Lock.Default );
[10e32a26]204  _SMP_lock_Stats_destroy( &the_thread->Potpourri_stats );
[57947f1]205#endif
206
[6e4f929]207  _Thread_queue_Destroy( &the_thread->Join_queue );
[b2e1bded]208  _Context_Destroy( the_thread, &the_thread->Registers );
[d7665823]209  _Objects_Free( &information->Objects, &the_thread->Object );
[1b1be254]210}
211
212static void _Thread_Wait_for_execution_stop( Thread_Control *the_thread )
213{
214#if defined(RTEMS_SMP)
215  /*
216   * It is very unlikely that we see an executing thread here.  It can happen
217   * in case the thread termination sequence is interrupted by a slow interrupt
218   * service on a remote processor.
219   */
[38b59a6]220  while ( _Thread_Is_executing_on_a_processor( the_thread ) ) {
[1b1be254]221    /* Wait */
222  }
223#else
224  (void) the_thread;
225#endif
226}
227
228void _Thread_Kill_zombies( void )
229{
230  ISR_lock_Context lock_context;
231  Thread_Zombie_control *zombies = &_Thread_Zombies;
232  Thread_Control *the_thread;
233
234  _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
235
236  the_thread = (Thread_Control *) _Chain_Get_unprotected( &zombies->Chain );
237  while ( the_thread != NULL ) {
238    _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context );
239
240    _Thread_Wait_for_execution_stop( the_thread );
241    _Thread_Free( the_thread );
242
243    _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
244
245    the_thread = (Thread_Control *) _Chain_Get_unprotected( &zombies->Chain );
246  }
247
248  _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context );
249}
250
[9949d8a7]251static Thread_Life_state _Thread_Change_life_locked(
252  Thread_Control    *the_thread,
253  Thread_Life_state  clear,
254  Thread_Life_state  set,
255  Thread_Life_state  ignore
256)
257{
258  Thread_Life_state previous;
259  Thread_Life_state state;
260
261  previous = the_thread->Life.state;
262  state = previous;
263  state &= ~clear;
264  state |= set;
265  the_thread->Life.state = state;
266
267  state &= ~ignore;
268
269  if (
270    _Thread_Is_life_change_allowed( state )
271      && _Thread_Is_life_changing( state )
272  ) {
273    the_thread->is_preemptible   = the_thread->Start.is_preemptible;
274    the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
275    the_thread->budget_callout   = the_thread->Start.budget_callout;
276
277    _Thread_Add_post_switch_action(
278      the_thread,
279      &the_thread->Life.Action,
280      _Thread_Life_action_handler
281    );
282  }
283
284  return previous;
285}
286
[54550e04]287static Per_CPU_Control *_Thread_Wait_for_join(
288  Thread_Control  *executing,
289  Per_CPU_Control *cpu_self
290)
291{
292#if defined(RTEMS_POSIX_API)
293  ISR_lock_Context lock_context;
294
295  _Thread_State_acquire( executing, &lock_context );
296
297  if (
298    _Thread_Is_joinable( executing )
299      && _Thread_queue_Is_empty( &executing->Join_queue.Queue )
300  ) {
301    _Thread_Set_state_locked( executing, STATES_WAITING_FOR_JOIN_AT_EXIT );
302    _Thread_State_release( executing, &lock_context );
303    _Thread_Dispatch_enable( cpu_self );
304
305    /* Let other threads run */
306
307    cpu_self = _Thread_Dispatch_disable();
308  } else {
309    _Thread_State_release( executing, &lock_context );
310  }
311#endif
312
313  return cpu_self;
314}
315
[5c731a83]316void _Thread_Life_action_handler(
[6e4f929]317  Thread_Control   *executing,
318  Thread_Action    *action,
319  ISR_lock_Context *lock_context
[5c731a83]320)
321{
[29e1ecab]322  Thread_Life_state  previous_life_state;
323  Per_CPU_Control   *cpu_self;
[1b1be254]324
[5c731a83]325  (void) action;
[1b1be254]326
327  previous_life_state = executing->Life.state;
[29e1ecab]328  executing->Life.state = previous_life_state | THREAD_LIFE_PROTECTED;
[1b1be254]329
[6e4f929]330  _Thread_State_release( executing, lock_context );
[5c731a83]331
[1b1be254]332  if ( _Thread_Is_life_terminating( previous_life_state ) ) {
333    _User_extensions_Thread_terminate( executing );
334  } else {
335    _Assert( _Thread_Is_life_restarting( previous_life_state ) );
336
337    _User_extensions_Thread_restart( executing );
338  }
[391ad3e]339
[29e1ecab]340  cpu_self = _Thread_Dispatch_disable();
[5c731a83]341
[1b1be254]342  if ( _Thread_Is_life_terminating( previous_life_state ) ) {
[54550e04]343    cpu_self = _Thread_Wait_for_join( executing, cpu_self );
[1b1be254]344    _Thread_Make_zombie( executing );
[d78d529]345    _Thread_Dispatch_direct( cpu_self );
[e8d9b26]346    RTEMS_UNREACHABLE();
[29e1ecab]347  }
[1b1be254]348
[29e1ecab]349  _Assert( _Thread_Is_life_restarting( previous_life_state ) );
[1b1be254]350
[29e1ecab]351  _Thread_State_acquire( executing, lock_context );
[1b1be254]352
[29e1ecab]353  _Thread_Change_life_locked(
354    executing,
355    THREAD_LIFE_PROTECTED | THREAD_LIFE_RESTARTING,
356    0,
357    0
358  );
[9388390]359
[29e1ecab]360  _Thread_State_release( executing, lock_context );
[9388390]361
[29e1ecab]362  _Assert(
363    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
364  );
365  _Assert(
366    executing->current_state == STATES_READY
367      || executing->current_state == STATES_SUSPENDED
368  );
[9388390]369
[29e1ecab]370  _User_extensions_Destroy_iterators( executing );
371  _Thread_Load_environment( executing );
[9388390]372
373#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
[29e1ecab]374  if ( executing->fp_context != NULL ) {
375    _Context_Restore_fp( &executing->fp_context );
376  }
[9388390]377#endif
378
[29e1ecab]379  _Context_Restart_self( &executing->Registers );
380  RTEMS_UNREACHABLE();
[5c731a83]381}
382
[862a0ee]383static void _Thread_Add_life_change_request( Thread_Control *the_thread )
384{
385  uint32_t pending_requests;
386
387  _Assert( _Thread_State_is_owner( the_thread ) );
388
389  pending_requests = the_thread->Life.pending_life_change_requests;
390  the_thread->Life.pending_life_change_requests = pending_requests + 1;
391
392  if ( pending_requests == 0 ) {
393    _Thread_Set_state_locked( the_thread, STATES_LIFE_IS_CHANGING );
394  }
395}
396
397static void _Thread_Remove_life_change_request( Thread_Control *the_thread )
398{
399  ISR_lock_Context lock_context;
400  uint32_t         pending_requests;
401
402  _Thread_State_acquire( the_thread, &lock_context );
403
404  pending_requests = the_thread->Life.pending_life_change_requests;
405  the_thread->Life.pending_life_change_requests = pending_requests - 1;
406
407  if ( pending_requests == 1 ) {
408    /*
409     * Do not remove states used for thread queues to avoid race conditions on
410     * SMP configurations.  We could interrupt an extract operation on another
411     * processor disregarding the thread wait flags.  Rely on
412     * _Thread_queue_Extract_with_proxy() for removal of these states.
413     */
414    _Thread_Clear_state_locked(
415      the_thread,
416      STATES_LIFE_IS_CHANGING | STATES_SUSPENDED
417        | ( STATES_BLOCKED & ~STATES_LOCALLY_BLOCKED )
418    );
419  }
420
421  _Thread_State_release( the_thread, &lock_context );
422}
423
424static void _Thread_Finalize_life_change(
425  Thread_Control   *the_thread,
426  Priority_Control  priority
427)
428{
429  _Thread_queue_Extract_with_proxy( the_thread );
430  _Thread_Timer_remove( the_thread );
[69dd99b]431  _Thread_Raise_real_priority( the_thread, priority );
[862a0ee]432  _Thread_Remove_life_change_request( the_thread );
433}
434
[232147dd]435void _Thread_Join(
[93306058]436  Thread_Control       *the_thread,
437  States_Control        waiting_for_join,
438  Thread_Control       *executing,
439  Thread_queue_Context *queue_context
[232147dd]440)
441{
442  _Assert( the_thread != executing );
443  _Assert( _Thread_State_is_owner( the_thread ) );
444
[54550e04]445#if defined(RTEMS_POSIX_API)
446  executing->Wait.return_argument = NULL;
447#endif
448
[620b23e]449  _Thread_queue_Context_set_thread_state( queue_context, waiting_for_join );
[a4217c6]450  _Thread_queue_Enqueue(
[232147dd]451    &the_thread->Join_queue.Queue,
452    THREAD_JOIN_TQ_OPERATIONS,
453    executing,
[93306058]454    queue_context
[232147dd]455  );
456}
457
[54550e04]458static void _Thread_Set_exit_value(
459  Thread_Control *the_thread,
460  void           *exit_value
461)
462{
463#if defined(RTEMS_POSIX_API)
464  the_thread->Life.exit_value = exit_value;
465#endif
466}
467
468void _Thread_Cancel(
469  Thread_Control *the_thread,
470  Thread_Control *executing,
471  void           *exit_value
472)
[1b1be254]473{
[ef09017]474  ISR_lock_Context   lock_context;
475  Thread_Life_state  previous;
476  Per_CPU_Control   *cpu_self;
477  Priority_Control   priority;
478
[b7f5e391]479  _Assert( the_thread != executing );
[1b1be254]480
[ef09017]481  _Thread_State_acquire( the_thread, &lock_context );
482
[54550e04]483  _Thread_Set_exit_value( the_thread, exit_value );
[ef09017]484  previous = _Thread_Change_life_locked(
485    the_thread,
486    0,
487    THREAD_LIFE_TERMINATING,
488    0
489  );
490
491  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
[b20b736]492  priority = _Thread_Get_priority( executing );
[ef09017]493
[1b1be254]494  if ( _States_Is_dormant( the_thread->current_state ) ) {
[ef09017]495    _Thread_State_release( the_thread, &lock_context );
[1b1be254]496    _Thread_Make_zombie( the_thread );
[ef09017]497  } else if ( _Thread_Is_life_change_allowed( previous ) ) {
498    _Thread_Add_life_change_request( the_thread );
499    _Thread_State_release( the_thread, &lock_context );
500
501    _Thread_Finalize_life_change( the_thread, priority );
[1b1be254]502  } else {
[ef09017]503    _Thread_Add_life_change_request( the_thread );
504    _Thread_Clear_state_locked( the_thread, STATES_SUSPENDED );
505    _Thread_State_release( the_thread, &lock_context );
506
507    _Thread_Raise_real_priority( the_thread, priority );
508    _Thread_Remove_life_change_request( the_thread );
[1b1be254]509  }
[ef09017]510
511  _Thread_Dispatch_enable( cpu_self );
[5c731a83]512}
[05279b84]513
[125f248]514static void _Thread_Close_enqueue_callout(
515  Thread_queue_Queue   *queue,
516  Thread_Control       *the_thread,
[c3105894]517  Per_CPU_Control      *cpu_self,
[125f248]518  Thread_queue_Context *queue_context
519)
[232147dd]520{
[125f248]521  Thread_Close_context *context;
522
523  context = (Thread_Close_context *) queue_context;
524  _Thread_Cancel( context->cancel, the_thread, NULL );
525}
[232147dd]526
[125f248]527void _Thread_Close(
528  Thread_Control       *the_thread,
529  Thread_Control       *executing,
530  Thread_Close_context *context
531)
532{
533  context->cancel = the_thread;
534  _Thread_queue_Context_set_enqueue_callout(
535    &context->Base,
536    _Thread_Close_enqueue_callout
537  );
538  _Thread_State_acquire_critical(
539    the_thread,
540    &context->Base.Lock_context.Lock_context
541  );
[232147dd]542  _Thread_Join(
543    the_thread,
544    STATES_WAITING_FOR_JOIN,
545    executing,
[125f248]546    &context->Base
[232147dd]547  );
548}
549
[54550e04]550void _Thread_Exit(
551  Thread_Control    *executing,
552  Thread_Life_state  set,
553  void              *exit_value
554)
[b7f5e391]555{
[c99eb50b]556  ISR_lock_Context lock_context;
557
558  _Assert(
559    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
560  );
561  _Assert(
562    executing->current_state == STATES_READY
563      || executing->current_state == STATES_SUSPENDED
564  );
565
566  _Thread_State_acquire( executing, &lock_context );
[54550e04]567  _Thread_Set_exit_value( executing, exit_value );
[c99eb50b]568  _Thread_Change_life_locked(
[b7f5e391]569    executing,
[c99eb50b]570    0,
[54550e04]571    set,
[da826560]572    THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED
[b7f5e391]573  );
[c99eb50b]574  _Thread_State_release( executing, &lock_context );
[b7f5e391]575}
576
[9388390]577bool _Thread_Restart_other(
[ccd5434]578  Thread_Control                 *the_thread,
[9388390]579  const Thread_Entry_information *entry,
580  ISR_lock_Context               *lock_context
[5c731a83]581)
582{
[862a0ee]583  Thread_Life_state  previous;
584  Per_CPU_Control   *cpu_self;
[084c5cc]585
[9388390]586  _Thread_State_acquire_critical( the_thread, lock_context );
[05279b84]587
[9388390]588  if ( _States_Is_dormant( the_thread->current_state ) ) {
589    _Thread_State_release( the_thread, lock_context );
590    return false;
[05df0a8]591  }
[05279b84]592
[9388390]593  the_thread->Start.Entry = *entry;
[862a0ee]594  previous = _Thread_Change_life_locked(
595    the_thread,
596    0,
597    THREAD_LIFE_RESTARTING,
598    0
599  );
[9388390]600
601  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
602
[862a0ee]603  if ( _Thread_Is_life_change_allowed( previous ) ) {
604    _Thread_Add_life_change_request( the_thread );
605    _Thread_State_release( the_thread, lock_context );
606
607    _Thread_Finalize_life_change(
608      the_thread,
609      the_thread->Start.initial_priority
610    );
611  } else {
612    _Thread_Clear_state_locked( the_thread, STATES_SUSPENDED );
613    _Thread_State_release( the_thread, lock_context );
614  }
[9388390]615
616  _Thread_Dispatch_enable( cpu_self );
617  return true;
618}
619
620void _Thread_Restart_self(
621  Thread_Control                 *executing,
622  const Thread_Entry_information *entry,
623  ISR_lock_Context               *lock_context
624)
625{
[300f6a48]626  Per_CPU_Control      *cpu_self;
627  Thread_queue_Context  queue_context;
[9388390]628
629  _Assert(
630    _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
631  );
632  _Assert(
633    executing->current_state == STATES_READY
634      || executing->current_state == STATES_SUSPENDED
635  );
636
[5b6c290]637  _Thread_queue_Context_initialize( &queue_context );
638  _Thread_queue_Context_clear_priority_updates( &queue_context );
[9388390]639  _Thread_State_acquire_critical( executing, lock_context );
640
641  executing->Start.Entry = *entry;
642  _Thread_Change_life_locked(
643    executing,
644    0,
645    THREAD_LIFE_RESTARTING,
[da826560]646    THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED
[9388390]647  );
648
649  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
650  _Thread_State_release( executing, lock_context );
651
[300f6a48]652  _Thread_Wait_acquire_default( executing, lock_context );
653  _Thread_Priority_change(
[9388390]654    executing,
[300f6a48]655    &executing->Real_priority,
[9388390]656    executing->Start.initial_priority,
[300f6a48]657    false,
658    &queue_context
[9388390]659  );
[300f6a48]660  _Thread_Wait_release_default( executing, lock_context );
[9388390]661
[300f6a48]662  _Thread_Priority_update( &queue_context );
[9388390]663  _Thread_Dispatch_enable( cpu_self );
664  RTEMS_UNREACHABLE();
[05df0a8]665}
[1b1be254]666
[da826560]667Thread_Life_state _Thread_Change_life(
[9949d8a7]668  Thread_Life_state clear,
669  Thread_Life_state set,
670  Thread_Life_state ignore
671)
[1b1be254]672{
[6e4f929]673  ISR_lock_Context   lock_context;
674  Thread_Control    *executing;
[9949d8a7]675  Per_CPU_Control   *cpu_self;
676  Thread_Life_state  previous;
[1b1be254]677
[6e4f929]678  executing = _Thread_State_acquire_for_executing( &lock_context );
[1b1be254]679
[9949d8a7]680  previous = _Thread_Change_life_locked( executing, clear, set, ignore );
[1b1be254]681
[9949d8a7]682  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
[6e4f929]683  _Thread_State_release( executing, &lock_context );
[9949d8a7]684  _Thread_Dispatch_enable( cpu_self );
[1b1be254]685
[9949d8a7]686  return previous;
687}
[1b1be254]688
[9949d8a7]689Thread_Life_state _Thread_Set_life_protection( Thread_Life_state state )
690{
691  return _Thread_Change_life(
692    THREAD_LIFE_PROTECTED,
693    state & THREAD_LIFE_PROTECTED,
694    0
695  );
[1b1be254]696}
Note: See TracBrowser for help on using the repository browser.