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