Skip site navigation (1)Skip section navigation (2)
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>