[core] use pthread_condattr_setclock rather than pthread_cond_clockwait() #2302

This commit is contained in:
nick black 2021-10-27 12:55:08 -04:00 committed by nick black
parent 26d6c27329
commit fec64cfc33
6 changed files with 52 additions and 16 deletions

View File

@ -730,7 +730,7 @@ typedef struct ncinput {
// timespec to bound blocking. Returns a single Unicode code point, or
// (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, the
// return value is the 'id' field from that event. 'ni' may be NULL. 'ts' is an
// a delay bound against gettimeofday() (see pthread_cond_timedwait(3)).
// a delay bound against CLOCK_MONOTONIC (see clock_gettime(2)).
uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts,
ncinput* ni);

View File

@ -1086,7 +1086,7 @@ ncinput_equal_p(const ncinput* n1, const ncinput* n2){
// timespec to bound blocking. Returns a single Unicode code point, or
// (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, the
// return value is the 'id' field from that event. 'ni' may be NULL. 'ts' is an
// a delay bound against CLOCK_MONOTONIC (see pthread_cond_clockwait(3)).
// a delay bound against CLOCK_MONOTONIC (see clock_gettime(2)).
API uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts,
ncinput* ni)
__attribute__ ((nonnull (1)));

View File

@ -1,4 +1,5 @@
#include "compat/compat.h"
#include <pthread.h>
#ifdef __MINGW64__
#include <string.h>
#include <stdlib.h>
@ -44,11 +45,38 @@ pid_t waitpid(pid_t pid, int* state, int options){ // FIXME
*/
return 0;
}
int pthread_condmonotonic_init(pthread_cond_t* cond){
if(pthread_cond_init(cond, &cat)){
return -1;
}
return 0;
}
#else // not windows
#include <time.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
// initializes a pthread_cond_t to use CLOCK_MONOTONIC (as opposed to the
// default CLOCK_REALTIME) if possible. if not possible, initializes a
// regular ol' CLOCK_REALTIME condvar.
int pthread_condmonotonic_init(pthread_cond_t* cond){
pthread_condattr_t cat;
if(pthread_condattr_init(&cat)){
return -1;
}
if(pthread_condattr_setclock(&cat, CLOCK_MONOTONIC)){
pthread_condattr_destroy(&cat);
return -1;
}
if(pthread_cond_init(cond, &cat)){
pthread_condattr_destroy(&cat);
return -1;
}
pthread_condattr_destroy(&cat);
return 0;
}
int set_fd_nonblocking(int fd, unsigned state, unsigned* oldstate){
int flags = fcntl(fd, F_GETFL);
if(flags < 0){

View File

@ -67,10 +67,11 @@ struct winsize {
#include <sys/ioctl.h>
#endif
#ifndef _USE_GNU
// FIXME actually implement this honoring c: CLOCK_MONOTONIC
#define pthread_cond_clockwait(a, b, c, d) pthread_cond_timedwait(a, b, d)
#endif
// initializes a pthread_cond_t to use CLOCK_MONOTONIC (as opposed to the
// default CLOCK_REALTIME) if possible. if not possible, initializes a
// regular ol' CLOCK_REALTIME condvar. this eliminates the need for
// pthread_cond_clockwait(), which is highly nonportable.
int pthread_condmonotonic_init(pthread_cond_t* cond);
int set_fd_nonblocking(int fd, unsigned state, unsigned* oldstate);
int set_fd_cloexec(int fd, unsigned state, unsigned* oldstate);

View File

@ -17,8 +17,8 @@ static int input_pipefds[2] = {-1, -1};
static pthread_t tid;
static nciqueue* queue;
static nciqueue** enqueue = &queue;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond; // use pthread_condmonotonic_init()
static int
handle_mouse(const ncinput* ni){
@ -71,7 +71,7 @@ uint32_t demo_getc(struct notcurses* nc, const struct timespec* ts, ncinput* ni)
pthread_mutex_unlock(&lock);
return 0;
}
pthread_cond_clockwait(&cond, &lock, CLOCK_MONOTONIC, &abstime);
pthread_cond_timedwait(&cond, &lock, &abstime);
}
nciqueue* q = queue;
queue = queue->next;
@ -153,6 +153,10 @@ int input_dispatcher(struct notcurses* nc){
if(input_pipefds[0] >= 0){
return -1;
}
if(pthread_condmonotonic_init(&cond)){
fprintf(stderr, "error creating monotonic condvar\n");
return -1;
}
// freebsd doesn't have eventfd :/ and apple doesn't even have pipe2() =[ =[
// omg windows doesn't have pipe() fml FIXME
#ifndef __MINGW64__
@ -182,6 +186,7 @@ int stop_input(void){
ret |= close(input_pipefds[0]);
ret |= close(input_pipefds[1]);
input_pipefds[0] = input_pipefds[1] = -1;
ret |= pthread_cond_destroy(&cond);
}
return ret;
}

View File

@ -1396,9 +1396,9 @@ create_inputctx(tinfo* ti, FILE* infp, int lmargin, int tmargin, int rmargin,
i->isize = BUFSIZ;
if( (i->inputs = malloc(sizeof(*i->inputs) * i->isize)) ){
if(pthread_mutex_init(&i->ilock, NULL) == 0){
if(pthread_cond_init(&i->icond, NULL) == 0){
if(pthread_condmonotonic_init(&i->icond) == 0){
if(pthread_mutex_init(&i->clock, NULL) == 0){
if(pthread_cond_init(&i->ccond, NULL) == 0){
if(pthread_condmonotonic_init(&i->ccond) == 0){
if((i->stdinfd = fileno(infp)) >= 0){
if( (i->initdata = malloc(sizeof(*i->initdata))) ){
if(getpipes(i->readypipes) == 0){
@ -2079,7 +2079,7 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
if(ts == NULL){
pthread_cond_wait(&ictx->icond, &ictx->ilock);
}else{
int r = pthread_cond_clockwait(&ictx->icond, &ictx->ilock, CLOCK_MONOTONIC, ts);
int r = pthread_cond_timedwait(&ictx->icond, &ictx->ilock, ts);
if(r == ETIMEDOUT){
pthread_mutex_unlock(&ictx->ilock);
return 0;
@ -2119,15 +2119,17 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
return id;
}
// FIXME kill off for API3, and expect an absolute deadline directly
static void
delaybound_to_deadline(const struct timespec* ts, struct timespec* absdl){
if(ts){
// incoming ts is a delay bound, but we want an absolute deadline for
// pthread_cond_timedwait(). convert it.
struct timeval tv;
gettimeofday(&tv, NULL);
absdl->tv_sec = ts->tv_sec + tv.tv_sec;
absdl->tv_nsec = ts->tv_nsec + tv.tv_usec * 1000;
// pthread_cond_timedwait(). convert it, using CLOCK_MONOTONIC (we
// initialized the condvar with pthread_condmonotonic_init()).
struct timespec tspec;
clock_gettime(CLOCK_MONOTONIC, &tspec);
absdl->tv_sec = ts->tv_sec + tspec.tv_sec;
absdl->tv_nsec = ts->tv_nsec + tspec.tv_nsec;
if(absdl->tv_nsec > 1000000000){
++absdl->tv_sec;
absdl->tv_nsec -= 1000000000;