Bug Summary

File:lwp/./lwp.c
Location:line 150, column 12
Description:Access to field 'next' results in a dereference of a null pointer (loaded from variable 'p')

Annotated Source Code

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#include <afsconfig.h>
18#include <afs/param.h>
19
20#include <roken.h>
21
22/* allocate externs here */
23#define LWP_KERNEL
24#include "lwp.h"
25
26#ifdef AFS_AIX32_ENV
27#include <ulimit.h>
28#include <sys/errno(* __error()).h>
29#include <sys/user.h>
30#include <sys/pseg.h>
31#include <sys/core.h>
32#pragma alloca
33int setlim(int limcon, uchar_t hard, int limit);
34#endif
35
36#ifndef AFS_ARM_LINUX20_ENV
37#if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
38extern int PRE_Block; /* from preempt.c */
39#else
40extern char PRE_Block; /* from preempt.c */
41#endif
42#endif
43
44#define ON1 1
45#define OFF0 0
46#define TRUE1 1
47#define FALSE0 0
48#define READY2 2
49#define WAITING3 3
50#define DESTROYED4 4
51#define QWAITING5 5
52#define MAXINT(~(1<<((sizeof(int)*8)-1))) (~(1<<((sizeof(int)*8)-1)))
53#define MINSTACK44 44
54
55#if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
56#define MINFRAME 128
57#define STACK_ALIGN4 8
58#else
59#ifdef __s390x__
60#define MINFRAME 160
61#define STACK_ALIGN4 8
62#else
63#ifdef __s390__
64#define MINFRAME 96
65#define STACK_ALIGN4 8
66#elif defined(AFS_DARWIN_ENV)
67#define STACK_ALIGN4 16
68#else
69#define STACK_ALIGN4 4
70#endif
71#endif
72#endif
73
74/* Debugging macro */
75#ifdef DEBUG
76#define Debug(level, msg)do { ; } while (0) do { \
77 if (lwp_debug && lwp_debug >= level) { \
78 printf("***LWP (0x%x): ", lwp_cpptr); \
79 printf msg; \
80 putchar('\n')(!__isthreaded ? __sputc('\n', __stdoutp) : (putc)('\n', __stdoutp
))
; \
81 } \
82} while (0)
83#else
84#define Debug(level, msg)do { ; } while (0) do { \
85 ; \
86} while (0)
87#endif
88
89static void Dispatcher(void);
90static void Create_Process_Part2(void);
91static void Exit_LWP(void);
92static afs_int32 Initialize_Stack(char *stackptr, int stacksize);
93static int Stack_Used(char *stackptr, int stacksize);
94
95static void Abort_LWP(char *msg);
96static void Overflow_Complain(void);
97static void Initialize_PCB(PROCESS temp, int priority, char *stack,
98 int stacksize, void *(*ep)(void *), void *parm,
99 char *name);
100static void Dispose_of_Dead_PCB(PROCESS cur);
101static void Free_PCB(PROCESS pid);
102static int Internal_Signal(void *event);
103static int purge_dead_pcbs(void);
104static int LWP_MwaitProcess(int wcount, void *evlist[]);
105
106
107#define MAX_PRIORITIES(4 +1) (LWP_MAX_PRIORITY4+1)
108
109struct QUEUE {
110 PROCESS head;
111 int count;
112} runnable[MAX_PRIORITIES(4 +1)], blocked, qwaiting;
113/* Invariant for runnable queues: The head of each queue points to the
114 * currently running process if it is in that queue, or it points to the
115 * next process in that queue that should run. */
116
117/* Offset of stack field within pcb -- used by stack checking stuff */
118int stack_offset;
119
120/* special user-tweakable option for AIX */
121int lwp_MaxStackSize = 32768;
122
123/* biggest LWP stack created so far */
124int lwp_MaxStackSeen = 0;
125
126/* Stack checking action */
127int lwp_overflowAction = LWP_SOABORT2;
128
129/* Controls stack size counting. */
130int lwp_stackUseEnabled = TRUE1; /* pay the price */
131
132int lwp_nextindex;
133
134/* Minimum stack size */
135int lwp_MinStackSize = 0;
136
137static int
138lwp_remove(PROCESS p, struct QUEUE *q)
139{
140 /* Special test for only element on queue */
141 if (q->count == 1)
1
Taking true branch
142 q->head = NULL((void *)0);
143 else {
144 /* Not only element, do normal remove */
145 p->next->prev = p->prev;
146 p->prev->next = p->next;
147 }
148 /* See if head pointing to this element */
149 if (q->head == p)
2
Taking true branch
150 q->head = p->next;
3
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'p')
151 q->count--;
152 p->next = p->prev = NULL((void *)0);
153 return 0;
154}
155
156static int
157insert(PROCESS p, struct QUEUE *q)
158{
159 if (q->head == NULL((void *)0)) { /* Queue is empty */
160 q->head = p;
161 p->next = p->prev = p;
162 } else { /* Regular insert */
163 p->prev = q->head->prev;
164 q->head->prev->next = p;
165 q->head->prev = p;
166 p->next = q->head;
167 }
168 q->count++;
169 return 0;
170}
171
172static int
173move(PROCESS p, struct QUEUE *from, struct QUEUE *to)
174{
175
176 lwp_remove(p, from);
177
178 insert(p, to);
179 return 0;
180}
181
182/* Iterator macro */
183#define for_all_elts(var, q, body){ PROCESS var, _NEXT_; int _I_; for (_I_=q.count, var = q.head
; _I_>0; _I_--, var=_NEXT_) { _NEXT_ = var -> next; body
} }
\
184 {\
185 PROCESS var, _NEXT_;\
186 int _I_;\
187 for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\
188 _NEXT_ = var -> next;\
189 body\
190 }\
191 }
192
193/* */
194/*****************************************************************************\
195* *
196* Following section documents the Assembler interfaces used by LWP code *
197* *
198\*****************************************************************************/
199
200/*
201 savecontext(int (*ep)(), struct lwp_context *savearea, char *sp);
202
203Stub for Assembler routine that will
204save the current SP value in the passed
205context savearea and call the function
206whose entry point is in ep. If the sp
207parameter is NULL, the current stack is
208used, otherwise sp becomes the new stack
209pointer.
210
211 returnto(struct lwp_context *savearea);
212
213Stub for Assembler routine that will
214restore context from a passed savearea
215and return to the restored C frame.
216
217*/
218
219/* Macro to force a re-schedule. Strange name is historical */
220#define Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
savecontext(Dispatcher, &lwp_cpptr->context, NULL((void *)0))
221
222static struct lwp_ctl *lwp_init = 0;
223
224int
225LWP_QWait(void)
226{
227 PROCESS tp;
228 (tp = lwp_cpptr)->status = QWAITING5;
229 move(tp, &runnable[tp->priority], &qwaiting);
230 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
231 return LWP_SUCCESS0;
232}
233
234int
235LWP_QSignal(PROCESS pid)
236{
237 if (pid->status == QWAITING5) {
238 pid->status = READY2;
239 move(pid, &qwaiting, &runnable[pid->priority]);
240 return LWP_SUCCESS0;
241 } else
242 return LWP_ENOWAIT-8;
243}
244
245#ifdef AFS_AIX32_ENV
246char *
247reserveFromStack(afs_int32 size)
248{
249 char *x;
250 x = alloca(size)__builtin_alloca(size);
251 return x;
252}
253#endif
254
255int
256LWP_CreateProcess(void *(*ep) (void *), int stacksize, int priority, void *parm,
257 char *name, PROCESS * pid)
258{
259 PROCESS temp, temp2;
260#ifdef AFS_AIX32_ENV
261 static char *stackptr = 0;
262#else
263 char *stackptr;
264#endif
265 char *stackmemory;
266
267#if defined(AFS_LWP_MINSTACKSIZE(48 * 1024))
268 /*
269 * on some systems (e.g. hpux), a minimum usable stack size has
270 * been discovered
271 */
272 if (stacksize < lwp_MinStackSize) {
273 stacksize = lwp_MinStackSize;
274 }
275#endif /* defined(AFS_LWP_MINSTACKSIZE) */
276 /* more stack size computations; keep track of for IOMGR */
277 if (lwp_MaxStackSeen < stacksize)
278 lwp_MaxStackSeen = stacksize;
279
280 Debug(0, ("Entered LWP_CreateProcess"))do { ; } while (0);
281 /* Throw away all dead process control blocks */
282 purge_dead_pcbs();
283 if (lwp_init) {
284 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
285 if (temp == NULL((void *)0)) {
286 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
287 return LWP_ENOMEM-6;
288 }
289 if (stacksize < MINSTACK44)
290#ifdef AFS_DARWIN_ENV
291 stacksize = 1008;
292#else /* !AFS_DARWIN_ENV */
293 stacksize = 1000;
294#endif /* !AFS_DARWIN_ENV */
295 else
296 stacksize =
297 STACK_ALIGN4 * ((stacksize + STACK_ALIGN4 - 1) / STACK_ALIGN4);
298#ifdef AFS_AIX32_ENV
299 if (!stackptr) {
300 /*
301 * The following signal action for AIX is necessary so that in case of a
302 * crash (i.e. core is generated) we can include the user's data section
303 * in the core dump. Unfortunately, by default, only a partial core is
304 * generated which, in many cases, isn't too useful.
305 *
306 * We also do it here in case the main program forgets to do it.
307 */
308 struct sigaction nsa;
309 extern uid_t geteuid();
310
311 sigemptyset(&nsa.sa_mask);
312 nsa.sa_handler__sigaction_u.__sa_handler = SIG_DFL((__sighandler_t *)0);
313 nsa.sa_flags = SA_FULLDUMP;
314 sigaction(SIGABRT6, &nsa, NULL((void *)0));
315 sigaction(SIGSEGV11, &nsa, NULL((void *)0));
316
317 /*
318 * First we need to increase the default resource limits,
319 * if necessary, so that we can guarantee that we have the
320 * resources to create the core file, but we can't always
321 * do it as an ordinary user.
322 */
323 if (!geteuid()) {
324 /* vos dump causes problems */
325 /* setlim(RLIMIT_FSIZE, 0, 1048575); * 1 Gig */
326 setlim(RLIMIT_STACK, 0, 65536); /* 65 Meg */
327 setlim(RLIMIT_CORE, 0, 131072); /* 131 Meg */
328 }
329 /*
330 * Now reserve in one scoop all the stack space that will be used
331 * by the particular application's main (i.e. non-lwp) body. This
332 * is plenty space for any of our applications.
333 */
334 stackptr = reserveFromStack(lwp_MaxStackSize);
335 }
336 stackptr -= stacksize;
337 stackmemory = stackptr;
338#else
339#ifdef AFS_DARWIN_ENV
340 if ((stackmemory = (char *)malloc(stacksize + STACK_ALIGN4 - 1)) == NULL((void *)0))
341#else /* !AFS_DARWIN_ENV */
342 if ((stackmemory = (char *)malloc(stacksize + 7)) == NULL((void *)0))
343#endif /* !AFS_DARWIN_ENV */
344 {
345 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
346 return LWP_ENOMEM-6;
347 }
348 /* Round stack pointer to byte boundary */
349#ifdef AFS_DARWIN_ENV
350 stackptr = (char *)(STACK_ALIGN4 * (((long)stackmemory + STACK_ALIGN4 - 1) / STACK_ALIGN4));
351#else /* !AFS_DARWIN_ENV */
352 stackptr = (char *)(8 * (((long)stackmemory + 7) / 8));
353#endif /* !AFS_DARWIN_ENV */
354#endif
355 if (priority < 0 || priority >= MAX_PRIORITIES(4 +1)) {
356 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
357 return LWP_EBADPRI-11;
358 }
359 Initialize_Stack(stackptr, stacksize);
360 Initialize_PCB(temp, priority, stackmemory, stacksize, ep, parm, name);
361 insert(temp, &runnable[priority]);
362 temp2 = lwp_cpptr;
363#if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
364 if (PRE_Block != 0)
365 Abort_LWP("PRE_Block not 0");
366
367 /* Gross hack: beware! */
368 PRE_Block = 1;
369#endif
370 lwp_cpptr = temp;
371#if defined(AFS_PARISC_LINUX24_ENV)
372 savecontext(Create_Process_Part2, &temp2->context,
373 stackptr + MINFRAME);
374#else
375#ifdef __hp9000s800
376 savecontext(Create_Process_Part2, &temp2->context,
377 stackptr + MINFRAME);
378#else
379#if defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV1)
380#ifdef sys_x86_darwin_80
381 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16 - sizeof(void *)); /* 16 = 2 * jmp_buf_type */
382#else /* !sys_x86_darwin_80 */
383 /* Need to have the sp on an 8-byte boundary for storing doubles. */
384 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16); /* 16 = 2 * jmp_buf_type */
385#endif /* !sys_x86_darwin_80 */
386#else
387#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
388 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 0x40); /* lomgjmp does something
389 * with %fp + 0x38 */
390#else
391#if defined(AFS_S390_LINUX20_ENV)
392 savecontext(Create_Process_Part2, &temp2->context,
393 stackptr + stacksize - MINFRAME);
394#else /* !AFS_S390_LINUX20_ENV */
395 savecontext(Create_Process_Part2, &temp2->context,
396 stackptr + stacksize - sizeof(void *));
397#endif /* AFS_S390_LINUX20_ENV */
398#endif /* AFS_SPARC64_LINUX20_ENV || AFS_SPARC_LINUX20_ENV */
399#endif /* AFS_SGI62_ENV */
400#endif
401#endif
402 /* End of gross hack */
403
404 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
405 if (pid)
406 *pid = temp;
407 return 0;
408 } else
409 return LWP_EINIT-3;
410}
411
412#ifdef AFS_AIX32_ENV
413int
414LWP_CreateProcess2(void *(*ep) (void *), int stacksize, int priority, void *parm,LWP_CreateProcess((void *(*ep) (void *)), (int stacksize), (int
priority), (void *parm), (char *name), (PROCESS * pid))
415 char *name, PROCESS * pid)LWP_CreateProcess((void *(*ep) (void *)), (int stacksize), (int
priority), (void *parm), (char *name), (PROCESS * pid))
416{
417 PROCESS temp, temp2;
418 char *stackptr;
419
420#if defined(AFS_LWP_MINSTACKSIZE(48 * 1024))
421 /*
422 * on some systems (e.g. hpux), a minimum usable stack size has
423 * been discovered
424 */
425 if (stacksize < lwp_MinStackSize) {
426 stacksize = lwp_MinStackSize;
427 }
428#endif /* defined(AFS_LWP_MINSTACKSIZE) */
429 /* more stack size computations; keep track of for IOMGR */
430 if (lwp_MaxStackSeen < stacksize)
431 lwp_MaxStackSeen = stacksize;
432
433 Debug(0, ("Entered LWP_CreateProcess"))do { ; } while (0);
434 /* Throw away all dead process control blocks */
435 purge_dead_pcbs();
436 if (lwp_init) {
437 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
438 if (temp == NULL((void *)0)) {
439 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
440 return LWP_ENOMEM-6;
441 }
442 if (stacksize < MINSTACK44)
443 stacksize = 1000;
444 else
445 stacksize =
446 STACK_ALIGN4 * ((stacksize + STACK_ALIGN4 - 1) / STACK_ALIGN4);
447 if ((stackptr = (char *)malloc(stacksize)) == NULL((void *)0)) {
448 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
449 return LWP_ENOMEM-6;
450 }
451 if (priority < 0 || priority >= MAX_PRIORITIES(4 +1)) {
452 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
453 return LWP_EBADPRI-11;
454 }
455 Initialize_Stack(stackptr, stacksize);
456 Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
457 insert(temp, &runnable[priority]);
458 temp2 = lwp_cpptr;
459#if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
460 if (PRE_Block != 0)
461 Abort_LWP("PRE_Block not 0");
462
463 /* Gross hack: beware! */
464 PRE_Block = 1;
465#endif
466 lwp_cpptr = temp;
467 savecontext(Create_Process_Part2, &temp2->context,
468 stackptr + stacksize - sizeof(void *));
469 /* End of gross hack */
470
471 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
472 if (pid)
473 *pid = temp;
474 return 0;
475 } else
476 return LWP_EINIT-3;
477}
478#endif
479
480int
481LWP_CurrentProcess(PROCESS * pid)
482{ /* returns pid of current process */
483 Debug(0, ("Entered Current_Process"))do { ; } while (0);
484 if (lwp_init) {
485 *pid = lwp_cpptr;
486 return LWP_SUCCESS0;
487 } else
488 return LWP_EINIT-3;
489}
490
491PROCESS
492LWP_ThreadId(void)
493{
494 Debug(0, ("Entered ThreadId"))do { ; } while (0);
495 if (lwp_init)
496 return lwp_cpptr;
497 else
498 return (PROCESS) 0;
499}
500
501#define LWPANCHOR(*lwp_init) (*lwp_init)
502
503int
504LWP_DestroyProcess(PROCESS pid)
505{ /* destroy a lightweight process */
506 PROCESS temp;
507
508 Debug(0, ("Entered Destroy_Process"))do { ; } while (0);
509 if (lwp_init) {
510 if (lwp_cpptr != pid) {
511 Dispose_of_Dead_PCB(pid);
512 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
513 } else {
514 pid->status = DESTROYED4;
515 move(pid, &runnable[pid->priority], &blocked);
516 temp = lwp_cpptr;
517#if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
518 savecontext(Dispatcher, &(temp->context),
519 &(LWPANCHOR(*lwp_init).dsptchstack[MINFRAME]));
520#elif defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV1)
521 savecontext(Dispatcher, &(temp->context),
522 &(LWPANCHOR(*lwp_init).
523 dsptchstack[(sizeof LWPANCHOR(*lwp_init).dsptchstack) - 8]));
524#elif defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
525 savecontext(Dispatcher, &(temp->context),
526 &(LWPANCHOR(*lwp_init).
527 dsptchstack[(sizeof LWPANCHOR(*lwp_init).dsptchstack) -
528 0x40]));
529#elif defined(AFS_S390_LINUX20_ENV)
530 savecontext(Dispatcher, &(temp->context),
531 &(LWPANCHOR(*lwp_init).
532 dsptchstack[(sizeof LWPANCHOR(*lwp_init).dsptchstack) -
533 MINFRAME]));
534#else
535 savecontext(Dispatcher, &(temp->context),
536 &(LWPANCHOR(*lwp_init).
537 dsptchstack[(sizeof LWPANCHOR(*lwp_init).dsptchstack) -
538 sizeof(void *)]));
539#endif
540 }
541 return LWP_SUCCESS0;
542 } else
543 return LWP_EINIT-3;
544}
545
546int
547LWP_DispatchProcess(void)
548{ /* explicit voluntary preemption */
549 Debug(2, ("Entered Dispatch_Process"))do { ; } while (0);
550 if (lwp_init) {
551 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
552 return LWP_SUCCESS0;
553 } else
554 return LWP_EINIT-3;
555}
556
557#ifdef DEBUG
558int
559Dump_Processes(void)
560{
561 if (lwp_init) {
562 int i;
563 for (i = 0; i < MAX_PRIORITIES(4 +1); i++)
564 for_all_elts(x, runnable[i], {{ PROCESS x, _NEXT_; int _I_; for (_I_=runnable[i].count, x =
runnable[i].head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x ->
next; { printf("[Priority %d]\n", i); Dump_One_Process(x); }
} }
565 printf("[Priority %d]\n", i);{ PROCESS x, _NEXT_; int _I_; for (_I_=runnable[i].count, x =
runnable[i].head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x ->
next; { printf("[Priority %d]\n", i); Dump_One_Process(x); }
} }
566 Dump_One_Process(x);{ PROCESS x, _NEXT_; int _I_; for (_I_=runnable[i].count, x =
runnable[i].head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x ->
next; { printf("[Priority %d]\n", i); Dump_One_Process(x); }
} }
567 }{ PROCESS x, _NEXT_; int _I_; for (_I_=runnable[i].count, x =
runnable[i].head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x ->
next; { printf("[Priority %d]\n", i); Dump_One_Process(x); }
} }
568 ){ PROCESS x, _NEXT_; int _I_; for (_I_=runnable[i].count, x =
runnable[i].head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x ->
next; { printf("[Priority %d]\n", i); Dump_One_Process(x); }
} }
569 for_all_elts(x, blocked, {{ PROCESS x, _NEXT_; int _I_; for (_I_=blocked.count, x = blocked
.head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x -> next; { Dump_One_Process
(x);} } }
570 Dump_One_Process(x);}{ PROCESS x, _NEXT_; int _I_; for (_I_=blocked.count, x = blocked
.head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x -> next; { Dump_One_Process
(x);} } }
571 ){ PROCESS x, _NEXT_; int _I_; for (_I_=blocked.count, x = blocked
.head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x -> next; { Dump_One_Process
(x);} } }
572 for_all_elts(x, qwaiting, {{ PROCESS x, _NEXT_; int _I_; for (_I_=qwaiting.count, x = qwaiting
.head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x -> next; { Dump_One_Process
(x);} } }
573 Dump_One_Process(x);}{ PROCESS x, _NEXT_; int _I_; for (_I_=qwaiting.count, x = qwaiting
.head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x -> next; { Dump_One_Process
(x);} } }
574 ){ PROCESS x, _NEXT_; int _I_; for (_I_=qwaiting.count, x = qwaiting
.head; _I_>0; _I_--, x=_NEXT_) { _NEXT_ = x -> next; { Dump_One_Process
(x);} } }
575 } else
576 printf("***LWP: LWP support not initialized\n");
577 return 0;
578}
579#endif
580
581int
582LWP_GetProcessPriority(PROCESS pid, int *priority)
583{ /* returns process priority */
584 Debug(0, ("Entered Get_Process_Priority"))do { ; } while (0);
585 if (lwp_init) {
586 *priority = pid->priority;
587 return 0;
588 } else
589 return LWP_EINIT-3;
590}
591
592int
593LWP_InitializeProcessSupport(int priority, PROCESS * pid)
594{
595 PROCESS temp;
596 struct lwp_pcb dummy;
597 int i;
598 char *value;
599
600 Debug(0, ("Entered LWP_InitializeProcessSupport"))do { ; } while (0);
601 if (lwp_init != NULL((void *)0))
602 return LWP_SUCCESS0;
603
604 /* Set up offset for stack checking -- do this as soon as possible */
605 stack_offset = (char *)&dummy.stack - (char *)&dummy;
606
607 if (priority >= MAX_PRIORITIES(4 +1))
608 return LWP_EBADPRI-11;
609 for (i = 0; i < MAX_PRIORITIES(4 +1); i++) {
610 runnable[i].head = NULL((void *)0);
611 runnable[i].count = 0;
612 }
613 blocked.head = NULL((void *)0);
614 blocked.count = 0;
615 qwaiting.head = NULL((void *)0);
616 qwaiting.count = 0;
617 lwp_init = (struct lwp_ctl *)malloc(sizeof(struct lwp_ctl));
618 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
619 if (lwp_init == NULL((void *)0) || temp == NULL((void *)0))
620 Abort_LWP("Insufficient Storage to Initialize LWP Support");
621 LWPANCHOR(*lwp_init).processcnt = 1;
622 LWPANCHOR(*lwp_init).outerpid = temp;
623 LWPANCHOR(*lwp_init).outersp = NULL((void *)0);
624 Initialize_PCB(temp, priority, NULL((void *)0), 0, NULL((void *)0), NULL((void *)0),
625 "Main Process [created by LWP]");
626 insert(temp, &runnable[priority]);
627 savecontext(Dispatcher, &temp->context, NULL((void *)0));
628 LWPANCHOR(*lwp_init).outersp = temp->context.topstack;
629 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
630 if (pid)
631 *pid = temp;
632
633 /* get minimum stack size from the environment. this allows the administrator
634 * to change the lwp stack dynamically without getting a new binary version.
635 */
636 if ((value = getenv("AFS_LWP_STACK_SIZE")) == NULL((void *)0))
637 lwp_MinStackSize = AFS_LWP_MINSTACKSIZE(48 * 1024);
638 else
639 lwp_MinStackSize =
640 (AFS_LWP_MINSTACKSIZE(48 * 1024) >
641 atoi(value) ? AFS_LWP_MINSTACKSIZE(48 * 1024) : atoi(value));
642
643 return LWP_SUCCESS0;
644}
645
646int
647LWP_INTERNALSIGNAL(void *event, int yield)
648{ /* signal the occurence of an event */
649 Debug(2, ("Entered LWP_SignalProcess"))do { ; } while (0);
650 if (lwp_init) {
651 int rc;
652 rc = Internal_Signal(event);
653 if (yield)
654 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
655 return rc;
656 } else
657 return LWP_EINIT-3;
658}
659
660int
661LWP_TerminateProcessSupport(void)
662{ /* terminate all LWP support */
663 int i;
664
665 Debug(0, ("Entered Terminate_Process_Support"))do { ; } while (0);
666 if (lwp_init == NULL((void *)0))
667 return LWP_EINIT-3;
668 if (lwp_cpptr != LWPANCHOR(*lwp_init).outerpid)
669 Abort_LWP("Terminate_Process_Support invoked from wrong process!");
670 for (i = 0; i < MAX_PRIORITIES(4 +1); i++)
671 for_all_elts(cur, runnable[i], {{ PROCESS cur, _NEXT_; int _I_; for (_I_=runnable[i].count, cur
= runnable[i].head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur
-> next; { Free_PCB(cur);} } }
672 Free_PCB(cur);}{ PROCESS cur, _NEXT_; int _I_; for (_I_=runnable[i].count, cur
= runnable[i].head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur
-> next; { Free_PCB(cur);} } }
673 ){ PROCESS cur, _NEXT_; int _I_; for (_I_=runnable[i].count, cur
= runnable[i].head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur
-> next; { Free_PCB(cur);} } }
674 for_all_elts(cur, blocked, {{ PROCESS cur, _NEXT_; int _I_; for (_I_=blocked.count, cur =
blocked.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { Free_PCB(cur);} } }
675 Free_PCB(cur);}{ PROCESS cur, _NEXT_; int _I_; for (_I_=blocked.count, cur =
blocked.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { Free_PCB(cur);} } }
676 ){ PROCESS cur, _NEXT_; int _I_; for (_I_=blocked.count, cur =
blocked.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { Free_PCB(cur);} } }
677 for_all_elts(cur, qwaiting, {{ PROCESS cur, _NEXT_; int _I_; for (_I_=qwaiting.count, cur =
qwaiting.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { Free_PCB(cur);} } }
678 Free_PCB(cur);}{ PROCESS cur, _NEXT_; int _I_; for (_I_=qwaiting.count, cur =
qwaiting.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { Free_PCB(cur);} } }
679 ){ PROCESS cur, _NEXT_; int _I_; for (_I_=qwaiting.count, cur =
qwaiting.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { Free_PCB(cur);} } }
680 free(lwp_init);
681 lwp_init = NULL((void *)0);
682 return LWP_SUCCESS0;
683}
684
685int
686LWP_WaitProcess(void *event)
687{ /* wait on a single event */
688 void *tempev[2];
689
690 Debug(2, ("Entered Wait_Process"))do { ; } while (0);
691 if (event == NULL((void *)0))
692 return LWP_EBADEVENT-10;
693 tempev[0] = event;
694 tempev[1] = NULL((void *)0);
695 return LWP_MwaitProcess(1, tempev);
696}
697
698int
699LWP_MwaitProcess(int wcount, void *evlist[])
700{ /* wait on m of n events */
701 int ecount, i;
702
703
704 Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount))do { ; } while (0);
705
706 if (evlist == NULL((void *)0)) {
707 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
708 return LWP_EBADCOUNT-9;
709 }
710
711 for (ecount = 0; evlist[ecount] != NULL((void *)0); ecount++);
712
713 if (ecount == 0) {
714 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
715 return LWP_EBADCOUNT-9;
716 }
717
718 if (lwp_init) {
719
720 if (wcount > ecount || wcount < 0) {
721 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
722 return LWP_EBADCOUNT-9;
723 }
724 if (ecount > lwp_cpptr->eventlistsize) {
725
726 lwp_cpptr->eventlist =
727 (void **)realloc(lwp_cpptr->eventlist,
728 ecount * sizeof(void *));
729 lwp_cpptr->eventlistsize = ecount;
730 }
731 for (i = 0; i < ecount; i++)
732 lwp_cpptr->eventlist[i] = evlist[i];
733 if (wcount > 0) {
734 lwp_cpptr->status = WAITING3;
735
736 move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked);
737
738 }
739 lwp_cpptr->wakevent = 0;
740 lwp_cpptr->waitcnt = wcount;
741 lwp_cpptr->eventcnt = ecount;
742
743 Set_LWP_RC()savecontext(Dispatcher, &lwp_cpptr->context, ((void *)
0))
;
744
745 return LWP_SUCCESS0;
746 }
747
748 return LWP_EINIT-3;
749}
750
751int
752LWP_StackUsed(PROCESS pid, int *maxa, int *used)
753{
754 *maxa = pid->stacksize;
755 *used = Stack_Used(pid->stack, *maxa);
756 if (*used == 0)
757 return LWP_NO_STACK-12;
758 return LWP_SUCCESS0;
759}
760
761/*
762 * The following functions are strictly
763 * INTERNAL to the LWP support package.
764 */
765
766static void
767Abort_LWP(char *msg)
768{
769 struct lwp_context tempcontext;
770
771 Debug(0, ("Entered Abort_LWP"))do { ; } while (0);
772 printf("***LWP: %s\n", msg);
773 printf("***LWP: Abort --- dumping PCBs ...\n");
774#ifdef DEBUG
775 Dump_Processes();
776#endif
777 if (LWPANCHOR(*lwp_init).outersp == NULL((void *)0))
778 Exit_LWP();
779 else
780 savecontext(Exit_LWP, &tempcontext, LWPANCHOR(*lwp_init).outersp);
781 return;
782}
783
784static void
785Create_Process_Part2(void)
786{ /* creates a context for the new process */
787 PROCESS temp;
788
789 Debug(2, ("Entered Create_Process_Part2"))do { ; } while (0);
790 temp = lwp_cpptr; /* Get current process id */
791 savecontext(Dispatcher, &temp->context, NULL((void *)0));
792 (*temp->ep) (temp->parm);
793 LWP_DestroyProcess(temp);
794 return;
795}
796
797static int
798Delete_PCB(PROCESS pid)
799{ /* remove a PCB from the process list */
800 Debug(4, ("Entered Delete_PCB"))do { ; } while (0);
801 lwp_remove(pid,
802 (pid->blockflag || pid->status == WAITING3
803 || pid->status ==
804 DESTROYED4 ? &blocked :
805 (pid->status == QWAITING5) ? &qwaiting :
806 &runnable[pid->priority]));
807 LWPANCHOR(*lwp_init).processcnt--;
808 return 0;
809}
810
811#ifdef DEBUG
812static int
813Dump_One_Process(PROCESS pid)
814{
815 int i;
816
817 printf("***LWP: Process Control Block at 0x%x\n", pid);
818 printf("***LWP: Name: %s\n", pid->name);
819 if (pid->ep != NULL((void *)0))
820 printf("***LWP: Initial entry point: 0x%x\n", pid->ep);
821 if (pid->blockflag)
822 printf("BLOCKED and ");
823 switch (pid->status) {
824 case READY2:
825 printf("READY");
826 break;
827 case WAITING3:
828 printf("WAITING");
829 break;
830 case DESTROYED4:
831 printf("DESTROYED");
832 break;
833 case QWAITING5:
834 printf("QWAITING");
835 break;
836 default:
837 printf("unknown");
838 }
839 putchar('\n')(!__isthreaded ? __sputc('\n', __stdoutp) : (putc)('\n', __stdoutp
))
;
840 printf("***LWP: Priority: %d \tInitial parameter: 0x%x\n", pid->priority,
841 pid->parm);
842 if (pid->stacksize != 0) {
843 printf("***LWP: Stacksize: %d \tStack base address: 0x%x\n",
844 pid->stacksize, pid->stack);
845 printf("***LWP: HWM stack usage: ");
846 printf("%d\n", Stack_Used(pid->stack, pid->stacksize));
847 }
848 printf("***LWP: Current Stack Pointer: 0x%x\n", pid->context.topstack);
849 if (pid->eventcnt > 0) {
850 printf("***LWP: Number of events outstanding: %d\n", pid->waitcnt);
851 printf("***LWP: Event id list:");
852 for (i = 0; i < pid->eventcnt; i++)
853 printf(" 0x%x", pid->eventlist[i]);
854 putchar('\n')(!__isthreaded ? __sputc('\n', __stdoutp) : (putc)('\n', __stdoutp
))
;
855 }
856 if (pid->wakevent > 0)
857 printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent);
858 return 0;
859}
860#endif
861
862static int
863purge_dead_pcbs(void)
864{
865 for_all_elts(cur, blocked, {{ PROCESS cur, _NEXT_; int _I_; for (_I_=blocked.count, cur =
blocked.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { if (cur->status == 4) Dispose_of_Dead_PCB(cur);} }
}
866 if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur);}{ PROCESS cur, _NEXT_; int _I_; for (_I_=blocked.count, cur =
blocked.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { if (cur->status == 4) Dispose_of_Dead_PCB(cur);} }
}
867 ){ PROCESS cur, _NEXT_; int _I_; for (_I_=blocked.count, cur =
blocked.head; _I_>0; _I_--, cur=_NEXT_) { _NEXT_ = cur ->
next; { if (cur->status == 4) Dispose_of_Dead_PCB(cur);} }
}
868 return 0;
869}
870
871int LWP_TraceProcesses = 0;
872
873static void
874Dispatcher(void)
875{ /* Lightweight process dispatcher */
876 int i;
877#ifdef DEBUG
878 static int dispatch_count = 0;
879
880 if (LWP_TraceProcesses > 0) {
881 for (i = 0; i < MAX_PRIORITIES(4 +1); i++) {
882 printf("[Priority %d, runnable (%d):", i, runnable[i].count);
883 for_all_elts(p, runnable[i], {{ PROCESS p, _NEXT_; int _I_; for (_I_=runnable[i].count, p =
runnable[i].head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p ->
next; { printf(" \"%s\"", p->name); } } }
884 printf(" \"%s\"", p->name);{ PROCESS p, _NEXT_; int _I_; for (_I_=runnable[i].count, p =
runnable[i].head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p ->
next; { printf(" \"%s\"", p->name); } } }
885 }{ PROCESS p, _NEXT_; int _I_; for (_I_=runnable[i].count, p =
runnable[i].head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p ->
next; { printf(" \"%s\"", p->name); } } }
886 ){ PROCESS p, _NEXT_; int _I_; for (_I_=runnable[i].count, p =
runnable[i].head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p ->
next; { printf(" \"%s\"", p->name); } } }
887 puts("]");
888 }
889 printf("[Blocked (%d):", blocked.count);
890 for_all_elts(p, blocked, {{ PROCESS p, _NEXT_; int _I_; for (_I_=blocked.count, p = blocked
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
891 printf(" \"%s\"", p->name);{ PROCESS p, _NEXT_; int _I_; for (_I_=blocked.count, p = blocked
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
892 }{ PROCESS p, _NEXT_; int _I_; for (_I_=blocked.count, p = blocked
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
893 ){ PROCESS p, _NEXT_; int _I_; for (_I_=blocked.count, p = blocked
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
894 puts("]");
895 printf("[Qwaiting (%d):", qwaiting.count);
896 for_all_elts(p, qwaiting, {{ PROCESS p, _NEXT_; int _I_; for (_I_=qwaiting.count, p = qwaiting
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
897 printf(" \"%s\"", p->name);{ PROCESS p, _NEXT_; int _I_; for (_I_=qwaiting.count, p = qwaiting
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
898 }{ PROCESS p, _NEXT_; int _I_; for (_I_=qwaiting.count, p = qwaiting
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
899 ){ PROCESS p, _NEXT_; int _I_; for (_I_=qwaiting.count, p = qwaiting
.head; _I_>0; _I_--, p=_NEXT_) { _NEXT_ = p -> next; { printf
(" \"%s\"", p->name); } } }
900 puts("]");
901 }
902#endif
903
904 /* Check for stack overflowif this lwp has a stack. Check for
905 * the guard word at the front of the stack being damaged and
906 * for the stack pointer being below the front of the stack.
907 * WARNING! This code assumes that stacks grow downward. */
908#if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
909 /* Fix this (stackcheck at other end of stack?) */
910 if (lwp_cpptr != NULL((void *)0) && lwp_cpptr->stack != NULL((void *)0)
911 && (lwp_cpptr->stackcheck !=
912 *(afs_int32 *) ((lwp_cpptr->stack) + lwp_cpptr->stacksize - 4)
913 || lwp_cpptr->context.topstack >
914 lwp_cpptr->stack + lwp_cpptr->stacksize - 4)) {
915#else
916 if (lwp_cpptr && lwp_cpptr->stack
917 && (lwp_cpptr->stackcheck != *(int *)(lwp_cpptr->stack)
918 || lwp_cpptr->context.topstack < lwp_cpptr->stack
919 || lwp_cpptr->context.topstack >
920 (lwp_cpptr->stack + lwp_cpptr->stacksize))) {
921#endif
922 printf("stackcheck = %u: stack = %u \n", lwp_cpptr->stackcheck,
923 *(int *)lwp_cpptr->stack);
924 printf("topstack = 0x%" AFS_PTR_FMT"p" ": stackptr = 0x%" AFS_PTR_FMT"p" ": stacksize = 0x%x\n",
925 (void *)(uintptr_t)lwp_cpptr->context.topstack,
926 (void *)(uintptr_t)lwp_cpptr->stack,
927 lwp_cpptr->stacksize);
928
929 switch (lwp_overflowAction) {
930 case LWP_SOQUIET1:
931 break;
932 case LWP_SOABORT2:
933 Overflow_Complain();
934 abort();
935 case LWP_SOMESSAGE3:
936 default:
937 Overflow_Complain();
938 lwp_overflowAction = LWP_SOQUIET1;
939 break;
940 }
941 }
942
943 /* Move head of current runnable queue forward if current LWP is still in it. */
944 if (lwp_cpptr != NULL((void *)0) && lwp_cpptr == runnable[lwp_cpptr->priority].head)
945 runnable[lwp_cpptr->priority].head =
946 runnable[lwp_cpptr->priority].head->next;
947 /* Find highest priority with runnable processes. */
948 for (i = MAX_PRIORITIES(4 +1) - 1; i >= 0; i--)
949 if (runnable[i].head != NULL((void *)0))
950 break;
951
952 if (i < 0)
953 Abort_LWP("No READY processes");
954
955#ifdef DEBUG
956 if (LWP_TraceProcesses > 0)
957 printf("Dispatch %d [PCB at 0x%x] \"%s\"\n", ++dispatch_count,
958 runnable[i].head, runnable[i].head->name);
959#endif
960#if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
961 if (PRE_Block != 1)
962 Abort_LWP("PRE_Block not 1");
963#endif
964 lwp_cpptr = runnable[i].head;
965
966 returnto(&lwp_cpptr->context);
967
968 return; /* not reachable */
969}
970
971/* Complain of a stack overflow to stderr without using stdio. */
972static void
973Overflow_Complain(void)
974{
975 time_t currenttime;
976 char *timeStamp;
977 char *msg1 = " LWP: stack overflow in process ";
978 char *msg2 = "!\n";
979
980 currenttime = time(0);
981 timeStamp = ctime(&currenttime);
982 timeStamp[24] = 0;
983 write(2, timeStamp, strlen(timeStamp));
984
985 write(2, msg1, strlen(msg1));
986 write(2, lwp_cpptr->name, strlen(lwp_cpptr->name));
987 write(2, msg2, strlen(msg2));
988}
989
990static void
991Dispose_of_Dead_PCB(PROCESS cur)
992{
993 Debug(4, ("Entered Dispose_of_Dead_PCB"))do { ; } while (0);
994 Delete_PCB(cur);
995 Free_PCB(cur);
996/*
997 Internal_Signal(cur);
998*/
999}
1000
1001static void
1002Exit_LWP(void)
1003{
1004 abort();
1005}
1006
1007static void
1008Free_PCB(PROCESS pid)
1009{
1010 Debug(4, ("Entered Free_PCB"))do { ; } while (0);
1011 if (pid->stack != NULL((void *)0)) {
1012 Debug(0,do { ; } while (0)
1013 ("HWM stack usage: %d, [PCB at 0x%x]",do { ; } while (0)
1014 Stack_Used(pid->stack, pid->stacksize), pid))do { ; } while (0);
1015#ifndef AFS_AIX32_ENV
1016 free(pid->stack);
1017#endif
1018 }
1019 if (pid->eventlist != NULL((void *)0))
1020 free(pid->eventlist);
1021 free(pid);
1022}
1023
1024static void
1025Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
1026 void *(*ep) (void *), void *parm, char *name)
1027{
1028 int i = 0;
1029
1030 Debug(4, ("Entered Initialize_PCB"))do { ; } while (0);
1031 if (name != NULL((void *)0))
1032 while (((temp->name[i] = name[i]) != '\0') && (i < 31))
1033 i++;
1034 temp->name[31] = '\0';
1035 temp->status = READY2;
1036 temp->eventlist = (void **)malloc(EVINITSIZE5 * sizeof(void *));
1037 temp->eventlistsize = EVINITSIZE5;
1038 temp->eventcnt = 0;
1039 temp->wakevent = 0;
1040 temp->waitcnt = 0;
1041 temp->blockflag = 0;
1042 temp->iomgrRequest = 0;
1043 temp->priority = priority;
1044 temp->index = lwp_nextindex++;
1045 temp->stack = stack;
1046 temp->stacksize = stacksize;
1047#if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1048 if (temp->stack != NULL((void *)0))
1049 temp->stackcheck = *(int *)((temp->stack) + stacksize - 4);
1050#else
1051 if (temp->stack != NULL((void *)0))
1052 temp->stackcheck = *(int *)(temp->stack);
1053#endif
1054 temp->ep = ep;
1055 temp->parm = parm;
1056 temp->misc = NULL((void *)0); /* currently unused */
1057 temp->next = NULL((void *)0);
1058 temp->prev = NULL((void *)0);
1059 temp->lwp_rused = 0;
1060 temp->level = 1; /* non-preemptable */
1061}
1062
1063static int
1064Internal_Signal(void *event)
1065{
1066 int rc = LWP_ENOWAIT-8;
1067 int i;
1068
1069 Debug(0, ("Entered Internal_Signal [event id 0x%x]", event))do { ; } while (0);
1070 if (!lwp_init)
1071 return LWP_EINIT-3;
1072 if (event == NULL((void *)0))
1073 return LWP_EBADEVENT-10;
1074 for_all_elts(temp, blocked, {{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1075 if (temp->status == WAITING){ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1076 for (i = 0; i < temp->eventcnt; i++) {{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1077 if (temp->eventlist[i] == event) {{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1078 temp->eventlist[i] = NULL; rc = LWP_SUCCESS;{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1079 Debug(0, ("Signal satisfied for PCB 0x%x", temp));{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1080 if (--temp->waitcnt == 0) {{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1081 temp->status = READY; temp->wakevent = i + 1;{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1082 move(temp, &blocked, &runnable[temp->priority]); break;}{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1083 }{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1084 }{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1085 }{ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1086 ){ PROCESS temp, _NEXT_; int _I_; for (_I_=blocked.count, temp
= blocked.head; _I_>0; _I_--, temp=_NEXT_) { _NEXT_ = temp
-> next; { if (temp->status == 3) for (i = 0; i < temp
->eventcnt; i++) { if (temp->eventlist[i] == event) { temp
->eventlist[i] = ((void *)0); rc = 0; do { ; } while (0); if
(--temp->waitcnt == 0) { temp->status = 2; temp->wakevent
= i + 1; move(temp, &blocked, &runnable[temp->priority
]); break;} } } } } }
1087 return rc;
1088}
1089
1090/* This can be any unlikely pattern except 0x00010203 or the reverse. */
1091#define STACKMAGIC0xBADBADBA 0xBADBADBA
1092static afs_int32
1093Initialize_Stack(char *stackptr, int stacksize)
1094{
1095 int i;
1096
1097 Debug(4, ("Entered Initialize_Stack"))do { ; } while (0);
1098 if (lwp_stackUseEnabled)
1099 for (i = 0; i < stacksize; i++)
1100 stackptr[i] = i & 0xff;
1101 else
1102#if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1103 *(afs_int32 *) (stackptr + stacksize - 4) = STACKMAGIC0xBADBADBA;
1104#else
1105 *(afs_int32 *) stackptr = STACKMAGIC0xBADBADBA;
1106#endif
1107 return 0;
1108}
1109
1110static int
1111Stack_Used(char *stackptr, int stacksize)
1112{
1113 int i;
1114
1115#if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1116 if (*(afs_int32 *) (stackptr + stacksize - 4) == STACKMAGIC0xBADBADBA)
1117 return 0;
1118 else {
1119 for (i = stacksize - 1; i >= 0; i--)
1120 if ((unsigned char)stackptr[i] != (i & 0xff))
1121 return (i);
1122 return 0;
1123 }
1124#else
1125 if (*(afs_int32 *) stackptr == STACKMAGIC0xBADBADBA)
1126 return 0;
1127 else {
1128 for (i = 0; i < stacksize; i++)
1129 if ((unsigned char)stackptr[i] != (i & 0xff))
1130 return (stacksize - i);
1131 return 0;
1132 }
1133#endif
1134}
1135
1136
1137int
1138LWP_NewRock(int Tag, char *Value)
1139 /* Finds a free rock and sets its value to Value.
1140 * Return codes:
1141 * LWP_SUCCESS Rock did not exist and a new one was used
1142 * LWP_EBADROCK Rock already exists.
1143 * LWP_ENOROCKS All rocks are in use.
1144 *
1145 * From the above semantics, you can only set a rock value once. This is specifically
1146 * to prevent multiple users of the LWP package from accidentally using the same Tag
1147 * value and clobbering others. You can always use one level of indirection to obtain
1148 * a rock whose contents can change.
1149 */
1150{
1151 int i;
1152 struct rock *ra; /* rock array */
1153
1154 ra = lwp_cpptr->lwp_rlist;
1155
1156 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1157 if (ra[i].tag == Tag)
1158 return (LWP_EBADROCK-16);
1159
1160 if (lwp_cpptr->lwp_rused < MAXROCKS4) {
1161 ra[lwp_cpptr->lwp_rused].tag = Tag;
1162 ra[lwp_cpptr->lwp_rused].value = Value;
1163 lwp_cpptr->lwp_rused++;
1164 return (LWP_SUCCESS0);
1165 } else
1166 return (LWP_ENOROCKS-15);
1167}
1168
1169
1170int
1171LWP_GetRock(int Tag, char **Value)
1172 /* Obtains the pointer Value associated with the rock Tag of this LWP.
1173 * Returns:
1174 * LWP_SUCCESS if specified rock exists and Value has been filled
1175 * LWP_EBADROCK rock specified does not exist
1176 */
1177{
1178 int i;
1179 struct rock *ra;
1180
1181 ra = lwp_cpptr->lwp_rlist;
1182
1183 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1184 if (ra[i].tag == Tag) {
1185 *Value = ra[i].value;
1186 return (LWP_SUCCESS0);
1187 }
1188 return (LWP_EBADROCK-16);
1189}
1190
1191
1192#ifdef AFS_AIX32_ENV
1193int
1194setlim(int limcon, uchar_t hard, int limit)
1195{
1196 struct rlimit rlim;
1197
1198 (void)getrlimit(limcon, &rlim);
1199
1200 limit = limit * 1024;
1201 if (hard)
1202 rlim.rlim_max = limit;
1203 else if (limit == RLIM_INFINITY && geteuid() != 0)
1204 rlim.rlim_cur = rlim.rlim_max;
1205 else
1206 rlim.rlim_cur = limit;
1207
1208 /* Must use ulimit() due to Posix constraints */
1209 if (limcon == RLIMIT_FSIZE) {
1210 if (ulimit
1211 (UL_SETFSIZE,
1212 ((hard ? rlim.rlim_max : rlim.rlim_cur) / 512)) < 0) {
1213 printf("Can't %s%s limit\n",
1214 limit == RLIM_INFINITY ? "remove" : "set",
1215 hard ? " hard" : "");
1216 return (-1);
1217 }
1218 } else {
1219 if (setrlimit(limcon, &rlim) < 0) {
1220 perror("");
1221 printf("Can't %s%s limit\n",
1222 limit == RLIM_INFINITY ? "remove" : "set",
1223 hard ? " hard" : "");
1224 return (-1);
1225 }
1226 }
1227 return (0);
1228}
1229#endif
1230
1231#ifdef AFS_SUN5_ENV
1232int
1233LWP_NoYieldSignal(void *event)
1234{
1235 return (LWP_INTERNALSIGNAL(event, 0));
1236}
1237
1238int
1239LWP_SignalProcess(void *event)
1240{
1241 return (LWP_INTERNALSIGNAL(event, 1));
1242}
1243
1244#endif