root/tasking.s

/* [<][>][^][v][top][bottom][index][help] */
        .include "memory.inc"
        .include "kstructs.inc"

        .text

        .global TaskSwitch
        .global SpecificTaskSwitch
        .global CreateKernelTask

#===================================================================================================
# Save the current task, restore the next ready one (if there is one!), and initiate a task switch.
# If there isn't another runnable task, and the current task is still runnable, just continue.
# If there's no runnable task at all then halt the processor until the next interrupt.
#===================================================================================================
TaskSwitch:
.again:
        mov  currentTask, %r15
        push %r15
        push %rax
        push %rdx
        call moveTaskToEndOfQueue
        pop  %rdx
        pop  %rax
# Is there another task ready to run?
.nexttask:
        mov  runnableTasks, %r15
        cmp  $0, %r15
        jne  TS1
# There's no other runnable task, so pick the low-priority task
        mov  lowPriTask, %r15
        jmp  TS1

#==============================================================
# Save the current task and switch to the one specified in R15
#==============================================================
SpecificTaskSwitch:
# Save task state
        push %r15
TS1:    xchg currentTask, %r15
        mov  %rax, TS.rax(%r15)
        mov  %rbx, TS.rbx(%r15)
        mov  %rcx, TS.rcx(%r15)
        mov  %rdx, TS.rdx(%r15)
        mov  %rbp, TS.rbp(%r15)
        mov  %rsi, TS.rsi(%r15)
        mov  %rdi, TS.rdi(%r15)
        mov  %r8,  TS.r8(%r15)
        mov  %r9,  TS.r9(%r15)
        mov  %r10, TS.r10(%r15)
        mov  %r11, TS.r11(%r15)
        mov  %r12, TS.r12(%r15)
        mov  %r13, TS.r13(%r15)
        mov  %r14, TS.r14(%r15)
        pop  %rax
        mov  %rax, TS.r15(%r15)
        mov  %ds,  TS.ds(%r15)
        mov  %cr3, %rax
        mov  %rax, TS.cr3(%r15)
        pop  %rcx
        mov  %rsp, TS.rsp(%r15)
# Restore task state
        mov  currentTask, %r15  # Actually the task to switch to (which we stored in currentTask)
        mov  TS.cr3(%r15), %rax
        mov  %rax, %cr3
        mov  TS.rsp(%r15), %rsp
        push %rcx
        mov  TS.rcx(%r15), %rcx
        mov  TS.rdx(%r15), %rdx
        mov  TS.rbp(%r15), %rbp
        mov  TS.rsi(%r15), %rsi
        mov  TS.rdi(%r15), %rdi
        mov  TS.r8(%r15), %r8
        mov  TS.r9(%r15), %r9
        mov  TS.r10(%r15), %r10
        mov  TS.r11(%r15), %r11
        mov  TS.r12(%r15), %r12
        mov  TS.r13(%r15), %r13
        mov  TS.r14(%r15), %r14
        mov  TS.ds(%r15), %ds
        mov  TS.rax(%r15), %rax
        mov  TS.rbx(%r15), %rbx
        mov  TS.r15(%r15), %r15
        ret

        .data

        .global currentTask
        .global TSS64

TSS64:  .long 0
        .long tempstack
        .rept 0x2C
        .long 0
        .endr

/* [<][>][^][v][top][bottom][index][help] */