/*
 * Thread scheduler.
 */
#include "threadimpl.h"

static Thread *runthread(Proc*);
static void schedexit(Proc*);

/*
 * Main scheduling loop.
 */
void
_threadscheduler(void *arg)
{
	Proc *p;
	Thread *t;

	p = arg;

	_threadlinkmain();
	_threadsetproc(p);

	for(;;){
		/* 
		 * Clean up zombie children.
		 */

		/*
		 * Find next thread to run.
		 */
		_threaddebug(DBGSCHED, "runthread");
		t = runthread(p);
		if(t == nil)
			schedexit(p);
	
		/*
		 * If it's ready, run it (might instead be marked to die).
		 */
		lock(&p->lock);
		if(t->state == Ready){
			_threaddebug(DBGSCHED, "running %d.%d", p->id, t->id);
			t->state = Running;
			t->nextstate = Ready;
			p->thread = t;
			unlock(&p->lock);
			_swaplabel(&p->context, &t->context);
			lock(&p->lock);
			p->thread = nil;
		}

		/*
		 * If thread needs to die, kill it.
		 * t->proc == p may not be true if we're
		 * trying to jump into the exec proc (see exec-unix.c).
		 */
		if(t->moribund){
			_threaddebug(DBGSCHED, "moribund %d.%d", p->id, t->id);
			if(t->moribund != 1)
				print("moribund broke %p %d\n", &t->moribund, t->moribund);
			assert(t->moribund == 1);
			t->state = Dead;
			_procdelthread(p, t);
			unlock(&p->lock);
			_threadfree(t);
			t = nil;
			continue;
		}

		/*
		 * If the thread has asked to move to another proc,
		 * let it go (only to be used in *very* special situations).
		if(t->nextproc != p)
			_procdelthread(p, t);
		 */

		unlock(&p->lock);

		/*
		 * If the thread has asked to move to another proc,
		 * add it to the new proc.
		 */
		if(t->nextproc != p){
		//	lock(&t->nextproc->lock);
		//	_procaddthread(t->nextproc, t);
		//	unlock(&t->nextproc->lock);
			t->proc = t->nextproc;
		}

		/*
		 * If there is a request to run a function on the 
		 * scheduling stack, do so.
		 */
		if(p->schedfn){
			_threaddebug(DBGSCHED, "schedfn");
			p->schedfn(p);
			p->schedfn = nil;
			_threaddebug(DBGSCHED, "schedfn ended");
		}

		/*
		 * Move the thread along.
		 */
		t->state = t->nextstate;
		_threaddebug(DBGSCHED, "moveon %d.%d", t->proc->id, t->id);
		if(t->state == Ready)
			_threadready(t);
	}
}

/*
 * Called by thread to give up control of processor to scheduler.
 */
int
_sched(void)
{
	Proc *p;
	Thread *t;

	p = _threadgetproc();
	t = p->thread;
	assert(t != nil);
	_swaplabel(&t->context, &p->context);
	return p->nsched++;
}

/*
 * Called by thread to yield the processor to other threads.
 * Returns number of other threads run between call and return.
 */
int
yield(void)
{
	Proc *p;
	int nsched;

	p = _threadgetproc();
	nsched = p->nsched;
	return _sched() - nsched;
}

/*
 * Choose the next thread to run.
 */
