From f6132c99e1781f8ca2df08ddd7271bf5895dff0d Mon Sep 17 00:00:00 2001 From: Tomas Mudrunka Date: Fri, 2 Jul 2021 15:37:20 +0200 Subject: [PATCH] Pthread sleep --- c/pthread_extra/Makefile | 2 +- c/pthread_extra/pthread_extra.h | 6 ++++ c/pthread_extra/pthread_sleep.c | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 c/pthread_extra/pthread_sleep.c diff --git a/c/pthread_extra/Makefile b/c/pthread_extra/Makefile index 1197cca..35fac9c 100644 --- a/c/pthread_extra/Makefile +++ b/c/pthread_extra/Makefile @@ -11,7 +11,7 @@ CXXFLAGS+=$(COPT) $(CERR) $(CDEF) -std=c++11 $(CLIB) LDFLAGS+=$(COPT) $(LIB) BIN=test -OBJ=pthread_user_data.o pthread_pause.o pthread_multi.o pthread_msgqueue.o test.o +OBJ=pthread_user_data.o pthread_sleep.o pthread_pause.o pthread_multi.o pthread_msgqueue.o test.o all: $(BIN) $(BIN): $(OBJ) diff --git a/c/pthread_extra/pthread_extra.h b/c/pthread_extra/pthread_extra.h index 4df45d9..56c440b 100644 --- a/c/pthread_extra/pthread_extra.h +++ b/c/pthread_extra/pthread_extra.h @@ -56,6 +56,12 @@ int pthread_unpause_all(); int pthread_pause_reschedule(pthread_t thread); int pthread_extra_yield(); +// Pause compatible sleeps + +void pthread_nanosleep(struct timespec t); +void pthread_nsleep(time_t s, long ns); +void pthread_sleep(time_t s); + // Message queues //Flags diff --git a/c/pthread_extra/pthread_sleep.c b/c/pthread_extra/pthread_sleep.c new file mode 100644 index 0000000..12712c1 --- /dev/null +++ b/c/pthread_extra/pthread_sleep.c @@ -0,0 +1,49 @@ +#include +#include +#include + +#define NSEC_PER_SEC (1000*1000*1000) +// timespec_normalise() from https://github.com/solemnwarning/timespec/ +struct timespec timespec_normalise(struct timespec ts) +{ + while(ts.tv_nsec >= NSEC_PER_SEC) { + ++(ts.tv_sec); ts.tv_nsec -= NSEC_PER_SEC; + } + while(ts.tv_nsec <= -NSEC_PER_SEC) { + --(ts.tv_sec); ts.tv_nsec += NSEC_PER_SEC; + } + if(ts.tv_nsec < 0) { // Negative nanoseconds isn't valid according to POSIX. + --(ts.tv_sec); ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec); + } + return ts; +} + +void pthread_nanosleep(struct timespec t) { + //Sleep calls on Linux get interrupted by signals, causing premature wake + //Pthread (un)pause is built using signals + //Therefore we need self-restarting sleep implementation + //IO timeouts are restarted by SA_RESTART, but sleeps do need explicit restart + //We also need to sleep using absolute time, because relative time is paused + //You should use this in any thread that gets (un)paused + + struct timespec wake; + clock_gettime(CLOCK_MONOTONIC, &wake); + + t = timespec_normalise(t); + wake.tv_sec += t.tv_sec; + wake.tv_nsec += t.tv_nsec; + wake = timespec_normalise(wake); + + while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wake, NULL)) if(errno!=EINTR) break; + return; +} +void pthread_nsleep(time_t s, long ns) { + struct timespec t; + t.tv_sec = s; + t.tv_nsec = ns; + pthread_nanosleep(t); +} + +void pthread_sleep(time_t s) { + pthread_nsleep(s, 0); +} -- 2.30.2