diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-06-21 03:34:36 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-06-25 22:07:42 +0000 |
commit | e12e70b6bd242cb3fea74d1df8b7b44e0a9f7f26 (patch) | |
tree | 49f915d77028ae98852243efed2ab3c7c8323660 | |
parent | a18a08a0e9a7c472656afc86cbbbfcefda5e456d (diff) | |
download | cmogstored-e12e70b6bd242cb3fea74d1df8b7b44e0a9f7f26.tar.gz |
While pthread_yield is non-standard, it is relatively common and preferable for systems where pthreads are _not_ 1:1 mapped to kernel threads. This also provides a stronger yield to weaken the priority of the calling thread wherever we previously used sched_yield.
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | cmogstored.h | 3 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | fdmap.c | 2 | ||||
-rw-r--r-- | mnt.c | 2 | ||||
-rw-r--r-- | thrpool.c | 22 | ||||
-rw-r--r-- | yield.c | 29 |
7 files changed, 40 insertions, 22 deletions
diff --git a/Makefile.am b/Makefile.am index 918200c..dd1e9e3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -92,6 +92,7 @@ mog_src += trace.h mog_src += trywrite.c mog_src += util.h mog_src += upgrade.c +mog_src += yield.c LDADD = $(LIBINTL) $(top_builddir)/lib/libgnu.a libnostd.a noinst_LIBRARIES = libnostd.a diff --git a/cmogstored.h b/cmogstored.h index 580de8d..e6975c3 100644 --- a/cmogstored.h +++ b/cmogstored.h @@ -596,3 +596,6 @@ struct mog_ni { /* nameinfo.c */ void mog_nameinfo(struct mog_packaddr *, struct mog_ni *); + +/* yield.c */ +void mog_yield(void); diff --git a/configure.ac b/configure.ac index 8a9e6d1..5cfdc9b 100644 --- a/configure.ac +++ b/configure.ac @@ -45,6 +45,9 @@ AC_CHECK_FUNCS([sendfile]) AC_CHECK_FUNCS([open_memstream]) AC_CHECK_FUNCS([posix_fadvise]) +dnl non-standard, but common +AC_CHECK_FUNCS([pthread_yield]) + dnl gnulib doesn't actually define SOCK_NONBLOCK/SOCK_CLOEXEC, and dnl even if it did, emulation wouldn't be thread-safe AC_CHECK_FUNCS([accept4]) @@ -300,7 +300,7 @@ out: * 4) close sockets. */ for (fd = (int)expired * 8; --fd >= 0; ) - sched_yield(); + mog_yield(); return expired; } @@ -163,7 +163,7 @@ static void timed_init_once(void) if ((++tries % 1024) == 0) warn("pthread_create: %s (tries: %lu)", strerror(rc), tries); - sched_yield(); + mog_yield(); } else { assert(0 && "pthread_create usage error"); } @@ -67,24 +67,6 @@ void mog_thr_test_quit(void) } /* - * sched_yield may migrate us to the same CPU as the task we're waiting - * on, so just keep yielding for every CPU we have as this throttles - * our ability to spam SIGURG. This means the threads we're trying to - * gracefully kill off can finish their work and check their mog_do_quit - * flag sooner - */ -static void yield_all(void) -{ - static unsigned long nproc_all; - unsigned long i; - - if (!nproc_all) - nproc_all = num_processors(NPROC_ALL) * 2; - for (i = 0; i < nproc_all; i++) - pthread_yield(); -} - -/* * we no longer rely on pthreads cancellation, so our explicit checks for * thread quitting requires us to continuously signal a thread for death * in case it enters a sleeping syscall (epoll_wait/kevent) immediately @@ -99,7 +81,7 @@ static void poke(pthread_t thr, int sig) * we lower thread counts or shut down */ while ((err = pthread_kill(thr, sig)) == 0) - yield_all(); + mog_yield(); assert(err == ESRCH && "pthread_kill() usage bug"); } @@ -115,7 +97,7 @@ thr_create_fail_retry(struct mog_thrpool *tp, size_t size, syslog(LOG_ERR, "pthread_create: %m (tries: %lu)", *nr_eagain); } - yield_all(); + mog_yield(); return true; } else { errno = err; @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> + * License: GPLv3 or later (see COPYING for details) + */ +#include "cmogstored.h" +#ifndef HAVE_PTHREAD_YIELD +# define pthread_yield() (void)sched_yield() +#endif + +/* + * pthread_yield may migrate us to the same CPU as the task we're waiting + * on, so just keep yielding for every CPU we have as this throttles + * our ability to spam SIGURG. This means the threads we're trying to + * gracefully kill off can finish their work and check their mog_do_quit + * flag sooner + * + * We only use this as a last resort when normal wakeups/notifications + * are not usable (e.g. recovering from out-of-resource problems) + */ +void mog_yield(void) +{ + static unsigned long nproc_all; + unsigned long i; + + if (!nproc_all) + nproc_all = num_processors(NPROC_ALL) * 2; + for (i = 0; i < nproc_all; i++) + pthread_yield(); +} |