2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /*******************************************************************\
12 * Information Technology Center *
13 * Carnegie-Mellon University *
16 \*******************************************************************/
18 #ifndef __LWP_INCLUDE_
19 #define __LWP_INCLUDE_ 1
21 #if !defined(KERNEL) && !defined(_KMEMUSER)
22 #include <afs/param.h>
24 /* External function declarations. */
26 #ifndef _MFC_VER /*skip if doing Microsoft foundation class */
29 #elif defined(AFS_LINUX20_ENV)
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 */
38 # include <sys/select.h> /* fd_set on newer platforms */
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);
48 #if !defined(AFS_PTHREAD_ENV)
49 # if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
50 # include <ucontext.h>
56 #define LWP_EBADPID -1
57 #define LWP_EBLOCKED -2
59 #define LWP_EMAXPROC -4
60 #define LWP_ENOBLOCK -5
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 */
75 # if defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
76 # ifdef USE_SOLARIS_THREADS
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;
92 #define PTHREAD_DEFAULT_SCHED 1
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)
103 typedef struct PTHREAD_MUTEX {
108 } PTHREAD_MUTEX, *pthread_mutex_t;
111 typedef struct PTHREAD_ATTR {
114 } PTHREAD_ATTR, *pthread_attr_t;
117 void (*destructor) (void *);
122 int nentries; /* size allocated (in terms of number of slots) */
123 int next_free; /* next free slot */
125 } pthread_destructor_tab_t;
126 define DTAB_SIZE(size) (sizeof(pthread_destructor_tab_t) +
127 (size) * sizeof(dest_slot_t))
129 # include "pthread.h"
133 #define LWP_MAX_PRIORITY 0
134 #define LWP_NORMAL_PRIORITY 0
135 #define LWP_NO_PRIORITIES
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.
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 */
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 */
154 #define MAXROCKS 4 /* max no. of rocks per LWP */
159 /*#define CMA_DEBUG 1*/
163 # define LWP_CHECKSTUFF(msg) lwp_checkstuff(msg)
165 # define LWP_CHECKSTUFF(msg)
169 # define debugf(m) printf m
174 # define IOMGR_Poll() LWP_DispatchProcess()
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 .
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)
185 #define lwp_abort() abort()
187 /* Maximum priority permissible (minimum is always 0) */
188 #define LWP_MAX_PRIORITY 4 /* changed from 1 */
190 /* Usual priority used by user LWPs */
191 #define LWP_NORMAL_PRIORITY (LWP_MAX_PRIORITY-2)
193 /* Initial size of eventlist in a PCB; grows dynamically */
196 typedef struct lwp_pcb *PROCESS;
200 typedef struct lwp_pcb {
201 char name[32]; /* name of LWP */
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 */
215 struct lwp_pcb *next, *prev;
216 struct IoRequest *iomgrRequest;
217 int index; /* new number (++) for each process created. */
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)
226 #else /* !HAVE_UCONTEXT_H */
227 # if defined(sparc) && !defined(__linux__)
229 int globals[7 + 1 + 32 + 2 + 32 + 2]; /* g1-g7, y reg, f0-f31, fsr, fq, c0-c31, csr, cq. */
231 int globals[8]; /* g1-g7 and y registers. */
234 jmp_buf setjmp_buffer;
235 #endif /* HAVE_UCONTEXT_H */
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 */
243 #define MAXROCKS 4 /* max no. of rocks per LWP */
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 */
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 */
273 #endif /* AFS_NT40_ENV */
275 extern int lwp_nextindex; /* Next lwp index to assign */
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)
289 struct lwp_pcb *lwp_cpptr; /* pointer to current process pcb */
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 */
297 double dsptchstack[200]; /* stack for dispatcher use only */
298 /* force 8 byte alignment */
300 char dsptchstack[800]; /* stack for dispatcher use only */
307 char lwp_debug; /* ON = show LWP debugging trace */
310 * Under hpux, any stack size smaller than 16K seems prone to
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
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.
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)
330 #define AFS_LWP_MINSTACKSIZE (48 * 1024)
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;
339 /* Tells if stack size counting is enabled. */
340 extern int lwp_stackUseEnabled;
341 extern int lwp_MaxStackSeen;
343 #ifndef AFS_AIX32_ENV
344 #define LWP_CreateProcess2(a, b, c, d, e, f) \
345 LWP_CreateProcess((a), (b), (c), (d), (e), (f))
348 #endif /* USE_PTHREADS */
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);
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);
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);
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(register PROCESS pid);
389 extern afs_int32 savecontext(void (*ep)(void),
390 struct lwp_context *savearea, char *sp);
391 extern void returnto(struct lwp_context *savearea);
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 */
398 /* max time we are allowed to spend in a select call on NT */
399 #define IOMGR_MAXWAITTIME 5 /* seconds */
402 /* max time we spend on a select in a Win95 DOS box */
403 #define IOMGR_WIN95WAITTIME 5000 /* microseconds */
406 #endif /* __LWP_INCLUDE_ */
408 #endif /* !KERNEL && !_KMEMUSER */