#include <kernel.h>
#include <list.h>
#include <string.h>
struct thread_t SECTION(".task0") ALIGN(PAGE_SIZE) task0;
struct thread_t *current = &task0;
static struct list_t *ptask_list = &(task0.link);
volatile int switch_enable=0;
void task_add(struct thread_t *tsk)
{
list_insert(ptask_list, &tsk->link);
}
/*!!can not remove task0(idel task)*/
void task_remove(struct thread_t *tsk)
{
list_remove(&tsk->link);
}
#define GET_TASKQ_HDR taskq_next()
static thread_t *taskq_next()
{
static struct thread_t *qtaskpos = &task0;
qtaskpos = list_next(qtaskpos, link);
return qtaskpos;
}
static thread_t *get_thread_by_id(uint32_t tid)
{
struct thread_t *node;
KPRINTF("BUG!!");
list_for_each_entry(node, ptask_list, link)
{
if(node->id == tid)
return node;
}
return NULL;
}
uint8_t *task_switch(struct pt_regs *asmregs)
{
uint8_t *regs = (uint8_t *)asmregs;
if(!switch_enable)
return regs;
current->stack_top = regs;
current=GET_TASKQ_HDR;
if(current->state==FINISHED)
{
current->state=ZOMBIE;
/*BUG,....*/
task_remove(current);
current=GET_TASKQ_HDR;
}
if((current->state==BLOCKED) || (current->state==WAITING))
current=GET_TASKQ_HDR;
current->state=RUNNING;
return (current->stack_top);
}
static uint32_t new_tid()
{
static uint32_t last_pid = 0;
return last_pid++;
}
static void thread_stack_push(thread_t *t, uint32_t val)
{
t->stack_top-=4;
*((uint32_t *)t->stack_top)=val;
}
static void thread_exit()
{
if(current->pid>0)
{
thread_t *parent= get_thread_by_id(current->pid);
if(parent)
{
if(parent->state==WAITING)
parent->state=RUNNING;
parent->num_child--;
}
}
while(current->num_child!=0)
current->state=WAITING;
current->state=FINISHED;
for(;;)
;
}
static void thread_run(void (* entry)(uint32_t), uint32_t args)
{
entry(args);
thread_exit();
}
static void init_thread(struct thread_t *t, void (* entry)(uint32_t), uint32_t args, priority_t p, int detached)
{
memset((char*)t, 0, sizeof(thread_t));
t->stack_top=t->stack+STACK_SIZE - 1; /*align the stack_top*/
if((current==NULL)||detached)
t->pid=0;
else
{
t->pid=current->id; /*put the parent id*/
current->num_child++;
}
t->id=new_tid();
t->prio=p;
thread_stack_push(t,args);
thread_stack_push(t,(uint32_t)entry);
thread_stack_push(t,(uint32_t)0); /*push a fake return address for thread func*/
t->stack_top -= sizeof(struct pt_regs);
struct pt_regs *context = (struct pt_regs *)t->stack_top;
context->gs = KERNEL_DS_SEL;//USER_DS_SEL;
context->fs = KERNEL_DS_SEL;//USER_DS_SEL;
context->es = KERNEL_DS_SEL;//USER_DS_SEL;
context->ds = KERNEL_DS_SEL;//USER_DS_SEL;
context->edi=0;
context->esi=0;
context->ebp=0;
context->esp=(uint32_t)t->stack_top;
context->ebx=0;
context->edx=0;
context->ecx=0;
context->eax=0;
context->eip=(uint32_t)thread_run;
//tt->err_code=0x;
context->cs=KERNEL_CS_SEL;//USER_CS_SEL;
context->eflags=0x0200;
t->state=CREATED;
}
thread_t *create_thread(void (* entry)(uint32_t),uint32_t args, priority_t p, int detached)
{
thread_t *t=kmalloc(sizeof(thread_t));
if(!t)
{
KPRINTF("Insufficient memory for Task creation\n");
return NULL;
}
init_thread(t, entry, args, p, detached);
task_add(t);
return t;
}
static void thread_init()
{
gdt_ptr_t gdt_desc;
store_gdt(&gdt_desc);
dump_gdt(&gdt_desc);
KPRINTF("thread_init\n");
init_thread(&task0, NULL, 0, IDLE_PRIO, 1);
list_init(&(task0.link));/*must after init_thread!!*/
switch_enable = 1;
}
INITFUNC(thread_init, INIT_THREAD);