#include "threadimpl.h"

#define free
Pqueue _threadpq;

static int nextID(void);

/*
 * Create and initialize a new Thread structure attached to a given proc.
 */

typedef struct Stack Stack;
struct Stack {
	ulong magic;
	Thread *thr;
	Stack *next;
	uchar buf[STKSIZE-12];
};

static Stack *stkfree;
static Lock stklock;

void
_stackfree(void *v)
{
	Stack *s;

	s = v;
	lock(&stklock);
	s->thr = nil;
	s->magic = 0;
	s->next = stkfree;
	stkfree = s;
	unlock(&stklock);
}

static Stack*
stackalloc(void)
{
	char *buf;
	Stack *s;
	int i;

	lock(&stklock);
	while(stkfree == nil){
		unlock(&stklock);
		assert(STKSIZE == sizeof(Stack));
		buf = malloc(STKSIZE+128*STKSIZE);
		s = (Stack*)(((ulong)buf+STKSIZE)&~(STKSIZE-1));
		for(i=0; i<128; i++)
			_stackfree(&s[i]);
		lock(&stklock);
	}
	s = stkfree;
	stkfree = stkfree->next;
	unlock(&stklock);
	s->magic = STKMAGIC;
	return s;
}

static int
newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp)
{
	int id;
	Thread *t;
	Stack *s;

	if(stacksize < 32)
		sysfatal("bad stacksize %d", stacksize);
	t = _threadmalloc(sizeof(Thread), 1);
	s = stackalloc();
	s->thr = t;
	t->stk = (char*)s;
	t->stksize = STKSIZE;
	_threaddebugmemset(s->buf, 0xFE, sizeof s->buf);
	_threadinitstack(t, f, arg);
	t->proc = p;
	t->grp = grp;
	if(name)
		t->cmdname = strdup(name);
	t->id = nextID();
	id = t->id;
	t->next = (Thread*)~0;
	_threaddebug(DBGSCHED, "create thread %d.%d name %s", p->pid, t->id, name);
	lock(&p->lock);
	p->nthreads++;
	if(p->threads.head == nil)
		p->threads.head = t;
	else{
		t->prevt = p->threads.tail;
		t->prevt->nextt = t;
	}
	p->threads.tail = t;
	t->state = Ready;
	_threadready(t);
	unlock(&p->lock);
	return id;
}

static int
nextID(void)
{
	static Lock l;
	static int id;
	int i;

	lock(&l);
	i = ++id;
	unlock(&l);
	return i;
}
	
int
procrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag)
{
	Proc *p;
	int id;

	p = _threadgetproc();
	assert(p->newproc == nil);
	p->newproc = _newproc(f, arg, stacksize, nil, p->thread->grp, rforkflag);
	id = p->newproc->threads.head->id;
	_sched();
	return id;
}

int
proccreate(void (*f)(void*), void *arg, uint stacksize)
{
	return procrfork(f, arg, stacksize, 0);
}

void
_freeproc(Proc *p)
{
	Thread *t, *nextt;

	for(t = p->threads.head; t; t = nextt){
		if(t->cmdname)
			free(t->cmdname);
		assert(t->stk != nil);
		_stackfree((Stack*)t->stk);
		nextt = t->nextt;
		free(t);
	}
	free(p);
}

/* 
 * Create a new thread and schedule it to run.
 * The thread grp is inherited from the currently running thread.
 */
int
threadcreate(void (*f)(void *arg), void *arg, uint stacksize)
{
	return newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp());
}

/*
 * Create and initialize a new Proc structure with a single Thread
 * running inside it.  Add the Proc to the global process list.
 */
Proc*
_newproc(void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp, int rforkflag)
{
	Proc *p;

	p = _threadmalloc(sizeof *p, 1);
	p->pid = -1;
	p->rforkflag = rforkflag;
	newthread(p, f, arg, stacksize, name, grp);

	lock(&_threadpq.lock);
	if(_threadpq.head == nil)
		_threadpq.head = p;
	else
		*_threadpq.tail = p;
	_threadpq.tail = &p->next;
	unlock(&_threadpq.lock);
	return p;
}

