score: Replace _Thread_Delay_ended()

Use _Thread_Timeout() instead.  Use pseudo thread queue for nanosleep()
to deal with signals.

Close #2130.
This commit is contained in:
Sebastian Huber
2015-05-11 14:56:49 +02:00
parent d8752860e5
commit aa05cfbb3d
6 changed files with 30 additions and 74 deletions

View File

@@ -23,9 +23,13 @@
#include <rtems/seterr.h> #include <rtems/seterr.h>
#include <rtems/score/threadimpl.h> #include <rtems/score/threadimpl.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/timespec.h> #include <rtems/score/timespec.h>
#include <rtems/score/watchdogimpl.h> #include <rtems/score/watchdogimpl.h>
static Thread_queue_Control _Nanosleep_Pseudo_queue =
THREAD_QUEUE_FIFO_INITIALIZER( _Nanosleep_Pseudo_queue, "Nanosleep" );
/* /*
* 14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269 * 14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
*/ */
@@ -38,7 +42,8 @@ int nanosleep(
* It is critical to obtain the executing thread after thread dispatching is * It is critical to obtain the executing thread after thread dispatching is
* disabled on SMP configurations. * disabled on SMP configurations.
*/ */
Thread_Control *executing; Thread_Control *executing;
Per_CPU_Control *cpu_self;
Watchdog_Interval ticks; Watchdog_Interval ticks;
Watchdog_Interval elapsed; Watchdog_Interval elapsed;
@@ -58,16 +63,17 @@ int nanosleep(
*/ */
ticks = _Timespec_To_ticks( rqtp ); ticks = _Timespec_To_ticks( rqtp );
executing = _Thread_Get_executing();
/* /*
* A nanosleep for zero time is implemented as a yield. * A nanosleep for zero time is implemented as a yield.
* This behavior is also beyond the POSIX specification but is * This behavior is also beyond the POSIX specification but is
* consistent with the RTEMS API and yields desirable behavior. * consistent with the RTEMS API and yields desirable behavior.
*/ */
if ( !ticks ) { if ( !ticks ) {
_Thread_Disable_dispatch(); cpu_self = _Thread_Dispatch_disable();
executing = _Thread_Executing;
_Thread_Yield( executing ); _Thread_Yield( executing );
_Thread_Enable_dispatch(); _Thread_Dispatch_enable( cpu_self );
if ( rmtp ) { if ( rmtp ) {
rmtp->tv_sec = 0; rmtp->tv_sec = 0;
rmtp->tv_nsec = 0; rmtp->tv_nsec = 0;
@@ -78,20 +84,13 @@ int nanosleep(
/* /*
* Block for the desired amount of time * Block for the desired amount of time
*/ */
_Thread_Disable_dispatch(); _Thread_queue_Enqueue(
executing = _Thread_Executing; &_Nanosleep_Pseudo_queue,
_Thread_Set_state( executing,
executing, STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL,
STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL ticks,
); 0
_Watchdog_Initialize( );
&executing->Timer,
_Thread_Delay_ended,
0,
executing
);
_Watchdog_Insert_ticks( &executing->Timer, ticks );
_Thread_Enable_dispatch();
/* /*
* Calculate the time that passed while we were sleeping and how * Calculate the time that passed while we were sleeping and how

View File

@@ -110,16 +110,7 @@ bool _POSIX_signals_Unblock_thread(
if ( _States_Is_interruptible_by_signal( the_thread->current_state ) ) { if ( _States_Is_interruptible_by_signal( the_thread->current_state ) ) {
the_thread->Wait.return_code = EINTR; the_thread->Wait.return_code = EINTR;
/* _Thread_queue_Extract_with_proxy( the_thread );
* In pthread_cond_wait, a thread will be blocking on a thread
* queue, but is also interruptible by a POSIX signal.
*/
if ( _States_Is_delaying(the_thread->current_state) ) {
_Watchdog_Remove_ticks( &the_thread->Timer );
_Thread_Unblock( the_thread );
} else {
_Thread_queue_Extract_with_proxy( the_thread );
}
} }
} }
return _POSIX_signals_Unblock_thread_done( the_thread, api, false ); return _POSIX_signals_Unblock_thread_done( the_thread, api, false );

View File

@@ -30,23 +30,25 @@ rtems_status_code rtems_task_wake_after(
* It is critical to obtain the executing thread after thread dispatching is * It is critical to obtain the executing thread after thread dispatching is
* disabled on SMP configurations. * disabled on SMP configurations.
*/ */
Thread_Control *executing; Thread_Control *executing;
Per_CPU_Control *cpu_self;
_Thread_Disable_dispatch(); cpu_self = _Thread_Dispatch_disable();
executing = _Thread_Executing; executing = _Thread_Executing;
if ( ticks == 0 ) { if ( ticks == 0 ) {
_Thread_Yield( executing ); _Thread_Yield( executing );
} else { } else {
_Thread_Set_state( executing, STATES_DELAYING ); _Thread_Set_state( executing, STATES_DELAYING );
_Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED );
_Watchdog_Initialize( _Watchdog_Initialize(
&executing->Timer, &executing->Timer,
_Thread_Delay_ended, _Thread_Timeout,
0, 0,
executing executing
); );
_Watchdog_Insert_ticks( &executing->Timer, ticks ); _Watchdog_Insert_ticks( &executing->Timer, ticks );
} }
_Thread_Enable_dispatch(); _Thread_Dispatch_enable( cpu_self );
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }

View File

@@ -30,6 +30,7 @@ rtems_status_code rtems_task_wake_when(
{ {
Watchdog_Interval seconds; Watchdog_Interval seconds;
Thread_Control *executing; Thread_Control *executing;
Per_CPU_Control *cpu_self;
if ( !_TOD_Is_set() ) if ( !_TOD_Is_set() )
return RTEMS_NOT_DEFINED; return RTEMS_NOT_DEFINED;
@@ -47,12 +48,13 @@ rtems_status_code rtems_task_wake_when(
if ( seconds <= _TOD_Seconds_since_epoch() ) if ( seconds <= _TOD_Seconds_since_epoch() )
return RTEMS_INVALID_CLOCK; return RTEMS_INVALID_CLOCK;
_Thread_Disable_dispatch(); cpu_self = _Thread_Dispatch_disable();
executing = _Thread_Executing; executing = _Thread_Executing;
_Thread_Set_state( executing, STATES_WAITING_FOR_TIME ); _Thread_Set_state( executing, STATES_WAITING_FOR_TIME );
_Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED );
_Watchdog_Initialize( _Watchdog_Initialize(
&executing->Timer, &executing->Timer,
_Thread_Delay_ended, _Thread_Timeout,
0, 0,
executing executing
); );
@@ -60,6 +62,6 @@ rtems_status_code rtems_task_wake_when(
&executing->Timer, &executing->Timer,
seconds - _TOD_Seconds_since_epoch() seconds - _TOD_Seconds_since_epoch()
); );
_Thread_Enable_dispatch(); _Thread_Dispatch_enable( cpu_self );
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }

View File

@@ -280,7 +280,7 @@ libscore_a_SOURCES += src/rbtree.c \
## THREAD_C_FILES ## THREAD_C_FILES
libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \ libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
src/threadclearstate.c src/threadcreateidle.c \ src/threadclearstate.c src/threadcreateidle.c \
src/threaddelayended.c src/threaddispatch.c \ src/threaddispatch.c \
src/threadenabledispatch.c src/threaddisabledispatch.c \ src/threadenabledispatch.c src/threaddisabledispatch.c \
src/threadget.c src/threadhandler.c src/threadinitialize.c \ src/threadget.c src/threadhandler.c src/threadinitialize.c \
src/threadloadenv.c \ src/threadloadenv.c \

View File

@@ -1,38 +0,0 @@
/**
* @file
*
* @brief End the Delay of a Thread
* @ingroup ScoreThread
*/
/*
* COPYRIGHT (c) 1989-2007.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems/score/threadimpl.h>
void _Thread_Delay_ended(
Objects_Id id,
void *arg
)
{
Thread_Control *the_thread = arg;
(void) id;
_Thread_Clear_state(
the_thread,
STATES_DELAYING
| STATES_WAITING_FOR_TIME
| STATES_INTERRUPTIBLE_BY_SIGNAL
);
}