source: rtems/cpukit/score/src/threadrestart.c @ 0f5b2c09

5
Last change on this file since 0f5b2c09 was 54f35888, checked in by Sebastian Huber <sebastian.huber@…>, on 10/25/18 at 08:54:12

posix: Provide threads by default

Update #2514.

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