Skip to content

Commit

Permalink
feat: update for ex_9_1
Browse files Browse the repository at this point in the history
  • Loading branch information
ludics committed Sep 16, 2023
1 parent 1309e3b commit 4e9f648
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 16 deletions.
3 changes: 2 additions & 1 deletion code/exercises/ex_9_1/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ struct context {
reg_t t6;
};

extern int task_create(void (*task)(void));
extern int task_create(void (*task)(void* param), void *param, uint8_t priority);
extern void task_delay(volatile int count);
extern void task_yield();
extern void task_exit();

#endif /* __OS_H__ */
84 changes: 74 additions & 10 deletions code/exercises/ex_9_1/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,22 @@ extern void switch_to(struct context *next);
*/
uint8_t __attribute__((aligned(16))) task_stack[MAX_TASKS][STACK_SIZE];
struct context ctx_tasks[MAX_TASKS];
uint8_t task_priorities[MAX_TASKS];

#define TASK_EMPTY 0
#define TASK_READY 1
#define TASK_RUNNING 2
#define TASK_BLOCKED 3
#define TASK_EXITED 4

uint8_t task_status[MAX_TASKS];

#define task_schedulable(task_id) (task_status[task_id] == TASK_READY || task_status[task_id] == TASK_RUNNING)

/*
* _top is used to mark the max available position of ctx_tasks
* _current is used to point to the context of current task
*/
static int _top = 0;
static int _current = -1;

static void w_mscratch(reg_t x)
Expand All @@ -27,20 +37,53 @@ static void w_mscratch(reg_t x)
void sched_init()
{
w_mscratch(0);
for (int i = 0; i < MAX_TASKS; i++) {
task_status[i] = TASK_EMPTY;
task_priorities[i] = 0xff;
}
}

/*
* implment a simple cycle FIFO schedular
*/
void schedule()
{
if (_top <= 0) {
panic("Num of task should be greater than zero!");
// 先扫描获取最高优先级
int priority = 0xff;
for (int i = 0; i < MAX_TASKS; i++) {
if (task_schedulable(i) && task_priorities[i] < priority) {
priority = task_priorities[i];
}
}
// printf("priority: %d\n", priority);
// 扫描获取最高优先级的任务id,可能有多个,round-robin
int next_task_id = -1;
for (int i = 0; i < MAX_TASKS; i++) {
if (task_schedulable(i) && task_priorities[i] == priority) {
if (i > _current) {
next_task_id = i;
break;
}
}
}
if (next_task_id == -1) {
for (int i = 0; i < MAX_TASKS; i++) {
if (task_schedulable(i) && task_priorities[i] == priority) {
next_task_id = i;
break;
}
}
}
if (next_task_id == -1) {
panic("no task to run!\n");
return;
}

_current = (_current + 1) % _top;
if (next_task_id == _current) {
return;
}
_current = next_task_id;
struct context *next = &(ctx_tasks[_current]);
task_status[_current] = TASK_RUNNING;
switch_to(next);
}

Expand All @@ -52,25 +95,46 @@ void schedule()
* 0: success
* -1: if error occured
*/
int task_create(void (*start_routin)(void))
int task_create(void (*start_routin)(void* param), void* param, uint8_t priority)
{
if (_top < MAX_TASKS) {
ctx_tasks[_top].sp = (reg_t) &task_stack[_top][STACK_SIZE];
ctx_tasks[_top].ra = (reg_t) start_routin;
_top++;
int task_id = -1;
for (int i = 0; i < MAX_TASKS; i++) {
if (task_status[i] == TASK_EMPTY || task_status[i] == TASK_EXITED) {
task_id = i;
break;
}
}
if (task_id != -1) {
ctx_tasks[task_id].sp = (reg_t) &task_stack[task_id][STACK_SIZE];
if (param != NULL) {
ctx_tasks[task_id].a0 = (reg_t) param;
}
ctx_tasks[task_id].ra = (reg_t) start_routin;
task_priorities[task_id] = priority;
task_status[task_id] = TASK_READY;
return 0;
} else {
return -1;
}
}

/*
* DESCRIPTION
* task_exit() causes the currently executing task to exit.
*/
void task_exit(void) {
task_status[_current] = TASK_EXITED;
schedule();
}

/*
* DESCRIPTION
* task_yield() causes the calling task to relinquish the CPU and a new
* task gets to run.
*/
void task_yield()
{
task_status[_current] = TASK_READY;
schedule();
}

Expand Down
33 changes: 28 additions & 5 deletions code/exercises/ex_9_1/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#define DELAY 1000

void user_task0(void)
void user_task0(void* param)
{
uart_puts("Task 0: Created!\n");
while (1) {
Expand All @@ -12,7 +12,7 @@ void user_task0(void)
}
}

void user_task1(void)
void user_task1(void* param)
{
uart_puts("Task 1: Created!\n");
while (1) {
Expand All @@ -22,10 +22,33 @@ void user_task1(void)
}
}

void user_task(void* param) {
int task_id = (int)param;
printf("Task %d: Created!\n", task_id);
int iter_cnt = task_id;
while (1) {
printf("Task %d: Running...\n", task_id);
task_delay(DELAY);
task_yield();
if (iter_cnt-- == 0) {
break;
}
}
printf("Task %d: Finished!\n", task_id);
task_exit();
}

/* NOTICE: DON'T LOOP INFINITELY IN main() */
void os_main(void)
{
task_create(user_task0);
task_create(user_task1);
// task_create(user_task0, NULL, 255);
task_create(user_task1, NULL, 255);
task_create(user_task, (void *)3, 0);
task_create(user_task, (void *)4, 0);
task_create(user_task, (void *)5, 0);
task_create(user_task, (void *)6, 1);
task_create(user_task, (void *)7, 2);
task_create(user_task, (void *)8, 3);
task_create(user_task, (void *)9, 4);
task_create(user_task, (void *)10, 5);
}

0 comments on commit 4e9f648

Please sign in to comment.