source: rtems/cpukit/rtems/src/taskmode.c @ 66cb142

Last change on this file since 66cb142 was ed24ed4e, checked in by Sebastian Huber <sebastian.huber@…>, on Feb 8, 2018 at 9:47:16 AM

Use _Thread_Dispatch_direct()

Use _Thread_Dispatch_direct() for operations that block the executing
thread. This ensures that we get a fatal error
(INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL) if we try to block in
an invalid context, e.g. during system start or an interrupt handler.

  • Property mode set to 100644
File size: 3.8 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief RTEMS Task Mode
5 *  @ingroup ClassicTasks
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2014.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/rtems/tasks.h>
22#include <rtems/rtems/asrimpl.h>
23#include <rtems/rtems/modesimpl.h>
24#include <rtems/rtems/signalimpl.h>
25#include <rtems/score/schedulerimpl.h>
26#include <rtems/score/threadimpl.h>
27#include <rtems/config.h>
28
29rtems_status_code rtems_task_mode(
30  rtems_mode  mode_set,
31  rtems_mode  mask,
32  rtems_mode *previous_mode_set
33)
34{
35  ISR_lock_Context    lock_context;
36  Thread_Control     *executing;
37  RTEMS_API_Control  *api;
38  ASR_Information    *asr;
39  bool                preempt_enabled;
40  bool                needs_asr_dispatching;
41  rtems_mode          old_mode;
42
43  if ( !previous_mode_set )
44    return RTEMS_INVALID_ADDRESS;
45
46#if defined( RTEMS_SMP )
47  /*
48   * When in SMP, you cannot disable preemption for a thread or
49   * alter its interrupt level. It must be fully preemptible with
50   * all interrupts enabled.
51   */
52  if ( rtems_configuration_is_smp_enabled() ) {
53    if ( mask & RTEMS_PREEMPT_MASK ) {
54      if ( !_Modes_Is_preempt( mode_set ) ) {
55        return RTEMS_NOT_IMPLEMENTED;
56      }
57    }
58
59    if ( mask & RTEMS_INTERRUPT_MASK ) {
60      return RTEMS_NOT_IMPLEMENTED;
61    }
62  }
63#endif
64
65  /*
66   * Complete all error checking before doing any operations which
67   * impact the executing thread. There should be no errors returned
68   * past this point.
69   */
70 
71  executing     = _Thread_Get_executing();
72  api = executing->API_Extensions[ THREAD_API_RTEMS ];
73  asr = &api->Signal;
74
75  old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
76
77  if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
78    old_mode |= RTEMS_NO_TIMESLICE;
79  else
80    old_mode |= RTEMS_TIMESLICE;
81
82  old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
83  old_mode |= _ISR_Get_level();
84
85  *previous_mode_set = old_mode;
86
87  /*
88   *  These are generic thread scheduling characteristics.
89   */
90  preempt_enabled = false;
91  if ( mask & RTEMS_PREEMPT_MASK ) {
92    bool is_preempt_enabled = _Modes_Is_preempt( mode_set );
93
94    preempt_enabled = !executing->is_preemptible && is_preempt_enabled;
95    executing->is_preemptible = is_preempt_enabled;
96  }
97
98  if ( mask & RTEMS_TIMESLICE_MASK ) {
99    if ( _Modes_Is_timeslice(mode_set) ) {
100      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
101      executing->cpu_time_budget =
102        rtems_configuration_get_ticks_per_timeslice();
103    } else
104      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
105  }
106
107  /*
108   *  Set the new interrupt level
109   */
110  if ( mask & RTEMS_INTERRUPT_MASK ) {
111    _Modes_Set_interrupt_level( mode_set );
112  }
113
114  /*
115   *  This is specific to the RTEMS API
116   */
117  needs_asr_dispatching = false;
118  if ( mask & RTEMS_ASR_MASK ) {
119    bool is_asr_enabled = !_Modes_Is_asr_disabled( mode_set );
120
121    _Thread_State_acquire( executing, &lock_context );
122
123    if ( is_asr_enabled != asr->is_enabled ) {
124      asr->is_enabled = is_asr_enabled;
125
126      if ( _ASR_Swap_signals( asr ) != 0 ) {
127        needs_asr_dispatching = true;
128        _Thread_Add_post_switch_action(
129          executing,
130          &api->Signal_action,
131          _Signal_Action_handler
132        );
133      }
134    }
135
136    _Thread_State_release( executing, &lock_context );
137  }
138
139  if ( preempt_enabled || needs_asr_dispatching ) {
140    Per_CPU_Control  *cpu_self;
141
142    cpu_self = _Thread_Dispatch_disable();
143    _Thread_State_acquire( executing, &lock_context );
144    _Scheduler_Schedule( executing );
145    _Thread_State_release( executing, &lock_context );
146    _Thread_Dispatch_direct( cpu_self );
147  }
148
149  return RTEMS_SUCCESSFUL;
150}
Note: See TracBrowser for help on using the repository browser.