#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