task * tk_init(stack_t * st_base, int st_size) { task *tk; /* pointer to the first task */ stack_t * sp; /* create the first task */ tk = (task*)TK_ALLOC(sizeof(struct task)); /* return immediately if task structure could not be * allocated. The caller must handle this scenario. */ if (!tk) { ++tk_allocfail; return(tk); } tk_cur = tk; /* It is the currently running task */ /* Task is running thus does not need to be awakened. */ tk->tk_flags = TF_MAIN; /* mark it as using system stack */ tk->tk_name = "Main"; tk->tk_next = tk; /* task is only one in list */ tk->tk_count = 0; tk->tk_size = st_size; tk->tk_stack = st_base; /* fill the system stack with the guardword */ sp = tk_getsp(); #ifdef STK_TOPDOWN /* Intel x86 "top down" stack */ while (sp > st_base) { sp--; /* stop when sp == base */ *sp = GUARDWORD; } #elif STK_BOTTOMUP /* stack moves from bottom up */ { stack_t * stacktop = st_base + st_size/sizeof(stack_t); while (sp < stacktop) { sp++; *sp = GUARDWORD; } } #else #error You must define a stack type! (STK_TOPDOWN or STK_BOTTOMUP) #endif tk->tk_guard = sp; /* set address for stack check */ #ifdef DEBUG if (TDEBUG) dprintf("tk_init: Initial stack size = %d\n", tk->tk_size); #endif return(tk); }
TASK * tk_new(TASK *prev_tk, void (*start)(void *), int stksiz, char *name, uint32_t flags, void *arg) { TASK *tk; /* a pointer to the new task */ int i; /* find unused task struct */ tk = tk_tasklist; for (i = 0; i < tk_max_tasks; i++) { if (tk->tk_flags == 0) break; tk++; } if (i >= tk_max_tasks) { ++tk_allocfail; return ((TASK *)NULL); /* if no memory left, return null */ } #ifndef SUPERLOOP if (flags & TF_MAIN) /* task will use system stack */ { tk->tk_size = stksiz; tk->tk_stack = tk_getspbase() - (stksiz / sizeof(stack_t)); tk->tk_fp = tk_getsp(); } else /* task will use private stack */ { tk->tk_size = stksiz; tk->tk_stack = (stack_t *)STK_ALLOC(stksiz); if (tk->tk_stack == (stack_t *)NULL) { ++tk_allocfail; return ((TASK *)NULL); } /* set it up to run */ tk->tk_fp = tk_frame(tk, start, arg); } /* fill stack with guardword */ { stack_t *sp = tk->tk_fp; /* pointer to task stack area for fill */ #ifdef STK_TOPDOWN /* Intel x86 "top down" stack */ sp--; while (sp > tk->tk_stack) { sp--; *sp = GUARDWORD; } tk->tk_guard = sp; #else /* stack moves from bottom up */ dtrap(); /* untested */ x = stksiz - (sp - tk->tk_stack); /* bytes to fill */ x = x/(sizeof(stack_t)); x++; sp++; while (x++ > 0) *sp++ = GUARDWORD; #endif } /* add the new task to the list of tasks */ if (prev_tk) { tk->tk_next = prev_tk->tk_next; /* Fit it in after prev_tk. */ prev_tk->tk_next = tk; } else /* insert task before the current task */ { prev_tk = tk_cur; if (prev_tk == (TASK *)NULL) { tk->tk_next = tk; tk_cur = tk; } else { while (prev_tk->tk_next != tk_cur) prev_tk = prev_tk->tk_next; tk->tk_next = prev_tk->tk_next; /* Fit it in after prev_tk */ prev_tk->tk_next = tk; } } tk->tk_event = NULL; if ((tk->tk_semaphore = SEM_ALLOC()) == (IN_SEM *)NULL) { ++tk_allocfail; return ((TASK *)NULL); } #else /* SUPERLOOP */ tk->tk_flags |= TF_MAIN; tk->tk_func = start; tk->tk_param = arg; #endif /* SUPERLOOP */ tk->tk_name = name; /* Set its name */ tk->tk_count = 0; /* init the wakeup count */ tk->tk_waketick = 0; tk->tk_flags |= (flags | TF_ACTIVE); #ifndef SUPERLOOP TK_SUSPEND(tk); #endif return (tk); }