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

5
Last change on this file since 66cb142 was ed24ed4e, checked in by Sebastian Huber <sebastian.huber@…>, on 02/08/18 at 09:47:16

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
RevLine 
[a6500136]1/**
2 *  @file
[c4d69e2]3 *
[a6500136]4 *  @brief RTEMS Task Mode
5 *  @ingroup ClassicTasks
6 */
7
8/*
[6b998fee]9 *  COPYRIGHT (c) 1989-2014.
[c4d69e2]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
[c499856]14 *  http://www.rtems.org/license/LICENSE.
[c4d69e2]15 */
16
[1095ec1]17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
[5618c37a]21#include <rtems/rtems/tasks.h>
[f4d9ab3e]22#include <rtems/rtems/asrimpl.h>
[b79953cf]23#include <rtems/rtems/modesimpl.h>
[df55d07f]24#include <rtems/rtems/signalimpl.h>
[b8a5abf]25#include <rtems/score/schedulerimpl.h>
[5618c37a]26#include <rtems/score/threadimpl.h>
27#include <rtems/config.h>
[c4d69e2]28
29rtems_status_code rtems_task_mode(
30  rtems_mode  mode_set,
31  rtems_mode  mask,
32  rtems_mode *previous_mode_set
33)
34{
[6e4f929]35  ISR_lock_Context    lock_context;
[c4d69e2]36  Thread_Control     *executing;
37  RTEMS_API_Control  *api;
38  ASR_Information    *asr;
[b8a5abf]39  bool                preempt_enabled;
[7a34ca37]40  bool                needs_asr_dispatching;
[c4d69e2]41  rtems_mode          old_mode;
42
[e980b219]43  if ( !previous_mode_set )
44    return RTEMS_INVALID_ADDRESS;
45
[d2711c37]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 
[3b8d2fa4]71  executing     = _Thread_Get_executing();
[c4d69e2]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   */
[b8a5abf]90  preempt_enabled = false;
[05e82bd7]91  if ( mask & RTEMS_PREEMPT_MASK ) {
[b8a5abf]92    bool is_preempt_enabled = _Modes_Is_preempt( mode_set );
[05e82bd7]93
[b8a5abf]94    preempt_enabled = !executing->is_preemptible && is_preempt_enabled;
95    executing->is_preemptible = is_preempt_enabled;
[05e82bd7]96  }
[c4d69e2]97
98  if ( mask & RTEMS_TIMESLICE_MASK ) {
[c0f4682]99    if ( _Modes_Is_timeslice(mode_set) ) {
[c4d69e2]100      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
[e785fbaa]101      executing->cpu_time_budget =
102        rtems_configuration_get_ticks_per_timeslice();
[c0f4682]103    } else
[c4d69e2]104      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
105  }
106
107  /*
108   *  Set the new interrupt level
109   */
[d2711c37]110  if ( mask & RTEMS_INTERRUPT_MASK ) {
[c4d69e2]111    _Modes_Set_interrupt_level( mode_set );
[d2711c37]112  }
[c4d69e2]113
114  /*
115   *  This is specific to the RTEMS API
116   */
[eaef4657]117  needs_asr_dispatching = false;
[c4d69e2]118  if ( mask & RTEMS_ASR_MASK ) {
[7a34ca37]119    bool is_asr_enabled = !_Modes_Is_asr_disabled( mode_set );
120
[105b4e6]121    _Thread_State_acquire( executing, &lock_context );
122
[c4d69e2]123    if ( is_asr_enabled != asr->is_enabled ) {
124      asr->is_enabled = is_asr_enabled;
[bb2ad039]125
126      if ( _ASR_Swap_signals( asr ) != 0 ) {
[484a769]127        needs_asr_dispatching = true;
[6fd1bdb7]128        _Thread_Add_post_switch_action(
129          executing,
[df55d07f]130          &api->Signal_action,
131          _Signal_Action_handler
[6fd1bdb7]132        );
[c4d69e2]133      }
134    }
[105b4e6]135
136    _Thread_State_release( executing, &lock_context );
[c4d69e2]137  }
138
[b8a5abf]139  if ( preempt_enabled || needs_asr_dispatching ) {
[f5bb2991]140    Per_CPU_Control  *cpu_self;
[b8a5abf]141
[f5bb2991]142    cpu_self = _Thread_Dispatch_disable();
[bd12dda]143    _Thread_State_acquire( executing, &lock_context );
[b8a5abf]144    _Scheduler_Schedule( executing );
[bd12dda]145    _Thread_State_release( executing, &lock_context );
[ed24ed4e]146    _Thread_Dispatch_direct( cpu_self );
[b8a5abf]147  }
[c4d69e2]148
149  return RTEMS_SUCCESSFUL;
150}
Note: See TracBrowser for help on using the repository browser.