mirror of
https://salsa.debian.org/ha-team/libqb
synced 2026-08-08 02:41:53 +00:00
Merge some portability changes from the mingw branch
Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
This commit is contained in:
parent
3554d145fc
commit
ab3dc60f7f
105
configure.ac
105
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_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])
|
||||
|
||||
AC_MSG_RESULT($gcc_has_builtin_atomic_operations)
|
||||
if test $gcc_has_builtin_atomic_operations = yes; then
|
||||
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])
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -27,6 +27,8 @@ extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include <qb/qbconfig.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@ -26,6 +26,8 @@ extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#ifndef S_SPLINT_S
|
||||
#include <unistd.h>
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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 */
|
||||
@ -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];
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
19
lib/ipc_us.c
19
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");
|
||||
|
||||
11
lib/ipcc.c
11
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);
|
||||
|
||||
19
lib/ipcs.c
19
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,
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
465
lib/unix.c
Normal file
465
lib/unix.c
Normal file
@ -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 */
|
||||
218
lib/util.c
218
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
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user