1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2026-03-12 16:42:08 +00:00
Files
PLASMA/src/libsrc/fiber.pla
2018-01-24 21:40:41 -08:00

273 lines
5.5 KiB
Plaintext

//
// Cooperative multi-threading (fiber) scheduler
//
include "inc/cmdsys.plh"
//
// Maximum number of fibers
//
const MAX_FIBERS = 32
//
// Fiber states
//
const FIBER_UNAVAIL = 0
const FIBER_FREE = 1
const FIBER_HALT = 2
const FIBER_RUN = 3
byte fbrMax
byte fbrState[MAX_FIBERS]
byte fbrNext[MAX_FIBERS]
word fbrVMState[MAX_FIBERS]
word fbrPool
byte fbrRunning = 0
//
// Zero Page VM state and 6502 stack
//
struc t_vm
byte estkhi[$10]
byte estklo[$10]
word ifp
word pp
byte hwsp
byte esp
byte jmptmp
byte fill[8]
byte dropop
byte nextop[$10]
byte hwstk[$C0]
end
//
// Save current VM state and restore another
//
asm fbrSwap(saveVM, restoreVM)#0
!SOURCE "vmsrc/plvmzp.inc"
HWSP = IPY
LDA ESTKL,X
STA SRCL
LDA ESTKH,X
STA SRCH
INX
LDA ESTKL,X
STA DSTL
LDA ESTKH,X
STA DSTH
INX
STX ESP
TSX
STX HWSP
LDY #$26
- LDA ESTK,Y
STA (DST),Y
LDA (SRC),Y
STA ESTK,Y
DEY
BPL -
TXA
TAY
- LDA $100,Y
STA (DST),Y
INY
BNE -
LDY HWSP
- LDA (SRC),Y
STA $100,Y
INY
BNE -
LDX HWSP
TXS
LDX ESP
RTS
end
//
// Load Zero Page VM state and 6502 stack
//
asm fbrLoad(loadVM)#0
LDA ESTKL,X
STA SRCL
LDA ESTKH,X
STA SRCH
LDY #$26
- LDA (SRC),Y
STA ESTK,Y
DEY
BPL -
LDY HWSP
- LDA (SRC),Y
STA $100,Y
INY
BNE -
LDX HWSP
TXS
LDX ESP
RTS
end
//
// Initialize fiber pool
//
export def fbrInit(numPool)
byte i
word pool
if numPool >= MAX_FIBERS
numPool = MAX_FIBERS
fin
fbrMax = numPool - 1
//
// Allocate the fiber pool and initialize it to FREE
//
fbrPool = heapalloc(fbrMax * 512 + 256)
if fbrPool
//
// Each fiber gets 256 bytes of stack and 256 bytes
// for frame (local) data - except fiber 0 uses original frame data
//
pool = fbrPool + 256
for i = fbrMax downto 1
if i < numPool
fbrState[i] = FIBER_FREE
fbrVMState[i] = pool
pool = pool + 512
fin
next
//
// Set fiber 0 to the RUNning fiber
//
fbrState = FIBER_RUN
fbrVMState = fbrPool
else
return -1
fin
return 0
end
//
// Stop fiber and return it to FREE pool
//
export def fbrStop(fid)#0
byte i
//
// Don't STOP fiber 0 (avoid deadlock)
//
if fid
//
// Remove fiber from RUN list and tag as free
//
fbrState[fid] = FIBER_FREE
i = 0
while fbrNext[i] <> fid
i = fbrNext[i]
loop
fbrNext[i] = fbrNext[fid]
if fid == fbrRunning
fbrRunning = fbrNext[fbrRunning]
fbrLoad(fbrVMState[fbrRunning]) // This doesn't actually return here - returns to next fiber
fin
fin
end
//
// Stop current fiber
//
export def fbrExit#0
//
// Stop running fiber
//
fbrStop(fbrRunning)
end
//
// Start a fiber RUNning
//
export def fbrStart(defaddr, param)
byte i
word vmstate
for i = fbrMax downto 1
if fbrState[i] == FIBER_FREE
//
// Allocate fiber from pool
//
fbrState[i] = FIBER_RUN
vmstate = fbrVMState[i]
vmstate=>ifp = vmstate + 512
vmstate=>pp = vmstate + 512
//
// Set fiber parameters to fiber ID and passed-in value
//
vmstate->esp = $0E
vmstate->estklo.$0F = i
vmstate->estkhi.$0F = 0
vmstate->estklo.$0E = param.0 // param lo byte
vmstate->estkhi.$0E = param.1 // param hi byte
//
// Initialize stack to point to fiber def and fbrExit
// This allows a fiber to return and it will fall into fbrExit
//
vmstate->jmptmp = $4C
vmstate->hwsp = $FB
vmstate=>$FE = @fbrExit - 1
vmstate=>$FC = defaddr - 1
//
// Link into RUN list
//
fbrNext[i] = fbrNext[fbrRunning]
fbrNext[fbrRunning] = i
//
// Return fiber ID (index)
//
return i
fin
next
return -1
end
//
// Round-robin schedule RUNning fibers
//
export def fbrYield#0
byte prev
//
// Swap to text fiber if this isn't the only fiber RUNning
//
if fbrNext[fbrRunning] <> fbrRunning
prev = fbrRunning
fbrRunning = fbrNext[fbrRunning]
fbrSwap(fbrVMState[prev], fbrVMState[fbrRunning])
fin
end
//
// HALT current fiber and await a RESUME
//
export def fbrHalt#0
byte i
//
// Cannot HALT fiber 0 (avoid deadlock)
//
if fbrRunning
//
// Remove fiber from RUN list
//
i = 0
while fbrNext[i] <> fbrRunning
i = fbrNext[i]
loop
fbrState[fbrRunning] = FIBER_HALT
fbrNext[i] = fbrNext[fbrRunning]
i = fbrRunning
fbrRunning = fbrNext[fbrRunning]
fbrSwap(fbrVMState[i], fbrVMState[fbrRunning])
fin
end
//
// Restore HALTed fiber to RUN list
//
export def fbrResume(fid)#0
if fbrState[fid] == FIBER_HALT
//
// Insert HALTed fiber back into RUN list
//
fbrState[fid] = FIBER_RUN
fbrNext[fid] = fbrNext[fbrRunning]
fbrNext[fbrRunning] = fid
fin
end
done