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

5
Last change on this file since bb2ad039 was bb2ad039, checked in by Sebastian Huber <sebastian.huber@…>, on 05/04/16 at 08:09:45

rtems: Avoid Giant lock for signals

Update #2555.

  • Property mode set to 100644
File size: 3.2 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  Thread_Control     *executing;
36  RTEMS_API_Control  *api;
37  ASR_Information    *asr;
38  bool                preempt_enabled;
39  bool                needs_asr_dispatching;
40  rtems_mode          old_mode;
41
42  if ( !previous_mode_set )
43    return RTEMS_INVALID_ADDRESS;
44
45  executing     = _Thread_Get_executing();
46  api = executing->API_Extensions[ THREAD_API_RTEMS ];
47  asr = &api->Signal;
48
49  old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
50
51  if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
52    old_mode |= RTEMS_NO_TIMESLICE;
53  else
54    old_mode |= RTEMS_TIMESLICE;
55
56  old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
57  old_mode |= _ISR_Get_level();
58
59  *previous_mode_set = old_mode;
60
61  /*
62   *  These are generic thread scheduling characteristics.
63   */
64  preempt_enabled = false;
65  if ( mask & RTEMS_PREEMPT_MASK ) {
66#if defined( RTEMS_SMP )
67    if ( rtems_configuration_is_smp_enabled() &&
68         !_Modes_Is_preempt( mode_set ) ) {
69      return RTEMS_NOT_IMPLEMENTED;
70    }
71#endif
72    bool is_preempt_enabled = _Modes_Is_preempt( mode_set );
73
74    preempt_enabled = !executing->is_preemptible && is_preempt_enabled;
75    executing->is_preemptible = is_preempt_enabled;
76  }
77
78  if ( mask & RTEMS_TIMESLICE_MASK ) {
79    if ( _Modes_Is_timeslice(mode_set) ) {
80      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
81      executing->cpu_time_budget =
82        rtems_configuration_get_ticks_per_timeslice();
83    } else
84      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
85  }
86
87  /*
88   *  Set the new interrupt level
89   */
90  if ( mask & RTEMS_INTERRUPT_MASK )
91    _Modes_Set_interrupt_level( mode_set );
92
93  /*
94   *  This is specific to the RTEMS API
95   */
96  needs_asr_dispatching = false;
97  if ( mask & RTEMS_ASR_MASK ) {
98    bool is_asr_enabled = !_Modes_Is_asr_disabled( mode_set );
99
100    if ( is_asr_enabled != asr->is_enabled ) {
101      asr->is_enabled = is_asr_enabled;
102
103      if ( _ASR_Swap_signals( asr ) != 0 ) {
104        needs_asr_dispatching = true;
105        _Thread_Add_post_switch_action(
106          executing,
107          &api->Signal_action,
108          _Signal_Action_handler
109        );
110      }
111    }
112  }
113
114  if ( preempt_enabled || needs_asr_dispatching ) {
115    Per_CPU_Control  *cpu_self;
116    ISR_lock_Context  lock_context;
117
118    cpu_self = _Thread_Dispatch_disable();
119    _Scheduler_Acquire( executing, &lock_context );
120    _Scheduler_Schedule( executing );
121    _Scheduler_Release( executing, &lock_context );
122    _Thread_Dispatch_enable( cpu_self );
123  }
124
125  return RTEMS_SUCCESSFUL;
126}
Note: See TracBrowser for help on using the repository browser.