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/score/threadimpl.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/timespec.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
*/
@@ -38,7 +42,8 @@ int nanosleep(
* It is critical to obtain the executing thread after thread dispatching is
* disabled on SMP configurations.
*/
Thread_Control *executing;
Thread_Control *executing;
Per_CPU_Control *cpu_self;
Watchdog_Interval ticks;
Watchdog_Interval elapsed;
@@ -58,16 +63,17 @@ int nanosleep(
*/
ticks = _Timespec_To_ticks( rqtp );
executing = _Thread_Get_executing();
/*
* A nanosleep for zero time is implemented as a yield.
* This behavior is also beyond the POSIX specification but is
* consistent with the RTEMS API and yields desirable behavior.
*/
if ( !ticks ) {
_Thread_Disable_dispatch();
executing = _Thread_Executing;
cpu_self = _Thread_Dispatch_disable();
_Thread_Yield( executing );
_Thread_Enable_dispatch();
_Thread_Dispatch_enable( cpu_self );
if ( rmtp ) {
rmtp->tv_sec = 0;
rmtp->tv_nsec = 0;
@@ -78,20 +84,13 @@ int nanosleep(
/*
* Block for the desired amount of time
*/
_Thread_Disable_dispatch();
executing = _Thread_Executing;
_Thread_Set_state(
executing,
STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
);
_Watchdog_Initialize(
&executing->Timer,
_Thread_Delay_ended,
0,
executing
);
_Watchdog_Insert_ticks( &executing->Timer, ticks );
_Thread_Enable_dispatch();
_Thread_queue_Enqueue(
&_Nanosleep_Pseudo_queue,
executing,
STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL,
ticks,
0
);
/*
* 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 ) ) {
the_thread->Wait.return_code = EINTR;
/*
* 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 );
}
_Thread_queue_Extract_with_proxy( the_thread );
}
}
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
* 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;
if ( ticks == 0 ) {
_Thread_Yield( executing );
} else {
_Thread_Set_state( executing, STATES_DELAYING );
_Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED );
_Watchdog_Initialize(
&executing->Timer,
_Thread_Delay_ended,
_Thread_Timeout,
0,
executing
);
_Watchdog_Insert_ticks( &executing->Timer, ticks );
}
_Thread_Enable_dispatch();
_Thread_Dispatch_enable( cpu_self );
return RTEMS_SUCCESSFUL;
}

View File

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

View File

@@ -280,7 +280,7 @@ libscore_a_SOURCES += src/rbtree.c \
## THREAD_C_FILES
libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
src/threadclearstate.c src/threadcreateidle.c \
src/threaddelayended.c src/threaddispatch.c \
src/threaddispatch.c \
src/threadenabledispatch.c src/threaddisabledispatch.c \
src/threadget.c src/threadhandler.c src/threadinitialize.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
);
}