Module Name:    src
Committed By:   matt
Date:           Tue Dec 27 16:35:14 UTC 2011

Modified Files:
        src/sys/kern [matt-nb5-mips64]: init_main.c kern_kthread.c
        src/sys/sys [matt-nb5-mips64]: kthread.h lwp.h

Log Message:
Backport joinable kthread support (for flash infrastructure).


To generate a diff of this commit:
cvs rdiff -u -r1.371.2.3.4.1 -r1.371.2.3.4.2 src/sys/kern/init_main.c
cvs rdiff -u -r1.24.10.2 -r1.24.10.2.4.1 src/sys/kern/kern_kthread.c
cvs rdiff -u -r1.7.10.1 -r1.7.10.1.4.1 src/sys/sys/kthread.h
cvs rdiff -u -r1.114.4.1.4.3 -r1.114.4.1.4.4 src/sys/sys/lwp.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/init_main.c
diff -u src/sys/kern/init_main.c:1.371.2.3.4.1 src/sys/kern/init_main.c:1.371.2.3.4.2
--- src/sys/kern/init_main.c:1.371.2.3.4.1	Wed Apr 21 00:28:15 2010
+++ src/sys/kern/init_main.c	Tue Dec 27 16:35:13 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: init_main.c,v 1.371.2.3.4.1 2010/04/21 00:28:15 matt Exp $	*/
+/*	$NetBSD: init_main.c,v 1.371.2.3.4.2 2011/12/27 16:35:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.371.2.3.4.1 2010/04/21 00:28:15 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.371.2.3.4.2 2011/12/27 16:35:13 matt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_ipsec.h"
@@ -295,6 +295,7 @@ main(void)
 	kernel_lock_init();
 	once_init();
 	mutex_init(&cpu_lock, MUTEX_DEFAULT, IPL_NONE);
+	kthread_sysinit();
 
 	uvm_init();
 
@@ -477,6 +478,11 @@ main(void)
 	shminit();
 #endif
 
+	vmem_rehash_start();	/* must be before exec_init */
+
+	/* Initialize exec structures */
+	exec_init(1);		/* seminit calls exithook_establish() */
+
 #ifdef SYSVSEM
 	/* Initialize System V style semaphores. */
 	seminit();
@@ -661,11 +667,6 @@ main(void)
 	    uvm_aiodone_worker, NULL, PRI_VM, IPL_NONE, WQ_MPSAFE))
 		panic("fork aiodoned");
 
-	vmem_rehash_start();
-
-	/* Initialize exec structures */
-	exec_init(1);
-
 	/*
 	 * Okay, now we can let init(8) exec!  It's off to userland!
 	 */

Index: src/sys/kern/kern_kthread.c
diff -u src/sys/kern/kern_kthread.c:1.24.10.2 src/sys/kern/kern_kthread.c:1.24.10.2.4.1
--- src/sys/kern/kern_kthread.c:1.24.10.2	Mon Feb  2 22:02:24 2009
+++ src/sys/kern/kern_kthread.c	Tue Dec 27 16:35:13 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_kthread.c,v 1.24.10.2 2009/02/02 22:02:24 snj Exp $	*/
+/*	$NetBSD: kern_kthread.c,v 1.24.10.2.4.1 2011/12/27 16:35:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc.
@@ -31,39 +31,46 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.24.10.2 2009/02/02 22:02:24 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.24.10.2.4.1 2011/12/27 16:35:13 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
-#include <sys/proc.h>
+#include <sys/mutex.h>
 #include <sys/sched.h>
 #include <sys/kmem.h>
 
 #include <uvm/uvm_extern.h>
-
-/*
- * note that stdarg.h and the ansi style va_start macro is used for both
- * ansi and traditional c complers.
- * XXX: this requires that stdarg.h define: va_alist and va_dcl
- */
 #include <machine/stdarg.h>
 
