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
12 /*******************************************************************\
14 * Information Technology Center *
15 * Carnegie-Mellon University *
19 \*******************************************************************/
23 IO Manager routines & server process for VICE server.
26 #include <afs/param.h>
31 extern void lwp_abort(void);
33 #include <unistd.h> /* select() prototype */
34 #include <sys/types.h> /* fd_set on older platforms */
35 #include <sys/time.h> /* struct timeval, select() prototype */
37 # include <sys/select.h> /* fd_set on newer platforms */
40 #endif /* AFS_NT40_ENV */
48 #if defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
50 void IOMGR_Initialize() /* noop */
53 void IOMGR_Sleep (seconds)
60 assert(pthread_mutex_unlock(&lwp_mutex) == 0);
61 assert(pthread_delay_np(&itv) == 0);
62 assert(pthread_mutex_lock(&lwp_mutex) == 0);
68 extern void *malloc();
69 #endif /* AFS_DECOSF_ENV */
71 typedef unsigned char bool;
76 #define MIN(a,b) ((a)>(b)) ? b : a
79 static int SignalSignals();
81 /********************************\
83 * Stuff for managing IoRequests *
85 \********************************/
89 /* Pid of process making request (for use in IOMGR_Cancel */
92 /* Descriptor masks for requests */
98 struct TM_Elem timeout;
100 /* Result of select call */
105 /********************************\
107 * Stuff for managing signals *
109 \********************************/
111 #define badsig(signo) (((signo) <= 0) || ((signo) >= NSIG))
112 #define mysigmask(signo) (1 << ((signo)-1))
115 fd_set openMask; /* mask of open files on an IOMGR abort */
116 static afs_int32 sigsHandled; /* sigmask(signo) is on if we handle signo */
117 static int anySigsDelivered; /* true if any have been delivered. */
119 static struct sigaction oldActions[NSIG]; /* the old signal vectors */
121 static char *sigEvents[NSIG]; /* the event to do an LWP signal on */
122 static int sigDelivered[NSIG]; /* True for signals delivered so far.
123 This is an int array to make sure
124 there are no conflicts when trying
126 /* software 'signals' */
128 static int (*sigProc[NSOFTSIG])();
129 static char *sigRock[NSOFTSIG];
132 static struct IoRequest *iorFreeList = 0;
134 static struct TM_Elem *Requests; /* List of requests */
135 static struct timeval iomgr_timeout; /* global so signal handler can zap it */
137 /* stuff for debugging */
138 static int iomgr_errno;
139 static struct timeval iomgr_badtv;
140 static PROCESS iomgr_badpid;
141 static void SignalIO(int fds, fd_set *rfds, fd_set *wfds, fd_set *efs,
144 /* fd_set pool managment.
145 * Use the pool instead of creating fd_set's on the stack. fd_set's can be
146 * 2K in size, so making three could put 6K in the limited space of an LWP
149 struct IOMGR_fd_set {
150 struct IOMGR_fd_set *next;
151 } *iomgrFreeFDSets = (struct IOMGR_fd_set*)0;
154 * Return fd_set to the free list.
156 void IOMGR_FreeFDSet(fd_set *s)
158 struct IOMGR_fd_set *t = (struct IOMGR_fd_set *)s;
160 t->next = iomgrFreeFDSets;
165 * returns a zeroed fd_set or null if could not malloc one.
167 fd_set *IOMGR_AllocFDSet(void)
169 struct IOMGR_fd_set *t;
170 if (iomgrFreeFDSets) {
172 iomgrFreeFDSets = iomgrFreeFDSets->next;
175 t = (struct IOMGR_fd_set *)malloc(sizeof(fd_set));
185 #define FreeRequest(x) ((x)->result = (long) iorFreeList, iorFreeList = (x))
187 static struct IoRequest *NewRequest()
189 struct IoRequest *request;
191 if (request=iorFreeList)
192 iorFreeList = (struct IoRequest *) (request->result);
193 else request = (struct IoRequest *) malloc(sizeof(struct IoRequest));
195 memset((char*)request, 0, sizeof(struct IoRequest));
199 #define Purge(list) FOR_ALL_ELTS(req, list, { free(req->BackPointer); })
202 /* FD_SET support routines. All assume the fd_set size is a multiple of an int
203 * so we can at least do logical operations on ints instead of chars.
205 * For each routine, nfds is the highest bit set in either fd_set, starting
209 #define FD_N_ZERO(A, x) FD_ZERO(x)
211 #define FDS_P_POS (sizeof(int)*8)
212 #define INTS_PER_FDS(x) (((x)+(FDS_P_POS-1)) / FDS_P_POS)
213 #define FD_N_ZERO(nfds, x) bzero((char*)(x), (INTS_PER_FDS(nfds))*sizeof(int))
216 #if defined(AFS_LINUX22_ENV) && (__GLIBC_MINOR__ > 0)
217 /* Build for both glibc 2.0.x and 2.1.x */
218 #define FDS_BITS __fds_bits
220 #define FDS_BITS fds_bits
223 /* FDSetCmp - returns 1 if any bits in fd_set1 are also set in fd_set2.
224 * If nfds is 0, or one of the fd_sets is null return 0 (since there is no bit
225 * set in both fd_sets).
227 static int FDSetCmp(int nfds, fd_set *fd_set1, fd_set *fd_set2)
231 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
235 if (fd_set1->fd_count == 0 || fd_set2->fd_count == 0)
238 for (i=0; i<fd_set1->fd_count; i++) {
239 for (j=0; j<fd_set2->fd_count; j++) {
240 if (fd_set1->fd_array[i] == fd_set2->fd_array[j])
248 j = INTS_PER_FDS(nfds);
249 for (i=0; i<j; i++) {
250 if (fd_set1->FDS_BITS[i] & fd_set2->FDS_BITS[i])
257 /* FDSetSet - set bits from fd_set2 into fd_set1
259 static void FDSetSet(int nfds, fd_set *fd_set1, fd_set *fd_set2)
263 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
267 if (fd_set2->fd_count==0)
270 for (i=0; i<fd_set2->fd_count; i++)
271 FD_SET(fd_set2->fd_array[i], fd_set1);
276 n = INTS_PER_FDS(nfds);
277 for (i=0; i<n; i++) {
278 fd_set1->FDS_BITS[i] |= fd_set2->FDS_BITS[i];
283 /* FDSetAnd - fd_set1 <- fd_set1 & fd_set2.
286 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
291 if (fd_set1 == NULL || fd_set1->fd_count == 0)
294 if (fd_set2 == NULL || fd_set2->fd_count == 0) {
299 for (i=0; i<fd_set2->fd_count; i++) {
300 if (FD_ISSET(fd_set2->fd_array[i], fd_set1))
301 FD_SET(fd_set2->fd_array[i], &tmpset);
307 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
311 if (nfds == 0 || fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
314 n = INTS_PER_FDS(nfds);
315 for (i=0; i<n; i++) {
316 fd_set1->FDS_BITS[i] &= fd_set2->FDS_BITS[i];
321 /* FDSetEmpty - return true if fd_set is empty
323 static int FDSetEmpty(int nfds, fd_set *fds)
331 if (fds == (fd_set*)0)
335 if (fds->fd_count == 0)
340 n = INTS_PER_FDS(nfds);
342 for (i=n-1; i>=0; i--) {
343 if (fds->FDS_BITS[i])
354 /* The IOMGR process */
357 * Important invariant: process->iomgrRequest is null iff request not in timer
359 * also, request->pid is valid while request is in queue,
360 * also, don't signal selector while request in queue, since selector frees
364 /* These are not declared in IOMGR so that they don't use up 6K of stack. */
365 static fd_set IOMGR_readfds, IOMGR_writefds, IOMGR_exceptfds;
366 static int IOMGR_nfds = 0;
368 static int IOMGR(void *dummy)
372 struct TM_Elem *earliest;
373 struct timeval timeout, junk;
379 FD_ZERO(&IOMGR_readfds);
380 FD_ZERO(&IOMGR_writefds);
381 FD_ZERO(&IOMGR_exceptfds);
384 /* Wake up anyone who has expired or who has received a
385 Unix signal between executions. Keep going until we
388 woke_someone = FALSE;
389 /* Wake up anyone waiting on signals. */
390 /* Note: SignalSignals() may yield! */
391 if (anySigsDelivered && SignalSignals ())
393 FT_GetTimeOfDay(&junk, 0); /* force accurate time check */
396 register struct IoRequest *req;
397 struct TM_Elem *expired;
398 expired = TM_GetExpired(Requests);
399 if (expired == NULL) break;
401 req = (struct IoRequest *) expired -> BackPointer;
403 if (lwp_debug != 0) puts("[Polling SELECT]");
406 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
407 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
408 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
410 req->result = 0; /* no fds ready */
411 TM_Remove(Requests, &req->timeout);
413 req -> timeout.Next = (struct TM_Elem *) 2;
414 req -> timeout.Prev = (struct TM_Elem *) 2;
416 LWP_QSignal(req->pid);
417 req->pid->iomgrRequest = 0;
419 if (woke_someone) LWP_DispatchProcess();
420 } while (woke_someone);
422 /* Collect requests & update times */
423 FD_ZERO(&IOMGR_readfds);
424 FD_ZERO(&IOMGR_writefds);
425 FD_ZERO(&IOMGR_exceptfds);
428 FOR_ALL_ELTS(r, Requests, {
429 register struct IoRequest *req;
430 req = (struct IoRequest *) r -> BackPointer;
431 FDSetSet(req->nfds, &IOMGR_readfds, req->readfds);
432 FDSetSet(req->nfds, &IOMGR_writefds, req->writefds);
433 FDSetSet(req->nfds, &IOMGR_exceptfds, req->exceptfds);
434 if (req->nfds > IOMGR_nfds)
435 IOMGR_nfds = req->nfds;
437 earliest = TM_GetEarliest(Requests);
438 if (earliest != NULL) {
439 timeout = earliest -> TimeLeft;
444 if (lwp_debug != 0) {
447 printf("[Read Select:");
448 if (IOMGR_readfds.fd_count == 0)
451 for (idbg=0; idbg<IOMGR_readfds.fd_count; idbg++)
452 printf(" %d", IOMGR_readfds.fd_array[idbg]);
455 printf("[Write Select:");
456 if (IOMGR_writefds.fd_count == 0)
459 for (idbg=0; idbg<IOMGR_writefds.fd_count; idbg++)
460 printf(" %d", IOMGR_writefds.fd_array[idbg]);
463 printf("[Except Select:");
464 if (IOMGR_exceptfds.fd_count == 0)
467 for (idbg=0; idbg<IOMGR_exceptfds.fd_count; idbg++)
468 printf(" %d", IOMGR_exceptfds.fd_array[idbg]);
472 /* Only prints first 32. */
473 printf("[select(%d, 0x%x, 0x%x, 0x%x, ", IOMGR_nfds,
474 *(int*)&IOMGR_readfds, *(int*)&IOMGR_writefds,
475 *(int*)&IOMGR_exceptfds);
476 #endif /* AFS_NT40_ENV */
477 if (timeout.tv_sec == -1 && timeout.tv_usec == -1)
480 printf("<%d, %d>)]\n", timeout.tv_sec, timeout.tv_usec);
483 iomgr_timeout = timeout;
484 if (timeout.tv_sec == -1 && timeout.tv_usec == -1) {
485 /* infinite, sort of */
486 iomgr_timeout.tv_sec = 100000000;
487 iomgr_timeout.tv_usec = 0;
490 /* On NT, signals don't interrupt a select call. So this can potentially
491 * lead to long wait times before a signal is honored. To avoid this we
492 * dont do select() for longer than IOMGR_MAXWAITTIME (5 secs) */
493 if (iomgr_timeout.tv_sec > (IOMGR_MAXWAITTIME - 1)) {
494 iomgr_timeout.tv_sec = IOMGR_MAXWAITTIME;
495 iomgr_timeout.tv_usec = 0;
499 /* Check one last time for a signal delivery. If one comes after
500 this, the signal handler will set iomgr_timeout to zero, causing
501 the select to return immediately. The timer package won't return
502 a zero timeval because all of those guys were handled above.
504 I'm assuming that the kernel masks signals while it's picking up
505 the parameters to select. This may a bad assumption. -DN */
506 if (anySigsDelivered)
507 continue; /* go to the top and handle them. */
510 if (IOMGR_readfds.fd_count == 0 && IOMGR_writefds.fd_count == 0
511 && IOMGR_exceptfds.fd_count == 0) {
514 if (iomgr_timeout.tv_sec || iomgr_timeout.tv_usec) {
515 stime = iomgr_timeout.tv_sec * 1000
516 + iomgr_timeout.tv_usec/1000;
524 { /* select runs much faster if 0's are passed instead of &0s */
525 code = select(IOMGR_nfds,
526 (FDSetEmpty(IOMGR_nfds, &IOMGR_readfds)) ?
527 (fd_set*)0 : &IOMGR_readfds,
528 (FDSetEmpty(IOMGR_nfds, &IOMGR_writefds)) ?
529 (fd_set*)0 : &IOMGR_writefds,
530 (FDSetEmpty(IOMGR_nfds, &IOMGR_exceptfds)) ?
531 (fd_set*)0 : &IOMGR_exceptfds,
538 #if defined(AFS_SUN_ENV)
539 /* Tape drives on Sun boxes do not support select and return ENXIO */
540 if (errno == ENXIO) e=0, code=1;
542 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
543 /* For SGI and SVR4 - poll & select can return EAGAIN ... */
544 if (errno == EAGAIN) e=0;
546 #if defined(AFS_SUN5_ENV)
547 /* On sun4x_55, select doesn't block signal. It could be
548 interupted by a signal that changes iomgr_timeout, and
549 then select returns with EINVAL. In this case, we need
552 if (errno==EINVAL && anySigsDelivered)
554 #endif /* AFS_SUN5_ENV */
556 if ((errno != EINTR) && e) {
559 for(i=0; i<FD_SETSIZE; i++) {
560 if (fcntl(i, F_GETFD, 0) < 0 && errno == EBADF)
561 FD_SET(i, &openMask);
569 /* See what happened */
571 /* Action -- wake up everyone involved */
572 SignalIO(IOMGR_nfds, &IOMGR_readfds, &IOMGR_writefds,
573 &IOMGR_exceptfds, code);
576 && (iomgr_timeout.tv_sec != 0 || iomgr_timeout.tv_usec != 0)) {
577 /* Real timeout only if signal handler hasn't set
578 iomgr_timeout to zero. */
581 /* On NT, real timeout only if above and if iomgr_timeout
582 * interval is equal to timeout interval (i.e., not adjusted
583 * to check for pseudo-signals).
585 if (iomgr_timeout.tv_sec != timeout.tv_sec ||
586 iomgr_timeout.tv_usec != timeout.tv_usec) {
587 /* signal check interval timed out; not real timeout */
590 #endif /* AFS_NT40_ENV */
592 FT_GetTimeOfDay(&junk, 0);
593 SignalTimeout(code, &timeout);
596 LWP_DispatchProcess();
598 return -1; /* keeps compilers happy. */
601 /************************\
603 * Signalling routines *
605 \************************/
607 static void SignalIO(int fds, fd_set *readfds, fd_set *writefds,
608 fd_set *exceptfds, int code)
611 /* Look at everyone who's bit mask was affected */
612 FOR_ALL_ELTS(r, Requests, {
613 register struct IoRequest *req;
614 register PROCESS pid;
615 req = (struct IoRequest *) r -> BackPointer;
616 nfds = MIN(fds, req->nfds);
617 if (FDSetCmp(nfds, req->readfds, readfds) ||
618 FDSetCmp(nfds, req->writefds, writefds) ||
619 FDSetCmp(nfds, req->exceptfds, exceptfds)) {
620 /* put ready fd's into request. */
621 FDSetAnd(nfds, req->readfds, readfds);
622 FDSetAnd(nfds, req->writefds, writefds);
623 FDSetAnd(nfds, req->exceptfds, exceptfds);
624 req -> result = code;
625 TM_Remove(Requests, &req->timeout);
626 LWP_QSignal(pid=req->pid);
627 pid->iomgrRequest = 0;
632 static void SignalTimeout(int code, struct timeval *timeout)
634 /* Find everyone who has specified timeout */
635 FOR_ALL_ELTS(r, Requests, {
636 register struct IoRequest *req;
637 register PROCESS pid;
638 req = (struct IoRequest *) r -> BackPointer;
639 if (TM_eql(&r->TimeLeft, timeout)) {
640 req -> result = code;
641 TM_Remove(Requests, &req->timeout);
642 LWP_QSignal(pid=req->pid);
643 pid->iomgrRequest = 0;
649 /*****************************************************\
651 * Signal handling routine (not to be confused with *
652 * signalling routines, above). *
654 \*****************************************************/
655 static void SigHandler (signo)
658 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
659 return; /* can't happen. */
660 sigDelivered[signo] = TRUE;
661 anySigsDelivered = TRUE;
662 /* Make sure that the IOMGR process doesn't pause on the select. */
663 iomgr_timeout.tv_sec = 0;
664 iomgr_timeout.tv_usec = 0;
667 /* Alright, this is the signal signalling routine. It delivers LWP signals
668 to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
669 static int SignalSignals ()
676 anySigsDelivered = FALSE;
678 /* handle software signals */
679 stackSize = (AFS_LWP_MINSTACKSIZE < lwp_MaxStackSeen? lwp_MaxStackSeen : AFS_LWP_MINSTACKSIZE);
680 for (i=0; i < NSOFTSIG; i++) {
682 if (p=sigProc[i]) /* This yields!!! */
683 LWP_CreateProcess2(p, stackSize, LWP_NORMAL_PRIORITY, sigRock[i],
684 "SignalHandler", &pid);
688 for (i = 1; i <= NSIG; ++i) /* forall !badsig(i) */
689 if ((sigsHandled & mysigmask(i)) && sigDelivered[i] == TRUE) {
690 sigDelivered[i] = FALSE;
691 LWP_NoYieldSignal (sigEvents[i]);
698 /***************************\
700 * User-callable routines *
702 \***************************/
705 /* Keep IOMGR process id */
706 static PROCESS IOMGR_Id = NULL;
708 int IOMGR_SoftSig(aproc, arock)
712 for (i=0;i<NSOFTSIG;i++) {
713 if (sigProc[i] == 0) {
717 anySigsDelivered = TRUE;
718 iomgr_timeout.tv_sec = 0;
719 iomgr_timeout.tv_usec = 0;
727 unsigned char allOnes[100];
729 int IOMGR_Initialize(void)
731 extern int TM_Init();
734 /* If lready initialized, just return */
735 if (IOMGR_Id != NULL) return LWP_SUCCESS;
737 /* Init LWP if someone hasn't yet. */
738 if (LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY, &pid) != LWP_SUCCESS)
741 /* Initialize request lists */
742 if (TM_Init(&Requests) < 0) return -1;
744 /* Initialize signal handling stuff. */
746 anySigsDelivered = TRUE; /* A soft signal may have happened before
747 IOMGR_Initialize: so force a check for signals regardless */
748 memset(allOnes, 0xff, sizeof(allOnes));
750 return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, 0, "IO MANAGER",
760 status = LWP_DestroyProcess(IOMGR_Id);
765 /* signal I/O for anyone who is waiting for a FD or a timeout; not too cheap,
766 * since forces select and timeofday check */
767 int IOMGR_Poll(void) {
768 fd_set *readfds, *writefds, *exceptfds;
773 FT_GetTimeOfDay(&tv, 0); /* force accurate time check */
776 register struct IoRequest *req;
777 struct TM_Elem *expired;
778 expired = TM_GetExpired(Requests);
779 if (expired == NULL) break;
780 req = (struct IoRequest *) expired -> BackPointer;
782 if (lwp_debug != 0) puts("[Polling SELECT]");
785 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
786 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
787 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
789 req->result = 0; /* no fds ready */
790 TM_Remove(Requests, &req->timeout);
792 req -> timeout.Next = (struct TM_Elem *) 2;
793 req -> timeout.Prev = (struct TM_Elem *) 2;
795 LWP_QSignal(req->pid);
796 req->pid->iomgrRequest = 0;
799 /* Collect requests & update times */
800 readfds = IOMGR_AllocFDSet();
801 writefds = IOMGR_AllocFDSet();
802 exceptfds = IOMGR_AllocFDSet();
803 if (!(readfds && writefds && exceptfds)) {
804 fprintf(stderr, "IOMGR_Poll: Could not malloc space for fd_sets.\n");
810 FOR_ALL_ELTS(r, Requests, {
811 register struct IoRequest *req;
812 req = (struct IoRequest *) r -> BackPointer;
813 FDSetSet(req->nfds, readfds, req->readfds);
814 FDSetSet(req->nfds, writefds, req->writefds);
815 FDSetSet(req->nfds, exceptfds, req->exceptfds);
824 if (readfds->fd_count == 0 && writefds->fd_count == 0
825 && exceptfds->fd_count == 0)
827 code = select(fds, readfds, writefds, exceptfds, &tv);
829 SignalIO(fds, readfds, writefds, exceptfds, code);
832 if (readfds) IOMGR_FreeFDSet(readfds);
833 if (writefds) IOMGR_FreeFDSet(writefds);
834 if (exceptfds) IOMGR_FreeFDSet(exceptfds);
837 LWP_DispatchProcess(); /* make sure others run */
838 LWP_DispatchProcess();
842 int IOMGR_Select(fds, readfds, writefds, exceptfds, timeout)
844 fd_set *readfds, *writefds, *exceptfds;
845 struct timeval *timeout;
847 register struct IoRequest *request;
851 if(fds > FD_SETSIZE) {
852 fprintf(stderr, "IOMGR_Select: fds=%d, more than max %d\n",
859 /* See if polling request. If so, handle right here */
860 if (timeout != NULL) {
861 if (timeout->tv_sec == 0 && timeout->tv_usec == 0) {
864 if (lwp_debug != 0) puts("[Polling SELECT]");
867 code = select(fds, readfds, writefds, exceptfds, timeout);
868 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
870 * For SGI and SVR4 - poll & select can return EAGAIN ...
873 * this is basically for SGI, but I believe stock SVR4 (Solaris?)
874 * can also get this error return
876 if (code < 0 && errno == EAGAIN)
880 if (code == SOCKET_ERROR) {
881 if (WSAGetLastError() == WSAEINPROGRESS)
887 return (code > 1 ? 1 : code);
891 /* Construct request block & insert */
892 request = NewRequest(); /* zeroes fd_set's */
893 if (readfds && !FDSetEmpty(fds, readfds))
894 request->readfds = readfds;
895 if (writefds && !FDSetEmpty(fds, writefds))
896 request->writefds = writefds;
897 if (exceptfds && !FDSetEmpty(fds, exceptfds))
898 request->exceptfds = exceptfds;
901 if (timeout == NULL) {
902 request -> timeout.TotalTime.tv_sec = -1;
903 request -> timeout.TotalTime.tv_usec = -1;
905 request -> timeout.TotalTime = *timeout;
906 /* check for bad request */
907 if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999) {
909 iomgr_badtv = *timeout;
910 iomgr_badpid = LWP_ActiveProcess;
911 /* now fixup request */
912 if(request->timeout.TotalTime.tv_sec < 0)
913 request->timeout.TotalTime.tv_sec = 1;
914 request->timeout.TotalTime.tv_usec = 100000;
918 request -> timeout.BackPointer = (char *) request;
920 /* Insert my PID in case of IOMGR_Cancel */
921 request -> pid = LWP_ActiveProcess;
922 LWP_ActiveProcess -> iomgrRequest = request;
925 request -> timeout.Next = (struct TM_Elem *) 1;
926 request -> timeout.Prev = (struct TM_Elem *) 1;
928 TM_Insert(Requests, &request->timeout);
930 /* Wait for action */
933 /* Update parameters & return */
934 result = request -> result;
936 FreeRequest(request);
937 return (result > 1 ? 1 : result);
940 int IOMGR_Cancel(PROCESS pid)
942 register struct IoRequest *request;
944 if ((request = pid->iomgrRequest) == 0) return -1; /* Pid not found */
946 if (request->readfds) FD_N_ZERO(request->nfds, request->readfds);
947 if (request->writefds) FD_N_ZERO(request->nfds, request->writefds);
948 if (request->exceptfds) FD_N_ZERO(request->nfds, request->exceptfds);
951 request -> result = -2;
952 TM_Remove(Requests, &request->timeout);
954 request -> timeout.Next = (struct TM_Elem *) 5;
955 request -> timeout.Prev = (struct TM_Elem *) 5;
957 LWP_QSignal(request->pid);
958 pid->iomgrRequest = 0;
964 /* Cause delivery of signal signo to result in a LWP_SignalProcess of
966 IOMGR_Signal (signo, event)
975 return LWP_EBADEVENT;
976 sa.sa_handler = SigHandler;
977 sa.sa_mask = *((sigset_t *) allOnes); /* mask all signals */
979 sigsHandled |= mysigmask(signo);
980 sigEvents[signo] = event;
981 sigDelivered[signo] = FALSE;
982 if (sigaction (signo, &sa, &oldActions[signo]) == -1)
987 /* Stop handling occurrences of signo. */
988 IOMGR_CancelSignal (signo)
991 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
993 sigaction (signo, &oldActions[signo], (struct sigaction *)0);
994 sigsHandled &= ~mysigmask(signo);
997 #endif /* AFS_NT40_ENV */
998 /* This routine calls select is a fashion that simulates the standard sleep routine */
999 void IOMGR_Sleep (int seconds)
1001 struct timeval timeout;
1003 timeout.tv_sec = seconds;
1004 timeout.tv_usec = 0;
1005 IOMGR_Select(0, 0, 0, 0, &timeout);
1007 #endif /* USE_PTHREADS */