2022-05-22 01:55:56 +02:00
|
|
|
; task switching routines
|
|
|
|
|
|
|
|
; add a new task to the queue and jump to it immediately
|
|
|
|
; inputs:
|
|
|
|
; r0: task ID
|
2022-06-26 01:32:32 +02:00
|
|
|
; r1: initial instruction pointer
|
|
|
|
; r2: initial stack pointer (remember that the stack grows down!)
|
2022-06-25 01:37:43 +02:00
|
|
|
; r3: pointer to code block to free when task ends, or zero for none
|
|
|
|
; r4: pointer to stack block to free when task ends, or zero for none
|
2022-05-22 01:55:56 +02:00
|
|
|
; outputs:
|
|
|
|
; none
|
|
|
|
new_task:
|
2022-06-24 00:16:55 +02:00
|
|
|
; mark this task ID as used
|
|
|
|
bse [task_id_bitmap], r0
|
2022-05-22 01:55:56 +02:00
|
|
|
|
2022-06-25 01:37:43 +02:00
|
|
|
mov r6, r4 ; stack block pointer
|
|
|
|
mov r5, r3 ; code block pointer
|
2022-06-24 00:16:55 +02:00
|
|
|
mov r4, r2 ; stack pointer
|
|
|
|
mov r3, r1 ; instruction pointer
|
|
|
|
mov r2, r0 ; task ID
|
2022-05-22 01:55:56 +02:00
|
|
|
|
2022-06-24 00:16:55 +02:00
|
|
|
; add to the queue
|
2022-05-22 01:55:56 +02:00
|
|
|
mov r0, [task_queue_ptr]
|
|
|
|
call task_store
|
|
|
|
mov [task_queue_ptr], r0
|
|
|
|
|
|
|
|
; fall-through
|
|
|
|
|
|
|
|
; switch to the next task in the queue
|
2023-02-03 01:21:29 +01:00
|
|
|
; no registers are saved upon task yield
|
|
|
|
; if a register must be saved across a yield, push it before the yield and pop it after the yield
|
2022-05-22 01:55:56 +02:00
|
|
|
; inputs:
|
|
|
|
; none
|
|
|
|
; outputs:
|
|
|
|
; none
|
|
|
|
yield_task:
|
|
|
|
; add the current task back into the queue
|
|
|
|
mov r0, current_task ; get the current task struct
|
|
|
|
call task_load
|
|
|
|
pop r3 ; pop the return address off of the stack
|
|
|
|
mov r4, rsp
|
|
|
|
mov r0, [task_queue_ptr]
|
|
|
|
call task_store
|
|
|
|
mov [task_queue_ptr], r0
|
|
|
|
|
|
|
|
jmp yield_task_0
|
|
|
|
|
2023-02-08 00:58:13 +01:00
|
|
|
; push all registers and switch to the next task in the queue
|
|
|
|
; inputs:
|
|
|
|
; none
|
|
|
|
; outputs:
|
|
|
|
; none
|
|
|
|
save_state_and_yield_task:
|
|
|
|
push rfp
|
|
|
|
push r31
|
|
|
|
push r30
|
|
|
|
push r29
|
|
|
|
push r28
|
|
|
|
push r27
|
|
|
|
push r26
|
|
|
|
push r25
|
|
|
|
push r24
|
|
|
|
push r23
|
|
|
|
push r22
|
|
|
|
push r21
|
|
|
|
push r20
|
|
|
|
push r19
|
|
|
|
push r18
|
|
|
|
push r17
|
|
|
|
push r16
|
|
|
|
push r15
|
|
|
|
push r14
|
|
|
|
push r13
|
|
|
|
push r12
|
|
|
|
push r11
|
|
|
|
push r10
|
|
|
|
push r9
|
|
|
|
push r8
|
|
|
|
push r7
|
|
|
|
push r6
|
|
|
|
push r5
|
|
|
|
push r4
|
|
|
|
push r3
|
|
|
|
push r2
|
|
|
|
push r1
|
|
|
|
push r0
|
|
|
|
|
|
|
|
call yield_task
|
|
|
|
|
|
|
|
pop r0
|
|
|
|
pop r1
|
|
|
|
pop r2
|
|
|
|
pop r3
|
|
|
|
pop r4
|
|
|
|
pop r5
|
|
|
|
pop r6
|
|
|
|
pop r7
|
|
|
|
pop r8
|
|
|
|
pop r9
|
|
|
|
pop r10
|
|
|
|
pop r11
|
|
|
|
pop r12
|
|
|
|
pop r13
|
|
|
|
pop r14
|
|
|
|
pop r15
|
|
|
|
pop r16
|
|
|
|
pop r17
|
|
|
|
pop r18
|
|
|
|
pop r19
|
|
|
|
pop r20
|
|
|
|
pop r21
|
|
|
|
pop r22
|
|
|
|
pop r23
|
|
|
|
pop r24
|
|
|
|
pop r25
|
|
|
|
pop r26
|
|
|
|
pop r27
|
|
|
|
pop r28
|
|
|
|
pop r29
|
|
|
|
pop r30
|
|
|
|
pop r31
|
|
|
|
pop rfp
|
|
|
|
ret
|
|
|
|
|
2022-05-22 01:55:56 +02:00
|
|
|
; switch to the next task without adding the current task back into the queue
|
2022-06-25 01:37:43 +02:00
|
|
|
; this will automatically free the task's code and stack blocks
|
2022-05-22 01:55:56 +02:00
|
|
|
; inputs:
|
|
|
|
; none
|
|
|
|
; outputs:
|
|
|
|
; none
|
|
|
|
end_current_task:
|
|
|
|
mov r0, current_task ; get the current task struct
|
|
|
|
call task_load
|
|
|
|
bcl [task_id_bitmap], r2 ; mark this task ID as unused
|
2022-06-25 01:37:43 +02:00
|
|
|
mov r0, r5 ; code block pointer
|
|
|
|
cmp r0, 0
|
|
|
|
ifnz call free_memory
|
|
|
|
mov r0, r6 ; stack block pointer
|
2022-06-24 01:38:05 +02:00
|
|
|
cmp r0, 0
|
|
|
|
ifnz call free_memory
|
2022-06-24 00:16:55 +02:00
|
|
|
end_current_task_no_mark_no_free:
|
2022-05-22 01:55:56 +02:00
|
|
|
pop r0 ; pop the return address off of the stack
|
2022-05-22 02:04:39 +02:00
|
|
|
|
|
|
|
cmp [task_queue_ptr], task_queue_bottom
|
|
|
|
ifz jmp task_empty
|
2022-05-22 01:55:56 +02:00
|
|
|
yield_task_0:
|
|
|
|
mov r0, task_queue_bottom
|
|
|
|
call task_load
|
|
|
|
mov r0, current_task
|
|
|
|
call task_store
|
|
|
|
|
|
|
|
mov r1, task_queue_bottom
|
|
|
|
yield_task_1:
|
|
|
|
add r1, TASK_SIZE
|
|
|
|
|
|
|
|
cmp [task_queue_ptr], r1
|
|
|
|
ifz jmp yield_task_2
|
|
|
|
|
|
|
|
mov r0, r1
|
|
|
|
call task_load
|
|
|
|
|
|
|
|
mov r0, r1
|
|
|
|
sub r0, TASK_SIZE
|
|
|
|
call task_store
|
|
|
|
|
|
|
|
jmp yield_task_1
|
|
|
|
yield_task_2:
|
|
|
|
mov r0, current_task
|
|
|
|
call task_load
|
|
|
|
sub [task_queue_ptr], TASK_SIZE
|
|
|
|
|
|
|
|
mov rsp, r4
|
|
|
|
jmp r3
|
|
|
|
|
|
|
|
; get the next unused task ID, starting at 1
|
|
|
|
; inputs:
|
|
|
|
; none
|
|
|
|
; outputs:
|
|
|
|
; r0: task ID, or zero if all IDs are used
|
|
|
|
get_unused_task_id:
|
|
|
|
mov r0, 1
|
|
|
|
get_unused_task_id_loop:
|
|
|
|
bts [task_id_bitmap], r0
|
|
|
|
ifz ret
|
|
|
|
inc r0
|
|
|
|
cmp r0, 32
|
|
|
|
iflt jmp get_unused_task_id_loop
|
2022-06-25 02:40:52 +02:00
|
|
|
; if we reach this point, then all task IDs are used
|
2022-05-22 01:55:56 +02:00
|
|
|
mov r0, 0
|
|
|
|
ret
|
|
|
|
|
2022-06-25 02:40:52 +02:00
|
|
|
; get the task ID of the currently running task
|
|
|
|
; inputs:
|
|
|
|
; none
|
|
|
|
; outputs:
|
|
|
|
; r0: task ID
|
|
|
|
get_current_task_id:
|
|
|
|
push r2
|
|
|
|
push r3
|
|
|
|
push r4
|
|
|
|
push r5
|
|
|
|
push r6
|
|
|
|
|
|
|
|
mov r0, current_task
|
|
|
|
call task_load
|
|
|
|
mov r0, r2
|
|
|
|
|
|
|
|
pop r6
|
|
|
|
pop r5
|
|
|
|
pop r4
|
|
|
|
pop r3
|
|
|
|
pop r2
|
|
|
|
ret
|
|
|
|
|
2022-08-12 02:35:13 +02:00
|
|
|
; check if a task ID is used
|
|
|
|
; inputs:
|
|
|
|
; r0: task ID
|
|
|
|
; outputs:
|
|
|
|
; Z flag: set if unused, reset if used
|
|
|
|
is_task_id_used:
|
|
|
|
bts [task_id_bitmap], r0
|
|
|
|
ret
|
|
|
|
|
2022-05-22 01:55:56 +02:00
|
|
|
task_load:
|
|
|
|
mov r2, [r0] ; task ID
|
|
|
|
add r0, 4
|
|
|
|
mov r3, [r0] ; instruction pointer
|
|
|
|
add r0, 4
|
|
|
|
mov r4, [r0] ; stack pointer
|
|
|
|
add r0, 4
|
2022-06-25 01:37:43 +02:00
|
|
|
mov r5, [r0] ; code block pointer
|
|
|
|
add r0, 4
|
|
|
|
mov r6, [r0] ; stack block pointer
|
2022-06-24 00:16:55 +02:00
|
|
|
add r0, 4
|
2022-05-22 01:55:56 +02:00
|
|
|
ret
|
|
|
|
|
|
|
|
task_store:
|
|
|
|
mov [r0], r2 ; task ID
|
|
|
|
add r0, 4
|
|
|
|
mov [r0], r3 ; instruction pointer
|
|
|
|
add r0, 4
|
|
|
|
mov [r0], r4 ; stack pointer
|
|
|
|
add r0, 4
|
2022-06-25 01:37:43 +02:00
|
|
|
mov [r0], r5 ; code block pointer
|
|
|
|
add r0, 4
|
|
|
|
mov [r0], r6 ; stack block pointer
|
2022-06-24 00:16:55 +02:00
|
|
|
add r0, 4
|
2022-05-22 01:55:56 +02:00
|
|
|
ret
|
|
|
|
|
|
|
|
task_empty:
|
|
|
|
mov r0, task_panic_str
|
|
|
|
mov r1, task_queue_bottom ; show the address of the task queue in the panic brk output
|
|
|
|
mov r2, [task_queue_ptr] ; show the the task queue pointer in the panic brk output
|
|
|
|
call panic
|
|
|
|
|
2022-06-24 00:43:36 +02:00
|
|
|
task_panic_str: data.str "Scheduler starved, task queue empty!" data.8 10 data.8 0
|
2022-05-22 01:55:56 +02:00
|
|
|
|
2022-06-25 01:37:43 +02:00
|
|
|
const TASK_SIZE: 20
|
2022-05-22 01:55:56 +02:00
|
|
|
task_id_bitmap: data.32 0
|
|
|
|
current_task:
|
|
|
|
data.32 0 ; task ID
|
|
|
|
data.32 0 ; instruction pointer
|
|
|
|
data.32 0 ; stack pointer
|
2022-06-25 01:37:43 +02:00
|
|
|
data.32 0 ; code block pointer
|
|
|
|
data.32 0 ; stack block pointer
|
2022-05-22 01:55:56 +02:00
|
|
|
task_queue_ptr: data.32 task_queue_bottom
|
2022-06-25 01:37:43 +02:00
|
|
|
task_queue_bottom: data.fill 0, 640 ; 32 tasks * 5 entries per task * 4 bytes per word = 640
|