posix: Move clock_nanosleep()

Move clock_nanosleep() to a separate file to avoid a dependency on errno
which pulls in the Newlib reentrancy support.  This is an issue since
most parts which are pulled in cannot be garbage collected by the linker
due to the system initialization linker set.
This commit is contained in:
Sebastian Huber
2021-05-17 16:39:52 +02:00
parent 15e26f4d7f
commit 815a94326c
4 changed files with 118 additions and 91 deletions

View File

@@ -490,6 +490,7 @@ librtemscpu_a_SOURCES += posix/src/cleanuppush.c
librtemscpu_a_SOURCES += posix/src/clockgetcpuclockid.c
librtemscpu_a_SOURCES += posix/src/clockgetres.c
librtemscpu_a_SOURCES += posix/src/clockgettime.c
librtemscpu_a_SOURCES += posix/src/clocknanosleep.c
librtemscpu_a_SOURCES += posix/src/clocksettime.c
librtemscpu_a_SOURCES += posix/src/condattrdestroy.c
librtemscpu_a_SOURCES += posix/src/condattrgetclock.c

View File

@@ -0,0 +1,116 @@
/**
* @file
*
* @ingroup POSIXAPI
*
* @brief Suspends Execution of calling thread until Time elapses
*/
/*
* COPYRIGHT (c) 1989-2015.
* On-Line Applications Research Corporation (OAR).
*
* Copyright (c) 2016. Gedare Bloom.
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <time.h>
#include <rtems/score/threadimpl.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/timespec.h>
#include <rtems/score/timecounter.h>
#include <rtems/score/watchdogimpl.h>
#include <rtems/posix/posixapi.h>
static Thread_queue_Control _Nanosleep_Pseudo_queue =
THREAD_QUEUE_INITIALIZER( "Nanosleep" );
/*
* High Resolution Sleep with Specifiable Clock, IEEE Std 1003.1, 2001
*/
int clock_nanosleep(
clockid_t clock_id,
int flags,
const struct timespec *rqtp,
struct timespec *rmtp
)
{
Thread_queue_Context queue_context;
struct timespec uptime;
const struct timespec *end;
Thread_Control *executing;
int eno;
if ( clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC ) {
return ENOTSUP;
}
_Thread_queue_Context_initialize( &queue_context );
_Thread_queue_Context_set_thread_state(
&queue_context,
STATES_WAITING_FOR_TIME | STATES_INTERRUPTIBLE_BY_SIGNAL
);
if ( ( flags & TIMER_ABSTIME ) != 0 ) {
end = rqtp;
if ( clock_id == CLOCK_REALTIME ) {
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
&queue_context,
end
);
} else {
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
&queue_context,
end
);
}
} else {
_Timecounter_Nanouptime( &uptime );
end = _Watchdog_Future_timespec( &uptime, rqtp );
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
&queue_context,
end
);
}
_Thread_queue_Acquire( &_Nanosleep_Pseudo_queue, &queue_context );
executing = _Thread_Executing;
_Thread_queue_Enqueue(
&_Nanosleep_Pseudo_queue.Queue,
&_Thread_queue_Operations_FIFO,
executing,
&queue_context
);
eno = _POSIX_Get_error_after_wait( executing );
if ( eno == ETIMEDOUT ) {
eno = 0;
}
if ( rmtp != NULL && ( flags & TIMER_ABSTIME ) == 0 ) {
if ( eno == EINTR ) {
struct timespec actual_end;
_Timecounter_Nanouptime( &actual_end );
if ( _Timespec_Less_than( &actual_end, end ) ) {
_Timespec_Subtract( &actual_end, end, rmtp );
} else {
_Timespec_Set_to_zero( rmtp );
}
} else {
_Timespec_Set_to_zero( rmtp );
}
}
return eno;
}

View File

@@ -23,17 +23,8 @@
#include <time.h>
#include <rtems/score/threadimpl.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/timespec.h>
#include <rtems/score/timecounter.h>
#include <rtems/score/watchdogimpl.h>
#include <rtems/posix/posixapi.h>
#include <rtems/seterr.h>
static Thread_queue_Control _Nanosleep_Pseudo_queue =
THREAD_QUEUE_INITIALIZER( "Nanosleep" );
/*
* 14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
*/
@@ -52,85 +43,3 @@ int nanosleep(
return eno;
}
/*
* High Resolution Sleep with Specifiable Clock, IEEE Std 1003.1, 2001
*/
int clock_nanosleep(
clockid_t clock_id,
int flags,
const struct timespec *rqtp,
struct timespec *rmtp
)
{
Thread_queue_Context queue_context;
struct timespec uptime;
const struct timespec *end;
Thread_Control *executing;
int eno;
if ( clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC ) {
return ENOTSUP;
}
_Thread_queue_Context_initialize( &queue_context );
_Thread_queue_Context_set_thread_state(
&queue_context,
STATES_WAITING_FOR_TIME | STATES_INTERRUPTIBLE_BY_SIGNAL
);
if ( ( flags & TIMER_ABSTIME ) != 0 ) {
end = rqtp;
if ( clock_id == CLOCK_REALTIME ) {
_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
&queue_context,
end
);
} else {
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
&queue_context,
end
);
}
} else {
_Timecounter_Nanouptime( &uptime );
end = _Watchdog_Future_timespec( &uptime, rqtp );
_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
&queue_context,
end
);
}
_Thread_queue_Acquire( &_Nanosleep_Pseudo_queue, &queue_context );
executing = _Thread_Executing;
_Thread_queue_Enqueue(
&_Nanosleep_Pseudo_queue.Queue,
&_Thread_queue_Operations_FIFO,
executing,
&queue_context
);
eno = _POSIX_Get_error_after_wait( executing );
if ( eno == ETIMEDOUT ) {
eno = 0;
}
if ( rmtp != NULL && ( flags & TIMER_ABSTIME ) == 0 ) {
if ( eno == EINTR ) {
struct timespec actual_end;
_Timecounter_Nanouptime( &actual_end );
if ( _Timespec_Less_than( &actual_end, end ) ) {
_Timespec_Subtract( &actual_end, end, rmtp );
} else {
_Timespec_Set_to_zero( rmtp );
}
} else {
_Timespec_Set_to_zero( rmtp );
}
}
return eno;
}

View File

@@ -990,6 +990,7 @@ source:
- cpukit/posix/src/clockgetcpuclockid.c
- cpukit/posix/src/clockgetres.c
- cpukit/posix/src/clockgettime.c
- cpukit/posix/src/clocknanosleep.c
- cpukit/posix/src/clocksettime.c
- cpukit/posix/src/condattrdestroy.c
- cpukit/posix/src/condattrgetclock.c