* directory or online at http://www.openafs.org/dl/license10.html
*/
-#ifndef lint
-#endif
/*******************************************************************\
* *
* Information Technology Center *
IO Manager routines & server process for VICE server.
*/
+/* This controls the size of an fd_set; it must be defined early before
+ * the system headers define that type and the macros that operate on it.
+ * Its value should be as large as the maximum file descriptor limit we
+ * are likely to run into on any platform. Right now, that is 65536
+ * which is the default hard fd limit on Solaris 9 */
+/* We don't do this on Windows because on that platform there is code
+ * which allocates fd_set's on the stack (IOMGR_Sleep on Win9x, and
+ * FDSetAnd on WinNT) */
+#ifndef _WIN32
+#define FD_SETSIZE 65536
+#endif
+
+#include <afsconfig.h>
#include <afs/param.h>
+
+
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#include <malloc.h>
#ifdef AFS_SUN5_ENV
#include <fcntl.h>
#endif
-#ifdef AFS_DJGPP_ENV
-#include "dosdefs95.h"
-#include "netbios95.h"
-#include <sys/socket.h>
-#include <sys/farptr.h>
-#include <dpmi.h>
-#include <go32.h>
-#include <crt0.h>
-int _crt0_startup_flags = _CRT0_FLAG_LOCK_MEMORY;
-#endif /* AFS_DJGPP_ENV */
#if defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
#define TRUE 1
#ifndef MIN
-#define MIN(a,b) ((a)>(b)) ? b : a
+#define MIN(a,b) (((a)>(b)) ? (b) : (a))
#endif
#ifndef NSIG
#define NSIG 8*sizeof(sigset_t)
#endif
-static int SignalSignals();
+static int SignalSignals(void);
\f
/********************************\
* *
struct TM_Elem timeout;
/* Result of select call */
- long result;
+ int result;
-#ifdef AFS_DJGPP_ENV
- NCB *ncbp;
- dos_ptr dos_ncb;
-#endif /* AFS_DJGPP_ENV */
+ struct IoRequest *next; /* for iorFreeList */
};
-\f
+
/********************************\
* *
* Stuff for managing signals *
to write it */
/* software 'signals' */
#define NSOFTSIG 4
-static int (*sigProc[NSOFTSIG])();
-static char *sigRock[NSOFTSIG];
+static void *(*sigProc[NSOFTSIG])(void *);
+static void *sigRock[NSOFTSIG];
\f
static struct IoRequest *iorFreeList = 0;
static PROCESS iomgr_badpid;
static void SignalIO(int fds, fd_set *rfds, fd_set *wfds, fd_set *efs,
int code);
-
-#ifdef AFS_DJGPP_ENV
-/* handle Netbios NCB completion */
-static int NCB_fd;
-int anyNCBComplete = FALSE;
-int handler_seg, handler_off; /* seg:off of NCB completion handler */
-static __dpmi_regs callback_regs;
-static _go32_dpmi_seginfo callback_info;
-#endif /* AFS_DJGPP_ENV */
+static void SignalTimeout(int code, struct timeval *timeout);
/* fd_set pool managment.
* Use the pool instead of creating fd_set's on the stack. fd_set's can be
- * 2K in size, so making three could put 6K in the limited space of an LWP
+ * 8K in size, so making three could put 24K in the limited space of an LWP
* stack.
*/
struct IOMGR_fd_set {
}
}
-#define FreeRequest(x) ((x)->result = (long) iorFreeList, iorFreeList = (x))
+#define FreeRequest(x) ((x)->next = iorFreeList, iorFreeList = (x))
-static struct IoRequest *NewRequest()
+static struct IoRequest *NewRequest(void)
{
struct IoRequest *request;
- if (request=iorFreeList)
- iorFreeList = (struct IoRequest *) (request->result);
+ if ((request=iorFreeList))
+ iorFreeList = (struct IoRequest *) (request->next);
else request = (struct IoRequest *) malloc(sizeof(struct IoRequest));
memset((char*)request, 0, sizeof(struct IoRequest));
#else
#define FDS_P_POS (sizeof(int)*8)
#define INTS_PER_FDS(x) (((x)+(FDS_P_POS-1)) / FDS_P_POS)
-#define FD_N_ZERO(nfds, x) bzero((char*)(x), (INTS_PER_FDS(nfds))*sizeof(int))
+#define FD_N_ZERO(nfds, x) memset((char*)(x), 0, (INTS_PER_FDS(nfds))*sizeof(int))
#endif
-#if defined(AFS_LINUX22_ENV) && (__GLIBC_MINOR__ > 0)
-/* Build for both glibc 2.0.x and 2.1.x */
-#define FDS_BITS __fds_bits
+/* On Linux without __USE_XOPEN, we have __fds_bits. With __USE_XOPEN, or
+ * non-Linux, we have fds_bits. */
+#if defined(AFS_LINUX22_ENV) && (__GLIBC_MINOR__ > 0) && !defined(__USE_XOPEN)
+# define FDS_BITS __fds_bits
#else
-#define FDS_BITS fds_bits
+# define FDS_BITS fds_bits
#endif
/* FDSetCmp - returns 1 if any bits in fd_set1 are also set in fd_set2.
*/
static void FDSetSet(int nfds, fd_set *fd_set1, fd_set *fd_set2)
{
- unsigned int i, n;
+ unsigned int i;
+#ifndef AFS_NT40_ENV
+ unsigned int n;
+#endif
if (fd_set1 == (fd_set*)0 || fd_set2 == (fd_set*)0)
return;
if (nfds == 0)
return;
- n = INTS_PER_FDS(nfds);
- for (i=0; i<n; i++) {
+ for (i = 0, n = INTS_PER_FDS(nfds); i < n; i++) {
fd_set1->FDS_BITS[i] |= fd_set2->FDS_BITS[i];
}
#endif
static fd_set IOMGR_readfds, IOMGR_writefds, IOMGR_exceptfds;
static int IOMGR_nfds = 0;
-static int IOMGR(void *dummy)
+static void *IOMGR(void *dummy)
{
for (;;) {
int code;
struct TM_Elem *earliest;
struct timeval timeout, junk;
bool woke_someone;
-#ifndef AFS_NT40_ENV
- int fds;
-#endif
FD_ZERO(&IOMGR_readfds);
FD_ZERO(&IOMGR_writefds);
/* Note: SignalSignals() may yield! */
if (anySigsDelivered && SignalSignals ())
woke_someone = TRUE;
-#ifndef AFS_DJGPP_ENV
FT_GetTimeOfDay(&junk, 0); /* force accurate time check */
-#endif
TM_Rescan(Requests);
for (;;) {
register struct IoRequest *req;
req->pid->iomgrRequest = 0;
}
-#ifdef AFS_DJGPP_ENV
- if (IOMGR_CheckNCB()) /* check for completed netbios requests */
- woke_someone = TRUE;
-#endif /* AFS_DJGPP_ENV */
-
if (woke_someone) LWP_DispatchProcess();
} while (woke_someone);
iomgr_timeout.tv_sec = 100000000;
iomgr_timeout.tv_usec = 0;
}
-#ifdef AFS_NT40_ENV
+#if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV)
/* On NT, signals don't interrupt a select call. So this can potentially
* lead to long wait times before a signal is honored. To avoid this we
* dont do select() for longer than IOMGR_MAXWAITTIME (5 secs) */
+ /* Whereas Linux seems to sometimes "lose" signals */
if (iomgr_timeout.tv_sec > (IOMGR_MAXWAITTIME - 1)) {
iomgr_timeout.tv_sec = IOMGR_MAXWAITTIME;
iomgr_timeout.tv_usec = 0;
}
#endif /* NT40 */
-#ifdef AFS_DJGPP_ENV
- /* We do this also for the DOS-box Win95 client, since
- NCB calls don't interrupt a select, but we want to catch them
- in a reasonable amount of time (say, half a second). */
- iomgr_timeout.tv_sec = 0;
- iomgr_timeout.tv_usec = IOMGR_WIN95WAITTIME;
-#endif /* DJGPP */
-
/* Check one last time for a signal delivery. If one comes after
this, the signal handler will set iomgr_timeout to zero, causing
the select to return immediately. The timer package won't return
if (anySigsDelivered)
continue; /* go to the top and handle them. */
-#ifdef AFS_DJGPP_ENV
- if (IOMGR_CheckNCB()) /* check for completed netbios requests */
- LWP_DispatchProcess();
-#endif /* AFS_DJGPP_ENV */
-
#ifdef AFS_NT40_ENV
if (IOMGR_readfds.fd_count == 0 && IOMGR_writefds.fd_count == 0
&& IOMGR_exceptfds.fd_count == 0) {
/* Real timeout only if signal handler hasn't set
iomgr_timeout to zero. */
-#ifdef AFS_NT40_ENV
+#if defined(AFS_NT40_ENV) || defined(AFS_LINUX24_ENV)
/* On NT, real timeout only if above and if iomgr_timeout
* interval is equal to timeout interval (i.e., not adjusted
* to check for pseudo-signals).
*/
+ /* And also for Linux as above */
if (iomgr_timeout.tv_sec != timeout.tv_sec ||
iomgr_timeout.tv_usec != timeout.tv_usec) {
/* signal check interval timed out; not real timeout */
continue;
}
#endif /* AFS_NT40_ENV */
-#ifndef AFS_DJGPP_ENV
FT_GetTimeOfDay(&junk, 0);
-#endif
SignalTimeout(code, &timeout);
}
-#ifdef AFS_DJGPP_ENV
- IOMGR_CheckNCB();
-#endif /* AFS_DJGPP_ENV */
}
LWP_DispatchProcess();
}
- return -1; /* keeps compilers happy. */
+ return (void *)-1; /* keeps compilers happy. */
}
\f
/************************\
* signalling routines, above). *
* *
\*****************************************************/
-static void SigHandler (signo)
- int signo;
+static void SigHandler (int signo)
{
if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
return; /* can't happen. */
/* Alright, this is the signal signalling routine. It delivers LWP signals
to LWPs waiting on Unix signals. NOW ALSO CAN YIELD!! */
-static int SignalSignals ()
+static int SignalSignals (void)
{
bool gotone = FALSE;
register int i;
- register int (*p)();
+ register void *(*p)(void *);
afs_int32 stackSize;
anySigsDelivered = FALSE;
stackSize = (AFS_LWP_MINSTACKSIZE < lwp_MaxStackSeen? lwp_MaxStackSeen : AFS_LWP_MINSTACKSIZE);
for (i=0; i < NSOFTSIG; i++) {
PROCESS pid;
- if (p=sigProc[i]) /* This yields!!! */
- LWP_CreateProcess2(p, stackSize, LWP_NORMAL_PRIORITY, sigRock[i],
- "SignalHandler", &pid);
+ if ((p=sigProc[i])) /* This yields!!! */
+ LWP_CreateProcess2(p, stackSize, LWP_NORMAL_PRIORITY,
+ sigRock[i], "SignalHandler", &pid);
sigProc[i] = 0;
}
/* Keep IOMGR process id */
static PROCESS IOMGR_Id = NULL;
-int IOMGR_SoftSig(aproc, arock)
-int (*aproc)();
-char *arock; {
+int IOMGR_SoftSig(void *(*aproc)(void *), void *arock)
+{
register int i;
for (i=0;i<NSOFTSIG;i++) {
if (sigProc[i] == 0) {
}
-unsigned char allOnes[100];
-
int IOMGR_Initialize(void)
{
- extern int TM_Init();
PROCESS pid;
/* If lready initialized, just return */
sigsHandled = 0;
anySigsDelivered = TRUE; /* A soft signal may have happened before
IOMGR_Initialize: so force a check for signals regardless */
- memset(allOnes, 0xff, sizeof(allOnes));
-#ifdef AFS_DJGPP_ENV
- install_ncb_handler();
-#endif /* AFS_DJGPP_ENV */
-
- return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, 0, "IO MANAGER",
- &IOMGR_Id);
+ return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, (void *) 0,
+ "IO MANAGER", &IOMGR_Id);
}
-int IOMGR_Finalize()
+int IOMGR_Finalize(void)
{
int status;
return 0;
}
-int IOMGR_Select(fds, readfds, writefds, exceptfds, timeout)
- int fds;
- fd_set *readfds, *writefds, *exceptfds;
- struct timeval *timeout;
+int IOMGR_Select(int fds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout)
{
register struct IoRequest *request;
int result;
#ifdef DEBUG
if (lwp_debug != 0) puts("[Polling SELECT]");
#endif /* DEBUG */
+#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_NT40_ENV)
again:
+#endif
code = select(fds, readfds, writefds, exceptfds, timeout);
#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_AIX32_ENV)
/*
#ifndef AFS_NT40_ENV
/* Cause delivery of signal signo to result in a LWP_SignalProcess of
event. */
-IOMGR_Signal (signo, event)
- int signo;
- char *event;
+int IOMGR_Signal (int signo, char *event)
{
struct sigaction sa;
if (event == NULL)
return LWP_EBADEVENT;
sa.sa_handler = SigHandler;
- sa.sa_mask = *((sigset_t *) allOnes); /* mask all signals */
+ sigfillset(&sa.sa_mask); /* mask all signals */
sa.sa_flags = 0;
sigsHandled |= mysigmask(signo);
sigEvents[signo] = event;
}
/* Stop handling occurrences of signo. */
-IOMGR_CancelSignal (signo)
- int signo;
+int IOMGR_CancelSignal (int signo)
{
if (badsig(signo) || (sigsHandled & mysigmask(signo)) == 0)
return LWP_EBADSIG;
- sigaction (signo, &oldActions[signo], (struct sigaction *)0);
+ sigaction (signo, &oldActions[signo], NULL);
sigsHandled &= ~mysigmask(signo);
return LWP_SUCCESS;
}
/* This routine calls select is a fashion that simulates the standard sleep routine */
void IOMGR_Sleep (int seconds)
{
-#ifndef AFS_DJGPP_ENV
struct timeval timeout;
timeout.tv_sec = seconds;
timeout.tv_usec = 0;
IOMGR_Select(0, 0, 0, 0, &timeout);
-#else
- struct timeval timeout;
- int s;
- fd_set set, empty;
- FD_ZERO(&empty);
- FD_ZERO(&set);
- s = socket(AF_INET,SOCK_STREAM,0);
- FD_SET(s,&set);
-
- timeout.tv_sec = seconds;
- timeout.tv_usec = 0;
- IOMGR_Select(1,&set,&empty,&empty,&timeout);
- close(s);
-#endif /* DJGPP */
}
#endif /* USE_PTHREADS */
-
-
-#ifdef AFS_DJGPP_ENV
-
-/* Netbios code for djgpp port */
-
-int IOMGR_NCBSelect(ncbp, dos_ncb, timeout)
- NCB *ncbp;
- dos_ptr dos_ncb;
- struct timeval *timeout;
-{
- struct IoRequest *request;
- int result;
-
- if (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)
- {
- /* Poll */
- if (ncbp->ncb_event != NULL)
- {
- /* error */
- return -1;
- }
-
- if (get_dos_member_b(NCB, dos_ncb, ncb_cmd_cplt) != 0xff)
- {
- return 1;
- }
- else {
- return 0;
- }
- }
-
- /* Construct request block & insert */
- request = NewRequest();
- request->ncbp = ncbp;
- request->dos_ncb = dos_ncb;
-
- if (timeout == NULL)
- {
- request->timeout.TotalTime.tv_sec = -1;
- request->timeout.TotalTime.tv_usec = -1;
- }
- else
- {
- request -> timeout.TotalTime = *timeout;
- /* check for bad request */
- if (timeout->tv_sec < 0 || timeout->tv_usec < 0 || timeout->tv_usec > 999999)
- {
- /* invalid arg */
- iomgr_badtv = *timeout;
- iomgr_badpid = LWP_ActiveProcess;
- /* now fixup request */
- if(request->timeout.TotalTime.tv_sec < 0)
- request->timeout.TotalTime.tv_sec = 1;
- request->timeout.TotalTime.tv_usec = 100000;
- }
- }
-
- request->timeout.BackPointer = (char *)request;
-
- /* Insert my PID in case of IOMGR_Cancel */
- request -> pid = LWP_ActiveProcess;
- LWP_ActiveProcess -> iomgrRequest = request;
-
-#ifdef DEBUG
- request -> timeout.Next = (struct TM_Elem *) 1;
- request -> timeout.Prev = (struct TM_Elem *) 1;
-#endif /* DEBUG */
- TM_Insert(Requests, &request->timeout);
-
- if (ncbp->ncb_event != NULL)
- {
- /* since we were given an event, we can return immediately and just
- signal the event once the request completes. */
- return 0;
- }
- else
- {
- /* Wait for action */
-
- LWP_QWait();
-
- /* Update parameters & return */
- result = request -> result;
-
- FreeRequest(request);
- return (result > 1 ? 1 : result);
- }
-}
-
-int IOMGR_CheckNCB()
-{
- int woke_someone = FALSE;
- EVENT_HANDLE ev;
- PROCESS pid;
-
- anyNCBComplete = FALSE;
- FOR_ALL_ELTS(r, Requests, {
- register struct IoRequest *req;
- req = (struct IoRequest *) r -> BackPointer;
-
- if (req->dos_ncb && get_dos_member_b(NCB, req->dos_ncb, ncb_cmd_cplt) != 0xff)
- {
- /* this NCB has completed */
- TM_Remove(Requests, &req->timeout);
-
- /* copy out NCB from DOS to virtual space */
- dosmemget(req->dos_ncb, sizeof(NCB), (char *) req->ncbp);
-
- if (ev = req->ncbp->ncb_event)
- {
- thrd_SetEvent(ev);
- }
- else
- {
- woke_someone = TRUE;
- LWP_QSignal(pid=req->pid);
- pid->iomgrRequest = 0;
- }
- }
- })
- return woke_someone;
-}
-
-int ncb_handler(__dpmi_regs *r)
-{
- anyNCBComplete = TRUE; /* NCB completed */
- /* Make sure that the IOMGR process doesn't pause on the select. */
- iomgr_timeout.tv_sec = 0;
- iomgr_timeout.tv_usec = 0;
- return;
-}
-
-int install_ncb_handler()
-{
- callback_info.pm_offset = (long) ncb_handler;
- if (_go32_dpmi_allocate_real_mode_callback_retf(&callback_info,
- &callback_regs))
- {
- fprintf(stderr, "error, allocate_real_mode_callback_retf failed\n");
- return -1;
- }
-
- handler_seg = callback_info.rm_segment;
- handler_off = callback_info.rm_offset;
-
- /*printf("NCB handler_seg=0x%x, off=0x%x\n", handler_seg, handler_off);*/
-}
-#endif /* AFS_DJGPP_ENV */