qt.h revision 12027:1eb7dc7aa10b
1/* 2 * QuickThreads -- Threads-building toolkit. 3 * Copyright (c) 1993 by David Keppel 4 * 5 * Permission to use, copy, modify and distribute this software and 6 * its documentation for any purpose and without fee is hereby 7 * granted, provided that the above copyright notice and this notice 8 * appear in all copies. This software is provided as a 9 * proof-of-concept and for demonstration purposes; there is no 10 * representation about the suitability of this software for any 11 * purpose. 12 */ 13 14#ifndef QUICKTHREADS_QT_H 15#define QUICKTHREADS_QT_H 16 17#if !defined(SC_USE_PTHREADS) 18 19#ifdef __cplusplus 20extern "C" { 21#endif 22 23#include <sysc/qt/qtmd.h> 24 25 26/* A QuickThreads thread is represented by it's current stack pointer. 27 To restart a thread, you merely need pass the current sp (qt_t*) to 28 a QuickThreads primitive. `qt_t*' is a location on the stack. To 29 improve type checking, represent it by a particular struct. */ 30 31typedef struct qt_t { 32 char dummy; 33} qt_t; 34 35 36/* Alignment is guaranteed to be a power of two. */ 37#ifndef QUICKTHREADS_STKALIGN 38 #error "Need to know the machine-dependent stack alignment." 39#endif 40 41#define QUICKTHREADS_STKROUNDUP(bytes) \ 42 (((bytes)+QUICKTHREADS_STKALIGN) & ~(QUICKTHREADS_STKALIGN-1)) 43 44 45/* Find ``top'' of the stack, space on the stack. */ 46#ifndef QUICKTHREADS_SP 47#ifdef QUICKTHREADS_GROW_DOWN 48#define QUICKTHREADS_SP(sto, size) ((qt_t *)(&((char *)(sto))[(size)])) 49#endif 50#ifdef QUICKTHREADS_GROW_UP 51#define QUICKTHREADS_SP(sto, size) ((qt_t *)(sto)) 52#endif 53#if !defined(QUICKTHREADS_SP) 54 #error "QUICKTHREADS_QT_H: Stack must grow up or down!" 55#endif 56#endif 57 58 59/* The type of the user function: 60 For non-varargs, takes one void* function. 61 For varargs, takes some number of arguments. */ 62typedef void *(qt_userf_t)(void *pu); 63typedef void *(qt_vuserf_t)(int arg0, ...); 64 65/* For non-varargs, just call a client-supplied function, 66 it does all startup and cleanup, and also calls the user's 67 function. */ 68typedef void (qt_only_t)(void *pu, void *pt, qt_userf_t *userf); 69 70/* For varargs, call `startup', then call the user's function, 71 then call `cleanup'. */ 72typedef void (qt_startup_t)(void *pt); 73typedef void (qt_cleanup_t)(void *pt, void *vuserf_return); 74 75 76/* Internal helper for putting stuff on stack. */ 77#ifndef QUICKTHREADS_SPUT 78#define QUICKTHREADS_SPUT(top, at, val) \ 79 (((qt_word_t *)(top))[(at)] = (qt_word_t)(val)) 80#endif 81 82 83/* Push arguments for the non-varargs case. */ 84#ifndef QUICKTHREADS_ARGS 85 86#ifndef QUICKTHREADS_ARGS_MD 87#define QUICKTHREADS_ARGS_MD (0) 88#endif 89 90#ifndef QUICKTHREADS_STKBASE 91 #error "Need to know the machine-dependent stack allocation." 92#endif 93 94/* All things are put on the stack relative to the final value of 95 the stack pointer. */ 96#ifdef QUICKTHREADS_GROW_DOWN 97#define QUICKTHREADS_ADJ(sp) (((char *)sp) - QUICKTHREADS_STKBASE) 98#else 99#define QUICKTHREADS_ADJ(sp) (((char *)sp) + QUICKTHREADS_STKBASE) 100#endif 101 102#define QUICKTHREADS_ARGS(sp, pu, pt, userf, only) \ 103 (QUICKTHREADS_ARGS_MD (QUICKTHREADS_ADJ(sp)), \ 104 QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ONLY_INDEX, only), \ 105 QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_USER_INDEX, userf), \ 106 QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGT_INDEX, pt), \ 107 QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGU_INDEX, pu), \ 108 ((qt_t *)QUICKTHREADS_ADJ(sp))) 109 110#endif 111 112 113/* Push arguments for the varargs case. 114 Has to be a function call because initialization is an expression 115 and we need to loop to copy nbytes of stuff on to the stack. 116 But that's probably OK, it's not terribly cheap, anyway. */ 117 118#ifdef QUICKTHREADS_VARGS_DEFAULT 119#ifndef QUICKTHREADS_VARGS_MD0 120#define QUICKTHREADS_VARGS_MD0(sp, vasize) (sp) 121#endif 122#ifndef QUICKTHREADS_VARGS_MD1 123#define QUICKTHREADS_VARGS_MD1(sp) do { ; } while (0) 124#endif 125 126#ifndef QUICKTHREADS_VSTKBASE 127 #error "Need base stack size for varargs functions." 128#endif 129 130/* Sometimes the stack pointer needs to munged a bit when storing 131 the list of arguments. */ 132#ifndef QUICKTHREADS_VARGS_ADJUST 133#define QUICKTHREADS_VARGS_ADJUST(sp) (sp) 134#endif 135 136/* All things are put on the stack relative to the final value of 137 the stack pointer. */ 138#ifdef QUICKTHREADS_GROW_DOWN 139#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE) 140#else 141#define QUICKTHREADS_VADJ(sp) (((char *)sp) + QUICKTHREADS_VSTKBASE) 142#endif 143 144extern qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs, 145 void *pt, qt_startup_t *startup, 146 qt_vuserf_t *vuserf, qt_cleanup_t *cleanup); 147 148#ifndef QUICKTHREADS_VARGS 149#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ 150 (qt_vargs (sp, nbytes, vargs, pt, startup, vuserf, cleanup)) 151#endif 152 153#endif 154 155 156/* Save the state of the thread and call the helper function 157 using the stack of the new thread. */ 158typedef void *(qt_helper_t)(qt_t *old, void *a0, void *a1); 159typedef void *(qt_block_t)(qt_helper_t *helper, void *a0, void *a1, 160 qt_t *newthread); 161 162/* Rearrange the parameters so that things passed to the helper 163 function are already in the right argument registers. */ 164#ifndef QUICKTHREADS_ABORT 165extern void *qt_abort (qt_helper_t *h, void *a0, void *a1, qt_t *newthread); 166/* The following does, technically, `return' a value, but the 167 user had better not rely on it, since the function never 168 returns. */ 169#define QUICKTHREADS_ABORT(h, a0, a1, newthread) \ 170 do { qt_abort (h, a0, a1, newthread); } while (0) 171#endif 172 173#ifndef QUICKTHREADS_BLOCK 174extern void *qt_block (qt_helper_t *h, void *a0, void *a1, 175 qt_t *newthread); 176#define QUICKTHREADS_BLOCK(h, a0, a1, newthread) \ 177 (qt_block (h, a0, a1, newthread)) 178#endif 179 180#ifndef QUICKTHREADS_BLOCKI 181extern void *qt_blocki (qt_helper_t *h, void *a0, void *a1, 182 qt_t *newthread); 183#define QUICKTHREADS_BLOCKI(h, a0, a1, newthread) \ 184 (qt_blocki (h, a0, a1, newthread)) 185#endif 186 187#ifdef __cplusplus 188} /* Match `extern "C" {' at top. */ 189#endif 190 191#endif // !defined(SC_USE_PTHREADS) 192#endif /* ndef QUICKTHREADS_H */ 193