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_OSF_ENV) || 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) {
362 Initialize_Stack(stackptr, stacksize);
363 Initialize_PCB(temp, priority, stackmemory, stacksize, ep, parm, name);
364 insert(temp, &runnable[priority]);
366 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
368 Abort_LWP("PRE_Block not 0");
370 /* Gross hack: beware! */
374 #if defined(AFS_PARISC_LINUX24_ENV)
375 savecontext(Create_Process_Part2, &temp2->context,
376 stackptr + MINFRAME);
379 savecontext(Create_Process_Part2, &temp2->context,
380 stackptr + MINFRAME);
382 #if defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
383 #ifdef sys_x86_darwin_80
384 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16 - sizeof(void *)); /* 16 = 2 * jmp_buf_type */
385 #else /* !sys_x86_darwin_80 */
386 /* Need to have the sp on an 8-byte boundary for storing doubles. */
387 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16); /* 16 = 2 * jmp_buf_type */
388 #endif /* !sys_x86_darwin_80 */
390 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
391 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 0x40); /* lomgjmp does something
394 #if defined(AFS_S390_LINUX20_ENV)
395 savecontext(Create_Process_Part2, &temp2->context,
396 stackptr + stacksize - MINFRAME);
397 #else /* !AFS_S390_LINUX20_ENV */
398 savecontext(Create_Process_Part2, &temp2->context,
399 stackptr + stacksize - sizeof(void *));
400 #endif /* AFS_S390_LINUX20_ENV */
401 #endif /* AFS_SPARC64_LINUX20_ENV || AFS_SPARC_LINUX20_ENV */
402 #endif /* AFS_SGI62_ENV */
405 /* End of gross hack */
417 LWP_CreateProcess2(void *(*ep) (void *), int stacksize, int priority, void *parm,
418 char *name, PROCESS * pid)
423 #if defined(AFS_LWP_MINSTACKSIZE)
425 * on some systems (e.g. hpux), a minimum usable stack size has
428 if (stacksize < lwp_MinStackSize) {
429 stacksize = lwp_MinStackSize;
431 #endif /* defined(AFS_LWP_MINSTACKSIZE) */
432 /* more stack size computations; keep track of for IOMGR */
433 if (lwp_MaxStackSeen < stacksize)
434 lwp_MaxStackSeen = stacksize;
436 Debug(0, ("Entered LWP_CreateProcess"));
437 /* Throw away all dead process control blocks */
440 temp = malloc(sizeof(struct lwp_pcb));
445 if (stacksize < MINSTACK)
449 STACK_ALIGN * ((stacksize + STACK_ALIGN - 1) / STACK_ALIGN);
450 if ((stackptr = malloc(stacksize)) == NULL) {
454 if (priority < 0 || priority >= MAX_PRIORITIES) {
458 Initialize_Stack(stackptr, stacksize);
459 Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
460 insert(temp, &runnable[priority]);
462 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
464 Abort_LWP("PRE_Block not 0");
466 /* Gross hack: beware! */
470 savecontext(Create_Process_Part2, &temp2->context,
471 stackptr + stacksize - sizeof(void *));
472 /* End of gross hack */
484 LWP_CurrentProcess(PROCESS * pid)
485 { /* returns pid of current process */
486 Debug(0, ("Entered Current_Process"));
497 Debug(0, ("Entered ThreadId"));
504 #define LWPANCHOR (*lwp_init)
507 LWP_DestroyProcess(PROCESS pid)
508 { /* destroy a lightweight process */
511 Debug(0, ("Entered Destroy_Process"));
513 if (lwp_cpptr != pid) {
514 Dispose_of_Dead_PCB(pid);
517 pid->status = DESTROYED;
518 move(pid, &runnable[pid->priority], &blocked);
520 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
521 savecontext(Dispatcher, &(temp->context),
522 &(LWPANCHOR.dsptchstack[MINFRAME]));
523 #elif defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
524 savecontext(Dispatcher, &(temp->context),
526 dsptchstack[(sizeof LWPANCHOR.dsptchstack) - 8]));
527 #elif defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
528 savecontext(Dispatcher, &(temp->context),
530 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
532 #elif defined(AFS_S390_LINUX20_ENV)
533 savecontext(Dispatcher, &(temp->context),
535 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
538 savecontext(Dispatcher, &(temp->context),
540 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
550 LWP_DispatchProcess(void)
551 { /* explicit voluntary preemption */
552 Debug(2, ("Entered Dispatch_Process"));
566 for (i = 0; i < MAX_PRIORITIES; i++)
567 for_all_elts(x, runnable[i], {
568 printf("[Priority %d]\n", i);
572 for_all_elts(x, blocked, {
573 Dump_One_Process(x);}
575 for_all_elts(x, qwaiting, {
576 Dump_One_Process(x);}
579 printf("***LWP: LWP support not initialized\n");
585 LWP_GetProcessPriority(PROCESS pid, int *priority)
586 { /* returns process priority */
587 Debug(0, ("Entered Get_Process_Priority"));
589 *priority = pid->priority;
596 LWP_InitializeProcessSupport(int priority, PROCESS * pid)
599 struct lwp_pcb dummy;
603 Debug(0, ("Entered LWP_InitializeProcessSupport"));
604 if (lwp_init != NULL)
607 /* Set up offset for stack checking -- do this as soon as possible */
608 stack_offset = (char *)&dummy.stack - (char *)&dummy;
610 if (priority >= MAX_PRIORITIES)
612 for (i = 0; i < MAX_PRIORITIES; i++) {
613 runnable[i].head = NULL;
614 runnable[i].count = 0;
618 qwaiting.head = NULL;
620 lwp_init = malloc(sizeof(struct lwp_ctl));
621 temp = malloc(sizeof(struct lwp_pcb));
622 if (lwp_init == NULL || temp == NULL)
623 Abort_LWP("Insufficient Storage to Initialize LWP Support");
624 LWPANCHOR.processcnt = 1;
625 LWPANCHOR.outerpid = temp;
626 LWPANCHOR.outersp = NULL;
627 Initialize_PCB(temp, priority, NULL, 0, NULL, NULL,
628 "Main Process [created by LWP]");
629 insert(temp, &runnable[priority]);
630 savecontext(Dispatcher, &temp->context, NULL);
631 LWPANCHOR.outersp = temp->context.topstack;
636 /* get minimum stack size from the environment. this allows the administrator
637 * to change the lwp stack dynamically without getting a new binary version.
639 if ((value = getenv("AFS_LWP_STACK_SIZE")) == NULL)
640 lwp_MinStackSize = AFS_LWP_MINSTACKSIZE;
643 (AFS_LWP_MINSTACKSIZE >
644 atoi(value) ? AFS_LWP_MINSTACKSIZE : atoi(value));
650 LWP_INTERNALSIGNAL(void *event, int yield)
651 { /* signal the occurence of an event */
652 Debug(2, ("Entered LWP_SignalProcess"));
655 rc = Internal_Signal(event);
664 LWP_TerminateProcessSupport(void)
665 { /* terminate all LWP support */
668 Debug(0, ("Entered Terminate_Process_Support"));
669 if (lwp_init == NULL)
671 if (lwp_cpptr != LWPANCHOR.outerpid)
672 Abort_LWP("Terminate_Process_Support invoked from wrong process!");
673 for (i = 0; i < MAX_PRIORITIES; i++)
674 for_all_elts(cur, runnable[i], {
677 for_all_elts(cur, blocked, {
680 for_all_elts(cur, qwaiting, {
689 LWP_WaitProcess(void *event)
690 { /* wait on a single event */
693 Debug(2, ("Entered Wait_Process"));
695 return LWP_EBADEVENT;
698 return LWP_MwaitProcess(1, tempev);
702 LWP_MwaitProcess(int wcount, void *evlist[])
703 { /* wait on m of n events */
707 Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount));
709 if (evlist == NULL) {
711 return LWP_EBADCOUNT;
714 for (ecount = 0; evlist[ecount] != NULL; ecount++);
718 return LWP_EBADCOUNT;
723 if (wcount > ecount || wcount < 0) {
725 return LWP_EBADCOUNT;
727 if (ecount > lwp_cpptr->eventlistsize) {
729 lwp_cpptr->eventlist = realloc(lwp_cpptr->eventlist,
730 ecount * sizeof(void *));
731 lwp_cpptr->eventlistsize = ecount;
733 for (i = 0; i < ecount; i++)
734 lwp_cpptr->eventlist[i] = evlist[i];
736 lwp_cpptr->status = WAITING;
738 move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked);
741 lwp_cpptr->wakevent = 0;
742 lwp_cpptr->waitcnt = wcount;
743 lwp_cpptr->eventcnt = ecount;
754 LWP_StackUsed(PROCESS pid, int *maxa, int *used)
756 *maxa = pid->stacksize;
757 *used = Stack_Used(pid->stack, *maxa);
764 * The following functions are strictly
765 * INTERNAL to the LWP support package.
771 struct lwp_context tempcontext;
773 Debug(0, ("Entered Abort_LWP"));
774 printf("***LWP: %s\n", msg);
775 printf("***LWP: Abort --- dumping PCBs ...\n");
779 if (LWPANCHOR.outersp == NULL)
782 savecontext(Exit_LWP, &tempcontext, LWPANCHOR.outersp);
787 Create_Process_Part2(void)
788 { /* creates a context for the new process */
791 Debug(2, ("Entered Create_Process_Part2"));
792 temp = lwp_cpptr; /* Get current process id */
793 savecontext(Dispatcher, &temp->context, NULL);
794 (*temp->ep) (temp->parm);
795 LWP_DestroyProcess(temp);
800 Delete_PCB(PROCESS pid)
801 { /* remove a PCB from the process list */
802 Debug(4, ("Entered Delete_PCB"));
804 (pid->blockflag || pid->status == WAITING
806 DESTROYED ? &blocked :
807 (pid->status == QWAITING) ? &qwaiting :
808 &runnable[pid->priority]));
809 LWPANCHOR.processcnt--;
815 Dump_One_Process(PROCESS pid)
819 printf("***LWP: Process Control Block at 0x%x\n", pid);
820 printf("***LWP: Name: %s\n", pid->name);
822 printf("***LWP: Initial entry point: 0x%x\n", pid->ep);
824 printf("BLOCKED and ");
825 switch (pid->status) {
842 printf("***LWP: Priority: %d \tInitial parameter: 0x%x\n", pid->priority,
844 if (pid->stacksize != 0) {
845 printf("***LWP: Stacksize: %d \tStack base address: 0x%x\n",
846 pid->stacksize, pid->stack);
847 printf("***LWP: HWM stack usage: ");
848 printf("%d\n", Stack_Used(pid->stack, pid->stacksize));
850 printf("***LWP: Current Stack Pointer: 0x%x\n", pid->context.topstack);
851 if (pid->eventcnt > 0) {
852 printf("***LWP: Number of events outstanding: %d\n", pid->waitcnt);
853 printf("***LWP: Event id list:");
854 for (i = 0; i < pid->eventcnt; i++)
855 printf(" 0x%x", pid->eventlist[i]);
858 if (pid->wakevent > 0)
859 printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent);
865 purge_dead_pcbs(void)
867 for_all_elts(cur, blocked, {
868 if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur);}
873 int LWP_TraceProcesses = 0;
877 { /* Lightweight process dispatcher */
880 static int dispatch_count = 0;
882 if (LWP_TraceProcesses > 0) {
883 for (i = 0; i < MAX_PRIORITIES; i++) {
884 printf("[Priority %d, runnable (%d):", i, runnable[i].count);
885 for_all_elts(p, runnable[i], {
886 printf(" \"%s\"", p->name);
891 printf("[Blocked (%d):", blocked.count);
892 for_all_elts(p, blocked, {
893 printf(" \"%s\"", p->name);
897 printf("[Qwaiting (%d):", qwaiting.count);
898 for_all_elts(p, qwaiting, {
899 printf(" \"%s\"", p->name);
906 /* Check for stack overflowif this lwp has a stack. Check for
907 * the guard word at the front of the stack being damaged and
908 * for the stack pointer being below the front of the stack.
909 * WARNING! This code assumes that stacks grow downward. */
910 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
911 /* Fix this (stackcheck at other end of stack?) */
912 if (lwp_cpptr != NULL && lwp_cpptr->stack != NULL
913 && (lwp_cpptr->stackcheck !=
914 *(afs_int32 *) ((lwp_cpptr->stack) + lwp_cpptr->stacksize - 4)
915 || lwp_cpptr->context.topstack >
916 lwp_cpptr->stack + lwp_cpptr->stacksize - 4)) {
918 if (lwp_cpptr && lwp_cpptr->stack
919 && (lwp_cpptr->stackcheck != *(int *)(lwp_cpptr->stack)
920 || lwp_cpptr->context.topstack < lwp_cpptr->stack
921 || lwp_cpptr->context.topstack >
922 (lwp_cpptr->stack + lwp_cpptr->stacksize))) {
924 printf("stackcheck = %u: stack = %u \n", lwp_cpptr->stackcheck,
925 *(int *)lwp_cpptr->stack);
926 printf("topstack = 0x%" AFS_PTR_FMT ": stackptr = 0x%" AFS_PTR_FMT ": stacksize = 0x%x\n",
927 (void *)(uintptr_t)lwp_cpptr->context.topstack,
928 (void *)(uintptr_t)lwp_cpptr->stack,
929 lwp_cpptr->stacksize);
931 switch (lwp_overflowAction) {
940 lwp_overflowAction = LWP_SOQUIET;
945 /* Move head of current runnable queue forward if current LWP is still in it. */
946 if (lwp_cpptr != NULL && lwp_cpptr == runnable[lwp_cpptr->priority].head)
947 runnable[lwp_cpptr->priority].head =
948 runnable[lwp_cpptr->priority].head->next;
949 /* Find highest priority with runnable processes. */
950 for (i = MAX_PRIORITIES - 1; i >= 0; i--)
951 if (runnable[i].head != NULL)
955 Abort_LWP("No READY processes");
958 if (LWP_TraceProcesses > 0)
959 printf("Dispatch %d [PCB at 0x%x] \"%s\"\n", ++dispatch_count,
960 runnable[i].head, runnable[i].head->name);
962 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
964 Abort_LWP("PRE_Block not 1");
966 lwp_cpptr = runnable[i].head;
968 returnto(&lwp_cpptr->context);
970 return; /* not reachable */
973 /* Complain of a stack overflow to stderr without using stdio. */
975 Overflow_Complain(void)
979 char *msg1 = " LWP: stack overflow in process ";
982 currenttime = time(0);
983 timeStamp = ctime(¤ttime);
985 if (write(2, timeStamp, strlen(timeStamp)) < 0)
988 if (write(2, msg1, strlen(msg1)) < 0)
990 if (write(2, lwp_cpptr->name, strlen(lwp_cpptr->name)) < 0)
992 if (write(2, msg2, strlen(msg2)) < 0)
997 Dispose_of_Dead_PCB(PROCESS cur)
999 Debug(4, ("Entered Dispose_of_Dead_PCB"));
1003 Internal_Signal(cur);
1014 Free_PCB(PROCESS pid)
1016 Debug(4, ("Entered Free_PCB"));
1017 if (pid->stack != NULL) {
1019 ("HWM stack usage: %d, [PCB at 0x%x]",
1020 Stack_Used(pid->stack, pid->stacksize), pid));
1021 #ifndef AFS_AIX32_ENV
1025 if (pid->eventlist != NULL)
1026 free(pid->eventlist);
1031 Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
1032 void *(*ep) (void *), void *parm, char *name)
1036 Debug(4, ("Entered Initialize_PCB"));
1038 while (((temp->name[i] = name[i]) != '\0') && (i < 31))
1040 temp->name[31] = '\0';
1041 temp->status = READY;
1042 temp->eventlist = malloc(EVINITSIZE * sizeof(void *));
1043 temp->eventlistsize = EVINITSIZE;
1047 temp->blockflag = 0;
1048 temp->iomgrRequest = 0;
1049 temp->priority = priority;
1050 temp->index = lwp_nextindex++;
1051 temp->stack = stack;
1052 temp->stacksize = stacksize;
1053 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1054 if (temp->stack != NULL)
1055 temp->stackcheck = *(int *)((temp->stack) + stacksize - 4);
1057 if (temp->stack != NULL)
1058 temp->stackcheck = *(int *)(temp->stack);
1062 temp->misc = NULL; /* currently unused */
1065 temp->lwp_rused = 0;
1066 temp->level = 1; /* non-preemptable */
1070 Internal_Signal(void *event)
1072 int rc = LWP_ENOWAIT;
1075 Debug(0, ("Entered Internal_Signal [event id 0x%x]", event));
1079 return LWP_EBADEVENT;
1080 for_all_elts(temp, blocked, {
1081 if (temp->status == WAITING)
1082 for (i = 0; i < temp->eventcnt; i++) {
1083 if (temp->eventlist[i] == event) {
1084 temp->eventlist[i] = NULL; rc = LWP_SUCCESS;
1085 Debug(0, ("Signal satisfied for PCB 0x%x", temp));
1086 if (--temp->waitcnt == 0) {
1087 temp->status = READY; temp->wakevent = i + 1;
1088 move(temp, &blocked, &runnable[temp->priority]); break;}
1096 /* This can be any unlikely pattern except 0x00010203 or the reverse. */
1097 #define STACKMAGIC 0xBADBADBA
1099 Initialize_Stack(char *stackptr, int stacksize)
1103 Debug(4, ("Entered Initialize_Stack"));
1104 if (lwp_stackUseEnabled)
1105 for (i = 0; i < stacksize; i++)
1106 stackptr[i] = i & 0xff;
1108 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1109 *(afs_int32 *) (stackptr + stacksize - 4) = STACKMAGIC;
1111 *(afs_int32 *) stackptr = STACKMAGIC;
1117 Stack_Used(char *stackptr, int stacksize)
1121 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1122 if (*(afs_int32 *) (stackptr + stacksize - 4) == STACKMAGIC)
1125 for (i = stacksize - 1; i >= 0; i--)
1126 if ((unsigned char)stackptr[i] != (i & 0xff))
1131 if (*(afs_int32 *) stackptr == STACKMAGIC)
1134 for (i = 0; i < stacksize; i++)
1135 if ((unsigned char)stackptr[i] != (i & 0xff))
1136 return (stacksize - i);
1144 LWP_NewRock(int Tag, char *Value)
1145 /* Finds a free rock and sets its value to Value.
1147 * LWP_SUCCESS Rock did not exist and a new one was used
1148 * LWP_EBADROCK Rock already exists.
1149 * LWP_ENOROCKS All rocks are in use.
1151 * From the above semantics, you can only set a rock value once. This is specifically
1152 * to prevent multiple users of the LWP package from accidentally using the same Tag
1153 * value and clobbering others. You can always use one level of indirection to obtain
1154 * a rock whose contents can change.
1158 struct rock *ra; /* rock array */
1160 ra = lwp_cpptr->lwp_rlist;
1162 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1163 if (ra[i].tag == Tag)
1164 return (LWP_EBADROCK);
1166 if (lwp_cpptr->lwp_rused < MAXROCKS) {
1167 ra[lwp_cpptr->lwp_rused].tag = Tag;
1168 ra[lwp_cpptr->lwp_rused].value = Value;
1169 lwp_cpptr->lwp_rused++;
1170 return (LWP_SUCCESS);
1172 return (LWP_ENOROCKS);
1177 LWP_GetRock(int Tag, char **Value)
1178 /* Obtains the pointer Value associated with the rock Tag of this LWP.
1180 * LWP_SUCCESS if specified rock exists and Value has been filled
1181 * LWP_EBADROCK rock specified does not exist
1187 ra = lwp_cpptr->lwp_rlist;
1189 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1190 if (ra[i].tag == Tag) {
1191 *Value = ra[i].value;
1192 return (LWP_SUCCESS);
1194 return (LWP_EBADROCK);
1198 #ifdef AFS_AIX32_ENV
1200 setlim(int limcon, uchar_t hard, int limit)
1204 (void)getrlimit(limcon, &rlim);
1206 limit = limit * 1024;
1208 rlim.rlim_max = limit;
1209 else if (limit == RLIM_INFINITY && geteuid() != 0)
1210 rlim.rlim_cur = rlim.rlim_max;
1212 rlim.rlim_cur = limit;
1214 /* Must use ulimit() due to Posix constraints */
1215 if (limcon == RLIMIT_FSIZE) {
1218 ((hard ? rlim.rlim_max : rlim.rlim_cur) / 512)) < 0) {
1219 printf("Can't %s%s limit\n",
1220 limit == RLIM_INFINITY ? "remove" : "set",
1221 hard ? " hard" : "");
1225 if (setrlimit(limcon, &rlim) < 0) {
1227 printf("Can't %s%s limit\n",
1228 limit == RLIM_INFINITY ? "remove" : "set",
1229 hard ? " hard" : "");
1239 LWP_NoYieldSignal(void *event)
1241 return (LWP_INTERNALSIGNAL(event, 0));
1245 LWP_SignalProcess(void *event)
1247 return (LWP_INTERNALSIGNAL(event, 1));