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 #include <afsconfig.h>
25 #include <afs/param.h>
35 extern void lwp_abort(void);
37 #include <unistd.h> /* select() prototype */
38 #include <sys/types.h> /* fd_set on older platforms */
39 #include <sys/time.h> /* struct timeval, select() prototype */
41 # include <sys/select.h> /* fd_set on newer platforms */
44 #endif /* AFS_NT40_ENV */
53 #include "dosdefs95.h"
54 #include "netbios95.h"
55 #include <sys/socket.h>
56 #include <sys/farptr.h>
60 int _crt0_startup_flags = _CRT0_FLAG_LOCK_MEMORY;
61 #endif /* AFS_DJGPP_ENV */
63 #if defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
65 void IOMGR_Initialize() /* noop */
68 void IOMGR_Sleep (seconds)
75 assert(pthread_mutex_unlock(&lwp_mutex) == 0);
76 assert(pthread_delay_np(&itv) == 0);
77 assert(pthread_mutex_lock(&lwp_mutex) == 0);
83 extern void *malloc();
84 #endif /* AFS_DECOSF_ENV */
86 typedef unsigned char bool;
91 #define MIN(a,b) ((a)>(b)) ? b : a
95 #define NSIG 8*sizeof(sigset_t)
98 static int SignalSignals();
100 /********************************\
102 * Stuff for managing IoRequests *
104 \********************************/
108 /* Pid of process making request (for use in IOMGR_Cancel */
111 /* Descriptor masks for requests */
117 struct TM_Elem timeout;
119 /* Result of select call */
125 #endif /* AFS_DJGPP_ENV */
129 /********************************\
131 * Stuff for managing signals *
133 \********************************/
135 #define badsig(signo) (((signo) <= 0) || ((signo) >= NSIG))
136 #define mysigmask(signo) (1 << ((signo)-1))
139 fd_set openMask; /* mask of open files on an IOMGR abort */
140 static afs_int32 sigsHandled; /* sigmask(signo) is on if we handle signo */
141 static int anySigsDelivered; /* true if any have been delivered. */
143 static struct sigaction oldActions[NSIG]; /* the old signal vectors */
145 static char *sigEvents[NSIG]; /* the event to do an LWP signal on */
146 static int sigDelivered[NSIG]; /* True for signals delivered so far.
147 This is an int array to make sure
148 there are no conflicts when trying
150 /* software 'signals' */
152 static int (*sigProc[NSOFTSIG])();
153 static char *sigRock[NSOFTSIG];
156 static struct IoRequest *iorFreeList = 0;
158 static struct TM_Elem *Requests; /* List of requests */
159 static struct timeval iomgr_timeout; /* global so signal handler can zap it */
161 /* stuff for debugging */
162 static int iomgr_errno;
163 static struct timeval iomgr_badtv;
164 static PROCESS iomgr_badpid;
165 static void SignalIO(int fds, fd_set *rfds, fd_set *wfds, fd_set *efs,
167 static void SignalTimeout(int code, struct timeval *timeout);
170 /* handle Netbios NCB completion */
172 int anyNCBComplete = FALSE;
173 int handler_seg, handler_off; /* seg:off of NCB completion handler */
174 static __dpmi_regs callback_regs;
175 static _go32_dpmi_seginfo callback_info;
176 #endif /* AFS_DJGPP_ENV */
178 /* fd_set pool managment.
179 * Use the pool instead of creating fd_set's on the stack. fd_set's can be
180 * 2K in size, so making three could put 6K in the limited space of an LWP
183 struct IOMGR_fd_set {
184 struct IOMGR_fd_set *next;
185 } *iomgrFreeFDSets = (struct IOMGR_fd_set*)0;
188 * Return fd_set to the free list.
190 void IOMGR_FreeFDSet(fd_set *s)
192 struct IOMGR_fd_set *t = (struct IOMGR_fd_set *)s;
194 t->next = iomgrFreeFDSets;
199 * returns a zeroed fd_set or null if could not malloc one.
201 fd_set *IOMGR_AllocFDSet(void)
203 struct IOMGR_fd_set *t;
204 if (iomgrFreeFDSets) {
206 iomgrFreeFDSets = iomgrFreeFDSets->next;
209 t = (struct IOMGR_fd_set *)malloc(sizeof(fd_set));
219 #define FreeRequest(x) ((x)->result = (long) iorFreeList, iorFreeList = (x))
221 static struct IoRequest *NewRequest()
223 struct IoRequest *request;
225 if ((request=iorFreeList))
226 iorFreeList = (struct IoRequest *) (request->result);
227 else request = (struct IoRequest *) malloc(sizeof(struct IoRequest));
229 memset((char*)request, 0, sizeof(struct IoRequest));
233 #define Purge(list) FOR_ALL_ELTS(req, list, { free(req->BackPointer); })
236 /* FD_SET support routines. All assume the fd_set size is a multiple of an int
237 * so we can at least do logical operations on ints instead of chars.
239 * For each routine, nfds is the highest bit set in either fd_set, starting
243 #define FD_N_ZERO(A, x) FD_ZERO(x)
245 #define FDS_P_POS (sizeof(int)*8)
246 #define INTS_PER_FDS(x) (((x)+(FDS_P_POS-1)) / FDS_P_POS)
247 #define FD_N_ZERO(nfds, x) memset((char*)(x), 0, (INTS_PER_FDS(nfds))*sizeof(int))
250 #if defined(AFS_LINUX22_ENV) && (__GLIBC_MINOR__ > 0)
251 /* Build for both glibc 2.0.x and 2.1.x */
252 #define FDS_BITS __fds_bits
254 #define FDS_BITS fds_bits
257 /* FDSetCmp - returns 1 if any bits in fd_set1 are also set in fd_set2.
258 * If nfds is 0, or one of the fd_sets is null return 0 (since there is no bit
259 * set in both fd_sets).
261 static int FDSetCmp(int nfds, fd_set *fd_set1, fd_set *fd_set2)
265 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
269 if (fd_set1->fd_count == 0 || fd_set2->fd_count == 0)
272 for (i=0; i<fd_set1->fd_count; i++) {
273 for (j=0; j<fd_set2->fd_count; j++) {
274 if (fd_set1->fd_array[i] == fd_set2->fd_array[j])
282 j = INTS_PER_FDS(nfds);
283 for (i=0; i<j; i++) {
284 if (fd_set1->FDS_BITS[i] & fd_set2->FDS_BITS[i])
291 /* FDSetSet - set bits from fd_set2 into fd_set1
293 static void FDSetSet(int nfds, fd_set *fd_set1, fd_set *fd_set2)
297 if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
301 if (fd_set2->fd_count==0)
304 for (i=0; i<fd_set2->fd_count; i++)
305 FD_SET(fd_set2->fd_array[i], fd_set1);
310 n = INTS_PER_FDS(nfds);
311 for (i=0; i<n; i++) {
312 fd_set1->FDS_BITS[i] |= fd_set2->FDS_BITS[i];
317 /* FDSetAnd - fd_set1 <- fd_set1 & fd_set2.
320 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
325 if (fd_set1 == NULL || fd_set1->fd_count == 0)
328 if (fd_set2 == NULL || fd_set2->fd_count == 0) {
333 for (i=0; i<fd_set2->fd_count; i++) {
334 if (FD_ISSET(fd_set2->fd_array[i], fd_set1))
335 FD_SET(fd_set2->fd_array[i], &tmpset);
341 static void FDSetAnd(int nfds, fd_set *fd_set1, fd_set *fd_set2)
345 if (nfds == 0 || fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
348 n = INTS_PER_FDS(nfds);
349 for (i=0; i<n; i++) {
350 fd_set1->FDS_BITS[i] &= fd_set2->FDS_BITS[i];
355 /* FDSetEmpty - return true if fd_set is empty
357 static int FDSetEmpty(int nfds, fd_set *fds)
365 if (fds == (fd_set*)0)
369 if (fds->fd_count == 0)
374 n = INTS_PER_FDS(nfds);
376 for (i=n-1; i>=0; i--) {
377 if (fds->FDS_BITS[i])
388 /* The IOMGR process */
391 * Important invariant: process->iomgrRequest is null iff request not in timer
393 * also, request->pid is valid while request is in queue,
394 * also, don't signal selector while request in queue, since selector frees
398 /* These are not declared in IOMGR so that they don't use up 6K of stack. */
399 static fd_set IOMGR_readfds, IOMGR_writefds, IOMGR_exceptfds;
400 static int IOMGR_nfds = 0;
402 static int IOMGR(void *dummy)
406 struct TM_Elem *earliest;
407 struct timeval timeout, junk;
410 FD_ZERO(&IOMGR_readfds);
411 FD_ZERO(&IOMGR_writefds);
412 FD_ZERO(&IOMGR_exceptfds);
415 /* Wake up anyone who has expired or who has received a
416 Unix signal between executions. Keep going until we
419 woke_someone = FALSE;
420 /* Wake up anyone waiting on signals. */
421 /* Note: SignalSignals() may yield! */
422 if (anySigsDelivered && SignalSignals ())
424 #ifndef AFS_DJGPP_ENV
425 FT_GetTimeOfDay(&junk, 0); /* force accurate time check */
429 register struct IoRequest *req;
430 struct TM_Elem *expired;
431 expired = TM_GetExpired(Requests);
432 if (expired == NULL) break;
434 req = (struct IoRequest *) expired -> BackPointer;
436 if (lwp_debug != 0) puts("[Polling SELECT]");
439 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
440 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
441 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
443 req->result = 0; /* no fds ready */
444 TM_Remove(Requests, &req->timeout);
446 req -> timeout.Next = (struct TM_Elem *) 2;
447 req -> timeout.Prev = (struct TM_Elem *) 2;
449 LWP_QSignal(req->pid);
450 req->pid->iomgrRequest = 0;
454 if (IOMGR_CheckNCB()) /* check for completed netbios requests */
456 #endif /* AFS_DJGPP_ENV */
458 if (woke_someone) LWP_DispatchProcess();
459 } while (woke_someone);
461 /* Collect requests & update times */
462 FD_ZERO(&IOMGR_readfds);
463 FD_ZERO(&IOMGR_writefds);
464 FD_ZERO(&IOMGR_exceptfds);
467 FOR_ALL_ELTS(r, Requests, {
468 register struct IoRequest *req;
469 req = (struct IoRequest *) r -> BackPointer;
470 FDSetSet(req->nfds, &IOMGR_readfds, req->readfds);
471 FDSetSet(req->nfds, &IOMGR_writefds, req->writefds);
472 FDSetSet(req->nfds, &IOMGR_exceptfds, req->exceptfds);
473 if (req->nfds > IOMGR_nfds)
474 IOMGR_nfds = req->nfds;
476 earliest = TM_GetEarliest(Requests);
477 if (earliest != NULL) {
478 timeout = earliest -> TimeLeft;
483 if (lwp_debug != 0) {
486 printf("[Read Select:");
487 if (IOMGR_readfds.fd_count == 0)
490 for (idbg=0; idbg<IOMGR_readfds.fd_count; idbg++)
491 printf(" %d", IOMGR_readfds.fd_array[idbg]);
494 printf("[Write Select:");
495 if (IOMGR_writefds.fd_count == 0)
498 for (idbg=0; idbg<IOMGR_writefds.fd_count; idbg++)
499 printf(" %d", IOMGR_writefds.fd_array[idbg]);
502 printf("[Except Select:");
503 if (IOMGR_exceptfds.fd_count == 0)
506 for (idbg=0; idbg<IOMGR_exceptfds.fd_count; idbg++)
507 printf(" %d", IOMGR_exceptfds.fd_array[idbg]);
511 /* Only prints first 32. */
512 printf("[select(%d, 0x%x, 0x%x, 0x%x, ", IOMGR_nfds,
513 *(int*)&IOMGR_readfds, *(int*)&IOMGR_writefds,
514 *(int*)&IOMGR_exceptfds);
515 #endif /* AFS_NT40_ENV */
516 if (timeout.tv_sec == -1 && timeout.tv_usec == -1)
519 printf("<%d, %d>)]\n", timeout.tv_sec, timeout.tv_usec);
522 iomgr_timeout = timeout;
523 if (timeout.tv_sec == -1 && timeout.tv_usec == -1) {
524 /* infinite, sort of */
525 iomgr_timeout.tv_sec = 100000000;
526 iomgr_timeout.tv_usec = 0;
529 /* On NT, signals don't interrupt a select call. So this can potentially
530 * lead to long wait times before a signal is honored. To avoid this we
531 * dont do select() for longer than IOMGR_MAXWAITTIME (5 secs) */
532 if (iomgr_timeout.tv_sec > (IOMGR_MAXWAITTIME - 1)) {
533 iomgr_timeout.tv_sec = IOMGR_MAXWAITTIME;
534 iomgr_timeout.tv_usec = 0;
539 /* We do this also for the DOS-box Win95 client, since
540 NCB calls don't interrupt a select, but we want to catch them
541 in a reasonable amount of time (say, half a second). */
542 iomgr_timeout.tv_sec = 0;
543 iomgr_timeout.tv_usec = IOMGR_WIN95WAITTIME;
546 /* Check one last time for a signal delivery. If one comes after
547 this, the signal handler will set iomgr_timeout to zero, causing
548 the select to return immediately. The timer package won't return
549 a zero timeval because all of those guys were handled above.
551 I'm assuming that the kernel masks signals while it's picking up
552 the parameters to select. This may a bad assumption. -DN */
553 if (anySigsDelivered)
554 continue; /* go to the top and handle them. */
557 if (IOMGR_CheckNCB()) /* check for completed netbios requests */
558 LWP_DispatchProcess();
559 #endif /* AFS_DJGPP_ENV */
562 if (IOMGR_readfds.fd_count == 0 && IOMGR_writefds.fd_count == 0
563 && IOMGR_exceptfds.fd_count == 0) {
566 if (iomgr_timeout.tv_sec || iomgr_timeout.tv_usec) {
567 stime = iomgr_timeout.tv_sec * 1000
568 + iomgr_timeout.tv_usec/1000;
576 { /* select runs much faster if 0's are passed instead of &0s */
577 code = select(IOMGR_nfds,
578 (FDSetEmpty(IOMGR_nfds, &IOMGR_readfds)) ?
579 (fd_set*)0 : &IOMGR_readfds,
580 (FDSetEmpty(IOMGR_nfds, &IOMGR_writefds)) ?
581 (fd_set*)0 : &IOMGR_writefds,
582 (FDSetEmpty(IOMGR_nfds, &IOMGR_exceptfds)) ?
583 (fd_set*)0 : &IOMGR_exceptfds,
590 #if defined(AFS_SUN_ENV)
591 /* Tape drives on Sun boxes do not support select and return ENXIO */
592 if (errno == ENXIO) e=0, code=1;
594 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
595 /* For SGI and SVR4 - poll & select can return EAGAIN ... */
596 if (errno == EAGAIN) e=0;
598 #if defined(AFS_SUN5_ENV)
599 /* On sun4x_55, select doesn't block signal. It could be
600 interupted by a signal that changes iomgr_timeout, and
601 then select returns with EINVAL. In this case, we need
604 if (errno==EINVAL && anySigsDelivered)
606 #endif /* AFS_SUN5_ENV */
608 if ((errno != EINTR) && e) {
611 for(i=0; i<FD_SETSIZE; i++) {
612 if (fcntl(i, F_GETFD, 0) < 0 && errno == EBADF)
613 FD_SET(i, &openMask);
621 /* See what happened */
623 /* Action -- wake up everyone involved */
624 SignalIO(IOMGR_nfds, &IOMGR_readfds, &IOMGR_writefds,
625 &IOMGR_exceptfds, code);
628 && (iomgr_timeout.tv_sec != 0 || iomgr_timeout.tv_usec != 0)) {
629 /* Real timeout only if signal handler hasn't set
630 iomgr_timeout to zero. */
633 /* On NT, real timeout only if above and if iomgr_timeout
634 * interval is equal to timeout interval (i.e., not adjusted
635 * to check for pseudo-signals).
637 if (iomgr_timeout.tv_sec != timeout.tv_sec ||
638 iomgr_timeout.tv_usec != timeout.tv_usec) {
639 /* signal check interval timed out; not real timeout */
642 #endif /* AFS_NT40_ENV */
643 #ifndef AFS_DJGPP_ENV
644 FT_GetTimeOfDay(&junk, 0);
646 SignalTimeout(code, &timeout);
650 #endif /* AFS_DJGPP_ENV */
652 LWP_DispatchProcess();
654 return -1; /* keeps compilers happy. */
657 /************************\
659 * Signalling routines *
661 \************************/
663 static void SignalIO(int fds, fd_set *readfds, fd_set *writefds,
664 fd_set *exceptfds, int code)
667 /* Look at everyone who's bit mask was affected */
668 FOR_ALL_ELTS(r, Requests, {
669 register struct IoRequest *req;
670 register PROCESS pid;
671 req = (struct IoRequest *) r -> BackPointer;
672 nfds = MIN(fds, req->nfds);
673 if (FDSetCmp(nfds, req->readfds, readfds) ||
674 FDSetCmp(nfds, req->writefds, writefds) ||
675 FDSetCmp(nfds, req->exceptfds, exceptfds)) {
676 /* put ready fd's into request. */
677 FDSetAnd(nfds, req->readfds, readfds);
678 FDSetAnd(nfds, req->writefds, writefds);
679 FDSetAnd(nfds, req->exceptfds, exceptfds);
680 req -> result = code;
681 TM_Remove(Requests, &req->timeout);
682 LWP_QSignal(pid=req->pid);
683 pid->iomgrRequest = 0;
688 static void SignalTimeout(int code, struct timeval *timeout)
690 /* Find everyone who has specified timeout */
691 FOR_ALL_ELTS(r, Requests, {
692 register struct IoRequest *req;
693 register PROCESS pid;
694 req = (struct IoRequest *) r -> BackPointer;
695 if (TM_eql(&r->TimeLeft, timeout)) {
696 req -> result = code;
697 TM_Remove(Requests, &req->timeout);
698 LWP_QSignal(pid=req->pid);
699 pid->iomgrRequest = 0;
705 /*****************************************************\
707 * Signal handling routine (not to be confused with *
708 * signalling routines, above). *
710 \*****************************************************/
711 static void SigHandler (signo)
714 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
715 return; /* can't happen. */
716 sigDelivered[signo] = TRUE;
717 anySigsDelivered = TRUE;
718 /* Make sure that the IOMGR process doesn't pause on the select. */
719 iomgr_timeout.tv_sec = 0;
720 iomgr_timeout.tv_usec = 0;
723 /* Alright, this is the signal signalling routine. It delivers LWP signals
724 to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
725 static int SignalSignals ()
732 anySigsDelivered = FALSE;
734 /* handle software signals */
735 stackSize = (AFS_LWP_MINSTACKSIZE < lwp_MaxStackSeen? lwp_MaxStackSeen : AFS_LWP_MINSTACKSIZE);
736 for (i=0; i < NSOFTSIG; i++) {
738 if (p=sigProc[i]) /* This yields!!! */
739 LWP_CreateProcess2(p, stackSize, LWP_NORMAL_PRIORITY, sigRock[i],
740 "SignalHandler", &pid);
744 for (i = 1; i <= NSIG; ++i) /* forall !badsig(i) */
745 if ((sigsHandled & mysigmask(i)) && sigDelivered[i] == TRUE) {
746 sigDelivered[i] = FALSE;
747 LWP_NoYieldSignal (sigEvents[i]);
754 /***************************\
756 * User-callable routines *
758 \***************************/
761 /* Keep IOMGR process id */
762 static PROCESS IOMGR_Id = NULL;
764 int IOMGR_SoftSig(aproc, arock)
768 for (i=0;i<NSOFTSIG;i++) {
769 if (sigProc[i] == 0) {
773 anySigsDelivered = TRUE;
774 iomgr_timeout.tv_sec = 0;
775 iomgr_timeout.tv_usec = 0;
783 unsigned char allOnes[100];
785 int IOMGR_Initialize(void)
787 extern int TM_Init();
790 /* If lready initialized, just return */
791 if (IOMGR_Id != NULL) return LWP_SUCCESS;
793 /* Init LWP if someone hasn't yet. */
794 if (LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY, &pid) != LWP_SUCCESS)
797 /* Initialize request lists */
798 if (TM_Init(&Requests) < 0) return -1;
800 /* Initialize signal handling stuff. */
802 anySigsDelivered = TRUE; /* A soft signal may have happened before
803 IOMGR_Initialize: so force a check for signals regardless */
804 memset(allOnes, 0xff, sizeof(allOnes));
807 install_ncb_handler();
808 #endif /* AFS_DJGPP_ENV */
810 return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, 0, "IO MANAGER",
820 status = LWP_DestroyProcess(IOMGR_Id);
825 /* signal I/O for anyone who is waiting for a FD or a timeout; not too cheap,
826 * since forces select and timeofday check */
827 int IOMGR_Poll(void) {
828 fd_set *readfds, *writefds, *exceptfds;
833 FT_GetTimeOfDay(&tv, 0); /* force accurate time check */
836 register struct IoRequest *req;
837 struct TM_Elem *expired;
838 expired = TM_GetExpired(Requests);
839 if (expired == NULL) break;
840 req = (struct IoRequest *) expired -> BackPointer;
842 if (lwp_debug != 0) puts("[Polling SELECT]");
845 if (req->readfds) FD_N_ZERO(req->nfds, req->readfds);
846 if (req->writefds) FD_N_ZERO(req->nfds, req->writefds);
847 if (req->exceptfds) FD_N_ZERO(req->nfds, req->exceptfds);
849 req->result = 0; /* no fds ready */
850 TM_Remove(Requests, &req->timeout);
852 req -> timeout.Next = (struct TM_Elem *) 2;
853 req -> timeout.Prev = (struct TM_Elem *) 2;
855 LWP_QSignal(req->pid);
856 req->pid->iomgrRequest = 0;
859 /* Collect requests & update times */
860 readfds = IOMGR_AllocFDSet();
861 writefds = IOMGR_AllocFDSet();
862 exceptfds = IOMGR_AllocFDSet();
863 if (!(readfds && writefds && exceptfds)) {
864 fprintf(stderr, "IOMGR_Poll: Could not malloc space for fd_sets.\n");
870 FOR_ALL_ELTS(r, Requests, {
871 register struct IoRequest *req;
872 req = (struct IoRequest *) r -> BackPointer;
873 FDSetSet(req->nfds, readfds, req->readfds);
874 FDSetSet(req->nfds, writefds, req->writefds);
875 FDSetSet(req->nfds, exceptfds, req->exceptfds);
884 if (readfds->fd_count == 0 && writefds->fd_count == 0
885 && exceptfds->fd_count == 0)
887 code = select(fds, readfds, writefds, exceptfds, &tv);
889 SignalIO(fds, readfds, writefds, exceptfds, code);
892 if (readfds) IOMGR_FreeFDSet(readfds);
893 if (writefds) IOMGR_FreeFDSet(writefds);
894 if (exceptfds) IOMGR_FreeFDSet(exceptfds);
897 LWP_DispatchProcess(); /* make sure others run */
898 LWP_DispatchProcess();
902 int IOMGR_Select(fds, readfds, writefds, exceptfds, timeout)
904 fd_set *readfds, *writefds, *exceptfds;
905 struct timeval *timeout;
907 register struct IoRequest *request;
911 if(fds > FD_SETSIZE) {
912 fprintf(stderr, "IOMGR_Select: fds=%d, more than max %d\n",
919 /* See if polling request. If so, handle right here */
920 if (timeout != NULL) {
921 if (timeout->tv_sec == 0 && timeout->tv_usec == 0) {
924 if (lwp_debug != 0) puts("[Polling SELECT]");
927 code = select(fds, readfds, writefds, exceptfds, timeout);
928 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
930 * For SGI and SVR4 - poll & select can return EAGAIN ...
933 * this is basically for SGI, but I believe stock SVR4 (Solaris?)
934 * can also get this error return
936 if (code < 0 && errno == EAGAIN)
940 if (code == SOCKET_ERROR) {
941 if (WSAGetLastError() == WSAEINPROGRESS)
947 return (code > 1 ? 1 : code);
951 /* Construct request block & insert */
952 request = NewRequest(); /* zeroes fd_set's */
953 if (readfds && !FDSetEmpty(fds, readfds))
954 request->readfds = readfds;
955 if (writefds && !FDSetEmpty(fds, writefds))
956 request->writefds = writefds;
957 if (exceptfds && !FDSetEmpty(fds, exceptfds))
958 request->exceptfds = exceptfds;
961 if (timeout == NULL) {
962 request -> timeout.TotalTime.tv_sec = -1;
963 request -> timeout.TotalTime.tv_usec = -1;
965 request -> timeout.TotalTime = *timeout;
966 /* check for bad request */
967 if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999) {
969 iomgr_badtv = *timeout;
970 iomgr_badpid = LWP_ActiveProcess;
971 /* now fixup request */
972 if(request->timeout.TotalTime.tv_sec < 0)
973 request->timeout.TotalTime.tv_sec = 1;
974 request->timeout.TotalTime.tv_usec = 100000;
978 request -> timeout.BackPointer = (char *) request;
980 /* Insert my PID in case of IOMGR_Cancel */
981 request -> pid = LWP_ActiveProcess;
982 LWP_ActiveProcess -> iomgrRequest = request;
985 request -> timeout.Next = (struct TM_Elem *) 1;
986 request -> timeout.Prev = (struct TM_Elem *) 1;
988 TM_Insert(Requests, &request->timeout);
990 /* Wait for action */
993 /* Update parameters & return */
994 result = request -> result;
996 FreeRequest(request);
997 return (result > 1 ? 1 : result);
1000 int IOMGR_Cancel(PROCESS pid)
1002 register struct IoRequest *request;
1004 if ((request = pid->iomgrRequest) == 0) return -1; /* Pid not found */
1006 if (request->readfds) FD_N_ZERO(request->nfds, request->readfds);
1007 if (request->writefds) FD_N_ZERO(request->nfds, request->writefds);
1008 if (request->exceptfds) FD_N_ZERO(request->nfds, request->exceptfds);
1011 request -> result = -2;
1012 TM_Remove(Requests, &request->timeout);
1014 request -> timeout.Next = (struct TM_Elem *) 5;
1015 request -> timeout.Prev = (struct TM_Elem *) 5;
1017 LWP_QSignal(request->pid);
1018 pid->iomgrRequest = 0;
1023 #ifndef AFS_NT40_ENV
1024 /* Cause delivery of signal signo to result in a LWP_SignalProcess of
1026 IOMGR_Signal (signo, event)
1030 struct sigaction sa;
1035 return LWP_EBADEVENT;
1036 sa.sa_handler = SigHandler;
1037 sa.sa_mask = *((sigset_t *) allOnes); /* mask all signals */
1039 sigsHandled |= mysigmask(signo);
1040 sigEvents[signo] = event;
1041 sigDelivered[signo] = FALSE;
1042 if (sigaction (signo, &sa, &oldActions[signo]) == -1)
1047 /* Stop handling occurrences of signo. */
1048 IOMGR_CancelSignal (signo)
1051 if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
1053 sigaction (signo, &oldActions[signo], (struct sigaction *)0);
1054 sigsHandled &= ~mysigmask(signo);
1057 #endif /* AFS_NT40_ENV */
1058 /* This routine calls select is a fashion that simulates the standard sleep routine */
1059 void IOMGR_Sleep (int seconds)
1061 #ifndef AFS_DJGPP_ENV
1062 struct timeval timeout;
1064 timeout.tv_sec = seconds;
1065 timeout.tv_usec = 0;
1066 IOMGR_Select(0, 0, 0, 0, &timeout);
1068 struct timeval timeout;
1073 s = socket(AF_INET,SOCK_STREAM,0);
1076 timeout.tv_sec = seconds;
1077 timeout.tv_usec = 0;
1078 IOMGR_Select(1,&set,&empty,&empty,&timeout);
1082 #endif /* USE_PTHREADS */
1085 #ifdef AFS_DJGPP_ENV
1087 /* Netbios code for djgpp port */
1089 int IOMGR_NCBSelect(ncbp, dos_ncb, timeout)
1092 struct timeval *timeout;
1094 struct IoRequest *request;
1097 if (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)
1100 if (ncbp->ncb_event != NULL)
1106 if (get_dos_member_b(NCB, dos_ncb, ncb_cmd_cplt) != 0xff)
1115 /* Construct request block & insert */
1116 request = NewRequest();
1117 request->ncbp = ncbp;
1118 request->dos_ncb = dos_ncb;
1120 if (timeout == NULL)
1122 request->timeout.TotalTime.tv_sec = -1;
1123 request->timeout.TotalTime.tv_usec = -1;
1127 request -> timeout.TotalTime = *timeout;
1128 /* check for bad request */
1129 if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999)
1132 iomgr_badtv = *timeout;
1133 iomgr_badpid = LWP_ActiveProcess;
1134 /* now fixup request */
1135 if(request->timeout.TotalTime.tv_sec < 0)
1136 request->timeout.TotalTime.tv_sec = 1;
1137 request->timeout.TotalTime.tv_usec = 100000;
1141 request->timeout.BackPointer = (char *)request;
1143 /* Insert my PID in case of IOMGR_Cancel */
1144 request -> pid = LWP_ActiveProcess;
1145 LWP_ActiveProcess -> iomgrRequest = request;
1148 request -> timeout.Next = (struct TM_Elem *) 1;
1149 request -> timeout.Prev = (struct TM_Elem *) 1;
1151 TM_Insert(Requests, &request->timeout);
1153 if (ncbp->ncb_event != NULL)
1155 /* since we were given an event, we can return immediately and just
1156 signal the event once the request completes. */
1161 /* Wait for action */
1165 /* Update parameters & return */
1166 result = request -> result;
1168 FreeRequest(request);
1169 return (result > 1 ? 1 : result);
1173 int IOMGR_CheckNCB()
1175 int woke_someone = FALSE;
1179 anyNCBComplete = FALSE;
1180 FOR_ALL_ELTS(r, Requests, {
1181 register struct IoRequest *req;
1182 req = (struct IoRequest *) r -> BackPointer;
1184 if (req->dos_ncb && get_dos_member_b(NCB, req->dos_ncb, ncb_cmd_cplt) != 0xff)
1186 /* this NCB has completed */
1187 TM_Remove(Requests, &req->timeout);
1189 /* copy out NCB from DOS to virtual space */
1190 dosmemget(req->dos_ncb, sizeof(NCB), (char *) req->ncbp);
1192 if (ev = req->ncbp->ncb_event)
1198 woke_someone = TRUE;
1199 LWP_QSignal(pid=req->pid);
1200 pid->iomgrRequest = 0;
1204 return woke_someone;
1207 int ncb_handler(__dpmi_regs *r)
1209 anyNCBComplete = TRUE; /* NCB completed */
1210 /* Make sure that the IOMGR process doesn't pause on the select. */
1211 iomgr_timeout.tv_sec = 0;
1212 iomgr_timeout.tv_usec = 0;
1216 int install_ncb_handler()
1218 callback_info.pm_offset = (long) ncb_handler;
1219 if (_go32_dpmi_allocate_real_mode_callback_retf(&callback_info,
1222 fprintf(stderr, "error, allocate_real_mode_callback_retf failed\n");
1226 handler_seg = callback_info.rm_segment;
1227 handler_off = callback_info.rm_offset;
1229 /*printf("NCB handler_seg=0x%x, off=0x%x\n", handler_seg, handler_off);*/
1231 #endif /* AFS_DJGPP_ENV */