chiark / gitweb /
Create readable text `.bas' for each tokenized BASIC `,ffb' file.
[ssr] / StraySrc / Libraries / Sapphire / csapph / h / thread
1 /*
2  * thread.h
3  *
4  * [Generated from thread, 25 September 1996]
5  */
6
7 #if !defined(__CC_NORCROFT) || !defined(__arm)
8   #error You must use the Norcroft ARM Compiler for Sapphire programs
9 #endif
10
11 #pragma include_only_once
12 #pragma force_top_level
13
14 #ifndef __thread_h
15 #define __thread_h
16
17 #ifndef __sapphire_h
18   #include "sapphire.h"
19 #endif
20
21 /*----- Overview ----------------------------------------------------------*
22  *
23  * Functions provided:
24  *
25  *  thread_create
26  *  thread_setPriority
27  *  thread_setTimeSlice
28  *  thread_destroy
29  *  thread_suspend
30  *  thread_resume
31  *  thread_yield
32  *  thread_createSem
33  *  thread_destroySem
34  *  thread_threaded
35  *  thread_wait
36  *  thread_signal
37  *  thread_init
38  *  thread_enterCrit
39  *  thread_leaveCrit
40  *  thread_errorHandler
41  */
42
43 /* --- thread_create --- *
44  *
45  * On entry:    R0 == size of stack to allocate, or 0 for a default
46  *              R1 == pointer to thread routine
47  *              R2 == workspace pointer to pass in R10
48  *              R3 == workspace pointer to pass in R12
49  *
50  * On exit:     R0 == thread handle for the thread
51  *              May return an error
52  *
53  * Use:         Creates a new thread running `in the background' (i.e. over
54  *              idle events).
55  *
56  *              The thread is passed control with the registers R10 and R12
57  *              set up from R1 and R2 passed to this routine and R13 pointing
58  *              to the top of a stack chunk.  R0 on entry contains the
59  *              thread's handle.  The thread is passed the scratchpad
60  *              address (in R11).  The values of other registers are
61  *              indeterminate and must not be relied upon.
62  *
63  *              The default stack size for a new thread is 1K, although this
64  *              may change in future.
65  *
66  *              The thread may exit by calling thread_destroy or by
67  *              returning in the normal way.
68  */
69
70 extern routine thread_create;
71
72 /* --- thread_setPriority --- *
73  *
74  * On entry:    R0 == thread handle
75  *              R1 == new priority to set
76  *
77  * On exit:     --
78  *
79  * Use:         Changes the priority of a thread.  The priority if a thread
80  *              is a signed integer.  The highest priority thread is the one
81  *              which runs.  If more than one thread has maximum priority,
82  *              they are run in a cyclical order.
83  */
84
85 extern routine thread_setPriority;
86
87 /* --- thread_setTimeSlice --- *
88  *
89  * On entry:    R0 == thread handle
90  *              R1 == new timeslice size, in centiseconds
91  *
92  * On exit:     --
93  *
94  * Use:         Changes a thread's timeslice size.  Specify 0 to indicate
95  *              that thread shouldn't be pre-empted.
96  */
97
98 extern routine thread_setTimeSlice;
99
100 /* --- thread_destroy --- *
101  *
102  * On entry:    R0 == thread handle to destroy, if not executing a thread
103  *
104  * On exit:     --
105  *
106  * Use:         Destroys either the current thread or a thread with the
107  *              the given handle if no thread is executing currently.  You
108  *              can't destroy an arbitrary thread while running in one.
109  *
110  *              If a thread is waiting for a semaphore, it is removed from
111  *              the waiting list.
112  */
113
114 extern routine thread_destroy;
115
116 /* --- thread_suspend --- *
117  *
118  * On entry:    R0 == thread handle, or 0 for the current thread
119  *
120  * On exit:     --
121  *
122  * Use:         Suspends a thread's execution.  If a thread is currently
123  *              running, that thread is suspended.  Otherwise, any thread
124  *              may be suspended.
125  *
126  *              If the thread is currently claiming semaphores, the
127  *              semaphores are not released, because we don't whether the
128  *              system is in a fit state for this.
129  *
130  *              Thread suspensions are counted.  i.e. if you suspend a thread
131  *              5 times, you have to resume it 5 times for it to become
132  *              active again.
133  */
134
135 extern routine thread_suspend;
136
137 /* --- thread_resume --- *
138  *
139  * On entry:    R0 == thread handle
140  *
141  * On exit:     --
142  *
143  * Use:         Allows a suspended thread to continue operations.  If you
144  *              resume a thread more times than it has been suspended,
145  *              any excess resumes are ignored.  You can't resume a thread
146  *              to stop it being blocked by a semaphore.
147  */
148
149 extern routine thread_resume;
150
151 /* --- thread_yield --- *
152  *
153  * On entry:    --
154  *
155  * On exit:     --
156  *
157  * Use:         Pauses the thread for a while.  You only need to use this
158  *              call if you have stopped the current thread from being
159  *              timesliced.
160  */
161
162 extern routine thread_yield;
163
164 /* --- thread_createSem --- *
165  *
166  * On entry:    R0 == initial value for semaphore (0 for counter, 1 for
167  *                    mutex)
168  *
169  * On exit:     R0 == semaphore handle and V clear if all went well
170  *              R0 == pointer to error and V set if something went wrong
171  *
172  * Use:         Creates a semaphore with the given initial counter value.
173  *
174  *              The semaphore can be used to provide serialised access to
175  *              a resource by initialising its value to 1 and performing the
176  *              following:
177  *
178  *              thread_wait(mySemaphore)
179  *              //
180  *              // Do things with the resource
181  *              //
182  *              thread_signal(mySemaphore)
183  *
184  *              Or you can inform a thread that it has items in its input
185  *              queue by having the following in the thread code:
186  *
187  *              while true
188  *                thread_wait(theSemaphore)
189  *                getFromQueue(myQueue,item)
190  *                process(item)
191  *              endWhile
192  *
193  *              and when inserting queue items:
194  *
195  *              addToQueue(item)
196  *              thread_signal(theSemaphore)
197  *
198  *              It is distinctly possible that input queue management will
199  *              be introduced in a separate Sapphire module.
200  */
201
202 extern routine thread_createSem;
203
204 /* --- thread_destroySem --- *
205  *
206  * On entry:    R0 == semaphore handle
207  *
208  * On exit:     --
209  *
210  * Use:         Destroys a semaphore when it's no use any more.  If threads
211  *              are waiting for it, an error is generated.
212  */
213
214 extern routine thread_destroySem;
215
216 /* --- thread_threaded --- *
217  *
218  * On entry:    --
219  *
220  * On exit:     CS if currently running a thread, CC otherwise
221  *
222  * Use:         Informs the caller whether a thread is currently executing.
223  */
224
225 extern routine thread_threaded;
226
227 /* --- thread_wait --- *
228  *
229  * On entry:    R0 == semaphore handle
230  *
231  * On exit:     If successful, R0 preserved and V clear.
232  *              If failed, R0 == pointer to error block and V set
233  *
234  * Use:         Waits on a sempahore.  The algorithm actually is as follows:
235  *
236  *              if semaphore.counter == 0 then
237  *                addToWaitingList(semaphore,currentThread)
238  *                suspend(currentThread)
239  *              else
240  *                semaphore.counter -= 1
241  *              endIf
242  *
243  *              See thread_createSem for suggestions on how to make use of
244  *              semaphores.
245  */
246
247 extern routine thread_wait;
248
249 /* --- thread_signal --- *
250  *
251  * On entry:    R0 == semaphore handle
252  *
253  * On exit:     --
254  *
255  * Use:         Increments a semaphore's counter if no threads are waiting
256  *              for it, or releases a thread waiting for the semaphore.
257  *
258  *              The actual algorithm is shown below:
259  *
260  *              if semaphore.waitingList != 0 then
261  *                thread = removeFromWaitingList(semaphore)
262  *                unSuspend(thread)
263  *              else
264  *                semaphore.counter += 1;
265  *              endif
266  *
267  *              See thread_createSem for suggestions on how to make use of
268  *              semaphores.
269  */
270
271 extern routine thread_signal;
272
273 /* --- thread_init --- *
274  *
275  * On entry:    --
276  *
277  * On exit:     --
278  *
279  * Use:         Initialises the thread system for use.
280  */
281
282 extern routine thread_init;
283
284 /* --- thread_enterCrit --- *
285  *
286  * On entry:    --
287  *
288  * On exit:     --
289  *
290  * Use:         Declares that the current thread is about to enter a
291  *              critical section and must not be interrupted.
292  */
293
294 extern routine thread_enterCrit;
295
296 /* --- thread_leaveCrit --- *
297  *
298  * On entry:    --
299  *
300  * On exit:     --
301  *
302  * Use:         Declares that the current thread has left the critical
303  *              section and can be interrupted again.
304  */
305
306 extern routine thread_leaveCrit;
307
308 /* --- thread_errorHandler --- *
309  *
310  * On entry:    R0 == pointer to routine to call
311  *              R1 == R12 value to call with
312  *              R2 == R13 value to call with
313  *
314  * On exit:     --
315  *
316  * Use:         Sets up the error handler for a thread.
317  */
318
319 extern routine thread_errorHandler;
320
321 /*----- That's all, folks -------------------------------------------------*/
322
323 #endif