Signed-off-by: Angus Salkeld <asalkeld(a)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(a)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
--
1.7.7.4