summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-02-18 08:36:26 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-03-04 13:36:10 +0100
commit03b900d3ed120ea919ea3eded7edbece3488cff3 (patch)
tree182781fc14fe15fd67caeb80e46f1c58495839c2 /cpukit/posix/src
parentscore: Distribute clock tick to all online CPUs (diff)
downloadrtems-03b900d3ed120ea919ea3eded7edbece3488cff3.tar.bz2
score: Replace watchdog handler implementation
Use a red-black tree instead of delta chains. Close #2344. Update #2554. Update #2555. Close #2606.
Diffstat (limited to 'cpukit/posix/src')
-rw-r--r--cpukit/posix/src/alarm.c96
-rw-r--r--cpukit/posix/src/nanosleep.c5
-rw-r--r--cpukit/posix/src/pthread.c31
-rw-r--r--cpukit/posix/src/pthreadcreate.c6
-rw-r--r--cpukit/posix/src/pthreadsetschedparam.c14
-rw-r--r--cpukit/posix/src/timercreate.c3
-rw-r--r--cpukit/posix/src/timerdelete.c12
-rw-r--r--cpukit/posix/src/timergetoverrun.c7
-rw-r--r--cpukit/posix/src/timergettime.c29
-rw-r--r--cpukit/posix/src/timerinserthelper.c66
-rw-r--r--cpukit/posix/src/timersettime.c152
-rw-r--r--cpukit/posix/src/timertsr.c89
-rw-r--r--cpukit/posix/src/ualarm.c155
13 files changed, 317 insertions, 348 deletions
diff --git a/cpukit/posix/src/alarm.c b/cpukit/posix/src/alarm.c
index e85622fdf1..10443e4760 100644
--- a/cpukit/posix/src/alarm.c
+++ b/cpukit/posix/src/alarm.c
@@ -22,29 +22,18 @@
#endif
#include <unistd.h>
+#include <signal.h>
-#include <rtems/posix/pthreadimpl.h>
-#include <rtems/posix/psignalimpl.h>
-#include <rtems/score/threaddispatch.h>
#include <rtems/score/todimpl.h>
#include <rtems/score/watchdogimpl.h>
-/*
- * _POSIX_signals_Alarm_TSR
- */
-static void _POSIX_signals_Alarm_TSR(
- Objects_Id id RTEMS_UNUSED,
- void *argument RTEMS_UNUSED
-)
+ISR_LOCK_DEFINE( static, _POSIX_signals_Alarm_lock, "POSIX Alarm" )
+
+static void _POSIX_signals_Alarm_TSR( Watchdog_Control *the_watchdog )
{
- #if defined(RTEMS_DEBUG)
- int status;
- #define KILL_STATUS status =
- #else
- #define KILL_STATUS (void)
- #endif
+ int status;
- KILL_STATUS kill( getpid(), SIGALRM );
+ status = kill( getpid(), SIGALRM );
#if defined(RTEMS_DEBUG)
/*
@@ -52,43 +41,62 @@ static void _POSIX_signals_Alarm_TSR(
* cautious.
*/
_Assert(status == 0);
+ #else
+ (void) status;
#endif
}
-static Watchdog_Control _POSIX_signals_Alarm_timer = WATCHDOG_INITIALIZER(
- _POSIX_signals_Alarm_TSR,
- 0,
- NULL
+static Watchdog_Control _POSIX_signals_Alarm_watchdog = WATCHDOG_INITIALIZER(
+ _POSIX_signals_Alarm_TSR
);
unsigned int alarm(
unsigned int seconds
)
{
- unsigned int remaining = 0;
- Watchdog_Control *the_timer;
- Watchdog_States state;
-
- the_timer = &_POSIX_signals_Alarm_timer;
-
- _Thread_Disable_dispatch();
-
- state = _Watchdog_Remove_seconds( the_timer );
- if ( state == WATCHDOG_ACTIVE ) {
- /*
- * The stop_time and start_time fields are snapshots of ticks since
- * boot. Since alarm() is dealing in seconds, we must account for
- * this.
- */
-
- remaining = the_timer->initial -
- ((the_timer->stop_time - the_timer->start_time) / TOD_TICKS_PER_SECOND);
+ unsigned int remaining;
+ Watchdog_Control *the_watchdog;
+ ISR_lock_Context lock_context;
+ ISR_lock_Context lock_context2;
+ Per_CPU_Control *cpu;
+ uint64_t now;
+ uint32_t ticks_per_second;
+ uint32_t ticks;
+
+ the_watchdog = &_POSIX_signals_Alarm_watchdog;
+ ticks_per_second = TOD_TICKS_PER_SECOND;
+ ticks = seconds * ticks_per_second;
+
+ _ISR_lock_ISR_disable_and_acquire(
+ &_POSIX_signals_Alarm_lock,
+ &lock_context
+ );
+
+ cpu = _Watchdog_Get_CPU( the_watchdog );
+ _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
+ now = cpu->Watchdog.ticks;
+
+ remaining = (unsigned long) _Watchdog_Cancel(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now
+ );
+
+ if ( ticks != 0 ) {
+ cpu = _Per_CPU_Get();
+ _Watchdog_Set_CPU( the_watchdog, cpu );
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now + ticks
+ );
}
- if ( seconds )
- _Watchdog_Insert_seconds( the_timer, seconds );
-
- _Thread_Enable_dispatch();
+ _Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
+ _ISR_lock_Release_and_ISR_enable(
+ &_POSIX_signals_Alarm_lock,
+ &lock_context
+ );
- return remaining;
+ return ( remaining + ticks_per_second - 1 ) / ticks_per_second;
}
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
index 46697ae8fc..21bdb986b6 100644
--- a/cpukit/posix/src/nanosleep.c
+++ b/cpukit/posix/src/nanosleep.c
@@ -46,6 +46,7 @@ int nanosleep(
Per_CPU_Control *cpu_self;
Watchdog_Interval ticks;
+ Watchdog_Interval start;
Watchdog_Interval elapsed;
@@ -81,6 +82,8 @@ int nanosleep(
return 0;
}
+ start = _Watchdog_Ticks_since_boot;
+
/*
* Block for the desired amount of time
*/
@@ -96,7 +99,7 @@ int nanosleep(
* Calculate the time that passed while we were sleeping and how
* much remains from what we requested.
*/
- elapsed = executing->Timer.stop_time - executing->Timer.start_time;
+ elapsed = _Watchdog_Ticks_since_boot - start;
if ( elapsed >= ticks )
ticks = 0;
else
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c
index ac5fbe44bf..001ae7947a 100644
--- a/cpukit/posix/src/pthread.c
+++ b/cpukit/posix/src/pthread.c
@@ -104,18 +104,15 @@ static bool _POSIX_Threads_Sporadic_budget_TSR_filter(
/*
* _POSIX_Threads_Sporadic_budget_TSR
*/
-void _POSIX_Threads_Sporadic_budget_TSR(
- Objects_Id id RTEMS_UNUSED,
- void *argument
-)
+void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog )
{
uint32_t ticks;
- Thread_Control *the_thread;
POSIX_API_Control *api;
+ Thread_Control *the_thread;
+ ISR_Level level;
- the_thread = argument;
-
- api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+ api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic_timer );
+ the_thread = api->thread;
/* ticks is guaranteed to be at least one */
ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );
@@ -133,7 +130,15 @@ void _POSIX_Threads_Sporadic_budget_TSR(
/* ticks is guaranteed to be at least one */
ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );
- _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
+ _Thread_Disable_dispatch();
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_insert_relative(
+ &api->Sporadic_timer,
+ _Per_CPU_Get(),
+ ticks
+ );
+ _ISR_Enable( level );
+ _Thread_Unnest_dispatch();
}
static bool _POSIX_Threads_Sporadic_budget_callout_filter(
@@ -198,6 +203,7 @@ static bool _POSIX_Threads_Create_extension(
api = created->API_Extensions[ THREAD_API_POSIX ];
/* XXX check all fields are touched */
+ api->thread = created;
_POSIX_Threads_Initialize_attributes( &api->Attributes );
api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
@@ -229,11 +235,10 @@ static bool _POSIX_Threads_Create_extension(
_Thread_queue_Initialize( &api->Join_List, THREAD_QUEUE_DISCIPLINE_FIFO );
+ _Watchdog_Preinitialize( &api->Sporadic_timer, _Per_CPU_Get_by_index( 0 ) );
_Watchdog_Initialize(
&api->Sporadic_timer,
- _POSIX_Threads_Sporadic_budget_TSR,
- created->Object.id,
- created
+ _POSIX_Threads_Sporadic_budget_TSR
);
return true;
@@ -260,7 +265,7 @@ static void _POSIX_Threads_Terminate_extension(
*(void **)the_thread->Wait.return_argument = value_ptr;
if ( api->schedpolicy == SCHED_SPORADIC )
- _Watchdog_Remove_ticks( &api->Sporadic_timer );
+ _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
_Thread_queue_Destroy( &api->Join_List );
diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c
index 3185ab6553..fc07b1f7e1 100644
--- a/cpukit/posix/src/pthreadcreate.c
+++ b/cpukit/posix/src/pthreadcreate.c
@@ -74,6 +74,7 @@ int pthread_create(
struct sched_param schedparam;
Objects_Name name;
int rc;
+ ISR_Level level;
if ( !start_routine )
return EFAULT;
@@ -246,10 +247,13 @@ int pthread_create(
#endif
if ( schedpolicy == SCHED_SPORADIC ) {
- _Watchdog_Insert_ticks(
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_insert_relative(
&api->Sporadic_timer,
+ _Per_CPU_Get(),
_Timespec_To_ticks( &api->schedparam.sched_ss_repl_period )
);
+ _ISR_Enable( level );
}
_Thread_Enable_dispatch();
diff --git a/cpukit/posix/src/pthreadsetschedparam.c b/cpukit/posix/src/pthreadsetschedparam.c
index c3be366818..c9560f59ac 100644
--- a/cpukit/posix/src/pthreadsetschedparam.c
+++ b/cpukit/posix/src/pthreadsetschedparam.c
@@ -44,6 +44,7 @@ int pthread_setschedparam(
Objects_Locations location;
int rc;
Priority_Control unused;
+ ISR_Level level;
/*
* Check all the parameters
@@ -69,8 +70,11 @@ int pthread_setschedparam(
case OBJECTS_LOCAL:
api = the_thread->API_Extensions[ THREAD_API_POSIX ];
- if ( api->schedpolicy == SCHED_SPORADIC )
- _Watchdog_Remove_ticks( &api->Sporadic_timer );
+ if ( api->schedpolicy == SCHED_SPORADIC ) {
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
+ _ISR_Enable( level );
+ }
api->schedpolicy = policy;
api->schedparam = *param;
@@ -97,8 +101,10 @@ int pthread_setschedparam(
case SCHED_SPORADIC:
api->ss_high_priority = api->schedparam.sched_priority;
- _Watchdog_Remove_ticks( &api->Sporadic_timer );
- _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
+ _ISR_Enable( level );
+ _POSIX_Threads_Sporadic_budget_TSR( &api->Sporadic_timer );
break;
}
diff --git a/cpukit/posix/src/timercreate.c b/cpukit/posix/src/timercreate.c
index 697f1ceee1..5123071d99 100644
--- a/cpukit/posix/src/timercreate.c
+++ b/cpukit/posix/src/timercreate.c
@@ -91,7 +91,8 @@ int timer_create(
ptimer->timer_data.it_interval.tv_sec = 0;
ptimer->timer_data.it_interval.tv_nsec = 0;
- _Watchdog_Preinitialize( &ptimer->Timer );
+ _Watchdog_Preinitialize( &ptimer->Timer, _Per_CPU_Get_snapshot() );
+ _Watchdog_Initialize( &ptimer->Timer, _POSIX_Timer_TSR );
_Objects_Open_u32(&_POSIX_Timer_Information, &ptimer->Object, 0);
*timerid = ptimer->Object.id;
diff --git a/cpukit/posix/src/timerdelete.c b/cpukit/posix/src/timerdelete.c
index 8438b0d5b0..c39de8e168 100644
--- a/cpukit/posix/src/timerdelete.c
+++ b/cpukit/posix/src/timerdelete.c
@@ -45,16 +45,22 @@ int timer_delete(
*/
POSIX_Timer_Control *ptimer;
Objects_Locations location;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
_Objects_Allocator_lock();
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
_Objects_Close( &_POSIX_Timer_Information, &ptimer->Object );
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
ptimer->state = POSIX_TIMER_STATE_FREE;
- _Watchdog_Remove_ticks( &ptimer->Timer );
- _Objects_Put( &ptimer->Object );
+ _Watchdog_Remove(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ &ptimer->Timer
+ );
+ _POSIX_Timer_Release( cpu, &lock_context );
_POSIX_Timer_Free( ptimer );
_Objects_Allocator_unlock();
diff --git a/cpukit/posix/src/timergetoverrun.c b/cpukit/posix/src/timergetoverrun.c
index dd7669ee89..0a28fa7b5f 100644
--- a/cpukit/posix/src/timergetoverrun.c
+++ b/cpukit/posix/src/timergetoverrun.c
@@ -33,14 +33,17 @@ int timer_getoverrun(
int overrun;
POSIX_Timer_Control *ptimer;
Objects_Locations location;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
overrun = ptimer->overrun;
ptimer->overrun = 0;
- _Objects_Put( &ptimer->Object );
+ _POSIX_Timer_Release( cpu, &lock_context );
return overrun;
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/posix/src/timergettime.c b/cpukit/posix/src/timergettime.c
index f065cc927c..7f0015bf5e 100644
--- a/cpukit/posix/src/timergettime.c
+++ b/cpukit/posix/src/timergettime.c
@@ -42,31 +42,32 @@ int timer_gettime(
{
POSIX_Timer_Control *ptimer;
Objects_Locations location;
- struct timespec current_time;
- Watchdog_Interval left;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
+ uint64_t now;
+ uint32_t remaining;
if ( !value )
rtems_set_errno_and_return_minus_one( EINVAL );
- /* Reads the current time */
- _TOD_Get_as_timespec( &current_time );
-
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
- /* Calculates the time left before the timer finishes */
-
- left =
- (ptimer->Timer.start_time + ptimer->Timer.initial) - /* expire */
- _Watchdog_Ticks_since_boot; /* now */
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
+ now = cpu->Watchdog.ticks;
- _Timespec_From_ticks( left, &value->it_value );
+ if ( now < ptimer->Timer.expire ) {
+ remaining = (uint32_t) ( ptimer->Timer.expire - now );
+ } else {
+ remaining = 0;
+ }
- value->it_interval = ptimer->timer_data.it_interval;
+ _Timespec_From_ticks( remaining, &value->it_value );
+ value->it_interval = ptimer->timer_data.it_interval;
- _Objects_Put( &ptimer->Object );
+ _POSIX_Timer_Release( cpu, &lock_context );
return 0;
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/posix/src/timerinserthelper.c b/cpukit/posix/src/timerinserthelper.c
deleted file mode 100644
index b1f3373e06..0000000000
--- a/cpukit/posix/src/timerinserthelper.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * @file
- *
- * @brief Helper Routine for POSIX TIMERS
- * @ingroup POSIXAPI
- */
-
-/*
- * Helper routine for POSIX timers
- *
- * 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 <time.h>
-
-#include <rtems/system.h>
-#include <rtems/seterr.h>
-#include <rtems/score/isr.h>
-#include <rtems/score/watchdogimpl.h>
-#include <rtems/posix/timerimpl.h>
-#include <rtems/posix/ptimer.h>
-
-bool _POSIX_Timer_Insert_helper(
- Watchdog_Control *timer,
- Watchdog_Interval ticks,
- Objects_Id id,
- Watchdog_Service_routine_entry TSR,
- void *arg
-)
-{
- ISR_lock_Context lock_context;
- Watchdog_Header *header;
-
- _Watchdog_Remove_ticks( timer );
-
- header = &_Watchdog_Ticks_header;
- _Watchdog_Acquire( header, &lock_context );
-
- /*
- * Check to see if the watchdog has just been inserted by a
- * higher priority interrupt. If so, abandon this insert.
- */
- if ( timer->state != WATCHDOG_INACTIVE ) {
- _Watchdog_Release( header, &lock_context );
- return false;
- }
-
- /*
- * OK. Now we now the timer was not rescheduled by an interrupt
- * so we can atomically initialize it as in use.
- */
- _Watchdog_Initialize( timer, TSR, id, arg );
- timer->initial = ticks;
- _Watchdog_Insert_locked( header, timer, &lock_context );
- _Watchdog_Release( header, &lock_context );
- return true;
-}
diff --git a/cpukit/posix/src/timersettime.c b/cpukit/posix/src/timersettime.c
index fe54ff95c1..ac5c258eda 100644
--- a/cpukit/posix/src/timersettime.c
+++ b/cpukit/posix/src/timersettime.c
@@ -29,6 +29,76 @@
#include <rtems/score/watchdogimpl.h>
#include <rtems/seterr.h>
+static void _POSIX_Timer_Insert(
+ POSIX_Timer_Control *ptimer,
+ Per_CPU_Control *cpu,
+ Watchdog_Interval ticks
+)
+{
+ ptimer->ticks = ticks;
+
+ /* The state really did not change but just to be safe */
+ ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
+
+ /* Store the time when the timer was started again */
+ _TOD_Get_as_timespec( &ptimer->time );
+
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ &ptimer->Timer,
+ cpu->Watchdog.ticks + ticks
+ );
+}
+
+/*
+ * This is the operation that is run when a timer expires
+ */
+void _POSIX_Timer_TSR( Watchdog_Control *the_watchdog )
+{
+ POSIX_Timer_Control *ptimer;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
+
+ ptimer = RTEMS_CONTAINER_OF( the_watchdog, POSIX_Timer_Control, Timer );
+ _ISR_lock_ISR_disable( &lock_context );
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
+
+ /* Increment the number of expirations. */
+ ptimer->overrun = ptimer->overrun + 1;
+
+ /* The timer must be reprogrammed */
+ if ( ( ptimer->timer_data.it_interval.tv_sec != 0 ) ||
+ ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
+ _POSIX_Timer_Insert( ptimer, cpu, ptimer->ticks );
+ } else {
+ /* Indicates that the timer is stopped */
+ ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
+ }
+
+ _POSIX_Timer_Release( cpu, &lock_context );
+
+ /*
+ * The sending of the signal to the process running the handling function
+ * specified for that signal is simulated
+ */
+
+ if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
+ _Assert( FALSE );
+ /*
+ * TODO: What if an error happens at run-time? This should never
+ * occur because the timer should be canceled if the thread
+ * is deleted. This method is being invoked from the Clock
+ * Tick ISR so even if we decide to take action on an error,
+ * we don't have many options. We shouldn't shut the system down.
+ */
+ }
+
+ /* After the signal handler returns, the count of expirations of the
+ * timer must be set to 0.
+ */
+ ptimer->overrun = 0;
+}
+
int timer_settime(
timer_t timerid,
int flags,
@@ -38,7 +108,8 @@ int timer_settime(
{
POSIX_Timer_Control *ptimer;
Objects_Locations location;
- bool activated;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
uint32_t initial_period;
struct itimerspec normalize;
@@ -77,56 +148,47 @@ int timer_settime(
* or start it again
*/
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
+
+ /* Stop the timer */
+ _Watchdog_Remove(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ &ptimer->Timer
+ );
+
/* First, it verifies if the timer must be stopped */
if ( normalize.it_value.tv_sec == 0 && normalize.it_value.tv_nsec == 0 ) {
- /* Stop the timer */
- _Watchdog_Remove_ticks( &ptimer->Timer );
- /* The old data of the timer are returned */
- if ( ovalue )
- *ovalue = ptimer->timer_data;
- /* The new data are set */
- ptimer->timer_data = normalize;
- /* Indicates that the timer is created and stopped */
- ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
- /* Returns with success */
- _Objects_Put( &ptimer->Object );
+ /* The old data of the timer are returned */
+ if ( ovalue )
+ *ovalue = ptimer->timer_data;
+ /* The new data are set */
+ ptimer->timer_data = normalize;
+ /* Indicates that the timer is created and stopped */
+ ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
+ /* Returns with success */
+ _POSIX_Timer_Release( cpu, &lock_context );
return 0;
- }
-
- /* Convert from seconds and nanoseconds to ticks */
- ptimer->ticks = _Timespec_To_ticks( &value->it_interval );
- initial_period = _Timespec_To_ticks( &normalize.it_value );
-
-
- activated = _POSIX_Timer_Insert_helper(
- &ptimer->Timer,
- initial_period,
- ptimer->Object.id,
- _POSIX_Timer_TSR,
- ptimer
- );
- if ( !activated ) {
- _Objects_Put( &ptimer->Object );
- return 0;
- }
-
- /*
- * The timer has been started and is running. So we return the
- * old ones in "ovalue"
- */
- if ( ovalue )
- *ovalue = ptimer->timer_data;
- ptimer->timer_data = normalize;
-
- /* Indicate that the time is running */
- ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
- _TOD_Get_as_timespec( &ptimer->time );
- _Objects_Put( &ptimer->Object );
- return 0;
+ }
+
+ /* Convert from seconds and nanoseconds to ticks */
+ ptimer->ticks = _Timespec_To_ticks( &value->it_interval );
+ initial_period = _Timespec_To_ticks( &normalize.it_value );
+
+ _POSIX_Timer_Insert( ptimer, cpu, initial_period );
+
+ /*
+ * The timer has been started and is running. So we return the
+ * old ones in "ovalue"
+ */
+ if ( ovalue )
+ *ovalue = ptimer->timer_data;
+ ptimer->timer_data = normalize;
+ _POSIX_Timer_Release( cpu, &lock_context );
+ return 0;
#if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE:
diff --git a/cpukit/posix/src/timertsr.c b/cpukit/posix/src/timertsr.c
deleted file mode 100644
index 092bf16aa3..0000000000
--- a/cpukit/posix/src/timertsr.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * @file
- *
- * @brief Operation that is run when a timer expires
- * @ingroup POSIX_INTERNAL_TIMERS Timers
- */
-
-/*
- * _POSIX_Timer_TSR
- *
- * 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 <time.h>
-#include <pthread.h>
-#include <signal.h>
-
-#include <rtems/posix/ptimer.h>
-#include <rtems/posix/timerimpl.h>
-#include <rtems/score/todimpl.h>
-
-/*
- * This is the operation that is run when a timer expires
- */
-void _POSIX_Timer_TSR(
- Objects_Id timer RTEMS_UNUSED,
- void *data)
-{
- POSIX_Timer_Control *ptimer;
- bool activated;
-
- ptimer = (POSIX_Timer_Control *)data;
-
- /* Increment the number of expirations. */
- ptimer->overrun = ptimer->overrun + 1;
-
- /* The timer must be reprogrammed */
- if ( ( ptimer->timer_data.it_interval.tv_sec != 0 ) ||
- ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
- activated = _POSIX_Timer_Insert_helper(
- &ptimer->Timer,
- ptimer->ticks,
- ptimer->Object.id,
- _POSIX_Timer_TSR,
- ptimer
- );
- if ( !activated )
- return;
-
- /* Store the time when the timer was started again */
- _TOD_Get_as_timespec( &ptimer->time );
-
- /* The state really did not change but just to be safe */
- ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
- } else {
- /* Indicates that the timer is stopped */
- ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
- }
-
- /*
- * The sending of the signal to the process running the handling function
- * specified for that signal is simulated
- */
-
- if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
- _Assert( FALSE );
- /*
- * TODO: What if an error happens at run-time? This should never
- * occur because the timer should be canceled if the thread
- * is deleted. This method is being invoked from the Clock
- * Tick ISR so even if we decide to take action on an error,
- * we don't have many options. We shouldn't shut the system down.
- */
- }
-
- /* After the signal handler returns, the count of expirations of the
- * timer must be set to 0.
- */
- ptimer->overrun = 0;
-}
diff --git a/cpukit/posix/src/ualarm.c b/cpukit/posix/src/ualarm.c
index 9607d3f62c..86fe1b05cc 100644
--- a/cpukit/posix/src/ualarm.c
+++ b/cpukit/posix/src/ualarm.c
@@ -21,39 +21,62 @@
#include <signal.h>
#include <unistd.h>
-#include <rtems/posix/pthreadimpl.h>
-#include <rtems/posix/psignalimpl.h>
-#include <rtems/score/threaddispatch.h>
#include <rtems/score/todimpl.h>
#include <rtems/score/watchdogimpl.h>
+#include <rtems/config.h>
-static void _POSIX_signals_Ualarm_TSR( Objects_Id id, void *argument );
+ISR_LOCK_DEFINE( static, _POSIX_signals_Ualarm_lock, "POSIX Ualarm" )
-static Watchdog_Control _POSIX_signals_Ualarm_timer = WATCHDOG_INITIALIZER(
- _POSIX_signals_Ualarm_TSR,
- 0,
- NULL
-);
-
-/*
- * _POSIX_signals_Ualarm_TSR
- */
+static uint32_t _POSIX_signals_Ualarm_interval;
-static void _POSIX_signals_Ualarm_TSR(
- Objects_Id id RTEMS_UNUSED,
- void *argument RTEMS_UNUSED
-)
+static void _POSIX_signals_Ualarm_TSR( Watchdog_Control *the_watchdog )
{
- /*
- * Send a SIGALRM but if there is a problem, ignore it.
- * It's OK, there isn't a way this should fail.
- */
- (void) kill( getpid(), SIGALRM );
+ int status;
+ ISR_lock_Context lock_context;
+
+ status = kill( getpid(), SIGALRM );
+
+ #if defined(RTEMS_DEBUG)
+ /*
+ * There is no reason to think this might fail but we should be
+ * cautious.
+ */
+ _Assert(status == 0);
+ #else
+ (void) status;
+ #endif
+
+ _ISR_lock_ISR_disable_and_acquire(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
/*
* If the reset interval is non-zero, reschedule ourselves.
*/
- _Watchdog_Reset_ticks( &_POSIX_signals_Ualarm_timer );
+ if ( _POSIX_signals_Ualarm_interval != 0 ) {
+ _Watchdog_Per_CPU_insert_relative(
+ the_watchdog,
+ _Per_CPU_Get(),
+ _POSIX_signals_Ualarm_interval
+ );
+ }
+
+ _ISR_lock_Release_and_ISR_enable(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
+}
+
+static Watchdog_Control _POSIX_signals_Ualarm_watchdog = WATCHDOG_INITIALIZER(
+ _POSIX_signals_Ualarm_TSR
+);
+
+static uint32_t _POSIX_signals_Ualarm_us_to_ticks( useconds_t us )
+{
+ uint32_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
+
+ return ( us + us_per_tick - 1 ) / us_per_tick;
}
useconds_t ualarm(
@@ -61,51 +84,53 @@ useconds_t ualarm(
useconds_t interval
)
{
- useconds_t remaining = 0;
- Watchdog_Control *the_timer;
- Watchdog_Interval ticks;
- Watchdog_States state;
- struct timespec tp;
-
- the_timer = &_POSIX_signals_Ualarm_timer;
-
- _Thread_Disable_dispatch();
-
- state = _Watchdog_Remove_ticks( the_timer );
- if ( state == WATCHDOG_ACTIVE ) {
- /*
- * The stop_time and start_time fields are snapshots of ticks since
- * boot. Since alarm() is dealing in seconds, we must account for
- * this.
- */
-
- ticks = the_timer->initial;
- ticks -= (the_timer->stop_time - the_timer->start_time);
- /* remaining is now in ticks */
-
- _Timespec_From_ticks( ticks, &tp );
- remaining = tp.tv_sec * TOD_MICROSECONDS_PER_SECOND;
- remaining += tp.tv_nsec / 1000;
+ useconds_t remaining;
+ Watchdog_Control *the_watchdog;
+ ISR_lock_Context lock_context;
+ ISR_lock_Context lock_context2;
+ Per_CPU_Control *cpu;
+ uint64_t now;
+ uint32_t ticks_initial;
+ uint32_t ticks_interval;
+
+ the_watchdog = &_POSIX_signals_Ualarm_watchdog;
+ ticks_initial = _POSIX_signals_Ualarm_us_to_ticks( useconds );
+ ticks_interval = _POSIX_signals_Ualarm_us_to_ticks( interval );
+
+ _ISR_lock_ISR_disable_and_acquire(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
+
+ cpu = _Watchdog_Get_CPU( the_watchdog );
+ _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
+ now = cpu->Watchdog.ticks;
+
+ remaining = (useconds_t) _Watchdog_Cancel(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now
+ );
+
+ if ( ticks_initial != 0 ) {
+ _POSIX_signals_Ualarm_interval = ticks_interval;
+
+ cpu = _Per_CPU_Get();
+ _Watchdog_Set_CPU( the_watchdog, cpu );
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now + ticks_initial
+ );
}
- /*
- * If useconds is non-zero, then the caller wants to schedule
- * the alarm repeatedly at that interval. If the interval is
- * less than a single clock tick, then fudge it to a clock tick.
- */
- if ( useconds ) {
- Watchdog_Interval ticks;
-
- tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND;
- tp.tv_nsec = (useconds % TOD_MICROSECONDS_PER_SECOND) * 1000;
- ticks = _Timespec_To_ticks( &tp );
- if ( ticks == 0 )
- ticks = 1;
-
- _Watchdog_Insert_ticks( the_timer, _Timespec_To_ticks( &tp ) );
- }
+ _Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
+ _ISR_lock_Release_and_ISR_enable(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
- _Thread_Enable_dispatch();
+ remaining *= rtems_configuration_get_microseconds_per_tick();
return remaining;
}