rktio: first cut at moving Racket OS wrappers to a library
The world doesn't need yet another cross-platform I/O library, but it's getting one. This one has exactly the things that Racket needs, and pulling it out will make it reusable from other VMs while improving the Racket code organization. This first step just gets started.
This commit is contained in:
parent
5d4bf33906
commit
64146e94dc
6
racket/src/configure
vendored
6
racket/src/configure
vendored
|
@ -838,7 +838,8 @@ LDFLAGS
|
||||||
LIBS
|
LIBS
|
||||||
CPPFLAGS
|
CPPFLAGS
|
||||||
CPP'
|
CPP'
|
||||||
ac_subdirs_all='foreign/libffi '
|
ac_subdirs_all='foreign/libffi
|
||||||
|
rktio '
|
||||||
|
|
||||||
# Initialize some variables set by options.
|
# Initialize some variables set by options.
|
||||||
ac_init_help=
|
ac_init_help=
|
||||||
|
@ -7150,6 +7151,9 @@ else
|
||||||
fi
|
fi
|
||||||
makefiles="$makefiles foreign/Makefile"
|
makefiles="$makefiles foreign/Makefile"
|
||||||
|
|
||||||
|
subdirs="$subdirs rktio"
|
||||||
|
|
||||||
|
|
||||||
# Remove any --enable or --disable arguments from `ac_configure_args':
|
# Remove any --enable or --disable arguments from `ac_configure_args':
|
||||||
new_configure_args=
|
new_configure_args=
|
||||||
fixup_prev=
|
fixup_prev=
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# This is the source for the `configure' script, to be compiled #
|
# This is the source for the `configure' script, to be compiled #
|
||||||
# by autoconf (use make-configure in this directory). #
|
# by autoconf (use `make-configure` in this directory). #
|
||||||
#################################################################
|
#################################################################
|
||||||
|
|
||||||
# Remember:
|
# Remember:
|
||||||
|
@ -1938,6 +1938,8 @@ else
|
||||||
fi
|
fi
|
||||||
makefiles="$makefiles foreign/Makefile"
|
makefiles="$makefiles foreign/Makefile"
|
||||||
|
|
||||||
|
AC_CONFIG_SUBDIRS( rktio )
|
||||||
|
|
||||||
# Remove any --enable or --disable arguments from `ac_configure_args':
|
# Remove any --enable or --disable arguments from `ac_configure_args':
|
||||||
new_configure_args=
|
new_configure_args=
|
||||||
fixup_prev=
|
fixup_prev=
|
||||||
|
|
|
@ -10,6 +10,11 @@ if [ -e "$tgt" ]; then
|
||||||
fi
|
fi
|
||||||
autoconf "$src" | racket "$0" > "$tgt"
|
autoconf "$src" | racket "$0" > "$tgt"
|
||||||
chmod +x "$tgt"
|
chmod +x "$tgt"
|
||||||
|
src="../rktio/configure.ac"
|
||||||
|
tgt="../rktio/configure"
|
||||||
|
echo "Creating $tgt from $src"
|
||||||
|
autoconf "$src" > "$tgt"
|
||||||
|
chmod +x "$tgt"
|
||||||
exit 0
|
exit 0
|
||||||
|#
|
|#
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
21
racket/src/rktio/Makefile.in
Normal file
21
racket/src/rktio/Makefile.in
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
|
||||||
|
CC = @CC@
|
||||||
|
CFLAGS = @CFLAGS@ @CPPFLAGS@
|
||||||
|
|
||||||
|
RKTIO_HEADERS = $(srcdir)/rktio.h $(srcdir)/rktio_private.h rktio_config.h
|
||||||
|
|
||||||
|
all: rktio_filesystem.o rktio_read_write.o rktio_poll_set.o rktio_error.o
|
||||||
|
|
||||||
|
rktio_filesystem.o: $(srcdir)/rktio_filesystem.c $(RKTIO_HEADERS)
|
||||||
|
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_filesystem.o -c $(srcdir)/rktio_filesystem.c
|
||||||
|
|
||||||
|
rktio_read_write.o: $(srcdir)/rktio_read_write.c $(RKTIO_HEADERS)
|
||||||
|
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_read_write.o -c $(srcdir)/rktio_read_write.c
|
||||||
|
|
||||||
|
rktio_poll_set.o: $(srcdir)/rktio_poll_set.c $(RKTIO_HEADERS)
|
||||||
|
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_poll_set.o -c $(srcdir)/rktio_poll_set.c
|
||||||
|
|
||||||
|
rktio_error.o: $(srcdir)/rktio_error.c $(RKTIO_HEADERS)
|
||||||
|
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_error.o -c $(srcdir)/rktio_error.c
|
5110
racket/src/rktio/configure
vendored
Executable file
5110
racket/src/rktio/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
196
racket/src/rktio/configure.ac
Normal file
196
racket/src/rktio/configure.ac
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# This is the source for the `configure` script, to be compiled #
|
||||||
|
# by autoconf (use `make-configure` in "../racket"). #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
AC_INIT([rktio.h])
|
||||||
|
AC_CONFIG_HEADERS([rktio_config.h])
|
||||||
|
|
||||||
|
AC_CONFIG_AUX_DIR(../lt)
|
||||||
|
AC_CANONICAL_SYSTEM
|
||||||
|
|
||||||
|
###### Autoconfigure #######
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
|
||||||
|
AC_CHECK_LIB(dl, dlopen)
|
||||||
|
|
||||||
|
############## platform tests ################
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
############## C flags ################
|
||||||
|
|
||||||
|
AC_LANG_C
|
||||||
|
|
||||||
|
AC_TYPE_INTPTR_T
|
||||||
|
AC_TYPE_UINTPTR_T
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for getaddrinfo])
|
||||||
|
AC_TRY_LINK([#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>],
|
||||||
|
[getaddrinfo(0, 0, 0, 0);],
|
||||||
|
AC_DEFINE(HAVE_GETADDRINFO,1,[Have getaddrinfo])
|
||||||
|
have_getaddrinfo=yes,
|
||||||
|
have_getaddrinfo=no)
|
||||||
|
AC_MSG_RESULT($have_getaddrinfo)
|
||||||
|
|
||||||
|
iconv_lib_flag=""
|
||||||
|
if test "${skip_iconv_check}" = "no" ; then
|
||||||
|
if test "${enable_iconv}" = "yes" ; then
|
||||||
|
AC_CHECK_HEADER(iconv.h, enable_iconv=yes, enable_iconv=no)
|
||||||
|
if test "${enable_iconv}" = "yes" ; then
|
||||||
|
# Does it all work, now?
|
||||||
|
AC_TRY_RUN(
|
||||||
|
[ #include <iconv.h>]
|
||||||
|
[ #include <langinfo.h>]
|
||||||
|
int main() {
|
||||||
|
[ iconv_open("UTF-8", "UTF-8");]
|
||||||
|
return 0;
|
||||||
|
}, enable_iconv=yes, enable_iconv=no, enable_iconv=yes)
|
||||||
|
if test "${enable_iconv}" = "no" ; then
|
||||||
|
# Try adding -liconv ?
|
||||||
|
# We did not use AC_CHECK_LIB because iconv is sometimes macro-renamed
|
||||||
|
ORIG_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -liconv"
|
||||||
|
AC_TRY_RUN(
|
||||||
|
[ #include <iconv.h>]
|
||||||
|
[ #include <langinfo.h>]
|
||||||
|
int main() {
|
||||||
|
[ iconv_open("UTF-8", "UTF-8");]
|
||||||
|
return 0;
|
||||||
|
}, enable_iconv=yes, enable_iconv=no, enable_iconv=yes)
|
||||||
|
if test "${enable_iconv}" = "no" ; then
|
||||||
|
LIBS="$ORIG_LIBS"
|
||||||
|
else
|
||||||
|
iconv_lib_flag=" -liconv"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
[ msg="iconv is usable" ]
|
||||||
|
AC_MSG_CHECKING($msg)
|
||||||
|
iconv_usage_result="$enable_iconv$iconv_lib_flag"
|
||||||
|
AC_MSG_RESULT($iconv_usage_result)
|
||||||
|
if test "${enable_iconv}" = "no" ; then
|
||||||
|
CFLAGS="$CFLAGS -DRKTIO_NO_ICONV"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ msg="for mbsrtowcs" ]
|
||||||
|
AC_MSG_CHECKING($msg)
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <strings.h>
|
||||||
|
int main() {
|
||||||
|
mbstate_t state;
|
||||||
|
char *src = "X";
|
||||||
|
bzero(&state, sizeof(mbstate_t));
|
||||||
|
mbsrtowcs(0, &src, 0, &state);
|
||||||
|
return 0;
|
||||||
|
}])], mbsrtowcs=yes, mbsrtowcs=no)
|
||||||
|
if test "$mbsrtowcs" = "no" ; then
|
||||||
|
CFLAGS="$CFLAGS -DNO_MBTOWC_FUNCTIONS"
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT($mbsrtowcs)
|
||||||
|
|
||||||
|
if test "${try_poll_syscall}" = "yes" ; then
|
||||||
|
[ msg="for poll" ]
|
||||||
|
AC_MSG_CHECKING($msg)
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <poll.h>
|
||||||
|
int main() {
|
||||||
|
struct pollfd pfd;
|
||||||
|
int r;
|
||||||
|
pfd.fd = 0;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
r = poll(&pfd, 1, 0);
|
||||||
|
return 0;
|
||||||
|
}])], use_poll=yes, use_poll=no)
|
||||||
|
AC_MSG_RESULT($use_poll)
|
||||||
|
if test "${use_poll}" = "yes" ; then
|
||||||
|
AC_DEFINE(HAVE_POLL_SYSCALL,1,[Have poll])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "${try_epoll_syscall}" = "yes" ; then
|
||||||
|
[ msg="for epoll" ]
|
||||||
|
AC_MSG_CHECKING($msg)
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
int main() {
|
||||||
|
int fd;
|
||||||
|
struct epoll_event ev;
|
||||||
|
fd = epoll_create(5);
|
||||||
|
ev.events = EPOLLIN | EPOLLONESHOT;
|
||||||
|
epoll_ctl(fd, EPOLL_CTL_ADD, 0, &ev);
|
||||||
|
return 0;
|
||||||
|
}])], use_epoll=yes, use_epoll=no)
|
||||||
|
AC_MSG_RESULT($use_epoll)
|
||||||
|
if test "${use_epoll}" = "yes" ; then
|
||||||
|
AC_DEFINE(HAVE_EPOLL_SYSCALL,1,[Have epoll])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "${try_inotify_syscall}" = "yes" ; then
|
||||||
|
[ msg="for inotify" ]
|
||||||
|
AC_MSG_CHECKING($msg)
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
int main() {
|
||||||
|
int fd;
|
||||||
|
int wd;
|
||||||
|
fd = inotify_init();
|
||||||
|
wd = inotify_add_watch(fd, "/tmp",
|
||||||
|
(IN_CREATE | IN_DELETE | IN_DELETE_SELF
|
||||||
|
| IN_MODIFY | IN_MOVE_SELF | IN_MOVED_TO));
|
||||||
|
return 0;
|
||||||
|
}])], use_inotify=yes, use_inotify=no)
|
||||||
|
AC_MSG_RESULT($use_inotify)
|
||||||
|
if test "${use_inotify}" = "yes" ; then
|
||||||
|
AC_DEFINE(HAVE_INOTIFY_SYSCALL,1,[Have inotify])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "${try_kqueue_syscall}" = "yes" ; then
|
||||||
|
[ msg="for kqueue" ]
|
||||||
|
AC_MSG_CHECKING($msg)
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
int main() {
|
||||||
|
int kq;
|
||||||
|
struct kevent kev;
|
||||||
|
struct timespec timeout = {0, 0};
|
||||||
|
kq = kqueue();
|
||||||
|
EV_SET(&kev, 0, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||||
|
kevent(kq, &kev, 1, NULL, 0, &timeout);
|
||||||
|
return 0;
|
||||||
|
}])], use_kqueue=yes, use_kqueue=no)
|
||||||
|
AC_MSG_RESULT($use_kqueue)
|
||||||
|
if test "${use_kqueue}" = "yes" ; then
|
||||||
|
AC_DEFINE(HAVE_KQUEUE_SYSCALL,1,[Have kqueue])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
LFS_CFLAGS=`getconf LFS_CFLAGS 2> /dev/null`
|
||||||
|
if test "${LFS_CFLAGS}" != "" && test "${LFS_CFLAGS}" != "undefined"; then
|
||||||
|
echo "Large-file support: ${LFS_CFLAGS}"
|
||||||
|
CFLAGS="${CFLAGS} ${LFS_CFLAGS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
############## final output ################
|
||||||
|
|
||||||
|
AC_SUBST(CC)
|
||||||
|
AC_SUBST(CFLAGS)
|
||||||
|
AC_SUBST(LDFLAGS)
|
||||||
|
|
||||||
|
makefiles="Makefile"
|
||||||
|
|
||||||
|
AC_OUTPUT($makefiles)
|
167
racket/src/rktio/rktio.h
Normal file
167
racket/src/rktio/rktio.h
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
#ifndef __RKTIO_H__
|
||||||
|
#define __RKTIO_H__
|
||||||
|
|
||||||
|
#include "rktio_config.h"
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* Reading and writing files */
|
||||||
|
|
||||||
|
typedef struct rktio_fd_t rktio_fd_t;
|
||||||
|
|
||||||
|
#define RKTIO_OPEN_READ (1<<0)
|
||||||
|
#define RKTIO_OPEN_WRITE (1<<1)
|
||||||
|
#define RKTIO_OPEN_TRUNCATE (1<<2)
|
||||||
|
#define RKTIO_OPEN_APPEND (1<<3)
|
||||||
|
#define RKTIO_OPEN_REPLACE (1<<4)
|
||||||
|
#define RKTIO_OPEN_MUST_EXIST (1<<5)
|
||||||
|
#define RKTIO_OPEN_CAN_EXIST (1<<6)
|
||||||
|
|
||||||
|
rktio_fd_t *rktio_fd(intptr_t system_fd, int modes);
|
||||||
|
|
||||||
|
rktio_fd_t *rktio_open(char *src, int modes);
|
||||||
|
int rktio_close(rktio_fd_t *fd);
|
||||||
|
|
||||||
|
#define RKTIO_READ_EOF (-1)
|
||||||
|
#define RKTIO_READ_ERROR (-2)
|
||||||
|
#define RKTIO_WRITE_ERROR (-2)
|
||||||
|
#define RKTIO_POLL_ERROR (-2)
|
||||||
|
|
||||||
|
intptr_t rktio_read(rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||||
|
intptr_t rktio_write(rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||||
|
|
||||||
|
int rktio_poll_read_ready(rktio_fd_t *rfd);
|
||||||
|
int rktio_poll_write_ready(rktio_fd_t *rfd);
|
||||||
|
int rktio_poll_write_flushed(rktio_fd_t *rfd);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* File-descriptor sets */
|
||||||
|
|
||||||
|
typedef struct rktio_poll_set_t rktio_poll_set_t;
|
||||||
|
|
||||||
|
#define RKTIO_POLL_READ RKTIO_OPEN_READ
|
||||||
|
#define RKTIO_POLL_WRITE RKTIO_OPEN_WRITE
|
||||||
|
|
||||||
|
void rktio_poll_add(rktio_fd_t *rfd, rktio_poll_set_t *fds, int modes);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* Files, directories, and links */
|
||||||
|
|
||||||
|
int rktio_file_exists(char *filename);
|
||||||
|
int rktio_directory_exists(char *dirname);
|
||||||
|
int rktio_link_exists(char *filename);
|
||||||
|
int rktio_is_regular_file(char *filename);
|
||||||
|
|
||||||
|
int rktio_delete_file(char *fn, int enable_write_on_fail);
|
||||||
|
int rktio_rename_file(char *dest, char *src, int exists_ok);
|
||||||
|
|
||||||
|
char *rktio_get_current_directory();
|
||||||
|
int rktio_set_current_directory(char *expanded);
|
||||||
|
int rktio_make_directory(char *filename);
|
||||||
|
int rktio_delete_directory(char *filename, char *current_directory, int enable_write_on_fail);
|
||||||
|
|
||||||
|
char *rktio_readlink(char *fullfilename);
|
||||||
|
int rktio_make_link(char *src, char *dest, int dest_is_directory);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* File attributes */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned lo, hi;
|
||||||
|
} rktio_size_t;
|
||||||
|
|
||||||
|
typedef intptr_t rktio_timestamp_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uintptr_t a, b, c;
|
||||||
|
} rktio_identity_t;
|
||||||
|
|
||||||
|
rktio_size_t *rktio_file_size(char *filename);
|
||||||
|
|
||||||
|
rktio_timestamp_t *rktio_get_file_modify_seconds(char *file);
|
||||||
|
int rktio_set_file_modify_seconds(char *file, rktio_timestamp_t secs);
|
||||||
|
|
||||||
|
rktio_identity_t *rktio_get_fd_identity(intptr_t fd, char *path);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* Permissions */
|
||||||
|
|
||||||
|
/* Must match OS bits: */
|
||||||
|
#define RKTIO_PERMISSION_READ 0x1
|
||||||
|
#define RKTIO_PERMISSION_WRITE 0x2
|
||||||
|
#define RKTIO_PERMISSION_EXEC 0x4
|
||||||
|
|
||||||
|
int rktio_get_file_or_directory_permissions(char *filename, int all_bits);
|
||||||
|
int rktio_set_file_or_directory_permissions(char *filename, int new_bits);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* Directory listing */
|
||||||
|
|
||||||
|
typedef struct rktio_directory_list_t rktio_directory_list_t;
|
||||||
|
|
||||||
|
rktio_directory_list_t *rktio_directory_list_start(char *filename, int is_drive);
|
||||||
|
char *rktio_directory_list_step(rktio_directory_list_t *dl);
|
||||||
|
|
||||||
|
char **rktio_filesystem_root_list();
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* File copying */
|
||||||
|
|
||||||
|
typedef struct rktio_file_copy_t rktio_file_copy_t;
|
||||||
|
|
||||||
|
rktio_file_copy_t *rktio_copy_file_start(char *dest, char *src, int exists_ok);
|
||||||
|
int rktio_copy_file_is_done(rktio_file_copy_t *fc);
|
||||||
|
int rktio_copy_file_step(rktio_file_copy_t *fc);
|
||||||
|
void rktio_copy_file_stop(rktio_file_copy_t *fc);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* System paths */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RKTIO_PATH_SYS_DIR,
|
||||||
|
RKTIO_PATH_TEMP_DIR,
|
||||||
|
RKTIO_PATH_PREF_DIR,
|
||||||
|
RKTIO_PATH_PREF_FILE,
|
||||||
|
RKTIO_PATH_ADDON_DIR,
|
||||||
|
RKTIO_PATH_HOME_DIR,
|
||||||
|
RKTIO_PATH_DESK_DIR,
|
||||||
|
RKTIO_PATH_DOC_DIR,
|
||||||
|
RKTIO_PATH_INIT_DIR,
|
||||||
|
RKTIO_PATH_INIT_FILE
|
||||||
|
};
|
||||||
|
|
||||||
|
char *rktio_system_path(int which);
|
||||||
|
char *rktio_expand_user_tilde(char *filename);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
/* Errors */
|
||||||
|
|
||||||
|
/* Kinds of error values: */
|
||||||
|
enum {
|
||||||
|
RKTIO_ERROR_KIND_POSIX,
|
||||||
|
RKTIO_ERROR_KIND_WINDOWS,
|
||||||
|
RKTIO_ERROR_KIND_GAI,
|
||||||
|
RKTIO_ERROR_KIND_RACKET
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Error IDs of kind RKTIO_ERROR_KIND_RACKET */
|
||||||
|
enum {
|
||||||
|
RKTIO_ERROR_UNSUPPORTED,
|
||||||
|
RKTIO_ERROR_EXISTS,
|
||||||
|
RKTIO_ERROR_LINK_FAILED,
|
||||||
|
RKTIO_ERROR_NOT_A_LINK,
|
||||||
|
RKTIO_ERROR_BAD_PERMISSION,
|
||||||
|
RKTIO_ERROR_IS_A_DIRECTORY,
|
||||||
|
RKTIO_ERROR_NOT_A_DIRECTORY,
|
||||||
|
RKTIO_ERROR_NO_TILDE,
|
||||||
|
RKTIO_ERROR_ILL_FORMED_USER,
|
||||||
|
RKTIO_ERROR_UNKNOWN_USER
|
||||||
|
};
|
||||||
|
|
||||||
|
int rktio_get_last_error(void);
|
||||||
|
int rktio_get_last_error_kind(void);
|
||||||
|
|
||||||
|
char *rktio_get_error_string(int kind, int errid);
|
||||||
|
|
||||||
|
/*************************************************/
|
||||||
|
|
||||||
|
#endif
|
21
racket/src/rktio/rktio_config.h.in
Normal file
21
racket/src/rktio/rktio_config.h.in
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* Whether `intptr_t' is available. */
|
||||||
|
#undef HAVE_INTPTR_T
|
||||||
|
|
||||||
|
/* Whether `uintptr_t' is available. */
|
||||||
|
#undef HAVE_UINTPTR_T
|
||||||
|
|
||||||
|
#ifdef HAVE_INTPTR_T
|
||||||
|
# include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_INTPTR_T
|
||||||
|
typedef long intptr_t;
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_UINTPTR_T
|
||||||
|
typedef unsigned long uintptr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* When poll(), epoll(), kqueue(), etc. is available: */
|
||||||
|
#undef HAVE_POLL_SYSCALL
|
||||||
|
#undef HAVE_EPOLL_SYSCALL
|
||||||
|
#undef HAVE_INOTIFY_SYSCALL
|
||||||
|
#undef HAVE_KQUEUE_SYSCALL
|
44
racket/src/rktio/rktio_error.c
Normal file
44
racket/src/rktio/rktio_error.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "rktio.h"
|
||||||
|
#include "rktio_private.h"
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
THREAD_LOCAL_DECL(static intptr_t errid);
|
||||||
|
THREAD_LOCAL_DECL(static int errkind);
|
||||||
|
|
||||||
|
void rktio_get_posix_error(void)
|
||||||
|
{
|
||||||
|
errid = errno;
|
||||||
|
errkind = RKTIO_ERROR_KIND_POSIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_set_racket_error(int new_errid)
|
||||||
|
{
|
||||||
|
errid = new_errid;
|
||||||
|
errkind = RKTIO_ERROR_KIND_RACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
void rktio_get_windows_error(void)
|
||||||
|
{
|
||||||
|
errid = GetLastError();
|
||||||
|
errkind = RKTIO_ERROR_KIND_WINDOWS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int rktio_get_last_error(void)
|
||||||
|
{
|
||||||
|
return errid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rktio_get_last_error_kind(void)
|
||||||
|
{
|
||||||
|
return errkind;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *rktio_get_error_string(int kind, int errid)
|
||||||
|
{
|
||||||
|
return "???";
|
||||||
|
}
|
1964
racket/src/rktio/rktio_filesystem.c
Normal file
1964
racket/src/rktio/rktio_filesystem.c
Normal file
File diff suppressed because it is too large
Load Diff
779
racket/src/rktio/rktio_poll_set.c
Normal file
779
racket/src/rktio/rktio_poll_set.c
Normal file
|
@ -0,0 +1,779 @@
|
||||||
|
#include "rktio.h"
|
||||||
|
#include "rktio_private.h"
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
# include <sys/select.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Generalize fd arrays (FD_SET, etc) with a runtime-determined size,
|
||||||
|
special hooks for Windows "descriptors" like even queues and
|
||||||
|
semaphores, etc. */
|
||||||
|
|
||||||
|
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||||
|
THREAD_LOCAL_DECL(rktio_poll_set_t *rktio_global_poll_set);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void rktio_alloc_global_poll_set() {
|
||||||
|
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||||
|
rktio_global_poll_set = rktio_alloc_fdset_array(3);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************/
|
||||||
|
/* Poll variant */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_POLL_SYSCALL
|
||||||
|
|
||||||
|
# define PFD_EXTRA_SPACE 1
|
||||||
|
|
||||||
|
struct rktio_poll_set_t {
|
||||||
|
struct rktio_fd_set_data_t *data;
|
||||||
|
rktio_poll_set_t *w;
|
||||||
|
rktio_poll_set_t *e;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rktio_fd_set_data_t {
|
||||||
|
struct pollfd *pfd;
|
||||||
|
intptr_t size, count;
|
||||||
|
};
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_alloc_fdset_array(int count)
|
||||||
|
{
|
||||||
|
struct rktio_fd_set_data_t *data;
|
||||||
|
rktio_poll_set_t *r, *w, *e;
|
||||||
|
struct pollfd *pfd;
|
||||||
|
|
||||||
|
data = malloc(sizeof(struct rktio_fd_set_data_t));
|
||||||
|
r = malloc(sizeof(struct rktio_poll_set_t));
|
||||||
|
w = malloc(sizeof(struct rktio_poll_set_t));
|
||||||
|
e = malloc(sizeof(struct rktio_poll_set_t));
|
||||||
|
|
||||||
|
r->w = w;
|
||||||
|
r->e = e;
|
||||||
|
r->data = data;
|
||||||
|
w->data = data;
|
||||||
|
e->data = data;
|
||||||
|
|
||||||
|
r->flags = POLLIN;
|
||||||
|
w->flags = POLLOUT;
|
||||||
|
e->flags = 0;
|
||||||
|
|
||||||
|
data->size = 32;
|
||||||
|
data->count = 0;
|
||||||
|
|
||||||
|
pfd = malloc(sizeof(struct pollfd) * (32 + PFD_EXTRA_SPACE));
|
||||||
|
data->pfd = pfd;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_init_fdset_array(rktio_poll_set_t *fdarray, int count)
|
||||||
|
{
|
||||||
|
((struct rktio_fd_set *)fdarray)->data->count = 0;
|
||||||
|
return fdarray;
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos)
|
||||||
|
{
|
||||||
|
switch (pos) {
|
||||||
|
case 0:
|
||||||
|
return fdarray;
|
||||||
|
case 1:
|
||||||
|
return fdarray->w;
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
return fdarray->e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdzero(rktio_poll_set_t *fd)
|
||||||
|
{
|
||||||
|
fd->data->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_fd_pos(struct rktio_fd_set_data_t *data, int n)
|
||||||
|
{
|
||||||
|
intptr_t count = data->count;
|
||||||
|
intptr_t i;
|
||||||
|
|
||||||
|
/* This linear search probably isn't good enough for hundreds or
|
||||||
|
thousands of descriptors, but epoll()/kqueue() mode should handle
|
||||||
|
that case, anyway. */
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (data->pfd[i].fd == n) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdclr(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
struct rktio_fd_set_data_t *data = fd->data;
|
||||||
|
intptr_t flag = fd->flags;
|
||||||
|
intptr_t pos;
|
||||||
|
|
||||||
|
if (!flag) return;
|
||||||
|
|
||||||
|
pos = find_fd_pos(data, n);
|
||||||
|
if (pos >= 0) {
|
||||||
|
data->pfd[pos].events -= (data->pfd[pos].events & flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdset(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
struct rktio_fd_set_data_t *data = fd->data;
|
||||||
|
intptr_t flag = fd->flags;
|
||||||
|
intptr_t count, size, pos;
|
||||||
|
struct pollfd *pfd;
|
||||||
|
|
||||||
|
if (!flag) return;
|
||||||
|
|
||||||
|
pos = find_fd_pos(data, n);
|
||||||
|
if (pos >= 0) {
|
||||||
|
data->pfd[pos].events |= flag;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = data->count;
|
||||||
|
size = data->size;
|
||||||
|
if (count >= size) {
|
||||||
|
size = size * 2;
|
||||||
|
pfd = malloc(sizeof(struct pollfd) * (size + PFD_EXTRA_SPACE));
|
||||||
|
memcpy(pfd, data->pfd, sizeof(struct pollfd) * count);
|
||||||
|
free(data->pfd);
|
||||||
|
data->pfd = pfd;
|
||||||
|
data->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->pfd[count].fd = n;
|
||||||
|
data->pfd[count].events = flag;
|
||||||
|
count++;
|
||||||
|
data->count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rktio_fdisset(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
struct rktio_fd_set_data_t *data = data->data;
|
||||||
|
intptr_t flag = fd->flags;
|
||||||
|
intptr_t pos;
|
||||||
|
|
||||||
|
if (!flag) flag = (POLLERR | POLLHUP);
|
||||||
|
|
||||||
|
pos = find_fd_pos(data, n);
|
||||||
|
if (pos >= 0) {
|
||||||
|
if (data->pfd[pos].revents & flag)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_fd(const void *_a, const void *_b)
|
||||||
|
{
|
||||||
|
struct pollfd *a = (struct pollfd *)_a;
|
||||||
|
struct pollfd *b = (struct pollfd *)_b;
|
||||||
|
return a->fd - b->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds)
|
||||||
|
{
|
||||||
|
struct rktio_fd_set_data_t *data = fds->data;
|
||||||
|
struct rktio_fd_set_data_t *src_data = src_fds->data;
|
||||||
|
int i, si, c, sc, j, nc;
|
||||||
|
struct pollfd *pfds;
|
||||||
|
|
||||||
|
rktio_clean_fd_set(fds);
|
||||||
|
rktio_clean_fd_set(src_fds);
|
||||||
|
|
||||||
|
c = data->count;
|
||||||
|
sc = src_data->count;
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
return src_fds;
|
||||||
|
if (!sc)
|
||||||
|
return fds;
|
||||||
|
|
||||||
|
qsort(data->pfd, c, sizeof(struct pollfd), cmp_fd);
|
||||||
|
qsort(src_data->pfd, sc, sizeof(struct pollfd), cmp_fd);
|
||||||
|
|
||||||
|
nc = c + sc;
|
||||||
|
pfds = (struct pollfd *)rktio_malloc_atomic(sizeof(struct pollfd) * (nc + PFD_EXTRA_SPACE));
|
||||||
|
j = 0;
|
||||||
|
for (i = 0, si = 0; (i < c) && (si < sc); ) {
|
||||||
|
if (data->pfd[i].fd == src_data->pfd[si].fd) {
|
||||||
|
pfds[j].fd = data->pfd[i].fd;
|
||||||
|
pfds[j].events = (data->pfd[i].events | src_data->pfd[si].events);
|
||||||
|
i++;
|
||||||
|
si++;
|
||||||
|
} else if (data->pfd[i].fd < src_data->pfd[si].fd) {
|
||||||
|
pfds[j].fd = data->pfd[i].fd;
|
||||||
|
pfds[j].events = data->pfd[i].events;
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
pfds[j].fd = src_data->pfd[si].fd;
|
||||||
|
pfds[j].events = src_data->pfd[si].events;
|
||||||
|
si++;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
for ( ; i < c; i++, j++) {
|
||||||
|
pfds[j].fd = data->pfd[i].fd;
|
||||||
|
pfds[j].events = data->pfd[i].events;
|
||||||
|
}
|
||||||
|
for ( ; si < sc; si++, j++) {
|
||||||
|
pfds[j].fd = src_data->pfd[si].fd;
|
||||||
|
pfds[j].events = src_data->pfd[si].events;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nc > RKTIO_INT_VAL(data->size)) {
|
||||||
|
data->pfd = pfds;
|
||||||
|
data->size = rktio_make_integer(nc);
|
||||||
|
} else
|
||||||
|
memcpy(data->pfd, pfds, j * sizeof(struct pollfd));
|
||||||
|
data->count = rktio_make_integer(j);
|
||||||
|
|
||||||
|
return fds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_clean_fd_set(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
struct rktio_fd_set_data_t *data = fds->data;
|
||||||
|
intptr_t count = data->count;
|
||||||
|
intptr_t i, j = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (data->pfd[i].events) {
|
||||||
|
if (j < i) {
|
||||||
|
data->pfd[j].fd = data->pfd[i].fd;
|
||||||
|
data->pfd[j].events = data->pfd[i].events;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count = j;
|
||||||
|
data->count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rktio_get_fd_limit(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(USE_DYNAMIC_FDSET_SIZE)
|
||||||
|
|
||||||
|
/************************************************************/
|
||||||
|
/* Variant with run-time determined fd_set length */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
struct rktio_poll_set_t {
|
||||||
|
fd_set data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* initialized early via rktio_alloc_global_poll_set */
|
||||||
|
static int dynamic_fd_size;
|
||||||
|
|
||||||
|
# define STORED_ACTUAL_FDSET_LIMIT
|
||||||
|
# define FDSET_LIMIT(fd) (*(int *)((char *)fd + dynamic_fd_size))
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_alloc_fdset_array(int count)
|
||||||
|
{
|
||||||
|
if (!dynamic_fd_size) {
|
||||||
|
# ifdef USE_ULIMIT
|
||||||
|
dynamic_fd_size = ulimit(4, 0);
|
||||||
|
# else
|
||||||
|
dynamic_fd_size = getdtablesize();
|
||||||
|
# endif
|
||||||
|
/* divide by bits-per-byte: */
|
||||||
|
dynamic_fd_size = (dynamic_fd_size + 7) >> 3;
|
||||||
|
/* word-align: */
|
||||||
|
if (dynamic_fd_size % sizeof(void*))
|
||||||
|
dynamic_fd_size += sizeof(void*) - (dynamic_fd_size % sizeof(void*));
|
||||||
|
}
|
||||||
|
|
||||||
|
return malloc(count * (dynamic_fd_size + sizeof(intptr_t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_init_fdset_array(rktio_poll_set_t *fdarray, int count)
|
||||||
|
{
|
||||||
|
return fdarray;
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos)
|
||||||
|
{
|
||||||
|
return (rktio_poll_set_t *)(((char *)fdarray) + (pos * (dynamic_fd_size + sizeof(intptr_t))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdzero(rktio_poll_set_t *fd)
|
||||||
|
{
|
||||||
|
memset(fd, 0, dynamic_fd_size + sizeof(intptr_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined (RKTIO_SYSTEM_WINDOWS)
|
||||||
|
|
||||||
|
/************************************************************/
|
||||||
|
/* Windows variant */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SOCKET *sockets;
|
||||||
|
|
||||||
|
intptr_t added, alloc, last_alloc;
|
||||||
|
|
||||||
|
intptr_t num_handles, alloc_handles, last_alloc_handles;
|
||||||
|
OS_SEMAPHORE_TYPE *handles;
|
||||||
|
|
||||||
|
int *repost_sema;
|
||||||
|
|
||||||
|
int no_sleep; /* boolean */
|
||||||
|
|
||||||
|
intptr_t wait_event_mask;
|
||||||
|
|
||||||
|
HANDLE *wait_array;
|
||||||
|
|
||||||
|
HANDLE *combined_wait_array;
|
||||||
|
intptr_t combined_len;
|
||||||
|
} rktio_poll_set_t;
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_alloc_fdset_array(int count)
|
||||||
|
{
|
||||||
|
rktio_poll_set_t *fdarray;
|
||||||
|
if (count) {
|
||||||
|
fdarray = calloc(count, sizeof(rktio_poll_set_t));
|
||||||
|
rktio_init_fdset_array(fdarray, count);
|
||||||
|
} else
|
||||||
|
fdarray = NULL;
|
||||||
|
|
||||||
|
return fdarray;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_wait_array(rktio_poll_set_t *efd)
|
||||||
|
{
|
||||||
|
/* Allocate an array that may be big enough to hold all events
|
||||||
|
when we eventually call WaitForMultipleObjects. One of the three
|
||||||
|
arrays will be big enough. */
|
||||||
|
int sz = (3 * (efd->alloc + efd->alloc_handles)) + 2;
|
||||||
|
HANDLE *wa;
|
||||||
|
if (efd->wait_array) free(efd->wait_array);
|
||||||
|
wa = calloc(sz, sizeof(HANDLE));
|
||||||
|
efd->wait_array = wa;
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_init_fdset_array(rktio_poll_set_t *fdarray, int count)
|
||||||
|
{
|
||||||
|
if (count) {
|
||||||
|
int i;
|
||||||
|
rktio_poll_set_t *fd;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
int reset = 0;
|
||||||
|
fd = rktio_get_fdset(fdarray, i);
|
||||||
|
fd->added = 0;
|
||||||
|
if (RKTIO_INT_VAL(fd->alloc) > (2 * RKTIO_INT_VAL(fd->last_alloc))) {
|
||||||
|
fd->alloc = 0;
|
||||||
|
if (fd->sockets) free(fd->sockets);
|
||||||
|
fd->sockets = NULL;
|
||||||
|
reset = 1;
|
||||||
|
}
|
||||||
|
fd->last_alloc = 0;
|
||||||
|
fd->num_handles = 0;
|
||||||
|
if (RKTIO_INT_VAL(fd->alloc_handles) > (2 * RKTIO_INT_VAL(fd->last_alloc_handles))) {
|
||||||
|
fd->alloc_handles = 0;
|
||||||
|
if (fd->handles) free(fd->handles);
|
||||||
|
if (fd->repost_sema) free(fd->repost_sema);
|
||||||
|
fd->handles = NULL;
|
||||||
|
fd->repost_sema = NULL;
|
||||||
|
reset = 1;
|
||||||
|
}
|
||||||
|
fd->last_alloc_handles = 0;
|
||||||
|
fd->no_sleep = 0;
|
||||||
|
fd->wait_event_mask = 0;
|
||||||
|
if (reset)
|
||||||
|
reset_wait_array(fdarray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos)
|
||||||
|
{
|
||||||
|
return fdarray + pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdzero(rktio_poll_set_t *fd)
|
||||||
|
{
|
||||||
|
rktio_init_fdset_array(fd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdclr(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = fd->added; i--; ) {
|
||||||
|
if (fd->sockets[i] == n)
|
||||||
|
fd->sockets[i] = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int next_size(int v) { return (v ? (2 * v) : 10); }
|
||||||
|
|
||||||
|
void rktio_fdset(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
if (fd->added >= fd->last_alloc) {
|
||||||
|
int na;
|
||||||
|
na = next_size(fd->last_alloc);
|
||||||
|
efd->last_alloc = na;
|
||||||
|
}
|
||||||
|
if (fd->added >= fd->alloc) {
|
||||||
|
SOCKET *naya;
|
||||||
|
int na;
|
||||||
|
na = next_size(fd->alloc);
|
||||||
|
naya = malloc(na * sizeof(SOCKET));
|
||||||
|
memcpy(naya, fd->sockets, RKTIO_INT_VAL(fd->alloc) * sizeof(SOCKET));
|
||||||
|
if (fd->sockets) free(fd->sockets);
|
||||||
|
fd->sockets = naya;
|
||||||
|
fd->alloc = na;
|
||||||
|
reset_wait_array(fd);
|
||||||
|
}
|
||||||
|
fd->sockets[fd->added++] = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rktio_fdisset(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = fd->added; i--; ) {
|
||||||
|
if (fd->sockets[i] == n)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = src_fd->added; i--; ) {
|
||||||
|
if (stv_fd->sockets[i] != INVALID_SOCKET)
|
||||||
|
rktio_fdset(fds, src_fd->sockets[i]);
|
||||||
|
}
|
||||||
|
return fds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_clean_fd_set(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int rktio_get_fd_limit(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdset_add_handle(HANDLE h, rktio_poll_set_t *fds, int repost)
|
||||||
|
{
|
||||||
|
rktio_poll_set_t *efd = fds;
|
||||||
|
OS_SEMAPHORE_TYPE *hs;
|
||||||
|
int i, new_i, *rps;
|
||||||
|
|
||||||
|
if (efd->num_handles == efd->last_alloc_handles) {
|
||||||
|
i = next_size(efd->last_alloc_handles);
|
||||||
|
efd->last_alloc_handles = 1;
|
||||||
|
}
|
||||||
|
if (efd->num_handles == efd->alloc_handles) {
|
||||||
|
i = efd->alloc_handles;
|
||||||
|
new_i = next_size(i);
|
||||||
|
hs = malloc(sizeof(HANDLE) * new_i);
|
||||||
|
rps = malloc(sizeof(int) * new_i);
|
||||||
|
memcpy(hs, efd->handles, sizeof(HANDLE)*i);
|
||||||
|
memcpy(rps, efd->repost_sema, sizeof(int)*i);
|
||||||
|
if (efd->handles) free(efd->handles);
|
||||||
|
if (efd->repost_sema) free(efd->repost_sema);
|
||||||
|
efd->handles = hs;
|
||||||
|
efd->repost_sema = rps;
|
||||||
|
efd->alloc_handles = new_i;
|
||||||
|
reset_wait_array(efd);
|
||||||
|
}
|
||||||
|
i = efd->num_handles;
|
||||||
|
efd->handles[i] = h;
|
||||||
|
efd->repost_sema[i] = repost;
|
||||||
|
efd->num_handles++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_add_fd_nosleep(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
fds->no_sleep = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdset_add_eventmask(rktio_poll_set_t *fds, int mask)
|
||||||
|
{
|
||||||
|
fds->wait_event_mask |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSAEventSelect_plus_check(SOCKET s, WSAEVENT e, long mask)
|
||||||
|
{
|
||||||
|
fd_set rd[1], wr[1], ex[1];
|
||||||
|
struct timeval t = {0, 0};
|
||||||
|
|
||||||
|
WSAEventSelect(s, e, mask);
|
||||||
|
|
||||||
|
/* double-check with select(), because WSAEventSelect only
|
||||||
|
handles new activity (I think) */
|
||||||
|
FD_ZERO(rd);
|
||||||
|
FD_ZERO(wr);
|
||||||
|
FD_ZERO(ex);
|
||||||
|
|
||||||
|
if (mask & FD_READ)
|
||||||
|
FD_SET(s, rd);
|
||||||
|
if (mask & FD_WRITE)
|
||||||
|
FD_SET(s, wr);
|
||||||
|
if (mask & FD_OOB)
|
||||||
|
FD_SET(s, ex);
|
||||||
|
|
||||||
|
if (select(1, rd, wr, ex, &t)) {
|
||||||
|
/* already ready */
|
||||||
|
WSAEventSelect(s, NULL, 0);
|
||||||
|
SetEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_collapse_win_fd(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
rktio_poll_set_t *rfd, *wfd, *efd;
|
||||||
|
HANDLE *wa, e;
|
||||||
|
int i, p = 0, mask, j;
|
||||||
|
SOCKET s;
|
||||||
|
|
||||||
|
rfd = fds;
|
||||||
|
wfd = rktio_get_fdset(fds, 1);
|
||||||
|
efd = rktio_get_fdset(fds, 2);
|
||||||
|
|
||||||
|
if (rfd->combined_wait_array) {
|
||||||
|
/* clean up */
|
||||||
|
for (i = rfd->added; i--; ) {
|
||||||
|
if (rfd->sockets[i] != INVALID_SOCKET)
|
||||||
|
WSAEventSelect(rfd->sockets[i], NULL, 0);
|
||||||
|
}
|
||||||
|
for (i = wfd->added; i--; ) {
|
||||||
|
if (wfd->sockets[i] != INVALID_SOCKET)
|
||||||
|
WSAEventSelect(wfd->sockets[i], NULL, 0);
|
||||||
|
}
|
||||||
|
for (i = efd->added; i--; ) {
|
||||||
|
if (efd->sockets[i] != INVALID_SOCKET)
|
||||||
|
WSAEventSelect(efd->sockets[i], NULL, 0);
|
||||||
|
}
|
||||||
|
p = rfd->num_handles;
|
||||||
|
for (i = rfd->combined_len; i-- > p; ) {
|
||||||
|
WSACloseEvent(rfd->combined_wait_array[i]);
|
||||||
|
}
|
||||||
|
rfd->combined_wait_array = NULL;
|
||||||
|
} else {
|
||||||
|
/* merge */
|
||||||
|
if (rfd->alloc < RKTIO_INT_VAL(wfd->alloc)) {
|
||||||
|
if (wfd->alloc < efd->alloc)
|
||||||
|
wa = efd->wait_array;
|
||||||
|
else
|
||||||
|
wa = wfd->wait_array;
|
||||||
|
} else {
|
||||||
|
if (rfd->alloc < efd->alloc)
|
||||||
|
wa = efd->wait_array;
|
||||||
|
else
|
||||||
|
wa = rfd->wait_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
rfd->combined_wait_array = wa;
|
||||||
|
|
||||||
|
p = rfd->num_handles;
|
||||||
|
for (i = 0; i < p; i++) {
|
||||||
|
wa[i] = rfd->handles[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = rfd->added; i--; ) {
|
||||||
|
s = rfd->sockets[i];
|
||||||
|
if (s != INVALID_SOCKET) {
|
||||||
|
mask = FD_READ | FD_ACCEPT | FD_CLOSE;
|
||||||
|
|
||||||
|
for (j = wfd->added; j--; ) {
|
||||||
|
if (wfd->sockets[j] == s) {
|
||||||
|
mask |= FD_WRITE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = efd->added; j--; ) {
|
||||||
|
if (efd->sockets[j] == s) {
|
||||||
|
mask |= FD_OOB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e = WSACreateEvent();
|
||||||
|
wa[p++] = e;
|
||||||
|
WSAEventSelect_plus_check(s, e, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = wfd->added; i--; ) {
|
||||||
|
s = wfd->sockets[i];
|
||||||
|
if (s != INVALID_SOCKET) {
|
||||||
|
mask = FD_WRITE | FD_CONNECT | FD_CLOSE;
|
||||||
|
|
||||||
|
for (j = rfd->added; j--; ) {
|
||||||
|
if (rfd->sockets[j] == s) {
|
||||||
|
mask = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask) {
|
||||||
|
for (j = efd->added; j--; ) {
|
||||||
|
if (efd->sockets[j] == s) {
|
||||||
|
mask |= FD_OOB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e = WSACreateEvent();
|
||||||
|
wa[p++] = e;
|
||||||
|
WSAEventSelect_plus_check(s, e, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = efd->added; i--; ) {
|
||||||
|
s = efd->sockets[i];
|
||||||
|
if (s != INVALID_SOCKET) {
|
||||||
|
mask = FD_OOB | FD_CLOSE;
|
||||||
|
|
||||||
|
for (j = rfd->added; j--; ) {
|
||||||
|
if (rfd->sockets[j] == s) {
|
||||||
|
mask = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask) {
|
||||||
|
for (j = wfd->added; j--; ) {
|
||||||
|
if (wfd->sockets[j] == s) {
|
||||||
|
mask = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask) {
|
||||||
|
e = WSACreateEvent();
|
||||||
|
wa[p++] = e;
|
||||||
|
WSAEventSelect_plus_check(s, e, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rfd->combined_len = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/************************************************************/
|
||||||
|
/* Plain fd_set variant */
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_alloc_fdset_array(int count)
|
||||||
|
{
|
||||||
|
return malloc(count * sizeof(fd_set));
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_init_fdset_array(rktio_poll_set_t *fdarray, int count)
|
||||||
|
{
|
||||||
|
return fdarray;
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos)
|
||||||
|
{
|
||||||
|
return fdarray + pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdzero(rktio_poll_set_t *fd)
|
||||||
|
{
|
||||||
|
FD_ZERO(&(fd)->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdclr(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
FD_CLR(n, &(fd)->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_fdset(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
# ifdef STORED_ACTUAL_FDSET_LIMIT
|
||||||
|
int mx;
|
||||||
|
mx = FDSET_LIMIT(fd);
|
||||||
|
if (n > mx)
|
||||||
|
FDSET_LIMIT(fd) = n;
|
||||||
|
# endif
|
||||||
|
FD_SET(n, &(fd)->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rktio_fdisset(rktio_poll_set_t *fd, int n)
|
||||||
|
{
|
||||||
|
return FD_ISSET(n, &(fd)->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
unsigned char *p, *sp;
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
p = (unsigned char *)rktio_get_fdset(fds, j);
|
||||||
|
sp = (unsigned char *)rktio_get_fdset(src_fds, j);
|
||||||
|
# ifdef STORED_ACTUAL_FDSET_LIMIT
|
||||||
|
if (FDSET_LIMIT(sp) > FDSET_LIMIT(p)) {
|
||||||
|
i = FDSET_LIMIT(sp);
|
||||||
|
FDSET_LIMIT(p) = i;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# if defined(USE_DYNAMIC_FDSET_SIZE)
|
||||||
|
i = dynamic_fd_size;
|
||||||
|
# else
|
||||||
|
i = sizeof(fd_set);
|
||||||
|
# endif
|
||||||
|
for (; i--; p++, sp++) {
|
||||||
|
*p |= *sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rktio_clean_fd_set(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int rktio_get_fd_limit(rktio_poll_set_t *fds)
|
||||||
|
{
|
||||||
|
int actual_limit;
|
||||||
|
|
||||||
|
# ifdef STORED_ACTUAL_FDSET_LIMIT
|
||||||
|
actual_limit = FDSET_LIMIT(rd);
|
||||||
|
if (FDSET_LIMIT(wr) > actual_limit)
|
||||||
|
actual_limit = FDSET_LIMIT(wr);
|
||||||
|
if (FDSET_LIMIT(ex) > actual_limit)
|
||||||
|
actual_limit = FDSET_LIMIT(ex);
|
||||||
|
actual_limit++;
|
||||||
|
# elif defined (USE_ULIMIT)
|
||||||
|
actual_limit = ulimit(4, 0);
|
||||||
|
#elif defined(FIXED_FD_LIMIT)
|
||||||
|
actual_limit = FIXED_FD_LIMIT;
|
||||||
|
#else
|
||||||
|
actual_limit = getdtablesize();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return actual_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
86
racket/src/rktio/rktio_private.h
Normal file
86
racket/src/rktio/rktio_private.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#if ((defined(_MSC_VER) || defined(__MINGW32__)) \
|
||||||
|
&& (defined(__WIN32__) || defined(WIN32) || defined(_WIN32)))
|
||||||
|
# define RKTIO_SYSTEM_WINDOWS
|
||||||
|
# define MSC_IZE(n) _ ## n
|
||||||
|
# define MSC_W_IZE(n) _w ## n
|
||||||
|
# define MSC_WIDE_PATH_temp(n) WIDE_PATH_temp(n)
|
||||||
|
#else
|
||||||
|
# define RKTIO_SYSTEM_UNIX
|
||||||
|
# define MSC_IZE(n) n
|
||||||
|
# define MSC_W_IZE(n) MSC_IZE(n)
|
||||||
|
# define MSC_WIDE_PATH_temp(n) n
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define THREAD_LOCAL_DECL(decl) decl
|
||||||
|
|
||||||
|
void rktio_get_posix_error(void);
|
||||||
|
#define get_posix_error() rktio_get_posix_error()
|
||||||
|
|
||||||
|
void rktio_set_racket_error(int errid);
|
||||||
|
#define set_racket_error(e) rktio_set_racket_error(e)
|
||||||
|
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
void rktio_get_windows_error(void);
|
||||||
|
# define get_windows_error() rktio_get_windows_error()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
intptr_t rktio_fd_value(rktio_fd_t *fd);
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
typedef struct rktio_poll_set_t rktio_poll_set_t;
|
||||||
|
|
||||||
|
#if RKTIO_SYSTEM_WINDOWS
|
||||||
|
# define USE_FAR_RKTIO_FDCALLS
|
||||||
|
#endif
|
||||||
|
#ifdef USE_DYNAMIC_FDSET_SIZE
|
||||||
|
# define USE_FAR_RKTIO_FDCALLS
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_POLL_SYSCALL
|
||||||
|
# define USE_FAR_RKTIO_FDCALLS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_FAR_RKTIO_FDCALLS
|
||||||
|
/* A single fdset that can be reused for immediate actions: */
|
||||||
|
THREAD_LOCAL_DECL(extern rktio_poll_set_t *rktio_global_fd_set);
|
||||||
|
|
||||||
|
# define DECL_FDSET(n, c) fd_set *n
|
||||||
|
# define INIT_DECL_FDSET(r, w, e) { \
|
||||||
|
r = RKTIO_GET_FDSET(rktio_global_poll_set, 0 ); \
|
||||||
|
w = RKTIO_GET_FDSET(rktio_global_poll_set, 1 ); \
|
||||||
|
e = RKTIO_GET_FDSET(rktio_global_poll_set, 2 ); \
|
||||||
|
}
|
||||||
|
# define INIT_DECL_RD_FDSET(r) r = RKTIO_GET_FDSET(rktio_global_poll_set, 0 )
|
||||||
|
# define INIT_DECL_WR_FDSET(r) r = RKTIO_GET_FDSET(rktio_global_poll_set, 1 )
|
||||||
|
# define INIT_DECL_ER_FDSET(r) r = RKTIO_GET_FDSET(rktio_global_poll_set, 2 )
|
||||||
|
|
||||||
|
# define RKTIO_GET_FDSET(p, n) rktio_get_fdset(p, n)
|
||||||
|
# define RKTIO_FD_ZERO(p) rktio_fdzero(p)
|
||||||
|
# define RKTIO_FD_SET(n, p) rktio_fdset(p, n)
|
||||||
|
# define RKTIO_FD_CLR(n, p) rktio_fdclr(p, n)
|
||||||
|
# define RKTIO_FD_ISSET(n, p) rktio_fdisset(p, n)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <sys/select.h>
|
||||||
|
struct rktio_poll_set_t { fd_set data; };
|
||||||
|
|
||||||
|
# define DECL_FDSET(n, c) rktio_poll_set_t n[c]
|
||||||
|
# define INIT_DECL_FDSET(r, w, e) /* empty */
|
||||||
|
# define INIT_DECL_RD_FDSET(r) /* empty */
|
||||||
|
# define INIT_DECL_WR_FDSET(r) /* empty */
|
||||||
|
# define INIT_DECL_ER_FDSET(r) /* empty */
|
||||||
|
|
||||||
|
# define RKTIO_FDS(p) (&(p)->data)
|
||||||
|
|
||||||
|
# define RKTIO_GET_FDSET(p, n) ((p)+(n))
|
||||||
|
# define RKTIO_FD_ZERO(p) FD_ZERO(RKTIO_FDS(p))
|
||||||
|
# define RKTIO_FD_SET(n, p) FD_SET(n, RKTIO_FDS(p))
|
||||||
|
# define RKTIO_FD_CLR(n, p) FD_CLR(n, RKTIO_FDS(p))
|
||||||
|
# define RKTIO_FD_ISSET(n, p) FD_ISSET(n, RKTIO_FDS(p))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rktio_poll_set_t *rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds);
|
||||||
|
void rktio_clean_fd_set(rktio_poll_set_t *fds);
|
||||||
|
int rktio_get_fd_limit(rktio_poll_set_t *fds);
|
1168
racket/src/rktio/rktio_read_write.c
Normal file
1168
racket/src/rktio/rktio_read_write.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user