356 lines
8.3 KiB
C
356 lines
8.3 KiB
C
#include "common.h"
|
|
#include "dolphin/os.h"
|
|
|
|
extern int gcsetjmp(jmp_buf *jump);
|
|
extern void gclongjmp(jmp_buf *jump, int status);
|
|
|
|
#define EXEC_NORMAL 0
|
|
#define EXEC_SLEEP 1
|
|
#define EXEC_CHILDWATCH 2
|
|
#define EXEC_KILLED 3
|
|
|
|
static jmp_buf processjmpbuf;
|
|
static Process *processtop;
|
|
static Process *processcur;
|
|
static u16 processcnt;
|
|
u32 procfunc;
|
|
|
|
|
|
void HuPrcInit(void)
|
|
{
|
|
processcnt = 0;
|
|
processtop = NULL;
|
|
}
|
|
|
|
static void LinkProcess(Process** root, Process* process) {
|
|
Process* src_process = *root;
|
|
|
|
if (src_process && (src_process->prio >= process->prio)) {
|
|
while (src_process->next && src_process->next->prio >= process->prio) {
|
|
src_process = src_process->next;
|
|
}
|
|
|
|
process->next = src_process->next;
|
|
process->prev = src_process;
|
|
src_process->next = process;
|
|
if (process->next) {
|
|
process->next->prev = process;
|
|
}
|
|
} else {
|
|
process->next = (*root);
|
|
process->prev = NULL;
|
|
*root = process;
|
|
if (src_process) {
|
|
src_process->prev = process;
|
|
}
|
|
}
|
|
}
|
|
static void UnlinkProcess(Process **root, Process *process) {
|
|
if (process->next) {
|
|
process->next->prev = process->prev;
|
|
}
|
|
|
|
if (process->prev) {
|
|
process->prev->next = process->next;
|
|
}
|
|
|
|
else {
|
|
*root = process->next;
|
|
}
|
|
}
|
|
|
|
Process *HuPrcCreate(void (*func)(void), u16 prio, u32 stack_size, s32 extra_size)
|
|
{
|
|
Process *process;
|
|
s32 alloc_size;
|
|
void *heap;
|
|
if(stack_size == 0) {
|
|
stack_size = 2048;
|
|
}
|
|
alloc_size = HuMemMemoryAllocSizeGet(sizeof(Process))
|
|
+HuMemMemoryAllocSizeGet(stack_size)
|
|
+HuMemMemoryAllocSizeGet(extra_size);
|
|
if(!(heap = HuMemDirectMalloc(HEAP_SYSTEM, alloc_size))) {
|
|
OSReport("process> malloc error size %d\n", alloc_size);
|
|
return NULL;
|
|
}
|
|
HuMemHeapInit(heap, alloc_size);
|
|
process = HuMemMemoryAlloc(heap, sizeof(Process), 0xA5A5A5A5);
|
|
process->heap = heap;
|
|
process->exec = EXEC_NORMAL;
|
|
process->stat = 0;
|
|
process->prio = prio;
|
|
process->sleep_time = 0;
|
|
process->base_sp = ((u32)HuMemMemoryAlloc(heap, stack_size, 0xA5A5A5A5))+stack_size-8;
|
|
gcsetjmp(&process->jump);
|
|
process->jump.lr = (u32)func;
|
|
process->jump.sp = process->base_sp;
|
|
process->dtor = NULL;
|
|
process->user_data = NULL;
|
|
LinkProcess(&processtop, process);
|
|
process->child = NULL;
|
|
process->parent = NULL;
|
|
processcnt++;
|
|
return process;
|
|
}
|
|
|
|
void HuPrcChildLink(Process *parent, Process *child)
|
|
{
|
|
HuPrcChildUnlink(child);
|
|
if(parent->child) {
|
|
parent->child->first_child = child;
|
|
}
|
|
child->next_child = parent->child;
|
|
child->first_child = NULL;
|
|
parent->child = child;
|
|
child->parent = parent;
|
|
}
|
|
|
|
void HuPrcChildUnlink(Process *process)
|
|
{
|
|
if(process->parent) {
|
|
if(process->next_child) {
|
|
process->next_child->first_child = process->first_child;
|
|
}
|
|
if(process->first_child) {
|
|
process->first_child->next_child = process->next_child;
|
|
} else {
|
|
process->parent->child = process->next_child;
|
|
}
|
|
process->parent = NULL;
|
|
}
|
|
}
|
|
|
|
Process *HuPrcChildCreate(void (*func)(void), u16 prio, u32 stack_size, s32 extra_size, Process *parent)
|
|
{
|
|
Process *child = HuPrcCreate(func, prio, stack_size, extra_size);
|
|
HuPrcChildLink(parent, child);
|
|
return child;
|
|
}
|
|
|
|
void HuPrcChildWatch()
|
|
{
|
|
Process *curr = HuPrcCurrentGet();
|
|
if(curr->child) {
|
|
curr->exec = EXEC_CHILDWATCH;
|
|
if(!gcsetjmp(&curr->jump)) {
|
|
gclongjmp(&processjmpbuf, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
Process *HuPrcCurrentGet()
|
|
{
|
|
return processcur;
|
|
}
|
|
|
|
static int SetKillStatusProcess(Process *process)
|
|
{
|
|
if(process->exec != EXEC_KILLED) {
|
|
HuPrcWakeup(process);
|
|
process->exec = EXEC_KILLED;
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int HuPrcKill(Process *process)
|
|
{
|
|
if(process == NULL) {
|
|
process = HuPrcCurrentGet();
|
|
}
|
|
HuPrcChildKill(process);
|
|
HuPrcChildUnlink(process);
|
|
return SetKillStatusProcess(process);
|
|
}
|
|
|
|
void HuPrcChildKill(Process *process)
|
|
{
|
|
Process *child = process->child;
|
|
while(child) {
|
|
if(child->child) {
|
|
HuPrcChildKill(child);
|
|
}
|
|
SetKillStatusProcess(child);
|
|
child = child->next_child;
|
|
}
|
|
process->child = NULL;
|
|
}
|
|
|
|
static void gcTerminateProcess(Process *process)
|
|
{
|
|
if(process->dtor) {
|
|
process->dtor();
|
|
}
|
|
UnlinkProcess(&processtop, process);
|
|
processcnt--;
|
|
gclongjmp(&processjmpbuf, 2);
|
|
}
|
|
|
|
void HuPrcEnd()
|
|
{
|
|
Process *process = HuPrcCurrentGet();
|
|
HuPrcChildKill(process);
|
|
HuPrcChildUnlink(process);
|
|
gcTerminateProcess(process);
|
|
}
|
|
|
|
void HuPrcSleep(s32 time)
|
|
{
|
|
Process *process = HuPrcCurrentGet();
|
|
if(time != 0 && process->exec != EXEC_KILLED) {
|
|
process->exec = EXEC_SLEEP;
|
|
process->sleep_time = time;
|
|
}
|
|
if(!gcsetjmp(&process->jump)) {
|
|
gclongjmp(&processjmpbuf, 1);
|
|
}
|
|
}
|
|
|
|
void HuPrcVSleep()
|
|
{
|
|
Process *process = HuPrcCurrentGet();
|
|
if(!gcsetjmp(&process->jump)) {
|
|
gclongjmp(&processjmpbuf, 1);
|
|
}
|
|
}
|
|
|
|
void HuPrcWakeup(Process *process)
|
|
{
|
|
process->sleep_time = 0;
|
|
}
|
|
|
|
void HuPrcDestructorSet2(Process *process, void (*func)(void))
|
|
{
|
|
process->dtor = func;
|
|
}
|
|
|
|
void HuPrcDestructorSet(void (*func)(void))
|
|
{
|
|
Process *process = HuPrcCurrentGet();
|
|
process->dtor = func;
|
|
}
|
|
|
|
void HuPrcCall(int tick)
|
|
{
|
|
Process *process;
|
|
int ret;
|
|
processcur = processtop;
|
|
ret = gcsetjmp(&processjmpbuf);
|
|
while(1) {
|
|
switch(ret) {
|
|
case 2:
|
|
HuMemDirectFree(processcur->heap);
|
|
case 1:
|
|
if(((u8 *)(processcur->heap))[4] != 165) {
|
|
printf("stack overlap error.(process pointer %x)\n", processcur);
|
|
while(1);
|
|
} else {
|
|
processcur = processcur->next;
|
|
}
|
|
break;
|
|
}
|
|
process = processcur;
|
|
if(!process) {
|
|
return;
|
|
}
|
|
procfunc = process->jump.lr;
|
|
if((process->stat & 0x3) && process->exec != EXEC_KILLED) {
|
|
ret = 1;
|
|
continue;
|
|
}
|
|
switch(process->exec) {
|
|
case EXEC_SLEEP:
|
|
if(process->sleep_time > 0) {
|
|
process->sleep_time -= tick;
|
|
if(process->sleep_time <= 0) {
|
|
process->sleep_time = 0;
|
|
process->exec = EXEC_NORMAL;
|
|
}
|
|
}
|
|
ret = 1;
|
|
break;
|
|
|
|
case EXEC_CHILDWATCH:
|
|
if(process->child) {
|
|
ret = 1;
|
|
} else {
|
|
process->exec = EXEC_NORMAL;
|
|
ret = 0;
|
|
}
|
|
break;
|
|
|
|
case EXEC_KILLED:
|
|
process->jump.lr = (u32)HuPrcEnd;
|
|
case EXEC_NORMAL:
|
|
gclongjmp(&process->jump, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void *HuPrcMemAlloc(s32 size)
|
|
{
|
|
Process *process = HuPrcCurrentGet();
|
|
return HuMemMemoryAlloc(process->heap, size, 0xA5A5A5A5);
|
|
}
|
|
|
|
void HuPrcMemFree(void *ptr)
|
|
{
|
|
HuMemMemoryFree(ptr, 0xA5A5A5A5);
|
|
}
|
|
|
|
void HuPrcSetStat(Process *process, u16 value)
|
|
{
|
|
process->stat |= value;
|
|
}
|
|
|
|
void HuPrcResetStat(Process *process, u16 value)
|
|
{
|
|
process->stat &= ~value;
|
|
}
|
|
|
|
void HuPrcAllPause(int flag)
|
|
{
|
|
Process *process = processtop;
|
|
if(flag) {
|
|
while(process != NULL) {
|
|
if(!(process->stat & 0x4)) {
|
|
HuPrcSetStat(process, 0x1);
|
|
}
|
|
|
|
process = process->next;
|
|
}
|
|
} else {
|
|
while(process != NULL) {
|
|
if(process->stat & 0x1) {
|
|
HuPrcResetStat(process, 0x1);
|
|
}
|
|
|
|
process = process->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
void HuPrcAllUPause(int flag)
|
|
{
|
|
Process *process = processtop;
|
|
if(flag) {
|
|
while(process != NULL) {
|
|
if(!(process->stat & 0x8)) {
|
|
HuPrcSetStat(process, 0x2);
|
|
}
|
|
|
|
process = process->next;
|
|
}
|
|
} else {
|
|
while(process != NULL) {
|
|
if(process->stat & 0x2) {
|
|
HuPrcResetStat(process, 0x2);
|
|
}
|
|
|
|
process = process->next;
|
|
}
|
|
}
|
|
}
|