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 extern int PRE_Block; /* from preempt.c */
40 extern char PRE_Block; /* from preempt.c */
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 = (PROCESS) 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 = (char *)malloc(stacksize + STACK_ALIGN - 1)) == NULL)
341 #else /* !AFS_DARWIN_ENV */
342 if ((stackmemory = (char *)malloc(stacksize + 7)) == NULL)
343 #endif /* !AFS_DARWIN_ENV */
348 /* Round stack pointer to byte boundary */
349 #ifdef AFS_DARWIN_ENV
350 stackptr = (char *)(STACK_ALIGN * (((long)stackmemory + STACK_ALIGN - 1) / STACK_ALIGN));
351 #else /* !AFS_DARWIN_ENV */
352 stackptr = (char *)(8 * (((long)stackmemory + 7) / 8));
353 #endif /* !AFS_DARWIN_ENV */
355 if (priority < 0 || priority >= MAX_PRIORITIES) {
359 Initialize_Stack(stackptr, stacksize);
360 Initialize_PCB(temp, priority, stackmemory, stacksize, ep, parm, name);
361 insert(temp, &runnable[priority]);
363 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
365 Abort_LWP("PRE_Block not 0");
367 /* Gross hack: beware! */
371 #if defined(AFS_PARISC_LINUX24_ENV)
372 savecontext(Create_Process_Part2, &temp2->context,
373 stackptr + MINFRAME);
376 savecontext(Create_Process_Part2, &temp2->context,
377 stackptr + MINFRAME);
379 #if defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
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 */
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
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 */
402 /* End of gross hack */
414 LWP_CreateProcess2(void *(*ep) (void *), int stacksize, int priority, void *parm,
415 char *name, PROCESS * pid)
420 #if defined(AFS_LWP_MINSTACKSIZE)
422 * on some systems (e.g. hpux), a minimum usable stack size has
425 if (stacksize < lwp_MinStackSize) {
426 stacksize = lwp_MinStackSize;
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;
433 Debug(0, ("Entered LWP_CreateProcess"));
434 /* Throw away all dead process control blocks */
437 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
442 if (stacksize < MINSTACK)
446 STACK_ALIGN * ((stacksize + STACK_ALIGN - 1) / STACK_ALIGN);
447 if ((stackptr = (char *)malloc(stacksize)) == NULL) {
451 if (priority < 0 || priority >= MAX_PRIORITIES) {
455 Initialize_Stack(stackptr, stacksize);
456 Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
457 insert(temp, &runnable[priority]);
459 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
461 Abort_LWP("PRE_Block not 0");
463 /* Gross hack: beware! */
467 savecontext(Create_Process_Part2, &temp2->context,
468 stackptr + stacksize - sizeof(void *));
469 /* End of gross hack */
481 LWP_CurrentProcess(PROCESS * pid)
482 { /* returns pid of current process */
483 Debug(0, ("Entered Current_Process"));
494 Debug(0, ("Entered ThreadId"));
501 #define LWPANCHOR (*lwp_init)
504 LWP_DestroyProcess(PROCESS pid)
505 { /* destroy a lightweight process */
508 Debug(0, ("Entered Destroy_Process"));
510 if (lwp_cpptr != pid) {
511 Dispose_of_Dead_PCB(pid);
514 pid->status = DESTROYED;
515 move(pid, &runnable[pid->priority], &blocked);
517 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
518 savecontext(Dispatcher, &(temp->context),
519 &(LWPANCHOR.dsptchstack[MINFRAME]));
520 #elif defined(AFS_SGI62_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
521 savecontext(Dispatcher, &(temp->context),
523 dsptchstack[(sizeof LWPANCHOR.dsptchstack) - 8]));
524 #elif defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
525 savecontext(Dispatcher, &(temp->context),
527 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
529 #elif defined(AFS_S390_LINUX20_ENV)
530 savecontext(Dispatcher, &(temp->context),
532 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
535 savecontext(Dispatcher, &(temp->context),
537 dsptchstack[(sizeof LWPANCHOR.dsptchstack) -
547 LWP_DispatchProcess(void)
548 { /* explicit voluntary preemption */
549 Debug(2, ("Entered Dispatch_Process"));
563 for (i = 0; i < MAX_PRIORITIES; i++)
564 for_all_elts(x, runnable[i], {
565 printf("[Priority %d]\n", i);
569 for_all_elts(x, blocked, {
570 Dump_One_Process(x);}
572 for_all_elts(x, qwaiting, {
573 Dump_One_Process(x);}
576 printf("***LWP: LWP support not initialized\n");
582 LWP_GetProcessPriority(PROCESS pid, int *priority)
583 { /* returns process priority */
584 Debug(0, ("Entered Get_Process_Priority"));
586 *priority = pid->priority;
593 LWP_InitializeProcessSupport(int priority, PROCESS * pid)
596 struct lwp_pcb dummy;
600 Debug(0, ("Entered LWP_InitializeProcessSupport"));
601 if (lwp_init != NULL)
604 /* Set up offset for stack checking -- do this as soon as possible */
605 stack_offset = (char *)&dummy.stack - (char *)&dummy;
607 if (priority >= MAX_PRIORITIES)
609 for (i = 0; i < MAX_PRIORITIES; i++) {
610 runnable[i].head = NULL;
611 runnable[i].count = 0;
615 qwaiting.head = NULL;
617 lwp_init = (struct lwp_ctl *)malloc(sizeof(struct lwp_ctl));
618 temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
619 if (lwp_init == NULL || temp == NULL)
620 Abort_LWP("Insufficient Storage to Initialize LWP Support");
621 LWPANCHOR.processcnt = 1;
622 LWPANCHOR.outerpid = temp;
623 LWPANCHOR.outersp = NULL;
624 Initialize_PCB(temp, priority, NULL, 0, NULL, NULL,
625 "Main Process [created by LWP]");
626 insert(temp, &runnable[priority]);
627 savecontext(Dispatcher, &temp->context, NULL);
628 LWPANCHOR.outersp = temp->context.topstack;
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.
636 if ((value = getenv("AFS_LWP_STACK_SIZE")) == NULL)
637 lwp_MinStackSize = AFS_LWP_MINSTACKSIZE;
640 (AFS_LWP_MINSTACKSIZE >
641 atoi(value) ? AFS_LWP_MINSTACKSIZE : atoi(value));
647 LWP_INTERNALSIGNAL(void *event, int yield)
648 { /* signal the occurence of an event */
649 Debug(2, ("Entered LWP_SignalProcess"));
652 rc = Internal_Signal(event);
661 LWP_TerminateProcessSupport(void)
662 { /* terminate all LWP support */
665 Debug(0, ("Entered Terminate_Process_Support"));
666 if (lwp_init == NULL)
668 if (lwp_cpptr != LWPANCHOR.outerpid)
669 Abort_LWP("Terminate_Process_Support invoked from wrong process!");
670 for (i = 0; i < MAX_PRIORITIES; i++)
671 for_all_elts(cur, runnable[i], {
674 for_all_elts(cur, blocked, {
677 for_all_elts(cur, qwaiting, {
686 LWP_WaitProcess(void *event)
687 { /* wait on a single event */
690 Debug(2, ("Entered Wait_Process"));
692 return LWP_EBADEVENT;
695 return LWP_MwaitProcess(1, tempev);
699 LWP_MwaitProcess(int wcount, void *evlist[])
700 { /* wait on m of n events */
704 Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount));
706 if (evlist == NULL) {
708 return LWP_EBADCOUNT;
711 for (ecount = 0; evlist[ecount] != NULL; ecount++);
715 return LWP_EBADCOUNT;
720 if (wcount > ecount || wcount < 0) {
722 return LWP_EBADCOUNT;
724 if (ecount > lwp_cpptr->eventlistsize) {
726 lwp_cpptr->eventlist =
727 (void **)realloc(lwp_cpptr->eventlist,
728 ecount * sizeof(void *));
729 lwp_cpptr->eventlistsize = ecount;
731 for (i = 0; i < ecount; i++)
732 lwp_cpptr->eventlist[i] = evlist[i];
734 lwp_cpptr->status = WAITING;
736 move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked);
739 lwp_cpptr->wakevent = 0;
740 lwp_cpptr->waitcnt = wcount;
741 lwp_cpptr->eventcnt = ecount;
752 LWP_StackUsed(PROCESS pid, int *maxa, int *used)
754 *maxa = pid->stacksize;
755 *used = Stack_Used(pid->stack, *maxa);
762 * The following functions are strictly
763 * INTERNAL to the LWP support package.
769 struct lwp_context tempcontext;
771 Debug(0, ("Entered Abort_LWP"));
772 printf("***LWP: %s\n", msg);
773 printf("***LWP: Abort --- dumping PCBs ...\n");
777 if (LWPANCHOR.outersp == NULL)
780 savecontext(Exit_LWP, &tempcontext, LWPANCHOR.outersp);
785 Create_Process_Part2(void)
786 { /* creates a context for the new process */
789 Debug(2, ("Entered Create_Process_Part2"));
790 temp = lwp_cpptr; /* Get current process id */
791 savecontext(Dispatcher, &temp->context, NULL);
792 (*temp->ep) (temp->parm);
793 LWP_DestroyProcess(temp);
798 Delete_PCB(PROCESS pid)
799 { /* remove a PCB from the process list */
800 Debug(4, ("Entered Delete_PCB"));
802 (pid->blockflag || pid->status == WAITING
804 DESTROYED ? &blocked :
805 (pid->status == QWAITING) ? &qwaiting :
806 &runnable[pid->priority]));
807 LWPANCHOR.processcnt--;
813 Dump_One_Process(PROCESS pid)
817 printf("***LWP: Process Control Block at 0x%x\n", pid);
818 printf("***LWP: Name: %s\n", pid->name);
820 printf("***LWP: Initial entry point: 0x%x\n", pid->ep);
822 printf("BLOCKED and ");
823 switch (pid->status) {
840 printf("***LWP: Priority: %d \tInitial parameter: 0x%x\n", pid->priority,
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));
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]);
856 if (pid->wakevent > 0)
857 printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent);
863 purge_dead_pcbs(void)
865 for_all_elts(cur, blocked, {
866 if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur);}
871 int LWP_TraceProcesses = 0;
875 { /* Lightweight process dispatcher */
878 static int dispatch_count = 0;
880 if (LWP_TraceProcesses > 0) {
881 for (i = 0; i < MAX_PRIORITIES; i++) {
882 printf("[Priority %d, runnable (%d):", i, runnable[i].count);
883 for_all_elts(p, runnable[i], {
884 printf(" \"%s\"", p->name);
889 printf("[Blocked (%d):", blocked.count);
890 for_all_elts(p, blocked, {
891 printf(" \"%s\"", p->name);
895 printf("[Qwaiting (%d):", qwaiting.count);
896 for_all_elts(p, qwaiting, {
897 printf(" \"%s\"", p->name);
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 && lwp_cpptr->stack != NULL
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)) {
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))) {
922 printf("stackcheck = %u: stack = %u \n", lwp_cpptr->stackcheck,
923 *(int *)lwp_cpptr->stack);
924 printf("topstack = 0x%" AFS_PTR_FMT ": stackptr = 0x%" AFS_PTR_FMT ": stacksize = 0x%x\n",
925 (void *)(uintptr_t)lwp_cpptr->context.topstack,
926 (void *)(uintptr_t)lwp_cpptr->stack,
927 lwp_cpptr->stacksize);
929 switch (lwp_overflowAction) {
938 lwp_overflowAction = LWP_SOQUIET;
943 /* Move head of current runnable queue forward if current LWP is still in it. */
944 if (lwp_cpptr != NULL && 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 - 1; i >= 0; i--)
949 if (runnable[i].head != NULL)
953 Abort_LWP("No READY processes");
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);
960 #if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
962 Abort_LWP("PRE_Block not 1");
964 lwp_cpptr = runnable[i].head;
966 returnto(&lwp_cpptr->context);
968 return; /* not reachable */
971 /* Complain of a stack overflow to stderr without using stdio. */
973 Overflow_Complain(void)
977 char *msg1 = " LWP: stack overflow in process ";
980 currenttime = time(0);
981 timeStamp = ctime(¤ttime);
983 write(2, timeStamp, strlen(timeStamp));
985 write(2, msg1, strlen(msg1));
986 write(2, lwp_cpptr->name, strlen(lwp_cpptr->name));
987 write(2, msg2, strlen(msg2));
991 Dispose_of_Dead_PCB(PROCESS cur)
993 Debug(4, ("Entered Dispose_of_Dead_PCB"));
997 Internal_Signal(cur);
1008 Free_PCB(PROCESS pid)
1010 Debug(4, ("Entered Free_PCB"));
1011 if (pid->stack != NULL) {
1013 ("HWM stack usage: %d, [PCB at 0x%x]",
1014 Stack_Used(pid->stack, pid->stacksize), pid));
1015 #ifndef AFS_AIX32_ENV
1019 if (pid->eventlist != NULL)
1020 free(pid->eventlist);
1025 Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
1026 void *(*ep) (void *), void *parm, char *name)
1030 Debug(4, ("Entered Initialize_PCB"));
1032 while (((temp->name[i] = name[i]) != '\0') && (i < 31))
1034 temp->name[31] = '\0';
1035 temp->status = READY;
1036 temp->eventlist = (void **)malloc(EVINITSIZE * sizeof(void *));
1037 temp->eventlistsize = EVINITSIZE;
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)
1049 temp->stackcheck = *(int *)((temp->stack) + stacksize - 4);
1051 if (temp->stack != NULL)
1052 temp->stackcheck = *(int *)(temp->stack);
1056 temp->misc = NULL; /* currently unused */
1059 temp->lwp_rused = 0;
1060 temp->level = 1; /* non-preemptable */
1064 Internal_Signal(void *event)
1066 int rc = LWP_ENOWAIT;
1069 Debug(0, ("Entered Internal_Signal [event id 0x%x]", event));
1073 return LWP_EBADEVENT;
1074 for_all_elts(temp, blocked, {
1075 if (temp->status == WAITING)
1076 for (i = 0; i < temp->eventcnt; i++) {
1077 if (temp->eventlist[i] == event) {
1078 temp->eventlist[i] = NULL; rc = LWP_SUCCESS;
1079 Debug(0, ("Signal satisfied for PCB 0x%x", temp));
1080 if (--temp->waitcnt == 0) {
1081 temp->status = READY; temp->wakevent = i + 1;
1082 move(temp, &blocked, &runnable[temp->priority]); break;}
1090 /* This can be any unlikely pattern except 0x00010203 or the reverse. */
1091 #define STACKMAGIC 0xBADBADBA
1093 Initialize_Stack(char *stackptr, int stacksize)
1097 Debug(4, ("Entered Initialize_Stack"));
1098 if (lwp_stackUseEnabled)
1099 for (i = 0; i < stacksize; i++)
1100 stackptr[i] = i & 0xff;
1102 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1103 *(afs_int32 *) (stackptr + stacksize - 4) = STACKMAGIC;
1105 *(afs_int32 *) stackptr = STACKMAGIC;
1111 Stack_Used(char *stackptr, int stacksize)
1115 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
1116 if (*(afs_int32 *) (stackptr + stacksize - 4) == STACKMAGIC)
1119 for (i = stacksize - 1; i >= 0; i--)
1120 if ((unsigned char)stackptr[i] != (i & 0xff))
1125 if (*(afs_int32 *) stackptr == STACKMAGIC)
1128 for (i = 0; i < stacksize; i++)
1129 if ((unsigned char)stackptr[i] != (i & 0xff))
1130 return (stacksize - i);
1138 LWP_NewRock(int Tag, char *Value)
1139 /* Finds a free rock and sets its value to Value.
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.
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.
1152 struct rock *ra; /* rock array */
1154 ra = lwp_cpptr->lwp_rlist;
1156 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1157 if (ra[i].tag == Tag)
1158 return (LWP_EBADROCK);
1160 if (lwp_cpptr->lwp_rused < MAXROCKS) {
1161 ra[lwp_cpptr->lwp_rused].tag = Tag;
1162 ra[lwp_cpptr->lwp_rused].value = Value;
1163 lwp_cpptr->lwp_rused++;
1164 return (LWP_SUCCESS);
1166 return (LWP_ENOROCKS);
1171 LWP_GetRock(int Tag, char **Value)
1172 /* Obtains the pointer Value associated with the rock Tag of this LWP.
1174 * LWP_SUCCESS if specified rock exists and Value has been filled
1175 * LWP_EBADROCK rock specified does not exist
1181 ra = lwp_cpptr->lwp_rlist;
1183 for (i = 0; i < lwp_cpptr->lwp_rused; i++)
1184 if (ra[i].tag == Tag) {
1185 *Value = ra[i].value;
1186 return (LWP_SUCCESS);
1188 return (LWP_EBADROCK);
1192 #ifdef AFS_AIX32_ENV
1194 setlim(int limcon, uchar_t hard, int limit)
1198 (void)getrlimit(limcon, &rlim);
1200 limit = limit * 1024;
1202 rlim.rlim_max = limit;
1203 else if (limit == RLIM_INFINITY && geteuid() != 0)
1204 rlim.rlim_cur = rlim.rlim_max;
1206 rlim.rlim_cur = limit;
1208 /* Must use ulimit() due to Posix constraints */
1209 if (limcon == RLIMIT_FSIZE) {
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" : "");
1219 if (setrlimit(limcon, &rlim) < 0) {
1221 printf("Can't %s%s limit\n",
1222 limit == RLIM_INFINITY ? "remove" : "set",
1223 hard ? " hard" : "");
1233 LWP_NoYieldSignal(void *event)
1235 return (LWP_INTERNALSIGNAL(event, 0));
1239 LWP_SignalProcess(void *event)
1241 return (LWP_INTERNALSIGNAL(event, 1));