* 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>
+
+RCSID("$Header$");
+
#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)
void IOMGR_Initialize() /* noop */
#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();
/* Result of select call */
long result;
+#ifdef AFS_DJGPP_ENV
+ NCB *ncbp;
+ dos_ptr dos_ncb;
+#endif /* AFS_DJGPP_ENV */
+
};
\f
/********************************\
static PROCESS iomgr_badpid;
static void SignalIO(int fds, fd_set *rfds, fd_set *wfds, fd_set *efs,
int code);
+static void SignalTimeout(int code, struct timeval *timeout);
+
+#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 */
/* 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 {
{
struct IoRequest *request;
- if (request=iorFreeList)
+ if ((request=iorFreeList))
iorFreeList = (struct IoRequest *) (request->result);
else request = (struct IoRequest *) malloc(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)
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
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;
LWP_QSignal(req->pid);
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);
}
#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) {
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();
}
/* 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;
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);
+ LWP_CreateProcess2(p, stackSize, LWP_NORMAL_PRIORITY,
+ (void *) sigRock[i], "SignalHandler", &pid);
sigProc[i] = 0;
}
IOMGR_Initialize: so force a check for signals regardless */
memset(allOnes, 0xff, sizeof(allOnes));
- return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, 0, "IO MANAGER",
- &IOMGR_Id);
+#ifdef AFS_DJGPP_ENV
+ install_ncb_handler();
+#endif /* AFS_DJGPP_ENV */
+
+ return LWP_CreateProcess(IOMGR, AFS_LWP_MINSTACKSIZE, 0, (void *) 0,
+ "IO MANAGER", &IOMGR_Id);
}
int IOMGR_Finalize()
#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;
}
/* 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(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(void)
+{
+ 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(void)
+{
+ 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 */