#undef INT_TOC5
#define INT_TOC5 PM_TaskSwitch // set task switch interrupt vector
// -----------------------------------------
SECT SECT_ZEROPAGE
*
* MODULE PROCMAN.ASM
*
PM_CurrentProcess RMB 2 // store for corrent process
PM_TB_MainProcess RMB PM_LEN_TB // process block for first process
PM_TempSP RMB 2 // for temporary SP storage
// -----------------------------------------
SECT SECT_INIT
*
* MODULE PROCMAN.ASM
*
JSR SIO_PutString
FCC 'PM: Initialising...'
FCB 13,10,0
LDX #PM_TB_MainProcess // task block for first process
STX PM_CurrentProcess // make it the current process,
STX PM_OFS_TB_NEXT,X // the next process,
STX PM_OFS_TB_PREV,X // and the previous process
LDD #DEFAULT_TICKS
STD PM_OFS_TB_TICKS,X // give it the default number of ticks
LDD #NULL
STD PM_OFS_TB_MEMLIST,X // owns no memory
LDD #INIT_STACK
STD PM_OFS_TB_TOS,X // top of process's stack
JSR SIO_PutString
FCC 'PM: Init task created'
FCB 13,10,0
LDD TCNT // get the current timer count
ADDD PM_OFS_TB_TICKS,X // add time slice of process
STD TOC5 // set output compare register
BSET TMSK1 TMSK1_OC5I // enable interrupts on OC5
LDAA #TFLG1_OC5F
STAA TFLG1 // clear the OC5F flag
CLI // enable interrupts
JSR SIO_PutString
FCC 'PM: Switcher started'
FCB 13,10,0
// -----------------------------------------
SECT SECT_CODE
*
* MODULE PROCMAN.ASM
*
PM_TaskSwitch // task switch interrupt handler
LDX PM_CurrentProcess
STS PM_OFS_TB_SP,X // store stack pointer for outgoing process
LDX PM_OFS_TB_NEXT,X // get incoming process
STX PM_CurrentProcess // set incoming process as current process
LDS PM_OFS_TB_SP,X // load stack pointer for incoming process
LDD TCNT
ADDD PM_OFS_TB_TICKS,X // set TOC5 to end of time slice
STD TOC5
LDAA #TFLG1_OC5F // reset OC5F flag to allow next interrupt
STAA TFLG1
RTI // switch to next process
_idle // void idle(); gives up the remainder of the current time slice
PM_Idle
PM_SwitchNow // causes an immediate task switch
PSHY // push all registers as if interrupt had
PSHX // occurred (PC is already on stack)
PSHA // these seem backwards but
PSHB // the hc11 is just weird...
TPA
PSHA
SEI // disable interrupts
BRA PM_TaskSwitch // switch task
PM_AddTask // adds task whos task block is pointed to by X to task list
// the 'next' and 'prev' fields are changed, all others must
// be set up beforehand
// Adds process between current process and next
LDD PM_CurrentProcess
STD PM_OFS_TB_PREV,X // set up 'Prev' in new process
XGDX // X -> current process, D -> new process
XGDY // Y -> new process
SEI // interrupts must be disabled here
LDD PM_OFS_TB_NEXT,X // get process to be after new process
STD PM_OFS_TB_NEXT,Y // set up 'Next' in new process
XGDY // D -> new process, Y -> proc to be after new proc
STD PM_OFS_TB_NEXT,X // set up 'Next' in current process
STD PM_OFS_TB_PREV,Y // set up 'Prev' in process after new
XGDX // point X back to new process
CLI
RTS
_fork // int fork(int stacksize)
// forks, returning 0 to the child and the child PID to the parent
// the child's stack size is set to the given size in bytes
TSX
LDD 2,X
BSR PM_Fork
XGDX
RTS
PM_Fork // UNIX style fork
// D holds size of new stack
// Returns to child with D=0
// Returns to parent with X=child PID
// X=PM_FORKFAILED if fork failed
LDX #MM_Locked
JSR PM_LockX
JSR MM_BlockAlloc // try to allocate space for stack
BNE PM_Fork_Failed_
JMP PM_Fork_Failed
PM_Fork_Failed_
XGDX
XGDY // Y points to stack BLOCK
LDD #PM_LEN_TB
JSR MM_BlockAlloc // allocate space for task block
BNE PM_Fork_Failed2_
JMP PM_Fork_Failed2
PM_Fork_Failed2_
LDAA #MM_BLOCK_TYPE_TB
STAA MM_OFS_BLOCK_TYPE,X // set memory block type to task block
XGDX
ADDD #MM_BLOCK_LEN
XGDX // X now points to start of task block
LDD #NULL
STD PM_OFS_TB_MEMLIST,X // new process owns no memory
STY PM_OFS_TB_STACK,X // set start of stack BLOCK
PSHY
PULA
PULB
ADDD MM_OFS_BLOCK_SIZE,Y
XGDY
DEY // Y now holds top of stack
JSR SIO_PutString
FCC 'PM: Fork child TOS='
FCB SIO_Put_Y
FCC ' PID='
FCB SIO_Put_X,13,10,0
STY PM_OFS_TB_TOS,X // set top of stack
STS PM_TempSP
LDD PM_OFS_TB_TOS,X
LDS PM_OFS_TB_TOS,X // set SP to top of new stack
XGDX // store new TB in D
LDY PM_CurrentProcess
LDX PM_OFS_TB_TOS,Y // set X to top of current stack
XGDY // Y holds new TB
PM_Fork_CopyStack // copy the stack from the old to the new task
CPX PM_TempSP // check if finished
BEQ PM_Fork_StackCopied
LDAA 0,X // get a byte from the old stack
DEX
PSHA // put the byte onto the new stack
BRA PM_Fork_CopyStack
PM_Fork_StackCopied
// set up child stack contents ready for task switch
LDX #NULL
PSHY // value unimportant
PSHX // X=0 means process is child
PSHA // Values unimportant
PSHB //
TPA //
PSHA //
XGDY
XGDX // X points to child's TB
STS PM_OFS_TB_SP,X // store SP for new process
LDS PM_TempSP // restore parent's SP
LDY PM_CurrentProcess
LDD PM_OFS_TB_TICKS,Y
STD PM_OFS_TB_TICKS,X // child starts with same priority as parent
LDD PM_OFS_TB_STATUS,Y
STD PM_OFS_TB_STATUS,X // and same status
JSR PM_AddTask // add child's task to task list
BRA PM_Fork_End
PM_Fork_Failed2
// DEALLOCATE STACK MEMORY!!!
PM_Fork_Failed
LDX #PM_FORKFAILED
PM_Fork_End
PSHX
LDX #MM_Locked
JSR PM_UnlockX
PULX
CPX #NULL
RTS