diff options
-rw-r--r-- | Changes | 4 | ||||
-rw-r--r-- | eio.c | 43 | ||||
-rw-r--r-- | eio.h | 1 | ||||
-rw-r--r-- | xthread.h | 28 |
4 files changed, 55 insertions, 21 deletions
@@ -2,9 +2,11 @@ Revision history for libeio TODO: maybe add mincore support? available on at least darwin, solaris, linux, freebsd TODO: openbsd requires stdint.h for intptr_t - why posix? -TODO: mutex init in child after fork? 1.0 + - use nonstandard but maybe-working-on-bsd fork technique. + - support a max_idle value of 0. + - support setting of idle timeout value. - readdir: correctly handle malloc failures. - readdir: new flags argument, can return inode and possibly filetype, can sort in various ways. @@ -134,9 +134,6 @@ # define D_NAMLEN(de) strlen ((de)->d_name) #endif -/* number of seconds after which an idle threads exit */ -#define IDLE_TIMEOUT 10 - /* used for struct dirent, AIX doesn't provide it */ #ifndef NAME_MAX # define NAME_MAX 4096 @@ -225,12 +222,13 @@ static unsigned int max_poll_reqs; /* reslock */ static volatile unsigned int nreqs; /* reqlock */ static volatile unsigned int nready; /* reqlock */ static volatile unsigned int npending; /* reqlock */ -static volatile unsigned int max_idle = 4; +static volatile unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */ +static volatile unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */ -static xmutex_t wrklock = X_MUTEX_INIT; -static xmutex_t reslock = X_MUTEX_INIT; -static xmutex_t reqlock = X_MUTEX_INIT; -static xcond_t reqwait = X_COND_INIT; +static xmutex_t wrklock; +static xmutex_t reslock; +static xmutex_t reqlock; +static xcond_t reqwait; #if !HAVE_PREADWRITE /* @@ -370,6 +368,14 @@ static ETP_REQ *reqq_shift (etp_reqq *q) abort (); } +static void etp_thread_init (void) +{ + X_MUTEX_CREATE (wrklock); + X_MUTEX_CREATE (reslock); + X_MUTEX_CREATE (reqlock); + X_COND_CREATE (reqwait); +} + static void etp_atfork_prepare (void) { X_LOCK (wrklock); @@ -417,12 +423,13 @@ static void etp_atfork_child (void) nready = 0; npending = 0; - etp_atfork_parent (); + etp_thread_init (); } static void etp_once_init (void) -{ +{ + etp_thread_init (); X_THREAD_ATFORK (etp_atfork_prepare, etp_atfork_parent, etp_atfork_child); } @@ -623,7 +630,14 @@ static void etp_set_max_poll_reqs (unsigned int maxreqs) static void etp_set_max_idle (unsigned int nthreads) { if (WORDACCESS_UNSAFE) X_LOCK (reqlock); - max_idle = nthreads <= 0 ? 1 : nthreads; + max_idle = nthreads; + if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); +} + +static void etp_set_idle_timeout (unsigned int seconds) +{ + if (WORDACCESS_UNSAFE) X_LOCK (reqlock); + idle_timeout = seconds; if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); } @@ -761,6 +775,11 @@ void eio_set_max_idle (unsigned int nthreads) etp_set_max_idle (nthreads); } +void eio_set_idle_timeout (unsigned int seconds) +{ + etp_set_idle_timeout (seconds); +} + void eio_set_min_parallel (unsigned int nthreads) { etp_set_min_parallel (nthreads); @@ -1553,7 +1572,7 @@ X_THREAD_PROC (etp_proc) ++idle; - ts.tv_sec = time (0) + IDLE_TIMEOUT; + ts.tv_sec = time (0) + idle_timeout; if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT) { if (idle > max_idle) @@ -241,6 +241,7 @@ void eio_set_max_poll_reqs (unsigned int nreqs); void eio_set_min_parallel (unsigned int nthreads); void eio_set_max_parallel (unsigned int nthreads); void eio_set_max_idle (unsigned int nthreads); +void eio_set_idle_timeout (unsigned int seconds); unsigned int eio_nreqs (void); /* number of requests in-flight */ unsigned int eio_nready (void); /* number of not-yet handled requests */ @@ -29,6 +29,7 @@ typedef int ssize_t; #include <windows.h> #include <pthread.h> #define sigset_t int +#define sigfillset(a) #define pthread_sigmask(a,b,c) #define sigaddset(a,b) #define sigemptyset(s) @@ -36,11 +37,13 @@ typedef int ssize_t; typedef pthread_mutex_t xmutex_t; #define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +#define X_MUTEX_CREATE(mutex) pthread_mutex_init (&(mutex), 0) #define X_LOCK(mutex) pthread_mutex_lock (&(mutex)) #define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) typedef pthread_cond_t xcond_t; #define X_COND_INIT PTHREAD_COND_INITIALIZER +#define X_COND_CREATE(cond) pthread_cond_init (&(cond), 0) #define X_COND_SIGNAL(cond) pthread_cond_signal (&(cond)) #define X_COND_WAIT(cond,mutex) pthread_cond_wait (&(cond), &(mutex)) #define X_COND_TIMEDWAIT(cond,mutex,to) pthread_cond_timedwait (&(cond), &(mutex), &(to)) @@ -95,18 +98,27 @@ thread_create (xthread_t *tid, void *(*proc)(void *), void *arg) typedef pthread_mutex_t xmutex_t; #if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) -# define X_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +# define X_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +# define X_MUTEX_CREATE(mutex) \ + do { \ + pthread_mutexattr_t attr; \ + pthread_mutexattr_init (&attr); \ + pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ADAPTIVE_NP); \ + pthread_mutex_init (&(mutex), &attr); \ + } while (0) #else -# define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +# define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER +# define X_MUTEX_CREATE(mutex) pthread_mutex_init (&(mutex), 0) #endif -#define X_LOCK(mutex) pthread_mutex_lock (&(mutex)) -#define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) +#define X_LOCK(mutex) pthread_mutex_lock (&(mutex)) +#define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) typedef pthread_cond_t xcond_t; -#define X_COND_INIT PTHREAD_COND_INITIALIZER -#define X_COND_SIGNAL(cond) pthread_cond_signal (&(cond)) -#define X_COND_WAIT(cond,mutex) pthread_cond_wait (&(cond), &(mutex)) -#define X_COND_TIMEDWAIT(cond,mutex,to) pthread_cond_timedwait (&(cond), &(mutex), &(to)) +#define X_COND_INIT PTHREAD_COND_INITIALIZER +#define X_COND_CREATE(cond) pthread_cond_init (&(cond), 0) +#define X_COND_SIGNAL(cond) pthread_cond_signal (&(cond)) +#define X_COND_WAIT(cond,mutex) pthread_cond_wait (&(cond), &(mutex)) +#define X_COND_TIMEDWAIT(cond,mutex,to) pthread_cond_timedwait (&(cond), &(mutex), &(to)) typedef pthread_t xthread_t; #define X_THREAD_PROC(name) static void *name (void *thr_arg) |