Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Sep 2002 18:42:17 -0700 (PDT)
From:      Jonathan Mini <mini@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 17248 for review
Message-ID:  <200209090142.g891gH8o059266@freefall.freebsd.org>

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

Change 17248 by mini@mini_stylus on 2002/09/08 18:41:19

	Switch over to KSE-style scheduling primitives, but don't
	actually use KSE yet.

Affected files ...

.. //depot/projects/kse/lib/libc_r/arch/i386/_thread_enter_uts.S#1 add
.. //depot/projects/kse/lib/libc_r/arch/i386/_thread_switch.S#1 add
.. //depot/projects/kse/lib/libc_r/sys/Makefile.inc#2 edit
.. //depot/projects/kse/lib/libc_r/uthread/Makefile.inc#6 edit
.. //depot/projects/kse/lib/libc_r/uthread/pthread_private.h#9 edit
.. //depot/projects/kse/lib/libc_r/uthread/uthread_create.c#6 edit
.. //depot/projects/kse/lib/libc_r/uthread/uthread_init.c#7 edit
.. //depot/projects/kse/lib/libc_r/uthread/uthread_kern.c#8 edit
.. //depot/projects/kse/lib/libc_r/uthread/uthread_priority_queue.c#3 edit

Differences ...

==== //depot/projects/kse/lib/libc_r/sys/Makefile.inc#2 (text+ko) ====

@@ -2,5 +2,5 @@
 
 .PATH:	 ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH}
 
-SRCS+=	uthread_error.c _atomic_lock.S
+SRCS+=	uthread_error.c _atomic_lock.S _thread_enter_uts.S _thread_switch.S
 

==== //depot/projects/kse/lib/libc_r/uthread/Makefile.inc#6 (text+ko) ====

@@ -63,6 +63,7 @@
 	uthread_pause.c \
 	uthread_poll.c \
 	uthread_priority_queue.c \
+	uthread_printf.c \
 	uthread_pselect.c \
 	uthread_read.c \
 	uthread_readv.c \

==== //depot/projects/kse/lib/libc_r/uthread/pthread_private.h#9 (text+ko) ====

@@ -68,18 +68,8 @@
 
 
 /* Output debug messages like this: */
-#define stdout_debug(args...)	do {		\
-	char buf[128];				\
-	snprintf(buf, sizeof(buf), ##args);	\
-	__sys_write(1, buf, strlen(buf));	\
-} while (0)
-#define stderr_debug(args...)	do {		\
-	char buf[128];				\
-	snprintf(buf, sizeof(buf), ##args);	\
-	__sys_write(2, buf, strlen(buf));	\
-} while (0)
-
-
+#define stdout_debug(args...)	_thread_printf( args )
+#define stderr_debug(args...)	_thread_printf( args )
 
 /*
  * Priority queue manipulation macros (using pqe link):
@@ -704,13 +694,6 @@
 ;
 #endif
 
-SCLASS int              _thread_kern_in_sched
-#ifdef GLOBAL_PTHREAD_PRIVATE
-= 0;
-#else
-;
-#endif
-
 /* Time of day at last scheduling timer signal: */
 SCLASS struct timeval volatile	_sched_tod
 #ifdef GLOBAL_PTHREAD_PRIVATE
@@ -818,7 +801,7 @@
 /*
  * Declare the kernel scheduler jump buffer and stack:
  */
-SCLASS ucontext_t	_thread_kern_sched_ctx;
+SCLASS struct kse_mailbox	_thread_kern_kse_mailbox;
 
 SCLASS void *		_thread_kern_sched_stack
 #ifdef GLOBAL_PTHREAD_PRIVATE
@@ -891,15 +874,18 @@
 void    _thread_dump_info(void);
 void    _thread_init(void);
 void    _thread_kern_sched(void);
