Date: Thu, 19 Feb 2004 09:28:50 +0300 From: Mike Makonnen <mtm@identd.net> To: freebsd-threads@freebsd.org Subject: libthr patch Message-ID: <20040219062850.GC1074@mobile.acs-et.com>
next in thread | raw e-mail | index | archive | help
--kXdP64Ggrk/fb43R Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hello folks, The following patch stops libthr from using signals for syncronizng threads. I've tested it localy and have seen *really large* performance improvements in heavy thread/mutex contention situations. I'm interested in hearing your experiences. P.S. - The patch to the kernel applies two new syscalls so you must regenerate some files *after* applying the patch. Do the following: cd /usr/src/sys/kern sh makesyscalls.sh syscalls.master cd /usr/src/sys/compat/freebsd32 sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf and then build your kernel in the usual way. Cheers. -- Mike Makonnen | GPG-KEY: http://www.identd.net/~mtm/mtm.asc mtm@identd.net | Fingerprint: AC7B 5672 2D11 F4D0 EBF8 5279 5359 2B82 7CD4 1F55 mtm@FreeBSD.Org| FreeBSD - Unleash the Daemon ! --kXdP64Ggrk/fb43R Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="diff.sys" Index: sys/compat/freebsd32/syscalls.master =================================================================== RCS file: /home/ncvs/src/sys/compat/freebsd32/syscalls.master,v retrieving revision 1.34 diff -u -r1.34 syscalls.master --- sys/compat/freebsd32/syscalls.master 3 Feb 2004 05:18:48 -0000 1.34 +++ sys/compat/freebsd32/syscalls.master 12 Feb 2004 14:03:47 -0000 @@ -604,3 +604,5 @@ 439 UNIMPL extattr_list_link 440 UNIMPL kse_switchin 441 UNIMPL ksem_timedwait +442 MNOPROTO { int thr_suspend(const struct timespec *timeout); } +443 MNOPROTO { int thr_wake(thr_id_t id); } Index: sys/kern/kern_thr.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_thr.c,v retrieving revision 1.14 diff -u -r1.14 kern_thr.c --- sys/kern/kern_thr.c 14 Aug 2003 03:56:24 -0000 1.14 +++ sys/kern/kern_thr.c 15 Feb 2004 06:46:08 -0000 @@ -254,3 +254,47 @@ PROC_UNLOCK(p); return (error); } + +int +thr_suspend(struct thread *td, struct thr_suspend_args *uap) + /* const struct timespec *timeout */ +{ + struct timespec ts; + struct timeval tv; + int error; + int hz; + + hz = 0; + error = 0; + if (uap->timeout != NULL) { + error = copyin((const void *)uap->timeout, (void *)&ts, + sizeof(struct timespec)); + if (error != 0) + return (error); + if (ts.tv_nsec < 0 || ts.tv_nsec > 1000000000) + return (EINVAL); + if (ts.tv_sec == 0 && ts.tv_nsec == 0) + return (ETIMEDOUT); + TIMESPEC_TO_TIMEVAL(&tv, &ts); + hz = tvtohz(&tv); + } + PROC_LOCK(td->td_proc); + if ((td->td_lthrflags & LTF_THRWAKEUP) == 0) { + error = msleep((void *)td, &td->td_proc->p_mtx, + td->td_priority | PCATCH, "lthr", hz); + td->td_lthrflags &= ~LTF_THRWAKEUP; + } + PROC_UNLOCK(td->td_proc); + return (error == EWOULDBLOCK ? ETIMEDOUT : error); +} + +int +thr_wake(struct thread *td, struct thr_wake_args *uap) + /* thr_id_t id */ +{ + PROC_LOCK(((struct thread *)uap->id)->td_proc); + ((struct thread *)uap->id)->td_lthrflags |= LTF_THRWAKEUP; + PROC_UNLOCK(((struct thread *)uap->id)->td_proc); + wakeup_one((void *)uap->id); + return (0); +} Index: sys/kern/syscalls.master =================================================================== RCS file: /home/ncvs/src/sys/kern/syscalls.master,v retrieving revision 1.166 diff -u -r1.166 syscalls.master --- sys/kern/syscalls.master 3 Feb 2004 05:08:32 -0000 1.166 +++ sys/kern/syscalls.master 12 Feb 2004 18:48:12 -0000 @@ -629,5 +629,7 @@ 440 MSTD { int kse_switchin(const struct __mcontext *mcp, \ long val, long *loc); } 441 MNOSTD { int ksem_timedwait(semid_t id, struct timespec *abstime); } +442 MSTD { int thr_suspend(const struct timespec *timeout); } +443 MSTD { int thr_wake(thr_id_t id); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master Index: sys/sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.367 diff -u -r1.367 proc.h --- sys/sys/proc.h 4 Feb 2004 21:52:56 -0000 1.367 +++ sys/sys/proc.h 12 Feb 2004 13:13:22 -0000 @@ -301,6 +301,7 @@ sigset_t td_siglist; /* (c) Sigs arrived, not delivered. */ sigset_t *td_waitset; /* (c) Wait set for sigwait. */ TAILQ_ENTRY(thread) td_umtx; /* (c?) Link for when we're blocked. */ + int td_lthrflags; /* (c) Libthr thread flags. */ volatile u_int td_generation; /* (k) Enable detection of preemption */ stack_t td_sigstk; /* (k) Stack ptr and on-stack flag. */ Index: sys/sys/thr.h =================================================================== RCS file: /home/ncvs/src/sys/sys/thr.h,v retrieving revision 1.1 diff -u -r1.1 thr.h --- sys/sys/thr.h 1 Apr 2003 00:30:30 -0000 1.1 +++ sys/sys/thr.h 17 Feb 2004 06:15:29 -0000 @@ -37,6 +37,10 @@ #define THR_SUSPENDED 0x0001 /* Create the thread in the suspended state. */ +/* flags stored in td_lthrflags member of the thread structure */ +#define LTF_THRWAKEUP 0x000001 /* Thread must not suspend itself */ +#define LTF_UMTXWAKEUP 0x000002 /* Thread must not suspend on a umtx */ + /* * See pthread_* */ @@ -46,6 +50,8 @@ int thr_self(thr_id_t *id); void thr_exit(void); int thr_kill(thr_id_t id, int sig); +int thr_suspend(const struct timespec *timeout); +int thr_wake(thr_id_t id); #endif /* !_KERNEL */ --kXdP64Ggrk/fb43R Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="diff.lib" Index: lib/libthr/thread/thr_cond.c =================================================================== RCS file: /home/ncvs/src/lib/libthr/thread/thr_cond.c,v retrieving revision 1.10 diff -u -r1.10 thr_cond.c --- lib/libthr/thread/thr_cond.c 9 Dec 2003 11:12:11 -0000 1.10 +++ lib/libthr/thread/thr_cond.c 15 Feb 2004 08:15:20 -0000 @@ -285,7 +285,7 @@ _thread_critical_exit(curthread); COND_UNLOCK(*cond); rval = _thread_suspend(curthread, (struct timespec *)abstime); - if (rval != 0 && rval != EAGAIN && rval != EINTR) { + if (rval != 0 && rval != ETIMEDOUT && rval != EINTR) { printf("foo"); fflush(stdout); abort(); Index: lib/libthr/thread/thr_kern.c =================================================================== RCS file: /home/ncvs/src/lib/libthr/thread/thr_kern.c,v retrieving revision 1.17 diff -u -r1.17 thr_kern.c --- lib/libthr/thread/thr_kern.c 29 Jan 2004 09:44:36 -0000 1.17 +++ lib/libthr/thread/thr_kern.c 15 Feb 2004 08:26:04 -0000 @@ -74,10 +74,6 @@ * Block all signals. */ SIGFILLSET(set); - SIGADDSET(set, SIGTHR); -#ifdef _PTHREADS_INVARIANTS - SIGDELSET(set, SIGABRT); -#endif SIGDELSET(set, SIGTRAP); /* If we have already blocked signals, just up the refcount */ @@ -121,7 +117,6 @@ { struct timespec remaining; struct timespec *ts; - siginfo_t info; int error; /* @@ -139,19 +134,12 @@ ts = &remaining; /* - * If the absolute timeout has already passed set the - * relative timeout to 0 sec. so that sigtimedwait() - * returns immediately. * NOTE: timespecsub() makes sure the tv_nsec member >= 0. */ - if (ts->tv_sec < 0) { - ts->tv_sec = 0; - ts->tv_nsec = 0; - } + if (ts->tv_sec < 0) + return (ETIMEDOUT); } else ts = NULL; - - error = sigtimedwait(&_thread_suspend_sigset, &info, ts); - error = (error == -1) ? errno : 0; - return (error); + error = thr_suspend(ts); + return (error == -1 ? errno : error); } Index: lib/libthr/thread/thr_mutex.c =================================================================== RCS file: /home/ncvs/src/lib/libthr/thread/thr_mutex.c,v retrieving revision 1.21 diff -u -r1.21 thr_mutex.c --- lib/libthr/thread/thr_mutex.c 19 Jan 2004 15:00:57 -0000 1.21 +++ lib/libthr/thread/thr_mutex.c 15 Feb 2004 08:16:53 -0000 @@ -1402,7 +1402,7 @@ _thread_critical_exit(curthread); _SPINUNLOCK(&mutexp->lock); error = _thread_suspend(curthread, abstime); - if (error != 0 && error != EAGAIN && error != EINTR) + if (error != 0 && error != ETIMEDOUT && error != EINTR) PANIC("Cannot suspend on mutex."); _SPINLOCK(&mutexp->lock); _thread_critical_enter(curthread); Index: lib/libthr/thread/thr_private.h =================================================================== RCS file: /home/ncvs/src/lib/libthr/thread/thr_private.h,v retrieving revision 1.30 diff -u -r1.30 thr_private.h --- lib/libthr/thread/thr_private.h 22 Jan 2004 15:31:56 -0000 1.30 +++ lib/libthr/thread/thr_private.h 12 Feb 2004 10:17:55 -0000 @@ -139,10 +139,8 @@ } while (0) #define PTHREAD_NEW_STATE(thrd, newstate) do { \ - if (newstate == PS_RUNNING) { \ - if (thr_kill(thrd->thr_id, SIGTHR)) \ - abort(); \ - } \ + if (newstate == PS_RUNNING) \ + thr_wake(thrd->thr_id); \ PTHREAD_SET_STATE(thrd, newstate); \ } while (0) Index: lib/libthr/thread/thr_resume_np.c =================================================================== RCS file: /home/ncvs/src/lib/libthr/thread/thr_resume_np.c,v retrieving revision 1.5 diff -u -r1.5 thr_resume_np.c --- lib/libthr/thread/thr_resume_np.c 12 Dec 2003 09:51:39 -0000 1.5 +++ lib/libthr/thread/thr_resume_np.c 12 Feb 2004 13:41:31 -0000 @@ -84,6 +84,5 @@ resume_common(struct pthread *thread) { thread->flags &= ~PTHREAD_FLAGS_SUSPENDED; - if (thr_kill(thread->thr_id, SIGTHR)) - abort(); + thr_wake(thread->thr_id); } --kXdP64Ggrk/fb43R--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040219062850.GC1074>