libthr patch
Mike Makonnen
mtm at identd.net
Wed Feb 18 22:30:13 PST 2004
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 at identd.net | Fingerprint: AC7B 5672 2D11 F4D0 EBF8 5279 5359 2B82 7CD4 1F55
mtm at FreeBSD.Org| FreeBSD - Unleash the Daemon !
-------------- next part --------------
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 */
-------------- next part --------------
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);
}
More information about the freebsd-threads
mailing list