static Thread*
runthread(Proc *p)
{
	Thread *t;
	Tqueue *q;

	/*
	 * No threads left?
	 */
	if(p->nthreads==0 || (p->nthreads==1 && p->idle))
		return nil;

	_threadschednote();
	lock(&p->readylock);
	q = &p->ready;
	if(q->head == nil){
		/*
		 * Is this a single-process program with an idle thread?
		 */
		if(p->idle){
			/*
			 * The idle thread had better be ready!
			 */
			if(p->idle->state != Ready)
				sysfatal("all threads are asleep");

			/*
			 * Run the idle thread.
			 */
			unlock(&p->readylock);
			_threaddebug(DBGSCHED, "running idle thread", p->nthreads);
			return p->idle;
		}

		/*
		 * Wait until one of our threads is readied (by another proc!).
		 */
		q->asleep = 1;
		p->rend.l = &p->readylock;
		while(q->asleep){
			_procsleep(&p->rend);
			_threadschednote();
		}

		/*
		 * Maybe we were awakened to exit?
		 */
		if(_threadexitsallstatus){
			_threaddebug(DBGSCHED, "time to exit");
			_exits(_threadexitsallstatus);
		}
		assert(q->head != nil);
	}

	t = q->head;
	q->head = t->next;
	unlock(&p->readylock);

	return t;
}

/*
 * Add a newly-ready thread to its proc's run queue.
 */
void
_threadready(Thread *t)
{
	Tqueue *q;

	/*
	 * The idle thread does not go on the run queue.
	 */
	if(t == t->proc->idle){
		_threaddebug(DBGSCHED, "idle thread is ready");
		return;
	}

	assert(t->state == Ready);
	_threaddebug(DBGSCHED, "readying %d.%d", t->proc->id, t->id);

	/*
	 * Add thread to run queue.
	 */
	q = &t->proc->ready;
	lock(&t->proc->readylock);

	t->next = nil;
	if(q->head == nil)
		q->head = t;
	else
		q->tail->next = t;
	q->tail = t;

	/*
	 * Wake proc scheduler if it is sleeping.
	 */
	if(q->asleep){
		assert(q->asleep == 1);
		q->asleep = 0;
		_procwakeup(&t->proc->rend);
	}
	unlock(&t->proc->readylock);
}

/*
 * Mark the given thread as the idle thread.
 * Since the idle thread was just created, it is sitting
 * somewhere on the ready queue.
 */
void
_threadsetidle(int id)
{
	Tqueue *q;
	Thread *t, **l, *last;
	Proc *p;

	p = _threadgetproc();

	lock(&p->readylock);

	/*
	 * Find thread on ready queue.
	 */
	q = &p->ready;
	for(l=&q->head, last=nil; (t=*l) != nil; l=&t->next, last=t)
		if(t->id == id)
			break;
	assert(t != nil);

	/* 
	 * Remove it from ready queue.
	 */
	*l = t->next;
	if(t == q->head)
		q->head = t->next;
	if(t->next == nil)
		q->tail = last;

	/*
	 * Set as idle thread.
	 */
	p->idle = t;
	_threaddebug(DBGSCHED, "p->idle is %d\n", t->id);
	unlock(&p->readylock);
}

/*
 * Mark proc as internal so that if all but internal procs exit, we exit.
 */
void
_threadinternalproc(void)
{
	Proc *p;

	p = _threadgetproc();
	if(p->internal)
		return;
	lock(&_threadpq.lock);
	if(p->internal == 0){
		p->internal = 1;
		--_threadnprocs;
	}
	unlock(&_threadpq.lock);
}

static void
schedexit(Proc *p)
{
	char ex[ERRMAX];
	int n;
	Proc **l;

	_threaddebug(DBGSCHED, "exiting proc %d", p->id);
	lock(&_threadpq.lock);
	for(l=&_threadpq.head; *l; l=&(*l)->next){
		if(*l == p){
			*l = p->next;
			if(*l == nil)
				_threadpq.tail = l;
			break;
		}
	}
	if(p->internal)
		n = _threadnprocs;
	else
		n = --_threadnprocs;
	unlock(&_threadpq.lock);

	strncpy(ex, p->exitstr, sizeof ex);
	ex[sizeof ex-1] = '\0';
	free(p);
	if(n == 0){
		_threaddebug(DBGSCHED, "procexit; no more procs");
		_kthreadexitallproc(ex);
	}else{
		_threaddebug(DBGSCHED, "procexit");
		_kthreadexitproc(ex);
	}
}

