Signed-off-by: Angus Salkeld asalkeld@redhat.com --- configure.ac | 107 ++++++++---- include/os_base.h | 2 + include/qb/qbipcc.h | 2 + include/qb/qbutil.h | 2 + lib/Makefile.am | 18 ++- lib/atomic_gcc.c | 88 ---------- lib/atomic_lock.c | 214 ----------------------- lib/ipc_int.h | 8 +- lib/ipc_posix_mq.c | 2 - lib/ipc_sysv_mq.c | 4 + lib/ipc_us.c | 19 ++- lib/ipcc.c | 11 ++ lib/ipcs.c | 19 ++- lib/log.c | 6 +- lib/log_dcs.c | 4 +- lib/log_syslog.c | 3 + lib/loop_poll.c | 9 +- lib/ringbuffer.c | 18 +- lib/ringbuffer_int.h | 6 + lib/unix.c | 465 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/util.c | 218 +----------------------- lib/util_int.h | 11 +- tests/Makefile.am | 2 +- 23 files changed, 640 insertions(+), 598 deletions(-) delete mode 100644 lib/atomic_gcc.c delete mode 100644 lib/atomic_lock.c create mode 100644 lib/unix.c
diff --git a/configure.ac b/configure.ac index e46dc01..fd158aa 100644 --- a/configure.ac +++ b/configure.ac @@ -58,6 +58,7 @@ AC_PROG_CXX AC_PROG_AWK AC_PROG_CC AC_PROG_CPP +AM_PROG_CC_C_O AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET @@ -115,10 +116,11 @@ fi AC_HEADER_STDC AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h netinet/in.h stdint.h \ - time.h sys/time.h stdlib.h string.h strings.h sys/types.h sys/stat.h \ - sys/param.h sys/socket.h sys/time.h sys/timerfd.h sys/epoll.h \ - sys/sockio.h sys/un.h syslog.h errno.h unistd.h]) +AC_CHECK_HEADERS([arpa/inet.h link.h fcntl.h inttypes.h limits.h netinet/in.h stdint.h \ + dlfcn.h time.h sys/time.h stdlib.h string.h strings.h sys/types.h sys/stat.h \ + sys/param.h sys/socket.h sys/time.h sys/timerfd.h sys/poll.h sys/epoll.h sys/uio.h \ + sys/sockio.h sys/un.h sys/resource.h syslog.h errno.h unistd.h sys/mman.h \ + sys/sem.h sys/ipc.h sys/msg.h mqueue.h])
# Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UID_T @@ -141,19 +143,19 @@ AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_MMAP AC_FUNC_REALLOC -AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday localtime_r memset munmap \ - socket strchr strdup strerror strrchr strstr \ - epoll_create epoll_create1 \ +AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday localtime localtime_r \ + memset munmap socket strchr strrchr strchrnul strdup strerror strstr \ + poll epoll_create epoll_create1 random rand getrlimit sysconf \ pthread_spin_lock timerfd_create pthread_setschedparam \ sched_get_priority_max sched_setscheduler])
## local defines PACKAGE_FEATURES=""
-if test $ac_cv_func_timerfd_create = yes; then +if test x$ac_cv_func_timerfd_create = xyes; then PACKAGE_FEATURES="$PACKAGE_FEATURES timerfd" fi -if test $ac_cv_func_epoll_create = yes; then +if test x$ac_cv_func_epoll_create = xyes; then PACKAGE_FEATURES="$PACKAGE_FEATURES epoll" fi
@@ -207,6 +209,8 @@ fi # THIS SECTION MUST DIE! CP=cp LIB_RT=-lrt +supports_sysv_mq="yes" +supports_posix_mq="yes" AC_MSG_CHECKING([for os in ${host_os}]) case "$host_os" in *linux*) @@ -219,6 +223,8 @@ case "$host_os" in [Compiling for Darwin platform]) CP=rsync LIB_RT= + supports_sysv_mq="no" + supports_posix_mq="no" ac_cv_link_attribute_section=no dnl Attribute section appears to work here but fails later with: dnl cc1: error in backend: Global variable 'descriptor.4902' has an invalid section specifier '__verbose': mach-o section specifier requires a segment and section separated by a comma @@ -245,7 +251,7 @@ case "$host_os" in [Compiling for FreeBSD >= 8 platform]) ;; esac - AC_MSG_RESULT([BSB]) + AC_MSG_RESULT([BSD]) ;; *solaris*) AC_DEFINE_UNQUOTED([QB_SOLARIS], [1], @@ -262,42 +268,50 @@ case "$host_os" in ;; esac
-# Check for atomic support -gcc_has_builtin_atomic_operations=no -if test x"$GCC" = xyes; then - AC_MSG_CHECKING([whether GCC supports build-in atomic intrinsics]) - AC_TRY_LINK([], - [int i; - __sync_synchronize (); - __sync_bool_compare_and_swap (&i, 0, 1); - __sync_fetch_and_add (&i, 1); - ], - [gcc_has_builtin_atomic_operations=yes], - [gcc_has_builtin_atomic_operations=no]) - - AC_MSG_RESULT($gcc_has_builtin_atomic_operations) - if test $gcc_has_builtin_atomic_operations = yes; then +AC_MSG_CHECKING([whether GCC supports build-in atomic intrinsics]) +if test -z "$gcc_has_builtin_atomic_operations"; then + gcc_has_builtin_atomic_operations=no + if test x"$GCC" = xyes && test x$have_mingw != xyes; then + AC_TRY_LINK([], + [int i; + __sync_synchronize (); + __sync_bool_compare_and_swap (&i, 0, 1); + __sync_fetch_and_add (&i, 1); + ], + [gcc_has_builtin_atomic_operations=yes], + [gcc_has_builtin_atomic_operations=no]) + fi +fi +AC_MSG_RESULT($gcc_has_builtin_atomic_operations) +AM_CONDITIONAL(HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS, + [test "x$gcc_has_builtin_atomic_operations" = xyes]) + +if test "x$gcc_has_builtin_atomic_operations" = xyes; then + AC_DEFINE_UNQUOTED(HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS, 1, + [have builtin atomic operations]) +fi + +AC_MSG_CHECKING([whether atomics need memory barrier]) +if test -n "$ac_cv_atomic_need_memory_barrier"; then + memory_barrier_needed=$ac_cv_atomic_need_memory_barrier +else + if test x$gcc_has_builtin_atomic_operations = xyes; then memory_barrier_needed=yes - PACKAGE_FEATURES="$PACKAGE_FEATURES gcc__sync" + PACKAGE_FEATURES="$PACKAGE_FEATURES gcc__sync" else - if test $nongcc_memory_barrier_needed = yes; then - memory_barrier_needed=yes - fi + memory_barrier_needed=$nongcc_memory_barrier_needed AC_MSG_WARN([-----------------------------]) AC_MSG_WARN([You have gcc but not __sync_bool_compare_and_swap]) AC_MSG_WARN([try CFLAGS="-march=<your arch> -mtune=native" ./configure]) AC_MSG_WARN([-----------------------------]) fi fi +AC_MSG_RESULT($memory_barrier_needed)
if test x"$memory_barrier_needed" != xno; then AC_DEFINE_UNQUOTED(QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED, 1, [need atomic memory barrier]) - fi - -AM_CONDITIONAL(HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS, - [test $gcc_has_builtin_atomic_operations = yes]) - +fi
LINT_FLAGS="-weak -unrecog +posixlib +ignoresigns -fcnuse \ -badflag -D__gnuc_va_list=va_list -D__attribute(x)= \ @@ -393,12 +407,33 @@ else COVERAGE_LDFLAGS="" fi
- if test "x${enable_slow_tests}" = xyes ; then AC_DEFINE([HAVE_SLOW_TESTS], 1,[have slow tests]) AC_MSG_NOTICE([Enabling Slow tests]) fi -AM_CONDITIONAL(HAVE_SLOW_TESTS, [test "x$enable_slow_tests" = xyes]) +AM_CONDITIONAL(HAVE_SLOW_TESTS, [test "x${enable_slow_tests}" = xyes]) + +if test -n "$ac_cv_supports_sysv_mq"; then + supports_sysv_mq=$ac_cv_supports_sysv_mq +fi +if test "x${supports_sysv_mq}" = xyes ; then + AC_DEFINE([HAVE_SYSV_MQ], [1], + [have sysv message queues]) + PACKAGE_FEATURES="$PACKAGE_FEATURES sysv_mq" + AC_MSG_NOTICE([Enabling SYSV Message Queues]) +fi +AM_CONDITIONAL(HAVE_SYSV_MQ, [test "x${supports_sysv_mq}" = xyes]) + +if test -n "$ac_cv_supports_posix_mq"; then + supports_posix_mq=$ac_cv_supports_posix_mq +fi +if test "x${supports_posix_mq}" = xyes ; then + AC_DEFINE([HAVE_POSIX_MQ], [1], + [have posix message queues]) + PACKAGE_FEATURES="$PACKAGE_FEATURES posix_mq" + AC_MSG_NOTICE([Enabling POSIX Message Queues]) +fi +AM_CONDITIONAL(HAVE_POSIX_MQ, [test "x${supports_posix_mq}" = xyes])
AM_CONDITIONAL(USE_TIMERFD, [test "x$ac_cv_func_timerfd_create" = xyes]) diff --git a/include/os_base.h b/include/os_base.h index c034d25..8c9b039 100644 --- a/include/os_base.h +++ b/include/os_base.h @@ -37,7 +37,9 @@ #include <sys/types.h> #endif /* HAVE_SYS_TYPES_H */
+#ifdef HAVE_SYS_UIO_H #include <sys/uio.h> +#endif /* HAVE_SYS_UIO_H */
#ifdef HAVE_STDINT_H #include <stdint.h> diff --git a/include/qb/qbipcc.h b/include/qb/qbipcc.h index acecac9..6227e0f 100644 --- a/include/qb/qbipcc.h +++ b/include/qb/qbipcc.h @@ -27,6 +27,8 @@ extern "C" { #endif /* *INDENT-ON* */
+#include <qb/qbconfig.h> + #include <pthread.h> #include <sys/poll.h> #include <sys/socket.h> diff --git a/include/qb/qbutil.h b/include/qb/qbutil.h index fcc8550..2b450e9 100644 --- a/include/qb/qbutil.h +++ b/include/qb/qbutil.h @@ -26,6 +26,8 @@ extern "C" { #endif /* *INDENT-ON* */
+#include <pthread.h> + #include <stdint.h> #ifndef S_SPLINT_S #include <unistd.h> diff --git a/lib/Makefile.am b/lib/Makefile.am index 45d45bd..5210055 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -40,21 +40,25 @@ libqb_la_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include libqb_la_LDFLAGS = -version-info 7:0:7 source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c array.c \ loop.c loop_poll.c loop_job.c \ - ipcc.c ipcs.c ipc_posix_mq.c ipc_sysv_mq.c ipc_shm.c ipc_us.c \ + ipcc.c ipcs.c ipc_shm.c ipc_us.c \ log.c log_thread.c log_blackbox.c log_file.c \ log_syslog.c log_dcs.c log_format.c \ map.c skiplist.c hashtable.c trie.c
-libqb_la_SOURCES = $(source_to_lint) +libqb_la_SOURCES = $(source_to_lint) unix.c + +if HAVE_SYSV_MQ + libqb_la_SOURCES+=ipc_sysv_mq.c +endif + +if HAVE_POSIX_MQ + libqb_la_SOURCES+=ipc_posix_mq.c +endif + if USE_TIMERFD else libqb_la_SOURCES+=loop_timerlist.c endif -if HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS -libqb_la_SOURCES+=atomic_gcc.c -else -libqb_la_SOURCES+=atomic_lock.c -endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libqb.pc
diff --git a/lib/atomic_gcc.c b/lib/atomic_gcc.c deleted file mode 100644 index 80499cb..0000000 --- a/lib/atomic_gcc.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2009 Hiroyuki Ikezoe - * - * This file is part of libqb. - * - * libqb is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * libqb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libqb. If not, see http://www.gnu.org/licenses/. - */ - -/* - * Copied from the glib code base (glib/gatomic-gcc.c) and namespaced - * for libqb. - */ - -#include "config.h" -#include <qb/qbatomic.h> - -void -qb_atomic_init(void) -{ -} - -int32_t -qb_atomic_int_exchange_and_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t val) -{ - return __sync_fetch_and_add(atomic, val); -} - -void -qb_atomic_int_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t val) -{ - __sync_fetch_and_add(atomic, val); -} - -int32_t -qb_atomic_int_compare_and_exchange(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t oldval, int32_t newval) -{ - return __sync_bool_compare_and_swap(atomic, oldval, newval); -} - -int32_t -qb_atomic_pointer_compare_and_exchange(volatile void *QB_GNUC_MAY_ALIAS * - atomic, void *oldval, void *newval) -{ - return __sync_bool_compare_and_swap(atomic, oldval, newval); -} - -int32_t -(qb_atomic_int_get) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic) -{ - __sync_synchronize(); - return *atomic; -} - -void -(qb_atomic_int_set) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t newval) -{ - *atomic = newval; - __sync_synchronize(); -} - -void * -(qb_atomic_pointer_get) (volatile void *QB_GNUC_MAY_ALIAS * atomic) -{ - __sync_synchronize(); - return (void *)*atomic; -} - -void -(qb_atomic_pointer_set) (volatile void *QB_GNUC_MAY_ALIAS * atomic, - void *newval) -{ - *atomic = newval; - __sync_synchronize(); -} \ No newline at end of file diff --git a/lib/atomic_lock.c b/lib/atomic_lock.c deleted file mode 100644 index 0446b1b..0000000 --- a/lib/atomic_lock.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2003 Sebastian Wilhelmi - * Copyright (C) 2007 Nokia Corporation - * - * This file is part of libqb. - * - * libqb is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * libqb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with libqb. If not, see http://www.gnu.org/licenses/. - */ - -/* - * Copied basic locking backup method from the glib code base - * (glib/gatomic.c) and namespaced for libqb. - */ - -#include "os_base.h" - -#include <qb/qbatomic.h> -#include <qb/qbutil.h> - -#ifdef QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED -#if defined (QB_ARCH_SPARC) -#define QB_ATOMIC_MEMORY_BARRIER \ - __asm__ __volatile__ ("membar #LoadLoad | #LoadStore" \ - " | #StoreLoad | #StoreStore" : : : "memory") -#elif defined (QB_ARCH_ALPHA) -#define QB_ATOMIC_MEMORY_BARRIER __asm__ ("mb" : : : "memory") -#elif defined (QB_ARCH_POWERPC) -#define QB_ATOMIC_MEMORY_BARRIER __asm__ ("sync" : : : "memory") -#elif defined (QB_ARCH_IA64) -#define QB_ATOMIC_MEMORY_BARRIER __sync_synchronize () -#endif /* arch */ -#endif /* QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ - -/* We have to use the slow, but safe locking method */ -static qb_thread_lock_t *qb_atomic_mutex = NULL; - -void -qb_atomic_init(void) -{ - if (qb_atomic_mutex == NULL) { - qb_atomic_mutex = qb_thread_lock_create(QB_THREAD_LOCK_SHORT); - } - assert(qb_atomic_mutex); -} - -int32_t -qb_atomic_int_exchange_and_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t val) -{ - int32_t result; - - qb_thread_lock(qb_atomic_mutex); - result = *atomic; - *atomic += val; - qb_thread_unlock(qb_atomic_mutex); - - return result; -} - -void -qb_atomic_int_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t val) -{ - qb_thread_lock(qb_atomic_mutex); - *atomic += val; - qb_thread_unlock(qb_atomic_mutex); -} - -int32_t -qb_atomic_int_compare_and_exchange(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t oldval, int32_t newval) -{ - int32_t result; - - qb_thread_lock(qb_atomic_mutex); - if (*atomic == oldval) { - result = QB_TRUE; - *atomic = newval; - } else { - result = QB_FALSE; - } - qb_thread_unlock(qb_atomic_mutex); - - return result; -} - -int32_t -qb_atomic_pointer_compare_and_exchange(volatile void *QB_GNUC_MAY_ALIAS * - atomic, void *oldval, void *newval) -{ - int32_t result; - - qb_thread_lock(qb_atomic_mutex); - if (*atomic == oldval) { - result = QB_TRUE; - *atomic = newval; - } else { - result = QB_FALSE; - } - qb_thread_unlock(qb_atomic_mutex); - - return result; -} - -#ifdef QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED - -int32_t(qb_atomic_int_get) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic) { - int32_t result; - - qb_thread_lock(qb_atomic_mutex); - result = *atomic; - qb_thread_unlock(qb_atomic_mutex); - - return result; -} - -void -(qb_atomic_int_set) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t newval) -{ - qb_thread_lock(qb_atomic_mutex); - *atomic = newval; - qb_thread_unlock(qb_atomic_mutex); -} - -void * -(qb_atomic_pointer_get) (volatile void *QB_GNUC_MAY_ALIAS * atomic) -{ - void *result; - - qb_thread_lock(qb_atomic_mutex); - result = *atomic; - qb_thread_unlock(qb_atomic_mutex); - - return result; -} - -void -(qb_atomic_pointer_set) (volatile void *QB_GNUC_MAY_ALIAS * atomic, - void *newval) -{ - qb_thread_lock(qb_atomic_mutex); - *atomic = newval; - qb_thread_unlock(qb_atomic_mutex); -} - -int32_t -(qb_atomic_int_get) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic) -{ - QB_ATOMIC_MEMORY_BARRIER; - return *atomic; -} - -void -(qb_atomic_int_set) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t newval) -{ - *atomic = newval; - QB_ATOMIC_MEMORY_BARRIER; -} - -void * -(qb_atomic_pointer_get) (volatile void *QB_GNUC_MAY_ALIAS * atomic) -{ - QB_ATOMIC_MEMORY_BARRIER; - return *atomic; -} - -void -(qb_atomic_pointer_set) (volatile void *QB_GNUC_MAY_ALIAS * atomic, - void *newval) -{ - *atomic = newval; - QB_ATOMIC_MEMORY_BARRIER; -} - -#endif /* QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ -#ifndef QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED - -int32_t -(qb_atomic_int_get) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic) -{ - return qb_atomic_int_get(atomic); -} - -void -(qb_atomic_int_set) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic, - int32_t newval) -{ - qb_atomic_int_set(atomic, newval); -} - -void * -(qb_atomic_pointer_get) (volatile void *QB_GNUC_MAY_ALIAS * atomic) { - return qb_atomic_pointer_get(atomic); -} - -void -(qb_atomic_pointer_set) (volatile void *QB_GNUC_MAY_ALIAS * atomic, - void *newval) -{ - qb_atomic_pointer_set(atomic, newval); -} -#endif /* QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ diff --git a/lib/ipc_int.h b/lib/ipc_int.h index c19be90..c4eb082 100644 --- a/lib/ipc_int.h +++ b/lib/ipc_int.h @@ -25,9 +25,9 @@ #include "os_base.h"
#include <dirent.h> -#ifndef QB_DARWIN -# include <mqueue.h> -#endif +#ifdef HAVE_MQUEUE_H +#include <mqueue.h> +#endif /* HAVE_MQUEUE_H */ #include <qb/qblist.h> #include <qb/qbloop.h> #include <qb/qbipcc.h> @@ -77,7 +77,7 @@ struct qb_ipc_one_way { void* shared_data; char shared_file_name[NAME_MAX]; } us; -#ifndef QB_DARWIN +#ifdef HAVE_MQUEUE_H struct { mqd_t q; char name[NAME_MAX]; diff --git a/lib/ipc_posix_mq.c b/lib/ipc_posix_mq.c index d9c5372..068fad3 100644 --- a/lib/ipc_posix_mq.c +++ b/lib/ipc_posix_mq.c @@ -19,7 +19,6 @@ * along with libqb. If not, see http://www.gnu.org/licenses/. */ #include "os_base.h" -#ifndef QB_DARWIN
#include <mqueue.h> #include <sys/resource.h> @@ -417,4 +416,3 @@ qb_ipcs_pmq_init(struct qb_ipcs_service *s) s->needs_sock_for_poll = QB_TRUE; #endif } -#endif diff --git a/lib/ipc_sysv_mq.c b/lib/ipc_sysv_mq.c index f317539..f077617 100644 --- a/lib/ipc_sysv_mq.c +++ b/lib/ipc_sysv_mq.c @@ -20,8 +20,12 @@ */ #include "os_base.h"
+#ifdef HAVE_SYS_IPC_H #include <sys/ipc.h> +#endif +#ifdef HAVE_SYS_MSG_H #include <sys/msg.h> +#endif
#include <qb/qbdefs.h> #include <qb/qbloop.h> diff --git a/lib/ipc_us.c b/lib/ipc_us.c index 5ed0ced..3f11dfe 100644 --- a/lib/ipc_us.c +++ b/lib/ipc_us.c @@ -19,6 +19,7 @@ * along with libqb. If not, see http://www.gnu.org/licenses/. */ #include "os_base.h" + #if defined(HAVE_GETPEERUCRED) #include <ucred.h> #endif @@ -29,7 +30,9 @@ #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif +#ifdef HAVE_SYS_MMAN_H #include <sys/mman.h> +#endif
#include <qb/qbatomic.h> #include <qb/qbipcs.h> @@ -267,7 +270,7 @@ qb_ipcc_us_sock_connect(const char *socket_name, int32_t * sock_pt) #ifdef SO_NOSIGPIPE socket_nosigpipe(request_fd); #endif /* SO_NOSIGPIPE */ - res = qb_util_fd_nonblock_cloexec_set(request_fd); + res = qb_sys_fd_nonblock_cloexec_set(request_fd); if (res < 0) { goto error_connect; } @@ -371,8 +374,8 @@ qb_ipcc_us_connect(struct qb_ipcc_connection *c, c->response.u.us.sock = c->setup.u.us.sock; c->setup.u.us.sock = -1;
- fd_hdr = qb_util_mmap_file_open(path, r->request, - sizeof(struct ipc_us_control), O_RDWR); + fd_hdr = qb_sys_mmap_file_open(path, r->request, + sizeof(struct ipc_us_control), O_RDWR); if (fd_hdr < 0) { res = -errno; qb_util_perror(LOG_ERR, "couldn't open file for mmap"); @@ -444,7 +447,7 @@ qb_ipcs_us_publish(struct qb_ipcs_service * s) return res; }
- res = qb_util_fd_nonblock_cloexec_set(s->server_sock); + res = qb_sys_fd_nonblock_cloexec_set(s->server_sock); if (res < 0) { goto error_close; } @@ -779,7 +782,7 @@ retry_accept: return 0; }
- res = qb_util_fd_nonblock_cloexec_set(new_fd); + res = qb_sys_fd_nonblock_cloexec_set(new_fd); if (res < 0) { close(new_fd); /* This is an error, but -1 would indicate disconnect @@ -822,9 +825,9 @@ qb_ipcs_us_connect(struct qb_ipcs_service *s, snprintf(r->request, NAME_MAX, "qb-%s-control-%d-%d", s->name, c->pid, c->setup.u.us.sock);
- fd_hdr = qb_util_mmap_file_open(path, r->request, - sizeof(struct ipc_us_control), - O_CREAT | O_TRUNC | O_RDWR); + fd_hdr = qb_sys_mmap_file_open(path, r->request, + sizeof(struct ipc_us_control), + O_CREAT | O_TRUNC | O_RDWR); if (fd_hdr < 0) { res = -errno; qb_util_perror(LOG_ERR, "couldn't create file for mmap"); diff --git a/lib/ipcc.c b/lib/ipcc.c index 93fd896..ca1309a 100644 --- a/lib/ipcc.c +++ b/lib/ipcc.c @@ -20,6 +20,9 @@ */ #include "os_base.h"
+#ifdef HAVE_MQUEUE_H +#include <mqueue.h> +#endif /* HAVE_MQUEUE_H */ #include "ipc_int.h" #include "util_int.h" #include <qb/qbdefs.h> @@ -59,10 +62,18 @@ qb_ipcc_connect(const char *name, size_t max_msg_size) res = qb_ipcc_shm_connect(c, &response); break; case QB_IPC_POSIX_MQ: +#ifdef HAVE_POSIX_MQ res = qb_ipcc_pmq_connect(c, &response); +#else + res = -ENOTSUP; +#endif /* HAVE_POSIX_MQ */ break; case QB_IPC_SYSV_MQ: +#ifdef HAVE_SYSV_MQ res = qb_ipcc_smq_connect(c, &response); +#else + res = -ENOTSUP; +#endif /* HAVE_SYSV_MQ */ break; case QB_IPC_SOCKET: res = qb_ipcc_us_connect(c, &response); diff --git a/lib/ipcs.c b/lib/ipcs.c index d11c19b..569fd45 100644 --- a/lib/ipcs.c +++ b/lib/ipcs.c @@ -78,8 +78,7 @@ qb_ipcs_poll_handlers_set(struct qb_ipcs_service *s, int32_t qb_ipcs_run(struct qb_ipcs_service *s) { - int32_t res; - + int32_t res = 0;
if (s->poll_fns.dispatch_add == NULL || s->poll_fns.dispatch_mod == NULL || @@ -95,15 +94,27 @@ qb_ipcs_run(struct qb_ipcs_service *s) qb_ipcs_shm_init((struct qb_ipcs_service *)s); break; case QB_IPC_POSIX_MQ: +#ifdef HAVE_POSIX_MQ qb_ipcs_pmq_init((struct qb_ipcs_service *)s); +#else + res = -ENOTSUP; +#endif /* HAVE_POSIX_MQ */ break; case QB_IPC_SYSV_MQ: +#ifdef HAVE_SYSV_MQ qb_ipcs_smq_init((struct qb_ipcs_service *)s); +#else + res = -ENOTSUP; +#endif /* HAVE_SYSV_MQ */ break; default: res = -EINVAL; break; } + if (res < 0) { + qb_ipcs_unref(s); + return res; + } res = qb_ipcs_us_publish(s); if (res < 0) { (void)qb_ipcs_us_withdraw(s); @@ -121,12 +132,12 @@ _modify_dispatch_descriptor_(struct qb_ipcs_connection *c)
if (c->service->type == QB_IPC_POSIX_MQ && !c->service->needs_sock_for_poll) { -#ifndef QB_DARWIN +#ifdef HAVE_MQUEUE_H return disp_mod(c->service->poll_priority, (int32_t) c->request.u.pmq.q, c->poll_events, c, qb_ipcs_dispatch_service_request); -#endif +#endif /* HAVE_MQUEUE_H */ } else if (c->service->type == QB_IPC_SOCKET) { return disp_mod(c->service->poll_priority, c->event.u.us.sock, diff --git a/lib/log.c b/lib/log.c index 50fa58b..1002953 100644 --- a/lib/log.c +++ b/lib/log.c @@ -20,12 +20,14 @@ */ #include "os_base.h" #include <ctype.h> -#ifndef QB_DARWIN +#ifdef HAVE_LINK_H #include <link.h> -#endif +#endif /* HAVE_LINK_H */ #include <stdarg.h> #include <pthread.h> +#ifdef HAVE_DLFCN_H #include <dlfcn.h> +#endif /* HAVE_DLFCN_H */ #include <stdarg.h>
#include <qb/qbdefs.h> diff --git a/lib/log_dcs.c b/lib/log_dcs.c index 9b8db43..64a8bc4 100644 --- a/lib/log_dcs.c +++ b/lib/log_dcs.c @@ -20,8 +20,8 @@ */ #include "os_base.h" #include <ctype.h> -#ifndef QB_DARWIN -# include <link.h> +#ifdef HAVE_LINK_H +#include <link.h> #endif #include <stdarg.h>
diff --git a/lib/log_syslog.c b/lib/log_syslog.c index 85b51c0..6bb6182 100644 --- a/lib/log_syslog.c +++ b/lib/log_syslog.c @@ -19,7 +19,10 @@ * along with libqb. If not, see http://www.gnu.org/licenses/. */ #include "os_base.h" + +#ifdef HAVE_SYSLOG_H #include <syslog.h> +#endif /* HAVE_SYSLOG_H */ #include "log_int.h"
static void diff --git a/lib/loop_poll.c b/lib/loop_poll.c index f7b59fc..164286f 100644 --- a/lib/loop_poll.c +++ b/lib/loop_poll.c @@ -20,11 +20,16 @@ */ #include "os_base.h"
+#ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> +#endif #ifdef HAVE_SYS_EPOLL_H #include <sys/epoll.h> #endif /* HAVE_SYS_EPOLL_H */ + +#ifdef HAVE_SYS_POLL_H #include <sys/poll.h> +#endif /* HAVE_SYS_POLL_H */ #ifndef S_SPLINT_S #ifdef HAVE_SYS_TIMERFD_H #include <sys/timerfd.h> @@ -924,8 +929,8 @@ qb_loop_signals_create(struct qb_loop *l) qb_util_perror(LOG_ERR, "Can't light pipe"); goto error_exit; } - (void)qb_util_fd_nonblock_cloexec_set(pipe_fds[0]); - (void)qb_util_fd_nonblock_cloexec_set(pipe_fds[1]); + (void)qb_sys_fd_nonblock_cloexec_set(pipe_fds[0]); + (void)qb_sys_fd_nonblock_cloexec_set(pipe_fds[1]);
res = _poll_add_(l, QB_LOOP_HIGH, pipe_fds[0], POLLIN, NULL, &pe); diff --git a/lib/ringbuffer.c b/lib/ringbuffer.c index e767077..c983bf6 100644 --- a/lib/ringbuffer.c +++ b/lib/ringbuffer.c @@ -120,8 +120,8 @@ qb_rb_open(const char *name, size_t size, uint32_t flags, * Create a shared_hdr memory segment for the header. */ snprintf(filename, PATH_MAX, "qb-%s-header", name); - fd_hdr = qb_util_mmap_file_open(path, filename, - shared_size, file_flags); + fd_hdr = qb_sys_mmap_file_open(path, filename, + shared_size, file_flags); if (fd_hdr < 0) { error = fd_hdr; qb_util_log(LOG_ERR, "couldn't create file for mmap"); @@ -162,14 +162,14 @@ qb_rb_open(const char *name, size_t size, uint32_t flags, */ if (flags & QB_RB_FLAG_CREATE) { snprintf(filename, PATH_MAX, "qb-%s-data", name); - fd_data = qb_util_mmap_file_open(path, - filename, - real_size, file_flags); + fd_data = qb_sys_mmap_file_open(path, + filename, + real_size, file_flags); strncpy(rb->shared_hdr->data_path, path, PATH_MAX); } else { - fd_data = qb_util_mmap_file_open(path, - rb->shared_hdr->data_path, - real_size, file_flags); + fd_data = qb_sys_mmap_file_open(path, + rb->shared_hdr->data_path, + real_size, file_flags); } if (fd_data < 0) { error = fd_data; @@ -181,7 +181,7 @@ qb_rb_open(const char *name, size_t size, uint32_t flags, "shm size:%zd; real_size:%zd; rb->size:%d", size, real_size, rb->shared_hdr->size);
- error = qb_util_circular_mmap(fd_data, &shm_addr, real_size); + error = qb_sys_circular_mmap(fd_data, &shm_addr, real_size); rb->shared_data = shm_addr; if (error != 0) { qb_util_log(LOG_ERR, "couldn't create circular mmap on %s", diff --git a/lib/ringbuffer_int.h b/lib/ringbuffer_int.h index 0e04638..6866fd6 100644 --- a/lib/ringbuffer_int.h +++ b/lib/ringbuffer_int.h @@ -23,9 +23,15 @@
#include "os_base.h"
+#ifdef HAVE_SYS_MMAN_H #include <sys/mman.h> +#endif /* HAVE_SYS_MMAN_H */ +#ifdef HAVE_SYS_SEM_H #include <sys/sem.h> +#endif +#ifdef HAVE_SYS_IPC_H #include <sys/ipc.h> +#endif #include <pthread.h> #include <semaphore.h>
diff --git a/lib/unix.c b/lib/unix.c new file mode 100644 index 0000000..f683e7b --- /dev/null +++ b/lib/unix.c @@ -0,0 +1,465 @@ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Angus Salkeld asalkeld@redhat.com + * + * libqb is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * libqb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libqb. If not, see http://www.gnu.org/licenses/. + */ +#include "os_base.h" + +#ifdef HAVE_SYS_SHM_H +#include <sys/shm.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +#include "util_int.h" +#include <qb/qbdefs.h> +#include <qb/qbutil.h> +#include <qb/qbatomic.h> + +char * +qb_strerror_r(int errnum, char *buf, size_t buflen) +{ +#ifdef QB_LINUX + return strerror_r(errnum, buf, buflen); +#else + char *out_buf; + + if (strerror_r(errnum, buf, buflen) == 0) { + out_buf = buf; + } else { + out_buf = (char*)""; + } + return out_buf; +#endif /* QB_LINUX */ +} + +#ifndef HAVE_STRCHRNUL +/* Find the first occurrence of C in S or the final NUL byte. + */ +char * +qb_sys_strchrnul(const char *s, int c_in) +{ + char c = c_in; + while (*s && (*s != c)) + s++; + + return (char *) s; +} +#endif /* HAVE_STRCHRNUL */ + +static int32_t +open_mmap_file(char *path, uint32_t file_flags) +{ + if (strstr(path, "XXXXXX") != NULL) { + return mkstemp(path); + } + + return open(path, file_flags, 0600); +} + +int32_t +qb_sys_mmap_file_open(char *path, const char *file, size_t bytes, + uint32_t file_flags) +{ + int32_t fd; + int32_t i; + int32_t res = 0; + ssize_t written; + char *buffer = NULL; + char *is_absolute = strchr(file, '/');; + + if (is_absolute) { + strcpy(path, file); + } else { + snprintf(path, PATH_MAX, "/dev/shm/%s", file); + } + fd = open_mmap_file(path, file_flags); + if (fd < 0 && !is_absolute) { + res = -errno; + qb_util_perror(LOG_ERR, "couldn't open file %s", path); + + snprintf(path, PATH_MAX, LOCALSTATEDIR "/run/%s", file); + fd = open_mmap_file(path, file_flags); + if (fd < 0) { + res = -errno; + qb_util_perror(LOG_ERR, "couldn't open file %s", path); + return res; + } + } + + if (ftruncate(fd, bytes) == -1) { + res = -errno; + qb_util_perror(LOG_ERR, "couldn't truncate file %s", path); + goto unlink_exit; + } + + if (file_flags & O_CREAT) { + long page_size = sysconf(_SC_PAGESIZE); + if (page_size < 0) { + res = -errno; + goto unlink_exit; + } + buffer = calloc(1, page_size); + if (buffer == NULL) { + res = -ENOMEM; + goto unlink_exit; + } + for (i = 0; i < (bytes / page_size); i++) { +retry_write: + written = write(fd, buffer, page_size); + if (written == -1 && errno == EINTR) { + goto retry_write; + } + if (written != page_size) { + res = -ENOSPC; + free(buffer); + goto unlink_exit; + } + } + free(buffer); + } + + return fd; + +unlink_exit: + unlink(path); + if (fd > 0) { + close(fd); + } + return res; +} + + +int32_t +qb_sys_circular_mmap(int32_t fd, void **buf, size_t bytes) +{ + void *addr_orig = NULL; + void *addr; + void *addr_next; + int32_t res; + int flags = MAP_ANONYMOUS; + +#ifdef QB_FORCE_SHM_ALIGN +/* On a number of arches any fixed and shared mmap() mapping address + * must be aligned to 16k. If the first mmap() below is not shared then + * the first mmap() will succeed because these restrictions do not apply to + * private mappings. The second mmap() wants a shared memory mapping but + * the address returned by the first one is only page-aligned and not + * aligned to 16k. + */ + flags |= MAP_SHARED; +#else + flags |= MAP_PRIVATE; +#endif /* QB_FORCE_SHM_ALIGN */ + + addr_orig = mmap(NULL, bytes << 1, PROT_NONE, flags, -1, 0); + + if (addr_orig == MAP_FAILED) { + return -errno; + } + + addr = mmap(addr_orig, bytes, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd, 0); + + if (addr != addr_orig) { + res = -errno; + goto cleanup_fail; + } +#ifdef QB_BSD + madvise(addr_orig, bytes, MADV_NOSYNC); +#endif + addr_next = ((char *)addr_orig) + bytes; + addr = mmap(addr_next, + bytes, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd, 0); + if (addr != addr_next) { + res = -errno; + goto cleanup_fail; + } +#ifdef QB_BSD + madvise(((char *)addr_orig) + bytes, bytes, MADV_NOSYNC); +#endif + + res = close(fd); + if (res) { + goto cleanup_fail; + } + *buf = addr_orig; + return 0; + +cleanup_fail: + + if (addr_orig) { + munmap(addr_orig, bytes << 1); + } + close(fd); + return res; +} + +int32_t +qb_sys_fd_nonblock_cloexec_set(int32_t fd) +{ + int32_t res = 0; + int32_t oldflags = fcntl(fd, F_GETFD, 0); + + if (oldflags < 0) { + oldflags = 0; + } + oldflags |= FD_CLOEXEC; + res = fcntl(fd, F_SETFD, oldflags); + if (res == -1) { + res = -errno; + qb_util_perror(LOG_ERR, + "Could not set close-on-exit on fd:%d", fd); + return res; + } + + res = fcntl(fd, F_SETFL, O_NONBLOCK); + if (res == -1) { + res = -errno; + qb_util_log(LOG_ERR, "Could not set non-blocking on fd:%d", fd); + } + + return res; +} + +/* + * atomic operations + * -------------------------------------------------------------------------- + */ +#ifndef HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS +/* + * We have to use the slow, but safe locking method + */ + +static qb_thread_lock_t *qb_atomic_mutex = NULL; + +void +qb_atomic_init(void) +{ + if (qb_atomic_mutex == NULL) { + qb_atomic_mutex = qb_thread_lock_create(QB_THREAD_LOCK_SHORT); + } + assert(qb_atomic_mutex); +} + +int32_t +qb_atomic_int_exchange_and_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, + int32_t val) +{ + int32_t result; + + qb_thread_lock(qb_atomic_mutex); + result = *atomic; + *atomic += val; + qb_thread_unlock(qb_atomic_mutex); + + return result; +} + +void +qb_atomic_int_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t val) +{ + qb_thread_lock(qb_atomic_mutex); + *atomic += val; + qb_thread_unlock(qb_atomic_mutex); +} + +int32_t +qb_atomic_int_compare_and_exchange(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, + int32_t oldval, int32_t newval) +{ + int32_t result; + + qb_thread_lock(qb_atomic_mutex); + if (*atomic == oldval) { + result = QB_TRUE; + *atomic = newval; + } else { + result = QB_FALSE; + } + qb_thread_unlock(qb_atomic_mutex); + + return result; +} + +int32_t +qb_atomic_pointer_compare_and_exchange(volatile void *QB_GNUC_MAY_ALIAS * + atomic, void *oldval, void *newval) +{ + int32_t result; + + qb_thread_lock(qb_atomic_mutex); + if (*atomic == oldval) { + result = QB_TRUE; + *atomic = newval; + } else { + result = QB_FALSE; + } + qb_thread_unlock(qb_atomic_mutex); + + return result; +} + +#ifdef QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED +int32_t +(qb_atomic_int_get) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic) +{ + int32_t result; + + qb_thread_lock(qb_atomic_mutex); + result = *atomic; + qb_thread_unlock(qb_atomic_mutex); + + return result; +} + +void +(qb_atomic_int_set) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic, + int32_t newval) +{ + qb_thread_lock(qb_atomic_mutex); + *atomic = newval; + qb_thread_unlock(qb_atomic_mutex); +} + +void * +(qb_atomic_pointer_get) (volatile void *QB_GNUC_MAY_ALIAS * atomic) +{ + void *result; + + qb_thread_lock(qb_atomic_mutex); + result = (void*)*atomic; + qb_thread_unlock(qb_atomic_mutex); + + return result; +} + +void +(qb_atomic_pointer_set) (volatile void *QB_GNUC_MAY_ALIAS * atomic, + void *newval) +{ + qb_thread_lock(qb_atomic_mutex); + *atomic = newval; + qb_thread_unlock(qb_atomic_mutex); +} +#endif /* QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ + +#else + +/* + * gcc built-ins + */ + +void +qb_atomic_init(void) +{ +} + +int32_t +qb_atomic_int_exchange_and_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, + int32_t val) +{ + return __sync_fetch_and_add(atomic, val); +} + +void +qb_atomic_int_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t val) +{ + __sync_fetch_and_add(atomic, val); +} + +int32_t +qb_atomic_int_compare_and_exchange(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, + int32_t oldval, int32_t newval) +{ + return __sync_bool_compare_and_swap(atomic, oldval, newval); +} + +int32_t +qb_atomic_pointer_compare_and_exchange(volatile void *QB_GNUC_MAY_ALIAS * + atomic, void *oldval, void *newval) +{ + return __sync_bool_compare_and_swap(atomic, oldval, newval); +} + +#ifdef QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED +#define QB_ATOMIC_MEMORY_BARRIER __sync_synchronize () + +int32_t +(qb_atomic_int_get) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic) +{ + QB_ATOMIC_MEMORY_BARRIER; + return *atomic; +} + +void +(qb_atomic_int_set) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic, + int32_t newval) +{ + *atomic = newval; + QB_ATOMIC_MEMORY_BARRIER; +} + +void * +(qb_atomic_pointer_get) (volatile void *QB_GNUC_MAY_ALIAS * atomic) +{ + QB_ATOMIC_MEMORY_BARRIER; + return (void*)*atomic; +} + +void +(qb_atomic_pointer_set) (volatile void *QB_GNUC_MAY_ALIAS * atomic, + void *newval) +{ + *atomic = newval; + QB_ATOMIC_MEMORY_BARRIER; +} + +#endif /* QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ + +#endif /* HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS */ + +#ifndef QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED +int32_t +(qb_atomic_int_get) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic) +{ + return qb_atomic_int_get(atomic); +} + +void +(qb_atomic_int_set) (volatile int32_t QB_GNUC_MAY_ALIAS * atomic, + int32_t newval) +{ + qb_atomic_int_set(atomic, newval); +} + +void * +(qb_atomic_pointer_get) (volatile void *QB_GNUC_MAY_ALIAS * atomic) +{ + return qb_atomic_pointer_get(atomic); +} + +void +(qb_atomic_pointer_set) (volatile void *QB_GNUC_MAY_ALIAS * atomic, + void *newval) +{ + qb_atomic_pointer_set(atomic, newval); +} +#endif /* !QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ diff --git a/lib/util.c b/lib/util.c index 1ce5f4f..51c94bb 100644 --- a/lib/util.c +++ b/lib/util.c @@ -21,8 +21,6 @@ #include "os_base.h"
#include "util_int.h" -#include <sys/shm.h> -#include <sys/mman.h> #include <pthread.h> #include <sys/stat.h> #include <qb/qbdefs.h> @@ -220,7 +218,7 @@ qb_util_nano_from_epoch_get(void)
return (nano_from_epoch); } -#endif +#endif /* HAVE_MONOTONIC_CLOCK */
struct qb_util_stopwatch { uint64_t started; @@ -231,9 +229,7 @@ qb_util_stopwatch_t * qb_util_stopwatch_create(void) { struct qb_util_stopwatch *sw; - sw = (struct qb_util_stopwatch *)calloc(1, - sizeof(struct - qb_util_stopwatch)); + sw = (struct qb_util_stopwatch *)calloc(1, sizeof(struct qb_util_stopwatch)); return sw; }
@@ -276,213 +272,3 @@ qb_util_stopwatch_sec_elapsed_get(qb_util_stopwatch_t * sw) return ((float)e6 / (float)QB_TIME_US_IN_SEC); }
-static int32_t -open_mmap_file(char *path, uint32_t file_flags) -{ - if (strstr(path, "XXXXXX") != NULL) { - return mkstemp(path); - } - - return open(path, file_flags, 0600); -} - -/* - * --------------------------------------------------- - * shared memory functions. - */ -int32_t -qb_util_mmap_file_open(char *path, const char *file, size_t bytes, - uint32_t file_flags) -{ - int32_t fd; - int32_t i; - int32_t res = 0; - ssize_t written; - char *buffer = NULL; - char *is_absolute = strchr(file, '/');; - - if (is_absolute) { - strcpy(path, file); - } else { - snprintf(path, PATH_MAX, "/dev/shm/%s", file); - } - fd = open_mmap_file(path, file_flags); - if (fd < 0 && !is_absolute) { - res = -errno; - qb_util_perror(LOG_ERR, "couldn't open file %s", path); - - snprintf(path, PATH_MAX, LOCALSTATEDIR "/run/%s", file); - fd = open_mmap_file(path, file_flags); - if (fd < 0) { - res = -errno; - qb_util_perror(LOG_ERR, "couldn't open file %s", path); - return res; - } - } - - if (ftruncate(fd, bytes) == -1) { - res = -errno; - qb_util_perror(LOG_ERR, "couldn't truncate file %s", path); - goto unlink_exit; - } - - if (file_flags & O_CREAT) { - long page_size = sysconf(_SC_PAGESIZE); - if (page_size < 0) { - res = -errno; - goto unlink_exit; - } - buffer = calloc(1, page_size); - if (buffer == NULL) { - res = -ENOMEM; - goto unlink_exit; - } - for (i = 0; i < (bytes / page_size); i++) { -retry_write: - written = write(fd, buffer, page_size); - if (written == -1 && errno == EINTR) { - goto retry_write; - } - if (written != page_size) { - res = -ENOSPC; - free(buffer); - goto unlink_exit; - } - } - free(buffer); - } - - return fd; - -unlink_exit: - unlink(path); - if (fd > 0) { - close(fd); - } - return res; -} - -int32_t -qb_util_circular_mmap(int32_t fd, void **buf, size_t bytes) -{ - void *addr_orig = NULL; - void *addr; - void *addr_next; - int32_t res; - int flags = MAP_ANONYMOUS; - -#ifdef QB_FORCE_SHM_ALIGN -/* On a number of arches any fixed and shared mmap() mapping address - * must be aligned to 16k. If the first mmap() below is not shared then - * the first mmap() will succeed because these restrictions do not apply to - * private mappings. The second mmap() wants a shared memory mapping but - * the address returned by the first one is only page-aligned and not - * aligned to 16k. - */ - flags |= MAP_SHARED; -#else - flags |= MAP_PRIVATE; -#endif /* QB_FORCE_SHM_ALIGN */ - - addr_orig = mmap(NULL, bytes << 1, PROT_NONE, flags, -1, 0); - - if (addr_orig == MAP_FAILED) { - return -errno; - } - - addr = mmap(addr_orig, bytes, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_SHARED, fd, 0); - - if (addr != addr_orig) { - res = -errno; - goto cleanup_fail; - } -#ifdef QB_BSD - madvise(addr_orig, bytes, MADV_NOSYNC); -#endif - addr_next = ((char *)addr_orig) + bytes; - addr = mmap(addr_next, - bytes, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_SHARED, fd, 0); - if (addr != addr_next) { - res = -errno; - goto cleanup_fail; - } -#ifdef QB_BSD - madvise(((char *)addr_orig) + bytes, bytes, MADV_NOSYNC); -#endif - - res = close(fd); - if (res) { - goto cleanup_fail; - } - *buf = addr_orig; - return 0; - -cleanup_fail: - - if (addr_orig) { - munmap(addr_orig, bytes << 1); - } - close(fd); - return res; -} - -int32_t -qb_util_fd_nonblock_cloexec_set(int32_t fd) -{ - int32_t res; - int32_t oldflags = fcntl(fd, F_GETFD, 0); - - if (oldflags < 0) { - oldflags = 0; - } - oldflags |= FD_CLOEXEC; - res = fcntl(fd, F_SETFD, oldflags); - if (res == -1) { - res = -errno; - qb_util_perror(LOG_ERR, - "Could not set close-on-exit on fd:%d", fd); - return res; - } - - res = fcntl(fd, F_SETFL, O_NONBLOCK); - if (res == -1) { - res = -errno; - qb_util_log(LOG_ERR, "Could not set non-blocking on fd:%d", fd); - } - return res; -} - -char * -qb_strerror_r(int errnum, char *buf, size_t buflen) -{ -#ifdef QB_LINUX - return strerror_r(errnum, buf, buflen); -#else - char *out_buf; - - if (strerror_r(errnum, buf, buflen) == 0) { - out_buf = buf; - } else { - out_buf = (char*)""; - } - return out_buf; -#endif /* QB_LINUX */ -} - -#ifdef QB_DARWIN -/* Borrowed from gnulib's strchrnul.c under GLPv2+ */ - -#include <string.h> -/* Find the first occurrence of C in S or the final NUL byte. */ -char * -strchrnul (const char *s, int c_in) -{ - char c = c_in; - while (*s && (*s != c)) - s++; - - return (char *) s; -} -#endif diff --git a/lib/util_int.h b/lib/util_int.h index b26b79c..9d23285 100644 --- a/lib/util_int.h +++ b/lib/util_int.h @@ -20,6 +20,7 @@ #ifndef QB_UTIL_INT_H_DEFINED #define QB_UTIL_INT_H_DEFINED
+#include "os_base.h" #include <qb/qblog.h>
#if !defined (va_copy) @@ -61,7 +62,7 @@ * @param file_flags same as passed into open() * @return 0 (success) or -errno */ -int32_t qb_util_mmap_file_open(char *path, const char *file, size_t bytes, +int32_t qb_sys_mmap_file_open(char *path, const char *file, size_t bytes, uint32_t file_flags);
/** @@ -72,7 +73,7 @@ int32_t qb_util_mmap_file_open(char *path, const char *file, size_t bytes, * @param bytes the size of the shared memory. * @return 0 (success) or -errno */ -int32_t qb_util_circular_mmap(int32_t fd, void **buf, size_t bytes); +int32_t qb_sys_circular_mmap(int32_t fd, void **buf, size_t bytes);
/** @@ -80,6 +81,10 @@ int32_t qb_util_circular_mmap(int32_t fd, void **buf, size_t bytes); * @param fd the file descriptor. * @return 0 (success) or -errno */ -int32_t qb_util_fd_nonblock_cloexec_set(int32_t fd); +int32_t qb_sys_fd_nonblock_cloexec_set(int32_t fd);
+#ifndef HAVE_STRCHRNUL +#define strchrnul(s, c_in) qb_sys_strchrnul(s, c_in) +char * qb_sys_strchrnul(const char *s, int c_in); +#endif /* !HAVE_STRCHRNUL */ #endif /* QB_UTIL_INT_H_DEFINED */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 49287cb..d8f64e2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -73,7 +73,7 @@ bench_log_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la if HAVE_CHECK EXTRA_DIST += resources.test
-TESTS = array.test map.test rb.test log.test loop.test ipc.test resources.test map.test +TESTS = array.test map.test rb.test log.test loop.test ipc.test resources.test
resources.log: rb.log log.log ipc.log