*** empty log message ***
[bpt/guile.git] / qt / qt.h.in
1 #ifndef QT_H
2 #define QT_H
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8 #include <@qtmd_h@>
9
10
11 /* A QuickThreads thread is represented by it's current stack pointer.
12 To restart a thread, you merely need pass the current sp (qt_t*) to
13 a QuickThreads primitive. `qt_t*' is a location on the stack. To
14 improve type checking, represent it by a particular struct. */
15
16 typedef struct qt_t {
17 char dummy;
18 } qt_t;
19
20
21 /* Alignment is guaranteed to be a power of two. */
22 #ifndef QT_STKALIGN
23 #error "Need to know the machine-dependent stack alignment."
24 #endif
25
26 #define QT_STKROUNDUP(bytes) \
27 (((bytes)+QT_STKALIGN) & ~(QT_STKALIGN-1))
28
29
30 /* Find ``top'' of the stack, space on the stack. */
31 #ifndef QT_SP
32 #ifdef QT_GROW_DOWN
33 #define QT_SP(sto, size) ((qt_t *)(&((char *)(sto))[(size)]))
34 #endif
35 #ifdef QT_GROW_UP
36 #define QT_SP(sto, size) ((void *)(sto))
37 #endif
38 #if !defined(QT_SP)
39 #error "QT_H: Stack must grow up or down!"
40 #endif
41 #endif
42
43
44 /* The type of the user function:
45 For non-varargs, takes one void* function.
46 For varargs, takes some number of arguments. */
47 typedef void *(qt_userf_t)(void *pu);
48 typedef void *(qt_vuserf_t)(int arg0, ...);
49
50 /* For non-varargs, just call a client-supplied function,
51 it does all startup and cleanup, and also calls the user's
52 function. */
53 typedef void (qt_only_t)(void *pu, void *pt, qt_userf_t *userf);
54
55 /* For varargs, call `startup', then call the user's function,
56 then call `cleanup'. */
57 typedef void (qt_startup_t)(void *pt);
58 typedef void (qt_cleanup_t)(void *pt, void *vuserf_return);
59
60
61 /* Internal helper for putting stuff on stack. */
62 #ifndef QT_SPUT
63 #define QT_SPUT(top, at, val) \
64 (((qt_word_t *)(top))[(at)] = (qt_word_t)(val))
65 #endif
66
67
68 /* Push arguments for the non-varargs case. */
69 #ifndef QT_ARGS
70
71 #ifndef QT_ARGS_MD
72 #define QT_ARGS_MD (0)
73 #endif
74
75 #ifndef QT_STKBASE
76 #error "Need to know the machine-dependent stack allocation."
77 #endif
78
79 /* All things are put on the stack relative to the final value of
80 the stack pointer. */
81 #ifdef QT_GROW_DOWN
82 #define QT_ADJ(sp) (((char *)sp) - QT_STKBASE)
83 #else
84 #define QT_ADJ(sp) (((char *)sp) + QT_STKBASE)
85 #endif
86
87 #define QT_ARGS(sp, pu, pt, userf, only) \
88 (QT_ARGS_MD (QT_ADJ(sp)), \
89 QT_SPUT (QT_ADJ(sp), QT_ONLY_INDEX, only), \
90 QT_SPUT (QT_ADJ(sp), QT_USER_INDEX, userf), \
91 QT_SPUT (QT_ADJ(sp), QT_ARGT_INDEX, pt), \
92 QT_SPUT (QT_ADJ(sp), QT_ARGU_INDEX, pu), \
93 ((qt_t *)QT_ADJ(sp)))
94
95 #endif
96
97
98 /* Push arguments for the varargs case.
99 Has to be a function call because initialization is an expression
100 and we need to loop to copy nbytes of stuff on to the stack.
101 But that's probably OK, it's not terribly cheap, anyway. */
102
103 #ifdef QT_VARGS_DEFAULT
104 #ifndef QT_VARGS_MD0
105 #define QT_VARGS_MD0(sp, vasize) (sp)
106 #endif
107 #ifndef QT_VARGS_MD1
108 #define QT_VARGS_MD1(sp) do { ; } while (0)
109 #endif
110
111 #ifndef QT_VSTKBASE
112 #error "Need base stack size for varargs functions."
113 #endif
114
115 /* Sometimes the stack pointer needs to munged a bit when storing
116 the list of arguments. */
117 #ifndef QT_VARGS_ADJUST
118 #define QT_VARGS_ADJUST(sp) (sp)
119 #endif
120
121 /* All things are put on the stack relative to the final value of
122 the stack pointer. */
123 #ifdef QT_GROW_DOWN
124 #define QT_VADJ(sp) (((char *)sp) - QT_VSTKBASE)
125 #else
126 #define QT_VADJ(sp) (((char *)sp) + QT_VSTKBASE)
127 #endif
128
129 extern qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs,
130 void *pt, qt_startup_t *startup,
131 qt_vuserf_t *vuserf, qt_cleanup_t *cleanup);
132
133 #ifndef QT_VARGS
134 #define QT_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
135 (qt_vargs (sp, nbytes, vargs, pt, startup, vuserf, cleanup))
136 #endif
137
138 #endif
139
140 extern void qt_null (void);
141 extern void qt_error (void);
142
143 /* Save the state of the thread and call the helper function
144 using the stack of the new thread. */
145 typedef void *(qt_helper_t)(qt_t *old, void *a0, void *a1);
146 typedef void *(qt_block_t)(qt_helper_t *helper, void *a0, void *a1,
147 qt_t *newthread);
148
149 /* Rearrange the parameters so that things passed to the helper
150 function are already in the right argument registers. */
151 #ifndef QT_ABORT
152 extern void qt_abort (qt_helper_t *h, void *a0, void *a1, qt_t *newthread);
153 /* The following does, technically, `return' a value, but the
154 user had better not rely on it, since the function never
155 returns. */
156 #define QT_ABORT(h, a0, a1, newthread) \
157 do { qt_abort (h, a0, a1, newthread); } while (0)
158 #endif
159
160 #ifndef QT_BLOCK
161 extern void *qt_block (qt_helper_t *h, void *a0, void *a1,
162 qt_t *newthread);
163 #define QT_BLOCK(h, a0, a1, newthread) \
164 (qt_block (h, a0, a1, newthread))
165 #endif
166
167 #ifndef QT_BLOCKI
168 extern void *qt_blocki (qt_helper_t *h, void *a0, void *a1,
169 qt_t *newthread);
170 #define QT_BLOCKI(h, a0, a1, newthread) \
171 (qt_blocki (h, a0, a1, newthread))
172 #endif
173
174 #ifdef __cplusplus
175 } /* Match `extern "C" {' at top. */
176 #endif
177
178 #endif /* ndef QT_H */