2 ****************************************************************************
3 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
5 * Permission to use, copy, modify, and distribute this software and its *
6 * documentation for any purpose and without fee is hereby granted, *
7 * provided that the above copyright notice appear in all copies and *
8 * that both that copyright notice and this permission notice appear in *
9 * supporting documentation, and that the name of IBM not be used in *
10 * advertising or publicity pertaining to distribution of the software *
11 * without specific, written prior permission. *
13 * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
15 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY *
16 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER *
17 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *
18 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
19 ****************************************************************************
22 /*******************************************************************\
24 * Information Technology Center *
25 * Carnegie-Mellon University *
28 \*******************************************************************/
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
37 #ifdef HAVE_SYS_MMAN_H
51 /* allocate externs here */
61 #include <sys/errno.h>
75 * Make sure that alignment and saving of data is right
78 #if defined(__alpha) || defined(__uxpv__) || defined(__sparcv9) || defined(__x86_64__)
85 * Space before first stack frame expressed in registers.
87 * This should maybe be a ABI specific value defined somewhere else.
91 #define STACK_HEADROOM 16
92 #elif defined(__s390__)
93 #define STACK_HEADROOM 24
95 #define STACK_HEADROOM 5
100 #define Debug(level, msg)\
101 if (lwp_debug && lwp_debug >= level) {\
102 printf("***LWP (%p): ", lwp_cpptr);\
108 #define Debug(level, msg)
113 static void Abort_LWP(char *msg
) ;
114 static void Dispatcher(void);
115 static void Create_Process_Part2(void);
116 static void purge_dead_pcbs(void) ;
117 static void Overflow_Complain (void) ;
118 static void Dispose_of_Dead_PCB (PROCESS cur
) ;
119 static void Free_PCB(PROCESS pid
) ;
120 static void Exit_LWP(void);
121 static void Initialize_PCB(PROCESS temp
, int priority
, char *stack
,
122 int stacksize
, void (*ep
)() , char *parm
,
124 static long Initialize_Stack(char *stackptr
,int stacksize
) ;
125 static int Stack_Used(char *stackptr
, int stacksize
) ;
126 static int Internal_Signal(char *event
) ;
127 char (*RC_to_ASCII());
129 #define MAX_PRIORITIES (LWP_MAX_PRIORITY+1)
134 } runnable
[MAX_PRIORITIES
], blocked
;
136 * Invariant for runnable queues: The head of each queue points to the
137 * currently running process if it is in that queue, or it points to the
138 * next process in that queue that should run.
141 /* Offset of stack field within pcb -- used by stack checking stuff */
144 /* special user-tweakable option for AIX */
145 int lwp_MaxStackSize
= 32768;
147 /* biggest LWP stack created so far */
148 int lwp_MaxStackSeen
= 0;
150 /* Stack checking action */
151 int lwp_overflowAction
= LWP_SOABORT
;
153 /* Controls stack size counting. */
154 int lwp_stackUseEnabled
= 1;
159 lwp_remove(PROCESS p
, struct QUEUE
*q
)
161 /* Special test for only element on queue */
165 /* Not only element, do normal remove */
166 p
-> next
-> prev
= p
-> prev
;
167 p
-> prev
-> next
= p
-> next
;
169 /* See if head pointing to this element */
170 if (q
->head
== p
) q
-> head
= p
-> next
;
172 p
-> next
= p
-> prev
= NULL
;
176 insert(PROCESS p
, struct QUEUE
*q
)
178 if (q
->head
== NULL
) { /* Queue is empty */
180 p
-> next
= p
-> prev
= p
;
181 } else { /* Regular insert */
182 p
-> prev
= q
-> head
-> prev
;
183 q
-> head
-> prev
-> next
= p
;
184 q
-> head
-> prev
= p
;
185 p
-> next
= q
-> head
;
191 move(PROCESS p
, struct QUEUE
*from
, struct QUEUE
*to
)
199 #define for_all_elts(var, q, body)\
201 PROCESS var, _NEXT_;\
203 for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\
204 _NEXT_ = var -> next;\
210 /*****************************************************************************\
212 * Following section documents the Assembler interfaces used by LWP code *
214 \*****************************************************************************/
217 * savecontext(int (*ep)(), struct lwp_context *savearea, char *sp);
218 * XXX - the above prototype is a lie.
219 * Stub for Assembler routine that will
220 * save the current SP value in the passed
221 * context savearea and call the function
222 * whose entry point is in ep. If the sp
223 * parameter is NULL, the current stack is
224 * used, otherwise sp becomes the new stack
227 * returnto(struct lwp_context *savearea);
229 * Stub for Assembler routine that will
230 * restore context from a passed savearea
231 * and return to the restored C frame.
235 void savecontext(void (*)(), struct lwp_context
*, char *);
236 void returnto(struct lwp_context
*);
238 /* Macro to force a re-schedule. Strange name is historical */
239 #define Set_LWP_RC() savecontext(Dispatcher, &lwp_cpptr->context, NULL)
241 static struct lwp_ctl
*lwp_init
= 0;
247 (tp
=lwp_cpptr
) -> status
= QWAITING
;
248 lwp_remove(tp
, &runnable
[tp
->priority
]);
254 LWP_QSignal(PROCESS pid
)
256 if (pid
->status
== QWAITING
) {
258 insert(pid
, &runnable
[pid
->priority
]);
261 else return LWP_ENOWAIT
;
266 reserveFromStack(size
)
275 #if defined(LWP_REDZONE) && defined(HAVE_MMAP)
278 * Redzone protection of stack
280 * We protect one page before and one after the stack to make sure
281 * none over/under runs the stack. The size of the stack is saved one
282 * the first page together with a magic number to make sure we free
285 * If the operating system doesn't support mmap, turn redzone off in
289 #define P_SIZE_OFFSET 16
290 #define P_MAGIC 0x7442e938
293 lwp_stackmalloc(size_t size
)
295 char *p
, *p_after
, *p_before
;
296 size_t pagesize
= getpagesize();
297 int pages
= (size
- 1) / pagesize
+ 1;
302 #ifndef _PATH_DEV_ZERO
303 #define _PATH_DEV_ZERO "/dev/zero"
305 fd
= open(_PATH_DEV_ZERO
, O_RDWR
, 0644);
308 p
= mmap(0, (pages
+ 2) * pagesize
, PROT_READ
| PROT_WRITE
,
309 MAP_PRIVATE
| MAP_ANON
, fd
, 0);
310 if (p
== MAP_FAILED
) {
317 p_after
= p
+ pages
* pagesize
;
319 /* store the magic and the length in the first page */
321 *((unsigned long *)p_before
) = P_MAGIC
;
322 *((unsigned long *)(p_before
+ P_SIZE_OFFSET
)) = (pages
+ 2) * pagesize
;
326 if (mprotect(p_before
, pagesize
, PROT_NONE
) < 0) {
327 perror("mprotect before");
330 if (mprotect(p_after
, pagesize
, PROT_NONE
) < 0) {
331 perror("mprotect after");
338 lwp_stackfree(void *ptr
, size_t len
)
340 size_t pagesize
= getpagesize();
345 if (((size_t)ptr
) % pagesize
!= 0)
348 realptr
= ((char *)ptr
) - pagesize
;
350 if (mprotect(realptr
, pagesize
, PROT_READ
) < 0) {
355 magic
= *((unsigned long *)realptr
);
356 if (magic
!= P_MAGIC
)
358 length
= *((unsigned long *)(realptr
+ P_SIZE_OFFSET
));
359 if (len
!= length
- 2 * pagesize
)
362 if (munmap(realptr
, length
) < 0) {
371 lwp_stackmalloc(size_t size
)
377 lwp_stackfree(void *ptr
, size_t len
)
384 LWP_CreateProcess(void (*ep
)(), int stacksize
, int priority
,
385 char *parm
, const char *name
, PROCESS
*pid
)
389 static char *stackptr
= 0;
395 * on some systems (e.g. hpux), a minimum usable stack size has
398 if (stacksize
< AFS_LWP_MINSTACKSIZE
)
399 stacksize
= AFS_LWP_MINSTACKSIZE
;
401 /* more stack size computations; keep track of for IOMGR */
402 if (lwp_MaxStackSeen
< stacksize
)
403 lwp_MaxStackSeen
= stacksize
;
405 Debug(0, ("Entered LWP_CreateProcess"))
406 /* Throw away all dead process control blocks */
412 temp
= (PROCESS
) malloc(sizeof(struct lwp_pcb
));
418 /* align stacksize */
419 stacksize
= REGSIZE
* ((stacksize
+REGSIZE
-1) / REGSIZE
);
424 * The following signal action for AIX is necessary so that in case of a
425 * crash (i.e. core is generated) we can include the user's data section
426 * in the core dump. Unfortunately, by default, only a partial core is
427 * generated which, in many cases, isn't too useful.
429 * We also do it here in case the main program forgets to do it.
431 struct sigaction nsa
;
432 extern int geteuid();
434 sigemptyset(&nsa
.sa_mask
);
435 nsa
.sa_handler
= SIG_DFL
;
436 nsa
.sa_flags
= SA_FULLDUMP
;
437 sigaction(SIGSEGV
, &nsa
, NULL
);
440 * First we need to increase the default resource limits,
441 * if necessary, so that we can guarantee that we have the
442 * resources to create the core file, but we can't always
443 * do it as an ordinary user.
446 setlim(RLIMIT_FSIZE
, 0, 1048575); /* 1 Gig */
447 setlim(RLIMIT_STACK
, 0, 65536); /* 65 Meg */
448 setlim(RLIMIT_CORE
, 0, 131072); /* 131 Meg */
451 * Now reserve in one scoop all the stack space that will be used
452 * by the particular application's main (i.e. non-lwp) body. This
453 * is plenty space for any of our applications.
455 stackptr
= reserveFromStack(lwp_MaxStackSize
);
457 stackptr
-= stacksize
;
458 #else /* !AFS_AIX32_ENV */
459 if ((stackptr
= (char *) lwp_stackmalloc(stacksize
)) == NULL
) {
463 #endif /* AFS_AIX32_ENV */
464 if (priority
< 0 || priority
>= MAX_PRIORITIES
) {
468 Initialize_Stack(stackptr
, stacksize
);
469 Initialize_PCB(temp
, priority
, stackptr
, stacksize
, ep
, parm
, name
);
470 insert(temp
, &runnable
[priority
]);
474 Abort_LWP("PRE_Block not 0");
476 /* Gross hack: beware! */
480 savecontext(Create_Process_Part2
, &temp2
->context
,
481 stackptr
+ (REGSIZE
* STACK_HEADROOM
));
483 savecontext(Create_Process_Part2
, &temp2
->context
,
484 stackptr
+ stacksize
- (REGSIZE
* STACK_HEADROOM
));
486 /* End of gross hack */
493 /* returns pid of current process */
495 LWP_CurrentProcess(PROCESS
*pid
)
497 Debug(0, ("Entered Current_Process"))
505 #define LWPANCHOR (*lwp_init)
507 /* destroy a lightweight process */
509 LWP_DestroyProcess(PROCESS pid
)
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
);
523 savecontext(Dispatcher
, &(temp
-> context
),
524 &(LWPANCHOR
.dsptchstack
[(REGSIZE
* STACK_HEADROOM
)]));
526 savecontext(Dispatcher
, &(temp
-> context
),
527 &(LWPANCHOR
.dsptchstack
[(sizeof LWPANCHOR
.dsptchstack
)
528 - (REGSIZE
* STACK_HEADROOM
)]));
536 /* explicit voluntary preemption */
538 LWP_DispatchProcess(void)
540 Debug(2, ("Entered Dispatch_Process"))
549 static void Dump_One_Process(PROCESS pid
);
556 for (i
=0; i
<MAX_PRIORITIES
; i
++)
557 for_all_elts(x
, runnable
[i
], {
558 printf("[Priority %d]\n", i
);
561 for_all_elts(x
, blocked
, { Dump_One_Process(x
); })
563 printf("***LWP: LWP support not initialized\n");
567 /* returns process priority */
569 LWP_GetProcessPriority(PROCESS pid
, int *priority
)
571 Debug(0, ("Entered Get_Process_Priority"))
573 *priority
= pid
-> priority
;
580 LWP_InitializeProcessSupport(int priority
, PROCESS
*pid
)
583 struct lwp_pcb dummy
;
586 Debug(0, ("Entered LWP_InitializeProcessSupport"))
587 if (lwp_init
!= NULL
) return LWP_SUCCESS
;
589 /* Set up offset for stack checking -- do this as soon as possible */
590 stack_offset
= (char *) &dummy
.stack
- (char *) &dummy
;
592 if (priority
>= MAX_PRIORITIES
) return LWP_EBADPRI
;
593 for (i
=0; i
<MAX_PRIORITIES
; i
++) {
594 runnable
[i
].head
= NULL
;
595 runnable
[i
].count
= 0;
599 lwp_init
= (struct lwp_ctl
*) malloc(sizeof(struct lwp_ctl
));
600 temp
= (PROCESS
) malloc(sizeof(struct lwp_pcb
));
601 if (lwp_init
== NULL
|| temp
== NULL
)
602 Abort_LWP("Insufficient Storage to Initialize LWP Support");
603 LWPANCHOR
.processcnt
= 1;
604 LWPANCHOR
.outerpid
= temp
;
605 LWPANCHOR
.outersp
= NULL
;
606 Initialize_PCB(temp
, priority
, NULL
, 0, NULL
, NULL
,
607 "Main Process [created by LWP]");
608 insert(temp
, &runnable
[priority
]);
609 savecontext(Dispatcher
, &temp
->context
, NULL
);
610 LWPANCHOR
.outersp
= temp
-> context
.topstack
;
616 /* signal the occurence of an event */
618 LWP_INTERNALSIGNAL(void *event
, int yield
)
620 Debug(2, ("Entered LWP_SignalProcess"))
623 rc
= Internal_Signal(event
);
624 if (yield
) Set_LWP_RC();
630 /* terminate all LWP support */
632 LWP_TerminateProcessSupport(void)
636 Debug(0, ("Entered Terminate_Process_Support"))
637 if (lwp_init
== NULL
) return LWP_EINIT
;
638 if (lwp_cpptr
!= LWPANCHOR
.outerpid
)
639 Abort_LWP("Terminate_Process_Support invoked from wrong process!");
640 for (i
=0; i
<MAX_PRIORITIES
; i
++)
641 for_all_elts(cur
, runnable
[i
], { Free_PCB(cur
); })
642 for_all_elts(cur
, blocked
, { Free_PCB(cur
); })
648 /* wait on m of n events */
650 LWP_MwaitProcess(int wcount
, char *evlist
[])
655 Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount
))
657 if (evlist
== NULL
) {
659 return LWP_EBADCOUNT
;
662 for (ecount
= 0; evlist
[ecount
] != NULL
; ecount
++) ;
666 return LWP_EBADCOUNT
;
671 if (wcount
>ecount
|| wcount
<0) {
673 return LWP_EBADCOUNT
;
675 if (ecount
> lwp_cpptr
->eventlistsize
) {
677 lwp_cpptr
->eventlist
= (char **)realloc(lwp_cpptr
->eventlist
,
678 ecount
*sizeof(char *));
679 lwp_cpptr
->eventlistsize
= ecount
;
681 for (i
=0; i
<ecount
; i
++) lwp_cpptr
-> eventlist
[i
] = evlist
[i
];
683 lwp_cpptr
-> status
= WAITING
;
685 move(lwp_cpptr
, &runnable
[lwp_cpptr
->priority
], &blocked
);
687 lwp_cpptr
-> wakevent
= 0;
688 lwp_cpptr
-> waitcnt
= wcount
;
689 lwp_cpptr
-> eventcnt
= ecount
;
699 /* wait on a single event */
701 LWP_WaitProcess(void *event
)
705 Debug(2, ("Entered Wait_Process"))
706 if (event
== NULL
) return LWP_EBADEVENT
;
709 return LWP_MwaitProcess(1, tempev
);
713 LWP_StackUsed(PROCESS pid
, int *max
, int *used
)
715 *max
= pid
-> stacksize
;
716 *used
= Stack_Used(pid
->stack
, *max
);
723 * The following functions are strictly
724 * INTERNAL to the LWP support package.
730 struct lwp_context tempcontext
;
732 Debug(0, ("Entered Abort_LWP"))
733 printf("***LWP: %s\n",msg
);
734 printf("***LWP: Abort --- dumping PCBs ...\n");
738 if (LWPANCHOR
.outersp
== NULL
)
741 savecontext(Exit_LWP
, &tempcontext
, LWPANCHOR
.outersp
);
744 /* creates a context for the new process */
746 Create_Process_Part2(void)
750 Debug(2, ("Entered Create_Process_Part2"))
751 temp
= lwp_cpptr
; /* Get current process id */
752 savecontext(Dispatcher
, &temp
->context
, NULL
);
753 (*temp
->ep
)(temp
->parm
);
754 LWP_DestroyProcess(temp
);
757 /* remove a PCB from the process list */
759 Delete_PCB(PROCESS pid
)
761 Debug(4, ("Entered Delete_PCB"))
762 lwp_remove(pid
, (pid
->blockflag
||
763 pid
->status
==WAITING
||
764 pid
->status
==DESTROYED
766 : &runnable
[pid
->priority
]));
767 LWPANCHOR
.processcnt
--;
772 Dump_One_Process(PROCESS pid
)
776 printf("***LWP: Process Control Block at %p\n", pid
);
777 printf("***LWP: Name: %s\n", pid
->name
);
779 printf("***LWP: Initial entry point: %p\n", pid
->ep
);
780 if (pid
->blockflag
) printf("BLOCKED and ");
781 switch (pid
->status
) {
782 case READY
: printf("READY"); break;
783 case WAITING
: printf("WAITING"); break;
784 case DESTROYED
: printf("DESTROYED"); break;
785 default: printf("unknown");
788 printf("***LWP: Priority: %d \tInitial parameter: %p\n",
789 pid
->priority
, pid
->parm
);
790 if (pid
->stacksize
!= 0) {
791 printf("***LWP: Stacksize: %d \tStack base address: %p\n",
792 pid
->stacksize
, pid
->stack
);
793 printf("***LWP: HWM stack usage: ");
794 printf("%d\n", Stack_Used(pid
->stack
,pid
->stacksize
));
796 printf("***LWP: Current Stack Pointer: %p\n", pid
->context
.topstack
);
797 if (pid
->eventcnt
> 0) {
798 printf("***LWP: Number of events outstanding: %d\n", pid
->waitcnt
);
799 printf("***LWP: Event id list:");
800 for (i
=0;i
<pid
->eventcnt
;i
++)
801 printf(" %p", pid
->eventlist
[i
]);
805 printf("***LWP: Number of last wakeup event: %d\n", pid
->wakevent
);
810 purge_dead_pcbs(void)
812 for_all_elts(cur
, blocked
, {
813 if (cur
->status
== DESTROYED
) Dispose_of_Dead_PCB(cur
);
817 int LWP_TraceProcesses
= 0;
819 /* Lightweight process dispatcher */
825 static int dispatch_count
= 0;
827 if (LWP_TraceProcesses
> 0) {
828 for (i
=0; i
<MAX_PRIORITIES
; i
++) {
829 printf("[Priority %d, runnable (%d):", i
, runnable
[i
].count
);
830 for_all_elts(p
, runnable
[i
], {
831 printf(" \"%s\"", p
->name
);
835 printf("[Blocked (%d):", blocked
.count
);
836 for_all_elts(p
, blocked
, {
837 printf(" \"%s\"", p
->name
);
844 * Check for stack overflow if this lwp has a stack. Check for
845 * the guard word at the front of the stack being damaged and
846 * for the stack pointer being below the front of the stack.
847 * WARNING! This code assumes that stacks grow downward.
850 /* Fix this (stackcheck at other end of stack???) */
851 if (lwp_cpptr
!= NULL
&& lwp_cpptr
->stack
!= NULL
852 && (lwp_cpptr
->stackcheck
!=
853 *(long *)((lwp_cpptr
->stack
) + lwp_cpptr
->stacksize
- 4)
854 || lwp_cpptr
->context
.topstack
>
855 lwp_cpptr
->stack
+ lwp_cpptr
->stacksize
- 4)) {
857 if (lwp_cpptr
!= NULL
&& lwp_cpptr
->stack
!= NULL
858 && (lwp_cpptr
->stackcheck
!= *(long *)(lwp_cpptr
->stack
)
859 || lwp_cpptr
->context
.topstack
< lwp_cpptr
->stack
)) {
862 printf("stackcheck = %lul: stack = %lul\n",
863 lwp_cpptr
->stackcheck
,
864 *(long *)lwp_cpptr
->stack
);
865 printf("topstack = %lul\n", *(long *)lwp_cpptr
->context
.topstack
);
867 switch (lwp_overflowAction
) {
876 lwp_overflowAction
= LWP_SOQUIET
;
883 * Move head of current runnable queue forward if current LWP
886 if (lwp_cpptr
!= NULL
&& lwp_cpptr
== runnable
[lwp_cpptr
->priority
].head
)
887 runnable
[lwp_cpptr
->priority
].head
= runnable
[lwp_cpptr
->priority
].head
->next
;
889 /* Find highest priority with runnable processes. */
890 for (i
= MAX_PRIORITIES
- 1; i
>= 0; i
--)
891 if (runnable
[i
].head
!= NULL
)
895 Abort_LWP("No READY processes");
898 if (LWP_TraceProcesses
> 0)
899 printf("Dispatch %d [PCB at %p] \"%s\"\n",
902 runnable
[i
].head
->name
);
904 if (PRE_Block
!= 1) Abort_LWP("PRE_Block not 1");
905 lwp_cpptr
= runnable
[i
].head
;
907 returnto(&lwp_cpptr
->context
);
910 /* Complain of a stack overflow to stderr without using stdio. */
912 Overflow_Complain (void)
914 static char msg1
[] = "LWP: stack overflow in process ";
915 static char msg2
[] = "!\n";
917 write (2, msg1
, sizeof(msg1
) - 1);
918 write (2, lwp_cpptr
->name
, strlen(lwp_cpptr
->name
));
919 write (2, msg2
, sizeof(msg2
) - 1);
923 Dispose_of_Dead_PCB (PROCESS cur
)
925 Debug(4, ("Entered Dispose_of_Dead_PCB"))
929 Internal_Signal(cur);
940 Free_PCB(PROCESS pid
)
942 Debug(4, ("Entered Free_PCB"))
943 if (pid
-> stack
!= NULL
) {
944 Debug(0, ("HWM stack usage: %d, [PCB at %p]",
945 Stack_Used(pid
->stack
,pid
->stacksize
), pid
))
946 lwp_stackfree(pid
-> stack
, pid
->stacksize
);
948 if (pid
->eventlist
!= NULL
) free(pid
->eventlist
);
953 Initialize_PCB(PROCESS temp
, int priority
, char *stack
, int stacksize
,
954 void (*ep
)(), char *parm
, const char *name
)
956 Debug(4, ("Entered Initialize_PCB"))
958 strncpy(temp
-> name
, name
, sizeof(temp
-> name
));
959 temp
-> name
[sizeof(temp
-> name
) - 1] = '\0';
961 temp
-> name
[0] = '\0';
962 temp
-> status
= READY
;
963 temp
-> eventlist
= (char **)malloc(EVINITSIZE
*sizeof(char *));
964 temp
-> eventlistsize
= EVINITSIZE
;
965 temp
-> eventcnt
= 0;
966 temp
-> wakevent
= 0;
968 temp
-> blockflag
= 0;
969 temp
-> iomgrRequest
= 0;
970 temp
-> priority
= priority
;
971 temp
-> index
= lwp_nextindex
++;
972 temp
-> stack
= stack
;
973 temp
-> stacksize
= stacksize
;
975 if (temp
-> stack
!= NULL
)
976 temp
-> stackcheck
= *(long *) ((temp
-> stack
) + stacksize
- REGSIZE
);
978 if (temp
-> stack
!= NULL
)
979 temp
-> stackcheck
= *(long *) (temp
-> stack
);
983 temp
-> misc
= NULL
; /* currently unused */
987 temp
-> level
= 1; /* non-preemptable */
991 Internal_Signal(char *event
)
993 int rc
= LWP_ENOWAIT
;
996 Debug(0, ("Entered Internal_Signal [event id %p]", event
))
997 if (!lwp_init
) return LWP_EINIT
;
998 if (event
== NULL
) return LWP_EBADEVENT
;
999 for_all_elts(temp
, blocked
, {
1000 if (temp
->status
== WAITING
)
1001 for (i
=0; i
< temp
->eventcnt
; i
++) {
1002 if (temp
-> eventlist
[i
] == event
) {
1003 temp
-> eventlist
[i
] = NULL
;
1005 Debug(0, ("Signal satisfied for PCB %p", temp
))
1006 if (--temp
->waitcnt
== 0) {
1007 temp
-> status
= READY
;
1008 temp
-> wakevent
= i
+1;
1009 move(temp
, &blocked
, &runnable
[temp
->priority
]);
1018 /* This can be any unlikely pattern except 0x00010203 or the reverse. */
1019 #define STACKMAGIC 0xBADBADBA
1021 Initialize_Stack(char *stackptr
, int stacksize
)
1025 Debug(4, ("Entered Initialize_Stack"))
1026 if (lwp_stackUseEnabled
)
1027 for (i
=0; i
<stacksize
; i
++)
1028 stackptr
[i
] = i
&0xff;
1031 *(long *)(stackptr
+ stacksize
- 4) = STACKMAGIC
;
1033 *(long *)stackptr
= STACKMAGIC
;
1035 return 0; /* XXX - added. No clue what it should be */
1039 Stack_Used(char *stackptr
, int stacksize
)
1044 if (*(long *) (stackptr
+ stacksize
- 4) == STACKMAGIC
)
1047 for (i
= stacksize
- 1; i
>= 0 ; i
--)
1048 if ((unsigned char) stackptr
[i
] != (i
& 0xff))
1053 if (*(long *) stackptr
== STACKMAGIC
)
1056 for (i
= 0; i
< stacksize
; i
++)
1057 if ((unsigned char) stackptr
[i
] != (i
& 0xff))
1058 return (stacksize
- i
);
1066 * Finds a free rock and sets its value to Value.
1068 * LWP_SUCCESS Rock did not exist and a new one was used
1069 * LWP_EBADROCK Rock already exists.
1070 * LWP_ENOROCKS All rocks are in use.
1072 * From the above semantics, you can only set a rock value once.
1073 * This is specificallY to prevent multiple users of the LWP package from
1074 * accidentally using the same Tag value and clobbering others. You can always
1075 * use one level of indirection to obtain a rock whose contents can change.
1079 LWP_NewRock(int Tag
, char *Value
)
1082 struct rock
*ra
; /* rock array */
1084 ra
= lwp_cpptr
->rlist
;
1086 for (i
= 0; i
< lwp_cpptr
->rused
; i
++)
1087 if (ra
[i
].tag
== Tag
) return(LWP_EBADROCK
);
1089 if (lwp_cpptr
->rused
< MAXROCKS
)
1091 ra
[lwp_cpptr
->rused
].tag
= Tag
;
1092 ra
[lwp_cpptr
->rused
].value
= Value
;
1094 return(LWP_SUCCESS
);
1096 else return(LWP_ENOROCKS
);
1100 * Obtains the pointer Value associated with the rock Tag of this LWP.
1102 * LWP_SUCCESS if specified rock exists and Value has been filled
1103 * LWP_EBADROCK rock specified does not exist
1106 LWP_GetRock(int Tag
, char **Value
)
1111 ra
= lwp_cpptr
->rlist
;
1113 for (i
= 0; i
< lwp_cpptr
->rused
; i
++) {
1114 if (ra
[i
].tag
== Tag
) {
1115 *Value
= ra
[i
].value
;
1116 return(LWP_SUCCESS
);
1119 return(LWP_EBADROCK
);
1123 #ifdef AFS_AIX32_ENV
1124 setlim(limcon
, hard
, limit
)
1130 (void) getrlimit(limcon
, &rlim
);
1132 limit
= limit
* 1024;
1134 rlim
.rlim_max
= limit
;
1135 else if (limit
== RLIM_INFINITY
&& geteuid() != 0)
1136 rlim
.rlim_cur
= rlim
.rlim_max
;
1138 rlim
.rlim_cur
= limit
;
1140 /* Must use ulimit() due to Posix constraints */
1141 if (limcon
== RLIMIT_FSIZE
) {
1142 if (ulimit(UL_SETFSIZE
, ((hard
? rlim
.rlim_max
: rlim
.rlim_cur
) / 512)) < 0) {
1143 printf("Can't %s%s limit\n",
1144 limit
== RLIM_INFINITY
? "remove" : "set", hard
? " hard" : "");
1148 if (setrlimit(limcon
, &rlim
) < 0) {
1150 printf("Can't %s%s limit\n",
1151 limit
== RLIM_INFINITY
? "remove" : "set", hard
? " hard" : "");
1161 * Print the specific limit out
1163 plim(name
, lc
, hard
)
1171 printf("%s \t", name
);
1172 (void) getrlimit(lc
, &rlim
);
1173 lim
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
1174 if (lim
== RLIM_INFINITY
)
1175 printf("unlimited");
1176 printf("%d %s", lim
/ 1024, "kbytes");