From d50c437a65028f95aa72162004f2b61f64131a50 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 10 Feb 2016 14:26:54 +0100 Subject: [SHARED] signal.h -> fdsignal.h --- src/shared/fdsignal.c | 13 +++++ src/shared/fdsignal.h | 57 ++++++++++++++++++++++ src/shared/fdsignal.inc/eventfd.c | 74 +++++++++++++++++++++++++++++ src/shared/fdsignal.inc/pipe64.c | 88 ++++++++++++++++++++++++++++++++++ src/shared/fdsignal.inc/pipe_malloc.c | 89 +++++++++++++++++++++++++++++++++++ src/shared/signal.c | 13 ----- src/shared/signal.h | 57 ---------------------- src/shared/signal.inc/eventfd.c | 74 ----------------------------- src/shared/signal.inc/pipe64.c | 88 ---------------------------------- src/shared/signal.inc/pipe_malloc.c | 89 ----------------------------------- 10 files changed, 321 insertions(+), 321 deletions(-) create mode 100644 src/shared/fdsignal.c create mode 100644 src/shared/fdsignal.h create mode 100644 src/shared/fdsignal.inc/eventfd.c create mode 100644 src/shared/fdsignal.inc/pipe64.c create mode 100644 src/shared/fdsignal.inc/pipe_malloc.c delete mode 100644 src/shared/signal.c delete mode 100644 src/shared/signal.h delete mode 100644 src/shared/signal.inc/eventfd.c delete mode 100644 src/shared/signal.inc/pipe64.c delete mode 100644 src/shared/signal.inc/pipe_malloc.c (limited to 'src/shared') diff --git a/src/shared/fdsignal.c b/src/shared/fdsignal.c new file mode 100644 index 0000000..5e81284 --- /dev/null +++ b/src/shared/fdsignal.c @@ -0,0 +1,13 @@ +#include "fdsignal.h" + +#if defined(linux) || defined(__linux) || defined(__linux__) +//#warning "Using eventfd based signalling" +#include "fdsignal.inc/eventfd.c" +#elif __SIZEOF_INT__ == 4 && __SIZEOF_POINTER__ == 8 +//#warning "Using pointer-packing pipe based signalling" +#include "fdsignal.inc/pipe64.c" +#else +//#warning "Using fallback pipe based signalling" +#include "fdsignal.inc/pipe_malloc.c" +#endif + diff --git a/src/shared/fdsignal.h b/src/shared/fdsignal.h new file mode 100644 index 0000000..960a2a9 --- /dev/null +++ b/src/shared/fdsignal.h @@ -0,0 +1,57 @@ +#ifndef _FD_SIGNAL_H_ +#define _FD_SIGNAL_H_ + +#define SIGNAL_OK (0) +#define SIGNAL_TIMEOUT (-2) +#define SIGNAL_ERROR (-1) + +typedef struct _dnbd3_signal dnbd3_signal_t; + +/** + * Create a new signal, nonblocking. + * @return NULL on error, pointer to dnbd3_signal_t on success. + */ +dnbd3_signal_t* signal_new(); + +/** + * Create a new signal, blocking. + * @return NULL on error, pointer to dnbd3_signal_t on success. + */ +dnbd3_signal_t* signal_newBlocking(); + +/** + * Trigger the given signal, so a wait or clear call will succeed. + * @return SIGNAL_OK on success, SIGNAL_ERROR on error + */ +int signal_call(const dnbd3_signal_t* const signal); + +/** + * Wait for given signal, with an optional timeout. + * If timeout == 0, just poll once. + * If timeout < 0, wait forever. + * @return > 0 telling how many times the signal was called, + * SIGNAL_TIMEOUT if the timeout was reached, + * SIGNAL_ERROR if some error occured + */ +int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs); + +/** + * Clears any pending signals on this signal. + * @return number of signals that were pending, + * SIGNAL_ERROR if some error occured + */ +int signal_clear(const dnbd3_signal_t* const signal); + +/** + * Close the given signal. + */ +void signal_close(const dnbd3_signal_t* const signal); + +/** + * Get a file descriptor for the given signal that can be + * waited on using poll or similar. + * @return -1 if the signal is invalid + */ +int signal_getWaitFd(const dnbd3_signal_t* const signal); + +#endif diff --git a/src/shared/fdsignal.inc/eventfd.c b/src/shared/fdsignal.inc/eventfd.c new file mode 100644 index 0000000..b4d4d6e --- /dev/null +++ b/src/shared/fdsignal.inc/eventfd.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include + +/* + * Linux implementation of signals. + * Internally, eventfds are used for signalling, as they + * provide the least overhead. We don't allocate any struct + * ever, but cast the event fd+1 to dnbd3_signal_t* + * to save all the malloc() and free() calls. + */ + +dnbd3_signal_t* signal_new() +{ + // On error, eventfd() returns -1, so essentially we return NULL on error. + // (Yes, NULL doesn't have to be 0 everywhere, but cmon) + return (dnbd3_signal_t*)(intptr_t)( eventfd( 0, EFD_NONBLOCK ) + 1 ); +} + +dnbd3_signal_t* signal_newBlocking() +{ + return (dnbd3_signal_t*)(intptr_t)( eventfd( 0, 0 ) + 1 ); +} + +int signal_call(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + static uint64_t one = 1; + const int signalFd = ( (int)(intptr_t)signal ) - 1; + return write( signalFd, &one, sizeof one ) == sizeof one ? SIGNAL_OK : SIGNAL_ERROR; +} + +int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + const int signalFd = ( (int)(intptr_t)signal ) - 1; + struct pollfd ps = { + .fd = signalFd, + .events = POLLIN + }; + int ret = poll( &ps, 1, timeoutMs ); + if ( ret == 0 ) return SIGNAL_TIMEOUT; + if ( ret == -1 ) return SIGNAL_ERROR; + if ( ps.revents & ( POLLERR | POLLNVAL ) ) return SIGNAL_ERROR; + return signal_clear( signal ); +} + +int signal_clear(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + uint64_t ret; + const int signalFd = ( (int)(intptr_t)signal ) - 1; + if ( read( signalFd, &ret, sizeof ret ) != sizeof ret ) { + if ( errno == EAGAIN ) return 0; + return SIGNAL_ERROR; + } + return (int)ret; +} + +void signal_close(const dnbd3_signal_t* const signal) +{ + const int signalFd = ( (int)(intptr_t)signal ) - 1; + close( signalFd ); +} + +int signal_getWaitFd(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return -1; + const int signalFd = ( (int)(intptr_t)signal ) - 1; + return signalFd; +} + diff --git a/src/shared/fdsignal.inc/pipe64.c b/src/shared/fdsignal.inc/pipe64.c new file mode 100644 index 0000000..4f0614b --- /dev/null +++ b/src/shared/fdsignal.inc/pipe64.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include + +#define P_READ (0) +#define P_WRITE (1) + +/* + * Generic (posix) implelentation of signals, using pipes. + * 64bit version, packing two ints into a pointer. + * This version requires that you use -fno-strict-aliasing + * since it's doing evil pointer casting. + */ + +dnbd3_signal_t* signal_new() +{ + int fds[2]; + if ( pipe( fds ) == -1 ) return NULL; + fcntl( fds[P_READ], F_SETFL, O_NONBLOCK ); + fcntl( fds[P_WRITE], F_SETFL, O_NONBLOCK ); + return (dnbd3_signal_t*)*((uintptr_t*)fds); +} + +dnbd3_signal_t* signal_newBlocking() +{ + int fds[2]; + if ( pipe( fds ) == -1 ) return NULL; + return (dnbd3_signal_t*)*((uintptr_t*)fds); +} + +int signal_call(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + static char one = 1; + const int* fds = (int*)&signal; + // Write one byte on every call, so the number of bytes read will + // match the number of events + return write( fds[P_WRITE], &one, 1 ) > 0 ? SIGNAL_OK : SIGNAL_ERROR; +} + +int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + const int* fds = (int*)&signal; + struct pollfd ps = { + .fd = fds[P_READ], + .events = POLLIN + }; + int ret = poll( &ps, 1, timeoutMs ); + if ( ret == 0 ) return SIGNAL_TIMEOUT; + if ( ret == -1 ) return SIGNAL_ERROR; + if ( ps.revents & ( POLLERR | POLLNVAL ) ) return SIGNAL_ERROR; + return signal_clear( signal ); +} + +int signal_clear(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + char throwaway[100]; + const int* fds = (int*)&signal; + ssize_t ret, total = 0; + do { + ret = read( fds[P_READ], throwaway, sizeof throwaway ); + if ( ret < 0 ) { + if ( errno == EAGAIN ) return total; + return SIGNAL_ERROR; + } + total += ret; + } while ( (size_t)ret == sizeof throwaway ); + return (int)total; +} + +void signal_close(const dnbd3_signal_t* const signal) +{ + const int* fds = (int*)&signal; + close( fds[P_READ] ); + close( fds[P_WRITE] ); +} + +int signal_getWaitFd(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return -1; + const int* fds = (int*)&signal; + return fds[P_READ]; +} + diff --git a/src/shared/fdsignal.inc/pipe_malloc.c b/src/shared/fdsignal.inc/pipe_malloc.c new file mode 100644 index 0000000..b23ddcd --- /dev/null +++ b/src/shared/fdsignal.inc/pipe_malloc.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include + +struct _dnbd3_signal { + int read; + int write; +}; + +/* + * Generic (posix) implelentation of signals, using pipes. + * A struct containing both fds will be malloc()ed for each + * signal. + */ + +dnbd3_signal_t* signal_new() +{ + dnbd3_signal_t *ret = signal_newBlocking(); + if ( ret == NULL ) return NULL; + fcntl( ret->read, F_SETFL, O_NONBLOCK ); + fcntl( ret->write, F_SETFL, O_NONBLOCK ); + return ret; +} + +dnbd3_signal_t* signal_newBlocking() +{ + int fds[2]; + if ( pipe( fds ) == -1 ) return NULL; + dnbd3_signal_t* ret = malloc( sizeof(dnbd3_signal_t) ); + ret->read = fds[0]; + ret->write = fds[1]; + return ret; +} + +int signal_call(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + static char one = 1; + // Write one byte on every call, so the number of bytes read will + // match the number of events + return write( signal->write, &one, 1 ) > 0 ? SIGNAL_OK : SIGNAL_ERROR; +} + +int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + struct pollfd ps = { + .fd = signal->read, + .events = POLLIN + }; + int ret = poll( &ps, 1, timeoutMs ); + if ( ret == 0 ) return SIGNAL_TIMEOUT; + if ( ret == -1 ) return SIGNAL_ERROR; + if ( ps.revents & ( POLLERR | POLLNVAL ) ) return SIGNAL_ERROR; + return signal_clear( signal ); +} + +int signal_clear(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return SIGNAL_ERROR; + char throwaway[100]; + ssize_t ret, total = 0; + do { + ret = read( signal->read, throwaway, sizeof throwaway ); + if ( ret < 0 ) { + if ( errno == EAGAIN ) return (int)total; + return SIGNAL_ERROR; + } + total += ret; + } while ( (size_t)ret == sizeof throwaway ); + return (int)total; +} + +void signal_close(const dnbd3_signal_t* const signal) +{ + close( signal->read ); + close( signal->write ); + free( (void*)signal ); +} + +int signal_getWaitFd(const dnbd3_signal_t* const signal) +{ + if ( signal == NULL ) return -1; + return signal->read; +} + diff --git a/src/shared/signal.c b/src/shared/signal.c deleted file mode 100644 index 0107e49..0000000 --- a/src/shared/signal.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "signal.h" - -#if defined(linux) || defined(__linux) || defined(__linux__) -//#warning "Using eventfd based signalling" -#include "signal.inc/eventfd.c" -#elif __SIZEOF_INT__ == 4 && __SIZEOF_POINTER__ == 8 -//#warning "Using pointer-packing pipe based signalling" -#include "signal.inc/pipe64.c" -#else -//#warning "Using fallback pipe based signalling" -#include "signal.inc/pipe_malloc.c" -#endif - diff --git a/src/shared/signal.h b/src/shared/signal.h deleted file mode 100644 index 3eea6fb..0000000 --- a/src/shared/signal.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _SIGNAL_H_ -#define _SIGNAL_H_ - -#define SIGNAL_OK (0) -#define SIGNAL_TIMEOUT (-2) -#define SIGNAL_ERROR (-1) - -typedef struct _dnbd3_signal dnbd3_signal_t; - -/** - * Create a new signal, nonblocking. - * @return NULL on error, pointer to dnbd3_signal_t on success. - */ -dnbd3_signal_t* signal_new(); - -/** - * Create a new signal, blocking. - * @return NULL on error, pointer to dnbd3_signal_t on success. - */ -dnbd3_signal_t* signal_newBlocking(); - -/** - * Trigger the given signal, so a wait or clear call will succeed. - * @return SIGNAL_OK on success, SIGNAL_ERROR on error - */ -int signal_call(const dnbd3_signal_t* const signal); - -/** - * Wait for given signal, with an optional timeout. - * If timeout == 0, just poll once. - * If timeout < 0, wait forever. - * @return > 0 telling how many times the signal was called, - * SIGNAL_TIMEOUT if the timeout was reached, - * SIGNAL_ERROR if some error occured - */ -int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs); - -/** - * Clears any pending signals on this signal. - * @return number of signals that were pending, - * SIGNAL_ERROR if some error occured - */ -int signal_clear(const dnbd3_signal_t* const signal); - -/** - * Close the given signal. - */ -void signal_close(const dnbd3_signal_t* const signal); - -/** - * Get a file descriptor for the given signal that can be - * waited on using poll or similar. - * @return -1 if the signal is invalid - */ -int signal_getWaitFd(const dnbd3_signal_t* const signal); - -#endif diff --git a/src/shared/signal.inc/eventfd.c b/src/shared/signal.inc/eventfd.c deleted file mode 100644 index b4d4d6e..0000000 --- a/src/shared/signal.inc/eventfd.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include -#include -#include - -/* - * Linux implementation of signals. - * Internally, eventfds are used for signalling, as they - * provide the least overhead. We don't allocate any struct - * ever, but cast the event fd+1 to dnbd3_signal_t* - * to save all the malloc() and free() calls. - */ - -dnbd3_signal_t* signal_new() -{ - // On error, eventfd() returns -1, so essentially we return NULL on error. - // (Yes, NULL doesn't have to be 0 everywhere, but cmon) - return (dnbd3_signal_t*)(intptr_t)( eventfd( 0, EFD_NONBLOCK ) + 1 ); -} - -dnbd3_signal_t* signal_newBlocking() -{ - return (dnbd3_signal_t*)(intptr_t)( eventfd( 0, 0 ) + 1 ); -} - -int signal_call(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - static uint64_t one = 1; - const int signalFd = ( (int)(intptr_t)signal ) - 1; - return write( signalFd, &one, sizeof one ) == sizeof one ? SIGNAL_OK : SIGNAL_ERROR; -} - -int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - const int signalFd = ( (int)(intptr_t)signal ) - 1; - struct pollfd ps = { - .fd = signalFd, - .events = POLLIN - }; - int ret = poll( &ps, 1, timeoutMs ); - if ( ret == 0 ) return SIGNAL_TIMEOUT; - if ( ret == -1 ) return SIGNAL_ERROR; - if ( ps.revents & ( POLLERR | POLLNVAL ) ) return SIGNAL_ERROR; - return signal_clear( signal ); -} - -int signal_clear(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - uint64_t ret; - const int signalFd = ( (int)(intptr_t)signal ) - 1; - if ( read( signalFd, &ret, sizeof ret ) != sizeof ret ) { - if ( errno == EAGAIN ) return 0; - return SIGNAL_ERROR; - } - return (int)ret; -} - -void signal_close(const dnbd3_signal_t* const signal) -{ - const int signalFd = ( (int)(intptr_t)signal ) - 1; - close( signalFd ); -} - -int signal_getWaitFd(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return -1; - const int signalFd = ( (int)(intptr_t)signal ) - 1; - return signalFd; -} - diff --git a/src/shared/signal.inc/pipe64.c b/src/shared/signal.inc/pipe64.c deleted file mode 100644 index 4f0614b..0000000 --- a/src/shared/signal.inc/pipe64.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include -#include -#include - -#define P_READ (0) -#define P_WRITE (1) - -/* - * Generic (posix) implelentation of signals, using pipes. - * 64bit version, packing two ints into a pointer. - * This version requires that you use -fno-strict-aliasing - * since it's doing evil pointer casting. - */ - -dnbd3_signal_t* signal_new() -{ - int fds[2]; - if ( pipe( fds ) == -1 ) return NULL; - fcntl( fds[P_READ], F_SETFL, O_NONBLOCK ); - fcntl( fds[P_WRITE], F_SETFL, O_NONBLOCK ); - return (dnbd3_signal_t*)*((uintptr_t*)fds); -} - -dnbd3_signal_t* signal_newBlocking() -{ - int fds[2]; - if ( pipe( fds ) == -1 ) return NULL; - return (dnbd3_signal_t*)*((uintptr_t*)fds); -} - -int signal_call(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - static char one = 1; - const int* fds = (int*)&signal; - // Write one byte on every call, so the number of bytes read will - // match the number of events - return write( fds[P_WRITE], &one, 1 ) > 0 ? SIGNAL_OK : SIGNAL_ERROR; -} - -int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - const int* fds = (int*)&signal; - struct pollfd ps = { - .fd = fds[P_READ], - .events = POLLIN - }; - int ret = poll( &ps, 1, timeoutMs ); - if ( ret == 0 ) return SIGNAL_TIMEOUT; - if ( ret == -1 ) return SIGNAL_ERROR; - if ( ps.revents & ( POLLERR | POLLNVAL ) ) return SIGNAL_ERROR; - return signal_clear( signal ); -} - -int signal_clear(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - char throwaway[100]; - const int* fds = (int*)&signal; - ssize_t ret, total = 0; - do { - ret = read( fds[P_READ], throwaway, sizeof throwaway ); - if ( ret < 0 ) { - if ( errno == EAGAIN ) return total; - return SIGNAL_ERROR; - } - total += ret; - } while ( (size_t)ret == sizeof throwaway ); - return (int)total; -} - -void signal_close(const dnbd3_signal_t* const signal) -{ - const int* fds = (int*)&signal; - close( fds[P_READ] ); - close( fds[P_WRITE] ); -} - -int signal_getWaitFd(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return -1; - const int* fds = (int*)&signal; - return fds[P_READ]; -} - diff --git a/src/shared/signal.inc/pipe_malloc.c b/src/shared/signal.inc/pipe_malloc.c deleted file mode 100644 index b23ddcd..0000000 --- a/src/shared/signal.inc/pipe_malloc.c +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include -#include -#include - -struct _dnbd3_signal { - int read; - int write; -}; - -/* - * Generic (posix) implelentation of signals, using pipes. - * A struct containing both fds will be malloc()ed for each - * signal. - */ - -dnbd3_signal_t* signal_new() -{ - dnbd3_signal_t *ret = signal_newBlocking(); - if ( ret == NULL ) return NULL; - fcntl( ret->read, F_SETFL, O_NONBLOCK ); - fcntl( ret->write, F_SETFL, O_NONBLOCK ); - return ret; -} - -dnbd3_signal_t* signal_newBlocking() -{ - int fds[2]; - if ( pipe( fds ) == -1 ) return NULL; - dnbd3_signal_t* ret = malloc( sizeof(dnbd3_signal_t) ); - ret->read = fds[0]; - ret->write = fds[1]; - return ret; -} - -int signal_call(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - static char one = 1; - // Write one byte on every call, so the number of bytes read will - // match the number of events - return write( signal->write, &one, 1 ) > 0 ? SIGNAL_OK : SIGNAL_ERROR; -} - -int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - struct pollfd ps = { - .fd = signal->read, - .events = POLLIN - }; - int ret = poll( &ps, 1, timeoutMs ); - if ( ret == 0 ) return SIGNAL_TIMEOUT; - if ( ret == -1 ) return SIGNAL_ERROR; - if ( ps.revents & ( POLLERR | POLLNVAL ) ) return SIGNAL_ERROR; - return signal_clear( signal ); -} - -int signal_clear(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return SIGNAL_ERROR; - char throwaway[100]; - ssize_t ret, total = 0; - do { - ret = read( signal->read, throwaway, sizeof throwaway ); - if ( ret < 0 ) { - if ( errno == EAGAIN ) return (int)total; - return SIGNAL_ERROR; - } - total += ret; - } while ( (size_t)ret == sizeof throwaway ); - return (int)total; -} - -void signal_close(const dnbd3_signal_t* const signal) -{ - close( signal->read ); - close( signal->write ); - free( (void*)signal ); -} - -int signal_getWaitFd(const dnbd3_signal_t* const signal) -{ - if ( signal == NULL ) return -1; - return signal->read; -} - -- cgit v1.2.3-55-g7522