summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-11-14 09:11:07 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-11-18 07:30:31 +0100
commitd78d5294cd076b48160e12c2f52a940d783b4dac (patch)
tree15bdd7b4b424b6c4ab49435e71ac6c795bb5a58d /cpukit
parentscore: Remove obsolete defines (diff)
downloadrtems-d78d5294cd076b48160e12c2f52a940d783b4dac.tar.bz2
score: Add and use _Thread_Dispatch_direct()
This function is useful for operations which synchronously block, e.g. self restart, self deletion, yield, sleep. It helps to detect if these operations are called in the wrong context. Since the thread dispatch necessary indicator is not used, this is more robust in some SMP situations. Update #2751.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/posix/src/nanosleep.c2
-rw-r--r--cpukit/posix/src/sched_yield.c2
-rw-r--r--cpukit/rtems/src/taskwakeafter.c2
-rw-r--r--cpukit/sapi/src/interrtext.c3
-rw-r--r--cpukit/score/include/rtems/score/interr.h3
-rw-r--r--cpukit/score/include/rtems/score/threaddispatch.h14
-rw-r--r--cpukit/score/src/threaddispatch.c16
-rw-r--r--cpukit/score/src/threadrestart.c8
8 files changed, 38 insertions, 12 deletions
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
index 38a6b8d6c8..0fec1e48e1 100644
--- a/cpukit/posix/src/nanosleep.c
+++ b/cpukit/posix/src/nanosleep.c
@@ -96,7 +96,7 @@ static inline int nanosleep_yield( struct timespec *rmtp )
executing = _Thread_Get_executing();
cpu_self = _Thread_Dispatch_disable();
_Thread_Yield( executing );
- _Thread_Dispatch_enable( cpu_self );
+ _Thread_Dispatch_direct( cpu_self );
if ( rmtp ) {
rmtp->tv_sec = 0;
rmtp->tv_nsec = 0;
diff --git a/cpukit/posix/src/sched_yield.c b/cpukit/posix/src/sched_yield.c
index 7e056cef27..cbbcb34dd6 100644
--- a/cpukit/posix/src/sched_yield.c
+++ b/cpukit/posix/src/sched_yield.c
@@ -30,6 +30,6 @@ int sched_yield( void )
cpu_self = _Thread_Dispatch_disable();
_Thread_Yield( _Per_CPU_Get_executing( cpu_self ) );
- _Thread_Dispatch_enable( cpu_self );
+ _Thread_Dispatch_direct( cpu_self );
return 0;
}
diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c
index fa5f6f4eed..568b937388 100644
--- a/cpukit/rtems/src/taskwakeafter.c
+++ b/cpukit/rtems/src/taskwakeafter.c
@@ -48,6 +48,6 @@ rtems_status_code rtems_task_wake_after(
ticks
);
}
- _Thread_Dispatch_enable( cpu_self );
+ _Thread_Dispatch_direct( cpu_self );
return RTEMS_SUCCESSFUL;
}
diff --git a/cpukit/sapi/src/interrtext.c b/cpukit/sapi/src/interrtext.c
index 665302283b..edf09dbd93 100644
--- a/cpukit/sapi/src/interrtext.c
+++ b/cpukit/sapi/src/interrtext.c
@@ -56,7 +56,8 @@ static const char *const internal_error_text[] = {
"INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL",
"INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL",
"INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK",
- "INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE"
+ "INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE",
+ "INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL"
};
const char *rtems_internal_error_text( rtems_fatal_code error )
diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h
index dff61012d7..e23db5c58d 100644
--- a/cpukit/score/include/rtems/score/interr.h
+++ b/cpukit/score/include/rtems/score/interr.h
@@ -165,7 +165,8 @@ typedef enum {
INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL,
INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL,
INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK,
- INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE
+ INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_STICKY_FROM_BAD_STATE,
+ INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL
} Internal_errors_Core_list;
typedef CPU_Uint32ptr Internal_errors_t;
diff --git a/cpukit/score/include/rtems/score/threaddispatch.h b/cpukit/score/include/rtems/score/threaddispatch.h
index 801970ab21..f4ca096783 100644
--- a/cpukit/score/include/rtems/score/threaddispatch.h
+++ b/cpukit/score/include/rtems/score/threaddispatch.h
@@ -95,6 +95,20 @@ RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void )
void _Thread_Dispatch( void );
/**
+ * @brief Directly do a thread dispatch.
+ *
+ * Must be called with a thread dispatch disable level of one, otherwise the
+ * INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL will occur. This function
+ * is useful for operations which synchronously block, e.g. self restart, self
+ * deletion, yield, sleep.
+ *
+ * @param[in] cpu_self The current processor.
+ *
+ * @see _Thread_Dispatch().
+ */
+void _Thread_Dispatch_direct( Per_CPU_Control *cpu_self );
+
+/**
* @brief Performs a thread dispatch on the current processor.
*
* On entry the thread dispatch disable level must be equal to one and
diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c
index 36d2910ef2..c96299cb59 100644
--- a/cpukit/score/src/threaddispatch.c
+++ b/cpukit/score/src/threaddispatch.c
@@ -233,3 +233,19 @@ void _Thread_Dispatch( void )
_ISR_Local_enable( level );
}
}
+
+void _Thread_Dispatch_direct( Per_CPU_Control *cpu_self )
+{
+ ISR_Level level;
+
+ if ( cpu_self->thread_dispatch_disable_level != 1 ) {
+ _Terminate(
+ INTERNAL_ERROR_CORE,
+ 0,
+ INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL
+ );
+ }
+
+ _ISR_Local_disable( level );
+ _Thread_Do_dispatch( cpu_self, level );
+}
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 182cdb6128..a5ed837dfd 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -344,14 +344,8 @@ void _Thread_Life_action_handler(
if ( _Thread_Is_life_terminating( previous_life_state ) ) {
cpu_self = _Thread_Wait_for_join( executing, cpu_self );
-
_Thread_Make_zombie( executing );
-
- /* FIXME: Workaround for https://devel.rtems.org/ticket/2751 */
- cpu_self->dispatch_necessary = true;
-
- _Assert( cpu_self->heir != executing );
- _Thread_Dispatch_enable( cpu_self );
+ _Thread_Dispatch_direct( cpu_self );
RTEMS_UNREACHABLE();
}