death to register
[openafs.git] / src / lwp / lwp.h
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*******************************************************************\
11 *                                                                   *
12 *       Information Technology Center                               *
13 *       Carnegie-Mellon University                                  *
14 *                                                                   *
15 *                                                                   *
16 \*******************************************************************/
17
18 #ifndef __LWP_INCLUDE_
19 #define __LWP_INCLUDE_  1
20
21 #if !defined(KERNEL) && !defined(_KMEMUSER)
22 #include <afs/param.h>
23
24 /* External function declarations. */
25 #ifdef AFS_NT40_ENV
26 #ifndef _MFC_VER                /*skip if doing Microsoft foundation class */
27 #include <winsock2.h>
28 #endif
29 #elif defined(AFS_LINUX20_ENV)
30 #include <unistd.h>
31 #include <time.h>
32 #include <sys/time.h>
33 #else
34 # include <unistd.h>            /* select() prototype */
35 # include <sys/types.h>         /* fd_set on older platforms */
36 # include <sys/time.h>          /* struct timeval, select() prototype */
37 # ifndef FD_SET
38 #  include <sys/select.h>       /* fd_set on newer platforms */
39 # endif
40 #endif
41
42 /* fasttime.c */
43 extern int FT_GetTimeOfDay(struct timeval *tv, struct timezone *tz);
44 extern int FT_Init(int printErrors, int notReally);
45 extern int FT_AGetTimeOfDay(struct timeval *tv, struct timezone *tz);
46 extern unsigned int FT_ApproxTime(void);
47
48 #if !defined(AFS_PTHREAD_ENV)
49 # if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
50 #  include <ucontext.h>
51 # else
52 #  include <setjmp.h>
53 # endif
54
55 #define LWP_SUCCESS     0
56 #define LWP_EBADPID     -1
57 #define LWP_EBLOCKED    -2
58 #define LWP_EINIT       -3
59 #define LWP_EMAXPROC    -4
60 #define LWP_ENOBLOCK    -5
61 #define LWP_ENOMEM      -6
62 #define LWP_ENOPROCESS  -7
63 #define LWP_ENOWAIT     -8
64 #define LWP_EBADCOUNT   -9
65 #define LWP_EBADEVENT   -10
66 #define LWP_EBADPRI     -11
67 #define LWP_NO_STACK    -12
68 /* These two are for the signal mechanism. */
69 #define LWP_EBADSIG     -13     /* bad signal number */
70 #define LWP_ESYSTEM     -14     /* system call failed */
71 /* These are for the rock mechanism */
72 #define LWP_ENOROCKS    -15     /* all rocks are in use */
73 #define LWP_EBADROCK    -16     /* the specified rock does not exist */
74
75 # if    defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
76 #  ifdef        USE_SOLARIS_THREADS
77 #   include <thread.h>
78 typedef int pthread_t;
79 typedef void *pthread_addr_t;
80 typedef void *pthread_condattr_t;
81 typedef void (*pthread_destructor_t) (void *);
82 typedef pthread_addr_t(*pthread_startroutine_t) (pthread_addr_t);
83 #define pthread_mutex_lock      mutex_lock
84 #define pthread_mutex_unlock    mutex_unlock
85 #define pthread_getspecific     thr_getspecific
86 #define pthread_setspecific     thr_setspecific
87 #define pthread_yield           thr_yield
88 /*typedef mutex_t pthread_mutex_t;*/
89 typedef thread_key_t pthread_key_t;
90 typedef cond_t PTHREAD_COND, *pthread_cond_t;
91
92 #define PTHREAD_DEFAULT_SCHED 1
93 #define SCHED_FIFO  2
94 #define MUTEX_FAST_NP              0
95 #define PTHREAD_DEFAULT_STACK           65536   /* 64 K */
96 #define PRI_OTHER_MIN   1
97 #define PRI_OTHER_MAX   127
98 #define PRI_OTHER_MID   ((PRI_OTHER_MIN + PRI_OTHER_MAX)/2)
99 #define DESTRUCTOR_TAB_CHUNK 20
100 #define maskAllSignals(o) thr_sigsetmask(SIG_BLOCK,&pthread_allSignals,&o)
101 #define restoreAllSignals(o) thr_sigsetmask(SIG_SETMASK,&o,NULL)
102
103 typedef struct PTHREAD_MUTEX {
104     int kind;
105     pthread_t ownerId;
106     mutex_t fastMutex;
107     int timesInside;
108 } PTHREAD_MUTEX, *pthread_mutex_t;
109
110
111 typedef struct PTHREAD_ATTR {
112     long stackSize;
113     int prio;
114 } PTHREAD_ATTR, *pthread_attr_t;
115
116 typedef struct {
117     void (*destructor) (void *);
118     thread_key_t key;
119 } dest_slot_t;
120
121 typedef struct {
122     int nentries;               /* size allocated (in terms of number of slots) */
123     int next_free;              /* next free slot */
124     dest_slot_t slot[1];
125 } pthread_destructor_tab_t;
126 define DTAB_SIZE(size) (sizeof(pthread_destructor_tab_t) +
127                         (size) * sizeof(dest_slot_t))
128 # else
129 #  include "pthread.h"
130 # endif
131 # include <assert.h>
132
133 #define LWP_MAX_PRIORITY        0
134 #define LWP_NORMAL_PRIORITY     0
135 #define LWP_NO_PRIORITIES
136 /*
137  * We define PROCESS as a pointer to this struct, rather than simply as
138  * a pthread_t  since some applications test for a process handle being
139  * non-zero. This can't be done on a pthread_t.
140  */
141 typedef struct lwp_process {
142     pthread_t handle;           /* The pthreads handle */
143     struct lwp_process *next;   /* Next LWP process */
144     char *name;                 /* LWP name of the process */
145     pthread_startroutine_t ep;  /* Process entry point */
146     pthread_addr_t arg;         /* Initial parameter */
147 } *PROCESS;
148
149 struct rock {                   /* to hide things associated with this LWP under */
150     int tag;                    /* unique identifier for this rock */
151     char *value;                /* pointer to some arbitrary data structure */
152 };
153
154 #define MAXROCKS        4       /* max no. of rocks per LWP */
155
156 #define DEBUGF          0
157
158 # ifndef BDE_THREADS
159 /*#define CMA_DEBUG 1*/
160 # endif
161
162 # ifdef CMA_DEBUG
163 #  define LWP_CHECKSTUFF(msg)   lwp_checkstuff(msg)
164 # else
165 #  define LWP_CHECKSTUFF(msg)
166 # endif
167
168 # if DEBUGF
169 #  define debugf(m) printf m
170 # else
171 #  define debugf(m)
172 # endif
173
174 # define IOMGR_Poll() LWP_DispatchProcess()
175
176 /*
177  * These two macros can be used to enter/exit the LWP context in a CMA
178  * program. They simply acquire/release the global LWP mutex .
179  */
180 extern pthread_mutex_t lwp_mutex;
181 #define LWP_EXIT_LWP_CONTEXT() pthread_mutex_unlock(&lwp_mutex)
182 #define LWP_ENTER_LWP_CONTEXT() pthread_mutex_lock(&lwp_mutex)
183 #else
184 #ifndef AFS_NT40_ENV
185 #define lwp_abort() abort()
186 #endif
187 /* Maximum priority permissible (minimum is always 0) */
188 #define LWP_MAX_PRIORITY 4      /* changed from 1 */
189
190 /* Usual priority used by user LWPs */
191 #define LWP_NORMAL_PRIORITY (LWP_MAX_PRIORITY-2)
192
193 /* Initial size of eventlist in a PCB; grows dynamically  */
194 #define EVINITSIZE  5
195
196 typedef struct lwp_pcb *PROCESS;
197
198 #ifdef AFS_NT40_ENV
199 #include <windef.h>
200 typedef struct lwp_pcb {
201     char name[32];              /* name of LWP */
202     LPVOID fiber;
203     int (*funP) ();             /* function to execute on this LWP */
204     void *argP;                 /* argument for function */
205     int priority;               /* LWP priority */
206     int stacksize;              /* Just for reference. */
207     /* the following are used for scheduling */
208     int status:8;
209     int eventlistsize:8;
210     int eventcnt:8;
211     int padding:8;
212     void **eventlist;
213     int wakevent;
214     int waitcnt;
215     struct lwp_pcb *next, *prev;
216     struct IoRequest *iomgrRequest;
217     int index;                  /* new number (++) for each process created. */
218 } lwp_pcb_t;
219
220 #else
221 struct lwp_context {            /* saved context for dispatcher */
222     char *topstack;             /* ptr to top of process stack */
223 #if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
224     ucontext_t ucontext;
225     int state;
226 #else                           /* !HAVE_UCONTEXT_H */
227 # if defined(sparc) && !defined(__linux__)
228 # ifdef save_allregs
229     int globals[7 + 1 + 32 + 2 + 32 + 2];       /* g1-g7, y reg, f0-f31, fsr, fq, c0-c31, csr, cq. */
230 # else
231     int globals[8];             /* g1-g7 and y registers. */
232 # endif
233 # endif
234     jmp_buf setjmp_buffer;
235 #endif                          /* HAVE_UCONTEXT_H */
236 };
237
238 struct rock {                   /* to hide things associated with this LWP under */
239     int tag;                    /* unique identifier for this rock */
240     char *value;                /* pointer to some arbitrary data structure */
241 };
242
243 #define MAXROCKS        4       /* max no. of rocks per LWP */
244
245 struct lwp_pcb {                /* process control block */
246     char name[32];              /* ASCII name */
247     int rc;                     /* most recent return code */
248     char status;                /* status flags */
249     char blockflag;             /* if (blockflag), process blocked */
250     char eventlistsize;         /* size of eventlist array */
251     char padding;               /* force 32-bit alignment */
252     void **eventlist;           /* ptr to array of eventids */
253     int eventcnt;               /* no. of events currently in eventlist array */
254     int wakevent;               /* index of eventid causing wakeup */
255     int waitcnt;                /* min number of events awaited */
256     int priority;               /* dispatching priority */
257     struct lwp_pcb *misc;       /* for LWP internal use only */
258     char *stack;                /* ptr to process stack */
259     int stacksize;              /* size of stack */
260     int stackcheck;             /* first word of stack for overflow checking */
261     void *(*ep)(void *);        /* initial entry point */
262     char *parm;                 /* initial parm for process */
263     struct lwp_context
264       context;                  /* saved context for next dispatch */
265     int lwp_rused;              /* no of rocks presently in use */
266     struct rock lwp_rlist[MAXROCKS];    /* set of rocks to hide things under */
267     struct lwp_pcb *next, *prev;        /* ptrs to next and previous pcb */
268     int level;                  /* nesting level of critical sections */
269     struct IoRequest *iomgrRequest;     /* request we're waiting for */
270     int index;                  /* LWP index: should be small index; actually is
271                                  * incremented on each lwp_create_process */
272 };
273 #endif /* AFS_NT40_ENV */
274
275 extern int lwp_nextindex;       /* Next lwp index to assign */
276
277
278 #ifndef LWP_KERNEL
279 #define LWP_ActiveProcess       (lwp_cpptr+0)
280 #define LWP_Index() (LWP_ActiveProcess->index)
281 #define LWP_HighestIndex() (lwp_nextindex - 1)
282 #ifndef AFS_SUN5_ENV            /* Actual functions for solaris */
283 #define LWP_SignalProcess(event)        LWP_INTERNALSIGNAL(event, 1)
284 #define LWP_NoYieldSignal(event)        LWP_INTERNALSIGNAL(event, 0)
285 #endif
286
287 extern
288 #endif
289 struct lwp_pcb *lwp_cpptr;      /* pointer to current process pcb */
290
291 struct lwp_ctl {                /* LWP control structure */
292     int processcnt;             /* number of lightweight processes */
293     char *outersp;              /* outermost stack pointer */
294     struct lwp_pcb *outerpid;   /* process carved by Initialize */
295     struct lwp_pcb *first, last;        /* ptrs to first and last pcbs */
296 #ifdef __hp9000s800
297     double dsptchstack[200];    /* stack for dispatcher use only */
298     /* force 8 byte alignment        */
299 #else
300     char dsptchstack[800];      /* stack for dispatcher use only */
301 #endif
302 };
303
304 #ifndef LWP_KERNEL
305 extern
306 #endif
307 char lwp_debug;                 /* ON = show LWP debugging trace */
308
309 /* 
310  * Under hpux, any stack size smaller than 16K seems prone to
311  * overflow problems.
312  *
313  * On Solaris 2.5, gethostbyname() can use up to 21920 bytes of stack
314  * space.  Note: when measuring this, it is important to check the
315  * amount of stack space it uses for hosts that are known as well as
316  * for hosts that are unknown; the stack usage can differ between these
317  * cases, and also between machines apparently running the same OS
318  * version.
319  */
320 /*
321  * On ia64 where the ucontext is used, it can be an extra 48K
322  * Need to account for this.  There might be two of these on the
323  * stack too. This needs to be checked.
324  */
325 #if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
326 #define AFS_LWP_MINSTACKSIZE  (288 * 1024)
327 #elif defined(AFS_LINUX22_ENV)
328 #define AFS_LWP_MINSTACKSIZE    (192 * 1024)
329 #else
330 #define AFS_LWP_MINSTACKSIZE    (48 * 1024)
331 #endif
332
333 /* Action to take on stack overflow. */
334 #define LWP_SOQUIET     1       /* do nothing */
335 #define LWP_SOABORT     2       /* abort the program */
336 #define LWP_SOMESSAGE   3       /* print a message and be quiet */
337 extern int lwp_overflowAction;
338
339 /* Tells if stack size counting is enabled. */
340 extern int lwp_stackUseEnabled;
341 extern int lwp_MaxStackSeen;
342
343 #ifndef AFS_AIX32_ENV
344 #define LWP_CreateProcess2(a, b, c, d, e, f)    \
345         LWP_CreateProcess((a), (b), (c), (d), (e), (f))
346 #endif
347
348 #endif /* USE_PTHREADS */
349
350 /* iomgr.c */
351 extern fd_set *IOMGR_AllocFDSet(void);
352 extern int IOMGR_Select(int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,
353                         struct timeval *tvp);
354 extern int IOMGR_Poll(void);
355 extern void IOMGR_Sleep(int seconds);
356 extern int IOMGR_Cancel(PROCESS pid);
357 extern int IOMGR_Initialize(void);
358 extern void IOMGR_FreeFDSet(fd_set * fds);
359 extern int IOMGR_SoftSig(void *(*aproc) (void *), void *arock);
360
361 extern int LWP_WaitForKeystroke(int seconds);   /* -1 => forever */
362 extern int LWP_GetResponseKey(int seconds, char *key);
363 extern int LWP_GetLine(char *linebuf, int len);
364 #ifdef AFS_NT40_ENV
365 /* lwp.c */
366 extern int LWP_InitializeProcessSupport(int priority, PROCESS * pid);
367 extern int LWP_CreateProcess(int (*funP) (), int stacksize, int priority,
368                              void *argP, char *name, PROCESS * pid);
369 extern int LWP_DestroyProcess(PROCESS pid);
370 extern int LWP_DispatchProcess(void);
371 extern int LWP_WaitProcess(void *event);
372 extern int LWP_INTERNALSIGNAL(void *event, int yield);
373 extern int LWP_QWait(void);
374 extern int LWP_QSignal(PROCESS pid);
375 #else
376 extern int LWP_CurrentProcess(PROCESS * pid);
377 extern int LWP_INTERNALSIGNAL(void *event, int yield);
378 extern int LWP_InitializeProcessSupport(int priority, PROCESS * pid);
379 extern int LWP_CreateProcess(void *(*ep)(void *), int stacksize, int priority,
380                              void *parm, char *name, PROCESS * pid);
381 extern int LWP_DestroyProcess(PROCESS pid);
382 extern int LWP_DispatchProcess(void);
383 extern int LWP_WaitProcess(void *event);
384 extern PROCESS LWP_ThreadId(void);
385 extern int LWP_QWait(void);
386 extern int LWP_QSignal(PROCESS pid);
387 #endif
388
389 extern afs_int32 savecontext(void (*ep)(void), 
390                              struct lwp_context *savearea, char *sp);
391 extern void returnto(struct lwp_context *savearea);
392
393 #ifdef AFS_LINUX24_ENV
394 /* max time we are allowed to spend in a select call on Linux to avoid 
395  lost signal issues */
396 #define IOMGR_MAXWAITTIME        60     /* seconds */
397 #else
398 /* max time we are allowed to spend in a select call on NT */
399 #define IOMGR_MAXWAITTIME        5      /* seconds */
400 #endif
401
402 /* max time we spend on a select in a Win95 DOS box */
403 #define IOMGR_WIN95WAITTIME 5000        /* microseconds */
404
405 #endif
406 #endif /* __LWP_INCLUDE_ */
407
408 #endif /* !KERNEL && !_KMEMUSER */