qt.h

Go to the documentation of this file.
00001 /*
00002  * QuickThreads -- Threads-building toolkit.
00003  * Copyright (c) 1993 by David Keppel
00004  *
00005  * Permission to use, copy, modify and distribute this software and
00006  * its documentation for any purpose and without fee is hereby
00007  * granted, provided that the above copyright notice and this notice
00008  * appear in all copies.  This software is provided as a
00009  * proof-of-concept and for demonstration purposes; there is no
00010  * representation about the suitability of this software for any
00011  * purpose.
00012  */
00013 
00014 #ifndef QUICKTHREADS_QT_H
00015 #define QUICKTHREADS_QT_H
00016 
00017 #if !defined(SC_USE_PTHREADS)
00018 
00019 #ifdef __cplusplus
00020 extern "C" {
00021 #endif
00022 
00023 #include <sysc/qt/qtmd.h>
00024 
00025 
00026 /* A QuickThreads thread is represented by it's current stack pointer.
00027    To restart a thread, you merely need pass the current sp (qt_t*) to
00028    a QuickThreads primitive.  `qt_t*' is a location on the stack.  To
00029    improve type checking, represent it by a particular struct. */
00030 
00031 typedef struct qt_t {
00032   char dummy;
00033 } qt_t;
00034 
00035 
00036 /* Alignment is guaranteed to be a power of two. */
00037 #ifndef QUICKTHREADS_STKALIGN
00038   #error "Need to know the machine-dependent stack alignment."
00039 #endif
00040 
00041 #define QUICKTHREADS_STKROUNDUP(bytes) \
00042   (((bytes)+QUICKTHREADS_STKALIGN) & ~(QUICKTHREADS_STKALIGN-1))
00043 
00044 
00045 /* Find ``top'' of the stack, space on the stack. */
00046 #ifndef QUICKTHREADS_SP
00047 #ifdef QUICKTHREADS_GROW_DOWN
00048 #define QUICKTHREADS_SP(sto, size)      ((qt_t *)(&((char *)(sto))[(size)]))
00049 #endif
00050 #ifdef QUICKTHREADS_GROW_UP
00051 #define QUICKTHREADS_SP(sto, size)      ((qt_t *)(sto))
00052 #endif
00053 #if !defined(QUICKTHREADS_SP)
00054   #error "QUICKTHREADS_QT_H: Stack must grow up or down!"
00055 #endif
00056 #endif
00057 
00058 
00059 /* The type of the user function:
00060    For non-varargs, takes one void* function.
00061    For varargs, takes some number of arguments. */
00062 typedef void *(qt_userf_t)(void *pu);
00063 typedef void *(qt_vuserf_t)(int arg0, ...);
00064 
00065 /* For non-varargs, just call a client-supplied function,
00066    it does all startup and cleanup, and also calls the user's
00067    function. */
00068 typedef void (qt_only_t)(void *pu, void *pt, qt_userf_t *userf);
00069 
00070 /* For varargs, call `startup', then call the user's function,
00071    then call `cleanup'. */
00072 typedef void (qt_startup_t)(void *pt);
00073 typedef void (qt_cleanup_t)(void *pt, void *vuserf_return);
00074 
00075 
00076 /* Internal helper for putting stuff on stack. */
00077 #ifndef QUICKTHREADS_SPUT
00078 #define QUICKTHREADS_SPUT(top, at, val) \
00079     (((qt_word_t *)(top))[(at)] = (qt_word_t)(val))
00080 #endif
00081 
00082 
00083 /* Push arguments for the non-varargs case. */
00084 #ifndef QUICKTHREADS_ARGS
00085 
00086 #ifndef QUICKTHREADS_ARGS_MD
00087 #define QUICKTHREADS_ARGS_MD (0)
00088 #endif
00089 
00090 #ifndef QUICKTHREADS_STKBASE
00091   #error "Need to know the machine-dependent stack allocation."
00092 #endif
00093 
00094 /* All things are put on the stack relative to the final value of
00095    the stack pointer. */
00096 #ifdef QUICKTHREADS_GROW_DOWN
00097 #define QUICKTHREADS_ADJ(sp)    (((char *)sp) - QUICKTHREADS_STKBASE)
00098 #else
00099 #define QUICKTHREADS_ADJ(sp)    (((char *)sp) + QUICKTHREADS_STKBASE)
00100 #endif
00101 
00102 #define QUICKTHREADS_ARGS(sp, pu, pt, userf, only) \
00103     (QUICKTHREADS_ARGS_MD (QUICKTHREADS_ADJ(sp)), \
00104      QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ONLY_INDEX, only), \
00105      QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_USER_INDEX, userf), \
00106      QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGT_INDEX, pt), \
00107      QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGU_INDEX, pu), \
00108      ((qt_t *)QUICKTHREADS_ADJ(sp)))
00109 
00110 #endif
00111 
00112 
00113 /* Push arguments for the varargs case.
00114    Has to be a function call because initialization is an expression
00115    and we need to loop to copy nbytes of stuff on to the stack.
00116    But that's probably OK, it's not terribly cheap, anyway. */
00117 
00118 #ifdef QUICKTHREADS_VARGS_DEFAULT
00119 #ifndef QUICKTHREADS_VARGS_MD0
00120 #define QUICKTHREADS_VARGS_MD0(sp, vasize)      (sp)
00121 #endif
00122 #ifndef QUICKTHREADS_VARGS_MD1
00123 #define QUICKTHREADS_VARGS_MD1(sp)      do { ; } while (0)
00124 #endif
00125 
00126 #ifndef QUICKTHREADS_VSTKBASE
00127   #error "Need base stack size for varargs functions."
00128 #endif
00129 
00130 /* Sometimes the stack pointer needs to munged a bit when storing
00131    the list of arguments. */
00132 #ifndef QUICKTHREADS_VARGS_ADJUST
00133 #define QUICKTHREADS_VARGS_ADJUST(sp)   (sp)
00134 #endif
00135 
00136 /* All things are put on the stack relative to the final value of
00137    the stack pointer. */
00138 #ifdef QUICKTHREADS_GROW_DOWN
00139 #define QUICKTHREADS_VADJ(sp)   (((char *)sp) - QUICKTHREADS_VSTKBASE)
00140 #else
00141 #define QUICKTHREADS_VADJ(sp)   (((char *)sp) + QUICKTHREADS_VSTKBASE)
00142 #endif
00143 
00144 extern qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs,
00145                        void *pt, qt_startup_t *startup,
00146                        qt_vuserf_t *vuserf, qt_cleanup_t *cleanup);
00147 
00148 #ifndef QUICKTHREADS_VARGS
00149 #define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
00150       (qt_vargs (sp, nbytes, vargs, pt, startup, vuserf, cleanup))
00151 #endif
00152 
00153 #endif
00154 
00155 
00156 /* Save the state of the thread and call the helper function
00157    using the stack of the new thread. */
00158 typedef void *(qt_helper_t)(qt_t *old, void *a0, void *a1);
00159 typedef void *(qt_block_t)(qt_helper_t *helper, void *a0, void *a1,
00160                           qt_t *newthread);
00161 
00162 /* Rearrange the parameters so that things passed to the helper
00163    function are already in the right argument registers. */
00164 #ifndef QUICKTHREADS_ABORT
00165 extern void *qt_abort (qt_helper_t *h, void *a0, void *a1, qt_t *newthread);
00166 /* The following does, technically, `return' a value, but the
00167    user had better not rely on it, since the function never
00168    returns. */ 
00169 #define QUICKTHREADS_ABORT(h, a0, a1, newthread) \
00170     do { qt_abort (h, a0, a1, newthread); } while (0)
00171 #endif
00172 
00173 #ifndef QUICKTHREADS_BLOCK
00174 extern void *qt_block (qt_helper_t *h, void *a0, void *a1,
00175                        qt_t *newthread);
00176 #define QUICKTHREADS_BLOCK(h, a0, a1, newthread) \
00177     (qt_block (h, a0, a1, newthread))
00178 #endif
00179 
00180 #ifndef QUICKTHREADS_BLOCKI
00181 extern void *qt_blocki (qt_helper_t *h, void *a0, void *a1,
00182                         qt_t *newthread);
00183 #define QUICKTHREADS_BLOCKI(h, a0, a1, newthread) \
00184     (qt_blocki (h, a0, a1, newthread))
00185 #endif
00186 
00187 #ifdef __cplusplus
00188 }               /* Match `extern "C" {' at top. */
00189 #endif
00190 
00191 #endif // !defined(SC_USE_PTHREADS)
00192 #endif /* ndef QUICKTHREADS_H */
Generated by
Matthieu Moy <Matthieu.Moy@st.com>
Back to Pinapa Home Page