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