| 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 |