-void 	_thread_kern_scheduler(void);
+void 	_thread_kern_scheduler(struct kse_mailbox *);
 void    _thread_kern_sched_state(enum pthread_state, char *fname, int lineno);
 void	_thread_kern_sched_state_unlock(enum pthread_state state,
 	    spinlock_t *lock, char *fname, int lineno);
 void    _thread_kern_set_timeout(const struct timespec *);
 void    _thread_kern_sig_defer(void);
 void    _thread_kern_sig_undefer(void);
+void	_thread_printf(const char *, ...);
 void    _thread_start(void);
 void	_thread_seterrno(pthread_t, int);
+int	_thread_enter_uts(struct thread_mailbox *tm, struct kse_mailbox *km);
+int	_thread_switch(struct thread_mailbox *, struct thread_mailbox **);
 pthread_addr_t _thread_gc(pthread_addr_t);
 void	_thread_enter_cancellation_point(void);
 void	_thread_leave_cancellation_point(void);

==== //depot/projects/kse/lib/libc_r/uthread/uthread_create.c#6 (text+ko) ====

@@ -232,9 +232,6 @@
 {
 	struct pthread	*curthread = _get_curthread();
 
-	/* We just left the scheduler via swapcontext: */
-	_thread_kern_in_sched = 0;
-
 	/* Run the current thread's start routine with argument: */
 	pthread_exit(curthread->start_routine(curthread->arg));
 

==== //depot/projects/kse/lib/libc_r/uthread/uthread_init.c#7 (text+ko) ====

@@ -267,15 +267,12 @@
 		_thread_initial->attr.stacksize_attr = PTHREAD_STACK_INITIAL;
 
 		/* Setup the context for the scheduler: */
-		getcontext(&_thread_kern_sched_ctx);
-		_thread_kern_sched_ctx.uc_stack.ss_sp =
+		_thread_kern_kse_mailbox.km_stack.ss_sp =
 		    _thread_kern_sched_stack;
-		_thread_kern_sched_ctx.uc_stack.ss_size = sched_stack_size;
-		makecontext(&_thread_kern_sched_ctx, _thread_kern_scheduler, 1);
+		_thread_kern_kse_mailbox.km_stack.ss_size = sched_stack_size;
+		_thread_kern_kse_mailbox.km_func =
+		    (void *)_thread_kern_scheduler;
 
-		/* Block all signals to the scheduler's context. */
-		sigfillset(&_thread_kern_sched_ctx.uc_sigmask);
-
 		/*
 		 * Write a magic value to the thread structure
 		 * to help identify valid ones:
@@ -288,8 +285,10 @@
 
 		/* Setup the context for initial thread. */
 		getcontext(&_thread_initial->mailbox.tm_context);
-		_thread_kern_sched_ctx.uc_stack.ss_sp = _thread_initial->stack;
-		_thread_kern_sched_ctx.uc_stack.ss_size = PTHREAD_STACK_INITIAL;
+		_thread_initial->mailbox.tm_context.uc_stack.ss_sp =
+		    _thread_initial->stack;
+		_thread_initial->mailbox.tm_context.uc_stack.ss_size =
+		    PTHREAD_STACK_INITIAL;
 
 		/* Default the priority of the initial thread: */
 		_thread_initial->base_priority = PTHREAD_DEFAULT_PRIORITY;

==== //depot/projects/kse/lib/libc_r/uthread/uthread_kern.c#8 (text+ko) ====

@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>
  * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
  * All rights reserved.
  *
@@ -57,6 +58,7 @@
 #define DBG_MSG(x...)
 #endif
 
+
 /* Static function prototype definitions: */
 static void
 thread_kern_idle(void);
@@ -73,27 +75,137 @@
 void
 _thread_kern_sched(void)
 {
+	struct timespec	ts;
+	struct timeval	tv;
 	struct pthread	*curthread = _get_curthread();
+	unsigned int	current_tick;
+
+	/* Get the current time of day. */
+	GET_CURRENT_TOD(tv);
+	TIMEVAL_TO_TIMESPEC(&tv, &ts);
+	current_tick = _sched_ticks;
 
 	/*
-	 * Flag the pthread kernel as executing scheduler code
-	 * to avoid a scheduler signal from interrupting this
-	 * execution and calling the scheduler again.
+	 * Enter a critical section.
+	 */
+	_thread_kern_kse_mailbox.km_curthread = NULL;
+
+	/*
+	 * If this thread is becoming inactive, make note of the
+	 * time.
+	 */
+	if (curthread->state != PS_RUNNING) {
+		/*
+		 * Save the current time as the time that the
+		 * thread became inactive:
+		 */
+		curthread->last_inactive = (long)current_tick;
+		if (curthread->last_inactive <
+		    curthread->last_active) {
+			/* Account for a rollover: */
+			curthread->last_inactive =+
+			    UINT_MAX + 1;
+		}
+	}
+
+	/*
+	 * Place this thread into the appropriate queue(s).
 	 */
-	_thread_kern_in_sched = 1;
+	switch (curthread->state) {
+	case PS_DEAD:
+	case PS_STATE_MAX: /* XXX: silences -Wall */
+	case PS_SUSPENDED:
+		/* Dead or suspended threads are not placed in any queue. */
+		break;
+	case PS_RUNNING:
+		/*
+		 * Save the current time as the time that the
+		 * thread became inactive:
+		 */
+		current_tick = _sched_ticks;
+		curthread->last_inactive = (long)current_tick;
+		if (curthread->last_inactive <
+		    curthread->last_active) {
+			/* Account for a rollover: */
+			curthread->last_inactive =+ UINT_MAX + 1;
+		}
+
+		if ((curthread->slice_usec != -1) &&
+		   (curthread->attr.sched_policy != SCHED_FIFO)) {
+			/*
+			 * Accumulate the number of microseconds for
+			 * which the current thread has run:
+			 */
+			curthread->slice_usec +=
+			    (curthread->last_inactive -
+			    curthread->last_active) *
+			    (long)_clock_res_usec;
+			/* Check for time quantum exceeded: */
+			if (curthread->slice_usec > TIMESLICE_USEC)
+				curthread->slice_usec = -1;
+		}
+
+		if (curthread->slice_usec == -1) {
+			/*
+			 * The thread exceeded its time
+			 * quantum or it yielded the CPU;
+			 * place it at the tail of the
+			 * queue for its priority.
+			 */
+			PTHREAD_PRIOQ_INSERT_TAIL(curthread);
+		} else {
+			/*
+			 * The thread hasn't exceeded its
+			 * interval.  Place it at the head
+			 * of the queue for its priority.
+			 */
+			PTHREAD_PRIOQ_INSERT_HEAD(curthread);
+		}
+		break;
+	case PS_SPINBLOCK:
+		/* Increment spinblock count. */
+		_spinblock_count++;
+		/*FALLTHROUGH*/
+	case PS_DEADLOCK:
+	case PS_JOIN:
+	case PS_MUTEX_WAIT:
+	case PS_WAIT_WAIT:
+		/* No timeouts for these states. */
+		curthread->wakeup_time.tv_sec = -1;
+		curthread->wakeup_time.tv_nsec = -1;
+
+		/* Restart the time slice. */
+		curthread->slice_usec = -1;
+
+		/* Insert into the waiting queue. */
+		PTHREAD_WAITQ_INSERT(curthread);
+		break;
+
+	case PS_COND_WAIT:
+	case PS_SLEEP_WAIT:
+		/* These states can timeout. */
+		/* Restart the time slice. */
+		curthread->slice_usec = -1;
+
+		/* Insert into the waiting queue. */
+		PTHREAD_WAITQ_INSERT(curthread);
+		break;
+	}
 
 	/* Switch into the scheduler's context. */
-	swapcontext(&curthread->mailbox.tm_context, &_thread_kern_sched_ctx);
-	DBG_MSG("Returned from swapcontext, thread %p\n", curthread);
+	DBG_MSG("Calling _thread_enter_uts()\n");
+	_thread_enter_uts(&curthread->mailbox, &_thread_kern_kse_mailbox);
+	DBG_MSG("Returned from _thread_enter_uts, thread %p\n", curthread);
 
 	/*
-	 * This point is reached when swapcontext() is called
+	 * This point is reached when _thread_switch() is called
 	 * to restore the state of a thread.
 	 *
-	 * This is the normal way out of the scheduler.
+	 * This is the normal way out of the scheduler (for synchronous
+	 * switches).
 	 */
-	_thread_kern_in_sched = 0;
 
+	/* XXXKSE: Do this inside _thread_kern_scheduler() */
 	if (curthread->sig_defer_count == 0) {
 		if (((curthread->cancelflags &
 		    PTHREAD_AT_CANCEL_POINT) == 0) &&
@@ -114,128 +226,50 @@
 		/* Run the installed switch hook: */
 		thread_run_switch_hook(_last_user_thread, curthread);
 	}
+	DBG_MSG("Fuck me\n");
 }
 
 void
-_thread_kern_scheduler(void)
+_thread_kern_scheduler(struct kse_mailbox *km)
 {
 	struct timespec	ts;
 	struct timeval	tv;
-	struct pthread	*curthread = _get_curthread();
-	pthread_t	pthread, pthread_h;
+	pthread_t	td, pthread, pthread_h;
 	unsigned int	current_tick;
-	int		add_to_prioq;
+	struct thread_mailbox	*tm, *p;
 
-	/*
-	 * Enter a scheduling loop that finds the next thread that is
-	 * ready to run. This loop completes when there are no more threads
-	 * in the global list. It is interrupted each time a thread is
-	 * scheduled, but will continue when we return.
-	 */
-	while (!(TAILQ_EMPTY(&_thread_list))) {
+	DBG_MSG("entering\n");
+	while (!TAILQ_EMPTY(&_thread_list)) {
 
-		/* If the currently running thread is a user thread, save it: */
-		if ((curthread->flags & PTHREAD_FLAGS_PRIVATE) == 0)
-			_last_user_thread = curthread;
-
-		/* Get the current time of day: */
+		/* Get the current time of day. */
 		GET_CURRENT_TOD(tv);
 		TIMEVAL_TO_TIMESPEC(&tv, &ts);
 		current_tick = _sched_ticks;
 
-		add_to_prioq = 0;
-		if (curthread != &_thread_kern_thread) {
-			/*
-			 * This thread no longer needs to yield the CPU.
-			 */
-			if (curthread->state != PS_RUNNING) {
-				/*
-				 * Save the current time as the time that the
-				 * thread became inactive:
-				 */
-				curthread->last_inactive = (long)current_tick;
-				if (curthread->last_inactive <
-				    curthread->last_active) {
-					/* Account for a rollover: */
-					curthread->last_inactive =+
-					    UINT_MAX + 1;
-				}
-			}
-
-			/*
-			 * Place the currently running thread into the
-			 * appropriate queue(s).
-			 */
-			switch (curthread->state) {
-			case PS_DEAD:
-			case PS_STATE_MAX: /* to silence -Wall */
-			case PS_SUSPENDED:
-				/*
-				 * Dead and suspended threads are not placed
-				 * in any queue:
-				 */
-				break;
-
-			case PS_RUNNING:
-				/*
-				 * Runnable threads can't be placed in the
-				 * priority queue until after waiting threads
-				 * are polled (to preserve round-robin
-				 * scheduling).
-				 */
-				add_to_prioq = 1;
-				break;
-
-			/*
-			 * States which do not depend on file descriptor I/O
-			 * operations or timeouts:
-			 */
-			case PS_DEADLOCK:
-			case PS_JOIN:
-			case PS_MUTEX_WAIT:
-			case PS_WAIT_WAIT:
-				/* No timeouts for these states: */
-				curthread->wakeup_time.tv_sec = -1;
-				curthread->wakeup_time.tv_nsec = -1;
-
-				/* Restart the time slice: */
-				curthread->slice_usec = -1;
-
-				/* Insert into the waiting queue: */
-				PTHREAD_WAITQ_INSERT(curthread);
-				break;
-
-			/* States which can timeout: */
-			case PS_COND_WAIT:
-			case PS_SLEEP_WAIT:
-				/* Restart the time slice: */
-				curthread->slice_usec = -1;
-
-				/* Insert into the waiting queue: */
-				PTHREAD_WAITQ_INSERT(curthread);
-				break;
-	
-			/* States that require periodic work: */
-			case PS_SPINBLOCK:
-				/* No timeouts for this state: */
-				curthread->wakeup_time.tv_sec = -1;
-				curthread->wakeup_time.tv_nsec = -1;
-
-				/* Increment spinblock count: */
-				_spinblock_count++;
-
-				/* FALLTHROUGH */
-			}
+		/*
+		 * Pick up threads that had blocked in the kernel and
+		 * have now completed their trap (syscall, vm fault, etc).
+		 * These threads were PS_RUNNING (and still are), but they
+		 * need to be added to the run queue so that they can be
+		 * scheduled again.
+		 */
+		DBG_MSG("Picking up km_completed\n");
+		p = km->km_completed;
+		km->km_completed = NULL;	/* XXX: Atomic xchg here. */
+		while ((tm = p) != NULL) {
+			p = tm->tm_next;
+			tm->tm_next = NULL;
+			PTHREAD_PRIOQ_INSERT_TAIL((pthread_t)tm->tm_udata);
 		}
 
-		last_tick = current_tick;
+		/* Deliver posted signals. */
+		/* XXX: Not yet. */
+		DBG_MSG("Picking up signals\n");
 
-		/*
-		 * Wake up threads that have timedout.  This has to be
-		 * done after polling in case a thread does a poll or
-		 * select with zero time.
-		 */
+		/* Wake up threads that have timed out.  */
+		DBG_MSG("setactive\n");
 		PTHREAD_WAITQ_SETACTIVE();
+		DBG_MSG("Picking up timeouts (%x)\n", TAILQ_FIRST(&_waitingq));
 		while (((pthread = TAILQ_FIRST(&_waitingq)) != NULL) &&
 		    (pthread->wakeup_time.tv_sec != -1) &&
 		    (((pthread->wakeup_time.tv_sec == 0) &&
@@ -243,6 +277,7 @@
 		    (pthread->wakeup_time.tv_sec < ts.tv_sec) ||
 		    ((pthread->wakeup_time.tv_sec == ts.tv_sec) &&
 		    (pthread->wakeup_time.tv_nsec <= ts.tv_nsec)))) {
+			DBG_MSG("\t...\n");
 			/*
 			 * Remove this thread from the waiting queue
 			 * (and work queue if necessary) and place it
@@ -251,6 +286,7 @@
 			PTHREAD_WAITQ_CLEARACTIVE();
 			if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ)
 				PTHREAD_WORKQ_REMOVE(pthread);
+			DBG_MSG("\twaking thread\n");
 			PTHREAD_NEW_STATE(pthread, PS_RUNNING);
 			PTHREAD_WAITQ_SETACTIVE();
 			/*
@@ -258,119 +294,39 @@
 			 */
 			pthread->timeout = 1;
 		}
+		DBG_MSG("clearactive\n");
 		PTHREAD_WAITQ_CLEARACTIVE();
 
 		/*
-		 * Check to see if the current thread needs to be added
-		 * to the priority queue:
-		 */
-		if (add_to_prioq != 0) {
-			/*
-			 * Save the current time as the time that the
-			 * thread became inactive:
-			 */
-			current_tick = _sched_ticks;
-			curthread->last_inactive = (long)current_tick;
-			if (curthread->last_inactive <
-			    curthread->last_active) {
-				/* Account for a rollover: */
-				curthread->last_inactive =+ UINT_MAX + 1;
-			}
-
-			if ((curthread->slice_usec != -1) &&
-		 	   (curthread->attr.sched_policy != SCHED_FIFO)) {
-				/*
-				 * Accumulate the number of microseconds for
-				 * which the current thread has run:
-				 */
-				curthread->slice_usec +=
-				    (curthread->last_inactive -
-				    curthread->last_active) *
-				    (long)_clock_res_usec;
-				/* Check for time quantum exceeded: */
-				if (curthread->slice_usec > TIMESLICE_USEC)
-					curthread->slice_usec = -1;
-			}
-
-			if (curthread->slice_usec == -1) {
-				/*
-				 * The thread exceeded its time
-				 * quantum or it yielded the CPU;
-				 * place it at the tail of the
-				 * queue for its priority.
-				 */
-				PTHREAD_PRIOQ_INSERT_TAIL(curthread);
-			} else {
-				/*
-				 * The thread hasn't exceeded its
-				 * interval.  Place it at the head
-				 * of the queue for its priority.
-				 */
-				PTHREAD_PRIOQ_INSERT_HEAD(curthread);
-			}
-		}
-
-		/*
 		 * Get the highest priority thread in the ready queue.
 		 */
+		DBG_MSG("Selecting thread\n");
 		pthread_h = PTHREAD_PRIOQ_FIRST();
 
 		/* Check if there are no threads ready to run: */
-		if (pthread_h == NULL) {
-			/*
-			 * Lock the pthread kernel by changing the pointer to
-			 * the running thread to point to the global kernel
-			 * thread structure:
-			 */
-			_set_curthread(&_thread_kern_thread);
-			curthread = &_thread_kern_thread;
-
-			DBG_MSG("No runnable threads, using kernel thread %p\n",
-			    curthread);
-
-			/*
-			 * There are no threads ready to run, so wait until
-			 * something happens that changes this condition:
-			 */
-			thread_kern_idle();
-
-			/*
-			 * This process' usage will likely be very small
-			 * while waiting in a poll.  Since the scheduling
-			 * clock is based on the profiling timer, it is
-			 * unlikely that the profiling timer will fire
-			 * and update the time of day.  To account for this,
-			 * get the time of day after polling with a timeout.
-			 */
-			gettimeofday((struct timeval *) &_sched_tod, NULL);
-			
-			/* Check once more for a runnable thread: */
-			pthread_h = PTHREAD_PRIOQ_FIRST();
-		}
-
-		if (pthread_h != NULL) {
+		if (pthread_h) {
+			DBG_MSG("Scheduling thread\n");
 			/* Remove the thread from the ready queue: */
 			PTHREAD_PRIOQ_REMOVE(pthread_h);
 
 			/* Make the selected thread the current thread: */
 			_set_curthread(pthread_h);
-			curthread = pthread_h;
 
 			/*
 			 * Save the current time as the time that the thread
 			 * became active:
 			 */
 			current_tick = _sched_ticks;
-			curthread->last_active = (long) current_tick;
+			pthread_h->last_active = (long) current_tick;
 
 			/*
 			 * Check if this thread is running for the first time
 			 * or running again after using its full time slice
 			 * allocation:
 			 */
-			if (curthread->slice_usec == -1) {
+			if (pthread_h->slice_usec == -1) {
 				/* Reset the accumulated time slice period: */
-				curthread->slice_usec = 0;
+				pthread_h->slice_usec = 0;
 			}
 
 			/*
@@ -378,19 +334,47 @@
 			 * installed switch hooks.
 			 */
 			if ((_sched_switch_hook != NULL) &&
-			    (_last_user_thread != curthread)) {
+			    (_last_user_thread != pthread_h)) {
 				thread_run_switch_hook(_last_user_thread,
-				    curthread);
+				    pthread_h);
 			}
 			/*
 			 * Continue the thread at its current frame:
 			 */
-			swapcontext(&_thread_kern_sched_ctx,
-			    &curthread->mailbox.tm_context);
+			_last_user_thread = td;
+			DBG_MSG("switch in\n");
+			_thread_switch(&pthread_h->mailbox,
+			    &_thread_kern_kse_mailbox.km_curthread);
+			DBG_MSG("switch out\n");
+		} else {
+			/*
+			 * There is nothing for us to do. Either
+			 * yield, or idle until something wakes up.
+			 */
+			DBG_MSG("No runnable threads, idling.\n");
+
+			/*
+			 * kse_yield() only returns if we are the
+			 * only thread in this process. If so, then
+			 * we drop into an idle loop.
+			 */
+			kse_yield();
+			thread_kern_idle();
+
+			/*
+			 * This thread's usage will likely be very small
+			 * while waiting in a poll.  Since the scheduling
+			 * clock is based on the profiling timer, it is
+			 * unlikely that the profiling timer will fire
+			 * and update the time of day.  To account for this,
+			 * get the time of day after polling with a timeout.
+			 */
+			gettimeofday((struct timeval *) &_sched_tod, NULL);
 		}
+		DBG_MSG("looping\n");
 	}
-
-	/* There are no more threads, so exit this process: */
+	/* There are no threads; exit. */
+	DBG_MSG("No threads, exiting.\n");
 	exit(0);
 }
 
@@ -401,10 +385,10 @@
 
 	/*
 	 * Flag the pthread kernel as executing scheduler code
-	 * to avoid a scheduler signal from interrupting this
-	 * execution and calling the scheduler again.
+	 * to avoid an upcall from interrupting this execution
+	 * and calling the scheduler again.
 	 */
-	_thread_kern_in_sched = 1;
+	_thread_kern_kse_mailbox.km_curthread = NULL;
 
 	/* Change the state of the current thread: */
 	curthread->state = state;
@@ -423,10 +407,10 @@
 
 	/*
 	 * Flag the pthread kernel as executing scheduler code
-	 * to avoid a scheduler signal from interrupting this
-	 * execution and calling the scheduler again.
+	 * to avoid an upcall from interrupting this execution
+	 * and calling the scheduler again.
 	 */
-	_thread_kern_in_sched = 1;
+	_thread_kern_kse_mailbox.km_curthread = NULL;
 
 	/* Change the state of the current thread: */
 	curthread->state = state;
@@ -439,6 +423,13 @@
 	_thread_kern_sched();
 }
 
+/*
+ * XXX - What we need to do here is schedule ourselves an idle thread,
+ * which does the poll()/nanosleep()/whatever, and then will cause an
+ * upcall when it expires. This thread never gets inserted into the
+ * run_queue (in fact, there's no need for it to be a thread at all).
+ * timeout period has arrived.
+ */
 static void
 thread_kern_idle()
 {
@@ -460,6 +451,8 @@
 		/*
 		 * Either there are no threads in the waiting queue,
 		 * or there are no threads that can timeout.
+		 *
+		 * XXX: kse_yield() here, maybe?
 		 */
 		PANIC("Would idle forever");
 	}

==== //depot/projects/kse/lib/libc_r/uthread/uthread_priority_queue.c#3 (text+ko) ====

@@ -68,9 +68,9 @@
 	if (((thrd)->flags & _PQ_IN_SCHEDQ) != 0)	\
 		PANIC(msg);				\
 } while (0)
-#define _PQ_ASSERT_PROTECTED(msg)			\
-	PTHREAD_ASSERT((_thread_kern_in_sched != 0) ||	\
-	    ((_get_curthread())->sig_defer_count > 0), \
+#define _PQ_ASSERT_PROTECTED(msg)					       \
+	PTHREAD_ASSERT((_thread_kern_kse_mailbox.km_curthread == NULL) ||      \
+	    ((_get_curthread())->sig_defer_count > 0),			       \
 	    msg);
 
 #else

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?200209090142.g891gH8o059266>