Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Sep 2002 03:41:30 -0700 (PDT)
From:      Jonathan Mini <mini@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 17036 for review
Message-ID:  <200209041041.g84AfU1q017939@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=17036

Change 17036 by mini@mini_stylus on 2002/09/04 03:41:30

	- Convert back from a ucontext_t for UTS context in the
	  kse_mailbox to a function pointer and a stack_t. 
	- Synthesize machine state from scratch on each upcall, but
	  only set up the minimum amount of state.
	- Discard the UTS state in kse_yield().
	- Use a custom MI wrapper function to handle the user context
	  switch into a thread from the UTS.
	- Once again, only kse_mailbox.ke_curthread acts as a
	  critical section marker.
	- Move tm_context and km_curthread to the top of their
	  structs, because it makes the assembly less messy when
	  switching user contexts.
	- The UTS is now a run-once-per-upcall flow, instead of a
	  loop around swapcontext().
	- Clarify a few comments.

Affected files ...

.. //depot/projects/kse/sys/i386/i386/vm_machdep.c#64 edit
.. //depot/projects/kse/sys/kern/kern_proc.c#81 edit
.. //depot/projects/kse/sys/kern/kern_thread.c#100 edit
.. //depot/projects/kse/sys/sys/kse.h#18 edit
.. //depot/projects/kse/sys/sys/proc.h#126 edit
.. //depot/projects/kse/tools/KSE/uts/Makefile#2 edit
.. //depot/projects/kse/tools/KSE/uts/context.S#1 add
.. //depot/projects/kse/tools/KSE/uts/uts.c#6 edit

Differences ...

==== //depot/projects/kse/sys/i386/i386/vm_machdep.c#64 (text+ko) ====

@@ -368,6 +368,30 @@
 	 pcb2->pcb_ext = NULL;
 }
 
+/*
+ * Set the machine state for performing an upcall that had to
+ * wait until we selected a KSE to perform the upcall on.
+ */
+void
+cpu_set_upcall_kse(struct thread *td, struct kse *ke)
+{
+
+	/*
+	 * Set the trap frame to point at the beginning of the uts
+	 * function.
+	 */
+	td->td_frame->tf_esp =
+	    (int)ke->ke_stack.ss_sp + ke->ke_stack.ss_size - 16;
+	td->td_frame->tf_eip = (int)ke->ke_upcall;
+
+	/*
+	 * Pass the address of the mailbox for this kse to the uts
+	 * function as a parameter on the stack.
+	 */
+	suword((void *)(td->td_frame->tf_esp + sizeof(void *)),
+	    (int)ke->ke_mailbox);
+}
+
 void
 cpu_wait(p)
 	struct proc *p;

==== //depot/projects/kse/sys/kern/kern_proc.c#81 (text+ko) ====

