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>
41 #ifdef HAVE_SYS_SELECT_H
42 #include <sys/select.h>
50 typedef unsigned char bool;
55 #define MIN(a,b) (((a)>(b)) ? (b) : (a))
59 #define NSIG 8*sizeof(sigset_t)
62 static int SignalSignals(void);
64 /********************************\
66 * Stuff for managing IoRequests *
68 \********************************/
72 /* Pid of process making request (for use in IOMGR_Cancel */
75 /* Descriptor masks for requests */
81 struct TM_Elem timeout
;
83 /* Result of select call */
86 struct IoRequest
*next
; /* for iorFreeList */
90 /********************************\
92 * Stuff for managing signals *
94 \********************************/
96 #define badsig(signo) (((signo) <= 0) || ((signo) >= NSIG))
97 #define mysigmask(signo) (1 << ((signo)-1))
100 fd_set openMask
; /* mask of open files on an IOMGR abort */
101 static afs_int32 sigsHandled
; /* sigmask(signo) is on if we handle signo */
102 static int anySigsDelivered
; /* true if any have been delivered. */
104 static struct sigaction oldActions
[NSIG
]; /* the old signal vectors */
106 static char *sigEvents
[NSIG
]; /* the event to do an LWP signal on */
107 static int sigDelivered
[NSIG
]; /* True for signals delivered so far.
108 This is an int array to make sure
109 there are no conflicts when trying
111 /* software 'signals' */
113 static void *(*sigProc
[NSOFTSIG
])(void *);
114 static void *sigRock
[NSOFTSIG
];
117 static struct IoRequest
*iorFreeList
= 0;
119 static struct TM_Elem
*Requests
; /* List of requests */
120 static struct timeval iomgr_timeout
; /* global so signal handler can zap it */
122 /* stuff for debugging */
123 static int iomgr_errno
;
124 static struct timeval iomgr_badtv
;
125 static PROCESS iomgr_badpid
;
126 static void SignalIO(int fds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*efs
,
128 static void SignalTimeout(int code
, struct timeval
*timeout
);
130 /* fd_set pool managment.
131 * Use the pool instead of creating fd_set's on the stack. fd_set's can be
132 * 8K in size, so making three could put 24K in the limited space of an LWP
135 struct IOMGR_fd_set
{
136 struct IOMGR_fd_set
*next
;
137 } *iomgrFreeFDSets
= (struct IOMGR_fd_set
*)0;
140 * Return fd_set to the free list.
142 void IOMGR_FreeFDSet(fd_set
*s
)
144 struct IOMGR_fd_set
*t
= (struct IOMGR_fd_set
*)s
;
146 t
->next
= iomgrFreeFDSets
;
151 * returns a zeroed fd_set or null if could not malloc one.
153 fd_set
*IOMGR_AllocFDSet(void)
156 if (iomgrFreeFDSets
) {
157 t
= (fd_set
*) iomgrFreeFDSets
;
158 iomgrFreeFDSets
= iomgrFreeFDSets
->next
;
161 t
= malloc(sizeof(fd_set
));
171 #define FreeRequest(x) ((x)->next = iorFreeList, iorFreeList = (x))
173 static struct IoRequest
*NewRequest(void)
175 struct IoRequest
*request
;
177 if ((request
=iorFreeList
)) {
178 iorFreeList
= (struct IoRequest
*) (request
->next
);
179 memset(request
, 0, sizeof(struct IoRequest
));
180 } else request
= calloc(1, sizeof(struct IoRequest
));
185 #define Purge(list) FOR_ALL_ELTS(req, list, { free(req->BackPointer); })
188 /* FD_SET support routines. All assume the fd_set size is a multiple of an int
189 * so we can at least do logical operations on ints instead of chars.
191 * For each routine, nfds is the highest bit set in either fd_set, starting
195 #define FD_N_ZERO(A, x) FD_ZERO(x)
197 #define FDS_P_POS (sizeof(int)*8)
198 #define INTS_PER_FDS(x) (((x)+(FDS_P_POS-1)) / FDS_P_POS)
199 #define FD_N_ZERO(nfds, x) memset((char*)(x), 0, (INTS_PER_FDS(nfds))*sizeof(int))
202 /* On Linux without __USE_XOPEN, we have __fds_bits. With __USE_XOPEN, or
203 * non-Linux, we have fds_bits. */
204 #if defined(AFS_LINUX22_ENV) && (__GLIBC_MINOR__ > 0) && !defined(__USE_XOPEN)
205 # define FDS_BITS __fds_bits
207 # define FDS_BITS fds_bits
210 /* FDSetCmp - returns 1 if any bits in fd_set1 are also set in fd_set2.
211 * If nfds is 0, or one of the fd_sets is null return 0 (since there is no bit
212 * set in both fd_sets).
214 static int FDSetCmp(int nfds
, fd_set
*fd_set1
, fd_set
*fd_set2
)
218 if (fd_set1
== (fd_set
*)0 || fd_set2
== (fd_set
*)0)
222 if (fd_set1
->fd_count
== 0 || fd_set2
->fd_count
== 0)
225 for (i
=0; i
<fd_set1
->fd_count
; i
++) {
226 for (j
=0; j
<fd_set2
->fd_count
; j
++) {
227 if (fd_set1
->fd_array
[i
] == fd_set2
->fd_array
[j
])
235 j
= INTS_PER_FDS(nfds
);
236 for (i
=0; i
<j
; i
++) {
237 if (fd_set1
->FDS_BITS
[i
] & fd_set2
->FDS_BITS
[i
])
244 /* FDSetSet - set bits from fd_set2 into fd_set1
246 static void FDSetSet(int nfds
, fd_set
*fd_set1
, fd_set
*fd_set2
)
253 if (fd_set1
== (fd_set
*)0 || fd_set2
== (fd_set
*)0)
257 if (fd_set2
->fd_count
==0)
260 for (i
=0; i
<fd_set2
->fd_count
; i
++)
261 FD_SET(fd_set2
->fd_array
[i
], fd_set1
);
266 for (i
= 0, n
= INTS_PER_FDS(nfds
); i
< n
; i
++) {
267 fd_set1
->FDS_BITS
[i
] |= fd_set2
->FDS_BITS
[i
];
272 /* FDSetAnd - fd_set1 <- fd_set1 & fd_set2.
275 static void FDSetAnd(int nfds
, fd_set
*fd_set1
, fd_set
*fd_set2
)
280 if (fd_set1
== NULL
|| fd_set1
->fd_count
== 0)
283 if (fd_set2
== NULL
|| fd_set2
->fd_count
== 0) {
288 for (i
=0; i
<fd_set2
->fd_count
; i
++) {
289 if (FD_ISSET(fd_set2
->fd_array
[i
], fd_set1
))
290 FD_SET(fd_set2
->fd_array
[i
], &tmpset
);
296 static void FDSetAnd(int nfds
, fd_set
*fd_set1
, fd_set
*fd_set2
)
300 if (nfds
== 0 || fd_set1
== (fd_set
*)0 || fd_set2
== (fd_set
*)0)
303 n
= INTS_PER_FDS(nfds
);
304 for (i
=0; i
<n
; i
++) {
305 fd_set1
->FDS_BITS
[i
] &= fd_set2
->FDS_BITS
[i
];
310 /* FDSetEmpty - return true if fd_set is empty
312 static int FDSetEmpty(int nfds
, fd_set
*fds
)
320 if (fds
== (fd_set
*)0)
324 if (fds
->fd_count
== 0)
329 n
= INTS_PER_FDS(nfds
);
331 for (i
=n
-1; i
>=0; i
--) {
332 if (fds
->FDS_BITS
[i
])
343 /* The IOMGR process */
346 * Important invariant: process->iomgrRequest is null iff request not in timer
348 * also, request->pid is valid while request is in queue,
349 * also, don't signal selector while request in queue, since selector frees
353 /* These are not declared in IOMGR so that they don't use up 6K of stack. */
354 static fd_set IOMGR_readfds
, IOMGR_writefds
, IOMGR_exceptfds
;
355 static int IOMGR_nfds
= 0;
357 static void *IOMGR(void *dummy
)
361 struct TM_Elem
*earliest
;
362 struct timeval timeout
, junk
;
365 FD_ZERO(&IOMGR_readfds
);
366 FD_ZERO(&IOMGR_writefds
);
367 FD_ZERO(&IOMGR_exceptfds
);
370 /* Wake up anyone who has expired or who has received a
371 Unix signal between executions. Keep going until we
374 woke_someone
= FALSE
;
375 /* Wake up anyone waiting on signals. */
376 /* Note: SignalSignals() may yield! */
377 if (anySigsDelivered
&& SignalSignals ())
379 FT_GetTimeOfDay(&junk
, 0); /* force accurate time check */
382 struct IoRequest
*req
;
383 struct TM_Elem
*expired
;
384 expired
= TM_GetExpired(Requests
);
385 if (expired
== NULL
) break;
387 req
= (struct IoRequest
*) expired
-> BackPointer
;
389 if (lwp_debug
!= 0) puts("[Polling SELECT]");
392 if (req
->readfds
) FD_N_ZERO(req
->nfds
, req
->readfds
);
393 if (req
->writefds
) FD_N_ZERO(req
->nfds
, req
->writefds
);
394 if (req
->exceptfds
) FD_N_ZERO(req
->nfds
, req
->exceptfds
);
396 req
->result
= 0; /* no fds ready */
397 TM_Remove(Requests
, &req
->timeout
);
399 req
-> timeout
.Next
= (struct TM_Elem
*) 2;
400 req
-> timeout
.Prev
= (struct TM_Elem
*) 2;
402 LWP_QSignal(req
->pid
);
403 req
->pid
->iomgrRequest
= 0;
406 if (woke_someone
) LWP_DispatchProcess();
407 } while (woke_someone
);
409 /* Collect requests & update times */
410 FD_ZERO(&IOMGR_readfds
);
411 FD_ZERO(&IOMGR_writefds
);
412 FD_ZERO(&IOMGR_exceptfds
);
415 FOR_ALL_ELTS(r
, Requests
, {
416 struct IoRequest
*req
;
417 req
= (struct IoRequest
*) r
-> BackPointer
;
418 FDSetSet(req
->nfds
, &IOMGR_readfds
, req
->readfds
);
419 FDSetSet(req
->nfds
, &IOMGR_writefds
, req
->writefds
);
420 FDSetSet(req
->nfds
, &IOMGR_exceptfds
, req
->exceptfds
);
421 if (req
->nfds
> IOMGR_nfds
)
422 IOMGR_nfds
= req
->nfds
;
424 earliest
= TM_GetEarliest(Requests
);
425 if (earliest
!= NULL
) {
426 timeout
= earliest
-> TimeLeft
;
431 if (lwp_debug
!= 0) {
434 printf("[Read Select:");
435 if (IOMGR_readfds
.fd_count
== 0)
438 for (idbg
=0; idbg
<IOMGR_readfds
.fd_count
; idbg
++)
439 printf(" %d", IOMGR_readfds
.fd_array
[idbg
]);
442 printf("[Write Select:");
443 if (IOMGR_writefds
.fd_count
== 0)
446 for (idbg
=0; idbg
<IOMGR_writefds
.fd_count
; idbg
++)
447 printf(" %d", IOMGR_writefds
.fd_array
[idbg
]);
450 printf("[Except Select:");
451 if (IOMGR_exceptfds
.fd_count
== 0)
454 for (idbg
=0; idbg
<IOMGR_exceptfds
.fd_count
; idbg
++)
455 printf(" %d", IOMGR_exceptfds
.fd_array
[idbg
]);
459 /* Only prints first 32. */
460 printf("[select(%d, 0x%x, 0x%x, 0x%x, ", IOMGR_nfds
,
461 *(int*)&IOMGR_readfds
, *(int*)&IOMGR_writefds
,
462 *(int*)&IOMGR_exceptfds
);
463 #endif /* AFS_NT40_ENV */
464 if (timeout
.tv_sec
== -1 && timeout
.tv_usec
== -1)
467 printf("<%d, %d>)]\n", timeout
.tv_sec
, timeout
.tv_usec
);
470 iomgr_timeout
= timeout
;
471 if (timeout
.tv_sec
== -1 && timeout
.tv_usec
== -1) {
472 /* infinite, sort of */
473 iomgr_timeout
.tv_sec
= 100000000;
474 iomgr_timeout
.tv_usec
= 0;
476 #if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV)
477 /* On NT, signals don't interrupt a select call. So this can potentially
478 * lead to long wait times before a signal is honored. To avoid this we
479 * dont do select() for longer than IOMGR_MAXWAITTIME (5 secs) */
480 /* Whereas Linux seems to sometimes "lose" signals */
481 if (iomgr_timeout
.tv_sec
> (IOMGR_MAXWAITTIME
- 1)) {
482 iomgr_timeout
.tv_sec
= IOMGR_MAXWAITTIME
;
483 iomgr_timeout
.tv_usec
= 0;
487 /* Check one last time for a signal delivery. If one comes after
488 this, the signal handler will set iomgr_timeout to zero, causing
489 the select to return immediately. The timer package won't return
490 a zero timeval because all of those guys were handled above.
492 I'm assuming that the kernel masks signals while it's picking up
493 the parameters to select. This may a bad assumption. -DN */
494 if (anySigsDelivered
)
495 continue; /* go to the top and handle them. */
498 if (IOMGR_readfds
.fd_count
== 0 && IOMGR_writefds
.fd_count
== 0
499 && IOMGR_exceptfds
.fd_count
== 0) {
502 if (iomgr_timeout
.tv_sec
|| iomgr_timeout
.tv_usec
) {
503 stime
= iomgr_timeout
.tv_sec
* 1000
504 + iomgr_timeout
.tv_usec
/1000;
512 { /* select runs much faster if 0's are passed instead of &0s */
513 code
= select(IOMGR_nfds
,
514 (FDSetEmpty(IOMGR_nfds
, &IOMGR_readfds
)) ?
515 (fd_set
*)0 : &IOMGR_readfds
,
516 (FDSetEmpty(IOMGR_nfds
, &IOMGR_writefds
)) ?
517 (fd_set
*)0 : &IOMGR_writefds
,
518 (FDSetEmpty(IOMGR_nfds
, &IOMGR_exceptfds
)) ?
519 (fd_set
*)0 : &IOMGR_exceptfds
,
526 #if defined(AFS_SUN_ENV)
527 /* Tape drives on Sun boxes do not support select and return ENXIO */
528 if (errno
== ENXIO
) e
=0, code
=1;
530 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
531 /* For SGI and SVR4 - poll & select can return EAGAIN ... */
532 if (errno
== EAGAIN
) e
=0;
534 #if defined(AFS_SUN5_ENV)
535 /* On sun4x_55, select doesn't block signal. It could be
536 interupted by a signal that changes iomgr_timeout, and
537 then select returns with EINVAL. In this case, we need
540 if (errno
==EINVAL
&& anySigsDelivered
)
542 #endif /* AFS_SUN5_ENV */
544 if ((errno
!= EINTR
) && e
) {
547 for(i
=0; i
<FD_SETSIZE
; i
++) {
548 if (fcntl(i
, F_GETFD
, 0) < 0 && errno
== EBADF
)
549 FD_SET(i
, &openMask
);
557 /* See what happened */
559 /* Action -- wake up everyone involved */
560 SignalIO(IOMGR_nfds
, &IOMGR_readfds
, &IOMGR_writefds
,
561 &IOMGR_exceptfds
, code
);
564 && (iomgr_timeout
.tv_sec
!= 0 || iomgr_timeout
.tv_usec
!= 0)) {
565 /* Real timeout only if signal handler hasn't set
566 iomgr_timeout to zero. */
568 #if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV)
569 /* On NT, real timeout only if above and if iomgr_timeout
570 * interval is equal to timeout interval (i.e., not adjusted
571 * to check for pseudo-signals).
573 /* And also for Linux as above */
574 if (iomgr_timeout
.tv_sec
!= timeout
.tv_sec
||
575 iomgr_timeout
.tv_usec
!= timeout
.tv_usec
) {
576 /* signal check interval timed out; not real timeout */
579 #endif /* AFS_NT40_ENV */
580 FT_GetTimeOfDay(&junk
, 0);
581 SignalTimeout(code
, &timeout
);
584 LWP_DispatchProcess();
586 AFS_UNREACHED(return((void *)-1)); /* keeps compilers happy. */
589 /************************\
591 * Signalling routines *
593 \************************/
595 static void SignalIO(int fds
, fd_set
*readfds
, fd_set
*writefds
,
596 fd_set
*exceptfds
, int code
)
599 /* Look at everyone who's bit mask was affected */
600 FOR_ALL_ELTS(r
, Requests
, {
601 struct IoRequest
*req
;
603 req
= (struct IoRequest
*) r
-> BackPointer
;
604 nfds
= MIN(fds
, req
->nfds
);
605 if (FDSetCmp(nfds
, req
->readfds
, readfds
) ||
606 FDSetCmp(nfds
, req
->writefds
, writefds
) ||
607 FDSetCmp(nfds
, req
->exceptfds
, exceptfds
)) {
608 /* put ready fd's into request. */
609 FDSetAnd(nfds
, req
->readfds
, readfds
);
610 FDSetAnd(nfds
, req
->writefds
, writefds
);
611 FDSetAnd(nfds
, req
->exceptfds
, exceptfds
);
612 req
-> result
= code
;
613 TM_Remove(Requests
, &req
->timeout
);
614 LWP_QSignal(pid
=req
->pid
);
615 pid
->iomgrRequest
= 0;
620 static void SignalTimeout(int code
, struct timeval
*timeout
)
622 /* Find everyone who has specified timeout */
623 FOR_ALL_ELTS(r
, Requests
, {
624 struct IoRequest
*req
;
626 req
= (struct IoRequest
*) r
-> BackPointer
;
627 if (TM_eql(&r
->TimeLeft
, timeout
)) {
628 req
-> result
= code
;
629 TM_Remove(Requests
, &req
->timeout
);
630 LWP_QSignal(pid
=req
->pid
);
631 pid
->iomgrRequest
= 0;
637 /*****************************************************\
639 * Signal handling routine (not to be confused with *
640 * signalling routines, above). *
642 \*****************************************************/
643 static void SigHandler (int signo
)
645 if (badsig(signo
) || (sigsHandled
& mysigmask(signo
)) == 0)
646 return; /* can't happen. */
647 sigDelivered
[signo
] = TRUE
;
648 anySigsDelivered
= TRUE
;
649 /* Make sure that the IOMGR process doesn't pause on the select. */
650 iomgr_timeout
.tv_sec
= 0;
651 iomgr_timeout
.tv_usec
= 0;
654 /* Alright, this is the signal signalling routine. It delivers LWP signals
655 to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
656 static int SignalSignals (void)
663 anySigsDelivered
= FALSE
;
665 /* handle software signals */
666 stackSize
= (AFS_LWP_MINSTACKSIZE
< lwp_MaxStackSeen
? lwp_MaxStackSeen
: AFS_LWP_MINSTACKSIZE
);
667 for (i
=0; i
< NSOFTSIG
; i
++) {
669 if ((p
=sigProc
[i
])) /* This yields!!! */
670 LWP_CreateProcess2(p
, stackSize
, LWP_NORMAL_PRIORITY
,
671 sigRock
[i
], "SignalHandler", &pid
);
675 for (i
= 1; i
< NSIG
; ++i
) /* forall !badsig(i) */
676 if ((sigsHandled
& mysigmask(i
)) && sigDelivered
[i
] == TRUE
) {
677 sigDelivered
[i
] = FALSE
;
678 LWP_NoYieldSignal (sigEvents
[i
]);
685 /***************************\
687 * User-callable routines *
689 \***************************/
692 /* Keep IOMGR process id */
693 static PROCESS IOMGR_Id
= NULL
;
695 int IOMGR_SoftSig(void *(*aproc
)(void *), void *arock
)
698 for (i
=0;i
<NSOFTSIG
;i
++) {
699 if (sigProc
[i
] == 0) {
703 anySigsDelivered
= TRUE
;
704 iomgr_timeout
.tv_sec
= 0;
705 iomgr_timeout
.tv_usec
= 0;
713 int IOMGR_Initialize(void)
717 /* If lready initialized, just return */
718 if (IOMGR_Id
!= NULL
) return LWP_SUCCESS
;
720 /* Init LWP if someone hasn't yet. */
721 if (LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY
, &pid
) != LWP_SUCCESS
)
724 /* Initialize request lists */
725 if (TM_Init(&Requests
) < 0) return -1;
727 /* Initialize signal handling stuff. */
729 anySigsDelivered
= TRUE
; /* A soft signal may have happened before
730 IOMGR_Initialize: so force a check for signals regardless */
732 return LWP_CreateProcess(IOMGR
, AFS_LWP_MINSTACKSIZE
, 0, (void *) 0,
733 "IO MANAGER", &IOMGR_Id
);
736 int IOMGR_Finalize(void)
742 status
= LWP_DestroyProcess(IOMGR_Id
);
747 /* signal I/O for anyone who is waiting for a FD or a timeout; not too cheap,
748 * since forces select and timeofday check */
749 int IOMGR_Poll(void) {
750 fd_set
*readfds
, *writefds
, *exceptfds
;
755 FT_GetTimeOfDay(&tv
, 0); /* force accurate time check */
758 struct IoRequest
*req
;
759 struct TM_Elem
*expired
;
760 expired
= TM_GetExpired(Requests
);
761 if (expired
== NULL
) break;
762 req
= (struct IoRequest
*) expired
-> BackPointer
;
764 if (lwp_debug
!= 0) puts("[Polling SELECT]");
767 if (req
->readfds
) FD_N_ZERO(req
->nfds
, req
->readfds
);
768 if (req
->writefds
) FD_N_ZERO(req
->nfds
, req
->writefds
);
769 if (req
->exceptfds
) FD_N_ZERO(req
->nfds
, req
->exceptfds
);
771 req
->result
= 0; /* no fds ready */
772 TM_Remove(Requests
, &req
->timeout
);
774 req
-> timeout
.Next
= (struct TM_Elem
*) 2;
775 req
-> timeout
.Prev
= (struct TM_Elem
*) 2;
777 LWP_QSignal(req
->pid
);
778 req
->pid
->iomgrRequest
= 0;
781 /* Collect requests & update times */
782 readfds
= IOMGR_AllocFDSet();
783 writefds
= IOMGR_AllocFDSet();
784 exceptfds
= IOMGR_AllocFDSet();
785 if (!(readfds
&& writefds
&& exceptfds
)) {
786 fprintf(stderr
, "IOMGR_Poll: Could not malloc space for fd_sets.\n");
792 FOR_ALL_ELTS(r
, Requests
, {
793 struct IoRequest
*req
;
794 req
= (struct IoRequest
*) r
-> BackPointer
;
795 FDSetSet(req
->nfds
, readfds
, req
->readfds
);
796 FDSetSet(req
->nfds
, writefds
, req
->writefds
);
797 FDSetSet(req
->nfds
, exceptfds
, req
->exceptfds
);
806 if (readfds
->fd_count
== 0 && writefds
->fd_count
== 0
807 && exceptfds
->fd_count
== 0)
809 code
= select(fds
, readfds
, writefds
, exceptfds
, &tv
);
811 SignalIO(fds
, readfds
, writefds
, exceptfds
, code
);
814 if (readfds
) IOMGR_FreeFDSet(readfds
);
815 if (writefds
) IOMGR_FreeFDSet(writefds
);
816 if (exceptfds
) IOMGR_FreeFDSet(exceptfds
);
819 LWP_DispatchProcess(); /* make sure others run */
820 LWP_DispatchProcess();
824 int IOMGR_Select(int fds
, fd_set
*readfds
, fd_set
*writefds
,
825 fd_set
*exceptfds
, struct timeval
*timeout
)
827 struct IoRequest
*request
;
831 if(fds
> FD_SETSIZE
) {
832 fprintf(stderr
, "IOMGR_Select: fds=%d, more than max %d\n",
839 /* See if polling request. If so, handle right here */
840 if (timeout
!= NULL
) {
841 if (timeout
->tv_sec
== 0 && timeout
->tv_usec
== 0) {
844 if (lwp_debug
!= 0) puts("[Polling SELECT]");
846 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_NT40_ENV)
849 code
= select(fds
, readfds
, writefds
, exceptfds
, timeout
);
850 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
852 * For SGI and SVR4 - poll & select can return EAGAIN ...
855 * this is basically for SGI, but I believe stock SVR4 (Solaris?)
856 * can also get this error return
858 if (code
< 0 && errno
== EAGAIN
)
862 if (code
== SOCKET_ERROR
) {
863 if (WSAGetLastError() == WSAEINPROGRESS
)
869 return (code
> 1 ? 1 : code
);
873 /* Construct request block & insert */
874 request
= NewRequest(); /* zeroes fd_set's */
875 if (readfds
&& !FDSetEmpty(fds
, readfds
))
876 request
->readfds
= readfds
;
877 if (writefds
&& !FDSetEmpty(fds
, writefds
))
878 request
->writefds
= writefds
;
879 if (exceptfds
&& !FDSetEmpty(fds
, exceptfds
))
880 request
->exceptfds
= exceptfds
;
883 if (timeout
== NULL
) {
884 request
-> timeout
.TotalTime
.tv_sec
= -1;
885 request
-> timeout
.TotalTime
.tv_usec
= -1;
887 request
-> timeout
.TotalTime
= *timeout
;
888 /* check for bad request */
889 if (timeout
->tv_sec
< 0 || timeout
->tv_usec
< 0 || timeout
->tv_usec
> 999999) {
891 iomgr_badtv
= *timeout
;
892 iomgr_badpid
= LWP_ActiveProcess
;
893 /* now fixup request */
894 if(request
->timeout
.TotalTime
.tv_sec
< 0)
895 request
->timeout
.TotalTime
.tv_sec
= 1;
896 request
->timeout
.TotalTime
.tv_usec
= 100000;
900 request
-> timeout
.BackPointer
= (char *) request
;
902 /* Insert my PID in case of IOMGR_Cancel */
903 request
-> pid
= LWP_ActiveProcess
;
904 LWP_ActiveProcess
-> iomgrRequest
= request
;
907 request
-> timeout
.Next
= (struct TM_Elem
*) 1;
908 request
-> timeout
.Prev
= (struct TM_Elem
*) 1;
910 TM_Insert(Requests
, &request
->timeout
);
912 /* Wait for action */
915 /* Update parameters & return */
916 result
= request
-> result
;
918 FreeRequest(request
);
919 return (result
> 1 ? 1 : result
);
922 int IOMGR_Cancel(PROCESS pid
)
924 struct IoRequest
*request
;
926 if ((request
= pid
->iomgrRequest
) == 0) return -1; /* Pid not found */
928 if (request
->readfds
) FD_N_ZERO(request
->nfds
, request
->readfds
);
929 if (request
->writefds
) FD_N_ZERO(request
->nfds
, request
->writefds
);
930 if (request
->exceptfds
) FD_N_ZERO(request
->nfds
, request
->exceptfds
);
933 request
-> result
= -2;
934 TM_Remove(Requests
, &request
->timeout
);
936 request
-> timeout
.Next
= (struct TM_Elem
*) 5;
937 request
-> timeout
.Prev
= (struct TM_Elem
*) 5;
939 LWP_QSignal(request
->pid
);
940 pid
->iomgrRequest
= 0;
946 /* Cause delivery of signal signo to result in a LWP_SignalProcess of
948 int IOMGR_Signal (int signo
, char *event
)
955 return LWP_EBADEVENT
;
956 sa
.sa_handler
= SigHandler
;
957 sigfillset(&sa
.sa_mask
); /* mask all signals */
959 sigsHandled
|= mysigmask(signo
);
960 sigEvents
[signo
] = event
;
961 sigDelivered
[signo
] = FALSE
;
962 if (sigaction (signo
, &sa
, &oldActions
[signo
]) == -1)
967 /* Stop handling occurrences of signo. */
968 int IOMGR_CancelSignal (int signo
)
970 if (badsig(signo
) || (sigsHandled
& mysigmask(signo
)) == 0)
972 sigaction (signo
, &oldActions
[signo
], NULL
);
973 sigsHandled
&= ~mysigmask(signo
);
976 #endif /* AFS_NT40_ENV */
977 /* This routine calls select is a fashion that simulates the standard sleep routine */
978 void IOMGR_Sleep (int seconds
)
980 struct timeval timeout
;
982 timeout
.tv_sec
= seconds
;
984 IOMGR_Select(0, 0, 0, 0, &timeout
);