unix: Include libeio
This commit is contained in:
parent
39da51b20f
commit
bde908f565
3
LICENSE
3
LICENSE
@ -35,3 +35,6 @@ The externally maintained libraries used by libuv are:
|
||||
|
||||
- libev, located at ev/ is copyright Marc Alexander Lehmann, and
|
||||
dual-licensed under the MIT license and GPL2.
|
||||
|
||||
- libeio, located at eio/ is copyright Marc Alexander Lehmann, and
|
||||
dual-licensed under the MIT license and GPL2.
|
||||
|
||||
@ -26,6 +26,7 @@ LINKFLAGS=-lm
|
||||
|
||||
ifeq (SunOS,$(uname_S))
|
||||
EV_CONFIG=config_sunos.h
|
||||
EIO_CONFIG=config_sunos.h
|
||||
CPPFLAGS += -Ic-ares/config_sunos
|
||||
LINKFLAGS+=-lsocket -lnsl
|
||||
UV_OS_FILE=uv-sunos.c
|
||||
@ -33,6 +34,7 @@ endif
|
||||
|
||||
ifeq (Darwin,$(uname_S))
|
||||
EV_CONFIG=config_darwin.h
|
||||
EIO_CONFIG=config_darwin.h
|
||||
CPPFLAGS += -Ic-ares/config_darwin
|
||||
LINKFLAGS+=-framework CoreServices
|
||||
UV_OS_FILE=uv-darwin.c
|
||||
@ -40,6 +42,7 @@ endif
|
||||
|
||||
ifeq (Linux,$(uname_S))
|
||||
EV_CONFIG=config_linux.h
|
||||
EIO_CONFIG=config_linux.h
|
||||
CPPFLAGS += -Ic-ares/config_linux
|
||||
LINKFLAGS+=-lrt
|
||||
UV_OS_FILE=uv-linux.c
|
||||
@ -47,6 +50,7 @@ endif
|
||||
|
||||
ifeq (FreeBSD,$(uname_S))
|
||||
EV_CONFIG=config_freebsd.h
|
||||
EIO_CONFIG=config_freebsd.h
|
||||
CPPFLAGS += -Ic-ares/config_freebsd
|
||||
LINKFLAGS+=
|
||||
UV_OS_FILE=uv-freebsd.c
|
||||
@ -59,8 +63,9 @@ RUNNER_LINKFLAGS=$(LINKFLAGS) -pthread
|
||||
RUNNER_LIBS=
|
||||
RUNNER_SRC=test/runner-unix.c
|
||||
|
||||
uv.a: uv-unix.o uv-common.o uv-platform.o ev/ev.o $(CARES_OBJS)
|
||||
$(AR) rcs uv.a uv-unix.o uv-platform.o uv-common.o ev/ev.o $(CARES_OBJS)
|
||||
uv.a: uv-unix.o uv-common.o uv-platform.o ev/ev.o uv-eio.o eio/eio.o $(CARES_OBJS)
|
||||
$(AR) rcs uv.a uv-unix.o uv-platform.o uv-common.o uv-eio.o ev/ev.o \
|
||||
eio/eio.o $(CARES_OBJS)
|
||||
|
||||
uv-platform.o: $(UV_OS_FILE) uv.h uv-unix.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c $(UV_OS_FILE) -o uv-platform.o
|
||||
@ -74,12 +79,28 @@ uv-common.o: uv-common.c uv.h uv-unix.h
|
||||
ev/ev.o: ev/ev.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c ev/ev.c -o ev/ev.o -DEV_CONFIG_H=\"$(EV_CONFIG)\"
|
||||
|
||||
|
||||
EIO_CPPFLAGS += $(CPPFLAGS)
|
||||
EIO_CPPFLAGS += -DEIO_CONFIG_H=\"$(EIO_CONFIG)\"
|
||||
EIO_CPPFLAGS += -DEIO_STACKSIZE=65536
|
||||
EIO_CPPFLAGS += -D_LARGEFILE_SOURCE
|
||||
EIO_CPPFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
|
||||
eio/eio.o: eio/eio.c
|
||||
$(CC) $(EIO_CPPFLAGS) $(CFLAGS) -c eio/eio.c -o eio/eio.o
|
||||
|
||||
uv-eio.o: uv-eio.c
|
||||
$(CC) $(CPPFLAGS) -Ieio/ $(CFLAGS) -c uv-eio.c -o uv-eio.o
|
||||
|
||||
|
||||
clean-platform:
|
||||
-rm -f c-ares/*.o
|
||||
-rm -f ev/*.o
|
||||
-rm -f eio/*.o
|
||||
-rm -rf test/run-tests.dSYM run-benchmarks.dSYM
|
||||
|
||||
distclean-platform:
|
||||
-rm -f c-ares/*.o
|
||||
-rm -f ev/*.o
|
||||
-rm -f eio/*.o
|
||||
-rm -rf test/run-tests.dSYM run-benchmarks.dSYM
|
||||
|
||||
35
eio/Changes
Normal file
35
eio/Changes
Normal file
@ -0,0 +1,35 @@
|
||||
Revision history for libeio
|
||||
|
||||
TODO: maybe add mincore support? available on at least darwin, solaris, linux, freebsd
|
||||
TODO: openbsd requites stdint.h for intptr_t - why posix?
|
||||
|
||||
1.0
|
||||
- readdir: correctly handle malloc failures.
|
||||
- readdir: new flags argument, can return inode
|
||||
and possibly filetype, can sort in various ways.
|
||||
- readdir: stop immediately when cancelled, do
|
||||
not continue reading the directory.
|
||||
- fix return value of eio_sendfile_sync.
|
||||
- include sys/mman.h for msync.
|
||||
- added EIO_STACKSIZE.
|
||||
- added msync, mtouch support (untested).
|
||||
- added sync_file_range (untested).
|
||||
- fixed custom support.
|
||||
- use a more robust feed-add detection method.
|
||||
- "outbundled" from IO::AIO.
|
||||
- eio_set_max_polltime did not properly convert time to ticks.
|
||||
- tentatively support darwin in sendfile.
|
||||
- fix freebsd/darwin sendfile.
|
||||
- also use sendfile emulation for ENOTSUP and EOPNOTSUPP
|
||||
error codes.
|
||||
- add OS-independent EIO_MT_* and EIO_MS_* flag enums.
|
||||
- add eio_statvfs/eio_fstatvfs.
|
||||
- add eio_mlock/eio_mlockall and OS-independent MCL_* flag enums.
|
||||
- no longer set errno to 0 before making syscalls, this only lures
|
||||
people into the trap of believing errno shows success or failure.
|
||||
- "fix" demo.c so that it works as non-root.
|
||||
- suppoert utimes seperately from futimes, as some systems have
|
||||
utimes but not futimes.
|
||||
- use _POSIX_MEMLOCK_RANGE for mlock.
|
||||
- do not (errornously) overwrite CFLAGS in configure.ac.
|
||||
|
||||
36
eio/LICENSE
Normal file
36
eio/LICENSE
Normal file
@ -0,0 +1,36 @@
|
||||
All files in libeio are Copyright (C)2007,2008 Marc Alexander Lehmann.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Alternatively, the contents of this package may be used under the terms
|
||||
of the GNU General Public License ("GPL") version 2 or any later version,
|
||||
in which case the provisions of the GPL are applicable instead of the
|
||||
above. If you wish to allow the use of your version of this package only
|
||||
under the terms of the GPL and not to allow others to use your version of
|
||||
this file under the BSD license, indicate your decision by deleting the
|
||||
provisions above and replace them with the notice and other provisions
|
||||
required by the GPL in this and the other files of this package. If you do
|
||||
not delete the provisions above, a recipient may use your version of this
|
||||
file under either the BSD or the GPL.
|
||||
15
eio/Makefile.am
Normal file
15
eio/Makefile.am
Normal file
@ -0,0 +1,15 @@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
|
||||
VERSION_INFO = 1:0
|
||||
|
||||
EXTRA_DIST = LICENSE Changes autogen.sh
|
||||
|
||||
#man_MANS = ev.3
|
||||
|
||||
include_HEADERS = eio.h
|
||||
|
||||
lib_LTLIBRARIES = libeio.la
|
||||
|
||||
libeio_la_SOURCES = eio.c xthread.h config.h
|
||||
libeio_la_LDFLAGS = -version-info $(VERSION_INFO)
|
||||
|
||||
8957
eio/aclocal.m4
vendored
Normal file
8957
eio/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
eio/autogen.sh
Executable file
5
eio/autogen.sh
Executable file
@ -0,0 +1,5 @@
|
||||
libtoolize
|
||||
aclocal
|
||||
automake --add-missing
|
||||
autoconf
|
||||
autoheader
|
||||
86
eio/config.h.in
Normal file
86
eio/config.h.in
Normal file
@ -0,0 +1,86 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* fdatasync(2) is available */
|
||||
#undef HAVE_FDATASYNC
|
||||
|
||||
/* futimes(2) is available */
|
||||
#undef HAVE_FUTIMES
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* posix_fadvise(2) is available */
|
||||
#undef HAVE_POSIX_FADVISE
|
||||
|
||||
/* posix_madvise(2) is available */
|
||||
#undef HAVE_POSIX_MADVISE
|
||||
|
||||
/* pread(2) and pwrite(2) are available */
|
||||
#undef HAVE_PREADWRITE
|
||||
|
||||
/* readahead(2) is available (linux) */
|
||||
#undef HAVE_READAHEAD
|
||||
|
||||
/* sendfile(2) is available and supported */
|
||||
#undef HAVE_SENDFILE
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* sync_file_range(2) is available */
|
||||
#undef HAVE_SYNC_FILE_RANGE
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* utimes(2) is available */
|
||||
#undef HAVE_UTIMES
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
77
eio/config_cygwin.h
Normal file
77
eio/config_cygwin.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* fdatasync(2) is available */
|
||||
#define HAVE_FDATASYNC 1
|
||||
|
||||
/* futimes(2) is available */
|
||||
#define HAVE_FUTIMES 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* pread(2) and pwrite(2) are available */
|
||||
#define HAVE_PREADWRITE 1
|
||||
|
||||
/* readahead(2) is available (linux) */
|
||||
/* #undef HAVE_READAHEAD */
|
||||
|
||||
/* sendfile(2) is available and supported */
|
||||
/* #undef HAVE_SENDFILE */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* sync_file_range(2) is available */
|
||||
/* #undef HAVE_SYNC_FILE_RANGE */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libeio"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0"
|
||||
82
eio/config_darwin.h
Normal file
82
eio/config_darwin.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* fdatasync(2) is not available on 10.5 but is on 10.6
|
||||
* How should we deal with this? */
|
||||
/* #define HAVE_FDATASYNC 0 */
|
||||
|
||||
/* futimes(2) is available */
|
||||
#define HAVE_FUTIMES 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* pread(2) and pwrite(2) are available */
|
||||
#define HAVE_PREADWRITE 1
|
||||
|
||||
/* readahead(2) is available (linux) */
|
||||
/* #undef HAVE_READAHEAD */
|
||||
|
||||
/* sendfile(2) is available and supported */
|
||||
#define HAVE_SENDFILE 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* sync_file_range(2) is available */
|
||||
/* #undef HAVE_SYNC_FILE_RANGE */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libeio"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0"
|
||||
78
eio/config_freebsd.h
Normal file
78
eio/config_freebsd.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* fdatasync(2) is available */
|
||||
/* #undef HAVE_FDATASYNC */
|
||||
|
||||
/* futimes(2) is available */
|
||||
#define HAVE_FUTIMES 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* pread(2) and pwrite(2) are available */
|
||||
#define HAVE_PREADWRITE 1
|
||||
|
||||
/* readahead(2) is available (linux) */
|
||||
/* #undef HAVE_READAHEAD */
|
||||
|
||||
/* sendfile(2) is available and supported */
|
||||
#define HAVE_SENDFILE 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* sync_file_range(2) is available */
|
||||
/* #undef HAVE_SYNC_FILE_RANGE */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libeio"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0"
|
||||
81
eio/config_linux.h
Normal file
81
eio/config_linux.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* fdatasync(2) is available */
|
||||
#define HAVE_FDATASYNC 1
|
||||
|
||||
/* futimes(2) is available */
|
||||
#define HAVE_FUTIMES 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* pread(2) and pwrite(2) are available */
|
||||
#define HAVE_PREADWRITE 1
|
||||
|
||||
/* readahead(2) is available (linux) */
|
||||
#define HAVE_READAHEAD 1
|
||||
|
||||
/* sendfile(2) is available and supported */
|
||||
#define HAVE_SENDFILE 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* sync_file_range(2) is available */
|
||||
#define HAVE_SYNC_FILE_RANGE 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libeio"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0"
|
||||
81
eio/config_sunos.h
Normal file
81
eio/config_sunos.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* fdatasync(2) is available */
|
||||
#define HAVE_FDATASYNC 1
|
||||
|
||||
/* futimes(2) is available */
|
||||
/* #undef HAVE_FUTIMES */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* pread(2) and pwrite(2) are available */
|
||||
#define HAVE_PREADWRITE 1
|
||||
|
||||
/* readahead(2) is available (linux) */
|
||||
/* #undef HAVE_READAHEAD */
|
||||
|
||||
/* sendfile(2) is available and supported */
|
||||
/* #undef HAVE_SENDFILE */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* sync_file_range(2) is available */
|
||||
/* #undef HAVE_SYNC_FILE_RANGE */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libeio"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0"
|
||||
22
eio/configure.ac
Normal file
22
eio/configure.ac
Normal file
@ -0,0 +1,22 @@
|
||||
AC_PREREQ(2.59)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([eio.h])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AM_INIT_AUTOMAKE(libeio,1.0)
|
||||
AM_MAINTAINER_MODE
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_PROG_CC
|
||||
|
||||
if test "x$GCC" = xyes ; then
|
||||
CFLAGS="$CFLAGS -O3"
|
||||
fi
|
||||
|
||||
dnl somebody will forgive me
|
||||
CFLAGS="-D_GNU_SOURCE $CFLAGS"
|
||||
|
||||
m4_include([libeio.m4])
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
194
eio/demo.c
Normal file
194
eio/demo.c
Normal file
@ -0,0 +1,194 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "eio.h"
|
||||
|
||||
int respipe [2];
|
||||
|
||||
void
|
||||
want_poll (void)
|
||||
{
|
||||
char dummy;
|
||||
printf ("want_poll ()\n");
|
||||
write (respipe [1], &dummy, 1);
|
||||
}
|
||||
|
||||
void
|
||||
done_poll (void)
|
||||
{
|
||||
char dummy;
|
||||
printf ("done_poll ()\n");
|
||||
read (respipe [0], &dummy, 1);
|
||||
}
|
||||
|
||||
void
|
||||
event_loop (void)
|
||||
{
|
||||
// an event loop. yeah.
|
||||
struct pollfd pfd;
|
||||
pfd.fd = respipe [0];
|
||||
pfd.events = POLLIN;
|
||||
|
||||
printf ("\nentering event loop\n");
|
||||
while (eio_nreqs ())
|
||||
{
|
||||
poll (&pfd, 1, -1);
|
||||
printf ("eio_poll () = %d\n", eio_poll ());
|
||||
}
|
||||
printf ("leaving event loop\n");
|
||||
}
|
||||
|
||||
int
|
||||
res_cb (eio_req *req)
|
||||
{
|
||||
printf ("res_cb(%d|%s) = %d\n", req->type, req->data ? req->data : "?", EIO_RESULT (req));
|
||||
|
||||
if (req->result < 0)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
readdir_cb (eio_req *req)
|
||||
{
|
||||
char *buf = (char *)EIO_BUF (req);
|
||||
|
||||
printf ("readdir_cb = %d\n", EIO_RESULT (req));
|
||||
|
||||
if (EIO_RESULT (req) < 0)
|
||||
return 0;
|
||||
|
||||
while (EIO_RESULT (req)--)
|
||||
{
|
||||
printf ("readdir = <%s>\n", buf);
|
||||
buf += strlen (buf) + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
stat_cb (eio_req *req)
|
||||
{
|
||||
struct stat *buf = EIO_STAT_BUF (req);
|
||||
|
||||
if (req->type == EIO_FSTAT)
|
||||
printf ("fstat_cb = %d\n", EIO_RESULT (req));
|
||||
else
|
||||
printf ("stat_cb(%s) = %d\n", EIO_PATH (req), EIO_RESULT (req));
|
||||
|
||||
if (!EIO_RESULT (req))
|
||||
printf ("stat size %d perm 0%o\n", buf->st_size, buf->st_mode & 0777);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
read_cb (eio_req *req)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)EIO_BUF (req);
|
||||
|
||||
printf ("read_cb = %d (%02x%02x%02x%02x %02x%02x%02x%02x)\n",
|
||||
EIO_RESULT (req),
|
||||
buf [0], buf [1], buf [2], buf [3],
|
||||
buf [4], buf [5], buf [6], buf [7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int last_fd;
|
||||
|
||||
int
|
||||
open_cb (eio_req *req)
|
||||
{
|
||||
printf ("open_cb = %d\n", EIO_RESULT (req));
|
||||
|
||||
last_fd = EIO_RESULT (req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
printf ("pipe ()\n");
|
||||
if (pipe (respipe)) abort ();
|
||||
|
||||
printf ("eio_init ()\n");
|
||||
if (eio_init (want_poll, done_poll)) abort ();
|
||||
|
||||
do
|
||||
{
|
||||
/* avoid relative paths yourself(!) */
|
||||
eio_mkdir ("eio-test-dir", 0777, 0, res_cb, "mkdir");
|
||||
eio_nop (0, res_cb, "nop");
|
||||
event_loop ();
|
||||
|
||||
eio_stat ("eio-test-dir", 0, stat_cb, "stat");
|
||||
eio_lstat ("eio-test-dir", 0, stat_cb, "stat");
|
||||
eio_open ("eio-test-dir/eio-test-file", O_RDWR | O_CREAT, 0777, 0, open_cb, "open");
|
||||
eio_symlink ("test", "eio-test-dir/eio-symlink", 0, res_cb, "symlink");
|
||||
eio_mknod ("eio-test-dir/eio-fifo", S_IFIFO, 0, 0, res_cb, "mknod");
|
||||
event_loop ();
|
||||
|
||||
eio_utime ("eio-test-dir", 12345.678, 23456.789, 0, res_cb, "utime");
|
||||
eio_futime (last_fd, 92345.678, 93456.789, 0, res_cb, "futime");
|
||||
eio_chown ("eio-test-dir", getuid (), getgid (), 0, res_cb, "chown");
|
||||
eio_fchown (last_fd, getuid (), getgid (), 0, res_cb, "fchown");
|
||||
eio_fchmod (last_fd, 0723, 0, res_cb, "fchmod");
|
||||
eio_readdir ("eio-test-dir", 0, 0, readdir_cb, "readdir");
|
||||
eio_readdir ("/nonexistant", 0, 0, readdir_cb, "readdir");
|
||||
eio_fstat (last_fd, 0, stat_cb, "stat");
|
||||
eio_write (last_fd, "test\nfail\n", 10, 4, 0, res_cb, "write");
|
||||
event_loop ();
|
||||
|
||||
eio_read (last_fd, 0, 8, 0, EIO_PRI_DEFAULT, read_cb, "read");
|
||||
eio_readlink ("eio-test-dir/eio-symlink", 0, res_cb, "readlink");
|
||||
event_loop ();
|
||||
|
||||
eio_dup2 (1, 2, EIO_PRI_DEFAULT, res_cb, "dup"); // dup stdout to stderr
|
||||
eio_chmod ("eio-test-dir", 0765, 0, res_cb, "chmod");
|
||||
eio_ftruncate (last_fd, 9, 0, res_cb, "ftruncate");
|
||||
eio_fdatasync (last_fd, 0, res_cb, "fdatasync");
|
||||
eio_fsync (last_fd, 0, res_cb, "fsync");
|
||||
eio_sync (0, res_cb, "sync");
|
||||
eio_busy (0.5, 0, res_cb, "busy");
|
||||
event_loop ();
|
||||
|
||||
eio_sendfile (1, last_fd, 4, 5, 0, res_cb, "sendfile"); // write "test\n" to stdout
|
||||
eio_fstat (last_fd, 0, stat_cb, "stat");
|
||||
event_loop ();
|
||||
|
||||
eio_truncate ("eio-test-dir/eio-test-file", 6, 0, res_cb, "truncate");
|
||||
eio_readahead (last_fd, 0, 64, 0, res_cb, "readahead");
|
||||
event_loop ();
|
||||
|
||||
eio_close (last_fd, 0, res_cb, "close");
|
||||
eio_link ("eio-test-dir/eio-test-file", "eio-test-dir/eio-test-file-2", 0, res_cb, "link");
|
||||
event_loop ();
|
||||
|
||||
eio_rename ("eio-test-dir/eio-test-file", "eio-test-dir/eio-test-file-renamed", 0, res_cb, "rename");
|
||||
event_loop ();
|
||||
|
||||
eio_unlink ("eio-test-dir/eio-fifo", 0, res_cb, "unlink");
|
||||
eio_unlink ("eio-test-dir/eio-symlink", 0, res_cb, "unlink");
|
||||
eio_unlink ("eio-test-dir/eio-test-file-2", 0, res_cb, "unlink");
|
||||
eio_unlink ("eio-test-dir/eio-test-file-renamed", 0, res_cb, "unlink");
|
||||
event_loop ();
|
||||
|
||||
eio_rmdir ("eio-test-dir", 0, res_cb, "rmdir");
|
||||
event_loop ();
|
||||
}
|
||||
while (0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
356
eio/eio.h
Normal file
356
eio/eio.h
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
* libeio API header
|
||||
*
|
||||
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libeio@schmorp.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modifica-
|
||||
* tion, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
||||
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
||||
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
||||
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* the GNU General Public License ("GPL") version 2 or any later version,
|
||||
* in which case the provisions of the GPL are applicable instead of
|
||||
* the above. If you wish to allow the use of your version of this file
|
||||
* only under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the BSD license, indicate your decision
|
||||
* by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete the
|
||||
* provisions above, a recipient may use your version of this file under
|
||||
* either the BSD or the GPL.
|
||||
*/
|
||||
|
||||
#ifndef EIO_H_
|
||||
#define EIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define uid_t int
|
||||
# define gid_t int
|
||||
#endif
|
||||
|
||||
typedef struct eio_req eio_req;
|
||||
typedef struct eio_dirent eio_dirent;
|
||||
|
||||
typedef int (*eio_cb)(eio_req *req);
|
||||
|
||||
#ifndef EIO_REQ_MEMBERS
|
||||
# define EIO_REQ_MEMBERS
|
||||
#endif
|
||||
|
||||
#ifndef EIO_STRUCT_STAT
|
||||
# ifdef _WIN32
|
||||
# define EIO_STRUCT_STAT struct _stati64
|
||||
# else
|
||||
# define EIO_STRUCT_STAT struct stat
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef EIO_STRUCT_STATVFS
|
||||
# define EIO_STRUCT_STATVFS struct statvfs
|
||||
#endif
|
||||
|
||||
/* for readdir */
|
||||
|
||||
/* eio_readdir flags */
|
||||
enum
|
||||
{
|
||||
EIO_READDIR_DENTS = 0x01, /* ptr2 contains eio_dirents, not just the (unsorted) names */
|
||||
EIO_READDIR_DIRS_FIRST = 0x02, /* dirents gets sorted into a good stat() ing order to find directories first */
|
||||
EIO_READDIR_STAT_ORDER = 0x04, /* dirents gets sorted into a good stat() ing order to quickly stat all files */
|
||||
EIO_READDIR_FOUND_UNKNOWN = 0x80, /* set by eio_readdir when *_ARRAY was set and any TYPE=UNKNOWN's were found */
|
||||
|
||||
EIO_READDIR_CUSTOM1 = 0x100, /* for use by apps */
|
||||
EIO_READDIR_CUSTOM2 = 0x200 /* for use by apps */
|
||||
};
|
||||
|
||||
/* using "typical" values in the hope that the compiler will do something sensible */
|
||||
enum eio_dtype
|
||||
{
|
||||
EIO_DT_UNKNOWN = 0,
|
||||
EIO_DT_FIFO = 1,
|
||||
EIO_DT_CHR = 2,
|
||||
EIO_DT_MPC = 3, /* multiplexed char device (v7+coherent) */
|
||||
EIO_DT_DIR = 4,
|
||||
EIO_DT_NAM = 5, /* xenix special named file */
|
||||
EIO_DT_BLK = 6,
|
||||
EIO_DT_MPB = 7, /* multiplexed block device (v7+coherent) */
|
||||
EIO_DT_REG = 8,
|
||||
EIO_DT_NWK = 9, /* HP-UX network special */
|
||||
EIO_DT_CMP = 9, /* VxFS compressed */
|
||||
EIO_DT_LNK = 10,
|
||||
/* DT_SHAD = 11,*/
|
||||
EIO_DT_SOCK = 12,
|
||||
EIO_DT_DOOR = 13, /* solaris door */
|
||||
EIO_DT_WHT = 14,
|
||||
EIO_DT_MAX = 15 /* highest DT_VALUE ever, hopefully */
|
||||
};
|
||||
|
||||
struct eio_dirent
|
||||
{
|
||||
int nameofs; /* offset of null-terminated name string in (char *)req->ptr2 */
|
||||
unsigned short namelen; /* size of filename without trailing 0 */
|
||||
unsigned char type; /* one of EIO_DT_* */
|
||||
signed char score; /* internal use */
|
||||
ino_t inode; /* the inode number, if available, otherwise unspecified */
|
||||
};
|
||||
|
||||
/* eio_msync flags */
|
||||
enum
|
||||
{
|
||||
EIO_MS_ASYNC = 1,
|
||||
EIO_MS_INVALIDATE = 2,
|
||||
EIO_MS_SYNC = 4
|
||||
};
|
||||
|
||||
/* eio_mtouch flags */
|
||||
|
||||
enum
|
||||
{
|
||||
EIO_MT_MODIFY = 1
|
||||
};
|
||||
|
||||
/* eio_sync_file_range flags */
|
||||
|
||||
enum
|
||||
{
|
||||
EIO_SYNC_FILE_RANGE_WAIT_BEFORE = 1,
|
||||
EIO_SYNC_FILE_RANGE_WRITE = 2,
|
||||
EIO_SYNC_FILE_RANGE_WAIT_AFTER = 4
|
||||
};
|
||||
|
||||
typedef double eio_tstamp; /* feel free to use double in your code directly */
|
||||
|
||||
/* the eio request structure */
|
||||
|
||||
enum
|
||||
{
|
||||
EIO_CUSTOM,
|
||||
EIO_OPEN, EIO_CLOSE, EIO_DUP2,
|
||||
EIO_READ, EIO_WRITE,
|
||||
EIO_READAHEAD, EIO_SENDFILE,
|
||||
EIO_STAT, EIO_LSTAT, EIO_FSTAT,
|
||||
EIO_STATVFS, EIO_FSTATVFS,
|
||||
EIO_TRUNCATE, EIO_FTRUNCATE,
|
||||
EIO_UTIME, EIO_FUTIME,
|
||||
EIO_CHMOD, EIO_FCHMOD,
|
||||
EIO_CHOWN, EIO_FCHOWN,
|
||||
EIO_SYNC, EIO_FSYNC, EIO_FDATASYNC,
|
||||
EIO_MSYNC, EIO_MTOUCH, EIO_SYNC_FILE_RANGE,
|
||||
EIO_MLOCK, EIO_MLOCKALL,
|
||||
EIO_UNLINK, EIO_RMDIR, EIO_MKDIR, EIO_RENAME,
|
||||
EIO_MKNOD, EIO_READDIR,
|
||||
EIO_LINK, EIO_SYMLINK, EIO_READLINK,
|
||||
EIO_GROUP, EIO_NOP,
|
||||
EIO_BUSY
|
||||
};
|
||||
|
||||
/* mlockall constants */
|
||||
enum
|
||||
{
|
||||
EIO_MCL_CURRENT = 1,
|
||||
EIO_MCL_FUTURE = 2,
|
||||
};
|
||||
|
||||
/* request priorities */
|
||||
|
||||
enum {
|
||||
EIO_PRI_MIN = -4,
|
||||
EIO_PRI_MAX = 4,
|
||||
EIO_PRI_DEFAULT = 0,
|
||||
};
|
||||
|
||||
/* eio request structure */
|
||||
/* this structure is mostly read-only */
|
||||
/* when initialising it, all members must be zero-initialised */
|
||||
struct eio_req
|
||||
{
|
||||
eio_req volatile *next; /* private ETP */
|
||||
|
||||
ssize_t result; /* result of syscall, e.g. result = read (... */
|
||||
off_t offs; /* read, write, truncate, readahead, sync_file_range: file offset */
|
||||
size_t size; /* read, write, readahead, sendfile, msync, mlock, sync_file_range: length */
|
||||
void *ptr1; /* all applicable requests: pathname, old name; readdir: optional eio_dirents */
|
||||
void *ptr2; /* all applicable requests: new name or memory buffer; readdir: name strings */
|
||||
eio_tstamp nv1; /* utime, futime: atime; busy: sleep time */
|
||||
eio_tstamp nv2; /* utime, futime: mtime */
|
||||
|
||||
int type; /* EIO_xxx constant ETP */
|
||||
int int1; /* all applicable requests: file descriptor; sendfile: output fd; open, msync, mlockall, readdir: flags */
|
||||
long int2; /* chown, fchown: uid; sendfile: input fd; open, chmod, mkdir, mknod: file mode, sync_file_range: flags */
|
||||
long int3; /* chown, fchown: gid; mknod: dev_t */
|
||||
int errorno; /* errno value on syscall return */
|
||||
|
||||
unsigned char flags; /* private */
|
||||
signed char pri; /* the priority */
|
||||
|
||||
void *data;
|
||||
eio_cb finish;
|
||||
void (*destroy)(eio_req *req); /* called when requets no longer needed */
|
||||
void (*feed)(eio_req *req); /* only used for group requests */
|
||||
|
||||
EIO_REQ_MEMBERS
|
||||
|
||||
eio_req *grp, *grp_prev, *grp_next, *grp_first; /* private */
|
||||
};
|
||||
|
||||
/* _private_ request flags */
|
||||
enum {
|
||||
EIO_FLAG_CANCELLED = 0x01, /* request was cancelled */
|
||||
EIO_FLAG_PTR1_FREE = 0x02, /* need to free(ptr1) */
|
||||
EIO_FLAG_PTR2_FREE = 0x04, /* need to free(ptr2) */
|
||||
EIO_FLAG_GROUPADD = 0x08 /* some request was added to the group */
|
||||
};
|
||||
|
||||
/* undocumented/unsupported/private helper */
|
||||
/*void eio_page_align (void **addr, size_t *length);*/
|
||||
|
||||
/* returns < 0 on error, errno set
|
||||
* need_poll, if non-zero, will be called when results are available
|
||||
* and eio_poll_cb needs to be invoked (it MUST NOT call eio_poll_cb itself).
|
||||
* done_poll is called when the need to poll is gone.
|
||||
*/
|
||||
int eio_init (void (*want_poll)(void), void (*done_poll)(void));
|
||||
|
||||
/* must be called regularly to handle pending requests */
|
||||
/* returns 0 if all requests were handled, -1 if not, or the value of EIO_FINISH if != 0 */
|
||||
int eio_poll (void);
|
||||
|
||||
/* stop polling if poll took longer than duration seconds */
|
||||
void eio_set_max_poll_time (eio_tstamp nseconds);
|
||||
/* do not handle more then count requests in one call to eio_poll_cb */
|
||||
void eio_set_max_poll_reqs (unsigned int nreqs);
|
||||
|
||||
/* set minimum required number
|
||||
* maximum wanted number
|
||||
* or maximum idle number of threads */
|
||||
void eio_set_min_parallel (unsigned int nthreads);
|
||||
void eio_set_max_parallel (unsigned int nthreads);
|
||||
void eio_set_max_idle (unsigned int nthreads);
|
||||
|
||||
unsigned int eio_nreqs (void); /* number of requests in-flight */
|
||||
unsigned int eio_nready (void); /* number of not-yet handled requests */
|
||||
unsigned int eio_npending (void); /* numbe rof finished but unhandled requests */
|
||||
unsigned int eio_nthreads (void); /* number of worker threads in use currently */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* convinience wrappers */
|
||||
|
||||
#ifndef EIO_NO_WRAPPERS
|
||||
eio_req *eio_nop (int pri, eio_cb cb, void *data); /* does nothing except go through the whole process */
|
||||
eio_req *eio_busy (eio_tstamp delay, int pri, eio_cb cb, void *data); /* ties a thread for this long, simulating busyness */
|
||||
eio_req *eio_sync (int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_fsync (int fd, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_mlock (void *addr, size_t length, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_close (int fd, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_write (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_fstat (int fd, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
||||
eio_req *eio_fstatvfs (int fd, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
||||
eio_req *eio_futime (int fd, eio_tstamp atime, eio_tstamp mtime, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_ftruncate (int fd, off_t offset, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_fchmod (int fd, mode_t mode, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_fchown (int fd, uid_t uid, gid_t gid, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_open (const char *path, int flags, mode_t mode, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_utime (const char *path, eio_tstamp atime, eio_tstamp mtime, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_chown (const char *path, uid_t uid, gid_t gid, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_chmod (const char *path, mode_t mode, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_mkdir (const char *path, mode_t mode, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_readdir (const char *path, int flags, int pri, eio_cb cb, void *data); /* result=ptr2 allocated dynamically */
|
||||
eio_req *eio_rmdir (const char *path, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_unlink (const char *path, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data); /* result=ptr2 allocated dynamically */
|
||||
eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
||||
eio_req *eio_lstat (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
||||
eio_req *eio_statvfs (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
||||
eio_req *eio_mknod (const char *path, mode_t mode, dev_t dev, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_link (const char *path, const char *new_path, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_symlink (const char *path, const char *new_path, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_rename (const char *path, const char *new_path, int pri, eio_cb cb, void *data);
|
||||
eio_req *eio_custom (eio_cb execute, int pri, eio_cb cb, void *data);
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* groups */
|
||||
|
||||
eio_req *eio_grp (eio_cb cb, void *data);
|
||||
void eio_grp_feed (eio_req *grp, void (*feed)(eio_req *req), int limit);
|
||||
void eio_grp_limit (eio_req *grp, int limit);
|
||||
void eio_grp_add (eio_req *grp, eio_req *req);
|
||||
void eio_grp_cancel (eio_req *grp); /* cancels all sub requests but not the group */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* request api */
|
||||
|
||||
/* true if the request was cancelled, useful in the invoke callback */
|
||||
#define EIO_CANCELLED(req) ((req)->flags & EIO_FLAG_CANCELLED)
|
||||
|
||||
#define EIO_RESULT(req) ((req)->result)
|
||||
/* returns a pointer to the result buffer allocated by eio */
|
||||
#define EIO_BUF(req) ((req)->ptr2)
|
||||
#define EIO_STAT_BUF(req) ((EIO_STRUCT_STAT *)EIO_BUF(req))
|
||||
#define EIO_STATVFS_BUF(req) ((EIO_STRUCT_STATVFS *)EIO_BUF(req))
|
||||
#define EIO_PATH(req) ((char *)(req)->ptr1)
|
||||
|
||||
/* submit a request for execution */
|
||||
void eio_submit (eio_req *req);
|
||||
/* cancel a request as soon fast as possible, if possible */
|
||||
void eio_cancel (eio_req *req);
|
||||
/* destroy a request that has never been submitted */
|
||||
void eio_destroy (eio_req *req);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* convinience functions */
|
||||
|
||||
ssize_t eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* export these so node_file can use these function instead of pread/write */
|
||||
|
||||
#if !HAVE_PREADWRITE
|
||||
ssize_t eio__pread (int fd, void *buf, size_t count, off_t offset);
|
||||
ssize_t eio__pwrite (int fd, void *buf, size_t count, off_t offset);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
303
eio/eio.pod
Normal file
303
eio/eio.pod
Normal file
@ -0,0 +1,303 @@
|
||||
=head1 NAME
|
||||
|
||||
libeio - truly asynchronous POSIX I/O
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
#include <eio.h>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The newest version of this document is also available as an html-formatted
|
||||
web page you might find easier to navigate when reading it for the first
|
||||
time: L<http://pod.tst.eu/http://cvs.schmorp.de/libeio/eio.pod>.
|
||||
|
||||
Note that this library is a by-product of the C<IO::AIO> perl
|
||||
module, and many of the subtler points regarding requets lifetime
|
||||
and so on are only documented in its documentation at the
|
||||
moment: L<http://pod.tst.eu/http://cvs.schmorp.de/IO-AIO/AIO.pm>.
|
||||
|
||||
=head2 FEATURES
|
||||
|
||||
This library provides fully asynchronous versions of most POSIX functions
|
||||
dealign with I/O. Unlike most asynchronous libraries, this not only
|
||||
includes C<read> and C<write>, but also C<open>, C<stat>, C<unlink> and
|
||||
similar functions, as well as less rarely ones such as C<mknod>, C<futime>
|
||||
or C<readlink>.
|
||||
|
||||
It also offers wrappers around C<sendfile> (Solaris, Linux, HP-UX and
|
||||
FreeBSD, with emulation on other platforms) and C<readahead> (Linux, with
|
||||
emulation elsewhere>).
|
||||
|
||||
The goal is to enable you to write fully non-blocking programs. For
|
||||
example, in a game server, you would not want to freeze for a few seconds
|
||||
just because the server is running a backup and you happen to call
|
||||
C<readdir>.
|
||||
|
||||
=head2 TIME REPRESENTATION
|
||||
|
||||
Libeio represents time as a single floating point number, representing the
|
||||
(fractional) number of seconds since the (POSIX) epoch (somewhere near
|
||||
the beginning of 1970, details are complicated, don't ask). This type is
|
||||
called C<eio_tstamp>, but it is guarenteed to be of type C<double> (or
|
||||
better), so you can freely use C<double> yourself.
|
||||
|
||||
Unlike the name component C<stamp> might indicate, it is also used for
|
||||
time differences throughout libeio.
|
||||
|
||||
=head2 FORK SUPPORT
|
||||
|
||||
Calling C<fork ()> is fully supported by this module. It is implemented in these steps:
|
||||
|
||||
1. wait till all requests in "execute" state have been handled
|
||||
(basically requests that are already handed over to the kernel).
|
||||
2. fork
|
||||
3. in the parent, continue business as usual, done
|
||||
4. in the child, destroy all ready and pending requests and free the
|
||||
memory used by the worker threads. This gives you a fully empty
|
||||
libeio queue.
|
||||
|
||||
=head1 INITIALISATION/INTEGRATION
|
||||
|
||||
Before you can call any eio functions you first have to initialise the
|
||||
library. The library integrates into any event loop, but can also be used
|
||||
without one, including in polling mode.
|
||||
|
||||
You have to provide the necessary glue yourself, however.
|
||||
|
||||
=over 4
|
||||
|
||||
=item int eio_init (void (*want_poll)(void), void (*done_poll)(void))
|
||||
|
||||
This function initialises the library. On success it returns C<0>, on
|
||||
failure it returns C<-1> and sets C<errno> appropriately.
|
||||
|
||||
It accepts two function pointers specifying callbacks as argument, both of
|
||||
which can be C<0>, in which case the callback isn't called.
|
||||
|
||||
=item want_poll callback
|
||||
|
||||
The C<want_poll> callback is invoked whenever libeio wants attention (i.e.
|
||||
it wants to be polled by calling C<eio_poll>). It is "edge-triggered",
|
||||
that is, it will only be called once when eio wants attention, until all
|
||||
pending requests have been handled.
|
||||
|
||||
This callback is called while locks are being held, so I<you must
|
||||
not call any libeio functions inside this callback>. That includes
|
||||
C<eio_poll>. What you should do is notify some other thread, or wake up
|
||||
your event loop, and then call C<eio_poll>.
|
||||
|
||||
=item done_poll callback
|
||||
|
||||
This callback is invoked when libeio detects that all pending requests
|
||||
have been handled. It is "edge-triggered", that is, it will only be
|
||||
called once after C<want_poll>. To put it differently, C<want_poll> and
|
||||
C<done_poll> are invoked in pairs: after C<want_poll> you have to call
|
||||
C<eio_poll ()> until either C<eio_poll> indicates that everything has been
|
||||
handled or C<done_poll> has been called, which signals the same.
|
||||
|
||||
Note that C<eio_poll> might return after C<done_poll> and C<want_poll>
|
||||
have been called again, so watch out for races in your code.
|
||||
|
||||
As with C<want_poll>, this callback is called while lcoks are being held,
|
||||
so you I<must not call any libeio functions form within this callback>.
|
||||
|
||||
=item int eio_poll ()
|
||||
|
||||
This function has to be called whenever there are pending requests that
|
||||
need finishing. You usually call this after C<want_poll> has indicated
|
||||
that you should do so, but you can also call this function regularly to
|
||||
poll for new results.
|
||||
|
||||
If any request invocation returns a non-zero value, then C<eio_poll ()>
|
||||
immediately returns with that value as return value.
|
||||
|
||||
Otherwise, if all requests could be handled, it returns C<0>. If for some
|
||||
reason not all requests have been handled, i.e. some are still pending, it
|
||||
returns C<-1>.
|
||||
|
||||
=back
|
||||
|
||||
For libev, you would typically use an C<ev_async> watcher: the
|
||||
C<want_poll> callback would invoke C<ev_async_send> to wake up the event
|
||||
loop. Inside the callback set for the watcher, one would call C<eio_poll
|
||||
()> (followed by C<ev_async_send> again if C<eio_poll> indicates that not
|
||||
all requests have been handled yet). The race is taken care of because
|
||||
libev resets/rearms the async watcher before calling your callback,
|
||||
and therefore, before calling C<eio_poll>. This might result in (some)
|
||||
spurious wake-ups, but is generally harmless.
|
||||
|
||||
For most other event loops, you would typically use a pipe - the event
|
||||
loop should be told to wait for read readyness on the read end. In
|
||||
C<want_poll> you would write a single byte, in C<done_poll> you would try
|
||||
to read that byte, and in the callback for the read end, you would call
|
||||
C<eio_poll>. The race is avoided here because the event loop should invoke
|
||||
your callback again and again until the byte has been read (as the pipe
|
||||
read callback does not read it, only C<done_poll>).
|
||||
|
||||
=head2 CONFIGURATION
|
||||
|
||||
The functions in this section can sometimes be useful, but the default
|
||||
configuration will do in most case, so you should skip this section on
|
||||
first reading.
|
||||
|
||||
=over 4
|
||||
|
||||
=item eio_set_max_poll_time (eio_tstamp nseconds)
|
||||
|
||||
This causes C<eio_poll ()> to return after it has detected that it was
|
||||
running for C<nsecond> seconds or longer (this number can be fractional).
|
||||
|
||||
This can be used to limit the amount of time spent handling eio requests,
|
||||
for example, in interactive programs, you might want to limit this time to
|
||||
C<0.01> seconds or so.
|
||||
|
||||
Note that:
|
||||
|
||||
a) libeio doesn't know how long your request callbacks take, so the time
|
||||
spent in C<eio_poll> is up to one callback invocation longer then this
|
||||
interval.
|
||||
|
||||
b) this is implemented by calling C<gettimeofday> after each request,
|
||||
which can be costly.
|
||||
|
||||
c) at least one request will be handled.
|
||||
|
||||
=item eio_set_max_poll_reqs (unsigned int nreqs)
|
||||
|
||||
When C<nreqs> is non-zero, then C<eio_poll> will not handle more than
|
||||
C<nreqs> requests per invocation. This is a less costly way to limit the
|
||||
amount of work done by C<eio_poll> then setting a time limit.
|
||||
|
||||
If you know your callbacks are generally fast, you could use this to
|
||||
encourage interactiveness in your programs by setting it to C<10>, C<100>
|
||||
or even C<1000>.
|
||||
|
||||
=item eio_set_min_parallel (unsigned int nthreads)
|
||||
|
||||
Make sure libeio can handle at least this many requests in parallel. It
|
||||
might be able handle more.
|
||||
|
||||
=item eio_set_max_parallel (unsigned int nthreads)
|
||||
|
||||
Set the maximum number of threads that libeio will spawn.
|
||||
|
||||
=item eio_set_max_idle (unsigned int nthreads)
|
||||
|
||||
Libeio uses threads internally to handle most requests, and will start and stop threads on demand.
|
||||
|
||||
This call can be used to limit the number of idle threads (threads without
|
||||
work to do): libeio will keep some threads idle in preperation for more
|
||||
requests, but never longer than C<nthreads> threads.
|
||||
|
||||
In addition to this, libeio will also stop threads when they are idle for
|
||||
a few seconds, regardless of this setting.
|
||||
|
||||
=item unsigned int eio_nthreads ()
|
||||
|
||||
Return the number of worker threads currently running.
|
||||
|
||||
=item unsigned int eio_nreqs ()
|
||||
|
||||
Return the number of requests currently handled by libeio. This is the
|
||||
total number of requests that have been submitted to libeio, but not yet
|
||||
destroyed.
|
||||
|
||||
=item unsigned int eio_nready ()
|
||||
|
||||
Returns the number of ready requests, i.e. requests that have been
|
||||
submitted but have not yet entered the execution phase.
|
||||
|
||||
=item unsigned int eio_npending ()
|
||||
|
||||
Returns the number of pending requests, i.e. requests that have been
|
||||
executed and have results, but have not been finished yet by a call to
|
||||
C<eio_poll>).
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 ANATOMY OF AN EIO REQUEST
|
||||
|
||||
#TODO
|
||||
|
||||
|
||||
=head1 HIGH LEVEL REQUEST API
|
||||
|
||||
#TODO
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 LOW LEVEL REQUEST API
|
||||
|
||||
#TODO
|
||||
|
||||
=head1 EMBEDDING
|
||||
|
||||
Libeio can be embedded directly into programs. This functionality is not
|
||||
documented and not (yet) officially supported.
|
||||
|
||||
Note that, when including C<libeio.m4>, you are responsible for defining
|
||||
the compilation environment (C<_LARGEFILE_SOURCE>, C<_GNU_SOURCE> etc.).
|
||||
|
||||
If you need to know how, check the C<IO::AIO> perl module, which does
|
||||
exactly that.
|
||||
|
||||
|
||||
=head1 COMPILETIME CONFIGURATION
|
||||
|
||||
These symbols, if used, must be defined when compiling F<eio.c>.
|
||||
|
||||
=over 4
|
||||
|
||||
=item EIO_STACKSIZE
|
||||
|
||||
This symbol governs the stack size for each eio thread. Libeio itself
|
||||
was written to use very little stackspace, but when using C<EIO_CUSTOM>
|
||||
requests, you might want to increase this.
|
||||
|
||||
If this symbol is undefined (the default) then libeio will use its default
|
||||
stack size (C<sizeof (long) * 4096> currently). If it is defined, but
|
||||
C<0>, then the default operating system stack size will be used. In all
|
||||
other cases, the value must be an expression that evaluates to the desired
|
||||
stack size.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 PORTABILITY REQUIREMENTS
|
||||
|
||||
In addition to a working ISO-C implementation, libeio relies on a few
|
||||
additional extensions:
|
||||
|
||||
=over 4
|
||||
|
||||
=item POSIX threads
|
||||
|
||||
To be portable, this module uses threads, specifically, the POSIX threads
|
||||
library must be available (and working, which partially excludes many xBSD
|
||||
systems, where C<fork ()> is buggy).
|
||||
|
||||
=item POSIX-compatible filesystem API
|
||||
|
||||
This is actually a harder portability requirement: The libeio API is quite
|
||||
demanding regarding POSIX API calls (symlinks, user/group management
|
||||
etc.).
|
||||
|
||||
=item C<double> must hold a time value in seconds with enough accuracy
|
||||
|
||||
The type C<double> is used to represent timestamps. It is required to
|
||||
have at least 51 bits of mantissa (and 9 bits of exponent), which is good
|
||||
enough for at least into the year 4000. This requirement is fulfilled by
|
||||
implementations implementing IEEE 754 (basically all existing ones).
|
||||
|
||||
=back
|
||||
|
||||
If you know of other additional requirements drop me a note.
|
||||
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Marc Lehmann <libeio@schmorp.de>.
|
||||
|
||||
156
eio/libeio.m4
Normal file
156
eio/libeio.m4
Normal file
@ -0,0 +1,156 @@
|
||||
AC_SEARCH_LIBS(
|
||||
pthread_create,
|
||||
[pthread pthreads pthreadVC2],
|
||||
,
|
||||
[AC_MSG_ERROR(pthread functions not found)]
|
||||
)
|
||||
|
||||
AC_CACHE_CHECK(for utimes, ac_cv_utimes, [AC_LINK_IFELSE([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <utime.h>
|
||||
struct timeval tv[2];
|
||||
int res;
|
||||
int main (void)
|
||||
{
|
||||
res = utimes ("/", tv);
|
||||
return 0;
|
||||
}
|
||||
]],ac_cv_utimes=yes,ac_cv_utimes=no)])
|
||||
test $ac_cv_utimes = yes && AC_DEFINE(HAVE_UTIMES, 1, utimes(2) is available)
|
||||
|
||||
AC_CACHE_CHECK(for futimes, ac_cv_futimes, [AC_LINK_IFELSE([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <utime.h>
|
||||
struct timeval tv[2];
|
||||
int res;
|
||||
int fd;
|
||||
int main (void)
|
||||
{
|
||||
res = futimes (fd, tv);
|
||||
return 0;
|
||||
}
|
||||
]],ac_cv_futimes=yes,ac_cv_futimes=no)])
|
||||
test $ac_cv_futimes = yes && AC_DEFINE(HAVE_FUTIMES, 1, futimes(2) is available)
|
||||
|
||||
AC_CACHE_CHECK(for readahead, ac_cv_readahead, [AC_LINK_IFELSE([
|
||||
#include <fcntl.h>
|
||||
int main (void)
|
||||
{
|
||||
int fd = 0;
|
||||
size_t count = 2;
|
||||
ssize_t res;
|
||||
res = readahead (fd, 0, count);
|
||||
return 0;
|
||||
}
|
||||
],ac_cv_readahead=yes,ac_cv_readahead=no)])
|
||||
test $ac_cv_readahead = yes && AC_DEFINE(HAVE_READAHEAD, 1, readahead(2) is available (linux))
|
||||
|
||||
AC_CACHE_CHECK(for fdatasync, ac_cv_fdatasync, [AC_LINK_IFELSE([
|
||||
#include <unistd.h>
|
||||
int main (void)
|
||||
{
|
||||
int fd = 0;
|
||||
fdatasync (fd);
|
||||
return 0;
|
||||
}
|
||||
],ac_cv_fdatasync=yes,ac_cv_fdatasync=no)])
|
||||
test $ac_cv_fdatasync = yes && AC_DEFINE(HAVE_FDATASYNC, 1, fdatasync(2) is available)
|
||||
|
||||
AC_CACHE_CHECK(for pread and pwrite, ac_cv_preadwrite, [AC_LINK_IFELSE([
|
||||
#include <unistd.h>
|
||||
int main (void)
|
||||
{
|
||||
int fd = 0;
|
||||
size_t count = 1;
|
||||
char buf;
|
||||
off_t offset = 1;
|
||||
ssize_t res;
|
||||
res = pread (fd, &buf, count, offset);
|
||||
res = pwrite (fd, &buf, count, offset);
|
||||
return 0;
|
||||
}
|
||||
],ac_cv_preadwrite=yes,ac_cv_preadwrite=no)])
|
||||
test $ac_cv_preadwrite = yes && AC_DEFINE(HAVE_PREADWRITE, 1, pread(2) and pwrite(2) are available)
|
||||
|
||||
AC_CACHE_CHECK(for sendfile, ac_cv_sendfile, [AC_LINK_IFELSE([
|
||||
# include <sys/types.h>
|
||||
#if __linux
|
||||
# include <sys/sendfile.h>
|
||||
#elif __FreeBSD__ || defined __APPLE__
|
||||
# include <sys/socket.h>
|
||||
# include <sys/uio.h>
|
||||
#elif __hpux
|
||||
# include <sys/socket.h>
|
||||
#else
|
||||
# error unsupported architecture
|
||||
#endif
|
||||
int main (void)
|
||||
{
|
||||
int fd = 0;
|
||||
off_t offset = 1;
|
||||
size_t count = 2;
|
||||
ssize_t res;
|
||||
#if __linux
|
||||
res = sendfile (fd, fd, offset, count);
|
||||
#elif __FreeBSD__
|
||||
res = sendfile (fd, fd, offset, count, 0, &offset, 0);
|
||||
#elif __hpux
|
||||
res = sendfile (fd, fd, offset, count, 0, 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
],ac_cv_sendfile=yes,ac_cv_sendfile=no)])
|
||||
test $ac_cv_sendfile = yes && AC_DEFINE(HAVE_SENDFILE, 1, sendfile(2) is available and supported)
|
||||
|
||||
AC_CACHE_CHECK(for sync_file_range, ac_cv_sync_file_range, [AC_LINK_IFELSE([
|
||||
#include <fcntl.h>
|
||||
int main (void)
|
||||
{
|
||||
int fd = 0;
|
||||
off64_t offset = 1;
|
||||
off64_t nbytes = 1;
|
||||
unsigned int flags = SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER;
|
||||
ssize_t res;
|
||||
res = sync_file_range (fd, offset, nbytes, flags);
|
||||
return 0;
|
||||
}
|
||||
],ac_cv_sync_file_range=yes,ac_cv_sync_file_range=no)])
|
||||
test $ac_cv_sync_file_range = yes && AC_DEFINE(HAVE_SYNC_FILE_RANGE, 1, sync_file_range(2) is available)
|
||||
|
||||
dnl #############################################################################
|
||||
dnl # these checks exist for the benefit of IO::AIO
|
||||
|
||||
dnl at least uclibc defines _POSIX_ADVISORY_INFO without *any* of the required
|
||||
dnl functionality actually being present. ugh.
|
||||
AC_CACHE_CHECK(for posix_madvise, ac_cv_posix_madvise, [AC_LINK_IFELSE([
|
||||
#include <sys/mman.h>
|
||||
int main (void)
|
||||
{
|
||||
int res = posix_madvise ((void *)0, (size_t)0, POSIX_MADV_NORMAL);
|
||||
int a = POSIX_MADV_SEQUENTIAL;
|
||||
int b = POSIX_MADV_RANDOM;
|
||||
int c = POSIX_MADV_WILLNEED;
|
||||
int d = POSIX_MADV_DONTNEED;
|
||||
return 0;
|
||||
}
|
||||
],ac_cv_posix_madvise=yes,ac_cv_posix_madvise=no)])
|
||||
test $ac_cv_posix_madvise = yes && AC_DEFINE(HAVE_POSIX_MADVISE, 1, posix_madvise(2) is available)
|
||||
|
||||
AC_CACHE_CHECK(for posix_fadvise, ac_cv_posix_fadvise, [AC_LINK_IFELSE([
|
||||
#define _XOPEN_SOURCE 600
|
||||
#include <fcntl.h>
|
||||
int main (void)
|
||||
{
|
||||
int res = posix_fadvise ((int)0, (off_t)0, (off_t)0, POSIX_FADV_NORMAL);
|
||||
int a = POSIX_FADV_SEQUENTIAL;
|
||||
int b = POSIX_FADV_NOREUSE;
|
||||
int c = POSIX_FADV_RANDOM;
|
||||
int d = POSIX_FADV_WILLNEED;
|
||||
int e = POSIX_FADV_DONTNEED;
|
||||
return 0;
|
||||
}
|
||||
],ac_cv_posix_fadvise=yes,ac_cv_posix_fadvise=no)])
|
||||
test $ac_cv_posix_fadvise = yes && AC_DEFINE(HAVE_POSIX_FADVISE, 1, posix_fadvise(2) is available)
|
||||
|
||||
159
eio/xthread.h
Normal file
159
eio/xthread.h
Normal file
@ -0,0 +1,159 @@
|
||||
#ifndef XTHREAD_H_
|
||||
#define XTHREAD_H_
|
||||
|
||||
/* whether word reads are potentially non-atomic.
|
||||
* this is conservatice, likely most arches this runs
|
||||
* on have atomic word read/writes.
|
||||
*/
|
||||
#ifndef WORDACCESS_UNSAFE
|
||||
# if __i386 || __x86_64
|
||||
# define WORDACCESS_UNSAFE 0
|
||||
# else
|
||||
# define WORDACCESS_UNSAFE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef __MINGW32__
|
||||
typedef int ssize_t
|
||||
#endif
|
||||
|
||||
#define NTDDI_VERSION NTDDI_WIN2K // needed to get win2000 api calls
|
||||
#define _WIN32_WINNT 0x400
|
||||
#include <stdio.h>//D
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <time.h>
|
||||
#include <winsock2.h>
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#include <pthread.h>
|
||||
#define sigset_t int
|
||||
#define pthread_sigmask(a,b,c)
|
||||
#define sigaddset(a,b)
|
||||
#define sigemptyset(s)
|
||||
#define sigfillset(s)
|
||||
|
||||
typedef pthread_mutex_t xmutex_t;
|
||||
#define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
|
||||
#define X_LOCK(mutex) pthread_mutex_lock (&(mutex))
|
||||
#define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
|
||||
|
||||
typedef pthread_cond_t xcond_t;
|
||||
#define X_COND_INIT PTHREAD_COND_INITIALIZER
|
||||
#define X_COND_SIGNAL(cond) pthread_cond_signal (&(cond))
|
||||
#define X_COND_WAIT(cond,mutex) pthread_cond_wait (&(cond), &(mutex))
|
||||
#define X_COND_TIMEDWAIT(cond,mutex,to) pthread_cond_timedwait (&(cond), &(mutex), &(to))
|
||||
|
||||
typedef pthread_t xthread_t;
|
||||
#define X_THREAD_PROC(name) void *name (void *thr_arg)
|
||||
#define X_THREAD_ATFORK(a,b,c)
|
||||
|
||||
static int
|
||||
thread_create (xthread_t *tid, void *(*proc)(void *), void *arg)
|
||||
{
|
||||
int retval;
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init (&attr);
|
||||
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
retval = pthread_create (tid, &attr, proc, arg) == 0;
|
||||
|
||||
pthread_attr_destroy (&attr);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define respipe_read(a,b,c) PerlSock_recv ((a), (b), (c), 0)
|
||||
#define respipe_write(a,b,c) send ((a), (b), (c), 0)
|
||||
#define respipe_close(a) PerlSock_closesocket ((a))
|
||||
|
||||
#else
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if __linux && !defined(_GNU_SOURCE)
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
/* just in case */
|
||||
#define _REENTRANT 1
|
||||
|
||||
#if __solaris
|
||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||
/* try to bribe solaris headers into providing a current pthread API
|
||||
* despite environment being configured for an older version.
|
||||
*/
|
||||
# define __EXTENSIONS__ 1
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef pthread_mutex_t xmutex_t;
|
||||
#if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
|
||||
# define X_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
#else
|
||||
# define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
|
||||
#endif
|
||||
#define X_LOCK(mutex) pthread_mutex_lock (&(mutex))
|
||||
#define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
|
||||
|
||||
typedef pthread_cond_t xcond_t;
|
||||
#define X_COND_INIT PTHREAD_COND_INITIALIZER
|
||||
#define X_COND_SIGNAL(cond) pthread_cond_signal (&(cond))
|
||||
#define X_COND_WAIT(cond,mutex) pthread_cond_wait (&(cond), &(mutex))
|
||||
#define X_COND_TIMEDWAIT(cond,mutex,to) pthread_cond_timedwait (&(cond), &(mutex), &(to))
|
||||
|
||||
typedef pthread_t xthread_t;
|
||||
#define X_THREAD_PROC(name) static void *name (void *thr_arg)
|
||||
#define X_THREAD_ATFORK(prepare,parent,child) pthread_atfork (prepare, parent, child)
|
||||
|
||||
// the broken bsd's once more
|
||||
#ifndef PTHREAD_STACK_MIN
|
||||
# define PTHREAD_STACK_MIN 0
|
||||
#endif
|
||||
|
||||
#ifndef X_STACKSIZE
|
||||
# define X_STACKSIZE sizeof (long) * 4096
|
||||
#endif
|
||||
|
||||
static int
|
||||
thread_create (xthread_t *tid, void *(*proc)(void *), void *arg)
|
||||
{
|
||||
int retval;
|
||||
sigset_t fullsigset, oldsigset;
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init (&attr);
|
||||
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < X_STACKSIZE ? X_STACKSIZE : PTHREAD_STACK_MIN);
|
||||
#ifdef PTHREAD_SCOPE_PROCESS
|
||||
pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
|
||||
#endif
|
||||
|
||||
sigfillset (&fullsigset);
|
||||
|
||||
pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
|
||||
retval = pthread_create (tid, &attr, proc, arg) == 0;
|
||||
pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
|
||||
|
||||
pthread_attr_destroy (&attr);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define respipe_read(a,b,c) read ((a), (b), (c))
|
||||
#define respipe_write(a,b,c) write ((a), (b), (c))
|
||||
#define respipe_close(a) close ((a))
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
113
uv-eio.c
Normal file
113
uv-eio.c
Normal file
@ -0,0 +1,113 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* This file integrates the libuv event loop with the libeio thread pool */
|
||||
|
||||
#include "uv.h"
|
||||
#include "eio.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
static uv_async_t uv_eio_want_poll_notifier;
|
||||
static uv_async_t uv_eio_done_poll_notifier;
|
||||
static uv_idle_t uv_eio_poller;
|
||||
static int uv_eio_init_count;
|
||||
|
||||
|
||||
static void uv_eio_do_poll(uv_idle_t* watcher, int status) {
|
||||
assert(watcher == &uv_eio_poller);
|
||||
|
||||
/* printf("uv_eio_poller\n"); */
|
||||
|
||||
if (eio_poll() != -1 && uv_is_active((uv_handle_t*) &uv_eio_poller)) {
|
||||
/* printf("uv_eio_poller stop\n"); */
|
||||
uv_idle_stop(&uv_eio_poller);
|
||||
uv_unref();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called from the main thread. */
|
||||
static void uv_eio_want_poll_notifier_cb(uv_async_t* watcher, int status) {
|
||||
assert(watcher == &uv_eio_want_poll_notifier);
|
||||
|
||||
/* printf("want poll notifier\n"); */
|
||||
|
||||
if (eio_poll() == -1 && !uv_is_active((uv_handle_t*) &uv_eio_poller)) {
|
||||
/* printf("uv_eio_poller start\n"); */
|
||||
uv_idle_start(&uv_eio_poller, uv_eio_do_poll);
|
||||
uv_ref();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uv_eio_done_poll_notifier_cb(uv_async_t* watcher, int revents) {
|
||||
assert(watcher == &uv_eio_done_poll_notifier);
|
||||
|
||||
/* printf("done poll notifier\n"); */
|
||||
|
||||
if (eio_poll() != -1 && uv_is_active((uv_handle_t*) &uv_eio_poller)) {
|
||||
/* printf("uv_eio_poller stop\n"); */
|
||||
uv_idle_stop(&uv_eio_poller);
|
||||
uv_unref();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* uv_eio_want_poll() is called from the EIO thread pool each time an EIO
|
||||
* request (that is, one of the node.fs.* functions) has completed.
|
||||
*/
|
||||
static void uv_eio_want_poll(void) {
|
||||
/* Signal the main thread that eio_poll need to be processed. */
|
||||
uv_async_send(&uv_eio_want_poll_notifier);
|
||||
}
|
||||
|
||||
|
||||
static void uv_eio_done_poll(void) {
|
||||
/*
|
||||
* Signal the main thread that we should stop calling eio_poll().
|
||||
* from the idle watcher.
|
||||
*/
|
||||
uv_async_send(&uv_eio_done_poll_notifier);
|
||||
}
|
||||
|
||||
|
||||
void uv_eio_init() {
|
||||
if (uv_eio_init_count == 0) {
|
||||
uv_eio_init_count++;
|
||||
|
||||
uv_idle_init(&uv_eio_poller);
|
||||
uv_idle_start(&uv_eio_poller, uv_eio_do_poll);
|
||||
|
||||
uv_async_init(&uv_eio_want_poll_notifier, uv_eio_want_poll_notifier_cb);
|
||||
uv_unref();
|
||||
|
||||
uv_async_init(&uv_eio_done_poll_notifier, uv_eio_done_poll_notifier_cb);
|
||||
uv_unref();
|
||||
|
||||
eio_init(uv_eio_want_poll, uv_eio_done_poll);
|
||||
/*
|
||||
* Don't handle more than 10 reqs on each eio_poll(). This is to avoid
|
||||
* race conditions. See Node's test/simple/test-eio-race.js
|
||||
*/
|
||||
eio_set_max_poll_reqs(10);
|
||||
}
|
||||
}
|
||||
10
uv-eio.h
Normal file
10
uv-eio.h
Normal file
@ -0,0 +1,10 @@
|
||||
/* This header is private to libuv */
|
||||
#ifndef UV_EIO_H_
|
||||
#define UV_EIO_H_
|
||||
/*
|
||||
* Call this function to integrate libeio into the libuv event loop. It is
|
||||
* safe to call more than once.
|
||||
* TODO: uv_eio_deinit
|
||||
*/
|
||||
void uv_eio_init(void);
|
||||
#endif
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv-common.h"
|
||||
#include "uv-eio.h"
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h> /* printf */
|
||||
@ -64,7 +65,6 @@ static void uv__tcp_connect(uv_tcp_t*);
|
||||
int uv_tcp_open(uv_tcp_t*, int fd);
|
||||
static void uv__finish_close(uv_handle_t* handle);
|
||||
|
||||
|
||||
/* flags */
|
||||
enum {
|
||||
UV_CLOSING = 0x00000001, /* uv_close() called but not finished. */
|
||||
@ -1488,6 +1488,7 @@ int uv_getaddrinfo(uv_getaddrinfo_t* handle,
|
||||
const char* node,
|
||||
const char* service,
|
||||
const struct addrinfo* hints) {
|
||||
uv_eio_init();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user