source: rtems/cpukit/rtems/src/taskmode.c @ bf30999

4.115
Last change on this file since bf30999 was bf30999, checked in by Sebastian Huber <sebastian.huber@…>, on 08/23/13 at 14:15:50

smp: Add and use _Assert_Owner_of_giant()

Add and use _ISR_Disable_without_giant() and
_ISR_Enable_without_giant() if RTEMS_SMP is defined.

On single processor systems the ISR disable/enable was the big hammer
which ensured system-wide mutual exclusion. On SMP configurations this
no longer works since other processors do not care about disabled
interrupts on this processor and continue to execute freely.

On SMP in addition to ISR disable/enable an SMP lock must be used.
Currently we have only the Giant lock so we can check easily that ISR
disable/enable is used only in the right context.

  • Property mode set to 100644
File size: 3.4 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief RTEMS Task Mode
5 *  @ingroup ClassicTasks
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2010.
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.com/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/score/threadimpl.h>
25#include <rtems/config.h>
26
27static void _RTEMS_Tasks_Dispatch_if_necessary(
28  Thread_Control *executing,
29  bool            needs_asr_dispatching
30)
31{
32  if ( _Thread_Dispatch_is_enabled() ) {
33    bool dispatch_necessary = needs_asr_dispatching;
34
35    /*
36     * FIXME: This locking approach is brittle.  It only works since the
37     * current simple SMP scheduler has no support for the non-preempt mode.
38     */
39#if defined( RTEMS_SMP )
40    ISR_Level level;
41
42    _ISR_Disable_without_giant( level );
43#endif
44
45    if ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) {
46      dispatch_necessary = true;
47      _Thread_Dispatch_necessary = dispatch_necessary;
48    }
49
50#if defined( RTEMS_SMP )
51    _ISR_Enable_without_giant( level );
52#endif
53
54    if ( dispatch_necessary ) {
55      _Thread_Dispatch();
56    }
57  }
58}
59
60rtems_status_code rtems_task_mode(
61  rtems_mode  mode_set,
62  rtems_mode  mask,
63  rtems_mode *previous_mode_set
64)
65{
66  Thread_Control     *executing;
67  RTEMS_API_Control  *api;
68  ASR_Information    *asr;
69  bool                needs_asr_dispatching;
70  rtems_mode          old_mode;
71
72  if ( !previous_mode_set )
73    return RTEMS_INVALID_ADDRESS;
74
75  executing     = _Thread_Get_executing();
76  api = executing->API_Extensions[ THREAD_API_RTEMS ];
77  asr = &api->Signal;
78
79  old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
80
81  if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
82    old_mode |= RTEMS_NO_TIMESLICE;
83  else
84    old_mode |= RTEMS_TIMESLICE;
85
86  old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
87  old_mode |= _ISR_Get_level();
88
89  *previous_mode_set = old_mode;
90
91  /*
92   *  These are generic thread scheduling characteristics.
93   */
94  if ( mask & RTEMS_PREEMPT_MASK ) {
95#if defined( RTEMS_SMP )
96    if (
97      rtems_configuration_is_smp_enabled()
98        && !_Modes_Is_preempt( mode_set )
99    ) {
100      return RTEMS_NOT_IMPLEMENTED;
101    }
102#endif
103
104    executing->is_preemptible = _Modes_Is_preempt( mode_set );
105  }
106
107  if ( mask & RTEMS_TIMESLICE_MASK ) {
108    if ( _Modes_Is_timeslice(mode_set) ) {
109      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
110      executing->cpu_time_budget  = _Thread_Ticks_per_timeslice;
111    } else
112      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
113  }
114
115  /*
116   *  Set the new interrupt level
117   */
118  if ( mask & RTEMS_INTERRUPT_MASK )
119    _Modes_Set_interrupt_level( mode_set );
120
121  /*
122   *  This is specific to the RTEMS API
123   */
124  needs_asr_dispatching = false;
125  if ( mask & RTEMS_ASR_MASK ) {
126    bool is_asr_enabled = !_Modes_Is_asr_disabled( mode_set );
127
128    if ( is_asr_enabled != asr->is_enabled ) {
129      asr->is_enabled = is_asr_enabled;
130      _ASR_Swap_signals( asr );
131      if ( _ASR_Are_signals_pending( asr ) ) {
132        needs_asr_dispatching = true;
133      }
134    }
135  }
136
137  _RTEMS_Tasks_Dispatch_if_necessary( executing, needs_asr_dispatching );
138
139  return RTEMS_SUCCESSFUL;
140}
Note: See TracBrowser for help on using the repository browser.