Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Copyright (c) 2012 Teresa Bradbury
- ; Execution starts here
- ; In this example there are 3 threads
- ; Thread 2 prints twice then kills itself (by returning)
- ; Thread 1 loops until the main thread kills it
- 0x0100:
- call threadinit
- load #thread1 R1
- load #thread1stack R2
- call threadcreate
- store R1 thread1id
- load #thread2 R1
- load #thread2stack R2
- call threadcreate
- store R1 thread2id
- mainloop:
- load #mainstr R1
- call printstring
- call threadyield
- ;jump mainloop ; uncomment this for inf-loop
- load #mainstr R1
- call printstring
- call threadyield
- load #mainstr R1
- call printstring
- call threadyield
- load #mainstr R1
- call printstring
- call threadyield
- load thread1id R1
- call threaddestroy
- load #mainstr R1
- call printstring
- call threadyield
- load #mainstr R1
- call printstring
- call threadselfdestruct
- thread1id : block 1
- thread2id : block 1
- mainstr : block #"Main Thread\n"
- thread1 :
- load #thread1str R1
- call printstring
- call threadyield
- jump thread1
- ;return
- thread2 :
- load #thread2str R1
- call printstring
- call threadyield
- ;jump thread2
- load #thread2str R1
- call printstring
- call threadyield
- return
- thread1stack : block 8
- thread2stack : block 8
- thread1str : block #"Thread 1\n"
- thread2str : block #"Thread 2\n"
- ; R1 : string pointer (changed)
- printstring :
- load R1 R2
- jumpz R2 printstring_end
- store R2 0xfff0
- add R1 ONE R1
- jump printstring
- printstring_end :
- return
- ; -------------------------------------
- ; --------- Concurrency Data ----------
- ; -------------------------------------
- maxthreads : block #3
- ; For each thread, the first word is one if the thread exists
- ; and zero otherwise. The second word is the stack pointer.
- threaddata : block 6
- currentthreadid : block 1
- ; -------------------------------------
- ; ------- Concurrency Functions -------
- ; -------------------------------------
- ; must be called at start of the program
- ; it initializes the data structures
- ; No parameters
- threadinit :
- load maxthreads R0
- threadinit_threaddatainit :
- ; R0 is the thread that is being initialised. It counts down.
- add R0 MONE R0
- ; thread id
- move R0 R1
- ; structure offset
- move ZERO R2
- ; no flags
- move ZERO R3
- call threaddatastore
- jumpnz R0 threadinit_threaddatainit
- ; set thread zero to active
- move ZERO R1
- move ZERO R2
- move ONE R3
- call threaddatastore
- store ZERO currentthreadid
- return
- ; R1 : in thread id
- ; R2 : in structure offset
- ; R1 : out data
- ; preserves R0
- threaddataload :
- ; structure has size 2
- load #2 R3
- mult R1 R3 R3
- add R3 R2 R3
- load R3 #threaddata R1
- return
- ; R1 : in thread id
- ; R2 : in structure offset
- ; R3 : in data
- ; preserves R0
- threaddatastore :
- ; structure has size 2
- load #2 R4
- mult R1 R4 R4
- add R4 R2 R4
- store R3 #threaddata R4
- return
- ; R1 : in function pointer
- ; R2 : in stack pointer
- ; R1 : out thread id (-1 for error)
- ; Stack needs to be big enough for thread's workings,
- ; plus at least 3
- threadcreate :
- push R1
- push R2
- ; find a free thread id (in R0)
- move ZERO R0
- threadcreate_findid :
- load maxthreads R1
- sub R1 R0 R2
- ; if R2 == 0 then R0 == maxthreads
- ; so return -1 as no available threads
- jumpnz R2 threadcreate_no_error
- move MONE R1
- return
- threadcreate_no_error :
- move R0 R1
- move ZERO R2
- call threaddataload
- jumpz R1 threadcreate_foundid
- add ONE R0 R0
- jump threadcreate_findid
- threadcreate_foundid :
- ; created thread is inactive (not current) and
- ; the stack contains a pointer to selfdestruct then
- ; the provided stack pointer so first it will
- ; return to the given function and if it returns
- ; again it will be destroyed
- pop R2 ; stack pointer
- pop R1 ; function pointer
- store R1 #1 R2
- load #threadselfdestruct R1
- store R1 #0 R2
- ; Store the stack pointer
- move R0 R1
- add R2 ONE R3
- move ONE R2
- call threaddatastore
- ; Mark the thread as existant
- move R0 R1
- move ZERO R2
- move ONE R3
- call threaddatastore
- ; Return the created thread id
- move R0 R1
- return
- ; Pass thread id in R1
- threaddestroy :
- ; If thread id is not current, we just mark nonexistant
- ; If thread id *is* current, we mark nonexistant and then call
- ; threadyield to switch to another thread
- move R1 R0 ; because R0 survives the function calls
- ; Turn off the thread
- move R0 R1
- move ZERO R2
- move ZERO R3
- call threaddatastore
- ; Is this the current thread?
- load currentthreadid R1
- sub R0 R1 R2
- jumpnz R2 threaddestroy_notcurrentthread
- call threadyield
- threaddestroy_notcurrentthread :
- return
- ; No parameters - destroys current thread
- ; this is called on returning from a thread function
- threadselfdestruct :
- load currentthreadid R1
- jump threaddestroy
- ; No parameters
- threadyield :
- ; store the stackpointer
- load currentthreadid R1
- move ONE R2
- move SP R3
- call threaddatastore
- ; round robin scheduling
- ; we will eventually choose the thread id in R0
- load currentthreadid R0
- threadyield_findnext :
- load maxthreads R1
- add R0 ONE R0
- sub R1 R0 R2
- ; if R2 == 0 then R0 == maxthreads
- ; so R0 := 0
- jumpnz R2 threadyield_mod
- move ZERO R0
- threadyield_mod :
- move R0 R1
- move ZERO R2
- call threaddataload
- jumpnz R1 threadyield_foundnext
- ; if none of the threads exist, halt
- load currentthreadid R4
- sub R4 R0 R4
- jumpnz R4 threadyield_findnext
- halt
- threadyield_foundnext :
- store R0 currentthreadid
- ; load the new stack pointer
- load currentthreadid R1
- move ONE R2
- call threaddataload
- move R1 SP
- return
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement