diff options
| author | Garrett D'Amore <garrett@damore.org> | 2016-12-22 13:22:18 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2016-12-22 13:22:18 -0800 |
| commit | ee969ad99dc1e07e1c38876223e7aed13463b121 (patch) | |
| tree | 40bde325d041532661e7dcc3441185aca7701e53 /src/platform | |
| parent | 6c1325a2b17548a4249d26a846bc32b95b7d747d (diff) | |
| download | nng-ee969ad99dc1e07e1c38876223e7aed13463b121.tar.gz nng-ee969ad99dc1e07e1c38876223e7aed13463b121.tar.bz2 nng-ee969ad99dc1e07e1c38876223e7aed13463b121.zip | |
Synchronization enhancements - inproc & msgqueue. Absolute waits...
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/posix/posix_alloc.c | 20 | ||||
| -rw-r--r-- | src/platform/posix/posix_clock.c | 88 | ||||
| -rw-r--r-- | src/platform/posix/posix_impl.h | 7 | ||||
| -rw-r--r-- | src/platform/posix/posix_synch.c | 120 | ||||
| -rw-r--r-- | src/platform/posix/posix_thread.c | 4 |
5 files changed, 113 insertions, 126 deletions
diff --git a/src/platform/posix/posix_alloc.c b/src/platform/posix/posix_alloc.c index eb5c889e..83fe305d 100644 --- a/src/platform/posix/posix_alloc.c +++ b/src/platform/posix/posix_alloc.c @@ -1,11 +1,11 @@ -/* - * Copyright 2016 Garrett D'Amore <garrett@damore.org> - * - * This software is supplied under the terms of the MIT License, a - * copy of which should be located in the distribution where this - * file was obtained (LICENSE.txt). A copy of the license may also be - * found online at https://opensource.org/licenses/MIT. - */ +// +// Copyright 2016 Garrett D'Amore <garrett@damore.org> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// #include "core/nng_impl.h" @@ -13,9 +13,7 @@ #include <stdlib.h> -/* - * POSIX memory allocation. This is pretty much standard C. - */ +// POSIX memory allocation. This is pretty much standard C. void * nni_alloc(size_t size) { diff --git a/src/platform/posix/posix_clock.c b/src/platform/posix/posix_clock.c index 83f0b151..48a1e09b 100644 --- a/src/platform/posix/posix_clock.c +++ b/src/platform/posix/posix_clock.c @@ -1,15 +1,13 @@ -/* - * Copyright 2016 Garrett D'Amore <garrett@damore.org> - * - * This software is supplied under the terms of the MIT License, a - * copy of which should be located in the distribution where this - * file was obtained (LICENSE.txt). A copy of the license may also be - * found online at https://opensource.org/licenses/MIT. - */ - -/* - * POSIX clock stuff. - */ +// +// Copyright 2016 Garrett D'Amore <garrett@damore.org> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// POSIX clock stuff. #include "core/nng_impl.h" #ifdef PLATFORM_POSIX_CLOCK @@ -20,9 +18,7 @@ #ifndef NNG_USE_GETTIMEOFDAY -/* - * Use POSIX realtime stuff. - */ +// Use POSIX realtime stuff uint64_t nni_clock(void) { @@ -56,18 +52,16 @@ nni_usleep(uint64_t usec) } -#else /* NNG_USE_GETTIMEOFDAY */ +#else // NNG_USE_GETTIMEOFDAY -/* - * If you're here, its because you don't have a modern clock_gettime with - * monotonic clocks, or the necessary pthread_condattr_settclock(). In - * this case, you should be advised that *bad* things can happen if your - * system clock changes time while programs using this library are running. - * (Basically, timeouts can take longer or shorter, leading to either hangs - * or apparent spurious errors. Eventually it should all sort itself out, - * but if you change the clock by a large amount you might wonder what the - * heck is happening until it does.) - */ +// If you're here, its because you don't have a modern clock_gettime with +// monotonic clocks, or the necessary pthread_condattr_settclock(). In +// this case, you should be advised that *bad* things can happen if your +// system clock changes time while programs using this library are running. +// (Basically, timeouts can take longer or shorter, leading to either hangs +// or apparent spurious errors. Eventually it should all sort itself out, +// but if you change the clock by a large amount you might wonder what the +// heck is happening until it does.) #include <pthread.h> #include <sys/time.h> @@ -94,25 +88,21 @@ nni_clock(void) void nni_usleep(uint64_t usec) { - /* - * So probably there is no nanosleep. We could in theory use - * pthread condition variables, but that means doing memory - * allocation, or forcing the use of pthreads where the platform - * might be preferring the use of another threading package. - * Additionally, use of pthreads means that we cannot use - * relative times in a clock_settime safe manner. - * So we can use poll() instead, which is rather coarse, but - * pretty much guaranteed to work. - */ + // So probably there is no nanosleep. We could in theory use + // pthread condition variables, but that means doing memory + // allocation, or forcing the use of pthreads where the platform + // might be preferring the use of another threading package. + // Additionally, use of pthreads means that we cannot use + // relative times in a clock_settime safe manner. + // So we can use poll() instead, which is rather coarse, but + // pretty much guaranteed to work. struct pollfd pfd; uint64_t now; uint64_t expire; - /* - * Possibly we could pass NULL instead of pfd, but passing a valid - * pointer ensures that if the system dereferences the pointer it - * won't come back with EFAULT. - */ + // Possibly we could pass NULL instead of pfd, but passing a valid + // pointer ensures that if the system dereferences the pointer it + // won't come back with EFAULT. pfd.fd = -1; pfd.events = 0; @@ -120,19 +110,17 @@ nni_usleep(uint64_t usec) expire = now + usec; while (now < expire) { - /* - * In theory we could round up to a whole number of msec, - * but under the covers poll already does some rounding up, - * and the loop above guarantees that we will not bail out - * early. So this gives us a better chance to avoid adding - * nearly an extra unneeded millisecond to the wait. - */ + // In theory we could round up to a whole number of msec, + // but under the covers poll already does some rounding up, + // and the loop above guarantees that we will not bail out + // early. So this gives us a better chance to avoid adding + // nearly an extra unneeded millisecond to the wait. (void) poll(&pfd, 0, (int) ((expire - now) / 1000)); now = nni_clock(); } } -#endif /* NNG_USE_GETTIMEOFDAY */ +#endif // NNG_USE_GETTIMEOFDAY -#endif /* PLATFORM_POSIX_CLOCK */ +#endif // PLATFORM_POSIX_CLOCK diff --git a/src/platform/posix/posix_impl.h b/src/platform/posix/posix_impl.h index a7b15edc..4f93b101 100644 --- a/src/platform/posix/posix_impl.h +++ b/src/platform/posix/posix_impl.h @@ -10,6 +10,13 @@ #ifndef PLATFORM_POSIX_IMPL_H #define PLATFORM_POSIX_IMPL_H +// Some dependency notes: +// +// PLATFORM_POSIX_THREAD and PLATFORM_POSIX_SYNCH depend on each other, +// and they both depend on PLATFORM_POSIX_CLOCK. Furthermore, note that +// when using PLATFORM_POSIX_CLOCK, your condition variable timeouts need +// to use the same base clock values. Normally all three should be used +// together. #ifdef PLATFORM_POSIX #define PLATFORM_POSIX_ALLOC #define PLATFORM_POSIX_DEBUG diff --git a/src/platform/posix/posix_synch.c b/src/platform/posix/posix_synch.c index a3129f62..c0a2721c 100644 --- a/src/platform/posix/posix_synch.c +++ b/src/platform/posix/posix_synch.c @@ -1,23 +1,14 @@ -/* - * Copyright 2016 Garrett D'Amore <garrett@damore.org> - * - * This software is supplied under the terms of the MIT License, a - * copy of which should be located in the distribution where this - * file was obtained (LICENSE.txt). A copy of the license may also be - * found online at https://opensource.org/licenses/MIT. - */ - -/* - * This is more of a direct #include of a .c rather than .h file. - * But having it be a .h makes compiler rules work out properly. Do - * not include this more than once into your program, or you will - * get multiple symbols defined. - */ - -/* - * POSIX synchronization (mutexes and condition variables). This uses - * pthreads. - */ +// +// Copyright 2016 Garrett D'Amore <garrett@damore.org> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// POSIX synchronization (mutexes and condition variables). This uses +// pthreads. #include "core/nng_impl.h" @@ -51,6 +42,7 @@ nni_mutex_fini(nni_mutex *mp) } +// XXX: REMOVE THIS FUNCTION int nni_mutex_create(nni_mutex_t *mp) { @@ -62,7 +54,7 @@ nni_mutex_create(nni_mutex_t *mp) return (NNG_ENOMEM); } - /* We ask for more error checking... */ + // We ask for more error checking... if (pthread_mutexattr_init(&attr) != 0) { nni_free(m, sizeof (*m)); return (NNG_ENOMEM); @@ -87,6 +79,7 @@ nni_mutex_create(nni_mutex_t *mp) } +// XXX: REMOVE THIS FUNCTION void nni_mutex_destroy(nni_mutex_t m) { @@ -98,7 +91,7 @@ nni_mutex_destroy(nni_mutex_t m) void -nni_mutex_enter(nni_mutex_t m) +nni_mutex_enter(nni_mutex *m) { if (pthread_mutex_lock(&m->mx) != 0) { nni_panic("pthread_mutex_lock failed"); @@ -107,7 +100,7 @@ nni_mutex_enter(nni_mutex_t m) void -nni_mutex_exit(nni_mutex_t m) +nni_mutex_exit(nni_mutex *m) { if (pthread_mutex_unlock(&m->mx) != 0) { nni_panic("pthread_mutex_unlock failed"); @@ -116,7 +109,7 @@ nni_mutex_exit(nni_mutex_t m) int -nni_mutex_tryenter(nni_mutex_t m) +nni_mutex_tryenter(nni_mutex *m) { if (pthread_mutex_trylock(&m->mx) != 0) { return (NNG_EBUSY); @@ -125,51 +118,40 @@ nni_mutex_tryenter(nni_mutex_t m) } -static int -nni_cond_attr(pthread_condattr_t **attrpp) +int +nni_cond_init(nni_cond *c, nni_mutex *m) { -#if defined(NNG_USE_GETTIMEOFDAY) || NNG_USE_CLOCKID == CLOCK_REALTIME - *attrpp = NULL; + if (pthread_cond_init(&c->cv, &nni_condattr) != 0) { + // In theory could be EAGAIN, but handle like ENOMEM + nni_free(c, sizeof (*c)); + return (NNG_ENOMEM); + } + c->mx = &m->mx; return (0); +} -#else - /* In order to make this fast, avoid reinitializing attrs. */ - static pthread_condattr_t attr; - static pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; - static int init = 0; - int rv; - // For efficiency's sake, we try to reuse the same attr for the - // life of the library. This avoids many reallocations. Technically - // this means that we will leak the attr on exit(), but this is - // preferable to constantly allocating and reallocating it. - if (init) { - *attrpp = &attr; - return (0); +void +nni_cond_fini(nni_cond *c) +{ + if (pthread_cond_destroy(&c->cv) != 0) { + nni_panic("pthread_cond_destroy failed"); } +} - (void) pthread_mutex_lock(&mx); - while (!init) { - if ((rv = pthread_condattr_init(&attr)) != 0) { - (void) pthread_mutex_unlock(&mx); - return (NNG_ENOMEM); - } - rv = pthread_condattr_setclock(&attr, NNG_USE_CLOCKID); - if (rv != 0) { - nni_panic("condattr_setclock: %s", strerror(rv)); - } - init = 1; - } - (void) pthread_mutex_unlock(&mx); - *attrpp = &attr; - return (0); -#endif +// XXXX: REMOVE THIS FUNCTION +static int +nni_cond_attr(pthread_condattr_t **attrpp) +{ + *attrpp = NULL; + return (0); } +// XXX: REMOVE THIS FUNCTION int -nni_cond_create(nni_cond_t *cvp, nni_mutex_t mx) +nni_cond_create(nni_cond **cvp, nni_mutex *mx) { /* * By preference, we use a CLOCK_MONOTONIC version of condition @@ -196,8 +178,9 @@ nni_cond_create(nni_cond_t *cvp, nni_mutex_t mx) } +// XXX: REMOVE THIS FUNCTION void -nni_cond_destroy(nni_cond_t c) +nni_cond_destroy(nni_cond *c) { if (pthread_cond_destroy(&c->cv) != 0) { nni_panic("pthread_cond_destroy failed"); @@ -207,7 +190,7 @@ nni_cond_destroy(nni_cond_t c) void -nni_cond_signal(nni_cond_t c) +nni_cond_signal(nni_cond *c) { if (pthread_cond_signal(&c->cv) != 0) { nni_panic("pthread_cond_signal failed"); @@ -216,7 +199,7 @@ nni_cond_signal(nni_cond_t c) void -nni_cond_broadcast(nni_cond_t c) +nni_cond_broadcast(nni_cond *c) { if (pthread_cond_broadcast(&c->cv) != 0) { nni_panic("pthread_cond_broadcast failed"); @@ -225,7 +208,7 @@ nni_cond_broadcast(nni_cond_t c) void -nni_cond_wait(nni_cond_t c) +nni_cond_wait(nni_cond *c) { if (pthread_cond_wait(&c->cv, c->mx) != 0) { nni_panic("pthread_cond_wait failed"); @@ -234,7 +217,7 @@ nni_cond_wait(nni_cond_t c) int -nni_cond_timedwait(nni_cond_t c, uint64_t usec) +nni_cond_waituntil(nni_cond *c, uint64_t usec) { struct timespec ts; int rv; @@ -255,4 +238,15 @@ nni_cond_timedwait(nni_cond_t c, uint64_t usec) } +int +nni_cond_timedwait(nni_cond *c, int usec) +{ + if (usec < 0) { + nni_cond_wait(c); + return (0); + } + return (nni_cond_waituntil(c, ((uint64_t) usec) + nni_clock())); +} + + #endif diff --git a/src/platform/posix/posix_thread.c b/src/platform/posix/posix_thread.c index 1bbe6e28..79f69762 100644 --- a/src/platform/posix/posix_thread.c +++ b/src/platform/posix/posix_thread.c @@ -28,7 +28,7 @@ static int plat_init = 0; static int plat_fork = 0; static void * -thrfunc(void *arg) +nni_thrfunc(void *arg) { nni_thread_t thr = arg; @@ -49,7 +49,7 @@ nni_thread_create(nni_thread_t *tp, void (*fn)(void *), void *arg) thr->func = fn; thr->arg = arg; - if ((rv = pthread_create(&thr->tid, NULL, thrfunc, thr)) != 0) { + if ((rv = pthread_create(&thr->tid, NULL, nni_thrfunc, thr)) != 0) { nni_free(thr, sizeof (*thr)); return (NNG_ENOMEM); } |
