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