6 ****************************************************************************
7 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
9 * Permission to use, copy, modify, and distribute this software and its *
10 * documentation for any purpose and without fee is hereby granted, *
11 * provided that the above copyright notice appear in all copies and *
12 * that both that copyright notice and this permission notice appear in *
13 * supporting documentation, and that the name of IBM not be used in *
14 * advertising or publicity pertaining to distribution of the software *
15 * without specific, written prior permission. *
17 * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY *
20 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER *
21 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *
22 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
23 ****************************************************************************
26 /*******************************************************************\
28 * Information Technology Center *
29 * Carnegie-Mellon University *
33 \*******************************************************************/
37 IO Manager routines & server process for VICE server.
40 #include <afs/param.h>
45 extern void lwp_abort(void);
47 #include <unistd.h> /* select() prototype */
48 #include <sys/types.h> /* fd_set on older platforms */
49 #include <sys/time.h> /* struct timeval, select() prototype */
51 # include <sys/select.h> /* fd_set on newer platforms */
54 #endif /* AFS_NT40_ENV */
62 #if defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
64 void IOMGR_Initialize() /* noop */
67 void IOMGR_Sleep (seconds)
74 assert(pthread_mutex_unlock(&lwp_mutex) == 0);
75 assert(pthread_delay_np(&itv) == 0);
76 assert(pthread_mutex_lock(&lwp_mutex) == 0);
82 extern void *malloc();
83 #endif /* AFS_DECOSF_ENV */
85 typedef unsigned char bool;
90 #define MIN(a,b) ((a)>(b)) ? b : a
93 static int SignalSignals();
95 /********************************\
97 * Stuff for managing IoRequests *
99 \********************************/
103 /* Pid of process making request (for use in IOMGR_Cancel */
106 /* Descriptor masks for requests */
112 struct TM_Elem timeout;
114 /* Result of select call */
119 /********************************\
121 * Stuff for managing signals *
123 \********************************/
125 #define badsig(signo) (((signo) <= 0) || ((signo) >= NSIG))
126 #define mysigmask(signo) (1 << ((signo)-1))
129 fd_set openMask; /* mask of open files on an IOMGR abort */
130 static afs_int32 sigsHandled; /* sigmask(signo) is on if we handle signo */
131 static int anySigsDelivered; /* true if any have been delivered. */
133 static struct sigaction oldActions[NSIG]; /* the old signal vectors */
135 static char *sigEvents[NSIG]; /* the event to do an LWP signal on */
136 static int sigDelivered[NSIG]; /* True for signals delivered so far.
137 This is an int array to make sure
138 there are no conflicts when trying
140 /* software 'signals' */
142 static int (*sigProc[NSOFTSIG])();
143 static char *sigRock[NSOFTSIG];
146 static struct IoRequest *iorFreeList = 0;
148 static struct TM_Elem *Requests; /* List of requests */
149 static struct timeval iomgr_timeout; /* global so signal handler can zap it */
151 /* stuff for debugging */
152 static int iomgr_errno;
153 static struct timeval iomgr_badtv;
154 static PROCESS iomgr_badpid;
155 static void SignalIO(int fds, fd_set *rfds, fd_set *wfds, fd_set *efs,
158 /* fd_set pool managment.
159 * Use the pool instead of creating fd_set's on the stack. fd_set's can be
160 * 2K in size, so making three could put 6K in the limited space of an LWP
163 struct IOMGR_fd_set {
164 struct IOMGR_fd_set *next;
165 } *iomgrFreeFDSets = (struct IOMGR_fd_set*)0;
168 * Return fd_set to the free list.
170 void IOMGR_FreeFDSet(fd_set *s)
172 struct IOMGR_fd_set *t = (struct IOMGR_fd_set *)s;
174 t->next = iomgrFreeFDSets;
179 * returns a zeroed fd_set or null if could not malloc one.
181 fd_set *IOMGR_AllocFDSet(void)
183 struct IOMGR_fd_set *t;
184 if (iomgrFreeFDSets) {
186 iomgrFreeFDSets = iomgrFreeFDSets->next;
189 t = (struct IOMGR_fd_set *)malloc(sizeof(fd_set));
199 #define FreeRequest(x) ((x)->result = (long) iorFreeList, iorFreeList = (x))
201 static struct IoRequest *NewRequest()
203 struct IoRequest *request;
205 if (request=iorFreeList)
206 iorFreeList = (struct IoRequest *) (request->result);
207 else request = (struct IoRequest *) malloc(sizeof(struct IoRequest));
209 memset((char*)request, 0, sizeof(struct IoRequest));
213 #define Purge(list) FOR_ALL_ELTS(req, list, { free(req->BackPointer); })
216 /* FD_SET support routines. All assume the fd_set size is a multiple of an int
217 * so we can at least do logical operations on ints instead of chars.
219 * For each routine, nfds is the highest bit set in either fd_set, starting
223 #define FD_N_ZERO(A, x) FD_ZERO(x)
225 #define FDS_P_POS (sizeof(int)*8)
226 #define INTS_PER_FDS(x) (((x)+(FDS_P_POS-1)) / FDS_P_POS)
227 #define FD_N_ZERO(nfds, x) bzero((char*)(x), (INTS_PER_FDS(nfds))*sizeof(int))
230 #if defined(AFS_LINUX22_ENV) && (__GLIBC_MINOR__ > 0)
231 /* Build for both glibc 2.0.x and 2.1.x */
232 #define FDS_BITS __fds_bits
234 #define FDS_BITS fds_bits
237 /* FDSetCmp - returns 1 if any bits in fd_set1 are also set in fd_set2.
238 * If nfds is 0, or one of the fd_sets is null return 0 (since there is no bit
239 * set in both fd_sets).
241 static int FDSetCmp(int nfds, fd_set *fd_set1, fd_set *fd_set2)
245 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
249 if (fd_set1->fd_count == 0 || fd_set2->fd_count == 0)
252 for (i=0; i<fd_set1->fd_count; i++) {
253 for (j=0; j<fd_set2->fd_count; j++) {
254 if (fd_set1->fd_array[i] == fd_set2->fd_array[j])
262 j = INTS_PER_FDS(nfds);
263 for (i=0; i<j; i++) {
264 if (fd_set1->FDS_BITS[i] & fd_set2->FDS_BITS[i])
271 /* FDSetSet - set bits from fd_set2 into fd_set1
273 static void FDSetSet(int nfds, fd_set *fd_set1, fd_set *fd_set2)
277 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
281 if (fd_set2->fd_count==0)
284 for (i=0; i<fd_set2->fd_count; i++)
285 FD_SET(fd_set2->fd_array[i], fd_set1);
290 n = INTS_PER_FDS(nfds);
291 for (i=0; i<n; i++) {
292 fd_set1->FDS_BITS[i] |= fd_set2->FDS_BITS[i];
297 /* FDSetAnd - fd_set1 <- fd_set1 & fd_set2.
300 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
305 if (fd_set1 == NULL || fd_set1->fd_count == 0)
308 if (fd_set2 == NULL || fd_set2->fd_count == 0) {
313 for (i=0; i<fd_set2->fd_count; i++) {
314 if (FD_ISSET(fd_set2->fd_array[i], fd_set1))
315 FD_SET(fd_set2->fd_array[i], &tmpset);
321 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
325 if (nfds == 0 || fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
328 n = INTS_PER_FDS(nfds);
329 for (i=0; i<n; i++) {
330 fd_set1->FDS_BITS[i] &= fd_set2->FDS_BITS[i];
335 /* FDSetEmpty - return true if fd_set is empty
337 static int FDSetEmpty(int nfds, fd_set *fds)
345 if (fds == (fd_set*)0)
349 if (fds->fd_count == 0)
354 n = INTS_PER_FDS(nfds);
356 for (i=n-1; i>=0; i--) {
357 if (fds->FDS_BITS[i])
368 /* The IOMGR process */
371 * Important invariant: process->iomgrRequest is null iff request not in timer
373 * also, request->pid is valid while request is in queue,
374 * also, don't signal selector while request in queue, since selector frees
378 /* These are not declared in IOMGR so that they don't use up 6K of stack. */
379 static fd_set IOMGR_readfds, IOMGR_writefds, IOMGR_exceptfds;
380 static int IOMGR_nfds = 0;
382 static int IOMGR(void *dummy)
386 struct TM_Elem *earliest;
387 struct timeval timeout, junk;
393 FD_ZERO(&IOMGR_readfds);
394 FD_ZERO(&IOMGR_writefds);
395 FD_ZERO(&IOMGR_exceptfds);
398 /* Wake up anyone who has expired or who has received a
399 Unix signal between executions. Keep going until we
402 woke_someone = FALSE;
403 /* Wake up anyone waiting on signals. */
404 /* Note: SignalSignals() may yield! */
405 if (anySigsDelivered && SignalSignals ())
407 FT_GetTimeOfDay(&junk, 0); /* force accurate time check */
410 register struct IoRequest *req;
411 struct TM_Elem *expired;
412 expired = TM_GetExpired(Requests);
413 if (expired == NULL) break;
415 req = (struct IoRequest *) expired -> BackPointer;
417 if (lwp_debug != 0) puts("[Polling SELECT]");
420 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
421 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
422 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
424 req->result = 0; /* no fds ready */
425 TM_Remove(Requests, &req->timeout);
427 req -> timeout.Next = (struct TM_Elem *) 2;
428 req -> timeout.Prev = (struct TM_Elem *) 2;
430 LWP_QSignal(req->pid);
431 req->pid->iomgrRequest = 0;
433 if (woke_someone) LWP_DispatchProcess();
434 } while (woke_someone);
436 /* Collect requests & update times */
437 FD_ZERO(&IOMGR_readfds);
438 FD_ZERO(&IOMGR_writefds);
439 FD_ZERO(&IOMGR_exceptfds);
442 FOR_ALL_ELTS(r, Requests, {
443 register struct IoRequest *req;
444 req = (struct IoRequest *) r -> BackPointer;
445 FDSetSet(req->nfds, &IOMGR_readfds, req->readfds);
446 FDSetSet(req->nfds, &IOMGR_writefds, req->writefds);
447 FDSetSet(req->nfds, &IOMGR_exceptfds, req->exceptfds);
448 if (req->nfds > IOMGR_nfds)
449 IOMGR_nfds = req->nfds;
451 earliest = TM_GetEarliest(Requests);
452 if (earliest != NULL) {
453 timeout = earliest -> TimeLeft;
458 if (lwp_debug != 0) {
461 printf("[Read Select:");
462 if (IOMGR_readfds.fd_count == 0)
465 for (idbg=0; idbg<IOMGR_readfds.fd_count; idbg++)
466 printf(" %d", IOMGR_readfds.fd_array[idbg]);
469 printf("[Write Select:");
470 if (IOMGR_writefds.fd_count == 0)
473 for (idbg=0; idbg<IOMGR_writefds.fd_count; idbg++)
474 printf(" %d", IOMGR_writefds.fd_array[idbg]);
477 printf("[Except Select:");
478 if (IOMGR_exceptfds.fd_count == 0)
481 for (idbg=0; idbg<IOMGR_exceptfds.fd_count; idbg++)
482 printf(" %d", IOMGR_exceptfds.fd_array[idbg]);
486 /* Only prints first 32. */
487 printf("[select(%d, 0x%x, 0x%x, 0x%x, ", IOMGR_nfds,
488 *(int*)&IOMGR_readfds, *(int*)&IOMGR_writefds,
489 *(int*)&IOMGR_exceptfds);
490 #endif /* AFS_NT40_ENV */
491 if (timeout.tv_sec == -1 && timeout.tv_usec == -1)
494 printf("<%d, %d>)]\n", timeout.tv_sec, timeout.tv_usec);
497 iomgr_timeout = timeout;
498 if (timeout.tv_sec == -1 && timeout.tv_usec == -1) {
499 /* infinite, sort of */
500 iomgr_timeout.tv_sec = 100000000;
501 iomgr_timeout.tv_usec = 0;
504 /* On NT, signals don't interrupt a select call. So this can potentially
505 * lead to long wait times before a signal is honored. To avoid this we
506 * dont do select() for longer than IOMGR_MAXWAITTIME (5 secs) */
507 if (iomgr_timeout.tv_sec > (IOMGR_MAXWAITTIME - 1)) {
508 iomgr_timeout.tv_sec = IOMGR_MAXWAITTIME;
509 iomgr_timeout.tv_usec = 0;
513 /* Check one last time for a signal delivery. If one comes after
514 this, the signal handler will set iomgr_timeout to zero, causing
515 the select to return immediately. The timer package won't return
516 a zero timeval because all of those guys were handled above.
518 I'm assuming that the kernel masks signals while it's picking up
519 the parameters to select. This may a bad assumption. -DN */
520 if (anySigsDelivered)
521 continue; /* go to the top and handle them. */
524 if (IOMGR_readfds.fd_count == 0 && IOMGR_writefds.fd_count == 0
525 && IOMGR_exceptfds.fd_count == 0) {
528 if (iomgr_timeout.tv_sec || iomgr_timeout.tv_usec) {
529 stime = iomgr_timeout.tv_sec * 1000
530 + iomgr_timeout.tv_usec/1000;
538 { /* select runs much faster if 0's are passed instead of &0s */
539 code = select(IOMGR_nfds,
540 (FDSetEmpty(IOMGR_nfds, &IOMGR_readfds)) ?
541 (fd_set*)0 : &IOMGR_readfds,
542 (FDSetEmpty(IOMGR_nfds, &IOMGR_writefds)) ?
543 (fd_set*)0 : &IOMGR_writefds,
544 (FDSetEmpty(IOMGR_nfds, &IOMGR_exceptfds)) ?
545 (fd_set*)0 : &IOMGR_exceptfds,
552 #if defined(AFS_SUN_ENV)
553 /* Tape drives on Sun boxes do not support select and return ENXIO */
554 if (errno == ENXIO) e=0, code=1;
556 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
557 /* For SGI and SVR4 - poll & select can return EAGAIN ... */
558 if (errno == EAGAIN) e=0;
560 #if defined(AFS_SUN5_ENV)
561 /* On sun4x_55, select doesn't block signal. It could be
562 interupted by a signal that changes iomgr_timeout, and
563 then select returns with EINVAL. In this case, we need
566 if (errno==EINVAL && anySigsDelivered)
568 #endif /* AFS_SUN5_ENV */
570 if ((errno != EINTR) && e) {
573 for(i=0; i<FD_SETSIZE; i++) {
574 if (fcntl(i, F_GETFD, 0) < 0 && errno == EBADF)
575 FD_SET(i, &openMask);
583 /* See what happened */
585 /* Action -- wake up everyone involved */
586 SignalIO(IOMGR_nfds, &IOMGR_readfds, &IOMGR_writefds,
587 &IOMGR_exceptfds, code);
590 && (iomgr_timeout.tv_sec != 0 || iomgr_timeout.tv_usec != 0)) {
591 /* Real timeout only if signal handler hasn't set
592 iomgr_timeout to zero. */
595 /* On NT, real timeout only if above and if iomgr_timeout
596 * interval is equal to timeout interval (i.e., not adjusted
597 * to check for pseudo-signals).
599 if (iomgr_timeout.tv_sec != timeout.tv_sec ||
600 iomgr_timeout.tv_usec != timeout.tv_usec) {
601 /* signal check interval timed out; not real timeout */
604 #endif /* AFS_NT40_ENV */
606 FT_GetTimeOfDay(&junk, 0);
607 SignalTimeout(code, &timeout);
610 LWP_DispatchProcess();
612 return -1; /* keeps compilers happy. */
615 /************************\
617 * Signalling routines *
619 \************************/
621 static void SignalIO(int fds, fd_set *readfds, fd_set *writefds,
622 fd_set *exceptfds, int code)
625 /* Look at everyone who's bit mask was affected */
626 FOR_ALL_ELTS(r, Requests, {
627 register struct IoRequest *req;
628 register PROCESS pid;
629 req = (struct IoRequest *) r -> BackPointer;
630 nfds = MIN(fds, req->nfds);
631 if (FDSetCmp(nfds, req->readfds, readfds) ||
632 FDSetCmp(nfds, req->writefds, writefds) ||
633 FDSetCmp(nfds, req->exceptfds, exceptfds)) {
634 /* put ready fd's into request. */
635 FDSetAnd(nfds, req->readfds, readfds);
636 FDSetAnd(nfds, req->writefds, writefds);
637 FDSetAnd(nfds, req->exceptfds, exceptfds);
638 req -> result = code;
639 TM_Remove(Requests, &req->timeout);
640 LWP_QSignal(pid=req->pid);
641 pid->iomgrRequest = 0;
646 static void SignalTimeout(int code, struct timeval *timeout)
648 /* Find everyone who has specified timeout */
649 FOR_ALL_ELTS(r, Requests, {
650 register struct IoRequest *req;
651 register PROCESS pid;
652 req = (struct IoRequest *) r -> BackPointer;
653 if (TM_eql(&r->TimeLeft, timeout)) {
654 req -> result = code;
655 TM_Remove(Requests, &req->timeout);
656 LWP_QSignal(pid=req->pid);
657 pid->iomgrRequest = 0;
663 /*****************************************************\
665 * Signal handling routine (not to be confused with *
666 * signalling routines, above). *
668 \*****************************************************/
669 static void SigHandler (signo)
672 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
673 return; /* can't happen. */
674 sigDelivered[signo] = TRUE;
675 anySigsDelivered = TRUE;
676 /* Make sure that the IOMGR process doesn't pause on the select. */
677 iomgr_timeout.tv_sec = 0;
678 iomgr_timeout.tv_usec = 0;
681 /* Alright, this is the signal signalling routine. It delivers LWP signals
682 to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
683 static int SignalSignals ()
690 anySigsDelivered = FALSE;
692 /* handle software signals */
693 stackSize = (AFS_LWP_MINSTACKSIZE < lwp_MaxStackSeen? lwp_MaxStackSeen : AFS_LWP_MINSTACKSIZE);
694 for (i=0; i < NSOFTSIG; i++) {
696 if (p=sigProc[i]) /* This yields!!! */
697 LWP_CreateProcess2(p, stackSize, LWP_NORMAL_PRIORITY, sigRock[i],
698 "SignalHandler", &pid);
702 for (i = 1; i <= NSIG; ++i) /* forall !badsig(i) */
703 if ((sigsHandled & mysigmask(i)) && sigDelivered[i] == TRUE) {
704 sigDelivered[i] = FALSE;
705 LWP_NoYieldSignal (sigEvents[i]);
712 /***************************\
714 * User-callable routines *
716 \***************************/
719 /* Keep IOMGR process id */
720 static PROCESS IOMGR_Id = NULL;
722 int IOMGR_SoftSig(aproc, arock)
726 for (i=0;i<NSOFTSIG;i++) {
727 if (sigProc[i] == 0) {
731 anySigsDelivered = TRUE;
732 iomgr_timeout.tv_sec = 0;
733 iomgr_timeout.tv_usec = 0;
741 unsigned char allOnes[100];
743 int IOMGR_Initialize(void)
745 extern int TM_Init();
748 /* If lready initialized, just return */
749 if (IOMGR_Id != NULL) return LWP_SUCCESS;
751 /* Init LWP if someone hasn't yet. */
752 if (LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY, &pid) != LWP_SUCCESS)
755 /* Initialize request lists */
756 if (TM_Init(&Requests) < 0) return -1;
758 /* Initialize signal handling stuff. */
760 anySigsDelivered = TRUE; /* A soft signal may have happened before
761 IOMGR_Initialize: so force a check for signals regardless */
762 memset(allOnes, 0xff, sizeof(allOnes));
764 return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, 0, "IO MANAGER",
774 status = LWP_DestroyProcess(IOMGR_Id);
779 /* signal I/O for anyone who is waiting for a FD or a timeout; not too cheap,
780 * since forces select and timeofday check */
781 int IOMGR_Poll(void) {
782 fd_set *readfds, *writefds, *exceptfds;
787 FT_GetTimeOfDay(&tv, 0); /* force accurate time check */
790 register struct IoRequest *req;
791 struct TM_Elem *expired;
792 expired = TM_GetExpired(Requests);
793 if (expired == NULL) break;
794 req = (struct IoRequest *) expired -> BackPointer;
796 if (lwp_debug != 0) puts("[Polling SELECT]");
799 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
800 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
801 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
803 req->result = 0; /* no fds ready */
804 TM_Remove(Requests, &req->timeout);
806 req -> timeout.Next = (struct TM_Elem *) 2;
807 req -> timeout.Prev = (struct TM_Elem *) 2;
809 LWP_QSignal(req->pid);
810 req->pid->iomgrRequest = 0;
813 /* Collect requests & update times */
814 readfds = IOMGR_AllocFDSet();
815 writefds = IOMGR_AllocFDSet();
816 exceptfds = IOMGR_AllocFDSet();
817 if (!(readfds && writefds && exceptfds)) {
818 fprintf(stderr, "IOMGR_Poll: Could not malloc space for fd_sets.\n");
824 FOR_ALL_ELTS(r, Requests, {
825 register struct IoRequest *req;
826 req = (struct IoRequest *) r -> BackPointer;
827 FDSetSet(req->nfds, readfds, req->readfds);
828 FDSetSet(req->nfds, writefds, req->writefds);
829 FDSetSet(req->nfds, exceptfds, req->exceptfds);
838 if (readfds->fd_count == 0 && writefds->fd_count == 0
839 && exceptfds->fd_count == 0)
841 code = select(fds, readfds, writefds, exceptfds, &tv);
843 SignalIO(fds, readfds, writefds, exceptfds, code);
846 if (readfds) IOMGR_FreeFDSet(readfds);
847 if (writefds) IOMGR_FreeFDSet(writefds);
848 if (exceptfds) IOMGR_FreeFDSet(exceptfds);
851 LWP_DispatchProcess(); /* make sure others run */
852 LWP_DispatchProcess();
856 int IOMGR_Select(fds, readfds, writefds, exceptfds, timeout)
858 fd_set *readfds, *writefds, *exceptfds;
859 struct timeval *timeout;
861 register struct IoRequest *request;
865 if(fds > FD_SETSIZE) {
866 fprintf(stderr, "IOMGR_Select: fds=%d, more than max %d\n",
873 /* See if polling request. If so, handle right here */
874 if (timeout != NULL) {
875 if (timeout->tv_sec == 0 && timeout->tv_usec == 0) {
878 if (lwp_debug != 0) puts("[Polling SELECT]");
881 code = select(fds, readfds, writefds, exceptfds, timeout);
882 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
884 * For SGI and SVR4 - poll & select can return EAGAIN ...
887 * this is basically for SGI, but I believe stock SVR4 (Solaris?)
888 * can also get this error return
890 if (code < 0 && errno == EAGAIN)
894 if (code == SOCKET_ERROR) {
895 if (WSAGetLastError() == WSAEINPROGRESS)
901 return (code > 1 ? 1 : code);
905 /* Construct request block & insert */
906 request = NewRequest(); /* zeroes fd_set's */
907 if (readfds && !FDSetEmpty(fds, readfds))
908 request->readfds = readfds;
909 if (writefds && !FDSetEmpty(fds, writefds))
910 request->writefds = writefds;
911 if (exceptfds && !FDSetEmpty(fds, exceptfds))
912 request->exceptfds = exceptfds;
915 if (timeout == NULL) {
916 request -> timeout.TotalTime.tv_sec = -1;
917 request -> timeout.TotalTime.tv_usec = -1;
919 request -> timeout.TotalTime = *timeout;
920 /* check for bad request */
921 if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999) {
923 iomgr_badtv = *timeout;
924 iomgr_badpid = LWP_ActiveProcess;
925 /* now fixup request */
926 if(request->timeout.TotalTime.tv_sec < 0)
927 request->timeout.TotalTime.tv_sec = 1;
928 request->timeout.TotalTime.tv_usec = 100000;
932 request -> timeout.BackPointer = (char *) request;
934 /* Insert my PID in case of IOMGR_Cancel */
935 request -> pid = LWP_ActiveProcess;
936 LWP_ActiveProcess -> iomgrRequest = request;
939 request -> timeout.Next = (struct TM_Elem *) 1;
940 request -> timeout.Prev = (struct TM_Elem *) 1;
942 TM_Insert(Requests, &request->timeout);
944 /* Wait for action */
947 /* Update parameters & return */
948 result = request -> result;
950 FreeRequest(request);
951 return (result > 1 ? 1 : result);
954 int IOMGR_Cancel(PROCESS pid)
956 register struct IoRequest *request;
958 if ((request = pid->iomgrRequest) == 0) return -1; /* Pid not found */
960 if (request->readfds) FD_N_ZERO(request->nfds, request->readfds);
961 if (request->writefds) FD_N_ZERO(request->nfds, request->writefds);
962 if (request->exceptfds) FD_N_ZERO(request->nfds, request->exceptfds);
965 request -> result = -2;
966 TM_Remove(Requests, &request->timeout);
968 request -> timeout.Next = (struct TM_Elem *) 5;
969 request -> timeout.Prev = (struct TM_Elem *) 5;
971 LWP_QSignal(request->pid);
972 pid->iomgrRequest = 0;
978 /* Cause delivery of signal signo to result in a LWP_SignalProcess of
980 IOMGR_Signal (signo, event)
989 return LWP_EBADEVENT;
990 sa.sa_handler = SigHandler;
991 sa.sa_mask = *((sigset_t *) allOnes); /* mask all signals */
993 sigsHandled |= mysigmask(signo);
994 sigEvents[signo] = event;
995 sigDelivered[signo] = FALSE;
996 if (sigaction (signo, &sa, &oldActions[signo]) == -1)
1001 /* Stop handling occurrences of signo. */
1002 IOMGR_CancelSignal (signo)
1005 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
1007 sigaction (signo, &oldActions[signo], (struct sigaction *)0);
1008 sigsHandled &= ~mysigmask(signo);
1011 #endif /* AFS_NT40_ENV */
1012 /* This routine calls select is a fashion that simulates the standard sleep routine */
1013 void IOMGR_Sleep (int seconds)
1015 struct timeval timeout;
1017 timeout.tv_sec = seconds;
1018 timeout.tv_usec = 0;
1019 IOMGR_Select(0, 0, 0, 0, &timeout);
1021 #endif /* USE_PTHREADS */