summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src/nanosleep.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-11-02 18:35:52 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-11-02 18:35:52 +0000
commit9f95a19a57f0f85212c320327636e93d70bbecc8 (patch)
treed62e1fc518777ce07e83994183d0d1b82a7f8a02 /cpukit/posix/src/nanosleep.c
parentSplit condition variables into multiple files. (diff)
downloadrtems-9f95a19a57f0f85212c320327636e93d70bbecc8.tar.bz2
Split time.c into multiple files.
Diffstat (limited to 'cpukit/posix/src/nanosleep.c')
-rw-r--r--cpukit/posix/src/nanosleep.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
new file mode 100644
index 0000000000..7930c016e5
--- /dev/null
+++ b/cpukit/posix/src/nanosleep.c
@@ -0,0 +1,100 @@
+/*
+ * $Id$
+ */
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/posix/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
+ */
+
+int nanosleep(
+ const struct timespec *rqtp,
+ struct timespec *rmtp
+)
+{
+ Watchdog_Interval ticks;
+ struct timespec *the_rqtp;
+
+ if ( !rqtp )
+ set_errno_and_return_minus_one( EINVAL );
+
+ the_rqtp = (struct timespec *)rqtp;
+
+ /*
+ * Return EAGAIN if the delay interval is negative.
+ *
+ * NOTE: This behavior is beyond the POSIX specification.
+ * FSU pthreads shares this behavior.
+ */
+
+ if ( the_rqtp->tv_sec < 0 )
+ the_rqtp->tv_sec = 0;
+
+ if ( /* the_rqtp->tv_sec < 0 || */ the_rqtp->tv_nsec < 0 )
+ set_errno_and_return_minus_one( EAGAIN );
+
+ if ( the_rqtp->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
+ set_errno_and_return_minus_one( EINVAL );
+
+ ticks = _POSIX_Timespec_to_interval( the_rqtp );
+
+ /*
+ * This behavior is also beyond the POSIX specification but is
+ * consistent with the RTEMS api and yields desirable behavior.
+ */
+
+ if ( !ticks ) {
+ _Thread_Disable_dispatch();
+ _Thread_Yield_processor();
+ _Thread_Enable_dispatch();
+ if ( rmtp ) {
+ rmtp->tv_sec = 0;
+ rmtp->tv_nsec = 0;
+ }
+ return 0;
+ }
+
+ _Thread_Disable_dispatch();
+ _Thread_Set_state(
+ _Thread_Executing,
+ STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
+ );
+ _Watchdog_Initialize(
+ &_Thread_Executing->Timer,
+ _Thread_Delay_ended,
+ _Thread_Executing->Object.id,
+ NULL
+ );
+ _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
+ _Thread_Enable_dispatch();
+
+ /* calculate time remaining */
+
+ if ( rmtp ) {
+ ticks -=
+ _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;
+
+ _POSIX_Interval_to_timespec( ticks, rmtp );
+
+ /*
+ * If there is time remaining, then we were interrupted by a signal.
+ */
+
+ if ( ticks )
+ set_errno_and_return_minus_one( EINTR );
+ }
+
+ return 0;
+}