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>
28 /* allocate externs here */
33 #include <sys/errno.h>
38 int setlim(int limcon, uchar_t hard, int limit);
41 extern char *getenv();
46 #ifndef AFS_ARM_LINUX20_ENV
47 #if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
48 extern int PRE_Block; /* from preempt.c */
50 extern char PRE_Block; /* from preempt.c */
62 #define MAXINT (~(1<<((sizeof(int)*8)-1)))
65 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
76 #elif defined(AFS_DARWIN_ENV)
77 #define STACK_ALIGN 16
86 #define Debug(level, msg) do { \
87 if (lwp_debug && lwp_debug >= level) { \
88 printf("***LWP (0x%x): ", lwp_cpptr); \
94 #define Debug(level, msg) do { \
99 static void Dispatcher(void);
100 static void Create_Process_Part2(void);
101 static void Exit_LWP(void);
102 static afs_int32 Initialize_Stack(char *stackptr, int stacksize);
103 static int Stack_Used(char *stackptr, int stacksize);
105 static void Abort_LWP(char *msg);
106 static void Overflow_Complain(void);
107 static void Initialize_PCB(PROCESS temp, int priority, char *stack,
108 int stacksize, void *(*ep)(void *), void *parm,
110 static void Dispose_of_Dead_PCB(PROCESS cur);
111 static void Free_PCB(PROCESS pid);
112 static int Internal_Signal(void *event);
113 static int purge_dead_pcbs(void);
114 static int LWP_MwaitProcess(int wcount, void *evlist[]);
117 #define MAX_PRIORITIES (LWP_MAX_PRIORITY+1)
122 } runnable[MAX_PRIORITIES], blocked, qwaiting;
123 /* Invariant for runnable queues: The head of each queue points to the
124 * currently running process if it is in that queue, or it points to the
125 * next process in that queue that should run. */
127 /* Offset of stack field within pcb -- used by stack checking stuff */
130 /* special user-tweakable option for AIX */
131 int lwp_MaxStackSize = 32768;
133 /* biggest LWP stack created so far */
134 int lwp_MaxStackSeen = 0;
136 /* Stack checking action */
137 int lwp_overflowAction = LWP_SOABORT;
139 /* Controls stack size counting. */
140 int lwp_stackUseEnabled = TRUE; /* pay the price */
144 /* Minimum stack size */
145 int lwp_MinStackSize = 0;
148 lwp_remove(PROCESS p, struct QUEUE *q)
150 /* Special test for only element on queue */
154 /* Not only element, do normal remove */
155 p->next->prev = p->prev;
156 p->prev->next = p->next;
158 /* See if head pointing to this element */
162 p->next = p->prev = NULL;
167 insert(PROCESS p, struct QUEUE *q)
169 if (q->head == NULL) { /* Queue is empty */
171 p->next = p->prev = p;
172 } else { /* Regular insert */
173 p->prev = q->head->prev;
174 q->head->prev->next = p;
183 move(PROCESS p, struct QUEUE *from, struct QUEUE *to)
193 #define for_all_elts(var, q, body)\
195 PROCESS var, _NEXT_;\
197 for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\
198 _NEXT_ = var -> next;\
204 /*****************************************************************************\
206 * Following section documents the Assembler interfaces used by LWP code *
208 \*****************************************************************************/
211 savecontext(int (*ep)(), struct lwp_context *savearea, char *sp);
213 Stub for Assembler routine that will
214 save the current SP value in the passed
215 context savearea and call the function
216 whose entry point is in ep. If the sp
217 parameter is NULL, the current stack is
218 used, otherwise sp becomes the new stack
221 returnto(struct lwp_context *savearea);
223 Stub for Assembler routine that will
224 restore context from a passed savearea
225 and return to the restored C frame.
229 /* Macro to force a re-schedule. Strange name is historical */
230 #define Set_LWP_RC() savecontext(Dispatcher, &lwp_cpptr->context, NULL)
232 static struct lwp_ctl *lwp_init = 0;
238 (tp = lwp_cpptr)->status = QWAITING;
239 move(tp, &runnable[tp->priority], &qwaiting);
245 LWP_QSignal(PROCESS pid)
247 if (pid->status == QWAITING) {
249 move(pid, &qwaiting, &runnable[pid->priority]);
257 reserveFromStack(afs_int32 size)
266 LWP_CreateProcess(void *(*ep) (void *), int stacksize, int priority, void *parm,
267 char *name, PROCESS * pid)
271 static char *stackptr = 0;
277 #if defined(AFS_LWP_MINSTACKSIZE)
279 * on some systems (e.g. hpux), a minimum usable stack size has
282 if (stacksize < lwp_MinStackSize) {
283 stacksize = lwp_MinStackSize;
285 #endif /* defined(AFS_LWP_MINSTACKSIZE) */
286 /* more stack size computations; keep track of for IOMGR */
287 if (lwp_MaxStackSeen < stacksize)
288 lwp_MaxStackSeen = stacksize;
290 Debug(0, ("Entered LWP_CreateProcess"));
291 /* Throw away all dead process control blocks */
294 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
299 if (stacksize < MINSTACK)
300 #ifdef AFS_DARWIN_ENV
302 #else /* !AFS_DARWIN_ENV */
304 #endif /* !AFS_DARWIN_ENV */
307 STACK_ALIGN * ((stacksize + STACK_ALIGN - 1) / STACK_ALIGN);
311 * The following signal action for AIX is necessary so that in case of a
312 * crash (i.e. core is generated) we can include the user's data section
313 * in the core dump. Unfortunately, by default, only a partial core is
314 * generated which, in many cases, isn't too useful.
316 * We also do it here in case the main program forgets to do it.
318 struct sigaction nsa;
319 extern uid_t geteuid();
321 sigemptyset(&nsa.sa_mask);
322 nsa.sa_handler = SIG_DFL;
323 nsa.sa_flags = SA_FULLDUMP;
324 sigaction(SIGABRT, &nsa, NULL);
325 sigaction(SIGSEGV, &nsa, NULL);
328 * First we need to increase the default resource limits,
329 * if necessary, so that we can guarantee that we have the
330 * resources to create the core file, but we can't always
331 * do it as an ordinary user.
334 /* vos dump causes problems */
335 /* setlim(RLIMIT_FSIZE, 0, 1048575); * 1 Gig */
336 setlim(RLIMIT_STACK, 0, 65536); /* 65 Meg */
337 setlim(RLIMIT_CORE, 0, 131072); /* 131 Meg */
340 * Now reserve in one scoop all the stack space that will be used
341 * by the particular application's main (i.e. non-lwp) body. This
342 * is plenty space for any of our applications.
344 stackptr = reserveFromStack(lwp_MaxStackSize);
346 stackptr -= stacksize;
347 stackmemory = stackptr;
349 #ifdef AFS_DARWIN_ENV
350 if ((stackmemory = (char *)malloc(stacksize + STACK_ALIGN - 1)) == NULL)
351 #else /* !AFS_DARWIN_ENV */
352 if ((stackmemory = (char *)malloc(stacksize + 7)) == NULL)
353 #endif /* !AFS_DARWIN_ENV */
358 /* Round stack pointer to byte boundary */
359 #ifdef AFS_DARWIN_ENV
360 stackptr = (char *)(STACK_ALIGN * (((long)stackmemory + STACK_ALIGN - 1) / STACK_ALIGN));
361 #else /* !AFS_DARWIN_ENV */
362 stackptr = (char *)(8 * (((long)stackmemory + 7) / 8));
363 #endif /* !AFS_DARWIN_ENV */
365 if (priority < 0 || priority >= MAX_PRIORITIES) {
369 Initialize_Stack(stackptr, stacksize);
370 Initialize_PCB(temp, priority, stackmemory, stacksize, ep, parm, name);
371 insert(temp, &runnable[priority]);
373 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
375 Abort_LWP("PRE_Block not 0");
377 /* Gross hack: beware! */
381 #if defined(AFS_PARISC_LINUX24_ENV)
382 savecontext(Create_Process_Part2, &temp2->context,
383 stackptr + MINFRAME);
386 savecontext(Create_Process_Part2, &temp2->context,
387 stackptr + MINFRAME);
389 #if defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
390 #ifdef sys_x86_darwin_80
391 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16 - sizeof(void *)); /* 16 = 2 * jmp_buf_type */
392 #else /* !sys_x86_darwin_80 */
393 /* Need to have the sp on an 8-byte boundary for storing doubles. */
394 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 16); /* 16 = 2 * jmp_buf_type */
395 #endif /* !sys_x86_darwin_80 */
397 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
398 savecontext(Create_Process_Part2, &temp2->context, stackptr + stacksize - 0x40); /* lomgjmp does something
401 #if defined(AFS_S390_LINUX20_ENV)
402 savecontext(Create_Process_Part2, &temp2->context,
403 stackptr + stacksize - MINFRAME);
404 #else /* !AFS_S390_LINUX20_ENV */
405 savecontext(Create_Process_Part2, &temp2->context,
406 stackptr + stacksize - sizeof(void *));
407 #endif /* AFS_S390_LINUX20_ENV */
408 #endif /* AFS_SPARC64_LINUX20_ENV || AFS_SPARC_LINUX20_ENV */
409 #endif /* AFS_SGI62_ENV */
412 /* End of gross hack */
424 LWP_CreateProcess2(void *(*ep) (void *), int stacksize, int priority, void *parm,
425 char *name, PROCESS * pid)
430 #if defined(AFS_LWP_MINSTACKSIZE)
432 * on some systems (e.g. hpux), a minimum usable stack size has
435 if (stacksize < lwp_MinStackSize) {
436 stacksize = lwp_MinStackSize;
438 #endif /* defined(AFS_LWP_MINSTACKSIZE) */
439 /* more stack size computations; keep track of for IOMGR */
440 if (lwp_MaxStackSeen < stacksize)
441 lwp_MaxStackSeen = stacksize;
443 Debug(0, ("Entered LWP_CreateProcess"));
444 /* Throw away all dead process control blocks */
447 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
452 if (stacksize < MINSTACK)
456 STACK_ALIGN * ((stacksize + STACK_ALIGN - 1) / STACK_ALIGN);
457 if ((stackptr = (char *)malloc(stacksize)) == NULL) {
461 if (priority < 0 || priority >= MAX_PRIORITIES) {
465 Initialize_Stack(stackptr, stacksize);
466 Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
467 insert(temp, &runnable[priority]);
469 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
471 Abort_LWP("PRE_Block not 0");
473 /* Gross hack: beware! */
477 savecontext(Create_Process_Part2, &temp2->context,
478 stackptr + stacksize - sizeof(void *));
479 /* End of gross hack */
491 LWP_CurrentProcess(PROCESS * pid)
492 { /* returns pid of current process */
493 Debug(0, ("Entered Current_Process"));
504 Debug(0, ("Entered ThreadId"));
511 #define LWPANCHOR (*lwp_init)
514 LWP_DestroyProcess(PROCESS pid)
515 { /* destroy a lightweight process */
518 Debug(0, ("Entered Destroy_Process"));
520 if (lwp_cpptr != pid) {
521 Dispose_of_Dead_PCB(pid);
524 pid->status = DESTROYED;
525 move(pid, &runnable[pid->priority], &blocked);
527 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
528 savecontext(Dispatcher, &(temp->context),
529 &(LWPANCHOR.dsptchstack[MINFRAME]));
530 #elif defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
531 savecontext(Dispatcher, &(temp->context),
533 dsptchstack[(sizeof LWPANCHOR.dsptchstack) - 8]));
534 #elif defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
535 savecontext(Dispatcher, &(temp->context),
537 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
539 #elif defined(AFS_S390_LINUX20_ENV)
540 savecontext(Dispatcher, &(temp->context),
542 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
545 savecontext(Dispatcher, &(temp->context),
547 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
557 LWP_DispatchProcess(void)
558 { /* explicit voluntary preemption */
559 Debug(2, ("Entered Dispatch_Process"));
573 for (i = 0; i < MAX_PRIORITIES; i++)
574 for_all_elts(x, runnable[i], {
575 printf("[Priority %d]\n", i);
579 for_all_elts(x, blocked, {
580 Dump_One_Process(x);}
582 for_all_elts(x, qwaiting, {
583 Dump_One_Process(x);}
586 printf("***LWP: LWP support not initialized\n");
592 LWP_GetProcessPriority(PROCESS pid, int *priority)
593 { /* returns process priority */
594 Debug(0, ("Entered Get_Process_Priority"));
596 *priority = pid->priority;
603 LWP_InitializeProcessSupport(int priority, PROCESS * pid)
606 struct lwp_pcb dummy;
610 Debug(0, ("Entered LWP_InitializeProcessSupport"));
611 if (lwp_init != NULL)
614 /* Set up offset for stack checking -- do this as soon as possible */
615 stack_offset = (char *)&dummy.stack - (char *)&dummy;
617 if (priority >= MAX_PRIORITIES)
619 for (i = 0; i < MAX_PRIORITIES; i++) {
620 runnable[i].head = NULL;
621 runnable[i].count = 0;
625 qwaiting.head = NULL;
627 lwp_init = (struct lwp_ctl *)malloc(sizeof(struct lwp_ctl));
628 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
629 if (lwp_init == NULL || temp == NULL)
630 Abort_LWP("Insufficient Storage to Initialize LWP Support");
631 LWPANCHOR.processcnt = 1;
632 LWPANCHOR.outerpid = temp;
633 LWPANCHOR.outersp = NULL;
634 Initialize_PCB(temp, priority, NULL, 0, NULL, NULL,
635 "Main Process [created by LWP]");
636 insert(temp, &runnable[priority]);
637 savecontext(Dispatcher, &temp->context, NULL);
638 LWPANCHOR.outersp = temp->context.topstack;
643 /* get minimum stack size from the environment. this allows the administrator
644 * to change the lwp stack dynamically without getting a new binary version.
646 if ((value = getenv("AFS_LWP_STACK_SIZE")) == NULL)
647 lwp_MinStackSize = AFS_LWP_MINSTACKSIZE;
650 (AFS_LWP_MINSTACKSIZE >
651 atoi(value) ? AFS_LWP_MINSTACKSIZE : atoi(value));
657 LWP_INTERNALSIGNAL(void *event, int yield)
658 { /* signal the occurence of an event */
659 Debug(2, ("Entered LWP_SignalProcess"));
662 rc = Internal_Signal(event);
671 LWP_TerminateProcessSupport(void)
672 { /* terminate all LWP support */
675 Debug(0, ("Entered Terminate_Process_Support"));
676 if (lwp_init == NULL)
678 if (lwp_cpptr != LWPANCHOR.outerpid)
679 Abort_LWP("Terminate_Process_Support invoked from wrong process!");
680 for (i = 0; i < MAX_PRIORITIES; i++)
681 for_all_elts(cur, runnable[i], {
684 for_all_elts(cur, blocked, {
687 for_all_elts(cur, qwaiting, {
696 LWP_WaitProcess(void *event)
697 { /* wait on a single event */
700 Debug(2, ("Entered Wait_Process"));
702 return LWP_EBADEVENT;
705 return LWP_MwaitProcess(1, tempev);
709 LWP_MwaitProcess(int wcount, void *evlist[])
710 { /* wait on m of n events */
714 Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount));
716 if (evlist == NULL) {
718 return LWP_EBADCOUNT;
721 for (ecount = 0; evlist[ecount] != NULL; ecount++);
725 return LWP_EBADCOUNT;
730 if (wcount > ecount || wcount < 0) {
732 return LWP_EBADCOUNT;
734 if (ecount > lwp_cpptr->eventlistsize) {
736 lwp_cpptr->eventlist =
737 (void **)realloc(lwp_cpptr->eventlist,
738 ecount * sizeof(void *));
739 lwp_cpptr->eventlistsize = ecount;
741 for (i = 0; i < ecount; i++)
742 lwp_cpptr->eventlist[i] = evlist[i];
744 lwp_cpptr->status = WAITING;
746 move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked);
749 lwp_cpptr->wakevent = 0;
750 lwp_cpptr->waitcnt = wcount;
751 lwp_cpptr->eventcnt = ecount;
762 LWP_StackUsed(PROCESS pid, int *maxa, int *used)
764 *maxa = pid->stacksize;
765 *used = Stack_Used(pid->stack, *maxa);
772 * The following functions are strictly
773 * INTERNAL to the LWP support package.
779 struct lwp_context tempcontext;
781 Debug(0, ("Entered Abort_LWP"));
782 printf("***LWP: %s\n", msg);
783 printf("***LWP: Abort --- dumping PCBs ...\n");
787 if (LWPANCHOR.outersp == NULL)
790 savecontext(Exit_LWP, &tempcontext, LWPANCHOR.outersp);
795 Create_Process_Part2(void)
796 { /* creates a context for the new process */
799 Debug(2, ("Entered Create_Process_Part2"));
800 temp = lwp_cpptr; /* Get current process id */
801 savecontext(Dispatcher, &temp->context, NULL);
802 (*temp->ep) (temp->parm);
803 LWP_DestroyProcess(temp);
808 Delete_PCB(PROCESS pid)
809 { /* remove a PCB from the process list */
810 Debug(4, ("Entered Delete_PCB"));
812 (pid->blockflag || pid->status == WAITING
814 DESTROYED ? &blocked :
815 (pid->status == QWAITING) ? &qwaiting :
816 &runnable[pid->priority]));
817 LWPANCHOR.processcnt--;
823 Dump_One_Process(PROCESS pid)
827 printf("***LWP: Process Control Block at 0x%x\n", pid);
828 printf("***LWP: Name: %s\n", pid->name);
830 printf("***LWP: Initial entry point: 0x%x\n", pid->ep);
832 printf("BLOCKED and ");
833 switch (pid->status) {
850 printf("***LWP: Priority: %d \tInitial parameter: 0x%x\n", pid->priority,
852 if (pid->stacksize != 0) {
853 printf("***LWP: Stacksize: %d \tStack base address: 0x%x\n",
854 pid->stacksize, pid->stack);
855 printf("***LWP: HWM stack usage: ");
856 printf("%d\n", Stack_Used(pid->stack, pid->stacksize));
858 printf("***LWP: Current Stack Pointer: 0x%x\n", pid->context.topstack);
859 if (pid->eventcnt > 0) {
860 printf("***LWP: Number of events outstanding: %d\n", pid->waitcnt);
861 printf("***LWP: Event id list:");
862 for (i = 0; i < pid->eventcnt; i++)
863 printf(" 0x%x", pid->eventlist[i]);
866 if (pid->wakevent > 0)
867 printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent);
873 purge_dead_pcbs(void)
875 for_all_elts(cur, blocked, {
876 if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur);}
881 int LWP_TraceProcesses = 0;
885 { /* Lightweight process dispatcher */
888 static int dispatch_count = 0;
890 if (LWP_TraceProcesses > 0) {
891 for (i = 0; i < MAX_PRIORITIES; i++) {
892 printf("[Priority %d, runnable (%d):", i, runnable[i].count);
893 for_all_elts(p, runnable[i], {
894 printf(" \"%s\"", p->name);
899 printf("[Blocked (%d):", blocked.count);
900 for_all_elts(p, blocked, {
901 printf(" \"%s\"", p->name);
905 printf("[Qwaiting (%d):", qwaiting.count);
906 for_all_elts(p, qwaiting, {
907 printf(" \"%s\"", p->name);
914 /* Check for stack overflowif this lwp has a stack. Check for
915 * the guard word at the front of the stack being damaged and
916 * for the stack pointer being below the front of the stack.
917 * WARNING! This code assumes that stacks grow downward. */
918 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
919 /* Fix this (stackcheck at other end of stack?) */
920 if (lwp_cpptr != NULL && lwp_cpptr->stack != NULL
921 && (lwp_cpptr->stackcheck !=
922 *(afs_int32 *) ((lwp_cpptr->stack) + lwp_cpptr->stacksize - 4)
923 || lwp_cpptr->context.topstack >
924 lwp_cpptr->stack + lwp_cpptr->stacksize - 4)) {
926 if (lwp_cpptr && lwp_cpptr->stack
927 && (lwp_cpptr->stackcheck != *(int *)(lwp_cpptr->stack)
928 || lwp_cpptr->context.topstack < lwp_cpptr->stack
929 || lwp_cpptr->context.topstack >
930 (lwp_cpptr->stack + lwp_cpptr->stacksize))) {
932 printf("stackcheck = %u: stack = %u \n", lwp_cpptr->stackcheck,
933 *(int *)lwp_cpptr->stack);
934 printf("topstack = 0x%" AFS_PTR_FMT ": stackptr = 0x%" AFS_PTR_FMT ": stacksize = 0x%x\n",
935 (void *)(uintptr_t)lwp_cpptr->context.topstack,
936 (void *)(uintptr_t)lwp_cpptr->stack,
937 lwp_cpptr->stacksize);
939 switch (lwp_overflowAction) {
948 lwp_overflowAction = LWP_SOQUIET;
953 /* Move head of current runnable queue forward if current LWP is still in it. */
954 if (lwp_cpptr != NULL && lwp_cpptr == runnable[lwp_cpptr->priority].head)
955 runnable[lwp_cpptr->priority].head =
956 runnable[lwp_cpptr->priority].head->next;
957 /* Find highest priority with runnable processes. */
958 for (i = MAX_PRIORITIES - 1; i >= 0; i--)
959 if (runnable[i].head != NULL)
963 Abort_LWP("No READY processes");
966 if (LWP_TraceProcesses > 0)
967 printf("Dispatch %d [PCB at 0x%x] \"%s\"\n", ++dispatch_count,
968 runnable[i].head, runnable[i].head->name);
970 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
972 Abort_LWP("PRE_Block not 1");
974 lwp_cpptr = runnable[i].head;
976 returnto(&lwp_cpptr->context);
978 return; /* not reachable */
981 /* Complain of a stack overflow to stderr without using stdio. */
983 Overflow_Complain(void)
987 char *msg1 = " LWP: stack overflow in process ";
990 currenttime = time(0);
991 timeStamp = ctime(¤ttime);
993 write(2, timeStamp, strlen(timeStamp));
995 write(2, msg1, strlen(msg1));
996 write(2, lwp_cpptr->name, strlen(lwp_cpptr->name));
997 write(2, msg2, strlen(msg2));
1001 Dispose_of_Dead_PCB(PROCESS cur)
1003 Debug(4, ("Entered Dispose_of_Dead_PCB"));
1007 Internal_Signal(cur);
1018 Free_PCB(PROCESS pid)
1020 Debug(4, ("Entered Free_PCB"));
1021 if (pid->stack != NULL) {
1023 ("HWM stack usage: %d, [PCB at 0x%x]",
1024 Stack_Used(pid->stack, pid->stacksize), pid));
1025 #ifndef AFS_AIX32_ENV
1029 if (pid->eventlist != NULL)
1030 free(pid->eventlist);
1035 Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
1036 void *(*ep) (void *), void *parm, char *name)
1040 Debug(4, ("Entered Initialize_PCB"));
1042 while (((temp->name[i] = name[i]) != '\0') && (i < 31))
1044 temp->name[31] = '\0';
1045 temp->status = READY;
1046 temp->eventlist = (void **)malloc(EVINITSIZE * sizeof(void *));
1047 temp->eventlistsize = EVINITSIZE;
1051 temp->blockflag = 0;
1052 temp->iomgrRequest = 0;
1053 temp->priority = priority;
1054 temp->index = lwp_nextindex++;
1055 temp->stack = stack;
1056 temp->stacksize = stacksize;
1057 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1058 if (temp->stack != NULL)
1059 temp->stackcheck = *(int *)((temp->stack) + stacksize - 4);
1061 if (temp->stack != NULL)
1062 temp->stackcheck = *(int *)(temp->stack);
1066 temp->misc = NULL; /* currently unused */
1069 temp->lwp_rused = 0;
1070 temp->level = 1; /* non-preemptable */
1074 Internal_Signal(void *event)
1076 int rc = LWP_ENOWAIT;
1079 Debug(0, ("Entered Internal_Signal [event id 0x%x]", event));
1083 return LWP_EBADEVENT;
1084 for_all_elts(temp, blocked, {
1085 if (temp->status == WAITING)
1086 for (i = 0; i < temp->eventcnt; i++) {
1087 if (temp->eventlist[i] == event) {
1088 temp->eventlist[i] = NULL; rc = LWP_SUCCESS;
1089 Debug(0, ("Signal satisfied for PCB 0x%x", temp));
1090 if (--temp->waitcnt == 0) {
1091 temp->status = READY; temp->wakevent = i + 1;
1092 move(temp, &blocked, &runnable[temp->priority]); break;}
1100 /* This can be any unlikely pattern except 0x00010203 or the reverse. */
1101 #define STACKMAGIC 0xBADBADBA
1103 Initialize_Stack(char *stackptr, int stacksize)
1107 Debug(4, ("Entered Initialize_Stack"));
1108 if (lwp_stackUseEnabled)
1109 for (i = 0; i < stacksize; i++)
1110 stackptr[i] = i & 0xff;
1112 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1113 *(afs_int32 *) (stackptr + stacksize - 4) = STACKMAGIC;
1115 *(afs_int32 *) stackptr = STACKMAGIC;
1121 Stack_Used(char *stackptr, int stacksize)
1125 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1126 if (*(afs_int32 *) (stackptr + stacksize - 4) == STACKMAGIC)
1129 for (i = stacksize - 1; i >= 0; i--)
1130 if ((unsigned char)stackptr[i] != (i & 0xff))
1135 if (*(afs_int32 *) stackptr == STACKMAGIC)
1138 for (i = 0; i < stacksize; i++)
1139 if ((unsigned char)stackptr[i] != (i & 0xff))
1140 return (stacksize - i);
1148 LWP_NewRock(int Tag, char *Value)
1149 /* Finds a free rock and sets its value to Value.
1151 * LWP_SUCCESS Rock did not exist and a new one was used
1152 * LWP_EBADROCK Rock already exists.
1153 * LWP_ENOROCKS All rocks are in use.
1155 * From the above semantics, you can only set a rock value once. This is specifically
1156 * to prevent multiple users of the LWP package from accidentally using the same Tag
1157 * value and clobbering others. You can always use one level of indirection to obtain
1158 * a rock whose contents can change.
1162 struct rock *ra; /* rock array */
1164 ra = lwp_cpptr->lwp_rlist;
1166 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1167 if (ra[i].tag == Tag)
1168 return (LWP_EBADROCK);
1170 if (lwp_cpptr->lwp_rused < MAXROCKS) {
1171 ra[lwp_cpptr->lwp_rused].tag = Tag;
1172 ra[lwp_cpptr->lwp_rused].value = Value;
1173 lwp_cpptr->lwp_rused++;
1174 return (LWP_SUCCESS);
1176 return (LWP_ENOROCKS);
1181 LWP_GetRock(int Tag, char **Value)
1182 /* Obtains the pointer Value associated with the rock Tag of this LWP.
1184 * LWP_SUCCESS if specified rock exists and Value has been filled
1185 * LWP_EBADROCK rock specified does not exist
1191 ra = lwp_cpptr->lwp_rlist;
1193 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1194 if (ra[i].tag == Tag) {
1195 *Value = ra[i].value;
1196 return (LWP_SUCCESS);
1198 return (LWP_EBADROCK);
1202 #ifdef AFS_AIX32_ENV
1204 setlim(int limcon, uchar_t hard, int limit)
1208 (void)getrlimit(limcon, &rlim);
1210 limit = limit * 1024;
1212 rlim.rlim_max = limit;
1213 else if (limit == RLIM_INFINITY && geteuid() != 0)
1214 rlim.rlim_cur = rlim.rlim_max;
1216 rlim.rlim_cur = limit;
1218 /* Must use ulimit() due to Posix constraints */
1219 if (limcon == RLIMIT_FSIZE) {
1222 ((hard ? rlim.rlim_max : rlim.rlim_cur) / 512)) < 0) {
1223 printf("Can't %s%s limit\n",
1224 limit == RLIM_INFINITY ? "remove" : "set",
1225 hard ? " hard" : "");
1229 if (setrlimit(limcon, &rlim) < 0) {
1231 printf("Can't %s%s limit\n",
1232 limit == RLIM_INFINITY ? "remove" : "set",
1233 hard ? " hard" : "");
1243 LWP_NoYieldSignal(void *event)
1245 return (LWP_INTERNALSIGNAL(event, 0));
1249 LWP_SignalProcess(void *event)
1251 return (LWP_INTERNALSIGNAL(event, 1));