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 *
15 \*******************************************************************/
17 #include <afsconfig.h>
18 #include <afs/param.h>
22 /* allocate externs here */
28 #include <sys/errno.h>
33 int setlim(int limcon, uchar_t hard, int limit);
36 #ifndef AFS_ARM_LINUX20_ENV
37 #if defined(AFS_S390_LINUX20_ENV)
38 int PRE_Block; /* Remnants of preemption support. */
40 char PRE_Block; /* Remnants of preemption support. */
52 #define MAXINT (~(1<<((sizeof(int)*8)-1)))
55 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
66 #elif defined(AFS_DARWIN_ENV)
67 #define STACK_ALIGN 16
76 #define Debug(level, msg) do { \
77 if (lwp_debug && lwp_debug >= level) { \
78 printf("***LWP (0x%x): ", lwp_cpptr); \
84 #define Debug(level, msg) do { \
89 static void Dispatcher(void);
90 static void Create_Process_Part2(void);
91 static void Exit_LWP(void);
92 static afs_int32 Initialize_Stack(char *stackptr, int stacksize);
93 static int Stack_Used(char *stackptr, int stacksize);
95 static void Abort_LWP(char *msg);
96 static void Overflow_Complain(void);
97 static void Initialize_PCB(PROCESS temp, int priority, char *stack,
98 int stacksize, void *(*ep)(void *), void *parm,
100 static void Dispose_of_Dead_PCB(PROCESS cur);
101 static void Free_PCB(PROCESS pid);
102 static int Internal_Signal(void *event);
103 static int purge_dead_pcbs(void);
104 static int LWP_MwaitProcess(int wcount, void *evlist[]);
107 #define MAX_PRIORITIES (LWP_MAX_PRIORITY+1)
112 } runnable[MAX_PRIORITIES], 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. */
117 /* Offset of stack field within pcb -- used by stack checking stuff */
120 /* special user-tweakable option for AIX */
121 int lwp_MaxStackSize = 32768;
123 /* biggest LWP stack created so far */
124 int lwp_MaxStackSeen = 0;
126 /* Stack checking action */
127 int lwp_overflowAction = LWP_SOABORT;
129 /* Controls stack size counting. */
130 int lwp_stackUseEnabled = TRUE; /* pay the price */
134 /* Minimum stack size */
135 int lwp_MinStackSize = 0;
138 lwp_remove(PROCESS p, struct QUEUE *q)
140 /* Special test for only element on queue */
144 /* Not only element, do normal remove */
145 p->next->prev = p->prev;
146 p->prev->next = p->next;
148 /* See if head pointing to this element */
152 p->next = p->prev = NULL;
157 insert(PROCESS p, struct QUEUE *q)
159 if (q->head == NULL) { /* Queue is empty */
161 p->next = p->prev = p;
162 } else { /* Regular insert */
163 p->prev = q->head->prev;
164 q->head->prev->next = p;
173 move(PROCESS p, struct QUEUE *from, struct QUEUE *to)
183 #define for_all_elts(var, q, body)\
185 PROCESS var, _NEXT_;\
187 for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\
188 _NEXT_ = var -> next;\
194 /*****************************************************************************\
196 * Following section documents the Assembler interfaces used by LWP code *
198 \*****************************************************************************/
201 savecontext(int (*ep)(), struct lwp_context *savearea, char *sp);
203 Stub for Assembler routine that will
204 save the current SP value in the passed
205 context savearea and call the function
206 whose entry point is in ep. If the sp
207 parameter is NULL, the current stack is
208 used, otherwise sp becomes the new stack
211 returnto(struct lwp_context *savearea);
213 Stub for Assembler routine that will
214 restore context from a passed savearea
215 and return to the restored C frame.
219 /* Macro to force a re-schedule. Strange name is historical */
220 #define Set_LWP_RC() savecontext(Dispatcher, &lwp_cpptr->context, NULL)
222 static struct lwp_ctl *lwp_init = 0;
228 (tp = lwp_cpptr)->status = QWAITING;
229 move(tp, &runnable[tp->priority], &qwaiting);
235 LWP_QSignal(PROCESS pid)
237 if (pid->status == QWAITING) {
239 move(pid, &qwaiting, &runnable[pid->priority]);
247 reserveFromStack(afs_int32 size)
256 LWP_CreateProcess(void *(*ep) (void *), int stacksize, int priority, void *parm,
257 char *name, PROCESS * pid)
261 static char *stackptr = 0;
267 #if defined(AFS_LWP_MINSTACKSIZE)
269 * on some systems (e.g. hpux), a minimum usable stack size has
272 if (stacksize < lwp_MinStackSize) {
273 stacksize = lwp_MinStackSize;
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;
280 Debug(0, ("Entered LWP_CreateProcess"));
281 /* Throw away all dead process control blocks */
284 temp = malloc(sizeof(struct lwp_pcb));
289 if (stacksize < MINSTACK)
290 #ifdef AFS_DARWIN_ENV
292 #else /* !AFS_DARWIN_ENV */
294 #endif /* !AFS_DARWIN_ENV */
297 STACK_ALIGN * ((stacksize + STACK_ALIGN - 1) / STACK_ALIGN);
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.
306 * We also do it here in case the main program forgets to do it.
308 struct sigaction nsa;
309 extern uid_t geteuid();
311 sigemptyset(&nsa.sa_mask);
312 nsa.sa_handler = SIG_DFL;
313 nsa.sa_flags = SA_FULLDUMP;
314 sigaction(SIGABRT, &nsa, NULL);
315 sigaction(SIGSEGV, &nsa, NULL);
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.
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 */
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.
334 stackptr = reserveFromStack(lwp_MaxStackSize);
336 stackptr -= stacksize;
337 stackmemory = stackptr;
339 #ifdef AFS_DARWIN_ENV
340 if ((stackmemory = malloc(stacksize + STACK_ALIGN - 1)) == NULL)
341 #else /* !AFS_DARWIN_ENV */
342 if ((stackmemory = malloc(stacksize + 7)) == NULL)
343 #endif /* !AFS_DARWIN_ENV */
349 /* Round stack pointer to byte boundary */
350 #ifdef AFS_DARWIN_ENV
351 stackptr = (char *)(STACK_ALIGN * (((long)stackmemory + STACK_ALIGN - 1) / STACK_ALIGN));
352 #else /* !AFS_DARWIN_ENV */
353 stackptr = (char *)(8 * (((long)stackmemory + 7) / 8));
354 #endif /* !AFS_DARWIN_ENV */
356 if (priority < 0 || priority >= MAX_PRIORITIES) {
358 #ifndef AFS_AIX32_ENV
364 Initialize_Stack(stackptr, stacksize);
365 Initialize_PCB(temp, priority, stackmemory, stacksize, ep, parm, name);
366 insert(temp, &runnable[priority]);
368 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
370 Abort_LWP("PRE_Block not 0");
372 /* Gross hack: beware! */
376 #if defined(AFS_PARISC_LINUX24_ENV)
377 savecontext(Create_Process_Part2, &temp2->context,
378 stackptr + MINFRAME);
381 savecontext(Create_Process_Part2, &temp2->context,
382 stackptr + MINFRAME);
384 #if defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
385 #ifdef sys_x86_darwin_80
386 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16 - sizeof(void *)); /* 16 = 2 * jmp_buf_type */
387 #else /* !sys_x86_darwin_80 */
388 /* Need to have the sp on an 8-byte boundary for storing doubles. */
389 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16); /* 16 = 2 * jmp_buf_type */
390 #endif /* !sys_x86_darwin_80 */
392 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
393 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 0x40); /* lomgjmp does something
396 #if defined(AFS_S390_LINUX20_ENV)
397 savecontext(Create_Process_Part2, &temp2->context,
398 stackptr + stacksize - MINFRAME);
399 #else /* !AFS_S390_LINUX20_ENV */
400 savecontext(Create_Process_Part2, &temp2->context,
401 stackptr + stacksize - sizeof(void *));
402 #endif /* AFS_S390_LINUX20_ENV */
403 #endif /* AFS_SPARC64_LINUX20_ENV || AFS_SPARC_LINUX20_ENV */
404 #endif /* AFS_SGI62_ENV */
407 /* End of gross hack */
419 LWP_CreateProcess2(void *(*ep) (void *), int stacksize, int priority, void *parm,
420 char *name, PROCESS * pid)
425 #if defined(AFS_LWP_MINSTACKSIZE)
427 * on some systems (e.g. hpux), a minimum usable stack size has
430 if (stacksize < lwp_MinStackSize) {
431 stacksize = lwp_MinStackSize;
433 #endif /* defined(AFS_LWP_MINSTACKSIZE) */
434 /* more stack size computations; keep track of for IOMGR */
435 if (lwp_MaxStackSeen < stacksize)
436 lwp_MaxStackSeen = stacksize;
438 Debug(0, ("Entered LWP_CreateProcess"));
439 /* Throw away all dead process control blocks */
442 temp = malloc(sizeof(struct lwp_pcb));
447 if (stacksize < MINSTACK)
451 STACK_ALIGN * ((stacksize + STACK_ALIGN - 1) / STACK_ALIGN);
452 if ((stackptr = malloc(stacksize)) == NULL) {
456 if (priority < 0 || priority >= MAX_PRIORITIES) {
460 Initialize_Stack(stackptr, stacksize);
461 Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
462 insert(temp, &runnable[priority]);
464 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
466 Abort_LWP("PRE_Block not 0");
468 /* Gross hack: beware! */
472 savecontext(Create_Process_Part2, &temp2->context,
473 stackptr + stacksize - sizeof(void *));
474 /* End of gross hack */
486 LWP_CurrentProcess(PROCESS * pid)
487 { /* returns pid of current process */
488 Debug(0, ("Entered Current_Process"));
499 Debug(0, ("Entered ThreadId"));
506 #define LWPANCHOR (*lwp_init)
509 LWP_DestroyProcess(PROCESS pid)
510 { /* destroy a lightweight process */
513 Debug(0, ("Entered Destroy_Process"));
515 if (lwp_cpptr != pid) {
516 Dispose_of_Dead_PCB(pid);
519 pid->status = DESTROYED;
520 move(pid, &runnable[pid->priority], &blocked);
522 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
523 savecontext(Dispatcher, &(temp->context),
524 &(LWPANCHOR.dsptchstack[MINFRAME]));
525 #elif defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
526 savecontext(Dispatcher, &(temp->context),
528 dsptchstack[(sizeof LWPANCHOR.dsptchstack) - 8]));
529 #elif defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
530 savecontext(Dispatcher, &(temp->context),
532 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
534 #elif defined(AFS_S390_LINUX20_ENV)
535 savecontext(Dispatcher, &(temp->context),
537 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
540 savecontext(Dispatcher, &(temp->context),
542 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
552 LWP_DispatchProcess(void)
553 { /* explicit voluntary preemption */
554 Debug(2, ("Entered Dispatch_Process"));
568 for (i = 0; i < MAX_PRIORITIES; i++)
569 for_all_elts(x, runnable[i], {
570 printf("[Priority %d]\n", i);
574 for_all_elts(x, blocked, {
575 Dump_One_Process(x);}
577 for_all_elts(x, qwaiting, {
578 Dump_One_Process(x);}
581 printf("***LWP: LWP support not initialized\n");
587 LWP_GetProcessPriority(PROCESS pid, int *priority)
588 { /* returns process priority */
589 Debug(0, ("Entered Get_Process_Priority"));
591 *priority = pid->priority;
598 LWP_InitializeProcessSupport(int priority, PROCESS * pid)
601 struct lwp_pcb dummy;
605 Debug(0, ("Entered LWP_InitializeProcessSupport"));
606 if (lwp_init != NULL)
609 /* Set up offset for stack checking -- do this as soon as possible */
610 stack_offset = (char *)&dummy.stack - (char *)&dummy;
612 if (priority >= MAX_PRIORITIES)
614 for (i = 0; i < MAX_PRIORITIES; i++) {
615 runnable[i].head = NULL;
616 runnable[i].count = 0;
620 qwaiting.head = NULL;
622 lwp_init = malloc(sizeof(struct lwp_ctl));
623 temp = malloc(sizeof(struct lwp_pcb));
624 if (lwp_init == NULL || temp == NULL)
625 Abort_LWP("Insufficient Storage to Initialize LWP Support");
626 LWPANCHOR.processcnt = 1;
627 LWPANCHOR.outerpid = temp;
628 LWPANCHOR.outersp = NULL;
629 Initialize_PCB(temp, priority, NULL, 0, NULL, NULL,
630 "Main Process [created by LWP]");
631 insert(temp, &runnable[priority]);
632 savecontext(Dispatcher, &temp->context, NULL);
633 LWPANCHOR.outersp = temp->context.topstack;
638 /* get minimum stack size from the environment. this allows the administrator
639 * to change the lwp stack dynamically without getting a new binary version.
641 if ((value = getenv("AFS_LWP_STACK_SIZE")) == NULL)
642 lwp_MinStackSize = AFS_LWP_MINSTACKSIZE;
645 (AFS_LWP_MINSTACKSIZE >
646 atoi(value) ? AFS_LWP_MINSTACKSIZE : atoi(value));
652 LWP_INTERNALSIGNAL(void *event, int yield)
653 { /* signal the occurence of an event */
654 Debug(2, ("Entered LWP_SignalProcess"));
657 rc = Internal_Signal(event);
666 LWP_TerminateProcessSupport(void)
667 { /* terminate all LWP support */
670 Debug(0, ("Entered Terminate_Process_Support"));
671 if (lwp_init == NULL)
673 if (lwp_cpptr != LWPANCHOR.outerpid)
674 Abort_LWP("Terminate_Process_Support invoked from wrong process!");
675 for (i = 0; i < MAX_PRIORITIES; i++)
676 for_all_elts(cur, runnable[i], {
679 for_all_elts(cur, blocked, {
682 for_all_elts(cur, qwaiting, {
691 LWP_WaitProcess(void *event)
692 { /* wait on a single event */
695 Debug(2, ("Entered Wait_Process"));
697 return LWP_EBADEVENT;
700 return LWP_MwaitProcess(1, tempev);
704 LWP_MwaitProcess(int wcount, void *evlist[])
705 { /* wait on m of n events */
709 Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount));
711 if (evlist == NULL) {
713 return LWP_EBADCOUNT;
716 for (ecount = 0; evlist[ecount] != NULL; ecount++);
720 return LWP_EBADCOUNT;
725 if (wcount > ecount || wcount < 0) {
727 return LWP_EBADCOUNT;
729 if (ecount > lwp_cpptr->eventlistsize) {
731 lwp_cpptr->eventlist = realloc(lwp_cpptr->eventlist,
732 ecount * sizeof(void *));
733 lwp_cpptr->eventlistsize = ecount;
735 for (i = 0; i < ecount; i++)
736 lwp_cpptr->eventlist[i] = evlist[i];
738 lwp_cpptr->status = WAITING;
740 move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked);
743 lwp_cpptr->wakevent = 0;
744 lwp_cpptr->waitcnt = wcount;
745 lwp_cpptr->eventcnt = ecount;
756 LWP_StackUsed(PROCESS pid, int *maxa, int *used)
758 *maxa = pid->stacksize;
759 *used = Stack_Used(pid->stack, *maxa);
766 * The following functions are strictly
767 * INTERNAL to the LWP support package.
773 struct lwp_context tempcontext;
775 Debug(0, ("Entered Abort_LWP"));
776 printf("***LWP: %s\n", msg);
777 printf("***LWP: Abort --- dumping PCBs ...\n");
781 if (LWPANCHOR.outersp == NULL)
784 savecontext(Exit_LWP, &tempcontext, LWPANCHOR.outersp);
789 Create_Process_Part2(void)
790 { /* creates a context for the new process */
793 Debug(2, ("Entered Create_Process_Part2"));
794 temp = lwp_cpptr; /* Get current process id */
795 savecontext(Dispatcher, &temp->context, NULL);
796 (*temp->ep) (temp->parm);
797 LWP_DestroyProcess(temp);
802 Delete_PCB(PROCESS pid)
803 { /* remove a PCB from the process list */
804 Debug(4, ("Entered Delete_PCB"));
806 (pid->blockflag || pid->status == WAITING
808 DESTROYED ? &blocked :
809 (pid->status == QWAITING) ? &qwaiting :
810 &runnable[pid->priority]));
811 LWPANCHOR.processcnt--;
817 Dump_One_Process(PROCESS pid)
821 printf("***LWP: Process Control Block at 0x%x\n", pid);
822 printf("***LWP: Name: %s\n", pid->name);
824 printf("***LWP: Initial entry point: 0x%x\n", pid->ep);
826 printf("BLOCKED and ");
827 switch (pid->status) {
844 printf("***LWP: Priority: %d \tInitial parameter: 0x%x\n", pid->priority,
846 if (pid->stacksize != 0) {
847 printf("***LWP: Stacksize: %d \tStack base address: 0x%x\n",
848 pid->stacksize, pid->stack);
849 printf("***LWP: HWM stack usage: ");
850 printf("%d\n", Stack_Used(pid->stack, pid->stacksize));
852 printf("***LWP: Current Stack Pointer: 0x%x\n", pid->context.topstack);
853 if (pid->eventcnt > 0) {
854 printf("***LWP: Number of events outstanding: %d\n", pid->waitcnt);
855 printf("***LWP: Event id list:");
856 for (i = 0; i < pid->eventcnt; i++)
857 printf(" 0x%x", pid->eventlist[i]);
860 if (pid->wakevent > 0)
861 printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent);
867 purge_dead_pcbs(void)
869 for_all_elts(cur, blocked, {
870 if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur);}
875 int LWP_TraceProcesses = 0;
879 { /* Lightweight process dispatcher */
882 static int dispatch_count = 0;
884 if (LWP_TraceProcesses > 0) {
885 for (i = 0; i < MAX_PRIORITIES; i++) {
886 printf("[Priority %d, runnable (%d):", i, runnable[i].count);
887 for_all_elts(p, runnable[i], {
888 printf(" \"%s\"", p->name);
893 printf("[Blocked (%d):", blocked.count);
894 for_all_elts(p, blocked, {
895 printf(" \"%s\"", p->name);
899 printf("[Qwaiting (%d):", qwaiting.count);
900 for_all_elts(p, qwaiting, {
901 printf(" \"%s\"", p->name);
908 /* Check for stack overflowif this lwp has a stack. Check for
909 * the guard word at the front of the stack being damaged and
910 * for the stack pointer being below the front of the stack.
911 * WARNING! This code assumes that stacks grow downward. */
912 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
913 /* Fix this (stackcheck at other end of stack?) */
914 if (lwp_cpptr != NULL && lwp_cpptr->stack != NULL
915 && (lwp_cpptr->stackcheck !=
916 *(afs_int32 *) ((lwp_cpptr->stack) + lwp_cpptr->stacksize - 4)
917 || lwp_cpptr->context.topstack >
918 lwp_cpptr->stack + lwp_cpptr->stacksize - 4)) {
920 if (lwp_cpptr && lwp_cpptr->stack
921 && (lwp_cpptr->stackcheck != *(int *)(lwp_cpptr->stack)
922 || lwp_cpptr->context.topstack < lwp_cpptr->stack
923 || lwp_cpptr->context.topstack >
924 (lwp_cpptr->stack + lwp_cpptr->stacksize))) {
926 printf("stackcheck = %u: stack = %u \n", lwp_cpptr->stackcheck,
927 *(int *)lwp_cpptr->stack);
928 printf("topstack = 0x%" AFS_PTR_FMT ": stackptr = 0x%" AFS_PTR_FMT ": stacksize = 0x%x\n",
929 (void *)(uintptr_t)lwp_cpptr->context.topstack,
930 (void *)(uintptr_t)lwp_cpptr->stack,
931 lwp_cpptr->stacksize);
933 switch (lwp_overflowAction) {
942 lwp_overflowAction = LWP_SOQUIET;
947 /* Move head of current runnable queue forward if current LWP is still in it. */
948 if (lwp_cpptr != NULL && lwp_cpptr == runnable[lwp_cpptr->priority].head)
949 runnable[lwp_cpptr->priority].head =
950 runnable[lwp_cpptr->priority].head->next;
951 /* Find highest priority with runnable processes. */
952 for (i = MAX_PRIORITIES - 1; i >= 0; i--)
953 if (runnable[i].head != NULL)
957 Abort_LWP("No READY processes");
960 if (LWP_TraceProcesses > 0)
961 printf("Dispatch %d [PCB at 0x%x] \"%s\"\n", ++dispatch_count,
962 runnable[i].head, runnable[i].head->name);
964 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
966 Abort_LWP("PRE_Block not 1");
968 lwp_cpptr = runnable[i].head;
970 returnto(&lwp_cpptr->context);
972 return; /* not reachable */
975 /* Complain of a stack overflow to stderr without using stdio. */
977 Overflow_Complain(void)
981 char *msg1 = " LWP: stack overflow in process ";
984 currenttime = time(0);
985 timeStamp = ctime(¤ttime);
987 if (write(2, timeStamp, strlen(timeStamp)) < 0)
990 if (write(2, msg1, strlen(msg1)) < 0)
992 if (write(2, lwp_cpptr->name, strlen(lwp_cpptr->name)) < 0)
994 if (write(2, msg2, strlen(msg2)) < 0)
999 Dispose_of_Dead_PCB(PROCESS cur)
1001 Debug(4, ("Entered Dispose_of_Dead_PCB"));
1005 Internal_Signal(cur);
1016 Free_PCB(PROCESS pid)
1018 Debug(4, ("Entered Free_PCB"));
1019 if (pid->stack != NULL) {
1021 ("HWM stack usage: %d, [PCB at 0x%x]",
1022 Stack_Used(pid->stack, pid->stacksize), pid));
1023 #ifndef AFS_AIX32_ENV
1027 if (pid->eventlist != NULL)
1028 free(pid->eventlist);
1033 Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
1034 void *(*ep) (void *), void *parm, char *name)
1038 Debug(4, ("Entered Initialize_PCB"));
1040 while (((temp->name[i] = name[i]) != '\0') && (i < 31))
1042 temp->name[31] = '\0';
1043 temp->status = READY;
1044 temp->eventlist = malloc(EVINITSIZE * sizeof(void *));
1045 temp->eventlistsize = EVINITSIZE;
1049 temp->blockflag = 0;
1050 temp->iomgrRequest = 0;
1051 temp->priority = priority;
1052 temp->index = lwp_nextindex++;
1053 temp->stack = stack;
1054 temp->stacksize = stacksize;
1055 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1056 if (temp->stack != NULL)
1057 temp->stackcheck = *(int *)((temp->stack) + stacksize - 4);
1059 if (temp->stack != NULL)
1060 temp->stackcheck = *(int *)(temp->stack);
1064 temp->misc = NULL; /* currently unused */
1067 temp->lwp_rused = 0;
1068 temp->level = 1; /* non-preemptable */
1072 Internal_Signal(void *event)
1074 int rc = LWP_ENOWAIT;
1077 Debug(0, ("Entered Internal_Signal [event id 0x%x]", event));
1081 return LWP_EBADEVENT;
1082 for_all_elts(temp, blocked, {
1083 if (temp->status == WAITING)
1084 for (i = 0; i < temp->eventcnt; i++) {
1085 if (temp->eventlist[i] == event) {
1086 temp->eventlist[i] = NULL; rc = LWP_SUCCESS;
1087 Debug(0, ("Signal satisfied for PCB 0x%x", temp));
1088 if (--temp->waitcnt == 0) {
1089 temp->status = READY; temp->wakevent = i + 1;
1090 move(temp, &blocked, &runnable[temp->priority]); break;}
1098 /* This can be any unlikely pattern except 0x00010203 or the reverse. */
1099 #define STACKMAGIC 0xBADBADBA
1101 Initialize_Stack(char *stackptr, int stacksize)
1105 Debug(4, ("Entered Initialize_Stack"));
1106 if (lwp_stackUseEnabled)
1107 for (i = 0; i < stacksize; i++)
1108 stackptr[i] = i & 0xff;
1110 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1111 *(afs_int32 *) (stackptr + stacksize - 4) = STACKMAGIC;
1113 *(afs_int32 *) stackptr = STACKMAGIC;
1119 Stack_Used(char *stackptr, int stacksize)
1123 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1124 if (*(afs_int32 *) (stackptr + stacksize - 4) == STACKMAGIC)
1127 for (i = stacksize - 1; i >= 0; i--)
1128 if ((unsigned char)stackptr[i] != (i & 0xff))
1133 if (*(afs_int32 *) stackptr == STACKMAGIC)
1136 for (i = 0; i < stacksize; i++)
1137 if ((unsigned char)stackptr[i] != (i & 0xff))
1138 return (stacksize - i);
1146 LWP_NewRock(int Tag, char *Value)
1147 /* Finds a free rock and sets its value to Value.
1149 * LWP_SUCCESS Rock did not exist and a new one was used
1150 * LWP_EBADROCK Rock already exists.
1151 * LWP_ENOROCKS All rocks are in use.
1153 * From the above semantics, you can only set a rock value once. This is specifically
1154 * to prevent multiple users of the LWP package from accidentally using the same Tag
1155 * value and clobbering others. You can always use one level of indirection to obtain
1156 * a rock whose contents can change.
1160 struct rock *ra; /* rock array */
1162 ra = lwp_cpptr->lwp_rlist;
1164 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1165 if (ra[i].tag == Tag)
1166 return (LWP_EBADROCK);
1168 if (lwp_cpptr->lwp_rused < MAXROCKS) {
1169 ra[lwp_cpptr->lwp_rused].tag = Tag;
1170 ra[lwp_cpptr->lwp_rused].value = Value;
1171 lwp_cpptr->lwp_rused++;
1172 return (LWP_SUCCESS);
1174 return (LWP_ENOROCKS);
1179 LWP_GetRock(int Tag, char **Value)
1180 /* Obtains the pointer Value associated with the rock Tag of this LWP.
1182 * LWP_SUCCESS if specified rock exists and Value has been filled
1183 * LWP_EBADROCK rock specified does not exist
1189 ra = lwp_cpptr->lwp_rlist;
1191 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1192 if (ra[i].tag == Tag) {
1193 *Value = ra[i].value;
1194 return (LWP_SUCCESS);
1196 return (LWP_EBADROCK);
1200 #ifdef AFS_AIX32_ENV
1202 setlim(int limcon, uchar_t hard, int limit)
1206 (void)getrlimit(limcon, &rlim);
1208 limit = limit * 1024;
1210 rlim.rlim_max = limit;
1211 else if (limit == RLIM_INFINITY && geteuid() != 0)
1212 rlim.rlim_cur = rlim.rlim_max;
1214 rlim.rlim_cur = limit;
1216 /* Must use ulimit() due to Posix constraints */
1217 if (limcon == RLIMIT_FSIZE) {
1220 ((hard ? rlim.rlim_max : rlim.rlim_cur) / 512)) < 0) {
1221 printf("Can't %s%s limit\n",
1222 limit == RLIM_INFINITY ? "remove" : "set",
1223 hard ? " hard" : "");
1227 if (setrlimit(limcon, &rlim) < 0) {
1229 printf("Can't %s%s limit\n",
1230 limit == RLIM_INFINITY ? "remove" : "set",
1231 hard ? " hard" : "");
1241 LWP_NoYieldSignal(void *event)
1243 return (LWP_INTERNALSIGNAL(event, 0));
1247 LWP_SignalProcess(void *event)
1249 return (LWP_INTERNALSIGNAL(event, 1));