4 ; Preemptive multitasking of idle threads
6 ; © 1994-1998 Straylight
9 ;----- Licensing note -------------------------------------------------------
11 ; This file is part of Straylight's Sapphire library.
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ; GNU General Public License for more details.
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 ;----- Overview -------------------------------------------------------------
48 [ :LNOT::DEF:thread__dfn
51 ; --- thread_create ---
53 ; On entry: R0 == size of stack to allocate, or 0 for a default
54 ; R1 == pointer to thread routine
55 ; R2 == workspace pointer to pass in R10
56 ; R3 == workspace pointer to pass in R12
58 ; On exit: R0 == thread handle for the thread
61 ; Use: Creates a new thread running `in the background' (i.e. over
64 ; The thread is passed control with the registers R10 and R12
65 ; set up from R1 and R2 passed to this routine and R13 pointing
66 ; to the top of a stack chunk. R0 on entry contains the
67 ; thread's handle. The thread is passed the scratchpad
68 ; address (in R11). The values of other registers are
69 ; indeterminate and must not be relied upon.
71 ; The default stack size for a new thread is 1K, although this
72 ; may change in future.
74 ; The thread may exit by calling thread_destroy or by
75 ; returning in the normal way.
79 ; --- thread_setPriority ---
81 ; On entry: R0 == thread handle
82 ; R1 == new priority to set
86 ; Use: Changes the priority of a thread. The priority if a thread
87 ; is a signed integer. The highest priority thread is the one
88 ; which runs. If more than one thread has maximum priority,
89 ; they are run in a cyclical order.
91 IMPORT thread_setPriority
93 ; --- thread_setTimeSlice ---
95 ; On entry: R0 == thread handle
96 ; R1 == new timeslice size, in centiseconds
100 ; Use: Changes a thread's timeslice size. Specify 0 to indicate
101 ; that thread shouldn't be pre-empted.
103 IMPORT thread_setTimeSlice
105 ; --- thread_destroy ---
107 ; On entry: R0 == thread handle to destroy, if not executing a thread
111 ; Use: Destroys either the current thread or a thread with the
112 ; the given handle if no thread is executing currently. You
113 ; can't destroy an arbitrary thread while running in one.
115 ; If a thread is waiting for a semaphore, it is removed from
118 IMPORT thread_destroy
120 ; --- thread_suspend ---
122 ; On entry: R0 == thread handle, or 0 for the current thread
126 ; Use: Suspends a thread's execution. If a thread is currently
127 ; running, that thread is suspended. Otherwise, any thread
130 ; If the thread is currently claiming semaphores, the
131 ; semaphores are not released, because we don't whether the
132 ; system is in a fit state for this.
134 ; Thread suspensions are counted. i.e. if you suspend a thread
135 ; 5 times, you have to resume it 5 times for it to become
138 IMPORT thread_suspend
140 ; --- thread_resume ---
142 ; On entry: R0 == thread handle
146 ; Use: Allows a suspended thread to continue operations. If you
147 ; resume a thread more times than it has been suspended,
148 ; any excess resumes are ignored. You can't resume a thread
149 ; to stop it being blocked by a semaphore.
153 ; --- thread_yield ---
159 ; Use: Pauses the thread for a while. You only need to use this
160 ; call if you have stopped the current thread from being
165 ; --- thread_createSem ---
167 ; On entry: R0 == initial value for semaphore (0 for counter, 1 for
170 ; On exit: R0 == semaphore handle and V clear if all went well
171 ; R0 == pointer to error and V set if something went wrong
173 ; Use: Creates a semaphore with the given initial counter value.
175 ; The semaphore can be used to provide serialised access to
176 ; a resource by initialising its value to 1 and performing the
179 ; thread_wait(mySemaphore)
181 ; // Do things with the resource
183 ; thread_signal(mySemaphore)
185 ; Or you can inform a thread that it has items in its input
186 ; queue by having the following in the thread code:
189 ; thread_wait(theSemaphore)
190 ; getFromQueue(myQueue,item)
194 ; and when inserting queue items:
197 ; thread_signal(theSemaphore)
199 ; It is distinctly possible that input queue management will
200 ; be introduced in a separate Sapphire module.
202 IMPORT thread_createSem
204 ; --- thread_destroySem ---
206 ; On entry: R0 == semaphore handle
210 ; Use: Destroys a semaphore when it's no use any more. If threads
211 ; are waiting for it, an error is generated.
213 IMPORT thread_destroySem
215 ; --- thread_threaded ---
219 ; On exit: CS if currently running a thread, CC otherwise
221 ; Use: Informs the caller whether a thread is currently executing.
223 IMPORT thread_threaded
225 ; --- thread_wait ---
227 ; On entry: R0 == semaphore handle
229 ; On exit: If successful, R0 preserved and V clear.
230 ; If failed, R0 == pointer to error block and V set
232 ; Use: Waits on a sempahore. The algorithm actually is as follows:
234 ; if semaphore.counter == 0 then
235 ; addToWaitingList(semaphore,currentThread)
236 ; suspend(currentThread)
238 ; semaphore.counter -= 1
241 ; See thread_createSem for suggestions on how to make use of
246 ; --- thread_signal ---
248 ; On entry: R0 == semaphore handle
252 ; Use: Increments a semaphore's counter if no threads are waiting
253 ; for it, or releases a thread waiting for the semaphore.
255 ; The actual algorithm is shown below:
257 ; if semaphore.waitingList != 0 then
258 ; thread = removeFromWaitingList(semaphore)
261 ; semaphore.counter += 1;
264 ; See thread_createSem for suggestions on how to make use of
269 ; --- thread_init ---
275 ; Use: Initialises the thread system for use.
279 ; --- thread_enterCrit ---
285 ; Use: Declares that the current thread is about to enter a
286 ; critical section and must not be interrupted.
288 IMPORT thread_enterCrit
290 ; --- thread_leaveCrit ---
296 ; Use: Declares that the current thread has left the critical
297 ; section and can be interrupted again.
299 IMPORT thread_leaveCrit
301 ; --- thread_errorHandler ---
303 ; On entry: R0 == pointer to routine to call
304 ; R1 == R12 value to call with
305 ; R2 == R13 value to call with
309 ; Use: Sets up the error handler for a thread.
311 IMPORT thread_errorHandler
315 ;----- That's all, folks ----------------------------------------------------