+static lwp_t *		kthread_jtarget;
+static kmutex_t		kthread_lock;
+static kcondvar_t	kthread_cv;
+
+void
+kthread_sysinit(void)
+{
+
+	mutex_init(&kthread_lock, MUTEX_DEFAULT, IPL_NONE);
+	cv_init(&kthread_cv, "kthrwait");
+	kthread_jtarget = NULL;
+}
+
 /*
- * Fork a kernel thread.  Any process can request this to be done.
+ * kthread_create: create a kernel thread, that is, system-only LWP.
  */
 int
 kthread_create(pri_t pri, int flag, struct cpu_info *ci,
-	       void (*func)(void *), void *arg,
-	       lwp_t **lp, const char *fmt, ...)
+    void (*func)(void *), void *arg, lwp_t **lp, const char *fmt, ...)
 {
 	lwp_t *l;
 	vaddr_t uaddr;
 	bool inmem;
-	int error;
+	int error, lc;
 	va_list ap;
-	int lc;
+
+	KASSERT((flag & KTHREAD_INTR) == 0 || (flag & KTHREAD_MPSAFE) != 0);
 
 	inmem = uvm_uarea_alloc(&uaddr);
 	if (uaddr == 0)
@@ -83,7 +90,7 @@ kthread_create(pri_t pri, int flag, stru
 	if (fmt != NULL) {
 		l->l_name = kmem_alloc(MAXCOMLEN, KM_SLEEP);
 		if (l->l_name == NULL) {
-			lwp_exit(l);
+			kthread_destroy(l);
 			return ENOMEM;
 		}
 		va_start(ap, fmt);
@@ -94,10 +101,6 @@ kthread_create(pri_t pri, int flag, stru
 	/*
 	 * Set parameters.
 	 */
-	if ((flag & KTHREAD_INTR) != 0) {
-		KASSERT((flag & KTHREAD_MPSAFE) != 0);
-	}
-
 	if (pri == PRI_NONE) {
 		if ((flag & KTHREAD_TS) != 0) {
 			/* Maximum user priority level. */
@@ -118,10 +121,17 @@ kthread_create(pri_t pri, int flag, stru
 		l->l_pflag |= LP_BOUND;
 		l->l_cpu = ci;
 	}
-	if ((flag & KTHREAD_INTR) != 0)
+
+	if ((flag & KTHREAD_JOINABLE) != 0) {
+		KASSERT(lp != NULL);
+		l->l_pflag |= LP_JOINABLE;
+	}
+	if ((flag & KTHREAD_INTR) != 0) {
 		l->l_pflag |= LP_INTR;
-	if ((flag & KTHREAD_MPSAFE) == 0)
+	}
+	if ((flag & KTHREAD_MPSAFE) == 0) {
 		l->l_pflag &= ~LP_MPSAFE;
+	}
 
 	/*
 	 * Set the new LWP running, unless the caller has requested
@@ -142,10 +152,10 @@ kthread_create(pri_t pri, int flag, stru
 	mutex_exit(proc0.p_lock);
 
 	/* All done! */
-	if (lp != NULL)
+	if (lp != NULL) {
 		*lp = l;
-
-	return (0);
+	}
+	return 0;
 }
 
 /*
@@ -166,15 +176,20 @@ kthread_exit(int ecode)
 		    name, l->l_lid, ecode);
 	}
 
+	/* Barrier for joining. */
+	if (l->l_pflag & LP_JOINABLE) {
+		mutex_enter(&kthread_lock);
+		while (kthread_jtarget != l) {
+			cv_wait(&kthread_cv, &kthread_lock);
+		}
+		kthread_jtarget = NULL;
+		cv_broadcast(&kthread_cv);
+		mutex_exit(&kthread_lock);
+	}
+
 	/* And exit.. */
 	lwp_exit(l);
-
-	/*
-	 * XXX Fool the compiler.  Making exit1() __noreturn__ is a can
-	 * XXX of worms right now.
-	 */
-	for (;;)
-		;
+	KASSERT(false);
 }
 
 /*
@@ -189,3 +204,31 @@ kthread_destroy(lwp_t *l)
 
 	lwp_exit(l);
 }
+
+/*
+ * Wait for a kthread to exit, as pthread_join().
+ */
+int
+kthread_join(lwp_t *l)
+{
+
+	KASSERT((l->l_flag & LW_SYSTEM) != 0);
+
+	/*
+	 * - Wait if some other thread has occupied the target.
+	 * - Speicfy our kthread as a target and notify it.
+	 * - Wait for the target kthread to notify us.
+	 */
+	mutex_enter(&kthread_lock);
+	while (kthread_jtarget) {
+		cv_wait(&kthread_cv, &kthread_lock);
+	}
+	kthread_jtarget = l;
+	cv_broadcast(&kthread_cv);
+	while (kthread_jtarget == l) {
+		cv_wait(&kthread_cv, &kthread_lock);
+	}
+	mutex_exit(&kthread_lock);
+
+	return 0;
+}

Index: src/sys/sys/kthread.h
diff -u src/sys/sys/kthread.h:1.7.10.1 src/sys/sys/kthread.h:1.7.10.1.4.1
--- src/sys/sys/kthread.h:1.7.10.1	Mon Feb  2 22:01:34 2009
+++ src/sys/sys/kthread.h	Tue Dec 27 16:35:13 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: kthread.h,v 1.7.10.1 2009/02/02 22:01:34 snj Exp $	*/
+/*	$NetBSD: kthread.h,v 1.7.10.1.4.1 2011/12/27 16:35:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2009 The NetBSD Foundation, Inc.
@@ -33,17 +33,23 @@
 #ifndef _SYS_KTHREAD_H_
 #define	_SYS_KTHREAD_H_
 
+#if !defined(_KERNEL)
+#error "not supposed to be exposed to userland"
+#endif
+
 /*
  * Kernel thread handling.
  */
 
-#ifdef _KERNEL
 #include <sys/proc.h>
 
-#define	KTHREAD_IDLE	0x01	/* do not set runnable */
-#define	KTHREAD_MPSAFE	0x02	/* does not need kernel_lock */
-#define	KTHREAD_INTR	0x04	/* interrupt handler */
-#define	KTHREAD_TS	0x08	/* timeshared */
+#define	KTHREAD_IDLE		0x01	/* Do not run on creation */
+#define	KTHREAD_MPSAFE		0x02	/* Do not acquire kernel_lock */
+#define	KTHREAD_INTR		0x04	/* Software interrupt handler */
+#define	KTHREAD_TS		0x08	/* Time-sharing priority range */
+#define	KTHREAD_JOINABLE	0x10	/* Joinable */
+
+void	kthread_sysinit(void);
 
 int	kthread_create(pri_t, int, struct cpu_info *,
 		       void (*)(void *), void *,
@@ -51,6 +57,6 @@ int	kthread_create(pri_t, int, struct cp
 	    __attribute__((__format__(__printf__,7,8)));
 void	kthread_exit(int) __dead;
 void	kthread_destroy(lwp_t *);
-#endif /* _KERNEL */
+int	kthread_join(lwp_t *);
 
 #endif /* _SYS_KTHREAD_H_ */

Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.114.4.1.4.3 src/sys/sys/lwp.h:1.114.4.1.4.4
--- src/sys/sys/lwp.h:1.114.4.1.4.3	Fri Apr 29 08:20:15 2011
+++ src/sys/sys/lwp.h	Tue Dec 27 16:35:13 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: lwp.h,v 1.114.4.1.4.3 2011/04/29 08:20:15 matt Exp $	*/
+/*	$NetBSD: lwp.h,v 1.114.4.1.4.4 2011/12/27 16:35:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -194,6 +194,14 @@ struct lwp {
 #define	UAREA_TO_USER(uarea)	((struct user *)((uarea) + UAREA_USER_OFFSET))
 #endif /* !defined(UAREA_TO_USER) */
 
+#ifdef _KERNEL
+static inline void *
+lwp_getpcb(lwp_t *l)
+{
+	return l->l_addr;
+}
+#endif
+
 LIST_HEAD(lwplist, lwp);		/* a list of LWPs */
 
 #ifdef _KERNEL
@@ -203,13 +211,6 @@ extern struct lwplist alllwp;		/* List o
 extern struct pool lwp_uc_pool;		/* memory pool for LWP startup args */
 
 extern lwp_t lwp0;			/* LWP for proc0 */
-
-static inline void *
-lwp_getpcb(lwp_t *l)
-{
-
-	return l->l_addr;
-}
 #endif
 
 /* These flags are kept in l_flag. */
@@ -242,6 +243,7 @@ lwp_getpcb(lwp_t *l)
 #define	LP_MPSAFE	0x00000020 /* Starts life without kernel_lock */
 #define	LP_INTR		0x00000040 /* Soft interrupt handler */
 #define	LP_SYSCTLWRITE	0x00000080 /* sysctl write lock held */
+#define	LP_JOINABLE	0x00000100 /* Joinable kthread */
 #define	LP_SA_PAGEFAULT	0x00000200 /* SA LWP in pagefault handler */
 #define	LP_SA_NOBLOCK	0x00000400 /* SA don't upcall on block */
 #define	LP_TIMEINTR	0x00010000 /* Time this soft interrupt */

Reply via email to