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 *
17 \*******************************************************************/
21 IO Manager routines & server process for VICE server.
24 /* This controls the size of an fd_set; it must be defined early before
25 * the system headers define that type and the macros that operate on it.
26 * Its value should be as large as the maximum file descriptor limit we
27 * are likely to run into on any platform. Right now, that is 65536
28 * which is the default hard fd limit on Solaris 9 */
29 /* We don't do this on Windows because on that platform there is code
30 * which allocates fd_set's on the stack (IOMGR_Sleep on Win9x, and
31 * FDSetAnd on WinNT) */
33 #define FD_SETSIZE 65536
36 #include <afsconfig.h>
37 #include <afs/param.h>
47 extern void lwp_abort(void);
49 #include <unistd.h> /* select() prototype */
50 #include <sys/types.h> /* fd_set on older platforms */
51 #include <sys/time.h> /* struct timeval, select() prototype */
53 # include <sys/select.h> /* fd_set on newer platforms */
56 #endif /* AFS_NT40_ENV */
65 #if defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
67 void IOMGR_Initialize() /* noop */
70 void IOMGR_Sleep (seconds)
77 assert(pthread_mutex_unlock(&lwp_mutex) == 0);
78 assert(pthread_delay_np(&itv) == 0);
79 assert(pthread_mutex_lock(&lwp_mutex) == 0);
85 extern void *malloc();
86 #endif /* AFS_DECOSF_ENV */
88 typedef unsigned char bool;
93 #define MIN(a,b) (((a)>(b)) ? (b) : (a))
97 #define NSIG 8*sizeof(sigset_t)
100 static int SignalSignals();
102 /********************************\
104 * Stuff for managing IoRequests *
106 \********************************/
110 /* Pid of process making request (for use in IOMGR_Cancel */
113 /* Descriptor masks for requests */
119 struct TM_Elem timeout;
121 /* Result of select call */
124 struct IoRequest *next; /* for iorFreeList */
128 /********************************\
130 * Stuff for managing signals *
132 \********************************/
134 #define badsig(signo) (((signo) <= 0) || ((signo) >= NSIG))
135 #define mysigmask(signo) (1 << ((signo)-1))
138 fd_set openMask; /* mask of open files on an IOMGR abort */
139 static afs_int32 sigsHandled; /* sigmask(signo) is on if we handle signo */
140 static int anySigsDelivered; /* true if any have been delivered. */
142 static struct sigaction oldActions[NSIG]; /* the old signal vectors */
144 static char *sigEvents[NSIG]; /* the event to do an LWP signal on */
145 static int sigDelivered[NSIG]; /* True for signals delivered so far.
146 This is an int array to make sure
147 there are no conflicts when trying
149 /* software 'signals' */
151 static int (*sigProc[NSOFTSIG])();
152 static char *sigRock[NSOFTSIG];
155 static struct IoRequest *iorFreeList = 0;
157 static struct TM_Elem *Requests; /* List of requests */
158 static struct timeval iomgr_timeout; /* global so signal handler can zap it */
160 /* stuff for debugging */
161 static int iomgr_errno;
162 static struct timeval iomgr_badtv;
163 static PROCESS iomgr_badpid;
164 static void SignalIO(int fds, fd_set *rfds, fd_set *wfds, fd_set *efs,
166 static void SignalTimeout(int code, struct timeval *timeout);
168 /* fd_set pool managment.
169 * Use the pool instead of creating fd_set's on the stack. fd_set's can be
170 * 8K in size, so making three could put 24K in the limited space of an LWP
173 struct IOMGR_fd_set {
174 struct IOMGR_fd_set *next;
175 } *iomgrFreeFDSets = (struct IOMGR_fd_set*)0;
178 * Return fd_set to the free list.
180 void IOMGR_FreeFDSet(fd_set *s)
182 struct IOMGR_fd_set *t = (struct IOMGR_fd_set *)s;
184 t->next = iomgrFreeFDSets;
189 * returns a zeroed fd_set or null if could not malloc one.
191 fd_set *IOMGR_AllocFDSet(void)
193 struct IOMGR_fd_set *t;
194 if (iomgrFreeFDSets) {
196 iomgrFreeFDSets = iomgrFreeFDSets->next;
199 t = (struct IOMGR_fd_set *)malloc(sizeof(fd_set));
209 #define FreeRequest(x) ((x)->next = iorFreeList, iorFreeList = (x))
211 static struct IoRequest *NewRequest()
213 struct IoRequest *request;
215 if ((request=iorFreeList))
216 iorFreeList = (struct IoRequest *) (request->next);
217 else request = (struct IoRequest *) malloc(sizeof(struct IoRequest));
219 memset((char*)request, 0, sizeof(struct IoRequest));
223 #define Purge(list) FOR_ALL_ELTS(req, list, { free(req->BackPointer); })
226 /* FD_SET support routines. All assume the fd_set size is a multiple of an int
227 * so we can at least do logical operations on ints instead of chars.
229 * For each routine, nfds is the highest bit set in either fd_set, starting
233 #define FD_N_ZERO(A, x) FD_ZERO(x)
235 #define FDS_P_POS (sizeof(int)*8)
236 #define INTS_PER_FDS(x) (((x)+(FDS_P_POS-1)) / FDS_P_POS)
237 #define FD_N_ZERO(nfds, x) memset((char*)(x), 0, (INTS_PER_FDS(nfds))*sizeof(int))
240 #if defined(AFS_LINUX22_ENV) && (__GLIBC_MINOR__ > 0)
241 /* Build for both glibc 2.0.x and 2.1.x */
242 #define FDS_BITS __fds_bits
244 #define FDS_BITS fds_bits
247 /* FDSetCmp - returns 1 if any bits in fd_set1 are also set in fd_set2.
248 * If nfds is 0, or one of the fd_sets is null return 0 (since there is no bit
249 * set in both fd_sets).
251 static int FDSetCmp(int nfds, fd_set *fd_set1, fd_set *fd_set2)
255 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
259 if (fd_set1->fd_count == 0 || fd_set2->fd_count == 0)
262 for (i=0; i<fd_set1->fd_count; i++) {
263 for (j=0; j<fd_set2->fd_count; j++) {
264 if (fd_set1->fd_array[i] == fd_set2->fd_array[j])
272 j = INTS_PER_FDS(nfds);
273 for (i=0; i<j; i++) {
274 if (fd_set1->FDS_BITS[i] & fd_set2->FDS_BITS[i])
281 /* FDSetSet - set bits from fd_set2 into fd_set1
283 static void FDSetSet(int nfds, fd_set *fd_set1, fd_set *fd_set2)
290 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
294 if (fd_set2->fd_count==0)
297 for (i=0; i<fd_set2->fd_count; i++)
298 FD_SET(fd_set2->fd_array[i], fd_set1);
303 for (i = 0, n = INTS_PER_FDS(nfds); i < n; i++) {
304 fd_set1->FDS_BITS[i] |= fd_set2->FDS_BITS[i];
309 /* FDSetAnd - fd_set1 <- fd_set1 & fd_set2.
312 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
317 if (fd_set1 == NULL || fd_set1->fd_count == 0)
320 if (fd_set2 == NULL || fd_set2->fd_count == 0) {
325 for (i=0; i<fd_set2->fd_count; i++) {
326 if (FD_ISSET(fd_set2->fd_array[i], fd_set1))
327 FD_SET(fd_set2->fd_array[i], &tmpset);
333 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
337 if (nfds == 0 || fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
340 n = INTS_PER_FDS(nfds);
341 for (i=0; i<n; i++) {
342 fd_set1->FDS_BITS[i] &= fd_set2->FDS_BITS[i];
347 /* FDSetEmpty - return true if fd_set is empty
349 static int FDSetEmpty(int nfds, fd_set *fds)
357 if (fds == (fd_set*)0)
361 if (fds->fd_count == 0)
366 n = INTS_PER_FDS(nfds);
368 for (i=n-1; i>=0; i--) {
369 if (fds->FDS_BITS[i])
380 /* The IOMGR process */
383 * Important invariant: process->iomgrRequest is null iff request not in timer
385 * also, request->pid is valid while request is in queue,
386 * also, don't signal selector while request in queue, since selector frees
390 /* These are not declared in IOMGR so that they don't use up 6K of stack. */
391 static fd_set IOMGR_readfds, IOMGR_writefds, IOMGR_exceptfds;
392 static int IOMGR_nfds = 0;
394 static int IOMGR(void *dummy)
398 struct TM_Elem *earliest;
399 struct timeval timeout, junk;
402 FD_ZERO(&IOMGR_readfds);
403 FD_ZERO(&IOMGR_writefds);
404 FD_ZERO(&IOMGR_exceptfds);
407 /* Wake up anyone who has expired or who has received a
408 Unix signal between executions. Keep going until we
411 woke_someone = FALSE;
412 /* Wake up anyone waiting on signals. */
413 /* Note: SignalSignals() may yield! */
414 if (anySigsDelivered && SignalSignals ())
416 FT_GetTimeOfDay(&junk, 0); /* force accurate time check */
419 register struct IoRequest *req;
420 struct TM_Elem *expired;
421 expired = TM_GetExpired(Requests);
422 if (expired == NULL) break;
424 req = (struct IoRequest *) expired -> BackPointer;
426 if (lwp_debug != 0) puts("[Polling SELECT]");
429 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
430 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
431 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
433 req->result = 0; /* no fds ready */
434 TM_Remove(Requests, &req->timeout);
436 req -> timeout.Next = (struct TM_Elem *) 2;
437 req -> timeout.Prev = (struct TM_Elem *) 2;
439 LWP_QSignal(req->pid);
440 req->pid->iomgrRequest = 0;
443 if (woke_someone) LWP_DispatchProcess();
444 } while (woke_someone);
446 /* Collect requests & update times */
447 FD_ZERO(&IOMGR_readfds);
448 FD_ZERO(&IOMGR_writefds);
449 FD_ZERO(&IOMGR_exceptfds);
452 FOR_ALL_ELTS(r, Requests, {
453 register struct IoRequest *req;
454 req = (struct IoRequest *) r -> BackPointer;
455 FDSetSet(req->nfds, &IOMGR_readfds, req->readfds);
456 FDSetSet(req->nfds, &IOMGR_writefds, req->writefds);
457 FDSetSet(req->nfds, &IOMGR_exceptfds, req->exceptfds);
458 if (req->nfds > IOMGR_nfds)
459 IOMGR_nfds = req->nfds;
461 earliest = TM_GetEarliest(Requests);
462 if (earliest != NULL) {
463 timeout = earliest -> TimeLeft;
468 if (lwp_debug != 0) {
471 printf("[Read Select:");
472 if (IOMGR_readfds.fd_count == 0)
475 for (idbg=0; idbg<IOMGR_readfds.fd_count; idbg++)
476 printf(" %d", IOMGR_readfds.fd_array[idbg]);
479 printf("[Write Select:");
480 if (IOMGR_writefds.fd_count == 0)
483 for (idbg=0; idbg<IOMGR_writefds.fd_count; idbg++)
484 printf(" %d", IOMGR_writefds.fd_array[idbg]);
487 printf("[Except Select:");
488 if (IOMGR_exceptfds.fd_count == 0)
491 for (idbg=0; idbg<IOMGR_exceptfds.fd_count; idbg++)
492 printf(" %d", IOMGR_exceptfds.fd_array[idbg]);
496 /* Only prints first 32. */
497 printf("[select(%d, 0x%x, 0x%x, 0x%x, ", IOMGR_nfds,
498 *(int*)&IOMGR_readfds, *(int*)&IOMGR_writefds,
499 *(int*)&IOMGR_exceptfds);
500 #endif /* AFS_NT40_ENV */
501 if (timeout.tv_sec == -1 && timeout.tv_usec == -1)
504 printf("<%d, %d>)]\n", timeout.tv_sec, timeout.tv_usec);
507 iomgr_timeout = timeout;
508 if (timeout.tv_sec == -1 && timeout.tv_usec == -1) {
509 /* infinite, sort of */
510 iomgr_timeout.tv_sec = 100000000;
511 iomgr_timeout.tv_usec = 0;
513 #if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV)
514 /* On NT, signals don't interrupt a select call. So this can potentially
515 * lead to long wait times before a signal is honored. To avoid this we
516 * dont do select() for longer than IOMGR_MAXWAITTIME (5 secs) */
517 /* Whereas Linux seems to sometimes "lose" signals */
518 if (iomgr_timeout.tv_sec > (IOMGR_MAXWAITTIME - 1)) {
519 iomgr_timeout.tv_sec = IOMGR_MAXWAITTIME;
520 iomgr_timeout.tv_usec = 0;
524 /* Check one last time for a signal delivery. If one comes after
525 this, the signal handler will set iomgr_timeout to zero, causing
526 the select to return immediately. The timer package won't return
527 a zero timeval because all of those guys were handled above.
529 I'm assuming that the kernel masks signals while it's picking up
530 the parameters to select. This may a bad assumption. -DN */
531 if (anySigsDelivered)
532 continue; /* go to the top and handle them. */
535 if (IOMGR_readfds.fd_count == 0 && IOMGR_writefds.fd_count == 0
536 && IOMGR_exceptfds.fd_count == 0) {
539 if (iomgr_timeout.tv_sec || iomgr_timeout.tv_usec) {
540 stime = iomgr_timeout.tv_sec * 1000
541 + iomgr_timeout.tv_usec/1000;
549 { /* select runs much faster if 0's are passed instead of &0s */
550 code = select(IOMGR_nfds,
551 (FDSetEmpty(IOMGR_nfds, &IOMGR_readfds)) ?
552 (fd_set*)0 : &IOMGR_readfds,
553 (FDSetEmpty(IOMGR_nfds, &IOMGR_writefds)) ?
554 (fd_set*)0 : &IOMGR_writefds,
555 (FDSetEmpty(IOMGR_nfds, &IOMGR_exceptfds)) ?
556 (fd_set*)0 : &IOMGR_exceptfds,
563 #if defined(AFS_SUN_ENV)
564 /* Tape drives on Sun boxes do not support select and return ENXIO */
565 if (errno == ENXIO) e=0, code=1;
567 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
568 /* For SGI and SVR4 - poll & select can return EAGAIN ... */
569 if (errno == EAGAIN) e=0;
571 #if defined(AFS_SUN5_ENV)
572 /* On sun4x_55, select doesn't block signal. It could be
573 interupted by a signal that changes iomgr_timeout, and
574 then select returns with EINVAL. In this case, we need
577 if (errno==EINVAL && anySigsDelivered)
579 #endif /* AFS_SUN5_ENV */
581 if ((errno != EINTR) && e) {
584 for(i=0; i<FD_SETSIZE; i++) {
585 if (fcntl(i, F_GETFD, 0) < 0 && errno == EBADF)
586 FD_SET(i, &openMask);
594 /* See what happened */
596 /* Action -- wake up everyone involved */
597 SignalIO(IOMGR_nfds, &IOMGR_readfds, &IOMGR_writefds,
598 &IOMGR_exceptfds, code);
601 && (iomgr_timeout.tv_sec != 0 || iomgr_timeout.tv_usec != 0)) {
602 /* Real timeout only if signal handler hasn't set
603 iomgr_timeout to zero. */
605 #if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV)
606 /* On NT, real timeout only if above and if iomgr_timeout
607 * interval is equal to timeout interval (i.e., not adjusted
608 * to check for pseudo-signals).
610 /* And also for Linux as above */
611 if (iomgr_timeout.tv_sec != timeout.tv_sec ||
612 iomgr_timeout.tv_usec != timeout.tv_usec) {
613 /* signal check interval timed out; not real timeout */
616 #endif /* AFS_NT40_ENV */
617 FT_GetTimeOfDay(&junk, 0);
618 SignalTimeout(code, &timeout);
621 LWP_DispatchProcess();
623 return -1; /* keeps compilers happy. */
626 /************************\
628 * Signalling routines *
630 \************************/
632 static void SignalIO(int fds, fd_set *readfds, fd_set *writefds,
633 fd_set *exceptfds, int code)
636 /* Look at everyone who's bit mask was affected */
637 FOR_ALL_ELTS(r, Requests, {
638 register struct IoRequest *req;
639 register PROCESS pid;
640 req = (struct IoRequest *) r -> BackPointer;
641 nfds = MIN(fds, req->nfds);
642 if (FDSetCmp(nfds, req->readfds, readfds) ||
643 FDSetCmp(nfds, req->writefds, writefds) ||
644 FDSetCmp(nfds, req->exceptfds, exceptfds)) {
645 /* put ready fd's into request. */
646 FDSetAnd(nfds, req->readfds, readfds);
647 FDSetAnd(nfds, req->writefds, writefds);
648 FDSetAnd(nfds, req->exceptfds, exceptfds);
649 req -> result = code;
650 TM_Remove(Requests, &req->timeout);
651 LWP_QSignal(pid=req->pid);
652 pid->iomgrRequest = 0;
657 static void SignalTimeout(int code, struct timeval *timeout)
659 /* Find everyone who has specified timeout */
660 FOR_ALL_ELTS(r, Requests, {
661 register struct IoRequest *req;
662 register PROCESS pid;
663 req = (struct IoRequest *) r -> BackPointer;
664 if (TM_eql(&r->TimeLeft, timeout)) {
665 req -> result = code;
666 TM_Remove(Requests, &req->timeout);
667 LWP_QSignal(pid=req->pid);
668 pid->iomgrRequest = 0;
674 /*****************************************************\
676 * Signal handling routine (not to be confused with *
677 * signalling routines, above). *
679 \*****************************************************/
680 static void SigHandler (signo)
683 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
684 return; /* can't happen. */
685 sigDelivered[signo] = TRUE;
686 anySigsDelivered = TRUE;
687 /* Make sure that the IOMGR process doesn't pause on the select. */
688 iomgr_timeout.tv_sec = 0;
689 iomgr_timeout.tv_usec = 0;
692 /* Alright, this is the signal signalling routine. It delivers LWP signals
693 to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
694 static int SignalSignals (void)
701 anySigsDelivered = FALSE;
703 /* handle software signals */
704 stackSize = (AFS_LWP_MINSTACKSIZE < lwp_MaxStackSeen? lwp_MaxStackSeen : AFS_LWP_MINSTACKSIZE);
705 for (i=0; i < NSOFTSIG; i++) {
707 if (p=sigProc[i]) /* This yields!!! */
708 LWP_CreateProcess2(p, stackSize, LWP_NORMAL_PRIORITY,
709 (void *) sigRock[i], "SignalHandler", &pid);
713 for (i = 1; i <= NSIG; ++i) /* forall !badsig(i) */
714 if ((sigsHandled & mysigmask(i)) && sigDelivered[i] == TRUE) {
715 sigDelivered[i] = FALSE;
716 LWP_NoYieldSignal (sigEvents[i]);
723 /***************************\
725 * User-callable routines *
727 \***************************/
730 /* Keep IOMGR process id */
731 static PROCESS IOMGR_Id = NULL;
733 int IOMGR_SoftSig(aproc, arock)
737 for (i=0;i<NSOFTSIG;i++) {
738 if (sigProc[i] == 0) {
742 anySigsDelivered = TRUE;
743 iomgr_timeout.tv_sec = 0;
744 iomgr_timeout.tv_usec = 0;
752 unsigned char allOnes[100];
754 int IOMGR_Initialize(void)
756 extern int TM_Init();
759 /* If lready initialized, just return */
760 if (IOMGR_Id != NULL) return LWP_SUCCESS;
762 /* Init LWP if someone hasn't yet. */
763 if (LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY, &pid) != LWP_SUCCESS)
766 /* Initialize request lists */
767 if (TM_Init(&Requests) < 0) return -1;
769 /* Initialize signal handling stuff. */
771 anySigsDelivered = TRUE; /* A soft signal may have happened before
772 IOMGR_Initialize: so force a check for signals regardless */
773 memset(allOnes, 0xff, sizeof(allOnes));
775 return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, (void *) 0,
776 "IO MANAGER", &IOMGR_Id);
785 status = LWP_DestroyProcess(IOMGR_Id);
790 /* signal I/O for anyone who is waiting for a FD or a timeout; not too cheap,
791 * since forces select and timeofday check */
792 int IOMGR_Poll(void) {
793 fd_set *readfds, *writefds, *exceptfds;
798 FT_GetTimeOfDay(&tv, 0); /* force accurate time check */
801 register struct IoRequest *req;
802 struct TM_Elem *expired;
803 expired = TM_GetExpired(Requests);
804 if (expired == NULL) break;
805 req = (struct IoRequest *) expired -> BackPointer;
807 if (lwp_debug != 0) puts("[Polling SELECT]");
810 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
811 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
812 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
814 req->result = 0; /* no fds ready */
815 TM_Remove(Requests, &req->timeout);
817 req -> timeout.Next = (struct TM_Elem *) 2;
818 req -> timeout.Prev = (struct TM_Elem *) 2;
820 LWP_QSignal(req->pid);
821 req->pid->iomgrRequest = 0;
824 /* Collect requests & update times */
825 readfds = IOMGR_AllocFDSet();
826 writefds = IOMGR_AllocFDSet();
827 exceptfds = IOMGR_AllocFDSet();
828 if (!(readfds && writefds && exceptfds)) {
829 fprintf(stderr, "IOMGR_Poll: Could not malloc space for fd_sets.\n");
835 FOR_ALL_ELTS(r, Requests, {
836 register struct IoRequest *req;
837 req = (struct IoRequest *) r -> BackPointer;
838 FDSetSet(req->nfds, readfds, req->readfds);
839 FDSetSet(req->nfds, writefds, req->writefds);
840 FDSetSet(req->nfds, exceptfds, req->exceptfds);
849 if (readfds->fd_count == 0 && writefds->fd_count == 0
850 && exceptfds->fd_count == 0)
852 code = select(fds, readfds, writefds, exceptfds, &tv);
854 SignalIO(fds, readfds, writefds, exceptfds, code);
857 if (readfds) IOMGR_FreeFDSet(readfds);
858 if (writefds) IOMGR_FreeFDSet(writefds);
859 if (exceptfds) IOMGR_FreeFDSet(exceptfds);
862 LWP_DispatchProcess(); /* make sure others run */
863 LWP_DispatchProcess();
867 int IOMGR_Select(fds, readfds, writefds, exceptfds, timeout)
869 fd_set *readfds, *writefds, *exceptfds;
870 struct timeval *timeout;
872 register struct IoRequest *request;
876 if(fds > FD_SETSIZE) {
877 fprintf(stderr, "IOMGR_Select: fds=%d, more than max %d\n",
884 /* See if polling request. If so, handle right here */
885 if (timeout != NULL) {
886 if (timeout->tv_sec == 0 && timeout->tv_usec == 0) {
889 if (lwp_debug != 0) puts("[Polling SELECT]");
892 code = select(fds, readfds, writefds, exceptfds, timeout);
893 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
895 * For SGI and SVR4 - poll & select can return EAGAIN ...
898 * this is basically for SGI, but I believe stock SVR4 (Solaris?)
899 * can also get this error return
901 if (code < 0 && errno == EAGAIN)
905 if (code == SOCKET_ERROR) {
906 if (WSAGetLastError() == WSAEINPROGRESS)
912 return (code > 1 ? 1 : code);
916 /* Construct request block & insert */
917 request = NewRequest(); /* zeroes fd_set's */
918 if (readfds && !FDSetEmpty(fds, readfds))
919 request->readfds = readfds;
920 if (writefds && !FDSetEmpty(fds, writefds))
921 request->writefds = writefds;
922 if (exceptfds && !FDSetEmpty(fds, exceptfds))
923 request->exceptfds = exceptfds;
926 if (timeout == NULL) {
927 request -> timeout.TotalTime.tv_sec = -1;
928 request -> timeout.TotalTime.tv_usec = -1;
930 request -> timeout.TotalTime = *timeout;
931 /* check for bad request */
932 if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999) {
934 iomgr_badtv = *timeout;
935 iomgr_badpid = LWP_ActiveProcess;
936 /* now fixup request */
937 if(request->timeout.TotalTime.tv_sec < 0)
938 request->timeout.TotalTime.tv_sec = 1;
939 request->timeout.TotalTime.tv_usec = 100000;
943 request -> timeout.BackPointer = (char *) request;
945 /* Insert my PID in case of IOMGR_Cancel */
946 request -> pid = LWP_ActiveProcess;
947 LWP_ActiveProcess -> iomgrRequest = request;
950 request -> timeout.Next = (struct TM_Elem *) 1;
951 request -> timeout.Prev = (struct TM_Elem *) 1;
953 TM_Insert(Requests, &request->timeout);
955 /* Wait for action */
958 /* Update parameters & return */
959 result = request -> result;
961 FreeRequest(request);
962 return (result > 1 ? 1 : result);
965 int IOMGR_Cancel(PROCESS pid)
967 register struct IoRequest *request;
969 if ((request = pid->iomgrRequest) == 0) return -1; /* Pid not found */
971 if (request->readfds) FD_N_ZERO(request->nfds, request->readfds);
972 if (request->writefds) FD_N_ZERO(request->nfds, request->writefds);
973 if (request->exceptfds) FD_N_ZERO(request->nfds, request->exceptfds);
976 request -> result = -2;
977 TM_Remove(Requests, &request->timeout);
979 request -> timeout.Next = (struct TM_Elem *) 5;
980 request -> timeout.Prev = (struct TM_Elem *) 5;
982 LWP_QSignal(request->pid);
983 pid->iomgrRequest = 0;
989 /* Cause delivery of signal signo to result in a LWP_SignalProcess of
991 int IOMGR_Signal (int signo, char *event)
998 return LWP_EBADEVENT;
999 sa.sa_handler = SigHandler;
1000 sa.sa_mask = *((sigset_t *) allOnes); /* mask all signals */
1002 sigsHandled |= mysigmask(signo);
1003 sigEvents[signo] = event;
1004 sigDelivered[signo] = FALSE;
1005 if (sigaction (signo, &sa, &oldActions[signo]) == -1)
1010 /* Stop handling occurrences of signo. */
1011 int IOMGR_CancelSignal (int signo)
1013 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
1015 sigaction (signo, &oldActions[signo], NULL);
1016 sigsHandled &= ~mysigmask(signo);
1019 #endif /* AFS_NT40_ENV */
1020 /* This routine calls select is a fashion that simulates the standard sleep routine */
1021 void IOMGR_Sleep (int seconds)
1023 struct timeval timeout;
1025 timeout.tv_sec = seconds;
1026 timeout.tv_usec = 0;
1027 IOMGR_Select(0, 0, 0, 0, &timeout);
1029 #endif /* USE_PTHREADS */