Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
6efeaf4
try to fix issue #3 by special casing listening sockets in is_not_yet…
jiixyj Sep 29, 2018
7ebe14a
ignore EVFILT_WRITE deregistration ENOENT errors (issue #4)
jiixyj Oct 7, 2018
2b2d977
add test for correct EVFILT_WRITE deregistration (issue #4)
jiixyj Oct 7, 2018
f1ced85
Add tests for closed file descriptors
sghctoma Nov 24, 2018
e0a1d75
add parens around return values
jiixyj Jun 4, 2019
f3ce2bd
clear internal state if trying to remove an already closed fd from th…
jiixyj Jun 4, 2019
7fca585
don't run interactive test by default
jiixyj Jun 4, 2019
b026aad
adjust test_same_fd_value test so that epoll_ctl EPOLL_CTL_DEL is called
jiixyj Jun 4, 2019
fba999a
add README.md
jiixyj Jun 4, 2019
0cf1332
enable running tests with CTest
jiixyj Jun 21, 2019
db0f2de
use kqueue EVFILT_TIMER based implementation for timerfd if possible
jiixyj Jun 22, 2019
b3be554
add missing test source file
jiixyj Jun 22, 2019
4eff41b
refactor build system slightly, install pkgconfig file
jiixyj Jun 22, 2019
8d66fa5
make epoll-shim link privately against Threads::Threads
jiixyj Jun 22, 2019
58aa9a5
remove old Makefile
jiixyj Jun 22, 2019
7f13ee4
add installation instructions
jiixyj Jun 22, 2019
baacd40
fix sign of errno value
jiixyj Jun 22, 2019
cb75197
fix sign of errno value
jiixyj Jun 22, 2019
1605b57
only ask for fd type when adding to epoll fd (avoids fstat'ing invali…
jiixyj Jun 22, 2019
602e331
try to fix infinite loop in test20
jiixyj Jun 22, 2019
4037460
fix name of pkg-config file
jiixyj Jun 22, 2019
c680517
also install epoll-shim.pc when building the static lib
jiixyj Jun 22, 2019
a790d8d
install cmake config files for consumers
jiixyj Jun 22, 2019
872ce7e
remove superfluous 'libepoll-shim' in pkg-config file (issue #9)
jiixyj Sep 3, 2019
1fe0d0b
fix compile and test failures on FreeBSD 11.3
jiixyj Sep 25, 2019
7c38c31
implement eventfd (WIP, untested)
jiixyj Nov 1, 2019
c53b9be
add '.vscode' to .gitignore
jiixyj Nov 1, 2019
dc4c71e
add some eventfd tests
jiixyj Nov 1, 2019
7fd5712
implement blocking semantics for eventfd read()
jiixyj Nov 1, 2019
103defa
add tests for EventFDCtx
jiixyj Nov 1, 2019
65e1d54
fix include order
jiixyj Nov 1, 2019
31e0955
fix racy update of 'current_expirations' of timerfd_context
jiixyj Nov 1, 2019
355c9ae
Merge remote-tracking branch 'origin/master' into 6-eventfd
jiixyj Nov 1, 2019
0c033bf
mention eventfd in documentation
jiixyj Nov 1, 2019
6391177
forward declare eventfd_context
jiixyj Nov 1, 2019
8b94746
split up shim helper include guards so that every fd type gets what i…
jiixyj Nov 1, 2019
0c54d2e
move blocking logic out of EventFDCtx
jiixyj Nov 1, 2019
80eaa39
use poll to wait for eventfd
jiixyj Nov 2, 2019
31ab9b2
eventfd: take kqueue fd as argument instead of creating it
jiixyj Nov 2, 2019
6756028
split out timerfd logic into separate 'TimerFDCtx'
jiixyj Nov 2, 2019
3de9c7c
save a non owning kqueue fd reference in EventFDCtx
jiixyj Nov 2, 2019
ce72f9a
improve locking in TimerFDCtx
jiixyj Nov 2, 2019
1ab6cde
rename complex to complx to avoid problems with vim's syntax highligh…
jiixyj Nov 2, 2019
34a78b6
improve consistency of kevent calls
jiixyj Nov 2, 2019
0d6517a
split out signalfd logic into SignalFDCtx
jiixyj Nov 3, 2019
da27e15
copy signalfd_siginfo out via memcpy
jiixyj Nov 3, 2019
1a5e4fc
major refactoring of 'fd to context object' mapping
jiixyj Nov 3, 2019
aa62cc4
check for correct type in timerfd_settime_impl
jiixyj Nov 3, 2019
078493a
fix compiler errors under FreeBSD 11.3
jiixyj Nov 3, 2019
301e812
add worst case performance test of old lookup mechanism
jiixyj Nov 3, 2019
d72542e
Merge branch '6-eventfd' into 11-fd-to-context-map
jiixyj Nov 3, 2019
e8c4435
require that perf-many-fds test does not take longer than 10s
jiixyj Nov 3, 2019
b544984
perf-many-fds: reduce number of fds a bit
jiixyj Nov 3, 2019
c6b2829
perf-many-fds: increase timeout to 15s
jiixyj Nov 3, 2019
7fd5230
fix compiler warnings
jiixyj Nov 3, 2019
ffe71b9
port many-timers test to Linux
jiixyj Nov 3, 2019
d6c4506
autoformat
jiixyj Nov 3, 2019
0d56434
add test for correct errno value on invalid write calls
jiixyj Nov 3, 2019
23bb4d7
fix 'invalid writes' test
jiixyj Nov 3, 2019
e918e62
test invalid writes/reads on epoll fd
jiixyj Nov 3, 2019
71af8c1
create simple EpollFDCtx, to be expanded later
jiixyj Nov 3, 2019
c13d163
fix cleaning up old context objects when the kq was closed with close…
jiixyj Nov 3, 2019
7cb38bb
improve error handling of kqueue_load_state/kqueue_save_state
jiixyj Nov 3, 2019
f9e7fd5
add mutex to EpollFDCtx
jiixyj Nov 3, 2019
908fff5
remove poll hack for now
jiixyj Nov 3, 2019
a3e7ddd
move epollfd implementation details into epollfd_ctx.c
jiixyj Nov 3, 2019
dbb2624
fix assertion
jiixyj Nov 3, 2019
e4c4393
update sys/epoll.h header from musl
jiixyj Nov 4, 2019
ea515f0
add support for one poll-only fd per epoll instance
jiixyj Nov 4, 2019
b99d614
fix build under FreeBSD 11.3
jiixyj Nov 9, 2019
2ac5622
Merge branch 'master' into update-20191109
jiixyj Nov 9, 2019
354324a
try to make CI work again
jiixyj Nov 9, 2019
a449a25
CI: install cmake
jiixyj Nov 9, 2019
ac72bda
Merge remote-tracking branch 'origin/master' into update-20191109
jiixyj Nov 9, 2019
2575d0a
CI: increase verbosity of test results
jiixyj Nov 9, 2019
160581d
test/many-timers: allow some additional timer slack
jiixyj Nov 9, 2019
40a7c9c
Merge remote-tracking branch 'origin/master' into update-20191109
jiixyj Nov 9, 2019
283f48b
test/many-timers: revert timer slack change
jiixyj Nov 10, 2019
94689eb
Merge remote-tracking branch 'origin/master' into update-20191109
jiixyj Nov 10, 2019
bd90ddb
CI: update to FreeBSD 11.3
jiixyj Nov 10, 2019
7d68a8c
CI: try to use FreeBSD 11.3 in another way
jiixyj Nov 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ task:
freebsd_instance:
matrix:
image: freebsd-12-0-release-amd64
image: freebsd-11-2-release-amd64
image: freebsd-11-3-stable-amd64-v20190808
install_script:
- sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf
- pkg upgrade -y

script: |
make -j 4
- pkg install -y cmake
build_script:
- pwd
- mkdir build
- cd build
- cmake .. -DCMAKE_BUILD_TYPE=Release
- cmake --build . -- -j4
test_script:
- pwd
- cd build
- ctest -VV --output-on-failure
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build*/
.vscode
76 changes: 72 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,76 @@
cmake_minimum_required(VERSION 3.9)
project(epoll-shim C)
cmake_minimum_required(VERSION 3.14)
project(epoll-shim LANGUAGES C)

set(CMAKE_C_STANDARD 99)
option(BUILD_SHARED_LIBS "build libepoll-shim as shared lib" ON)
option(ENABLE_COMPILER_WARNINGS "enable compiler warnings" OFF)

if(ENABLE_COMPILER_WARNINGS)
add_compile_options("-Wall"
"-Wextra"
"-Wconversion"
"-Wsign-conversion"
"-Wmissing-prototypes"
"-pedantic"
"-Werror=implicit-function-declaration"
"-Werror=return-type"
"-Werror=incompatible-pointer-types")
endif()

include(CTest)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_EXTENSIONS ON)

add_subdirectory(src)
add_subdirectory(test)

if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(_namespace "${PROJECT_NAME}")

if(BUILD_TESTING)
file(WRITE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
"add_library(${_namespace}::epoll-shim ALIAS epoll-shim)\n")
set(${PROJECT_NAME}_DIR "${PROJECT_BINARY_DIR}")
if(ENABLE_COMPILER_WARNINGS)
add_compile_options("-w")
endif()
add_subdirectory(test)
endif()

include(GNUInstallDirs)

set(CMAKE_INSTALL_PKGCONFIGDIR
"libdata/pkgconfig"
CACHE PATH "Installation directory for pkgconfig (.pc) files")
mark_as_advanced(CMAKE_INSTALL_PKGCONFIGDIR)
set(CMAKE_INSTALL_CMAKEBASEDIR
"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
CACHE PATH "Installation directory for CMake config (.cmake) files")
mark_as_advanced(CMAKE_INSTALL_CMAKEBASEDIR)

configure_file("${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.pc.cmakein"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc" @ONLY)
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc"
DESTINATION "${CMAKE_INSTALL_PKGCONFIGDIR}")

set(CMAKE_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/libepoll-shim")
install(TARGETS epoll-shim
EXPORT ${PROJECT_NAME}-targets
LIBRARY
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" TYPE INCLUDE)

install(EXPORT ${PROJECT_NAME}-targets
NAMESPACE "${_namespace}::"
DESTINATION "${CMAKE_INSTALL_CMAKEBASEDIR}")
if(NOT BUILD_SHARED_LIBS)
set(_deps "include(CMakeFindDependencyMacro)\n"
"set(THREADS_PREFER_PTHREAD_FLAG ON)\n"
"find_dependency(Threads)\n")
endif()
file(
WRITE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
${_deps}
"include(\"\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}-targets.cmake\")\n")
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
DESTINATION "${CMAKE_INSTALL_CMAKEBASEDIR}")
endif()
27 changes: 0 additions & 27 deletions Makefile

This file was deleted.

48 changes: 44 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,44 @@
# epoll-shim
Small epoll implementation using kqueue; includes all features needed for libinput/libevdev

This repo is used by the port `devel/libepoll-shim`
epoll-shim
==========

This is a small library that implements epoll on top of kqueue.
It has been successfully used to port libinput, libevdev, Wayland and more
software to FreeBSD: https://www.freshports.org/devel/libepoll-shim/

It may be useful for porting other software that uses epoll as well.

There are some tests inside `test/`. They should also compile under Linux and
can be used to verify proper epoll behavior.

However, this library contains some very ugly hacks and workarounds. For
example:
- When using timerfd, signalfd or eventfd, `read`, `write` and `close` are
redefined as macros to internal helper functions. This is needed as there
is some internal context that has to be free'd properly. This means that
you shouldn't create a timerfd/signalfd in one part of a program and close
it in a different part where `sys/timerfd.h` isn't included. The context
would leak. Luckily, software such as `libinput` behaves very nicely and
puts all timerfd related code in a single source file.
- There is exactly one static int reserved for fds that can be polled but are
not supported by kqueue under FreeBSD. This includes graphics or sound
devices under `/dev`. You can only have one of them throughout all epoll
instances in your process!


Installation
------------

Run the following commands to build libepoll-shim:

$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo
$ cmake --build .

To run the tests:

$ ctest --output-on-failure

To install (as root):

# cmake --build . --target install
4 changes: 4 additions & 0 deletions Version.map
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
global:
epoll_shim_close;
epoll_shim_read;
epoll_shim_write;
epoll_create;
epoll_create1;
epoll_ctl;
epoll_wait;
signalfd;
timerfd_create;
timerfd_settime;
eventfd;
eventfd_read;
eventfd_write;
local: *;
};
8 changes: 4 additions & 4 deletions src/epoll-shim.pc.in → epoll-shim.pc.cmakein
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: epoll-shim
URL: https://github.com/FreeBSDDesktop/epoll-shim
URL: https://github.com/jiixyj/epoll-shim
Description: Small epoll implementation using kqueue
Version: @PROJECT_VERSION@
Version:
Libs: -L${libdir} -lepoll-shim
Libs.private: -pthread -lrt
Cflags: -I${includedir}/libepoll-shim
32 changes: 20 additions & 12 deletions include/sys/epoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
extern "C" {
#endif

/* include the same file as musl */
#include <sys/types.h> /* IWYU pragma: keep */

#include <fcntl.h>
#include <stdint.h>
#include <sys/types.h>
#include <fcntl.h>

#if 0
#define __NEED_sigset_t
Expand All @@ -25,13 +23,15 @@ enum EPOLL_EVENTS { __EPOLL_DUMMY };
#define EPOLLPRI 0x002
#define EPOLLOUT 0x004
#define EPOLLRDNORM 0x040
#define EPOLLNVAL 0x020
#define EPOLLRDBAND 0x080
#define EPOLLWRNORM 0x100
#define EPOLLWRBAND 0x200
#define EPOLLMSG 0x400
#define EPOLLERR 0x008
#define EPOLLHUP 0x010
#define EPOLLRDHUP 0x2000
#define EPOLLEXCLUSIVE (1U<<28)
#define EPOLLWAKEUP (1U<<29)
#define EPOLLONESHOT (1U<<30)
#define EPOLLET (1U<<31)
Expand All @@ -51,22 +51,30 @@ struct epoll_event {
uint32_t events;
epoll_data_t data;
}
#if defined(__amd64__)
__attribute__((packed))
#ifdef __x86_64__
__attribute__ ((__packed__))
#endif
;

int epoll_create(int /*size*/);
int epoll_create1(int /*flags*/);
int epoll_ctl(
int /*fd*/, int /*op*/, int /*fd2*/, struct epoll_event * /*ev*/);
int epoll_wait(
int /*fd*/, struct epoll_event * /*ev*/, int /*cnt*/, int /*to*/);

int epoll_create(int);
int epoll_create1(int);
int epoll_ctl(int, int, int, struct epoll_event *);
int epoll_wait(int, struct epoll_event *, int, int);
#if 0
int epoll_pwait(int, struct epoll_event *, int, int, const sigset_t *);
#endif


#ifndef SHIM_SYS_SHIM_HELPERS
#define SHIM_SYS_SHIM_HELPERS
#include <unistd.h> /* IWYU pragma: keep */

extern int epoll_shim_close(int);
#define close epoll_shim_close
#endif


#ifdef __cplusplus
}
#endif
Expand Down
47 changes: 47 additions & 0 deletions include/sys/eventfd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef SHIM_SYS_EVENTFD_H
#define SHIM_SYS_EVENTFD_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <fcntl.h>

typedef uint64_t eventfd_t;

#define EFD_SEMAPHORE 1
#define EFD_CLOEXEC O_CLOEXEC
#define EFD_NONBLOCK O_NONBLOCK

int eventfd(unsigned int, int);
int eventfd_read(int, eventfd_t *);
int eventfd_write(int, eventfd_t);


#ifndef SHIM_SYS_SHIM_HELPERS
#define SHIM_SYS_SHIM_HELPERS
#include <unistd.h> /* IWYU pragma: keep */

extern int epoll_shim_close(int);
#define close epoll_shim_close
#endif

#ifndef SHIM_SYS_SHIM_HELPERS_READ
#define SHIM_SYS_SHIM_HELPERS_READ
extern ssize_t epoll_shim_read(int, void *, size_t);
#define read epoll_shim_read
#endif

#ifndef SHIM_SYS_SHIM_HELPERS_WRITE
#define SHIM_SYS_SHIM_HELPERS_WRITE
extern ssize_t epoll_shim_write(int, void const*, size_t);
#define write epoll_shim_write
#endif


#ifdef __cplusplus
}
#endif

#endif /* sys/eventfd.h */
12 changes: 9 additions & 3 deletions include/sys/signalfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,22 @@ struct signalfd_siginfo {
uint8_t pad[128-12*4-4*8-2];
};


#ifndef SHIM_SYS_SHIM_HELPERS
#define SHIM_SYS_SHIM_HELPERS
#include <unistd.h> /* IWYU pragma: keep */

extern int epoll_shim_close(int /*fd*/);
extern ssize_t epoll_shim_read(int /*fd*/, void * /*buf*/, size_t /*nbytes*/);
#define read epoll_shim_read
extern int epoll_shim_close(int);
#define close epoll_shim_close
#endif

#ifndef SHIM_SYS_SHIM_HELPERS_READ
#define SHIM_SYS_SHIM_HELPERS_READ
extern ssize_t epoll_shim_read(int, void *, size_t);
#define read epoll_shim_read
#endif


#ifdef __cplusplus
}
#endif
Expand Down
12 changes: 9 additions & 3 deletions include/sys/timerfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,22 @@ int timerfd_settime(int /*fd*/, int /*flags*/,
int timerfd_gettime(int, struct itimerspec *);
#endif


#ifndef SHIM_SYS_SHIM_HELPERS
#define SHIM_SYS_SHIM_HELPERS
#include <unistd.h> /* IWYU pragma: keep */

extern int epoll_shim_close(int /*fd*/);
extern ssize_t epoll_shim_read(int /*fd*/, void * /*buf*/, size_t /*nbytes*/);
#define read epoll_shim_read
extern int epoll_shim_close(int);
#define close epoll_shim_close
#endif

#ifndef SHIM_SYS_SHIM_HELPERS_READ
#define SHIM_SYS_SHIM_HELPERS_READ
extern ssize_t epoll_shim_read(int, void *, size_t);
#define read epoll_shim_read
#endif


#ifdef __cplusplus
}
#endif
Expand Down
Loading