mirror of
https://github.com/dschmenk/PLASMA.git
synced 2024-10-18 07:24:16 +00:00
Lightweight thread (fiber) library. Rearrage VM ZP for faster state swaps.
This commit is contained in:
parent
024f5d1a74
commit
f4e0b4cb6b
303
src/libsrc/fiber.pla
Normal file
303
src/libsrc/fiber.pla
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
//
|
||||||
|
// Cooperative multi-threading (fiber) scheduler
|
||||||
|
//
|
||||||
|
import cmdsys
|
||||||
|
predef syscall, call, getc, gets, putc, puts, putln
|
||||||
|
predef memset, memcpy, modaddr, modexec
|
||||||
|
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||||
|
predef isugt, isuge, isult, isule
|
||||||
|
byte MACHID
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// 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 estklo[$10]
|
||||||
|
byte estkhi[$10]
|
||||||
|
word ifp
|
||||||
|
word pp
|
||||||
|
byte esp
|
||||||
|
byte hwsp
|
||||||
|
byte fill[9]
|
||||||
|
byte drop
|
||||||
|
byte nextop[$10]
|
||||||
|
byte hwstk[$C0]
|
||||||
|
end
|
||||||
|
byte valstr[] = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
|
||||||
|
//
|
||||||
|
// Save current VM state and restore another
|
||||||
|
//
|
||||||
|
asm fbrSwap(saveVM, restoreVM)
|
||||||
|
!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
|
||||||
|
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
|
||||||
|
LDY IPY
|
||||||
|
RTS
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// Load Zero Page VM state and 6502 stack
|
||||||
|
//
|
||||||
|
asm fbrLoad(loadVM)
|
||||||
|
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
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// Stop fiber and return it to FREE pool
|
||||||
|
//
|
||||||
|
export def fbrStop(fid)
|
||||||
|
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]
|
||||||
|
return fbrLoad(fbrVMState[fbrRunning])
|
||||||
|
fin
|
||||||
|
fin
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// Stop current fiber
|
||||||
|
//
|
||||||
|
export def fbrExit
|
||||||
|
//
|
||||||
|
// 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->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
|
||||||
|
byte prev
|
||||||
|
|
||||||
|
//
|
||||||
|
// Swap to text fiber if this isn't the only fiber RUNning
|
||||||
|
//
|
||||||
|
if fbrNext[fbrRunning] <> fbrRunning
|
||||||
|
prev = fbrRunning
|
||||||
|
fbrRunning = fbrNext[fbrRunning]
|
||||||
|
return fbrSwap(fbrVMState[prev], fbrVMState[fbrRunning])
|
||||||
|
fin
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// HALT current fiber and await a RESUME
|
||||||
|
//
|
||||||
|
export def fbrHalt
|
||||||
|
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]
|
||||||
|
return fbrSwap(fbrVMState[i], fbrVMState[fbrRunning])
|
||||||
|
fin
|
||||||
|
end
|
||||||
|
//
|
||||||
|
// Restore HALTed fiber to RUN list
|
||||||
|
//
|
||||||
|
export def fbrResume(fid)
|
||||||
|
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
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test Fiber library
|
||||||
|
//
|
||||||
|
|
||||||
|
def puth(h)
|
||||||
|
putc('$')
|
||||||
|
putc(valstr[(h >> 12) & $0F])
|
||||||
|
putc(valstr[(h >> 8) & $0F])
|
||||||
|
putc(valstr[(h >> 4) & $0F])
|
||||||
|
putc(valstr[ h & $0F])
|
||||||
|
end
|
||||||
|
|
||||||
|
def fbrTest(fid, param)
|
||||||
|
byte i
|
||||||
|
|
||||||
|
for i = 1 to param
|
||||||
|
puth(param); putc($0D)
|
||||||
|
fbrYield
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
fbrInit(4)
|
||||||
|
fbrStart(@fbrTest, 3)
|
||||||
|
fbrStart(@fbrTest, 2)
|
||||||
|
fbrStart(@fbrTest, 1)
|
||||||
|
fbrYield; fbrYield; fbrYield; fbrYield
|
||||||
|
done
|
@ -28,6 +28,7 @@ TESTLIB = TESTLIB\#FE1000
|
|||||||
PROFILE = PROFILE\#FE1000
|
PROFILE = PROFILE\#FE1000
|
||||||
MEMMGR = MEMMGR\#FE1000
|
MEMMGR = MEMMGR\#FE1000
|
||||||
MEMTEST = MEMTEST\#FE1000
|
MEMTEST = MEMTEST\#FE1000
|
||||||
|
FIBER = FIBER\#FE1000
|
||||||
PLASM = plasm
|
PLASM = plasm
|
||||||
INCS = toolsrc/tokens.h toolsrc/symbols.h toolsrc/lex.h toolsrc/parse.h toolsrc/codegen.h
|
INCS = toolsrc/tokens.h toolsrc/symbols.h toolsrc/lex.h toolsrc/parse.h toolsrc/codegen.h
|
||||||
OBJS = toolsrc/plasm.c toolsrc/parse.o toolsrc/lex.o toolsrc/codegen.o
|
OBJS = toolsrc/plasm.c toolsrc/parse.o toolsrc/lex.o toolsrc/codegen.o
|
||||||
@ -47,7 +48,7 @@ TXTTYPE = .TXT
|
|||||||
#SYSTYPE = \#FF2000
|
#SYSTYPE = \#FF2000
|
||||||
#TXTTYPE = \#040000
|
#TXTTYPE = \#040000
|
||||||
|
|
||||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(WIZNET) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(FIBER) $(SB) $(MON) $(ROD) $(SIEVE) $(WIZNET) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
|
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
|
||||||
@ -112,6 +113,10 @@ $(MEMTEST): samplesrc/memtest.pla $(PLVM02) $(PLASM)
|
|||||||
./$(PLASM) -AM < samplesrc/memtest.pla > samplesrc/memtest.a
|
./$(PLASM) -AM < samplesrc/memtest.pla > samplesrc/memtest.a
|
||||||
acme --setpc 4094 -o $(MEMTEST) samplesrc/memtest.a
|
acme --setpc 4094 -o $(MEMTEST) samplesrc/memtest.a
|
||||||
|
|
||||||
|
$(FIBER): libsrc/fiber.pla $(PLVM02) $(PLASM)
|
||||||
|
./$(PLASM) -AM < libsrc/fiber.pla > libsrc/fiber.a
|
||||||
|
acme --setpc 4094 -o $(FIBER) libsrc/fiber.a
|
||||||
|
|
||||||
$(MON): samplesrc/mon.pla $(PLVM02) $(PLASM)
|
$(MON): samplesrc/mon.pla $(PLVM02) $(PLASM)
|
||||||
./$(PLASM) -AM < samplesrc/mon.pla > samplesrc/mon.a
|
./$(PLASM) -AM < samplesrc/mon.pla > samplesrc/mon.a
|
||||||
acme --setpc 4094 -o $(MON) samplesrc/mon.a
|
acme --setpc 4094 -o $(MON) samplesrc/mon.a
|
||||||
|
@ -20,14 +20,14 @@ IFPH = IFP+1
|
|||||||
PP = IFP+2
|
PP = IFP+2
|
||||||
PPL = PP
|
PPL = PP
|
||||||
PPH = PP+1
|
PPH = PP+1
|
||||||
IPY = PP+2
|
DVSIGN = PP+2
|
||||||
|
ESP = PP+2
|
||||||
|
IPY = ESP+1
|
||||||
TMP = IPY+1
|
TMP = IPY+1
|
||||||
TMPL = TMP
|
TMPL = TMP
|
||||||
TMPH = TMP+1
|
TMPH = TMP+1
|
||||||
NPARMS = TMPL
|
NPARMS = TMPL
|
||||||
FRMSZ = TMPH
|
FRMSZ = TMPH
|
||||||
DVSIGN = TMP+2
|
|
||||||
ESP = TMP+2
|
|
||||||
DROP = $EF
|
DROP = $EF
|
||||||
NEXTOP = $F0
|
NEXTOP = $F0
|
||||||
FETCHOP = NEXTOP+3
|
FETCHOP = NEXTOP+3
|
||||||
|
Loading…
Reference in New Issue
Block a user