This patch switches the MINIX3 ethernet driver stack from a port-based
model to an instance-based model. Each ethernet driver instance is now responsible for exactly one network interface card. The port field in /etc/inet.conf now acts as an instance field instead. This patch also updates the data link protocol. This update: - eliminates the concept of ports entirely; - eliminates DL_GETNAME entirely; - standardizes on using m_source for IPC and DL_ENDPT for safecopies; - removes error codes from TASK/STAT replies, as they were unused; - removes a number of other old or unused fields; - names and renames a few other fields. All ethernet drivers have been changed to: - conform to the new protocol, and exactly that; - take on an instance number based on a given "instance" argument; - skip that number of PCI devices in probe iterations; - use config tables and environment variables based on that number; - no longer be limited to a predefined maximum of cards in any way; - get rid of any leftover non-safecopy support and other ancient junk; - have a correct banner protocol figure, or none at all. Other changes: * Inet.conf is now taken to be line-based, and supports #-comments. No existing installations are expected to be affected by this. * A new, select-based asynchio library replaces the old one. Kindly contributed by Kees J. Bot. * Inet now supports use of select() on IP devices. Combined, the last two changes together speed up dhcpd considerably in the presence of multiple interfaces. * A small bug has been fixed in nonamed.
This commit is contained in:
@@ -7,7 +7,7 @@ LIB= c
|
||||
CPPFLAGS+=-O -D_MINIX -D_POSIX_SOURCE
|
||||
|
||||
.include "${.CURDIR}/ansi/Makefile.inc"
|
||||
.include "${.CURDIR}/wchar/Makefile.inc"
|
||||
.include "${.CURDIR}/asyn/Makefile.inc"
|
||||
.include "${.CURDIR}/ip/Makefile.inc"
|
||||
.include "${.CURDIR}/math/Makefile.inc"
|
||||
.include "${.CURDIR}/other/Makefile.inc"
|
||||
@@ -17,6 +17,7 @@ CPPFLAGS+=-O -D_MINIX -D_POSIX_SOURCE
|
||||
.include "${.CURDIR}/stdtime/Makefile.inc"
|
||||
.include "${.CURDIR}/syscall/Makefile.inc"
|
||||
.include "${.CURDIR}/sysvipc/Makefile.inc"
|
||||
.include "${.CURDIR}/wchar/Makefile.inc"
|
||||
|
||||
.include "${.CURDIR}/arch/${ARCH}/int64/Makefile.inc"
|
||||
.include "${.CURDIR}/arch/${ARCH}/misc/Makefile.inc"
|
||||
|
||||
12
lib/libc/asyn/Makefile.inc
Normal file
12
lib/libc/asyn/Makefile.inc
Normal file
@@ -0,0 +1,12 @@
|
||||
# ansi sources
|
||||
.PATH: ${.CURDIR}/asyn
|
||||
|
||||
SRCS+= \
|
||||
asyn_cancel.c \
|
||||
asyn_close.c \
|
||||
asyn_init.c \
|
||||
asyn_pending.c \
|
||||
asyn_read.c \
|
||||
asyn_synch.c \
|
||||
asyn_wait.c \
|
||||
asyn_write.c
|
||||
17
lib/libc/asyn/asyn.h
Normal file
17
lib/libc/asyn/asyn.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* asyn.h - async I/O
|
||||
* Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
* Minix-vmd compatible asynchio(3) using BSD select(2).
|
||||
*/
|
||||
#define nil 0
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/asynchio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct _asynfd asynfd_t;
|
||||
|
||||
typedef enum state { IDLE, WAITING, PENDING } state_t;
|
||||
21
lib/libc/asyn/asyn_cancel.c
Normal file
21
lib/libc/asyn/asyn_cancel.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/* asyn_cancel() - cancel an asynch operation Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
|
||||
int asyn_cancel(asynchio_t *asyn, int fd, int op)
|
||||
/* Cancel an asynchronous operation if one is in progress. (This is easy with
|
||||
* select(2), because no operation is actually happening.)
|
||||
*/
|
||||
{
|
||||
asynfd_t *afd;
|
||||
|
||||
if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
|
||||
afd= &asyn->asyn_afd[fd];
|
||||
|
||||
if (afd->afd_state[op] == WAITING) {
|
||||
afd->afd_state[op]= IDLE;
|
||||
FD_CLR(fd, &asyn->asyn_fdset[SEL_READ]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
24
lib/libc/asyn/asyn_close.c
Normal file
24
lib/libc/asyn/asyn_close.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/* asyn_close() - forcefully forget about a file descriptor
|
||||
* Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
|
||||
int asyn_close(asynchio_t *asyn, int fd)
|
||||
/* Stop caring about any async operations on this file descriptor. */
|
||||
{
|
||||
asynfd_t *afd;
|
||||
int op;
|
||||
|
||||
if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
|
||||
|
||||
afd= &asyn->asyn_afd[fd];
|
||||
|
||||
for (op= 0; op < SEL_NR; op++) {
|
||||
afd->afd_state[op]= IDLE;
|
||||
FD_CLR(fd, &asyn->asyn_fdset[op]);
|
||||
}
|
||||
afd->afd_seen= 0;
|
||||
asyn->asyn_more++;
|
||||
return 0;
|
||||
}
|
||||
9
lib/libc/asyn/asyn_init.c
Normal file
9
lib/libc/asyn/asyn_init.c
Normal file
@@ -0,0 +1,9 @@
|
||||
/* asyn_init() Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
|
||||
void asyn_init(asynchio_t *asyn)
|
||||
{
|
||||
memset(asyn, 0, sizeof(*asyn));
|
||||
}
|
||||
14
lib/libc/asyn/asyn_pending.c
Normal file
14
lib/libc/asyn/asyn_pending.c
Normal file
@@ -0,0 +1,14 @@
|
||||
/* asyn_pending() - any results pending? Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
|
||||
int asyn_pending(asynchio_t *asyn, int fd, int op)
|
||||
/* Check if a result of an operation is pending. (This is easy with
|
||||
* select(2), because no operation is actually happening.)
|
||||
*/
|
||||
{
|
||||
if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
61
lib/libc/asyn/asyn_read.c
Normal file
61
lib/libc/asyn/asyn_read.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* asyn_read() Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
#include <signal.h>
|
||||
|
||||
ssize_t asyn_read(asynchio_t *asyn, int fd, void *buf, size_t len)
|
||||
/* Asynchronous read(). Try if a read can be done, if not then set a flag
|
||||
* indicating that select(2) should look out for it. Returns like a normal
|
||||
* read or returns -1 with errno set to EAGAIN.
|
||||
*/
|
||||
{
|
||||
asynfd_t *afd;
|
||||
|
||||
/* Asyn_wait() may block if this counter equals zero indicating that
|
||||
* all of the asyn_* functions are "in progress".
|
||||
*/
|
||||
asyn->asyn_more++;
|
||||
|
||||
if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
|
||||
afd= &asyn->asyn_afd[fd];
|
||||
|
||||
/* If this is the first async call on this filedescriptor then
|
||||
* remember its file flags.
|
||||
*/
|
||||
if (!afd->afd_seen) {
|
||||
if ((afd->afd_flags= fcntl(fd, F_GETFL)) < 0) return -1;
|
||||
afd->afd_seen= 1;
|
||||
}
|
||||
|
||||
/* Try to read if I/O is pending. */
|
||||
if (afd->afd_state[SEL_READ] == PENDING) {
|
||||
sigset_t mask;
|
||||
ssize_t result;
|
||||
int err;
|
||||
|
||||
sigemptyset(&mask);
|
||||
if (sigprocmask(SIG_SETMASK, &mask, &mask) < 0) return -1;
|
||||
(void) fcntl(fd, F_SETFL, afd->afd_flags | O_NONBLOCK);
|
||||
|
||||
/* Try the actual read. */
|
||||
result= read(fd, buf, len);
|
||||
err= errno;
|
||||
|
||||
(void) fcntl(fd, F_SETFL, afd->afd_flags);
|
||||
(void) sigprocmask(SIG_SETMASK, &mask, nil);
|
||||
|
||||
errno= err;
|
||||
if (result != -1 || errno != EAGAIN) {
|
||||
afd->afd_state[SEL_READ]= IDLE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Record this read as "waiting". */
|
||||
afd->afd_state[SEL_READ]= WAITING;
|
||||
FD_SET(fd, &asyn->asyn_fdset[SEL_READ]);
|
||||
errno= EAGAIN;
|
||||
asyn->asyn_more--;
|
||||
return -1;
|
||||
}
|
||||
104
lib/libc/asyn/asyn_special.c
Normal file
104
lib/libc/asyn/asyn_special.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/* asyn_special(), asyn_result() Author: Kees J. Bot
|
||||
* 8 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
#include <signal.h>
|
||||
|
||||
/* Saved signal mask between asyn_special() and asyn_result(). */
|
||||
static sigset_t mask;
|
||||
|
||||
int asyn_special(asynchio_t *asyn, int fd, int op)
|
||||
/* Wait for an operation. This is an odd one out compared to asyn_read()
|
||||
* and asyn_write(). It does not do an operation itself, but together with
|
||||
* asyn_result() it is a set of brackets around a system call xxx that has
|
||||
* no asyn_xxx() for itself. It can be used to build an asyn_accept() or
|
||||
* asyn_connect() for instance. (Minix-vmd has asyn_ioctl() instead,
|
||||
* which is used for any other event like TCP/IP listen/connect. BSD has
|
||||
* a myriad of calls that can't be given an asyn_xxx() counterpart each.)
|
||||
* Asyn_special() returns -1 for "forget it", 0 for "try it", and 1 for
|
||||
* "very first call, maybe you should try it once, maybe not". Errno is
|
||||
* set to EAGAIN if the result is -1 or 1. After trying the system call
|
||||
* make sure errno equals EAGAIN if the call is still in progress and call
|
||||
* asyn_result with the result of the system call. Asyn_result() must be
|
||||
* called if asyn_special() returns 0 or 1.
|
||||
*
|
||||
* Example use:
|
||||
*
|
||||
* int asyn_accept(asynchio_t *asyn, int s, struct sockaddr *addr, int *addrlen)
|
||||
* {
|
||||
* int r;
|
||||
* if ((r= asyn_special(asyn, fd, SEL_READ)) < 0) return -1;
|
||||
* r= r == 0 ? accept(fd, addr, addrlen) : -1;
|
||||
* return asyn_result(asyn, fd, SEL_READ, r);
|
||||
* }
|
||||
*
|
||||
* int asyn_connect(asynchio_t *asyn, int s, struct sockaddr *name, int namelen)
|
||||
* {
|
||||
* int r;
|
||||
* if ((r= asyn_special(asyn, fd, SEL_WRITE)) < 0) return -1;
|
||||
* if (r == 1 && (r= connect(fd, name, namelen)) < 0) {
|
||||
* if (errno == EINPROGRESS) errno= EAGAIN;
|
||||
* }
|
||||
* return asyn_result(asyn, fd, SEL_WRITE, r);
|
||||
* }
|
||||
*/
|
||||
{
|
||||
asynfd_t *afd;
|
||||
int seen;
|
||||
|
||||
asyn->asyn_more++;
|
||||
|
||||
if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
|
||||
afd= &asyn->asyn_afd[fd];
|
||||
|
||||
/* If this is the first async call on this filedescriptor then
|
||||
* remember its file flags.
|
||||
*/
|
||||
if (!(seen= afd->afd_seen)) {
|
||||
if ((afd->afd_flags= fcntl(fd, F_GETFL)) < 0) return -1;
|
||||
afd->afd_seen= 1;
|
||||
}
|
||||
|
||||
/* Try to read if I/O is pending. */
|
||||
if (!seen || afd->afd_state[op] == PENDING) {
|
||||
sigemptyset(&mask);
|
||||
if (sigprocmask(SIG_SETMASK, &mask, &mask) < 0) return -1;
|
||||
(void) fcntl(fd, F_SETFL, afd->afd_flags | O_NONBLOCK);
|
||||
|
||||
/* Let the caller try the system call. */
|
||||
errno= EAGAIN;
|
||||
return seen ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Record this read as "waiting". */
|
||||
afd->afd_state[op]= WAITING;
|
||||
FD_SET(fd, &asyn->asyn_fdset[op]);
|
||||
errno= EAGAIN;
|
||||
asyn->asyn_more--;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int asyn_result(asynchio_t *asyn, int fd, int op, int result)
|
||||
/* The caller has tried the system call with the given result. Finish up. */
|
||||
{
|
||||
int err;
|
||||
asynfd_t *afd= &asyn->asyn_afd[fd];
|
||||
|
||||
err= errno;
|
||||
|
||||
(void) fcntl(fd, F_SETFL, afd->afd_flags);
|
||||
(void) sigprocmask(SIG_SETMASK, &mask, nil);
|
||||
|
||||
errno= err;
|
||||
if (result != -1 || errno != EAGAIN) {
|
||||
afd->afd_state[op]= IDLE;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Record this operation as "waiting". */
|
||||
afd->afd_state[op]= WAITING;
|
||||
FD_SET(fd, &asyn->asyn_fdset[op]);
|
||||
errno= EAGAIN;
|
||||
asyn->asyn_more--;
|
||||
return -1;
|
||||
}
|
||||
27
lib/libc/asyn/asyn_synch.c
Normal file
27
lib/libc/asyn/asyn_synch.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* asyn_synch() - step back to synch Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
|
||||
int asyn_synch(asynchio_t *asyn, int fd)
|
||||
/* No more asynchronous operations on this file descriptor. */
|
||||
{
|
||||
asynfd_t *afd;
|
||||
int flags;
|
||||
int op;
|
||||
|
||||
if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
|
||||
afd= &asyn->asyn_afd[fd];
|
||||
|
||||
for (op= 0; op < SEL_NR; op++) {
|
||||
if (afd->afd_state[op] != IDLE) {
|
||||
errno= EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the file flags are as they once were. */
|
||||
if (afd->afd_seen && fcntl(fd, F_SETFL, afd->afd_flags) < 0) return -1;
|
||||
afd->afd_seen= 0;
|
||||
return 0;
|
||||
}
|
||||
119
lib/libc/asyn/asyn_wait.c
Normal file
119
lib/libc/asyn/asyn_wait.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/* asyn_wait() - wait for asynch operations Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#define DEBUG 0
|
||||
|
||||
#include "asyn.h"
|
||||
#include <time.h>
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define TBOUND_MIN 1
|
||||
#define TBOUND_MAX 16
|
||||
|
||||
int asyn_wait(asynchio_t *asyn, int flags, struct timeval *to)
|
||||
/* Wait for one or more nonblocking operations to return a result. */
|
||||
{
|
||||
int r;
|
||||
static struct timeval zero_time;
|
||||
struct timeval t;
|
||||
static time_t tbound= TBOUND_MIN;
|
||||
|
||||
/* Are there more things to do before we can block? */
|
||||
if (asyn->asyn_more > 0) { asyn->asyn_more= 0; return 0; }
|
||||
|
||||
if (flags & ASYN_NONBLOCK) {
|
||||
/* Don't block by using a zero second timeout. */
|
||||
to= &zero_time;
|
||||
} else
|
||||
if (to != nil) {
|
||||
/* asyn_wait() uses an absolute time. */
|
||||
if (to->tv_usec >= 1000000L) {
|
||||
to->tv_sec+= to->tv_usec / 1000000L;
|
||||
to->tv_usec%= 1000000L;
|
||||
}
|
||||
(void) gettimeofday(&t, nil);
|
||||
if (t.tv_sec > to->tv_sec || (t.tv_sec == to->tv_sec
|
||||
&& t.tv_usec >= to->tv_usec)) {
|
||||
to= &zero_time;
|
||||
} else {
|
||||
t.tv_sec= to->tv_sec - t.tv_sec;
|
||||
t.tv_usec= to->tv_usec - t.tv_usec;
|
||||
if (t.tv_usec < 0) {
|
||||
t.tv_sec--;
|
||||
t.tv_usec+= 1000000L;
|
||||
}
|
||||
to= &t;
|
||||
}
|
||||
|
||||
/* Don't sleep too long, we don't trust select(). */
|
||||
if (to->tv_sec > tbound) goto bound;
|
||||
} else {
|
||||
bound:
|
||||
/* No timeout? Don't hang in (buggy?) select() forever. */
|
||||
to= &t;
|
||||
t.tv_sec= tbound;
|
||||
t.tv_usec= 0;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
int op;
|
||||
|
||||
fprintf(stderr, "select: ");
|
||||
for (op= 0; op < SEL_NR; op++) {
|
||||
fd_set *fdsetp= &asyn->asyn_fdset[op];
|
||||
int fd;
|
||||
|
||||
for (fd= 0; fd < FD_SETSIZE; fd++) {
|
||||
if (FD_ISSET(fd, fdsetp)) {
|
||||
asyn->asyn_afd[fd].afd_state[op]=
|
||||
PENDING;
|
||||
fprintf(stderr, "%d%c", fd, "rwx"[op]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
r= select(FD_SETSIZE, &asyn->asyn_fdset[SEL_READ],
|
||||
&asyn->asyn_fdset[SEL_WRITE],
|
||||
&asyn->asyn_fdset[SEL_EXCEPT], to);
|
||||
#if DEBUG
|
||||
fprintf(stderr, " (%d) ", r);
|
||||
#endif
|
||||
if (r > 0) {
|
||||
/* An event occurred on one or more file descriptors. */
|
||||
int op;
|
||||
|
||||
for (op= 0; op < SEL_NR; op++) {
|
||||
fd_set *fdsetp= &asyn->asyn_fdset[op];
|
||||
int fd;
|
||||
|
||||
for (fd= 0; fd < FD_SETSIZE; fd++) {
|
||||
if (FD_ISSET(fd, fdsetp)) {
|
||||
asyn->asyn_afd[fd].afd_state[op]=
|
||||
PENDING;
|
||||
#if DEBUG
|
||||
fprintf(stderr, "%d%c", fd, "rwx"[op]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
tbound= TBOUND_MIN;
|
||||
} else
|
||||
if (r == 0) {
|
||||
/* If nothing happened then let the time boundary slip a bit. */
|
||||
if (tbound < TBOUND_MAX) tbound <<= 1;
|
||||
}
|
||||
#if DEBUG
|
||||
fputc('\n', stderr);
|
||||
#endif
|
||||
|
||||
FD_ZERO(&asyn->asyn_fdset[SEL_READ]);
|
||||
FD_ZERO(&asyn->asyn_fdset[SEL_WRITE]);
|
||||
FD_ZERO(&asyn->asyn_fdset[SEL_EXCEPT]);
|
||||
|
||||
return r == 0 ? (errno= EINTR, -1) : r;
|
||||
}
|
||||
50
lib/libc/asyn/asyn_write.c
Normal file
50
lib/libc/asyn/asyn_write.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* asyn_write() Author: Kees J. Bot
|
||||
* 7 Jul 1997
|
||||
*/
|
||||
#include "asyn.h"
|
||||
#include <signal.h>
|
||||
|
||||
ssize_t asyn_write(asynchio_t *asyn, int fd, const void *buf, size_t len)
|
||||
/* Nonblocking write(). (See asyn_read()). */
|
||||
{
|
||||
asynfd_t *afd;
|
||||
ssize_t result;
|
||||
|
||||
asyn->asyn_more++;
|
||||
|
||||
if ((unsigned) fd >= FD_SETSIZE) { errno= EBADF; return -1; }
|
||||
afd= &asyn->asyn_afd[fd];
|
||||
|
||||
if (!afd->afd_seen) {
|
||||
if ((afd->afd_flags= fcntl(fd, F_GETFL)) < 0) return -1;
|
||||
afd->afd_seen= 1;
|
||||
}
|
||||
|
||||
if (afd->afd_state[SEL_WRITE] == PENDING) {
|
||||
sigset_t mask;
|
||||
ssize_t result;
|
||||
int err;
|
||||
|
||||
sigemptyset(&mask);
|
||||
if (sigprocmask(SIG_SETMASK, &mask, &mask) < 0) return -1;
|
||||
(void) fcntl(fd, F_SETFL, afd->afd_flags | O_NONBLOCK);
|
||||
|
||||
result= write(fd, buf, len);
|
||||
err= errno;
|
||||
|
||||
(void) fcntl(fd, F_SETFL, afd->afd_flags);
|
||||
(void) sigprocmask(SIG_SETMASK, &mask, nil);
|
||||
|
||||
errno= err;
|
||||
if (result != -1 || errno != EAGAIN) {
|
||||
afd->afd_state[SEL_WRITE]= IDLE;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
afd->afd_state[SEL_WRITE]= WAITING;
|
||||
FD_SET(fd, &asyn->asyn_fdset[SEL_WRITE]);
|
||||
errno= EAGAIN;
|
||||
asyn->asyn_more--;
|
||||
return -1;
|
||||
}
|
||||
@@ -35,7 +35,6 @@ SRCS+= \
|
||||
_vm_set_priv.c \
|
||||
_vm_update.c \
|
||||
_vm_query_exit.c \
|
||||
asynchio.c \
|
||||
basename.c \
|
||||
bcmp.c \
|
||||
bcopy.c \
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/* asyn_init(), asyn_read(), asyn_write(), asyn_ioctl(),
|
||||
* asyn_wait(), asyn_synch(), asyn_close()
|
||||
* Author: Kees J. Bot
|
||||
* 26 Jan 1995
|
||||
* Thise are just stub routines that are call compatible with
|
||||
* the asynchio(3) library of Minix-vmd. See asynchio.h.
|
||||
*/
|
||||
#define alarm _alarm
|
||||
#define ioctl _ioctl
|
||||
#define read _read
|
||||
#define sigaction _sigaction
|
||||
#define sigfillset _sigfillset
|
||||
#define time _time
|
||||
#define write _write
|
||||
#include <lib.h>
|
||||
#include <time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/asynchio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define IO_IDLE 0
|
||||
#define IO_INPROGRESS 1
|
||||
#define IO_RESULT 2
|
||||
|
||||
#define OP_NOOP 0
|
||||
#define OP_READ 1
|
||||
#define OP_WRITE 2
|
||||
#define OP_IOCTL 3
|
||||
|
||||
static asynchio_t *asyn_current;
|
||||
|
||||
void asyn_init(asynchio_t *asyn)
|
||||
{
|
||||
asyn->state= IO_IDLE;
|
||||
asyn->op= OP_NOOP;
|
||||
}
|
||||
|
||||
static ssize_t operation(int op, asynchio_t *asyn, int fd, int req,
|
||||
void *data, ssize_t count)
|
||||
{
|
||||
switch (asyn->state) {
|
||||
case IO_INPROGRESS:
|
||||
if (asyn_current != asyn && asyn->op != op) abort();
|
||||
/*FALL THROUGH*/
|
||||
case IO_IDLE:
|
||||
asyn_current= asyn;
|
||||
asyn->op= op;
|
||||
asyn->fd= fd;
|
||||
asyn->req= req;
|
||||
asyn->data= data;
|
||||
asyn->count= count;
|
||||
asyn->state= IO_INPROGRESS;
|
||||
errno= EINPROGRESS;
|
||||
return -1;
|
||||
case IO_RESULT:
|
||||
if (asyn_current != asyn && asyn->op != op) abort();
|
||||
errno= asyn->errno;
|
||||
return asyn->count;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t asyn_read(asynchio_t *asyn, int fd, void *buf, size_t len)
|
||||
{
|
||||
return operation(OP_READ, asyn, fd, 0, buf, len);
|
||||
}
|
||||
|
||||
ssize_t asyn_write(asynchio_t *asyn, int fd, const void *buf, size_t len)
|
||||
{
|
||||
return operation(OP_WRITE, asyn, fd, 0, (void *) buf, len);
|
||||
}
|
||||
|
||||
int asyn_ioctl(asynchio_t *asyn, int fd, unsigned long request, void *data)
|
||||
{
|
||||
return operation(OP_IOCTL, asyn, fd, request, data, 0);
|
||||
}
|
||||
|
||||
static void time_out(int sig)
|
||||
{
|
||||
alarm(1);
|
||||
}
|
||||
|
||||
int asyn_wait(asynchio_t *asyn, int flags, struct timeval *to)
|
||||
{
|
||||
time_t now;
|
||||
unsigned old_timer, new_timer;
|
||||
struct sigaction old_sa, new_sa;
|
||||
|
||||
if (asyn_current != asyn) abort();
|
||||
if (flags & ASYN_NONBLOCK) abort();
|
||||
|
||||
if (asyn->state == IO_RESULT) {
|
||||
asyn->state= IO_IDLE;
|
||||
asyn->op= OP_NOOP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (to != NULL) {
|
||||
now= time(NULL);
|
||||
if (to->tv_sec <= now) { errno= EINTR; return -1; }
|
||||
old_timer= alarm(0);
|
||||
new_sa.sa_handler= time_out;
|
||||
sigfillset(&new_sa.sa_mask);
|
||||
new_sa.sa_flags= 0;
|
||||
sigaction(SIGALRM, &new_sa, &old_sa);
|
||||
new_timer= to->tv_sec - now;
|
||||
if (new_timer < old_timer) {
|
||||
new_timer= old_timer;
|
||||
}
|
||||
alarm(new_timer);
|
||||
}
|
||||
switch (asyn->op) {
|
||||
case OP_NOOP:
|
||||
asyn->count= pause();
|
||||
asyn->errno= errno;
|
||||
case OP_READ:
|
||||
asyn->count= read(asyn->fd, asyn->data, asyn->count);
|
||||
asyn->errno= errno;
|
||||
break;
|
||||
case OP_WRITE:
|
||||
asyn->count= write(asyn->fd, asyn->data, asyn->count);
|
||||
asyn->errno= errno;
|
||||
break;
|
||||
case OP_IOCTL:
|
||||
asyn->count= ioctl(asyn->fd, asyn->req, asyn->data);
|
||||
asyn->errno= errno;
|
||||
break;
|
||||
}
|
||||
if (to != NULL) {
|
||||
alarm(0);
|
||||
sigaction(SIGALRM, &old_sa, (struct sigaction *)0);
|
||||
alarm(old_timer);
|
||||
}
|
||||
|
||||
if (asyn->count == -1 && asyn->errno == EINTR) {
|
||||
errno= EINTR;
|
||||
return -1;
|
||||
} else {
|
||||
asyn->state= IO_RESULT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int asyn_synch(asynchio_t *asyn, int fd)
|
||||
{
|
||||
}
|
||||
|
||||
int asyn_close(asynchio_t *asyn, int fd)
|
||||
{
|
||||
asyn_init(asyn);
|
||||
}
|
||||
@@ -64,7 +64,7 @@ int *status_ptr;
|
||||
if(m_ptr->m_type == DL_CONF) {
|
||||
conf_expected = FALSE;
|
||||
}
|
||||
else if(m_ptr->m_type != DL_GETNAME) {
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user