@@ -279,22 +279,6 @@
 int
 kse_yield(struct thread *td, struct kse_yield_args *uap)
 {
-	int error;
-	ucontext_t uc;
-	struct kse *ke;
-
-	/* Save UTS context. */
-	ke = td->td_kse;
-	if (ke == NULL)
-		return (EFAULT);
-	error = copyin(&ke->ke_mailbox->km_context, &uc, sizeof(ucontext_t));
-	if (error)
-		return (error);
-	thread_getcontext(td, &uc);
-	uc.uc_busy = 0;
-	error = copyout(&uc, &ke->ke_mailbox->km_context, sizeof(ucontext_t));
-	if (error)
-		return (error);
 
 	/* Abandon thread. */
 	PROC_LOCK(td->td_proc);
@@ -363,6 +347,8 @@
 	mi_switch();	/* Save current registers to PCB. */
 	mtx_unlock_spin(&sched_lock);
 	newkse->ke_mailbox = uap->mbx;
+	newkse->ke_upcall = mbx.km_func;
+	bcopy(&mbx.km_stack, &newkse->ke_stack, sizeof(stack_t));
 	/* Note that we are the returning syscall */
 	td->td_retval[0] = 0;
 	td->td_retval[1] = 0;

==== //depot/projects/kse/sys/kern/kern_thread.c#100 (text+ko) ====

@@ -549,16 +549,6 @@
 		 */
 		discard = 1;
 
-	/* Make sure the KSE's UTS context is free for use. */
-	if (fuword(&ke->ke_mailbox->km_context.uc_busy) != 0)
-		/*
-		 * The KSE's UTS context is currently marked busy. This
-		 * means the UTS is currently running, so switch to it
-		 * instead of performing another upcall (abandon this
-		 * thread).
-		 */
-		discard = 1;
-
 	/* Discard thread or mark for upcall. */
 	if (discard) {
 		/*
@@ -605,7 +595,6 @@
     struct thread *td, struct trapframe *frame)
 {
 	int error;
-	ucontext_t uc;
 
 	/*
 	 * Ensure that we have a spare thread available.
@@ -642,10 +631,9 @@
 		    td, p->p_pid, p->p_comm);
 
 		/*
-		 * Fetch the current UTS context from userland.
+		 * Set user context to the UTS.
 		 */
-		error = copyin(&ke->ke_mailbox->km_context, &uc,
-		    sizeof(ucontext_t));
+		cpu_set_upcall_kse(td, ke);
 		if (error)
 			/*
 			 * Failing to do the KSE operation just defaults
@@ -655,21 +643,6 @@
 			goto cont;
 
 		/*
-		 * Set user context to the UTS's.
-		 *
-		 * XXX - Add the busy marker to thread_setcontext().
-		 */
-		error = thread_setcontext(td, &uc);
-		if (error)
-			/*
-			 * Failing to do the KSE operation just defaults
-			 * back to synchonous operation, so just return from
-			 * the syscall.
-			 */
-			goto cont;
-		suword(&ke->ke_mailbox->km_context.uc_busy, (intptr_t)td);
-
-		/*
 		 * Set state and mailbox.
 		 */
 		td->td_flags &= ~TDF_UPCALLING;

==== //depot/projects/kse/sys/sys/kse.h#18 (text+ko) ====

@@ -47,12 +47,12 @@
 /*
  * Thread mailbox.
  *
- * This describes a user thread ot the kernel scheduler.
+ * This describes a user thread to the kernel scheduler.
  */
 struct thread_mailbox {
+	ucontext_t		tm_context;	/* User and machine context */
 	unsigned int		tm_flags;	/* Thread flags */
 	struct thread_mailbox	*tm_next;	/* Next thread in list */
-	ucontext_t		tm_context;	/* User and machine context */
 	void			*tm_udata;	/* For use by the UTS */
 	int			tm_spare[8];
 };
@@ -64,12 +64,12 @@
  * a single KSE.
  */
 struct kse_mailbox {
-	unsigned int		km_flags;	/* KSE flags */
-#define KSEKMF_CRITICAL 0x00000001
-	ucontext_t		km_context;	/* UTS context */
 	struct thread_mailbox	*km_curthread;	/* Currently running thread */
 	struct thread_mailbox	*km_completed;	/* Threads back from kernel */
 	sigset_t		km_sigscaught;	/* Caught signals */
+	unsigned int		km_flags;	/* KSE flags */
+	void			*km_func;	/* UTS function */
+	stack_t			km_stack;	/* UTS context */
 	void			*km_udata;	/* For use by the UTS */
 	int			tm_spare[8];
 };

==== //depot/projects/kse/sys/sys/proc.h#126 (text+ko) ====

@@ -373,6 +373,8 @@
 		KES_THREAD	/* slaved to thread state */
 	} ke_state;     /* (j) S* process status. */
 	struct kse_mailbox	*ke_mailbox;	/* the userland mailbox address */
+	stack_t		ke_stack;
+	void		*ke_upcall;
 	struct thread	*ke_tdspare;	/* spare thread for upcalls */
 #define	ke_endzero ke_dummy
 	char		ke_dummy;
@@ -835,6 +837,7 @@
 struct	thread *thread_alloc(void);
 void	thread_free(struct thread *td);
 void	cpu_set_upcall(struct thread *td, void *pcb);
+void	cpu_set_upcall_kse(struct thread *td, struct kse *ke);
 void	cpu_thread_exit(struct thread *);
 void	cpu_thread_setup(struct thread *td);
 void	kse_reassign(struct kse *ke);

==== //depot/projects/kse/tools/KSE/uts/Makefile#2 (text+ko) ====

@@ -1,5 +1,6 @@
 PROG=	uts
 NOMAN=
 CFLAGS+= -g
+SRCS=	context.S uts.c 
 
 .include <bsd.prog.mk>

==== //depot/projects/kse/tools/KSE/uts/uts.c#6 (text+ko) ====

@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $P4: //depot/projects/kse/tools/KSE/uts/uts.c#5 $
+ * $P4: //depot/projects/kse/tools/KSE/uts/uts.c#6 $
  */
 
 #include <sys/types.h>
@@ -39,10 +39,12 @@
 #include <sysexits.h>
 #include <unistd.h>
 
+#undef TRACE_UTS
+
 #ifdef TRACE_UTS
 #define	UPFMT(fmt...)	pfmt(#fmt)
 #define	UPSTR(s)	pstr(s)
-#define	UPCHAR(c)	pchar(s)
+#define	UPCHAR(c)	pchar(c)
 #else
 #define	UPFMT(fmt...)	/* Nothing. */
 #define	UPSTR(s)	/* Nothing. */
@@ -54,6 +56,7 @@
 
 static struct kse_mailbox	uts_mb;
 static struct thread_mailbox	*run_queue;
+static struct thread_mailbox	*aa;
 
 static int progress = 0;
 
@@ -64,12 +67,19 @@
 static void	runq_insert(struct thread_mailbox *tm);
 static struct thread_mailbox *runq_remove(void);
 static void	thread_start(const void *func);
-static void	uts(void);
+static void	uts(struct kse_mailbox *km);
+
+extern int uts_to_thread(struct thread_mailbox *tdp, struct thread_mailbox **curthreadp);
+
+static void
+foof(int sig)
+{
+	pfmt("%d", sig);
+}
 
 void
 aaaa(void)
 {
-	progress++;
 	for (;;) {
 		pchar('.');
 		sleep(1);
@@ -94,7 +104,7 @@
 	// thread_start(spin);
 	init_uts();
 	for (i = 0;1;i++) {
-		progress++;
+		if (i) progress++;
 		pchar('a' + (i % 26));
 		sleep(5);
 	}
@@ -120,7 +130,7 @@
 
 	/* Throw us into its context. */
 	getcontext(&tm->tm_context);
-	tm->tm_context.uc_flags = UCF_SKIPSIGMASK | UCF_OBEYBUSY;
+	tm->tm_context.uc_flags = UCF_SKIPSIGMASK;
 
 	/* Find our stack. */
 	mib[0] = CTL_KERN;
@@ -134,19 +144,15 @@
 	tm->tm_context.uc_stack.ss_size = MAIN_STACK_SIZE;
 
 	/*
-	 * Create UTS context.
+	 * Create KSE mailbox.
 	 */
+	p = (char *)malloc(THREAD_STACK_SIZE);
 	bzero(&uts_mb, sizeof(struct kse_mailbox));
-	getcontext(&uts_mb.km_context);
-	p = (char *)malloc(THREAD_STACK_SIZE);
-	uts_mb.km_context.uc_stack.ss_sp = p;
-	uts_mb.km_context.uc_stack.ss_size = THREAD_STACK_SIZE;
-	makecontext(&uts_mb.km_context, uts, 1);
-	uts_mb.km_context.uc_flags = UCF_SKIPSIGMASK | UCF_OBEYBUSY;
-	pfmt("ucontext at : 0x%x\n", &uts_mb.km_context);
-	pfmt("mcontext mc_len : %d (%d)\n",
-	    uts_mb.km_context.uc_mcontext.mc_len, sizeof(mcontext_t));
+	uts_mb.km_stack.ss_sp = p;
+	uts_mb.km_stack.ss_size = THREAD_STACK_SIZE;
+	uts_mb.km_func = (void *)uts;
 	pfmt("uts() at : 0x%x\n", uts);
+	pfmt("uts stack at : 0x%x - 0x%x\n", p, p + THREAD_STACK_SIZE);
 
 	/*
 	 * Start KSE scheduling.
@@ -270,53 +276,60 @@
  * Userland thread scheduler.
  */
 static void
-uts(void)
+uts(struct kse_mailbox *km)
 {
 	struct thread_mailbox *tm, *p;
 	int ret;
 
 	UPSTR("\n--uts() start--\n");
-	for (;;) {
-		UPFMT("km_curthread -> 0x%x\n", uts_mb.km_curthread);
+	UPFMT("mailbox -> %x\n", km);
+
+	/*
+	 * Insert any processes back from being blocked
+	 * in the kernel into the run queue.
+	 */
+	p = km->km_completed;
+	uts_mb.km_completed = NULL;
+	UPFMT("km_completed -> 0x%x", p);
+	while ((tm = p) != NULL) {
+		p = tm->tm_next;
+		UPFMT(" 0x%x", p);
+		runq_insert(tm);
+	}
+	UPCHAR('\n');
+
+	/*
+	 * Process any signals we've recieved.
+	 */
+	/* XXX: Not yet. */
 
-		/*
-		 * Insert any processes back from being blocked
-		 * in the kernel into the run queue.
-		 */
-		p = uts_mb.km_completed;
-		uts_mb.km_completed = NULL;
-		UPFMT("km_completed -> 0x%x", p);
-		while ((tm = p) != NULL) {
-			p = tm->tm_next;
-			UPFMT(" 0x%x", p);
-			runq_insert(tm);
-		}
-		UPCHAR('\n');
+	/*
+	 * Pull a thread off the run queue.
+	 */
+	p = runq_remove();
+#if 0
+	if ((p == aa) && (progress > 0)) {
+		--progress;
+		signalcontext(&p->tm_context, 1, foof);
+	}
+#endif
 
-		/*
-		 * Pull a process off the run queue.
-		 */
-		p = runq_remove();
-		if (p != NULL) {
-			UPFMT("\n-- uts() scheduling 0x%x--\n", p);
-			UPFMT("eip -> 0x%x progress -> %d\n",
-			    p->tm_context.uc_mcontext.mc_eip, progress);
-			if ((p->tm_context.uc_flags & UCF_CRITICAL) == 0)
-				p->tm_context.uc_flags |=
-				    UCF_CRITICAL | UCF_CLEARSTATE;
-			uts_mb.km_curthread = p;
-			UPSTR("curthread set\n");
-			ret = swapcontext(&uts_mb.km_context, &p->tm_context);
-			UPFMT("\n-- uts() back from swapcontext() [%d] --\n",
-			    ret);
-			if (ret)
-				/*
-				 * Invalid thread context. Exit.
-				 */
-				exit(ret);
-		} else
-			kse_yield();
+	/*
+	 * Either schedule a thread, or idle if none ready to run.
+	 */
+	if (p != NULL) {
+		UPFMT("\n-- uts() scheduling 0x%x--\n", p);
+		UPFMT("eip -> 0x%x progress -> %d\n",
+		    p->tm_context.uc_mcontext.mc_eip, progress);
+		if ((p->tm_context.uc_flags & UCF_CRITICAL) == 0)
+			p->tm_context.uc_flags |=
+			    UCF_CRITICAL | UCF_CLEARSTATE;
+		uts_mb.km_curthread = p;
+		UPSTR("curthread set\n");
+		uts_to_thread(p, &km->km_curthread);
+		UPSTR("\n-- uts_to_thread() failed --\n");
 	}
+	kse_yield();
 	pstr("** uts() exiting **\n");
 	exit(EX_SOFTWARE);
 }
@@ -330,13 +343,14 @@
 	struct thread_mailbox *tm;
 	char *p;
 
-	tm = (struct thread_mailbox *)calloc(1, sizeof(struct thread_mailbox));
-	pfmt("thread_start() : 0x%x\n", tm);
+	aa = tm = (struct thread_mailbox *)calloc(1, sizeof(struct thread_mailbox));
+	pfmt("thread_start() : 0x%x %x\n", tm, &aa->tm_context);
 	getcontext(&tm->tm_context);
 	p = (char *)malloc(THREAD_STACK_SIZE);
 	tm->tm_context.uc_stack.ss_sp = p;
 	tm->tm_context.uc_stack.ss_size = THREAD_STACK_SIZE;
 	makecontext(&tm->tm_context, func, 1);
-	tm->tm_context.uc_flags = UCF_SKIPSIGMASK | UCF_OBEYBUSY;
+	tm->tm_context.uc_flags = UCF_SKIPSIGMASK;
+	// setcontext(&tm->tm_context);
 	runq_insert(tm);
 }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200209041041.g84AfU1q017939>