nanosleep(3), and sleep(3) rewrite, by Erik van der Kouwe
This commit is contained in:
parent
323f0abdd6
commit
5a13b2eda8
@ -72,4 +72,14 @@ _PROTOTYPE( int stime, (time_t *_top) );
|
|||||||
|
|
||||||
extern long timezone;
|
extern long timezone;
|
||||||
|
|
||||||
|
#ifdef _POSIX_SOURCE
|
||||||
|
struct timespec
|
||||||
|
{
|
||||||
|
time_t tv_sec;
|
||||||
|
long tv_nsec;
|
||||||
|
};
|
||||||
|
|
||||||
|
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _TIME_H */
|
#endif /* _TIME_H */
|
||||||
|
@ -56,6 +56,7 @@ libc_FILES=" \
|
|||||||
_mkfifo.c \
|
_mkfifo.c \
|
||||||
_mknod.c \
|
_mknod.c \
|
||||||
_mmap.c \
|
_mmap.c \
|
||||||
|
_nanosleep.c \
|
||||||
_open.c \
|
_open.c \
|
||||||
_opendir.c \
|
_opendir.c \
|
||||||
_pathconf.c \
|
_pathconf.c \
|
||||||
|
77
lib/posix/_nanosleep.c
Normal file
77
lib/posix/_nanosleep.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* nanosleep() - Sleep for a number of nanoseconds. Author: Erik van der Kouwe
|
||||||
|
* 25 July 2009
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lib.h>
|
||||||
|
#define nanosleep _nanosleep
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define MSEC_PER_SEC 1000
|
||||||
|
#define USEC_PER_MSEC 1000
|
||||||
|
#define NSEC_PER_USEC 1000
|
||||||
|
|
||||||
|
#define USEC_PER_SEC (USEC_PER_MSEC * MSEC_PER_SEC)
|
||||||
|
#define NSEC_PER_SEC (NSEC_PER_USEC * USEC_PER_SEC)
|
||||||
|
|
||||||
|
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
|
||||||
|
{
|
||||||
|
struct timeval timeout, timestart = { 0, 0 }, timeend;
|
||||||
|
int errno_select, r;
|
||||||
|
|
||||||
|
/* keep track of start time if needed */
|
||||||
|
if (rmtp)
|
||||||
|
{
|
||||||
|
rmtp->tv_sec = 0;
|
||||||
|
rmtp->tv_nsec = 0;
|
||||||
|
if (gettimeofday(×tart, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use select to wait */
|
||||||
|
timeout.tv_sec = rqtp->tv_sec;
|
||||||
|
timeout.tv_usec = (rqtp->tv_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC;
|
||||||
|
r = select(0, NULL, NULL, NULL, &timeout);
|
||||||
|
|
||||||
|
/* return remaining time only if requested */
|
||||||
|
/* if select succeeded then we slept all time */
|
||||||
|
if (!rmtp || r >= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* measure end time; preserve errno */
|
||||||
|
errno_select = errno;
|
||||||
|
if (gettimeofday(&timeend, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
errno = errno_select;
|
||||||
|
|
||||||
|
/* compute remaining time */
|
||||||
|
rmtp->tv_sec = rqtp->tv_sec - (timeend.tv_sec - timestart.tv_sec);
|
||||||
|
rmtp->tv_nsec = rqtp->tv_nsec -
|
||||||
|
(timeend.tv_usec - timestart.tv_usec) * NSEC_PER_USEC;
|
||||||
|
|
||||||
|
/* bring remaining time into canonical form */
|
||||||
|
while (rmtp->tv_nsec < 0)
|
||||||
|
{
|
||||||
|
rmtp->tv_sec -= 1;
|
||||||
|
rmtp->tv_nsec += NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rmtp->tv_nsec > NSEC_PER_SEC)
|
||||||
|
{
|
||||||
|
rmtp->tv_sec += 1;
|
||||||
|
rmtp->tv_nsec -= NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remaining time must not be negative */
|
||||||
|
if (rmtp->tv_sec < 0)
|
||||||
|
{
|
||||||
|
rmtp->tv_sec = 0;
|
||||||
|
rmtp->tv_nsec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
@ -1,69 +1,22 @@
|
|||||||
/* sleep() - Sleep for a number of seconds. Author: Kees J. Bot
|
/* sleep() - Sleep for a number of seconds. Author: Erik van der Kouwe
|
||||||
* 24 Apr 2000
|
* 25 July 2009
|
||||||
* (Inspired by the Minix-vmd version of same, except that
|
|
||||||
* this implementation doesn't bother to check if all the signal
|
|
||||||
* functions succeed. Under Minix that is no problem.)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#define sleep _sleep
|
#define sleep _sleep
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
static void handler(int sig)
|
|
||||||
{
|
|
||||||
/* Dummy signal handler. */
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned sleep(unsigned sleep_seconds)
|
unsigned sleep(unsigned sleep_seconds)
|
||||||
{
|
{
|
||||||
sigset_t ss_full, ss_orig, ss_alarm;
|
struct timespec rqtp, rmtp;
|
||||||
struct sigaction action_alarm, action_orig;
|
|
||||||
unsigned alarm_seconds, nap_seconds;
|
|
||||||
|
|
||||||
if (sleep_seconds == 0) return 0; /* No rest for the wicked */
|
/* nanosleep implements this call;
|
||||||
|
* ignore failure, it cannot be reported
|
||||||
|
*/
|
||||||
|
rqtp.tv_sec = sleep_seconds;
|
||||||
|
rqtp.tv_nsec = 0;
|
||||||
|
nanosleep(&rqtp, &rmtp);
|
||||||
|
|
||||||
/* Mask all signals. */
|
/* round remainder up to seconds */
|
||||||
sigfillset(&ss_full);
|
return rmtp.tv_sec + ((rmtp.tv_nsec > 0) ? 1 : 0);
|
||||||
sigprocmask(SIG_BLOCK, &ss_full, &ss_orig);
|
|
||||||
|
|
||||||
/* Cancel currently running alarm. */
|
|
||||||
alarm_seconds= alarm(0);
|
|
||||||
|
|
||||||
/* How long can we nap without interruptions? */
|
|
||||||
nap_seconds= sleep_seconds;
|
|
||||||
if (alarm_seconds != 0 && alarm_seconds < sleep_seconds) {
|
|
||||||
nap_seconds= alarm_seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now sleep. */
|
|
||||||
action_alarm.sa_handler= handler;
|
|
||||||
sigemptyset(&action_alarm.sa_mask);
|
|
||||||
action_alarm.sa_flags= 0;
|
|
||||||
sigaction(SIGALRM, &action_alarm, &action_orig);
|
|
||||||
alarm(nap_seconds);
|
|
||||||
|
|
||||||
/* Wait for a wakeup call, either our alarm, or some other signal. */
|
|
||||||
ss_alarm= ss_orig;
|
|
||||||
sigdelset(&ss_alarm, SIGALRM);
|
|
||||||
sigsuspend(&ss_alarm);
|
|
||||||
|
|
||||||
/* Cancel alarm, set mask and stuff back to normal. */
|
|
||||||
nap_seconds -= alarm(0);
|
|
||||||
sigaction(SIGALRM, &action_orig, NULL);
|
|
||||||
sigprocmask(SIG_SETMASK, &ss_orig, NULL);
|
|
||||||
|
|
||||||
/* Restore alarm counter to the time remaining. */
|
|
||||||
if (alarm_seconds != 0 && alarm_seconds >= nap_seconds) {
|
|
||||||
alarm_seconds -= nap_seconds;
|
|
||||||
if (alarm_seconds == 0) {
|
|
||||||
raise(SIGALRM); /* Alarm expires now! */
|
|
||||||
} else {
|
|
||||||
alarm(alarm_seconds); /* Count time remaining. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return time not slept. */
|
|
||||||
return sleep_seconds - nap_seconds;
|
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ libc_FILES=" \
|
|||||||
mknod.s \
|
mknod.s \
|
||||||
mmap.s \
|
mmap.s \
|
||||||
mount.s \
|
mount.s \
|
||||||
|
nanosleep.s \
|
||||||
open.s \
|
open.s \
|
||||||
opendir.s \
|
opendir.s \
|
||||||
pathconf.s \
|
pathconf.s \
|
||||||
|
6
lib/syscall/nanosleep.s
Normal file
6
lib/syscall/nanosleep.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.sect .text
|
||||||
|
.extern __nanosleep
|
||||||
|
.define _nanosleep
|
||||||
|
|
||||||
|
_nanosleep:
|
||||||
|
jmp __nanosleep
|
Loading…
x
Reference in New Issue
Block a user