Rearrange and fixup abstraction layer
- Replace os_result by dds_retcode_t and move DDS return code defines down. Eliminates the need to convert between different return code types. - Move dds_time_t down and remove os_time. Eliminates the need to convert between different time representations and reduces code duplication. - Remove use of Microsoft source-code annotation language (SAL). SAL annotations are Microsoft specific and not very well documented. This makes it very difficult for contributers to write. - Rearrange the abstraction layer to be feature-based. The previous layout falsely assumed that the operating system dictates which implementation is best suited. For general purpose operating systems this is mostly true, but embedded targets require a slightly different approach and may not even offer all features. The new layout makes it possible to mix-and-match feature implementations and allows for features to not be implemented at all. - Replace the os prefix by ddsrt to avoid name collisions. - Remove various portions of unused and unwanted code. - Export thread names on all supported platforms. - Return native thread identifier on POSIX compatible platforms. - Add timed wait for condition variables that takes an absolute time. - Remove system abstraction for errno. The os_getErrno and os_setErrno were incorrect. Functions that might fail now simply return a DDS return code instead. - Remove thread-specific memory abstraction. os_threadMemGet and accompanying functions were a mess and their use has been eliminated by other changes in this commit. - Replace attribute (re)defines by ddsrt_ prefixed equivalents to avoid name collisions and problems with faulty __nonnull__ attributes. Signed-off-by: Jeroen Koekkoek <jeroen@koekkoek.nl>
This commit is contained in:
parent
318968f40f
commit
cd6742ee12
439 changed files with 22117 additions and 28782 deletions
210
src/ddsrt/CMakeLists.txt
Normal file
210
src/ddsrt/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
#
|
||||
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Eclipse Public License v. 2.0 which is available at
|
||||
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
# v. 1.0 which is available at
|
||||
# http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
#
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckLibraryExists)
|
||||
|
||||
function(check_runtime_feature SOURCE_FILE)
|
||||
set(expr "cmake_([_a-zA-Z0-9]+)=([_a-zA-Z0-9]+)")
|
||||
try_compile(
|
||||
foo "${CMAKE_BINARY_DIR}"
|
||||
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}"
|
||||
OUTPUT_VARIABLE output)
|
||||
string(REGEX MATCHALL "${expr}" matches "${output}")
|
||||
foreach(match ${matches})
|
||||
string(REGEX REPLACE "${expr}" "\\1" option "${match}")
|
||||
string(REGEX REPLACE "${expr}" "\\2" value "${match}")
|
||||
set(${option} ${value} PARENT_SCOPE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
if(APPLE)
|
||||
set(system_name darwin)
|
||||
else()
|
||||
string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
|
||||
endif()
|
||||
|
||||
# A better choice is to use a so-called object library for ddsrt, but it was
|
||||
# not possible to use target_link_libraries with object libraries until CMake
|
||||
# 3.12. At the time of this writing most long-term stable distributions still
|
||||
# ship an older version, so an interface library with public sources is used
|
||||
# as a workaround for now.
|
||||
add_library(ddsrt INTERFACE)
|
||||
target_include_directories(
|
||||
ddsrt INTERFACE
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>")
|
||||
|
||||
# Generate version header.
|
||||
configure_file("include/dds/version.h.in" "include/dds/version.h")
|
||||
target_sources(
|
||||
ddsrt INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/include/dds/version.h")
|
||||
|
||||
if(WIN32)
|
||||
configure_file("include/getopt.h.in" "include/getopt.h" COPYONLY)
|
||||
list(APPEND headers "${CMAKE_CURRENT_BINARY_DIR}/include/getopt.h")
|
||||
list(APPEND sources "${CMAKE_CURRENT_SOURCE_DIR}/src/getopt.c")
|
||||
endif()
|
||||
|
||||
set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
|
||||
list(APPEND headers
|
||||
"${include_path}/dds/ddsrt/log.h"
|
||||
"${include_path}/dds/ddsrt/retcode.h"
|
||||
"${include_path}/dds/ddsrt/attributes.h"
|
||||
"${include_path}/dds/ddsrt/endian.h"
|
||||
"${include_path}/dds/ddsrt/arch.h"
|
||||
"${include_path}/dds/ddsrt/misc.h"
|
||||
"${include_path}/dds/ddsrt/io.h"
|
||||
"${include_path}/dds/ddsrt/process.h"
|
||||
"${include_path}/dds/ddsrt/strtod.h"
|
||||
"${include_path}/dds/ddsrt/strtol.h"
|
||||
"${include_path}/dds/ddsrt/types.h")
|
||||
|
||||
list(APPEND sources
|
||||
"${source_path}/io.c"
|
||||
"${source_path}/log.c"
|
||||
"${source_path}/retcode.c"
|
||||
"${source_path}/process.c"
|
||||
"${source_path}/strtod.c"
|
||||
"${source_path}/strtol.c")
|
||||
|
||||
# Not every target offers the same set of features. For embedded targets the
|
||||
# set of features may even be different between builds. e.g. a FreeRTOS build
|
||||
# could use the lightweight IP stack, but later change to FreeRTOS+TCP.
|
||||
#
|
||||
# Most features and target specific settings can be determined at compile time
|
||||
# by a combination of pre-defined macros. However, some features require input
|
||||
# from the build system. e.g. that the target operating system is FreeRTOS or
|
||||
# that the network stack to be used is lwIP as opposed to the target native
|
||||
# network stack. In order to mix-and-match various compilers, architectures,
|
||||
# operating systems, etc input from the build system is required.
|
||||
foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
||||
sockets string sync threads time)
|
||||
if(EXISTS "${include_path}/dds/ddsrt/${feature}.h")
|
||||
list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h")
|
||||
file(GLOB
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${include_path}/dds/ddsrt/${feature}/**.h")
|
||||
list(APPEND headers ${files})
|
||||
|
||||
# Do not add any sources if a feature is not offered by the target. The
|
||||
# headers will define any macros needed by the source code by combining
|
||||
# build system exports and pre-defined macros. To determine if a certain
|
||||
# feature is offered by the target and whether or not to compile any
|
||||
# source files, that information must be made available to CMake.
|
||||
#
|
||||
# Tests that export the required information can be written in
|
||||
# cmake/${feature}.c. A test consists of a source file that includes the
|
||||
# required header files and results in a specifically crafted compiler
|
||||
# error that is picked up by CMake. By default, if a file named after the
|
||||
# feature does not exist in cmake, the feature is expected to be
|
||||
# implemented for all targets.
|
||||
string(TOUPPER "${feature}" feature_uc)
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${feature}.c")
|
||||
check_runtime_feature(cmake/${feature}.c)
|
||||
else()
|
||||
set(HAVE_${feature_uc} TRUE)
|
||||
endif()
|
||||
|
||||
if(HAVE_${feature_uc})
|
||||
# Code that is more-or-less the same for all targets can placed in
|
||||
# src/<feature>.c. An example would be ddsrt_freeifaddrs.
|
||||
if(EXISTS "${source_path}/${feature}.c")
|
||||
list(APPEND sources "${source_path}/${feature}.c")
|
||||
endif()
|
||||
set(system_exists FALSE)
|
||||
foreach(system ${system_name} posix)
|
||||
# Headers that must remain private but are required by other runtime
|
||||
# source files must be located in src/<feature>/dds/ddsrt.
|
||||
if(IS_DIRECTORY "${source_path}/${feature}/include")
|
||||
file(GLOB
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${source_path}/${feature}/include/**.h")
|
||||
list(APPEND sources ${files})
|
||||
target_include_directories(
|
||||
ddsrt INTERFACE
|
||||
"$<BUILD_INTERFACE:${source_path}/${feature}/include/>")
|
||||
endif()
|
||||
if(IS_DIRECTORY "${source_path}/${feature}/${system}")
|
||||
file(GLOB
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${source_path}/${feature}/${system}/**.c")
|
||||
list(APPEND sources ${files})
|
||||
set(system_exists TRUE)
|
||||
endif()
|
||||
# Break as soon a system-specific headers or sources are found.
|
||||
if(system_exists)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
message(STATUS "Feature ${feature} disabled")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Feature ${feature} does not exist")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
target_sources(ddsrt INTERFACE ${sources})
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(ddsrt INTERFACE Threads::Threads)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi)
|
||||
elseif(UNIX)
|
||||
check_library_exists(c clock_gettime "" HAVE_CLOCK_GETTIME)
|
||||
if(NOT HAVE_CLOCK_GETTIME)
|
||||
# Before glibc 2.17, clock_gettime was in librt.
|
||||
check_library_exists(rt clock_gettime "time.h" HAVE_CLOCK_GETTIME_RT)
|
||||
if(HAVE_CLOCK_GETTIME_RT)
|
||||
set(HAVE_CLOCK_GETTIME TRUE)
|
||||
target_link_libraries(ddsrt INTERFACE rt)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT HAVE_CLOCK_GETTIME)
|
||||
message(FATAL_ERROR "clock_gettime is not available")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${CMAKE_C_COMPILER_ID} STREQUAL "SunPro")
|
||||
target_link_libraries(ddsrt INTERFACE socket nsl)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
install(
|
||||
DIRECTORY "include/dds"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT dev
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/include/dds/version.h"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/dds"
|
||||
COMPONENT dev)
|
||||
|
||||
if(WIN32)
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/include/getopt.h"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT dev)
|
||||
endif()
|
||||
|
||||
29
src/ddsrt/include/dds/ddsrt/arch.h
Normal file
29
src/ddsrt/include/dds/ddsrt/arch.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ARCH_H
|
||||
#define DDSRT_ARCH_H
|
||||
|
||||
#if _WIN32
|
||||
# if _WIN64
|
||||
# define DDSRT_64BIT 1
|
||||
# else
|
||||
# define DDSRT_64BIT 0
|
||||
# endif
|
||||
#else
|
||||
# if defined(_LP64)
|
||||
# define DDSRT_64BIT 1
|
||||
# else
|
||||
# define DDSRT_64BIT 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_ARCH_H */
|
||||
66
src/ddsrt/include/dds/ddsrt/atomics.h
Normal file
66
src/ddsrt/include/dds/ddsrt/atomics.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ATOMICS_H
|
||||
#define DDSRT_ATOMICS_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/arch.h"
|
||||
#include "dds/ddsrt/endian.h"
|
||||
#include "dds/ddsrt/types.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Types on which atomic operations are defined.
|
||||
*
|
||||
* @note 64-bit types are defined even if atomic operations on them are not
|
||||
* really supported. atomic
|
||||
*/
|
||||
typedef struct { uint32_t v; } ddsrt_atomic_uint32_t;
|
||||
typedef struct { uint64_t v; } ddsrt_atomic_uint64_t;
|
||||
typedef struct { uintptr_t v; } ddsrt_atomic_uintptr_t;
|
||||
typedef ddsrt_atomic_uintptr_t ddsrt_atomic_voidp_t;
|
||||
|
||||
#if DDSRT_64BIT
|
||||
# define DDSRT_HAVE_ATOMIC64 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initializers for the types on which atomic operations are defined.
|
||||
*/
|
||||
#define DDSRT_ATOMIC_UINT32_INIT(v) { (v) }
|
||||
#define DDSRT_ATOMIC_UINT64_INIT(v) { (v) }
|
||||
#define DDSRT_ATOMIC_UINTPTR_INIT(v) { (v) }
|
||||
#define DDSRT_ATOMIC_VOIDP_INIT(v) { (uintptr_t) (v) }
|
||||
|
||||
|
||||
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40100
|
||||
#include "dds/ddsrt/atomics/gcc.h"
|
||||
#elif defined(_WIN32)
|
||||
#include "dds/ddsrt/atomics/msvc.h"
|
||||
#elif defined(__sun)
|
||||
#include "dds/ddsrt/atomics/sun.h"
|
||||
#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__)
|
||||
#include "dds/ddsrt/atomics/arm.h"
|
||||
#else
|
||||
#error "Atomic operations are not supported"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_ATOMICS_H */
|
||||
213
src/ddsrt/include/dds/ddsrt/atomics/arm.h
Normal file
213
src/ddsrt/include/dds/ddsrt/atomics/arm.h
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ATOMICS_ARM_H
|
||||
#define DDSRT_ATOMICS_ARM_H
|
||||
|
||||
#if !defined(__arm__)
|
||||
#define __arm__
|
||||
#endif
|
||||
|
||||
/* IAR documentation states that __CPU_MODE__ is a predefined preprocessor
|
||||
symbol reflecting the selected CPU mode and is defined to 1 for Thumb and
|
||||
2 for ARM. */
|
||||
#if !defined(__thumb__) && __CPU_MODE__ == 1
|
||||
#define __thumb__
|
||||
#endif
|
||||
|
||||
/* LD, ST */
|
||||
|
||||
inline uint32_t ddsrt_atomic_ld32 (const volatile ddsrt_atomic_uint32_t *x) { return x->v; }
|
||||
inline uintptr_t ddsrt_atomic_ldptr (const volatile ddsrt_atomic_uintptr_t *x) { return x->v; }
|
||||
inline void *ddsrt_atomic_ldvoidp (const volatile ddsrt_atomic_voidp_t *x) { return (void *) ddsrt_atomic_ldptr (x); }
|
||||
|
||||
inline void ddsrt_atomic_st32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_stptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_stvoidp (volatile ddsrt_atomic_voidp_t *x, void *v) { ddsrt_atomic_stptr (x, (uintptr_t) v); }
|
||||
|
||||
/* CAS */
|
||||
|
||||
inline int ddsrt_atomic_cas32 (volatile ddsrt_atomic_uint32_t *x, uint32_t exp, uint32_t des) {
|
||||
register int result;
|
||||
asm volatile ("ldrex r0, [%1]\n\t" /*exclusive load of ptr */
|
||||
"cmp r0, %2\n\t" /*compare the oldval == *ptr */
|
||||
#if defined(__thumb__)
|
||||
"ite eq\n\t"
|
||||
#endif
|
||||
"strexeq %0, %3, [%1]\n\t" /*store if eq, strex+eq*/
|
||||
#if defined(__thumb__)
|
||||
"clrexne"
|
||||
#endif
|
||||
: "=&r" (result)
|
||||
: "r"(&x->v), "r"(exp),"r"(des)
|
||||
: "r0");
|
||||
return result == 0;
|
||||
}
|
||||
inline int ddsrt_atomic_casptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t exp, uintptr_t des) {
|
||||
return ddsrt_atomic_cas32 ((volatile ddsrt_atomic_uint32_t *) x, exp, des);
|
||||
}
|
||||
inline int ddsrt_atomic_casvoidp (volatile ddsrt_atomic_voidp_t *x, void *exp, void *des) {
|
||||
return ddsrt_atomic_casptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) exp, (uintptr_t) des);
|
||||
}
|
||||
|
||||
/* ADD */
|
||||
|
||||
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
register unsigned int result;
|
||||
asm volatile ("1: ldrex %0, [%1]\n\t"
|
||||
"add %0, %0, %2\n\t"
|
||||
"strex r1, %0, [%1]\n\t"
|
||||
"cmp r1, #0\n\t"
|
||||
"bne 1b"
|
||||
: "=&r" (result)
|
||||
: "r"(&x->v), "r"(v)
|
||||
: "r1");
|
||||
return result;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_addptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return ddsrt_atomic_add32_nv ((volatile ddsrt_atomic_uint32_t *) x, v);
|
||||
}
|
||||
inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return (void *) ddsrt_atomic_addptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
(void) ddsrt_atomic_add32_nv (x, v);
|
||||
}
|
||||
inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
(void) ddsrt_atomic_addptr_nv (x, v);
|
||||
}
|
||||
inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
(void) ddsrt_atomic_addvoidp_nv (x, v);
|
||||
}
|
||||
|
||||
/* SUB */
|
||||
|
||||
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return ddsrt_atomic_add32_nv (x, -v);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return ddsrt_atomic_addptr_nv (x, -v);
|
||||
}
|
||||
inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return ddsrt_atomic_addvoidp_nv (x, -v);
|
||||
}
|
||||
inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
ddsrt_atomic_add32 (x, -v);
|
||||
}
|
||||
inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
ddsrt_atomic_subptr (x, -v);
|
||||
}
|
||||
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
ddsrt_atomic_subvoidp (x, -v);
|
||||
}
|
||||
|
||||
/* INC */
|
||||
|
||||
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return ddsrt_atomic_add32_nv (x, 1);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_incptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return ddsrt_atomic_addptr_nv (x, 1);
|
||||
}
|
||||
inline void ddsrt_atomic_inc32 (volatile ddsrt_atomic_uint32_t *x) {
|
||||
(void) ddsrt_atomic_inc32_nv (x);
|
||||
}
|
||||
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
(void) ddsrt_atomic_incptr_nv (x);
|
||||
}
|
||||
|
||||
/* DEC */
|
||||
|
||||
inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return ddsrt_atomic_sub32_nv (x, 1);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_decptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return ddsrt_atomic_subptr_nv (x, 1);
|
||||
}
|
||||
inline void ddsrt_atomic_dec32 (volatile ddsrt_atomic_uint32_t *x) {
|
||||
(void) ddsrt_atomic_dec32_nv (x);
|
||||
}
|
||||
inline void ddsrt_atomic_decptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
(void) ddsrt_atomic_decptr_nv (x);
|
||||
}
|
||||
|
||||
/* AND */
|
||||
|
||||
inline uint32_t ddsrt_atomic_and32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
uint32_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval & v; } while (!ddsrt_atomic_cas32 (x, oldval, newval));
|
||||
return oldval;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_andptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
uintptr_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval & v; } while (!ddsrt_atomic_casptr (x, oldval, newval));
|
||||
return oldval;
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_and32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
uint32_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval & v; } while (!ddsrt_atomic_cas32 (x, oldval, newval));
|
||||
return newval;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_andptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
uintptr_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval & v; } while (!ddsrt_atomic_casptr (x, oldval, newval));
|
||||
return newval;
|
||||
}
|
||||
inline void ddsrt_atomic_and32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
(void) ddsrt_atomic_and32_nv (x, v);
|
||||
}
|
||||
inline void ddsrt_atomic_andptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
(void) ddsrt_atomic_andptr_nv (x, v);
|
||||
}
|
||||
|
||||
/* OR */
|
||||
|
||||
inline uint32_t ddsrt_atomic_or32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
uint32_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval | v; } while (!ddsrt_atomic_cas32 (x, oldval, newval));
|
||||
return oldval;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_orptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
uintptr_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval | v; } while (!ddsrt_atomic_casptr (x, oldval, newval));
|
||||
return oldval;
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_or32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
uint32_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval | v; } while (!ddsrt_atomic_cas32 (x, oldval, newval));
|
||||
return newval;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_orptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
uintptr_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval | v; } while (!ddsrt_atomic_casptr (x, oldval, newval));
|
||||
return newval;
|
||||
}
|
||||
inline void ddsrt_atomic_or32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
(void) ddsrt_atomic_or32_nv (x, v);
|
||||
}
|
||||
inline void ddsrt_atomic_orptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
(void) ddsrt_atomic_orptr_nv (x, v);
|
||||
}
|
||||
|
||||
/* FENCES */
|
||||
|
||||
inline void ddsrt_atomic_fence (void) {
|
||||
__asm volatile ("dmb" : : : "memory");
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_rel (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
|
||||
#endif /* DDSRT_ATOMICS_ARM_H */
|
||||
|
||||
291
src/ddsrt/include/dds/ddsrt/atomics/gcc.h
Normal file
291
src/ddsrt/include/dds/ddsrt/atomics/gcc.h
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ATOMICS_GCC_H
|
||||
#define DDSRT_ATOMICS_GCC_H
|
||||
|
||||
#include "dds/ddsrt/misc.h"
|
||||
|
||||
#if ( DDSRT_HAVE_ATOMIC64 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) || \
|
||||
(!DDSRT_HAVE_ATOMIC64 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
# define DDSRT_HAVE_ATOMIC_LIFO 1
|
||||
#endif
|
||||
|
||||
/* LD, ST */
|
||||
|
||||
inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x) { return x->v; }
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_ld64(const volatile ddsrt_atomic_uint64_t *x) { return x->v; }
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x) { return x->v; }
|
||||
inline void *ddsrt_atomic_ldvoidp(const volatile ddsrt_atomic_voidp_t *x) { return (void *) ddsrt_atomic_ldptr(x); }
|
||||
|
||||
inline void ddsrt_atomic_st32(volatile ddsrt_atomic_uint32_t *x, uint32_t v) { x->v = v; }
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_st64(volatile ddsrt_atomic_uint64_t *x, uint64_t v) { x->v = v; }
|
||||
#endif
|
||||
inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v) { ddsrt_atomic_stptr(x, (uintptr_t)v); }
|
||||
|
||||
/* INC */
|
||||
|
||||
inline void ddsrt_atomic_inc32(volatile ddsrt_atomic_uint32_t *x) {
|
||||
__sync_fetch_and_add (&x->v, 1);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
__sync_fetch_and_add (&x->v, 1);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
__sync_fetch_and_add (&x->v, 1);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return __sync_add_and_fetch (&x->v, 1);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return __sync_add_and_fetch (&x->v, 1);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_incptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return __sync_add_and_fetch (&x->v, 1);
|
||||
}
|
||||
|
||||
/* DEC */
|
||||
|
||||
inline void ddsrt_atomic_dec32 (volatile ddsrt_atomic_uint32_t *x) {
|
||||
__sync_fetch_and_sub (&x->v, 1);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
__sync_fetch_and_sub (&x->v, 1);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_decptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
__sync_fetch_and_sub (&x->v, 1);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return __sync_sub_and_fetch (&x->v, 1);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return __sync_sub_and_fetch (&x->v, 1);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_decptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return __sync_sub_and_fetch (&x->v, 1);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_dec32_ov (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return __sync_fetch_and_sub (&x->v, 1);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_dec64_ov (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return __sync_fetch_and_sub (&x->v, 1);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_decptr_ov (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return __sync_fetch_and_sub (&x->v, 1);
|
||||
}
|
||||
|
||||
/* ADD */
|
||||
|
||||
inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
__sync_fetch_and_add (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
__sync_fetch_and_add (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
__sync_fetch_and_add (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
ddsrt_atomic_addptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_add_and_fetch (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return __sync_add_and_fetch (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_addptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return __sync_add_and_fetch (&x->v, v);
|
||||
}
|
||||
inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return (void *) ddsrt_atomic_addptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
|
||||
/* SUB */
|
||||
|
||||
inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
__sync_fetch_and_sub (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
__sync_fetch_and_sub (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
__sync_fetch_and_sub (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_sub_and_fetch (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return __sync_sub_and_fetch (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return __sync_sub_and_fetch (&x->v, v);
|
||||
}
|
||||
inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return (void *) ddsrt_atomic_subptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
|
||||
/* AND */
|
||||
|
||||
inline void ddsrt_atomic_and32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
__sync_fetch_and_and (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
__sync_fetch_and_and (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_andptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
__sync_fetch_and_and (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_and32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_fetch_and_and (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return __sync_fetch_and_and (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_andptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return __sync_fetch_and_and (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_and32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_and_and_fetch (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return __sync_and_and_fetch (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_andptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return __sync_and_and_fetch (&x->v, v);
|
||||
}
|
||||
|
||||
/* OR */
|
||||
|
||||
inline void ddsrt_atomic_or32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
__sync_fetch_and_or (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
__sync_fetch_and_or (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_orptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
__sync_fetch_and_or (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_or32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_fetch_and_or (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return __sync_fetch_and_or (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_orptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return __sync_fetch_and_or (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_or32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_or_and_fetch (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return __sync_or_and_fetch (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_orptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return __sync_or_and_fetch (&x->v, v);
|
||||
}
|
||||
|
||||
/* CAS */
|
||||
|
||||
inline int ddsrt_atomic_cas32 (volatile ddsrt_atomic_uint32_t *x, uint32_t exp, uint32_t des) {
|
||||
return __sync_bool_compare_and_swap (&x->v, exp, des);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des) {
|
||||
return __sync_bool_compare_and_swap (&x->v, exp, des);
|
||||
}
|
||||
#endif
|
||||
inline int ddsrt_atomic_casptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t exp, uintptr_t des) {
|
||||
return __sync_bool_compare_and_swap (&x->v, exp, des);
|
||||
}
|
||||
inline int ddsrt_atomic_casvoidp (volatile ddsrt_atomic_voidp_t *x, void *exp, void *des) {
|
||||
return ddsrt_atomic_casptr (x, (uintptr_t) exp, (uintptr_t) des);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC_LIFO
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
typedef union { __int128_t x; struct { uintptr_t a, b; } s; } ddsrt_atomic_uintptr2_t;
|
||||
#else
|
||||
typedef union { uint64_t x; struct { uintptr_t a, b; } s; } ddsrt_atomic_uintptr2_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
ddsrt_atomic_uintptr2_t aba_head;
|
||||
} ddsrt_atomic_lifo_t;
|
||||
|
||||
DDS_EXPORT void ddsrt_atomic_lifo_init(ddsrt_atomic_lifo_t *head);
|
||||
DDS_EXPORT void ddsrt_atomic_lifo_push(ddsrt_atomic_lifo_t *head, void *elem, size_t linkoff);
|
||||
DDS_EXPORT void *ddsrt_atomic_lifo_pop(ddsrt_atomic_lifo_t *head, size_t linkoff);
|
||||
DDS_EXPORT void ddsrt_atomic_lifo_pushmany(ddsrt_atomic_lifo_t *head, void *first, void *last, size_t linkoff);
|
||||
|
||||
inline int ddsrt_atomic_casvoidp2 (volatile ddsrt_atomic_uintptr2_t *x, uintptr_t a0, uintptr_t b0, uintptr_t a1, uintptr_t b1) {
|
||||
ddsrt_atomic_uintptr2_t o, n;
|
||||
o.s.a = a0; o.s.b = b0;
|
||||
n.s.a = a1; n.s.b = b1;
|
||||
return __sync_bool_compare_and_swap (&x->x, o.x, n.x);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FENCES */
|
||||
|
||||
inline void ddsrt_atomic_fence (void) {
|
||||
__sync_synchronize ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_ldld (void) {
|
||||
#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
|
||||
__sync_synchronize ();
|
||||
#endif
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_rel (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
|
||||
#endif /* DDSRT_ATOMICS_GCC_H */
|
||||
|
||||
299
src/ddsrt/include/dds/ddsrt/atomics/msvc.h
Normal file
299
src/ddsrt/include/dds/ddsrt/atomics/msvc.h
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ATOMICS_MSVC_H
|
||||
#define DDSRT_ATOMICS_MSVC_H
|
||||
|
||||
#include "dds/ddsrt/misc.h"
|
||||
|
||||
/* x86 has supported 64-bit CAS for a long time, so Windows ought to
|
||||
provide all the interlocked operations for 64-bit operands on x86
|
||||
platforms, but it doesn't. */
|
||||
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
#define DDSRT_ATOMIC_PTROP(name) name##64
|
||||
#else
|
||||
#define DDSRT_ATOMIC_PTROP(name) name
|
||||
#endif
|
||||
|
||||
/* LD, ST */
|
||||
|
||||
inline uint32_t ddsrt_atomic_ld32 (const volatile ddsrt_atomic_uint32_t *x) { return x->v; }
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x) { return x->v; }
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_ldptr (const volatile ddsrt_atomic_uintptr_t *x) { return x->v; }
|
||||
inline void *ddsrt_atomic_ldvoidp (const volatile ddsrt_atomic_voidp_t *x) { return (void *) ddsrt_atomic_ldptr (x); }
|
||||
|
||||
inline void ddsrt_atomic_st32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { x->v = v; }
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { x->v = v; }
|
||||
#endif
|
||||
inline void ddsrt_atomic_stptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_stvoidp (volatile ddsrt_atomic_voidp_t *x, void *v) { ddsrt_atomic_stptr (x, (uintptr_t) v); }
|
||||
|
||||
/* CAS */
|
||||
|
||||
inline int ddsrt_atomic_cas32 (volatile ddsrt_atomic_uint32_t *x, uint32_t exp, uint32_t des) {
|
||||
return InterlockedCompareExchange (&x->v, des, exp) == exp;
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des) {
|
||||
return InterlockedCompareExchange64 (&x->v, des, exp) == exp;
|
||||
}
|
||||
#endif
|
||||
inline int ddsrt_atomic_casptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t exp, uintptr_t des) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedCompareExchange) (&x->v, des, exp) == exp;
|
||||
}
|
||||
inline int ddsrt_atomic_casvoidp (volatile ddsrt_atomic_voidp_t *x, void *exp, void *des) {
|
||||
return ddsrt_atomic_casptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) exp, (uintptr_t) des);
|
||||
}
|
||||
|
||||
/* INC */
|
||||
|
||||
inline void ddsrt_atomic_inc32 (volatile ddsrt_atomic_uint32_t *x) {
|
||||
InterlockedIncrement (&x->v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
InterlockedIncrement64 (&x->v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
DDSRT_ATOMIC_PTROP (InterlockedIncrement) (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return InterlockedIncrement (&x->v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return InterlockedIncrement64 (&x->v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_incptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedIncrement) (&x->v);
|
||||
}
|
||||
|
||||
/* DEC */
|
||||
|
||||
inline void ddsrt_atomic_dec32 (volatile ddsrt_atomic_uint32_t *x) {
|
||||
InterlockedDecrement (&x->v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
InterlockedDecrement64 (&x->v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_decptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
DDSRT_ATOMIC_PTROP (InterlockedDecrement) (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return InterlockedDecrement (&x->v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return InterlockedDecrement64 (&x->v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_decptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedDecrement) (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_dec32_ov (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return InterlockedDecrement (&x->v) + 1;
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_dec64_ov (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return InterlockedDecrement64 (&x->v) + 1;
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_decptr_ov (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedDecrement) (&x->v) + 1;
|
||||
}
|
||||
|
||||
/* ADD */
|
||||
|
||||
inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
InterlockedExchangeAdd (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
InterlockedExchangeAdd64 (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
ddsrt_atomic_addptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return InterlockedExchangeAdd (&x->v, v) + v;
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return InterlockedExchangeAdd64 (&x->v, v) + v;
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_addptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, v) + v;
|
||||
}
|
||||
inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return (void *) ddsrt_atomic_addptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
|
||||
/* SUB */
|
||||
|
||||
inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
/* disable unary minus applied to unsigned type, result still unsigned */
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
InterlockedExchangeAdd (&x->v, -v);
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
/* disable unary minus applied to unsigned type, result still unsigned */
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
InterlockedExchangeAdd64 (&x->v, -v);
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
/* disable unary minus applied to unsigned type, result still unsigned */
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v);
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
}
|
||||
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
ddsrt_atomic_subptr ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
/* disable unary minus applied to unsigned type, result still unsigned */
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
return InterlockedExchangeAdd (&x->v, -v) - v;
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
/* disable unary minus applied to unsigned type, result still unsigned */
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
return InterlockedExchangeAdd64 (&x->v, -v) - v;
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
/* disable unary minus applied to unsigned type, result still unsigned */
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v) - v;
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
}
|
||||
inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return (void *) ddsrt_atomic_subptr_nv ((volatile ddsrt_atomic_uintptr_t *) x, (uintptr_t) v);
|
||||
}
|
||||
|
||||
/* AND */
|
||||
|
||||
inline void ddsrt_atomic_and32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
InterlockedAnd (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
InterlockedAnd64 (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_andptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
DDSRT_ATOMIC_PTROP (InterlockedAnd) (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_and32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return InterlockedAnd (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return InterlockedAnd64 (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_andptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedAnd) (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_and32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return InterlockedAnd (&x->v, v) & v;
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return InterlockedAnd64 (&x->v, v) & v;
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_andptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedAnd) (&x->v, v) & v;
|
||||
}
|
||||
|
||||
/* OR */
|
||||
|
||||
inline void ddsrt_atomic_or32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
InterlockedOr (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
InterlockedOr64 (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline void ddsrt_atomic_orptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
DDSRT_ATOMIC_PTROP (InterlockedOr) (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_or32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return InterlockedOr (&x->v, v);
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return InterlockedOr64 (&x->v, v);
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_orptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedOr) (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_or32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return InterlockedOr (&x->v, v) | v;
|
||||
}
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
inline uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return InterlockedOr64 (&x->v, v) | v;
|
||||
}
|
||||
#endif
|
||||
inline uintptr_t ddsrt_atomic_orptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedOr) (&x->v, v) | v;
|
||||
}
|
||||
|
||||
/* FENCES */
|
||||
|
||||
inline void ddsrt_atomic_fence (void) {
|
||||
/* 28113: accessing a local variable tmp via an Interlocked
|
||||
function: This is an unusual usage which could be reconsidered.
|
||||
It is too heavyweight, true, but it does the trick. */
|
||||
DDSRT_WARNING_MSVC_OFF(28113)
|
||||
volatile LONG tmp = 0;
|
||||
InterlockedExchange (&tmp, 0);
|
||||
DDSRT_WARNING_MSVC_ON(28113)
|
||||
}
|
||||
inline void ddsrt_atomic_fence_ldld (void) {
|
||||
#if !(defined _M_IX86 || defined _M_X64)
|
||||
ddsrt_atomic_fence ();
|
||||
#endif
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_rel (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
|
||||
#undef DDSRT_ATOMIC_PTROP
|
||||
|
||||
#endif /* DDSRT_ATOMICS_MSVC_H */
|
||||
|
||||
241
src/ddsrt/include/dds/ddsrt/atomics/sun.h
Normal file
241
src/ddsrt/include/dds/ddsrt/atomics/sun.h
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <atomic.h>
|
||||
|
||||
#define DDSRT_ATOMIC64_SUPPORT 1
|
||||
|
||||
/* LD, ST */
|
||||
|
||||
inline uint32_t ddsrt_atomic_ld32 (const volatile ddsrt_atomic_uint32_t *x) { return x->v; }
|
||||
inline uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x) { return x->v; }
|
||||
inline uintptr_t ddsrt_atomic_ldptr (const volatile ddsrt_atomic_uintptr_t *x) { return x->v; }
|
||||
inline void *ddsrt_atomic_ldvoidp (const volatile ddsrt_atomic_voidp_t *x) { return (void *) ddsrt_atomic_ldptr (x); }
|
||||
|
||||
inline void ddsrt_atomic_st32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_stptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) { x->v = v; }
|
||||
inline void ddsrt_atomic_stvoidp (volatile ddsrt_atomic_voidp_t *x, void *v) { ddsrt_atomic_stptr (x, (uintptr_t) v); }
|
||||
|
||||
/* INC */
|
||||
|
||||
inline void ddsrt_atomic_inc32 (volatile ddsrt_atomic_uint32_t *x) {
|
||||
atomic_inc_32 (&x->v);
|
||||
}
|
||||
inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
atomic_inc_64 (&x->v);
|
||||
}
|
||||
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
atomic_inc_ulong (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return atomic_inc_32_nv (&x->v);
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return atomic_inc_64_nv (&x->v);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_incptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return atomic_inc_ulong_nv (&x->v);
|
||||
}
|
||||
|
||||
/* DEC */
|
||||
|
||||
inline void ddsrt_atomic_dec32 (volatile ddsrt_atomic_uint32_t *x) {
|
||||
atomic_dec_32 (&x->v);
|
||||
}
|
||||
inline void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
atomic_dec_64 (&x->v);
|
||||
}
|
||||
inline void ddsrt_atomic_decptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
atomic_dec_ulong (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return atomic_dec_32_nv (&x->v);
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return atomic_dec_64_nv (&x->v);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_decptr_nv (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
return atomic_dec_ulong_nv (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_dec32_ov (volatile ddsrt_atomic_uint32_t *x) {
|
||||
uint32_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval - 1; } while (atomic_cas_32 (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_dec64_ov (volatile ddsrt_atomic_uint64_t *x) {
|
||||
uint64_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval - 1; } while (atomic_cas_64 (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_decptr_ov (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
uintptr_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval - 1; } while (atomic_cas_64 (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
|
||||
/* ADD */
|
||||
|
||||
inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
atomic_add_32 (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
atomic_add_64 (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
atomic_add_long (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
atomic_add_ptr (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return atomic_add_32_nv (&x->v, v);
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return atomic_add_64_nv (&x->v, v);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_addptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return atomic_add_long_nv (&x->v, v);
|
||||
}
|
||||
inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return atomic_add_ptr_nv (&x->v, v);
|
||||
}
|
||||
|
||||
/* SUB */
|
||||
|
||||
inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
atomic_add_32 (&x->v, -v);
|
||||
}
|
||||
inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
atomic_add_64 (&x->v, -v);
|
||||
}
|
||||
inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
atomic_add_long (&x->v, -v);
|
||||
}
|
||||
inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
atomic_add_ptr (&x->v, -v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return atomic_add_32_nv (&x->v, -v);
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return atomic_add_64_nv (&x->v, -v);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return atomic_add_long_nv (&x->v, -v);
|
||||
}
|
||||
inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v) {
|
||||
return atomic_add_ptr_nv (&x->v, -v);
|
||||
}
|
||||
|
||||
/* AND */
|
||||
|
||||
inline void ddsrt_atomic_and32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
atomic_and_32 (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
atomic_and_64 (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_andptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
atomic_and_ulong (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_and32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
uint32_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval & v; } while (atomic_cas_32 (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
uint64_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval & v; } while (atomic_cas_64 (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_andptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
uintptr_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval & v; } while (atomic_cas_ulong (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_and32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return atomic_and_32_nv (&x->v, v);
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return atomic_and_64_nv (&x->v, v);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_andptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return atomic_and_ulong_nv (&x->v, v);
|
||||
}
|
||||
|
||||
/* OR */
|
||||
|
||||
inline void ddsrt_atomic_or32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
atomic_or_32 (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
atomic_or_64 (&x->v, v);
|
||||
}
|
||||
inline void ddsrt_atomic_orptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
atomic_or_ulong (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_or32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
uint32_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval | v; } while (atomic_cas_32 (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
uint64_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval | v; } while (atomic_cas_64 (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_orptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
uintptr_t oldval, newval;
|
||||
do { oldval = x->v; newval = oldval | v; } while (atomic_cas_ulong (&x->v, oldval, newval) != oldval);
|
||||
return oldval;
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_or32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return atomic_or_32_nv (&x->v, v);
|
||||
}
|
||||
inline uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v) {
|
||||
return atomic_or_64_nv (&x->v, v);
|
||||
}
|
||||
inline uintptr_t ddsrt_atomic_orptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
return atomic_or_ulong_nv (&x->v, v);
|
||||
}
|
||||
|
||||
/* CAS */
|
||||
|
||||
inline int ddsrt_atomic_cas32 (volatile ddsrt_atomic_uint32_t *x, uint32_t exp, uint32_t des) {
|
||||
return atomic_cas_32 (&x->v, exp, des) == exp;
|
||||
}
|
||||
inline int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des) {
|
||||
return atomic_cas_64 (&x->v, exp, des) == exp;
|
||||
}
|
||||
inline int ddsrt_atomic_casptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t exp, uintptr_t des) {
|
||||
return atomic_cas_ulong (&x->v, exp, des) == exp;
|
||||
}
|
||||
inline int ddsrt_atomic_casvoidp (volatile ddsrt_atomic_voidp_t *x, void *exp, void *des) {
|
||||
return atomic_cas_ptr (&x->v, exp, des) == exp;
|
||||
}
|
||||
|
||||
/* FENCES */
|
||||
|
||||
inline void ddsrt_atomic_fence (void) {
|
||||
membar_exit ();
|
||||
membar_enter ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_ldld (void) {
|
||||
membar_enter ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
membar_enter ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_rel (void) {
|
||||
membar_exit ();
|
||||
}
|
||||
|
||||
104
src/ddsrt/include/dds/ddsrt/attributes.h
Normal file
104
src/ddsrt/include/dds/ddsrt/attributes.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ATTRIBUTES_H
|
||||
#define DDSRT_ATTRIBUTES_H
|
||||
|
||||
#if __clang__
|
||||
# define ddsrt_gnuc (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#else
|
||||
# define ddsrt_gnuc (0)
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
# define ddsrt_clang (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
|
||||
#else
|
||||
# define ddsrt_clang (0)
|
||||
#endif
|
||||
|
||||
#if defined(__has_attribute)
|
||||
# define ddsrt_has_attribute(params) __has_attribute(params)
|
||||
#elif ddsrt_gnuc
|
||||
# define ddsrt_has_attribute(params) (1) /* GCC < 5 */
|
||||
#else
|
||||
# define ddsrt_has_attribute(params) (0)
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(malloc)
|
||||
# define ddsrt_attribute_malloc __attribute__ ((__malloc__))
|
||||
#else
|
||||
# define ddsrt_attribute_malloc
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(unused)
|
||||
# define ddsrt_attribute_unused __attribute__((__unused__))
|
||||
#else
|
||||
# define ddsrt_attribute_unused
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(noreturn)
|
||||
# define ddsrt_attribute_noreturn __attribute__ ((__noreturn__))
|
||||
#else
|
||||
# define ddsrt_attribute_noreturn
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(nonnull)
|
||||
# define ddsrt_nonnull(params) __attribute__ ((__nonnull__ params))
|
||||
# define ddsrt_nonnull_all __attribute__ ((__nonnull__))
|
||||
#else
|
||||
# define ddsrt_nonnull(params)
|
||||
# define ddsrt_nonnull_all
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(returns_nonnull) && (ddsrt_clang || ddsrt_gnuc >= 40900)
|
||||
# define ddsrt_attribute_returns_nonnull __attribute__ ((__returns_nonnull__))
|
||||
#else
|
||||
# define ddsrt_attribute_returns_nonnull
|
||||
#endif
|
||||
|
||||
/* GCC <= 4.2.4 has the attribute, but warns that it ignores it. */
|
||||
#if !ddsrt_has_attribute(alloc_size) || (ddsrt_gnuc <= 40204)
|
||||
# define ddsrt_attribute_alloc_size(params)
|
||||
#else
|
||||
# define ddsrt_attribute_alloc_size(params) __attribute__ ((__alloc_size__ params))
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(const)
|
||||
# define ddsrt_attribute_const __attribute__ ((__const__))
|
||||
#else
|
||||
# define ddsrt_attribute_const
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(pure)
|
||||
# define ddsrt_attribute_pure __attribute__ ((__pure__))
|
||||
#else
|
||||
# define ddsrt_attribute_pure
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(format)
|
||||
# define ddsrt_attribute_format(params) __attribute__ ((__format__ params))
|
||||
#else
|
||||
# define ddsrt_attribute_format(params)
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(warn_unused_result)
|
||||
# define ddsrt_attribute_warn_unused_result __attribute__ ((__warn_unused_result__))
|
||||
#else
|
||||
# define ddsrt_attribute_warn_unused_result
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(assume_aligned)
|
||||
# define ddsrt_attribute_assume_aligned(params) __attribute__ ((__assume_aligned__ params))
|
||||
#else
|
||||
# define ddsrt_attribute_assume_aligned(params)
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_ATTRIBUTES_H */
|
||||
24
src/ddsrt/include/dds/ddsrt/cdtors.h
Normal file
24
src/ddsrt/include/dds/ddsrt/cdtors.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_CDTORS_H
|
||||
#define DDSRT_CDTORS_H
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
|
||||
DDS_EXPORT void ddsrt_init(void);
|
||||
|
||||
DDS_EXPORT void ddsrt_fini(void);
|
||||
|
||||
DDS_EXPORT ddsrt_mutex_t *ddsrt_get_singleton_mutex(void);
|
||||
|
||||
#endif /* DDSRT_CDTORS_H */
|
||||
47
src/ddsrt/include/dds/ddsrt/endian.h
Normal file
47
src/ddsrt/include/dds/ddsrt/endian.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ENDIAN_H
|
||||
#define DDSRT_ENDIAN_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DDSRT_LITTLE_ENDIAN 1
|
||||
#define DDSRT_BIG_ENDIAN 2
|
||||
|
||||
#if _WIN32
|
||||
# if defined(__BIG_ENDIAN)
|
||||
# define DDSRT_ENDIAN DDSRT_BIG_ENDIAN
|
||||
# else
|
||||
# define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN
|
||||
# endif
|
||||
#else /* _WIN32 */
|
||||
# if defined(__BYTE_ORDER__)
|
||||
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define DDSRT_ENDIAN DDSRT_BIG_ENDIAN
|
||||
# elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN
|
||||
# endif
|
||||
# endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if (DDSRT_ENDIAN != DDSRT_LITTLE_ENDIAN) && \
|
||||
(DDSRT_ENDIAN != DDSRT_BIG_ENDIAN)
|
||||
# error "Endianness cannot be determined"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_ENDIAN_H */
|
||||
103
src/ddsrt/include/dds/ddsrt/environ.h
Normal file
103
src/ddsrt/include/dds/ddsrt/environ.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_ENVIRON_H
|
||||
#define DDSRT_ENVIRON_H
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get value for environment variable.
|
||||
*
|
||||
* @param[in] name Environment variable name.
|
||||
* @param[in] buf Buffer to write value to.
|
||||
* @param[in] sz Size of buffer.
|
||||
* @param[out] reqsz Number of bytes written (excluding the terminating null
|
||||
* byte), or would have been written would @buf have been
|
||||
* sufficiently large enough.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Environment variable written to @buf.
|
||||
* @retval DDS_RETCODE_NOT_FOUND
|
||||
* Environment variable not found.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* FIXME: document
|
||||
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||
* FIXME: document
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* Unspecified error.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_getenv(
|
||||
const char *name,
|
||||
char **value)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Set environment variable value.
|
||||
*
|
||||
* Sets the environment variable to the value specified in value, or
|
||||
* alternatively, unsets the environment variable if value is an empty string.
|
||||
*
|
||||
* @param[in] name Environment variable name.
|
||||
* @param[in] value Value to set environment variable to.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Environment variable successfully set to @value.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Invalid environment variable name.
|
||||
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||
* Not enough system resources to set environment variable.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* Unspecified system error.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_setenv(
|
||||
const char *name,
|
||||
const char *value)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Unset environment variable value.
|
||||
*
|
||||
* @param[in] name Environment variable name.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Environment variable successfully unset.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Invalid environment variable name.
|
||||
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||
* Not enough system resources to unset environment variable.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* Unspecified system error.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_unsetenv(
|
||||
const char *name)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_ENVIRON_H */
|
||||
155
src/ddsrt/include/dds/ddsrt/heap.h
Normal file
155
src/ddsrt/include/dds/ddsrt/heap.h
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
/**
|
||||
* @file heap.h
|
||||
* @brief Heap memory management.
|
||||
*
|
||||
* Platform independent interface to heap memory management.
|
||||
*/
|
||||
#ifndef DDSRT_HEAP_H
|
||||
#define DDSRT_HEAP_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Allocate memory from heap.
|
||||
*
|
||||
* The allocated block of memory must be freed by calling @ddsrt_free when no
|
||||
* longer used.
|
||||
*
|
||||
* @param[in] size The size, in bytes, of the block of memory to allocate.
|
||||
*
|
||||
* @returns A pointer to the allocated block of memory. abort() is called if
|
||||
* not enough free memory was available.
|
||||
*/
|
||||
DDS_EXPORT void *
|
||||
ddsrt_malloc(
|
||||
size_t size)
|
||||
ddsrt_attribute_malloc
|
||||
ddsrt_attribute_alloc_size((1));
|
||||
|
||||
/**
|
||||
* @brief Allocate memory from heap.
|
||||
*
|
||||
* Allocate a block of memory from heap with the given size. The allocated
|
||||
* block of memory must be freed by calling @ddsrt_free when no longer used.
|
||||
*
|
||||
* @param[in] size The size, in bytes, of memory to allocate.
|
||||
*
|
||||
* @returns A pointer to the allocated block of memory, NULL if not enough
|
||||
* memory was available.
|
||||
*/
|
||||
DDS_EXPORT void *
|
||||
ddsrt_malloc_s(
|
||||
size_t size)
|
||||
ddsrt_attribute_malloc
|
||||
ddsrt_attribute_alloc_size((1));
|
||||
|
||||
/**
|
||||
* @brief Allocate memory from heap for an array of @count elements of @size
|
||||
* bytes.
|
||||
*
|
||||
* The allocated memory is initialized to zero. The allocated memory must be
|
||||
* freed by calling @ddsrt_free when no longer used.
|
||||
*
|
||||
* A non-NULL pointer, that must be freed is always returned, even if the sum
|
||||
* @count and @size equals zero.
|
||||
*
|
||||
* @returns A pointer to the allocated memory. abort() is called if not enough
|
||||
* free memory was available.
|
||||
*/
|
||||
DDS_EXPORT void *
|
||||
ddsrt_calloc(
|
||||
size_t count,
|
||||
size_t size)
|
||||
ddsrt_attribute_malloc
|
||||
ddsrt_attribute_alloc_size((1,2));
|
||||
|
||||
/**
|
||||
* @brief Allocate memory from heap for an array of @count elements of @size
|
||||
* bytes.
|
||||
*
|
||||
* The allocated memory is initialized to zero. The allocated memory must be
|
||||
* freed by calling @ddsrt_free when no longer used.
|
||||
*
|
||||
* A non-NULL pointer, that must be freed is always returned, even if the sum
|
||||
* @count and @size equals zero.
|
||||
*
|
||||
* @returns A pointer to the allocated memory, or NULL if not enough memory was
|
||||
* available.
|
||||
*/
|
||||
DDS_EXPORT void *
|
||||
ddsrt_calloc_s(
|
||||
size_t count,
|
||||
size_t size)
|
||||
ddsrt_attribute_malloc
|
||||
ddsrt_attribute_alloc_size((1,2));
|
||||
|
||||
/**
|
||||
* @brief Reallocate memory from heap.
|
||||
*
|
||||
* Reallocate memory from heap. If memblk is NULL the function returns
|
||||
* ddsrt_malloc_s(size). If size is 0, ddsrt_realloc_s free's the memory
|
||||
* pointed to by memblk and returns a pointer as if ddsrt_malloc_s(0) was
|
||||
* invoked. The returned pointer must be free'd with ddsrt_free.
|
||||
*
|
||||
* @returns A pointer to reallocated memory. Calls abort() if not enough free
|
||||
* memory was available.
|
||||
*/
|
||||
DDS_EXPORT void *
|
||||
ddsrt_realloc(
|
||||
void *memblk,
|
||||
size_t size)
|
||||
ddsrt_attribute_malloc
|
||||
ddsrt_attribute_alloc_size((2));
|
||||
|
||||
/**
|
||||
* @brief Reallocate memory from heap.
|
||||
*
|
||||
* Reallocate memory from heap. If memblk is NULL the function returns
|
||||
* ddsrt_malloc_s(size). If size is 0, ddsrt_realloc_s free's the memory
|
||||
* pointed to by memblk and returns a pointer as if ddsrt_malloc_s(0) was
|
||||
* invoked. The returned pointer must be free'd with ddsrt_free.
|
||||
*
|
||||
* @returns A pointer to reallocated memory, or NULL if not enough free memory
|
||||
* was available.
|
||||
*/
|
||||
DDS_EXPORT void *
|
||||
ddsrt_realloc_s(
|
||||
void *memblk,
|
||||
size_t size)
|
||||
ddsrt_attribute_malloc
|
||||
ddsrt_attribute_alloc_size((2));
|
||||
|
||||
/**
|
||||
* @brief Free a previously allocated block of memory and return it to heap.
|
||||
*
|
||||
* Free the allocated memory pointed to by @ptr and release it to the heap. No
|
||||
* action will be taken if @ptr is NULL.
|
||||
*
|
||||
* @param[in] ptr Pointer to previously allocated block of memory.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_free(void *ptr);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_HEAP_H */
|
||||
46
src/ddsrt/include/dds/ddsrt/ifaddrs.h
Normal file
46
src/ddsrt/include/dds/ddsrt/ifaddrs.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_IFADDRS_H
|
||||
#define DDSRT_IFADDRS_H
|
||||
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ddsrt_ifaddrs {
|
||||
struct ddsrt_ifaddrs *next;
|
||||
char *name;
|
||||
uint32_t index;
|
||||
uint32_t flags;
|
||||
struct sockaddr *addr;
|
||||
struct sockaddr *netmask;
|
||||
struct sockaddr *broadaddr;
|
||||
};
|
||||
|
||||
typedef struct ddsrt_ifaddrs ddsrt_ifaddrs_t;
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const int *afs);
|
||||
|
||||
DDS_EXPORT void
|
||||
ddsrt_freeifaddrs(
|
||||
ddsrt_ifaddrs_t *ifa);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_IFADDRS_H */
|
||||
41
src/ddsrt/include/dds/ddsrt/io.h
Normal file
41
src/ddsrt/include/dds/ddsrt/io.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_IO_H
|
||||
#define DDSRT_IO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Write a formatted string to a newly allocated buffer.
|
||||
*/
|
||||
DDS_EXPORT int
|
||||
ddsrt_asprintf(
|
||||
char **strp,
|
||||
const char *fmt,
|
||||
...);
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
extern int snprintf(char *s, size_t n, const char *format, ...);
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_IO_H */
|
||||
302
src/ddsrt/include/dds/ddsrt/log.h
Normal file
302
src/ddsrt/include/dds/ddsrt/log.h
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @brief DDS C Logging API
|
||||
*
|
||||
* This header file defines the public API for logging and controlling logging
|
||||
* in the DDS C language binding.
|
||||
*/
|
||||
#ifndef DDS_LOG_H
|
||||
#define DDS_LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup log_categories Convenience log category definitions.
|
||||
*
|
||||
* These defines expand into numeric values that can be ORed together to
|
||||
* specify messages of which categories must be passed to the respective sinks.
|
||||
*
|
||||
* Every category other than DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING and
|
||||
* DDS_LC_INFO automatically falls into the trace category.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/** Fatal error condition. Immediate abort on sink return. */
|
||||
#define DDS_LC_FATAL (1u)
|
||||
/** Error condition. */
|
||||
#define DDS_LC_ERROR (2u)
|
||||
/** Warning condition. */
|
||||
#define DDS_LC_WARNING (4u)
|
||||
/** Informational message. */
|
||||
#define DDS_LC_INFO (8u)
|
||||
/** Debug/trace messages related to configuration settings. */
|
||||
#define DDS_LC_CONFIG (16u)
|
||||
/** Debug/trace messages related to node discovery. */
|
||||
#define DDS_LC_DISCOVERY (32u)
|
||||
/** Currently unused. */
|
||||
#define DDS_LC_DATA (64u)
|
||||
/** Debug/trace messages for which no specialized category exists (yet). */
|
||||
#define DDS_LC_TRACE (128u)
|
||||
/** Debug/trace messages related to receive administration. */
|
||||
#define DDS_LC_RADMIN (256u)
|
||||
/** Debug/trace messages related to timing. */
|
||||
#define DDS_LC_TIMING (512u)
|
||||
/** Debug/trace messages related to send administration. */
|
||||
#define DDS_LC_TRAFFIC (1024u)
|
||||
/** Currently unused. */
|
||||
#define DDS_LC_TOPIC (2048u)
|
||||
/** Debug/trace messages related to TCP communication. */
|
||||
#define DDS_LC_TCP (4096u)
|
||||
/** Debug/trace messages related to parameter list processing. */
|
||||
#define DDS_LC_PLIST (8192u)
|
||||
/** Debug/trace messages related to the writer history cache. */
|
||||
#define DDS_LC_WHC (16384u)
|
||||
/** Debug/trace messages related to throttling. */
|
||||
#define DDS_LC_THROTTLE (32768u)
|
||||
/** All common trace categories. */
|
||||
#define DDS_LC_RHC (65536u)
|
||||
/** All common trace categories. */
|
||||
#define DDS_LC_ALL \
|
||||
(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_INFO | \
|
||||
DDS_LC_CONFIG | DDS_LC_DISCOVERY | DDS_LC_DATA | DDS_LC_TRACE | \
|
||||
DDS_LC_TIMING | DDS_LC_TRAFFIC | DDS_LC_TCP | DDS_LC_THROTTLE)
|
||||
/** @}*/
|
||||
|
||||
#define DDS_LOG_MASK \
|
||||
(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_INFO)
|
||||
|
||||
#define DDS_TRACE_MASK \
|
||||
(~DDS_LOG_MASK)
|
||||
|
||||
/** Structure with log message and meta data passed to callbacks. */
|
||||
typedef struct {
|
||||
/** Log category the message falls into. */
|
||||
uint32_t priority;
|
||||
/** Filename where message was generated. */
|
||||
const char *file;
|
||||
/** Line number in file where message was generated. */
|
||||
uint32_t line;
|
||||
/** Name of function message where message was generated. */
|
||||
const char *function;
|
||||
/** Log message. */
|
||||
const char *message;
|
||||
/** Size of log message. */
|
||||
size_t size;
|
||||
} dds_log_data_t;
|
||||
|
||||
/** Function signature that log and trace callbacks must adhere too. */
|
||||
typedef void(*dds_log_write_fn_t)(void *, const dds_log_data_t *);
|
||||
|
||||
extern uint32_t *const dds_log_mask;
|
||||
|
||||
/**
|
||||
* @brief Get currently enabled log and trace categories.
|
||||
*
|
||||
* @returns A uint32_t with enabled categories set.
|
||||
*/
|
||||
inline uint32_t
|
||||
dds_get_log_mask(void)
|
||||
{
|
||||
return *dds_log_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set enabled log and trace categories.
|
||||
*
|
||||
* @param[in] cats Log and trace categories to enable.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_set_log_mask(
|
||||
uint32_t cats);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_set_log_file(
|
||||
FILE *file);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_set_trace_file(
|
||||
FILE *file);
|
||||
|
||||
/**
|
||||
* @brief Register callback to receive log messages
|
||||
*
|
||||
* Callbacks registered to handle log messages will receive messages of type
|
||||
* info, warning, error and fatal. Messages that fall into the trace category
|
||||
* will never be delivered to the callback.
|
||||
*
|
||||
* This operation is synchronous and only returns once the operation is
|
||||
* registered with all threads. Meaning that neither callback or userdata will
|
||||
* be referenced by the DDS stack on return.
|
||||
*
|
||||
* @param[in] callback Function pointer matching dds_log_write_fn signature
|
||||
* or a null pointer to restore the default sink.
|
||||
* @param[in] userdata User specified data passed along with each invocation
|
||||
* of callback.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_set_log_sink(
|
||||
dds_log_write_fn_t callback,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Register callback to receive trace messages
|
||||
*
|
||||
* Callbacks registered to handle trace messages will receive messages of type
|
||||
* info, warning, error and fatal as well as all message types that fall into
|
||||
* the trace category depending on the log mask.
|
||||
*
|
||||
* This operation is synchronous and only returns once the operation is
|
||||
* registered with all threads. Meaning that neither callback or
|
||||
* userdata will be referenced by the DDS stack on return.
|
||||
*
|
||||
* @param[in] callback Function pointer matching dds_log_write_fn_t signature
|
||||
* or a null pointer to restore the default sink.
|
||||
* @param[in] userdata User specified data passed along with each invocation
|
||||
* of callback.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_set_trace_sink(
|
||||
dds_log_write_fn_t callback,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Write a log or trace message.
|
||||
*
|
||||
* Write a log or trace message to one (or both) of the currently active sinks.
|
||||
*
|
||||
* Direct use of #dds_log is discouraged. Use #DDS_INFO, #DDS_WARNING,
|
||||
* #DDS_ERROR, #DDS_FATAL or #DDS_LOG instead.
|
||||
*/
|
||||
DDS_EXPORT int
|
||||
dds_log(
|
||||
uint32_t prio,
|
||||
const char *file,
|
||||
uint32_t line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
...);
|
||||
|
||||
/**
|
||||
* @brief Undecorated function name of the current function.
|
||||
*
|
||||
* Behavior of DDS_FUNCTION outside a function is undefined. Note that
|
||||
* implementations differ across compilers and compiler versions. It might be
|
||||
* implemented as either a string literal or a constant variable.
|
||||
*/
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
||||
# define DDS_FUNCTION __func__
|
||||
#elif defined(__cplusplus) && (__cplusplus >= 201103)
|
||||
# define DDS_FUNCTION __func__
|
||||
#elif defined(__GNUC__)
|
||||
# define DDS_FUNCTION __FUNCTION__
|
||||
#elif defined(__clang__)
|
||||
# define DDS_FUNCTION __FUNCTION__
|
||||
#elif defined(__ghs__)
|
||||
# define DDS_FUNCTION __FUNCTION__
|
||||
#elif (defined(__SUNPRO_C) || defined(__SUNPRO_CC))
|
||||
/* Solaris Studio had support for __func__ before it supported __FUNCTION__.
|
||||
Compiler flag -features=extensions is required on older versions. */
|
||||
# define DDS_FUNCTION __func__
|
||||
#elif defined(__FUNCTION__)
|
||||
/* Visual Studio */
|
||||
# define DDS_FUNCTION __FUNCTION__
|
||||
#elif defined(__vxworks)
|
||||
/* At least versions 2.9.6 and 3.3.4 of the GNU C Preprocessor only define
|
||||
__GNUC__ if the entire GNU C compiler is in use. VxWorks 5.5 targets invoke
|
||||
the preprocessor separately resulting in __GNUC__ not being defined. */
|
||||
# define DDS_FUNCTION __FUNCTION__
|
||||
#else
|
||||
# warning "DDS_FUNCTION is not supported"
|
||||
# define DDS_FUNCTION ""
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function signature of the current function.
|
||||
*
|
||||
* See comments on DDS_FUNCTION for details.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
# define DDS_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#elif defined(__clang__)
|
||||
# define DDS_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#elif defined(__ghs__)
|
||||
# define DDS_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#elif (defined(__SUNPRO_C) && __SUNPRO_C >= 0x5100)
|
||||
/* Solaris Studio supports __PRETTY_FUNCTION__ in C since version 12.1 */
|
||||
# define DDS_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#elif (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5120)
|
||||
/* Solaris Studio supports __PRETTY_FUNCTION__ in C++ since version 12.3 */
|
||||
# define DDS_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#elif defined(__FUNCSIG__)
|
||||
/* Visual Studio */
|
||||
# define DDS_PRETTY_FUNCTION __FUNCSIG__
|
||||
#elif defined(__vxworks)
|
||||
/* See comments on __vxworks macro above. */
|
||||
# define DDS_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
||||
#else
|
||||
/* Fall back to DDS_FUNCTION. */
|
||||
# define DDS_PRETTY_FUNCTION DDS_FUNCTION
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Write a log message.
|
||||
*
|
||||
* Write a log or trace message to the currently active log and/or trace sinks
|
||||
* if the log category is enabled. Whether or not the category is enabled is
|
||||
* checked before any dds_log-related activities to save a couple of % CPU.
|
||||
*
|
||||
* Only messages that fall into one of the log categories are passed onto
|
||||
* dds_log. While messages that fall into a trace category could have been
|
||||
* passed just as easily, they are rejected so that tracing is kept entirely
|
||||
* separate from logging, if only cosmetic.
|
||||
*/
|
||||
#define DDS_LOG(cat, ...) \
|
||||
((dds_get_log_mask() & (cat)) ? \
|
||||
dds_log(cat, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
|
||||
|
||||
/** Write a log message of type #DDS_LC_INFO. */
|
||||
#define DDS_INFO(...) \
|
||||
DDS_LOG(DDS_LC_INFO, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_WARNING. */
|
||||
#define DDS_WARNING(...) \
|
||||
DDS_LOG(DDS_LC_WARNING, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_ERROR. */
|
||||
#define DDS_ERROR(...) \
|
||||
DDS_LOG(DDS_LC_ERROR, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_ERROR and abort. */
|
||||
#define DDS_FATAL(...) \
|
||||
dds_log(DDS_LC_FATAL, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__)
|
||||
/** Write a #DDS_LC_TRACE message. */
|
||||
#define DDS_TRACE(...) \
|
||||
DDS_LOG(DDS_LC_TRACE, __VA_ARGS__)
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDS_LOG_H */
|
||||
81
src/ddsrt/include/dds/ddsrt/misc.h
Normal file
81
src/ddsrt/include/dds/ddsrt/misc.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_MISC_H
|
||||
#define DDSRT_MISC_H
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
|
||||
# define DDSRT_GNUC_STR(s) #s
|
||||
# define DDSRT_GNUC_JOINSTR(x,y) DDSRT_GNUC_DIAG_STR(x ## y)
|
||||
# define DDSRT_GNUC_DO_PRAGMA(x) _Pragma (#x)
|
||||
# define DDSRT_GNUC_PRAGMA(x) DDSRT_GNUC_DO_PRAGMA(GCC diagnostic x)
|
||||
# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
|
||||
# define DDSRT_WARNING_GNUC_OFF(x) \
|
||||
DDSRT_GNUC_PRAGMA(push) \
|
||||
DDSRT_GNUC_PRAGMA(ignored DDSRT_GNUC_JOINSTR(-W,x))
|
||||
# define DDSRT_WARNING_GNUC_ON(x) \
|
||||
DDSRT_GNUC_PRAGMA(pop)
|
||||
# else
|
||||
# define DDSRT_WARNING_GNUC_OFF(x) \
|
||||
DDSRT_GNUC_PRAGMA(ignored DDSRT_GNUC_JOINSTR(-W,x))
|
||||
# define DDSRT_WARNING_GNUC_ON(x) \
|
||||
DDSRT_GNUC_PRAGMA(warning DDSRT_GNUC_JOINSTR(-W,x))
|
||||
# endif
|
||||
#else
|
||||
# define DDSRT_WARNING_GNUC_OFF(x)
|
||||
# define DDSRT_WARNING_GNUC_ON(x)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define DDSRT_WARNING_MSVC_OFF(x) \
|
||||
__pragma (warning(push)) \
|
||||
__pragma (warning(disable: ## x))
|
||||
# define DDSRT_WARNING_MSVC_ON(x) \
|
||||
__pragma (warning(pop))
|
||||
#else
|
||||
# define DDSRT_WARNING_MSVC_OFF(x)
|
||||
# define DDSRT_WARNING_MSVC_ON(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Calculate maximum value of an integer type
|
||||
*
|
||||
* A somewhat complex, but efficient way to calculate the maximum value of an
|
||||
* integer type at compile time.
|
||||
*
|
||||
* For unsigned numerical types the first part up to XOR is enough. The second
|
||||
* part is to make up for signed numerical types.
|
||||
*/
|
||||
#define DDSRT_MAX_INTEGER(T) \
|
||||
((T)(((T)~0) ^ ((T)!((T)~0 > 0) << (CHAR_BIT * sizeof(T) - 1))))
|
||||
/**
|
||||
* @brief Calculate minimum value of an integer type
|
||||
*/
|
||||
#define DDSRT_MIN_INTEGER(T) \
|
||||
((-DDSRT_MAX_INTEGER(T)) - 1)
|
||||
|
||||
/**
|
||||
* @brief Macro to disable unused argument warnings
|
||||
*/
|
||||
#define DDSRT_UNUSED_ARG(a) (void)(a)
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_MISC_H */
|
||||
48
src/ddsrt/include/dds/ddsrt/process.h
Normal file
48
src/ddsrt/include/dds/ddsrt/process.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_PROCESS_H
|
||||
#define DDSRT_PROCESS_H
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/types.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
typedef DWORD ddsrt_pid_t;
|
||||
#define PRIdPID "u"
|
||||
#else /* _WIN32 */
|
||||
#include <unistd.h>
|
||||
#if defined(_WRS_KERNEL)
|
||||
typedef RTP_ID ddsrt_pid_t; /* typedef struct wind_rtp *RTP_ID */
|
||||
#define PRIdPID PRIuPTR
|
||||
#else
|
||||
typedef pid_t ddsrt_pid_t;
|
||||
#define PRIdPID "d"
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/**
|
||||
* @brief Return process ID (PID) of the calling process.
|
||||
*
|
||||
* @returns The process ID of the calling process.
|
||||
*/
|
||||
DDS_EXPORT ddsrt_pid_t
|
||||
ddsrt_getpid(void);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_PROCESS_H */
|
||||
27
src/ddsrt/include/dds/ddsrt/random.h
Normal file
27
src/ddsrt/include/dds/ddsrt/random.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_RANDOM_H
|
||||
#define DDSRT_RANDOM_H
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DDS_EXPORT long ddsrt_random(void);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_RANDOM_H */
|
||||
89
src/ddsrt/include/dds/ddsrt/retcode.h
Normal file
89
src/ddsrt/include/dds/ddsrt/retcode.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef DDS_RETCODE_H
|
||||
#define DDS_RETCODE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
typedef int32_t dds_retcode_t;
|
||||
|
||||
/*
|
||||
State is unchanged following a function call returning an error
|
||||
other than UNSPECIFIED, OUT_OF_RESOURCES and ALREADY_DELETED.
|
||||
|
||||
Error handling functions. Three components to returned int status value.
|
||||
|
||||
1 - The DDS_ERR_xxx error number
|
||||
2 - The file identifier
|
||||
3 - The line number
|
||||
|
||||
All functions return >= 0 on success, < 0 on error
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name DDS_Error_Type
|
||||
* @{
|
||||
*/
|
||||
#define DDS_RETCODE_OK 0 /**< Success */
|
||||
#define DDS_RETCODE_ERROR 1 /**< Non specific error */
|
||||
#define DDS_RETCODE_UNSUPPORTED 2 /**< Feature unsupported */
|
||||
#define DDS_RETCODE_BAD_PARAMETER 3 /**< Bad parameter value */
|
||||
#define DDS_RETCODE_PRECONDITION_NOT_MET 4 /**< Precondition for operation not met */
|
||||
#define DDS_RETCODE_OUT_OF_RESOURCES 5 /**< When an operation fails because of a lack of resources */
|
||||
#define DDS_RETCODE_NOT_ENABLED 6 /**< When a configurable feature is not enabled */
|
||||
#define DDS_RETCODE_IMMUTABLE_POLICY 7 /**< When an attempt is made to modify an immutable policy */
|
||||
#define DDS_RETCODE_INCONSISTENT_POLICY 8 /**< When a policy is used with inconsistent values */
|
||||
#define DDS_RETCODE_ALREADY_DELETED 9 /**< When an attempt is made to delete something more than once */
|
||||
#define DDS_RETCODE_TIMEOUT 10 /**< When a timeout has occurred */
|
||||
#define DDS_RETCODE_NO_DATA 11 /**< When expected data is not provided */
|
||||
#define DDS_RETCODE_ILLEGAL_OPERATION 12 /**< When a function is called when it should not be */
|
||||
#define DDS_RETCODE_NOT_ALLOWED_BY_SECURITY 13 /**< When credentials are not enough to use the function */
|
||||
|
||||
|
||||
/* Extended return codes are not in the DDS specification and are meant
|
||||
exclusively for internal use and must not be returned by the C API. */
|
||||
#define DDS_XRETCODE_BASE (50)
|
||||
#define DDS_XRETCODE(x) (DDS_XRETCODE_BASE + (x))
|
||||
|
||||
/** Requested resource is busy */
|
||||
#define DDS_RETCODE_IN_PROGRESS DDS_XRETCODE(1)
|
||||
/** Resource unavailable, try again */
|
||||
#define DDS_RETCODE_TRY_AGAIN DDS_XRETCODE(2)
|
||||
/** Operation was interrupted */
|
||||
#define DDS_RETCODE_INTERRUPTED DDS_XRETCODE(3)
|
||||
/** Permission denied */
|
||||
#define DDS_RETCODE_NOT_ALLOWED DDS_XRETCODE(4)
|
||||
/** Host not found */
|
||||
#define DDS_RETCODE_HOST_NOT_FOUND DDS_XRETCODE(5)
|
||||
/** Network is not available */
|
||||
#define DDS_RETCODE_NO_NETWORK DDS_XRETCODE(6)
|
||||
/** Connection is not available */
|
||||
#define DDS_RETCODE_NO_CONNECTION DDS_XRETCODE(7)
|
||||
/* Host not reachable is used to indicate that a connection was refused
|
||||
(ECONNREFUSED), reset by peer (ECONNRESET) or that a host or network cannot
|
||||
be reached (EHOSTUNREACH, ENETUNREACH). Generally all system errors that
|
||||
indicate a connection cannot be made or that a message cannot be delivered,
|
||||
map onto host not reachable. */
|
||||
/** Not enough space available */
|
||||
#define DDS_RETCODE_NOT_ENOUGH_SPACE DDS_XRETCODE(8)
|
||||
/* Not enough space is used to indicate there is not enough buffer space to
|
||||
read a message from the network (i.e. EMSGSIZE), but is also used to
|
||||
indicate there is not enough space left on a device, etc. */
|
||||
/** Result too large */
|
||||
#define DDS_RETCODE_OUT_OF_RANGE DDS_XRETCODE(9)
|
||||
/** Not found */
|
||||
#define DDS_RETCODE_NOT_FOUND DDS_XRETCODE(10)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Takes the error value and outputs a string corresponding to it.
|
||||
*
|
||||
* @param[in] err Error value to be converted to a string
|
||||
*
|
||||
* @returns String corresponding to the error value
|
||||
*/
|
||||
DDS_EXPORT const char *dds_strretcode(dds_retcode_t ret);
|
||||
|
||||
#endif /* DDS_RETCODE_H */
|
||||
50
src/ddsrt/include/dds/ddsrt/rusage.h
Normal file
50
src/ddsrt/include/dds/ddsrt/rusage.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_RUSAGE_H
|
||||
#define DDSRT_RUSAGE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
typedef struct {
|
||||
dds_time_t utime; /* User CPU time used. */
|
||||
dds_time_t stime; /* System CPU time used. */
|
||||
size_t maxrss; /* Maximum resident set size in bytes. */
|
||||
size_t idrss; /* Integral unshared data size. Not maintained on (at least)
|
||||
Linux and Windows. */
|
||||
size_t nvcsw; /* Voluntary context switches. Not maintained on Windows. */
|
||||
size_t nivcsw; /* Involuntary context switches. Not maintained on Windows. */
|
||||
} ddsrt_rusage_t;
|
||||
|
||||
#define DDSRT_RUSAGE_SELF (0)
|
||||
#define DDSRT_RUSAGE_THREAD (1)
|
||||
|
||||
/**
|
||||
* @brief Get resource usage for the current thread or process.
|
||||
*
|
||||
* @param[in] who DDSRT_RUSAGE_SELF or DDSRT_RUSAGE_THREAD.
|
||||
* @param[in] usage Structure where resource usage is returned.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Resource usage successfully returned in @usage.
|
||||
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||
* There were not enough resources to get resource usage.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An unidentified error occurred.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage);
|
||||
|
||||
#endif /* DDSRT_RUSAGE_H */
|
||||
262
src/ddsrt/include/dds/ddsrt/sockets.h
Normal file
262
src/ddsrt/include/dds/ddsrt/sockets.h
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
#ifndef DDSRT_SOCKETS_H
|
||||
#define DDSRT_SOCKETS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/types.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
#if !defined(_WIN32)
|
||||
#include "dds/ddsrt/sockets/posix.h"
|
||||
#else
|
||||
#include "dds/ddsrt/sockets/windows.h"
|
||||
#endif
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
#define INET6_ADDRSTRLEN_EXTENDED (INET6_ADDRSTRLEN + 8) /* "[]:12345" */
|
||||
extern const struct in6_addr ddsrt_in6addr_any;
|
||||
extern const struct in6_addr ddsrt_in6addr_loopback;
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
|
||||
#define DDSRT_AF_TERM (-1)
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_gethostname(
|
||||
char *hostname,
|
||||
size_t buffersize);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_socket(
|
||||
ddsrt_socket_t *sockptr,
|
||||
int domain,
|
||||
int type,
|
||||
int protocol);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_close(
|
||||
ddsrt_socket_t sock);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_connect(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_accept(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen,
|
||||
ddsrt_socket_t *connptr);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_listen(
|
||||
ddsrt_socket_t sock,
|
||||
int backlog);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_bind(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_getsockname(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_send(
|
||||
ddsrt_socket_t sock,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
int flags,
|
||||
ssize_t *sent);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_sendmsg(
|
||||
ddsrt_socket_t sock,
|
||||
const ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *sent);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_recv(
|
||||
ddsrt_socket_t sock,
|
||||
void *buf,
|
||||
size_t len,
|
||||
int flags,
|
||||
ssize_t *rcvd);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_recvmsg(
|
||||
ddsrt_socket_t sock,
|
||||
ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *rcvd);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_getsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level, /* SOL_SOCKET */
|
||||
int32_t optname, /* SO_REUSEADDR, SO_DONTROUTE, SO_BROADCAST, SO_SNDBUF, SO_RCVBUF */
|
||||
void *optval,
|
||||
socklen_t *optlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_setsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level, /* SOL_SOCKET */
|
||||
int32_t optname, /* SO_REUSEADDR, SO_DONTROUTE, SO_BROADCAST, SO_SNDBUF, SO_RCVBUF */
|
||||
const void *optval,
|
||||
socklen_t optlen);
|
||||
|
||||
/**
|
||||
* @brief Set the I/O on the socket to blocking or non-nonblocking.
|
||||
*
|
||||
* @param[in] sock Socket to set I/O mode for.
|
||||
* @param[in] nonblock true for nonblocking, or false for blocking I/O.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* I/O mode successfully set to (non)blocking.
|
||||
* @retval DDS_RETCODE_TRY_AGAIN
|
||||
* A blocking call is in progress.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* @sock is not a valid socket.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An unknown error error occurred.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_setsocknonblocking(
|
||||
ddsrt_socket_t sock,
|
||||
bool nonblock);
|
||||
|
||||
DDS_EXPORT int32_t
|
||||
ddsrt_select(
|
||||
int32_t nfds,
|
||||
fd_set *readfds,
|
||||
fd_set *writefds,
|
||||
fd_set *errorfds,
|
||||
dds_duration_t reltime,
|
||||
int32_t *ready);
|
||||
|
||||
#if _WIN32
|
||||
/* SOCKETs on Windows are NOT integers. The nfds parameter is only there for
|
||||
compatibility, the implementation ignores it. Implicit casts will generate
|
||||
warnings though, therefore ddsrt_select is redefined to discard the
|
||||
parameter on Windows. */
|
||||
#define ddsrt_select(nfds, readfds, writefds, errorfds, timeout, ready) \
|
||||
ddsrt_select(-1, readfds, writefds, errorfds, timeout, ready)
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/**
|
||||
* @brief Get the size of a socket address.
|
||||
*
|
||||
* @param[in] sa Socket address to return the size for.
|
||||
*
|
||||
* @returns Size of the socket address based on the address family, or 0 if
|
||||
* the address family is unknown.
|
||||
*/
|
||||
DDS_EXPORT socklen_t
|
||||
ddsrt_sockaddr_get_size(
|
||||
const struct sockaddr *const sa) ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Get the port number from a socket address.
|
||||
*
|
||||
* @param[in] sa Socket address to retrieve the port from.
|
||||
*
|
||||
* @return Port number in host order.
|
||||
*/
|
||||
DDS_EXPORT uint16_t
|
||||
ddsrt_sockaddr_get_port(
|
||||
const struct sockaddr *const sa) ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Check if the given address is unspecified.
|
||||
*
|
||||
* @param[in] sa Socket address to check.
|
||||
*
|
||||
* @return true if the address is unspecified, false otherwise.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_sockaddr_isunspecified(
|
||||
const struct sockaddr *__restrict sa) ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Check if the given address is a loopback address.
|
||||
*
|
||||
* @param[in] sa Socket address to check.
|
||||
*
|
||||
* @return true if the address is a loopback address, false otherwise.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_sockaddr_isloopback(
|
||||
const struct sockaddr *__restrict sa) ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Check if given socket IP addresses reside in the same subnet.
|
||||
*
|
||||
* Checks if two socket IP addresses reside in the same subnet, considering the
|
||||
* given subnetmask. IPv6 mapped IPv4 addresses are not taken in account.
|
||||
*
|
||||
* @param[in] sa1 First address
|
||||
* @param[in] sa2 Second address.
|
||||
* @param[in] mask Subnetmask.
|
||||
*
|
||||
* @returns true if both addresses reside in the same subnet, false otherwise.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_sockaddr_insamesubnet(
|
||||
const struct sockaddr *sa1,
|
||||
const struct sockaddr *sa2,
|
||||
const struct sockaddr *mask)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_sockaddrfromstr(
|
||||
int af, const char *str, void *sa);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_sockaddrtostr(
|
||||
const void *sa, char *buf, size_t size);
|
||||
|
||||
#if DDSRT_HAVE_DNS
|
||||
typedef struct {
|
||||
size_t naddrs;
|
||||
struct sockaddr_storage addrs[];
|
||||
} ddsrt_hostent_t;
|
||||
|
||||
/**
|
||||
* @brief Lookup addresses for given host name.
|
||||
*
|
||||
* @param[in] name Host name to resolve.
|
||||
* @param[in] af Address family, either AF_INET, AF_INET6 or AF_UNSPEC.
|
||||
* @param[out] hent Structure of type ddsrt_hostent_t.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Host name successfully resolved to address(es).
|
||||
* @retval DDS_RETCODE_HOST_NOT_FOUND
|
||||
* Host not found.
|
||||
* @retval DDS_RETCODE_NO_DATA
|
||||
* Valid name, no data record of requested type.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* Nonrecoverable error.
|
||||
* @retval DDS_RETCODE_TRY_AGAIN
|
||||
* Nonauthoratitative host not found.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_gethostbyname(
|
||||
const char *name,
|
||||
int af,
|
||||
ddsrt_hostent_t **hentp);
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_SOCKETS_H */
|
||||
54
src/ddsrt/include/dds/ddsrt/sockets/posix.h
Normal file
54
src/ddsrt/include/dds/ddsrt/sockets/posix.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_SOCKETS_POSIX_H
|
||||
#define DDSRT_SOCKETS_POSIX_H
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int ddsrt_socket_t;
|
||||
#define DDSRT_INVALID_SOCKET (-1)
|
||||
#define PRIdSOCK "d"
|
||||
|
||||
#define DDSRT_HAVE_IPV6 1
|
||||
#define DDSRT_HAVE_DNS 1
|
||||
#define DDSRT_HAVE_SSM 1
|
||||
|
||||
typedef struct iovec ddsrt_iovec_t;
|
||||
typedef size_t ddsrt_iov_len_t;
|
||||
|
||||
#if defined(__linux)
|
||||
typedef size_t ddsrt_msg_iovlen_t;
|
||||
#else /* POSIX says int (which macOS, FreeBSD, Solaris do) */
|
||||
typedef int ddsrt_msg_iovlen_t;
|
||||
#endif
|
||||
typedef struct msghdr ddsrt_msghdr_t;
|
||||
|
||||
#if defined(__sun) && !defined(_XPG4_2)
|
||||
# define DDSRT_MSGHDR_FLAGS 0
|
||||
#else
|
||||
# define DDSRT_MSGHDR_FLAGS 1
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_SOCKETS_POSIX_H */
|
||||
52
src/ddsrt/include/dds/ddsrt/sockets/windows.h
Normal file
52
src/ddsrt/include/dds/ddsrt/sockets/windows.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef DDSRT_WINDOWS_SOCKET_H
|
||||
#define DDSRT_WINDOWS_SOCKET_H
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef SOCKET ddsrt_socket_t;
|
||||
#define DDSRT_INVALID_SOCKET (INVALID_SOCKET)
|
||||
#define PRIdSOCK PRIuPTR
|
||||
|
||||
#define DDSRT_HAVE_IPV6 1
|
||||
#define DDSRT_HAVE_DNS 1
|
||||
|
||||
#if defined(NTDDI_VERSION) && \
|
||||
defined(_WIN32_WINNT_WS03) && \
|
||||
(NTDDI_VERSION >= _WIN32_WINNT_WS03)
|
||||
#define DDSRT_HAVE_SSM 1
|
||||
#else
|
||||
#define DDSRT_HAVE_SSM 0
|
||||
#endif
|
||||
|
||||
#define IFF_POINTOPOINT IFF_POINTTOPOINT
|
||||
|
||||
typedef unsigned ddsrt_iov_len_t;
|
||||
typedef struct ddsrt_iovec {
|
||||
ddsrt_iov_len_t iov_len;
|
||||
void *iov_base;
|
||||
} ddsrt_iovec_t;
|
||||
|
||||
typedef DWORD ddsrt_msg_iovlen_t;
|
||||
|
||||
typedef struct ddsrt_msghdr {
|
||||
void *msg_name;
|
||||
socklen_t msg_namelen;
|
||||
ddsrt_iovec_t *msg_iov;
|
||||
ddsrt_msg_iovlen_t msg_iovlen;
|
||||
void *msg_control;
|
||||
size_t msg_controllen;
|
||||
int msg_flags;
|
||||
} ddsrt_msghdr_t;
|
||||
|
||||
#define DDSRT_MSGHDR_FLAGS 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_WINDOWS_SOCKET_H */
|
||||
198
src/ddsrt/include/dds/ddsrt/string.h
Normal file
198
src/ddsrt/include/dds/ddsrt/string.h
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_STRING_H
|
||||
#define DDSRT_STRING_H
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Compare two strings ignoring case.
|
||||
*
|
||||
* @param[in] s1 String to compare.
|
||||
* @param[in] s2 String to compare.
|
||||
*
|
||||
* @returns Zero if @s1 and @s2 match, a negative integer if @s1 is less than
|
||||
* @s2 or a positive integer if @s1 is greater than @s2.
|
||||
*/
|
||||
DDS_EXPORT int
|
||||
ddsrt_strcasecmp(
|
||||
const char *s1,
|
||||
const char *s2)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Compare two strings ignoring case, but no more than @n bytes.
|
||||
*
|
||||
* @param[in] s1 String to compare.
|
||||
* @param[in] s2 String to compare.
|
||||
* @param[in] n Maximum number of bytes to compare.
|
||||
*
|
||||
* @returns Zero if @s1 and @s2 match, a negative integer if @s1 is less than
|
||||
* @s2 or a positive integer if @s1 is greater than @s2.
|
||||
*/
|
||||
DDS_EXPORT int
|
||||
ddsrt_strncasecmp(
|
||||
const char *s1,
|
||||
const char *s2,
|
||||
size_t n)
|
||||
ddsrt_nonnull((1,2));
|
||||
|
||||
/**
|
||||
* @brief Split string into tokens.
|
||||
*
|
||||
* @param[in] str String to split into tokens.
|
||||
* @param[in] delim Characters that delimit a token.
|
||||
* @param[inout] saveptr Pointer to a char * used internally.
|
||||
*
|
||||
* @returns The next token or NULL if there are no more tokens.
|
||||
*/
|
||||
DDS_EXPORT char *
|
||||
ddsrt_strtok_r(
|
||||
char *str,
|
||||
const char *delim,
|
||||
char **saveptr);
|
||||
|
||||
/**
|
||||
* @brief Extract token from string.
|
||||
*
|
||||
* Finds the first token in @stringp delimited by one of the characters in
|
||||
* @delim. The delimiter is overwritten with a null byte, terminating the
|
||||
* token and @stringp is updated to point past the delimiter.
|
||||
*
|
||||
* @param[inout] stringp String to extract token from.
|
||||
* @param[in] delim Characters that delimit a token.
|
||||
*
|
||||
* @returns The original value of @stringp.
|
||||
*/
|
||||
DDS_EXPORT char *
|
||||
ddsrt_strsep(
|
||||
char **stringp,
|
||||
const char *delim);
|
||||
|
||||
/**
|
||||
* @brief Duplicate block of memory.
|
||||
*
|
||||
* Copy a block of memory into a newly allocated block of memory. The memory
|
||||
* is obtained with @ddsrt_malloc and must be freed with @ddsrt_free when it
|
||||
* is no longer used.
|
||||
*
|
||||
* @param[in] ptr Pointer to block of memory to duplicate.
|
||||
* @param[in] len Number of bytes to copy into newly allocated buffer.
|
||||
*
|
||||
* @returns A new block of memory that is a duplicate of the block pointed to
|
||||
* by @ptr or NULL if not enough memory was available.
|
||||
*/
|
||||
DDS_EXPORT void *
|
||||
ddsrt_memdup(
|
||||
const void *ptr,
|
||||
size_t len)
|
||||
ddsrt_nonnull((1))
|
||||
ddsrt_attribute_malloc;
|
||||
|
||||
/**
|
||||
* @brief Duplicate string.
|
||||
*
|
||||
* Copy string into a newly allocated block of memory. The memory is obtained
|
||||
* with @ddsrt_malloc and must freed with @ddsrt_free when it is no longer
|
||||
* used.
|
||||
*
|
||||
* @param[in] str String to duplicate.
|
||||
*
|
||||
* @returns A new string that is a duplicate of @str or NULL if not enough
|
||||
* memory was available.
|
||||
*/
|
||||
DDS_EXPORT char *
|
||||
ddsrt_strdup(
|
||||
const char *str)
|
||||
ddsrt_nonnull_all
|
||||
ddsrt_attribute_malloc;
|
||||
|
||||
/**
|
||||
* @brief Copy string.
|
||||
*
|
||||
* Copy string to buffer with specified size. The string is truncated if there
|
||||
* is not enough space. The resulting string is guaranteed to be null
|
||||
* terminated if there is space.
|
||||
*
|
||||
* @param[out] dest Destination buffer.
|
||||
* @param[in] src Null terminated string to copy to dest.
|
||||
* @param[in] size Number of bytes available in dest.
|
||||
*
|
||||
* @returns Number of characters copied to dest (excluding the null byte), or
|
||||
* the number of characters that would have been copied if dest is not
|
||||
* sufficiently large enough.
|
||||
*/
|
||||
DDS_EXPORT
|
||||
size_t
|
||||
ddsrt_strlcpy(
|
||||
char * __restrict dest,
|
||||
const char * __restrict src,
|
||||
size_t size)
|
||||
ddsrt_nonnull((1,2));
|
||||
|
||||
/**
|
||||
* @brief Concatenate strings.
|
||||
*
|
||||
* Append the string specified by src to the string specified by dest. The
|
||||
* terminating null byte at the end of dest is overwritten. The resulting
|
||||
* string is truncated if there is not enough space. The resulting string
|
||||
* guaranteed to be null terminated if there is space.
|
||||
*
|
||||
* @param[inout] dest Destination buffer.
|
||||
* @param[in] src Null terminated string to append to dest.
|
||||
* @param[in] size Number of bytes available in dest.
|
||||
*
|
||||
* @returns Number of characters copied to dest (excluding the null byte), or
|
||||
* the number of characters that would have been copied if dest is not
|
||||
* sufficiently large enough.
|
||||
*/
|
||||
DDS_EXPORT
|
||||
size_t
|
||||
ddsrt_strlcat(
|
||||
char * __restrict dest,
|
||||
const char * __restrict src,
|
||||
size_t size)
|
||||
ddsrt_nonnull((1,2));
|
||||
|
||||
/**
|
||||
* @brief Get description for specified system error number.
|
||||
*
|
||||
* @param[in] errnum System error number.
|
||||
* @param[in] buf Buffer where description is copied to.
|
||||
* @param[in] buflen Number of bytes available in @buf.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Description for @errnum was successfully copied to @buf.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Unknown error number.
|
||||
* @retval DDS_RETCODE_NOT_ENOUGH_SPACE
|
||||
* Buffer was not large enough to hold the description.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_strerror_r(
|
||||
int errnum,
|
||||
char *buf,
|
||||
size_t buflen);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_STRING_H */
|
||||
75
src/ddsrt/include/dds/ddsrt/strtod.h
Normal file
75
src/ddsrt/include/dds/ddsrt/strtod.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
/**
|
||||
* @file strtod.h
|
||||
* @brief Floating-point number to/from string conversion functions.
|
||||
*
|
||||
* Locale independent versions of the floating-point number conversion
|
||||
* functions found in the standard library.
|
||||
*/
|
||||
#ifndef DDSRT_STRTOD_H
|
||||
#define DDSRT_STRTOD_H
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a double precision floating point number.
|
||||
*
|
||||
* @param[in] nptr A string to convert into a double.
|
||||
* @param[out] endptr If not NULL, a char* where the address of first invalid
|
||||
* character is stored.
|
||||
* @param[out] dblptr A double where the result is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_strtod(const char *nptr, char **endptr, double *dblptr);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a floating point number.
|
||||
*
|
||||
* @param[in] nptr A string to convert into a float.
|
||||
* @param[in] endptr If not NULL, a char* where the address of first invalid
|
||||
* character is stored.
|
||||
* @param[out] fltptr A float where the floating-point number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_strtof(const char *nptr, char **endptr, float *fltptr);
|
||||
|
||||
/**
|
||||
* @brief Convert a double-precision floating-point number to a string.
|
||||
*
|
||||
* @param[in] src Double-precision floating-point number to convert.
|
||||
* @param[in] str Buffer where string representation is written.
|
||||
* @param[in] size Number of bytes available in @str.
|
||||
*
|
||||
* @returns The number of bytes written (excluding the null terminating byte).
|
||||
*/
|
||||
DDS_EXPORT int
|
||||
ddsrt_dtostr(double src, char *str, size_t size);
|
||||
|
||||
/**
|
||||
* @brief convert a floating-point number to a string.
|
||||
*
|
||||
* @param[in] src Floating-point number to conver.
|
||||
* @param[in] str Buffer where string representation is written.
|
||||
* @param[in] size Number of bytes available in @str.
|
||||
*
|
||||
* @returns The number of bytes written (exluding the null terminating byte).
|
||||
*/
|
||||
DDS_EXPORT int
|
||||
ddsrt_ftostr(float src, char *str, size_t size);
|
||||
|
||||
#endif /* DDSRT_STRTOD_H */
|
||||
168
src/ddsrt/include/dds/ddsrt/strtol.h
Normal file
168
src/ddsrt/include/dds/ddsrt/strtol.h
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_STRTOL_H
|
||||
#define DDSRT_STRTOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a long long integer.
|
||||
*
|
||||
* Translate @str to a long long integer considering base, and sign. If @base
|
||||
* is 0, base is determined from @str. A prefix of "0x" or "0X" will cause the
|
||||
* number be read in base 16 (hexadecimal), otherwise base 10 (decimal) is
|
||||
* used, unless the first character is '0', in which case the number will be
|
||||
* read in base 8 (octal).
|
||||
*
|
||||
* @param[in] str String to convert into a number.
|
||||
* @param[out] endptr If not NULL, a char* where the address of first invalid
|
||||
* character is stored.
|
||||
* @param[in] base Base to use. Must be a base between 2 and 36, or 0 to
|
||||
* determine from @str.
|
||||
* @param[out] llng A long long integer where the number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Base is invalid.
|
||||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_strtoll(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
int32_t base,
|
||||
long long *llng);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to an unsigned long long integer.
|
||||
*
|
||||
* Translate @str to an unsigned long long integer considering base, and sign.
|
||||
* If @base is 0, base is determined from @str. A prefix of "0x" or "0X" will
|
||||
* cause the number be read in base 16 (hexadecimal), otherwise base 10
|
||||
* (decimal) is used, unless the first character is '0', in which case the
|
||||
* number will be read in base 8 (octal).
|
||||
*
|
||||
* @param[in] str String to convert into a number.
|
||||
* @param[out] endptr If not NULL, a char* where the address of first invalid
|
||||
* character is stored.
|
||||
* @param[in] base Base to use. Must be a base between 2 and 36, or 0 to
|
||||
* determine from @str.
|
||||
* @param[out] ullng A long long integer where the number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Base is invalid.
|
||||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_strtoull(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
int32_t base,
|
||||
unsigned long long *ullng);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to a long long integer.
|
||||
*
|
||||
* @param[in] str String to convert into a long long integer.
|
||||
* @param[in] llng A long long integer where the number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Base is invalid.
|
||||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_atoll(
|
||||
const char *str,
|
||||
long long *llng);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to an unsigned long long integer.
|
||||
*
|
||||
* @param[in] str String to conver into an unsigned long long integer.
|
||||
* @param[out] ullng An unsigned long long integer where the number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||
* Base is invalid.
|
||||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_atoull(
|
||||
const char *str,
|
||||
unsigned long long *ullng);
|
||||
|
||||
/**
|
||||
* @brief Convert a long long integer into a string.
|
||||
*
|
||||
* @param[in] num Long long integer to convert into a string.
|
||||
* @param[in] str Buffer where string representation is written.
|
||||
* @param[in] len Number of bytes available in buffer.
|
||||
* @param[out] endptr A char* where the address of the null terminating byte
|
||||
* is stored.
|
||||
*
|
||||
* @returns The value of @str on success, otherwise NULL.
|
||||
*/
|
||||
DDS_EXPORT char *
|
||||
ddsrt_lltostr(
|
||||
long long num,
|
||||
char *str,
|
||||
size_t len,
|
||||
char **endptr);
|
||||
|
||||
/**
|
||||
* @brief Convert an unsigned long long integer into a string.
|
||||
*
|
||||
* @param[in] num Unsigned long long integer to covert into a string.
|
||||
* @param[in] str Buffer where string representation is stored.
|
||||
* @param[in] len Number of bytes available in buffer.
|
||||
* @param[out] endptr A char* where the adress of the null terminating byte
|
||||
* is stored.
|
||||
*
|
||||
* @returns The value of @str on success, otherwise NULL.
|
||||
*/
|
||||
DDS_EXPORT char *
|
||||
ddsrt_ulltostr(
|
||||
unsigned long long num,
|
||||
char *str,
|
||||
size_t len,
|
||||
char **endptr);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_STRTOL_H */
|
||||
298
src/ddsrt/include/dds/ddsrt/sync.h
Normal file
298
src/ddsrt/include/dds/ddsrt/sync.h
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_SYNC_H
|
||||
#define DDSRT_SYNC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
||||
#if _WIN32
|
||||
#include "dds/ddsrt/sync/windows.h"
|
||||
#else
|
||||
#include "dds/ddsrt/sync/posix.h"
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize a mutex.
|
||||
*
|
||||
* @param[in] mutex Mutex to itialize.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_mutex_init(
|
||||
ddsrt_mutex_t *mutex)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Destroy a mutex.
|
||||
*
|
||||
* @param[in] mutex Mutex to destroy.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_mutex_destroy(
|
||||
ddsrt_mutex_t *mutex)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Acquire a mutex.
|
||||
*
|
||||
* @param[in] mutex Mutex to acquire.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_mutex_lock(
|
||||
ddsrt_mutex_t *mutex)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Acquire a mutex if it is not already acquired.
|
||||
*
|
||||
* @param[in] mutex Mutex to acquire.
|
||||
*
|
||||
* @returns true if the mutex was acquired, false otherwise.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_mutex_trylock(
|
||||
ddsrt_mutex_t *mutex)
|
||||
ddsrt_nonnull_all
|
||||
ddsrt_attribute_warn_unused_result;
|
||||
|
||||
/**
|
||||
* @brief Release an acquired mutex.
|
||||
*
|
||||
* @param[in] mutex Mutex to release.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_mutex_unlock (
|
||||
ddsrt_mutex_t *mutex)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Initialize a condition variable.
|
||||
*
|
||||
* @param[in] cond Condition variable to initialize.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_cond_init(
|
||||
ddsrt_cond_t *cond)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Destroy a condition variable.
|
||||
*
|
||||
* @param[in] cond Condition variable to destroy.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_cond_destroy(
|
||||
ddsrt_cond_t *cond)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Wait for a condition variable to be signalled.
|
||||
*
|
||||
* @param[in] cond Condition variable to block on.
|
||||
* @param[in] mutex Mutex to associate with condition variable.
|
||||
*
|
||||
* @pre The calling thread must hold the mutex specified by @mutex.
|
||||
*
|
||||
* @post The calling thread will hold the mutex specified by @mutex.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_cond_wait(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Wait until @abstime for a condition variable to be signalled.
|
||||
*
|
||||
* @param[in] cond Condition variable to block on.
|
||||
* @param[in] mutex Mutex to associate with condition variable.
|
||||
* @param[in] abstime Time in nanoseconds since UNIX Epoch.
|
||||
*
|
||||
* @pre The calling thread must hold the mutex specified by @mutex.
|
||||
*
|
||||
* @post The calling thread will hold the mutex specified by @mutex.
|
||||
*
|
||||
* @returns false if the condition variable was not signalled before the
|
||||
* absolute time specified by @abstime passed, otherwise true.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_cond_waituntil(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_time_t abstime)
|
||||
ddsrt_nonnull((1,2));
|
||||
|
||||
/**
|
||||
* @brief Wait for @reltime for a condition variable to be signalled.
|
||||
*
|
||||
* @param[in] cond Condition variable to block on.
|
||||
* @param[in] mutex Mutex to associate with condition variable.
|
||||
* @param[in] reltime Time in nanoseconds since UNIX Epoch.
|
||||
*
|
||||
* @pre The calling thread must hold the mutex specified by @mutex.
|
||||
*
|
||||
* @post The calling thread will hold the mutex specified by @mutex.
|
||||
*
|
||||
* @returns false if the condition variable was not signalled before the
|
||||
* relative time specified by @reltime passed, otherwise true.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_cond_waitfor(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_duration_t reltime)
|
||||
ddsrt_nonnull((1,2));
|
||||
|
||||
/**
|
||||
* @brief Signal a condition variable and unblock at least one thread.
|
||||
*
|
||||
* @param[in] cond Condition variable to signal.
|
||||
*
|
||||
* @pre The mutex associated with the condition in general should be acquired
|
||||
* by the calling thread before setting the condition state and
|
||||
* signalling.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_cond_signal(
|
||||
ddsrt_cond_t *cond)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Signal a condition variable and unblock all threads.
|
||||
*
|
||||
* @param[in] cond Condition variable to signal.
|
||||
*
|
||||
* @pre The mutex associated with the condition in general should be acquired
|
||||
* by the calling thread before setting the condition state and
|
||||
* signalling
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_cond_broadcast(
|
||||
ddsrt_cond_t *cond)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Initialize a read-write lock.
|
||||
*
|
||||
* @param[in] rwlock Read-write lock to initialize.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_rwlock_init(
|
||||
ddsrt_rwlock_t *rwlock)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Destroy a read-write lock.
|
||||
*
|
||||
* @param[in] rwlock Read-write lock to destroy.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_rwlock_destroy(
|
||||
ddsrt_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Acquire a read-write lock for reading.
|
||||
*
|
||||
* @param[in] rwlock Read-write lock to acquire.
|
||||
*
|
||||
* @post Data related to the critical section must not be changed by the
|
||||
* calling thread.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_rwlock_read(
|
||||
ddsrt_rwlock_t *rwlock)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Acquire a read-write lock for writing.
|
||||
*
|
||||
* @param[in] rwlock Read-write lock to acquire.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_rwlock_write(
|
||||
ddsrt_rwlock_t *rwlock)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Try to acquire a read-write lock for reading.
|
||||
*
|
||||
* Try to acquire a read-write lock while for reading, immediately return if
|
||||
* the lock is already exclusively acquired by another thread.
|
||||
*
|
||||
* @param[in] rwlock Read-write lock to aqcuire.
|
||||
*
|
||||
* @post Data related to the critical section must not changed by the
|
||||
* calling thread.
|
||||
*
|
||||
* @returns true if the lock was acquired, otherwise false.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_rwlock_tryread(
|
||||
ddsrt_rwlock_t *rwlock)
|
||||
ddsrt_nonnull_all
|
||||
ddsrt_attribute_warn_unused_result;
|
||||
|
||||
/**
|
||||
* @brief Try to acquire a read-write lock for writing.
|
||||
*
|
||||
* Try to acquire a read-write lock for writing, immediately return if the
|
||||
* lock is already acquired, either for reading or writing, by another thread.
|
||||
*
|
||||
* @param[in] rwlock Read-write lock to acquire.
|
||||
*
|
||||
* @returns true if the lock was acquired, otherwise false.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_rwlock_trywrite(
|
||||
ddsrt_rwlock_t *rwlock)
|
||||
ddsrt_nonnull_all
|
||||
ddsrt_attribute_warn_unused_result;
|
||||
|
||||
/**
|
||||
* @brief Release a previously acquired read-write lock.
|
||||
*
|
||||
* @param[in] rwlock Read-write lock to release.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_rwlock_unlock(
|
||||
ddsrt_rwlock_t *rwlock)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/* Initialization callback used by ddsrt_once */
|
||||
typedef void (*ddsrt_once_fn)(void);
|
||||
|
||||
/**
|
||||
* @brief Invoke init_fn exactly once for a given control.
|
||||
*
|
||||
* The first thread to call this function with a given control will call the
|
||||
* function specified by @init_fn with no arguments. All following calls with
|
||||
* the same control will not call the specified function.
|
||||
*
|
||||
* @pre The control parameter is properly initialized with DDSRT_ONCE_INIT.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_once(
|
||||
ddsrt_once_t *control,
|
||||
ddsrt_once_fn init_fn);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_SYNC_H */
|
||||
44
src/ddsrt/include/dds/ddsrt/sync/posix.h
Normal file
44
src/ddsrt/include/dds/ddsrt/sync/posix.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_POSIX_SYNC_H
|
||||
#define DDSRT_POSIX_SYNC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#if HAVE_LKST
|
||||
#include "lkst.h"
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
pthread_cond_t cond;
|
||||
} ddsrt_cond_t;
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mutex;
|
||||
} ddsrt_mutex_t;
|
||||
|
||||
typedef struct {
|
||||
pthread_rwlock_t rwlock;
|
||||
} ddsrt_rwlock_t;
|
||||
|
||||
typedef pthread_once_t ddsrt_once_t;
|
||||
#define DDSRT_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_POSIX_SYNC_H */
|
||||
39
src/ddsrt/include/dds/ddsrt/sync/windows.h
Normal file
39
src/ddsrt/include/dds/ddsrt/sync/windows.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_WINDOWS_SYNC_H
|
||||
#define DDSRT_WINDOWS_SYNC_H
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
CONDITION_VARIABLE cond;
|
||||
} ddsrt_cond_t;
|
||||
|
||||
typedef struct {
|
||||
SRWLOCK lock;
|
||||
} ddsrt_mutex_t;
|
||||
|
||||
typedef struct os_rwlock {
|
||||
SRWLOCK lock;
|
||||
int state; /* -1: exclusive, 0: free, 1: shared */
|
||||
} ddsrt_rwlock_t;
|
||||
|
||||
typedef INIT_ONCE ddsrt_once_t;
|
||||
#define DDSRT_ONCE_INIT INIT_ONCE_STATIC_INIT
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_WINDOWS_SYNC_H */
|
||||
262
src/ddsrt/include/dds/ddsrt/threads.h
Normal file
262
src/ddsrt/include/dds/ddsrt/threads.h
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
/**
|
||||
* @file threads.h
|
||||
* @brief Thread management and creation.
|
||||
*
|
||||
* Platform independent interface for managing and creating execution threads.
|
||||
*/
|
||||
#ifndef DDSRT_THREADS_H
|
||||
#define DDSRT_THREADS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#if _WIN32
|
||||
#include "dds/ddsrt/threads/windows.h"
|
||||
#else
|
||||
#include "dds/ddsrt/threads/posix.h"
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* Thread-local storage using __declspec(thread) on Windows versions before
|
||||
Vista and Server 2008 works in DLLs if they are bound to the executable,
|
||||
it does not work if the library is loaded using LoadLibrary. */
|
||||
#define ddsrt_thread_local __declspec(thread)
|
||||
#elif defined(__GNUC__) || (defined(__clang__) && __clang_major__ >= 2)
|
||||
/* GCC supports Thread-local storage for x86 since version 3.3. Clang
|
||||
supports Thread-local storage since version 2.0. */
|
||||
/* VxWorks 7 supports __thread for both GCC and DIAB, older versions may
|
||||
support it as well, but that is not verified. */
|
||||
#define ddsrt_thread_local __thread
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
#define ddsrt_thread_local __thread
|
||||
#else
|
||||
#error "Thread-local storage is not supported"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Definition for a thread routine invoked on thread create.
|
||||
*/
|
||||
typedef uint32_t (*ddsrt_thread_routine_t)(void*);
|
||||
|
||||
/**
|
||||
* @brief Thread scheduling classes
|
||||
* @{
|
||||
*/
|
||||
typedef enum {
|
||||
/** Schedule processes and threads according a platform default.
|
||||
* DDSRT_SCHED_REALTIME for timesharing platforms and
|
||||
* DDSRT_SCHED_TIMESHARE for realtime platforms
|
||||
*/
|
||||
DDSRT_SCHED_DEFAULT,
|
||||
/** Schedule processes and threads on realtime basis,
|
||||
* on most platforms implying:
|
||||
* - Fixed Priority
|
||||
* - Preemption
|
||||
* - Either "First In First Out" or "Round Robin"
|
||||
*/
|
||||
DDSRT_SCHED_REALTIME,
|
||||
/** Schedule processes and threads on timesharing basis,
|
||||
* on most platforms implying:
|
||||
* - Dynamic Priority to guarantee fair share
|
||||
* - Preemption
|
||||
*/
|
||||
DDSRT_SCHED_TIMESHARE
|
||||
} ddsrt_sched_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Definition of the thread attributes
|
||||
*/
|
||||
typedef struct {
|
||||
/** Specifies the scheduling class */
|
||||
ddsrt_sched_t schedClass;
|
||||
/** Specifies the thread priority */
|
||||
int32_t schedPriority;
|
||||
/** Specifies the thread stack size */
|
||||
uint32_t stackSize;
|
||||
} ddsrt_threadattr_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize thread attributes to platform defaults.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_threadattr_init(
|
||||
ddsrt_threadattr_t *attr)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
/**
|
||||
* @brief Create a new thread.
|
||||
*
|
||||
* Creates a new thread of control that executes concurrently with
|
||||
* the calling thread. The new thread applies the function start_routine
|
||||
* passing it arg as first argument.
|
||||
*
|
||||
* The new thread terminates by returning from the start_routine function.
|
||||
* The created thread is identified by the returned threadId.
|
||||
*
|
||||
* @param[out] thread Location where thread id is stored.
|
||||
* @param[in] name Name assigned to created thread.
|
||||
* @param[in] attr Attributes to create thread with.
|
||||
* @param[in] start_routine Function to execute in created thread.
|
||||
* @param[in] arg Argument passed to @start_routine.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Thread successfully created.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* Thread could not be created.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_thread_create(
|
||||
ddsrt_thread_t *thread,
|
||||
const char *name,
|
||||
const ddsrt_threadattr_t *attr,
|
||||
ddsrt_thread_routine_t start_routine,
|
||||
void *arg)
|
||||
ddsrt_nonnull((1,2,3,4));
|
||||
|
||||
/**
|
||||
* @brief Retrieve integer representation of the given thread id.
|
||||
*
|
||||
* @returns The integer representation of the given thread.
|
||||
*/
|
||||
DDS_EXPORT ddsrt_tid_t
|
||||
ddsrt_gettid(void);
|
||||
|
||||
/**
|
||||
* @brief Return thread ID of the calling thread.
|
||||
*
|
||||
* @returns Thread ID of the calling thread.
|
||||
*/
|
||||
DDS_EXPORT ddsrt_thread_t
|
||||
ddsrt_thread_self(void);
|
||||
|
||||
/**
|
||||
* @brief Compare thread identifiers.
|
||||
*
|
||||
* @returns true if thread ids match, otherwise false.
|
||||
*/
|
||||
DDS_EXPORT bool
|
||||
ddsrt_thread_equal(ddsrt_thread_t t1, ddsrt_thread_t t2);
|
||||
|
||||
/**
|
||||
* @brief Wait for termination of the specified thread.
|
||||
*
|
||||
* If the specified thread is still running, wait for its termination
|
||||
* else return immediately. In thread_result it returns the exit status
|
||||
* of the thread. If NULL is passed for @thread_result, no exit status is
|
||||
* returned, but ddsrt_thread_join still waits for the thread to terminate.
|
||||
*
|
||||
* @param[in] thread Id of thread to wait for.
|
||||
* @param[out] thread_result Location where thread result is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Target thread terminated.
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* An error occurred while waiting for the thread to terminate.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_thread_join(
|
||||
ddsrt_thread_t thread,
|
||||
uint32_t *thread_result);
|
||||
|
||||
/**
|
||||
* @brief Get name of current thread.
|
||||
*
|
||||
* @param[in] name Buffer where the name is copied to.
|
||||
* @param[in] size Number of bytes available in the buffer.
|
||||
*
|
||||
* @returns The number of bytes (excluding the null terminating bytes) that
|
||||
* are written. If the buffer is not sufficiently large enough, the
|
||||
* name is truncated and the number of bytes that would have been
|
||||
* written is returned.
|
||||
*/
|
||||
DDS_EXPORT size_t
|
||||
ddsrt_thread_getname(
|
||||
char *__restrict name,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* @brief Set name of current thread.
|
||||
*
|
||||
* Set name of the current thread to @name. If the name is longer than the
|
||||
* platform maximum, it is silently truncated.
|
||||
*
|
||||
* @param[in] name Name for current thread.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_thread_setname(
|
||||
const char *__restrict name);
|
||||
|
||||
/**
|
||||
* @brief Push cleanup handler onto the cleanup stack
|
||||
*
|
||||
* Push a cleanup handler onto the top of the calling thread's cleanup
|
||||
* stack. The cleanup handler will be popped of the thread's cleanup stack
|
||||
* and invoked with the specified argument when the thread exits.
|
||||
*
|
||||
* @param[in] routine Cleanup handler to push onto the thread cleanup stack.
|
||||
* @param[in] arg Argument that will be passed to the cleanup handler.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_thread_cleanup_push(
|
||||
void (*routine)(void*),
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* @brief Pop cleanup handler from the top of the cleanup stack
|
||||
*
|
||||
* Remove routine at the top of the calling thread's cleanup stack and
|
||||
* optionally invoke it (if execute is non-zero).
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
ddsrt_thread_cleanup_pop(
|
||||
int execute);
|
||||
|
||||
/**
|
||||
* @brief Initialize thread internals.
|
||||
*
|
||||
* Initialize internals for threads not created with @ddsrt_create_thread. By
|
||||
* default initialization is done automatically.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_thread_init(void);
|
||||
|
||||
/**
|
||||
* @brief Free thread resources and execute cleanup handlers.
|
||||
*
|
||||
* Platforms that support it, automatically free resources claimed by the
|
||||
* current thread and call any registered cleanup routines. This function only
|
||||
* needs to be called on platforms that do not support thread destructors and
|
||||
* only for threads that were not created with @ddsrt_thread_create.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
ddsrt_thread_fini(void);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_THREADS_H */
|
||||
59
src/ddsrt/include/dds/ddsrt/threads/posix.h
Normal file
59
src/ddsrt/include/dds/ddsrt/threads/posix.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_POSIX_THREAD_H
|
||||
#define DDSRT_POSIX_THREAD_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__linux)
|
||||
typedef long int ddsrt_tid_t;
|
||||
#define PRIdTID "ld"
|
||||
/* __linux */
|
||||
#elif defined(__FreeBSD__) && (__FreeBSD_version >= 900031)
|
||||
/* FreeBSD >= 9.0 */
|
||||
typedef int ddsrt_tid_t;
|
||||
#define PRIdTID "d"
|
||||
/* __FreeBSD__ */
|
||||
#elif defined(__APPLE__) && !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
|
||||
/* macOS X >= 10.6 */
|
||||
typedef uint64_t ddsrt_tid_t;
|
||||
#define PRIdTID PRIu64
|
||||
/* __APPLE__ */
|
||||
#elif defined(__VXWORKS__)
|
||||
/* TODO: Verify taskIdSelf is the right function to use on VxWorks */
|
||||
typedef TASK_ID ddsrt_tid_t;
|
||||
# if defined(_WRS_CONFIG_LP64)
|
||||
# define PRIdPID PRIuPTR /* typedef struct windTcb *TASK_ID */
|
||||
# else
|
||||
# define PRIdPID "d" /* typedef int TASK_ID */
|
||||
# endif
|
||||
/* __VXWORKS__ */
|
||||
#else
|
||||
typedef uintmax_t ddsrt_tid_t;
|
||||
#define PRIdTID PRIuPTR
|
||||
#endif
|
||||
|
||||
/* Wrapped in a struct to force conformation to abstraction. */
|
||||
typedef struct {
|
||||
pthread_t v;
|
||||
} ddsrt_thread_t;
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_POSIX_THREAD_H */
|
||||
33
src/ddsrt/include/dds/ddsrt/threads/windows.h
Normal file
33
src/ddsrt/include/dds/ddsrt/threads/windows.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_WINDOWS_THREADS_H
|
||||
#define DDSRT_WINDOWS_THREADS_H
|
||||
|
||||
#include "dds/ddsrt/types.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
DWORD tid;
|
||||
HANDLE handle;
|
||||
} ddsrt_thread_t;
|
||||
|
||||
typedef DWORD ddsrt_tid_t;
|
||||
#define PRIdTID "u"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_WINDOWS_THREADS_H */
|
||||
149
src/ddsrt/include/dds/ddsrt/time.h
Normal file
149
src/ddsrt/include/dds/ddsrt/time.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief DDS C Time support API
|
||||
*
|
||||
* This header file defines the public API of the in the
|
||||
* CycloneDDS C language binding.
|
||||
*/
|
||||
#ifndef DDS_TIME_H
|
||||
#define DDS_TIME_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/types.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
Times are represented using a 64-bit signed integer, encoding
|
||||
nanoseconds since the epoch. Considering the nature of these
|
||||
systems, one would best use TAI, International Atomic Time, rather
|
||||
than something UTC, but availability may be limited.
|
||||
|
||||
Valid times are non-negative and times up to 2**63-2 can be
|
||||
represented. 2**63-1 is defined to represent, essentially, "never".
|
||||
This is good enough for a couple of centuries.
|
||||
*/
|
||||
|
||||
/** Absolute Time definition */
|
||||
typedef int64_t dds_time_t;
|
||||
|
||||
/** Relative Time definition */
|
||||
typedef int64_t dds_duration_t;
|
||||
|
||||
/** @name Macro definition for time units in nanoseconds.
|
||||
@{**/
|
||||
#define DDS_NSECS_IN_SEC INT64_C(1000000000)
|
||||
#define DDS_NSECS_IN_MSEC INT64_C(1000000)
|
||||
#define DDS_NSECS_IN_USEC INT64_C(1000)
|
||||
/** @}*/
|
||||
|
||||
/** @name Infinite timeout for indicate absolute time */
|
||||
#define DDS_NEVER ((dds_time_t) INT64_MAX)
|
||||
|
||||
/** @name Infinite timeout for relative time */
|
||||
#define DDS_INFINITY ((dds_duration_t) INT64_MAX)
|
||||
|
||||
/** @name Macro definition for time conversion to nanoseconds
|
||||
@{**/
|
||||
#define DDS_SECS(n) ((n) * DDS_NSECS_IN_SEC)
|
||||
#define DDS_MSECS(n) ((n) * DDS_NSECS_IN_MSEC)
|
||||
#define DDS_USECS(n) ((n) * DDS_NSECS_IN_USEC)
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @brief Get the current time in nanoseconds since the UNIX Epoch.
|
||||
*
|
||||
* @returns Current time.
|
||||
*/
|
||||
DDS_EXPORT dds_time_t dds_time(void);
|
||||
|
||||
/**
|
||||
* @brief Suspend execution of calling thread until relative time n elapsed.
|
||||
*
|
||||
* Execution is suspended for n nanoseconds. Should the call be interrupted,
|
||||
* the call is re-entered with the remaining time.
|
||||
*
|
||||
* @param[in] reltime Relative time in nanoseconds.
|
||||
*/
|
||||
DDS_EXPORT void dds_sleepfor (dds_duration_t reltime);
|
||||
|
||||
/**
|
||||
* @brief Suspend execution of calling thread until absolute time n elapsed.
|
||||
*
|
||||
* Execution is suspended until the given absolute time elapsed. Should the
|
||||
* call be interrupted, it is re-entered with the remaining time.
|
||||
*
|
||||
* @param[in] abstime Absolute time in nanoseconds since UNIX Epoch.
|
||||
*/
|
||||
DDS_EXPORT void dds_sleepuntil (dds_time_t abstime);
|
||||
|
||||
/**
|
||||
* @brief Get high resolution, monotonic time.
|
||||
*
|
||||
* The monotonic clock is a clock with near real-time progression and can be
|
||||
* used when a high-resolution time is needed without the need for it to be
|
||||
* related to the wall-clock. The resolution of the clock is typically the
|
||||
* highest available on the platform.
|
||||
*
|
||||
* The clock is not guaranteed to be strictly monotonic, but on most common
|
||||
* platforms it will be (based on performance-counters or HPET's).
|
||||
*
|
||||
* @returns Monotonic time if available, otherwise real time.
|
||||
*/
|
||||
DDS_EXPORT dds_time_t ddsrt_time_monotonic(void);
|
||||
|
||||
/**
|
||||
* @brief Get high resolution, elapsed (and thus monotonic) time since some
|
||||
* fixed unspecified past time.
|
||||
*
|
||||
* The elapsed time clock is a clock with near real-time progression and can be
|
||||
* used when a high-resolution suspend-aware monotonic clock is needed, without
|
||||
* having to deal with the complications of discontinuities if for example the
|
||||
* time is changed. The fixed point from which the elapsed time is returned is
|
||||
* not guaranteed to be fixed over reboots of the system.
|
||||
*
|
||||
* @returns Elapsed time if available, otherwise return monotonic time.
|
||||
*/
|
||||
DDS_EXPORT dds_time_t ddsrt_time_elapsed(void);
|
||||
|
||||
/**
|
||||
* @brief Convert time into a human readable string in RFC 3339 format.
|
||||
*
|
||||
* Converts the calender time into a null-terminated string in RFC 3339 format.
|
||||
* e.g. "2014-10-24 15:32:27-04:00".
|
||||
*
|
||||
* UTC offset is omitted if time-zone information is unknown.
|
||||
*
|
||||
* @param[in] abstime Time in nanoseconds since UNIX Epoch.
|
||||
* @param[in] str String to write human readable timestamp to.
|
||||
* @param[in] size Number of bytes available in @str.
|
||||
*
|
||||
* @returns Number of bytes written (excluding terminating null byte). The
|
||||
* string is truncated if str is not sufficiently large enough. Thus,
|
||||
* a return value of size or more means the output was truncated.
|
||||
*/
|
||||
#define DDSRT_RFC3339STRLEN (25)
|
||||
|
||||
DDS_EXPORT size_t ddsrt_ctime(dds_time_t abstime, char *str, size_t size);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_TIME_H */
|
||||
30
src/ddsrt/include/dds/ddsrt/types.h
Normal file
30
src/ddsrt/include/dds/ddsrt/types.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_TYPES_H
|
||||
#define DDSRT_TYPES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if _WIN32
|
||||
# include "dds/ddsrt/types/windows.h"
|
||||
#elif __VXWORKS__
|
||||
# include "dds/ddsrt/types/vxworks.h"
|
||||
#else
|
||||
# include "dds/ddsrt/types/posix.h"
|
||||
#endif
|
||||
|
||||
#define PRIdSIZE "zd"
|
||||
#define PRIuSIZE "zu"
|
||||
#define PRIxSIZE "zx"
|
||||
|
||||
#endif /* DDSRT_TYPES_H */
|
||||
19
src/ddsrt/include/dds/ddsrt/types/posix.h
Normal file
19
src/ddsrt/include/dds/ddsrt/types/posix.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_TYPES_POSIX_H
|
||||
#define DDSRT_TYPES_POSIX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#endif /* DDSRT_TYPES_POSIX_H */
|
||||
74
src/ddsrt/include/dds/ddsrt/types/vxworks.h
Normal file
74
src/ddsrt/include/dds/ddsrt/types/vxworks.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_TYPES_VXWORKS_H
|
||||
#define DDSRT_TYPES_VXWORKS_H
|
||||
|
||||
#if defined(_WRS_KERNEL)
|
||||
/* inttypes.h does not exist in VxWorks DKM. */
|
||||
#include <st_inttypes.h>
|
||||
#include <cafe/inttypes.h>
|
||||
/* The above inttypes includes don't seem to define uintmax_t &c. */
|
||||
#ifdef _WRS_CONFIG_LP64 /* Used in cafe/inttypes.h too. */
|
||||
#define _PFX_64 "l"
|
||||
typedef unsigned long int uintmax_t;
|
||||
#else
|
||||
#define _PFX_64 "ll"
|
||||
typedef unsigned long long int uintmax_t;
|
||||
#endif
|
||||
|
||||
/* Not a complete replacement for inttypes.h (yet); No SCN/PRI?LEAST/FAST/etc. */
|
||||
#define PRId8 "d"
|
||||
#define PRId16 "d"
|
||||
#define PRId32 "d"
|
||||
#define PRId64 _PFX_64 "d"
|
||||
|
||||
#define PRIi8 "i"
|
||||
#define PRIi16 "i"
|
||||
#define PRIi32 "i"
|
||||
#define PRIi64 _PFX_64 "i"
|
||||
|
||||
#define PRIo8 "o"
|
||||
#define PRIo16 "o"
|
||||
#define PRIo32 "o"
|
||||
#define PRIo64 _PFX_64 "o"
|
||||
|
||||
#define PRIu8 "u"
|
||||
#define PRIu16 "u"
|
||||
#define PRIu32 "u"
|
||||
#define PRIu64 _PFX_64 "u"
|
||||
|
||||
#define PRIx8 "x"
|
||||
#define PRIx16 "x"
|
||||
#define PRIx32 "x"
|
||||
|
||||
#define PRIX8 "X"
|
||||
#define PRIX16 "X"
|
||||
#define PRIX32 "X"
|
||||
#define PRIX64 _PFX_64 "X"
|
||||
|
||||
#define PRIdMAX _PFX_64 "d"
|
||||
#define PRIiMAX _PFX_64 "i"
|
||||
#define PRIoMAX _PFX_64 "o"
|
||||
#define PRIuMAX _PFX_64 "u"
|
||||
#define PRIxMAX _PFX_64 "x"
|
||||
#define PRIXMAX _PFX_64 "X"
|
||||
|
||||
#define PRIdPTR _PFX_64 "d"
|
||||
#define PRIiPTR _PFX_64 "i"
|
||||
#define PRIoPTR _PFX_64 "o"
|
||||
#define PRIXPTR _PFX_64 "X"
|
||||
|
||||
#else /* _WRS_KERNEL */
|
||||
#include <inttypes.h>
|
||||
#endif /* _WRS_KERNEL */
|
||||
|
||||
#endif /* DDSRT_TYPES_VXWORKS_H */
|
||||
27
src/ddsrt/include/dds/ddsrt/types/windows.h
Normal file
27
src/ddsrt/include/dds/ddsrt/types/windows.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_TYPES_WINDOWS_H
|
||||
#define DDSRT_TYPES_WINDOWS_H
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <wchar.h>
|
||||
|
||||
typedef SSIZE_T ssize_t;
|
||||
|
||||
#endif /* DDSRT_TYPES_WINDOWS_H */
|
||||
28
src/ddsrt/include/dds/version.h.in
Normal file
28
src/ddsrt/include/dds/version.h.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDS_VERSION_H
|
||||
#define DDS_VERSION_H
|
||||
|
||||
#define DDS_VERSION "@CycloneDDS_VERSION@"
|
||||
#define DDS_VERSION_MAJOR @CycloneDDS_VERSION_MAJOR@
|
||||
#define DDS_VERSION_MINOR @CycloneDDS_VERSION_MINOR@
|
||||
#define DDS_VERSION_PATCH @CycloneDDS_VERSION_PATCH@
|
||||
#define DDS_VERSION_TWEAK @CycloneDDS_VERSION_TWEAK@
|
||||
#define DDS_PROJECT_NAME_NOSPACE_CAPS "@CMAKE_PROJECT_NAME_CAPS@"
|
||||
#define DDS_PROJECT_NAME_NOSPACE_SMALL "@CMAKE_PROJECT_NAME_SMALL@"
|
||||
#define DDS_PROJECT_NAME_NOSPACE "@CMAKE_PROJECT_NAME@"
|
||||
#define DDS_PROJECT_NAME "@CMAKE_PROJECT_NAME@"
|
||||
|
||||
#define DDS_HOST_NAME "@CMAKE_HOST_SYSTEM_NAME@"
|
||||
#define DDS_TARGET_NAME "@CMAKE_SYSTEM_NAME@"
|
||||
|
||||
#endif /* DDS_VERSION_H */
|
||||
24
src/ddsrt/include/getopt.h.in
Normal file
24
src/ddsrt/include/getopt.h.in
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef GETOPT_H
|
||||
#define GETOPT_H
|
||||
|
||||
#include "dds/export.h"
|
||||
|
||||
DDS_EXPORT extern int opterr;
|
||||
DDS_EXPORT extern int optind;
|
||||
DDS_EXPORT extern int optopt;
|
||||
DDS_EXPORT extern char *optarg;
|
||||
|
||||
DDS_EXPORT int getopt(int argc, char **argv, const char *opts);
|
||||
|
||||
#endif /* GETOPT_H */
|
||||
163
src/ddsrt/src/atomics.c
Normal file
163
src/ddsrt/src/atomics.c
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
|
||||
/* LD, ST */
|
||||
extern inline uint32_t ddsrt_atomic_ld32 (const volatile ddsrt_atomic_uint32_t *x);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_ldptr (const volatile ddsrt_atomic_uintptr_t *x);
|
||||
extern inline void *ddsrt_atomic_ldvoidp (const volatile ddsrt_atomic_voidp_t *x);
|
||||
extern inline void ddsrt_atomic_st32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline void ddsrt_atomic_stptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline void ddsrt_atomic_stvoidp (volatile ddsrt_atomic_voidp_t *x, void *v);
|
||||
/* INC */
|
||||
extern inline void ddsrt_atomic_inc32 (volatile ddsrt_atomic_uint32_t *x);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x);
|
||||
#endif
|
||||
extern inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x);
|
||||
extern inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_incptr_nv (volatile ddsrt_atomic_uintptr_t *x);
|
||||
/* DEC */
|
||||
extern inline void ddsrt_atomic_dec32 (volatile ddsrt_atomic_uint32_t *x);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x);
|
||||
#endif
|
||||
extern inline void ddsrt_atomic_decptr (volatile ddsrt_atomic_uintptr_t *x);
|
||||
extern inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_decptr_nv (volatile ddsrt_atomic_uintptr_t *x);
|
||||
extern inline uint32_t ddsrt_atomic_dec32_ov (volatile ddsrt_atomic_uint32_t *x);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_dec64_ov (volatile ddsrt_atomic_uint64_t *x);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_decptr_ov (volatile ddsrt_atomic_uintptr_t *x);
|
||||
/* ADD */
|
||||
extern inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline void ddsrt_atomic_addvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v);
|
||||
extern inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_addptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v);
|
||||
/* SUB */
|
||||
extern inline void ddsrt_atomic_sub32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v);
|
||||
extern inline uint32_t ddsrt_atomic_sub32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_subptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline void *ddsrt_atomic_subvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v);
|
||||
/* AND */
|
||||
extern inline void ddsrt_atomic_and32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline void ddsrt_atomic_andptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline uint32_t ddsrt_atomic_and32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_andptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline uint32_t ddsrt_atomic_and32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_andptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
/* OR */
|
||||
extern inline void ddsrt_atomic_or32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline void ddsrt_atomic_orptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline uint32_t ddsrt_atomic_or32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_orptr_ov (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
extern inline uint32_t ddsrt_atomic_or32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
#endif
|
||||
extern inline uintptr_t ddsrt_atomic_orptr_nv (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v);
|
||||
/* CAS */
|
||||
extern inline int ddsrt_atomic_cas32 (volatile ddsrt_atomic_uint32_t *x, uint32_t exp, uint32_t des);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
extern inline int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des);
|
||||
#endif
|
||||
extern inline int ddsrt_atomic_casptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t exp, uintptr_t des);
|
||||
extern inline int ddsrt_atomic_casvoidp (volatile ddsrt_atomic_voidp_t *x, void *exp, void *des);
|
||||
#if DDSRT_ATOMIC_LIFO_SUPPORT
|
||||
extern inline int ddsrt_atomic_casvoidp2 (volatile ddsrt_atomic_uintptr2_t *x, uintptr_t a0, uintptr_t b0, uintptr_t a1, uintptr_t b1);
|
||||
#endif
|
||||
/* FENCES */
|
||||
extern inline void ddsrt_atomic_fence (void);
|
||||
extern inline void ddsrt_atomic_fence_ldld (void);
|
||||
extern inline void ddsrt_atomic_fence_acq (void);
|
||||
extern inline void ddsrt_atomic_fence_rel (void);
|
||||
|
||||
#if DDSRT_ATOMIC_LIFO_SUPPORT
|
||||
void ddsrt_atomic_lifo_init (ddsrt_atomic_lifo_t *head)
|
||||
{
|
||||
head->aba_head.s.a = head->aba_head.s.b = 0;
|
||||
}
|
||||
void ddsrt_atomic_lifo_push (ddsrt_atomic_lifo_t *head, void *elem, size_t linkoff)
|
||||
{
|
||||
uintptr_t a0, b0;
|
||||
do {
|
||||
a0 = *((volatile uintptr_t *) &head->aba_head.s.a);
|
||||
b0 = *((volatile uintptr_t *) &head->aba_head.s.b);
|
||||
*((volatile uintptr_t *) ((char *) elem + linkoff)) = b0;
|
||||
} while (!ddsrt_atomic_casvoidp2 (&head->aba_head, a0, b0, a0+1, (uintptr_t)elem));
|
||||
}
|
||||
void *ddsrt_atomic_lifo_pop (ddsrt_atomic_lifo_t *head, size_t linkoff) {
|
||||
uintptr_t a0, b0, b1;
|
||||
do {
|
||||
a0 = *((volatile uintptr_t *) &head->aba_head.s.a);
|
||||
b0 = *((volatile uintptr_t *) &head->aba_head.s.b);
|
||||
if (b0 == 0) {
|
||||
return NULL;
|
||||
}
|
||||
b1 = (*((volatile uintptr_t *) ((char *) b0 + linkoff)));
|
||||
} while (!ddsrt_atomic_casvoidp2 (&head->aba_head, a0, b0, a0+1, b1));
|
||||
return (void *) b0;
|
||||
}
|
||||
void ddsrt_atomic_lifo_pushmany (ddsrt_atomic_lifo_t *head, void *first, void *last, size_t linkoff)
|
||||
{
|
||||
uintptr_t a0, b0;
|
||||
do {
|
||||
a0 = *((volatile uintptr_t *) &head->aba_head.s.a);
|
||||
b0 = *((volatile uintptr_t *) &head->aba_head.s.b);
|
||||
*((volatile uintptr_t *) ((char *) last + linkoff)) = b0;
|
||||
} while (!ddsrt_atomic_casvoidp2 (&head->aba_head, a0, b0, a0+1, (uintptr_t)first));
|
||||
}
|
||||
#endif
|
||||
149
src/ddsrt/src/cdtors.c
Normal file
149
src/ddsrt/src/cdtors.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
#if _WIN32
|
||||
/* Sockets API initialization is only necessary on Microsoft Windows. The
|
||||
overly correct approach would be to abstract this a little further, but for
|
||||
now a pragmatic approach will suffice. */
|
||||
extern void ddsrt_winsock_init(void);
|
||||
extern void ddsrt_winsock_fini(void);
|
||||
extern void ddsrt_time_init(void);
|
||||
extern void ddsrt_time_fini(void);
|
||||
#endif
|
||||
|
||||
#define INIT_STATUS_OK 0x80000000u
|
||||
static ddsrt_atomic_uint32_t init_status = DDSRT_ATOMIC_UINT32_INIT(0);
|
||||
static ddsrt_mutex_t init_mutex;
|
||||
|
||||
void ddsrt_init (void)
|
||||
{
|
||||
uint32_t v;
|
||||
v = ddsrt_atomic_inc32_nv(&init_status);
|
||||
retry:
|
||||
if (v > INIT_STATUS_OK)
|
||||
return;
|
||||
else if (v == 1) {
|
||||
ddsrt_mutex_init(&init_mutex);
|
||||
#if _WIN32
|
||||
ddsrt_winsock_init();
|
||||
ddsrt_time_init();
|
||||
#endif
|
||||
ddsrt_atomic_or32(&init_status, INIT_STATUS_OK);
|
||||
} else {
|
||||
while (v > 1 && !(v & INIT_STATUS_OK)) {
|
||||
dds_sleepfor(10000000);
|
||||
v = ddsrt_atomic_ld32(&init_status);
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
void ddsrt_fini (void)
|
||||
{
|
||||
uint32_t v, nv;
|
||||
do {
|
||||
v = ddsrt_atomic_ld32(&init_status);
|
||||
if (v == (INIT_STATUS_OK | 1)) {
|
||||
nv = 1;
|
||||
} else {
|
||||
nv = v - 1;
|
||||
}
|
||||
} while (!ddsrt_atomic_cas32(&init_status, v, nv));
|
||||
if (nv == 1)
|
||||
{
|
||||
ddsrt_mutex_destroy(&init_mutex);
|
||||
#if _WIN32
|
||||
ddsrt_winsock_fini();
|
||||
ddsrt_time_fini();
|
||||
#endif
|
||||
ddsrt_atomic_dec32(&init_status);
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_mutex_t *ddsrt_get_singleton_mutex(void)
|
||||
{
|
||||
return &init_mutex;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
/* Executed before DllMain within the context of the thread. Located here too
|
||||
avoid removal due to link time optimization. */
|
||||
void WINAPI
|
||||
ddsrt_cdtor(
|
||||
PVOID handle,
|
||||
DWORD reason,
|
||||
PVOID reserved)
|
||||
{
|
||||
switch (reason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
ddsrt_init();
|
||||
/* fall through */
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH: /* Specified when thread exits. */
|
||||
ddsrt_thread_fini();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH: /* Specified when main thread exits. */
|
||||
ddsrt_thread_fini();
|
||||
ddsrt_fini();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* These instructions are very specific to the Windows platform. They register
|
||||
a function (or multiple) as a TLS initialization function. TLS initializers
|
||||
are executed when a thread (or program) attaches or detaches. In contrast to
|
||||
DllMain, a TLS initializer is also executed when the library is linked
|
||||
statically. TLS initializers are always executed before DllMain (both when
|
||||
the library is attached and detached). See http://www.nynaeve.net/?p=190,
|
||||
for a detailed explanation on TLS initializers. Boost and/or POSIX Threads
|
||||
for Windows code bases may also form good sources of information on this
|
||||
subject.
|
||||
|
||||
These instructions could theoretically be hidden in the build system, but
|
||||
doing so would be going a bit overboard as only Windows offers (and
|
||||
requires) this type of functionality/initialization. Apart from that the
|
||||
logic isn't exactly as trivial as for example determining the endianness of
|
||||
a platform, so keeping this close to the implementation is probably wise. */
|
||||
#ifdef _WIN64
|
||||
#pragma comment (linker, "/INCLUDE:_tls_used")
|
||||
#pragma comment (linker, "/INCLUDE:tls_callback_func")
|
||||
#pragma const_seg(".CRT$XLZ")
|
||||
EXTERN_C const PIMAGE_TLS_CALLBACK tls_callback_func = ddsrt_cdtor;
|
||||
#pragma const_seg()
|
||||
#else
|
||||
#pragma comment (linker, "/INCLUDE:__tls_used")
|
||||
#pragma comment (linker, "/INCLUDE:_tls_callback_func")
|
||||
#pragma data_seg(".CRT$XLZ")
|
||||
EXTERN_C PIMAGE_TLS_CALLBACK tls_callback_func = ddsrt_cdtor;
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
#else /* _WIN32 */
|
||||
void __attribute__((constructor)) ddsrt_ctor(void)
|
||||
{
|
||||
ddsrt_init();
|
||||
}
|
||||
|
||||
void __attribute__((destructor)) ddsrt_dtor(void)
|
||||
{
|
||||
ddsrt_fini();
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
88
src/ddsrt/src/environ/posix/environ.c
Normal file
88
src/ddsrt/src/environ/posix/environ.c
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/environ.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
static int
|
||||
isenvvar(const char *name)
|
||||
{
|
||||
return (*name == '\0' || strchr(name, '=') != NULL) == 0;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getenv(const char *name, char **value)
|
||||
{
|
||||
char *env;
|
||||
|
||||
assert(name != NULL);
|
||||
assert(value != NULL);
|
||||
|
||||
if (!isenvvar(name))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if ((env = getenv(name)) != NULL) {
|
||||
*value = env;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_setenv(const char *name, const char *value)
|
||||
{
|
||||
assert(name != NULL);
|
||||
assert(value != NULL);
|
||||
|
||||
if (strlen(value) == 0)
|
||||
return ddsrt_unsetenv(name);
|
||||
if (!isenvvar(name))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if (setenv(name, value, 1) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_unsetenv(const char *name)
|
||||
{
|
||||
assert(name != NULL);
|
||||
|
||||
if (!isenvvar(name))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if (unsetenv(name) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
73
src/ddsrt/src/environ/windows/environ.c
Normal file
73
src/ddsrt/src/environ/windows/environ.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/environ.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
static int
|
||||
isenvvar(const char *name)
|
||||
{
|
||||
return (*name == '\0' || strchr(name, '=') != NULL) == 0;
|
||||
}
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4996)
|
||||
dds_retcode_t
|
||||
ddsrt_getenv(const char *name, char **value)
|
||||
{
|
||||
char *env;
|
||||
|
||||
assert(name != NULL);
|
||||
assert(value != NULL);
|
||||
|
||||
if (!isenvvar(name))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
if ((env = getenv(name)) != NULL) {
|
||||
*value = env;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
}
|
||||
DDSRT_WARNING_MSVC_ON(4996)
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_setenv(const char *name, const char *value)
|
||||
{
|
||||
assert(name != NULL);
|
||||
assert(value != NULL);
|
||||
|
||||
if (!isenvvar(name))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
switch (_putenv_s(name, value)) {
|
||||
case 0:
|
||||
return DDS_RETCODE_OK;
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_unsetenv(const char *name)
|
||||
{
|
||||
assert(name != NULL);
|
||||
return ddsrt_setenv(name, "");
|
||||
}
|
||||
83
src/ddsrt/src/getopt.c
Normal file
83
src/ddsrt/src/getopt.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
/* ::[[ @(#) getopt.c 1.5 89/03/11 05:40:23 ]]:: */
|
||||
#ifndef LINT
|
||||
static const char Id[] = "$Id: os_stdlib_getopt.c,v 1.2 2008-11-17 09:53:45 hansv Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Here's something you've all been waiting for: the AT&T public domain
|
||||
* source for getopt(3). It is the code which was given out at the 1985
|
||||
* UNIFORUM conference in Dallas. I obtained it by electronic mail
|
||||
* directly from AT&T. The people there assure me that it is indeed
|
||||
* in the public domain.
|
||||
*
|
||||
* There is no manual page. That is because the one they gave out at
|
||||
* UNIFORUM was slightly different from the current System V Release 2
|
||||
* manual page. The difference apparently involved a note about the
|
||||
* famous rules 5 and 6, recommending using white space between an option
|
||||
* and its first argument, and not grouping options that have arguments.
|
||||
* Getopt itself is currently lenient about both of these things White
|
||||
* space is allowed, but not mandatory, and the last option in a group can
|
||||
* have an argument. That particular version of the man page evidently
|
||||
* has no official existence, and my source at AT&T did not send a copy.
|
||||
* The current SVR2 man page reflects the actual behavor of this getopt.
|
||||
* However, I am not about to post a copy of anything licensed by AT&T.
|
||||
*/
|
||||
|
||||
#define ERR(szz,czz) if(opterr){fprintf(stderr,"%s%s%c\n",argv[0],szz,czz);}
|
||||
|
||||
int opterr = 1;
|
||||
int optind = 1;
|
||||
int optopt;
|
||||
char *optarg;
|
||||
|
||||
int
|
||||
getopt(
|
||||
int argc,
|
||||
char **argv,
|
||||
const char *opts)
|
||||
{
|
||||
static int sp = 1;
|
||||
register int c;
|
||||
register char *cp;
|
||||
|
||||
if (sp == 1) {
|
||||
if (optind >= argc ||
|
||||
argv[optind][0] != '-' || argv[optind][1] == '\0')
|
||||
return (EOF);
|
||||
else if (strcmp(argv[optind], "--") == 0) {
|
||||
optind++;
|
||||
return (EOF);
|
||||
}
|
||||
}
|
||||
optopt = c = argv[optind][sp];
|
||||
if (c == ':' || (cp = strchr(opts, c)) == NULL) {
|
||||
ERR(": illegal option -- ", c);
|
||||
if (argv[optind][++sp] == '\0') {
|
||||
optind++;
|
||||
sp = 1;
|
||||
}
|
||||
return ('?');
|
||||
}
|
||||
if (*++cp == ':') {
|
||||
if (argv[optind][sp + 1] != '\0')
|
||||
optarg = &argv[optind++][sp + 1];
|
||||
else if (++optind >= argc) {
|
||||
ERR(": option requires an argument -- ", c);
|
||||
sp = 1;
|
||||
return ('?');
|
||||
} else
|
||||
optarg = argv[optind++];
|
||||
sp = 1;
|
||||
} else {
|
||||
if (argv[optind][++sp] == '\0') {
|
||||
sp = 1;
|
||||
optind++;
|
||||
}
|
||||
optarg = NULL;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
91
src/ddsrt/src/heap/posix/heap.c
Normal file
91
src/ddsrt/src/heap/posix/heap.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
|
||||
void *
|
||||
ddsrt_malloc_s(size_t size)
|
||||
{
|
||||
return malloc(size ? size : 1); /* Allocate memory even if size == 0 */
|
||||
}
|
||||
|
||||
void *
|
||||
ddsrt_malloc(size_t size)
|
||||
{
|
||||
void *ptr = ddsrt_malloc_s(size);
|
||||
|
||||
if (ptr == NULL) {
|
||||
/* Heap exhausted */
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *
|
||||
ddsrt_calloc(size_t count, size_t size)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = ddsrt_calloc_s(count, size);
|
||||
|
||||
if (ptr == NULL) {
|
||||
/* Heap exhausted */
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *
|
||||
ddsrt_calloc_s(size_t count, size_t size)
|
||||
{
|
||||
if (count == 0 || size == 0) {
|
||||
count = size = 1;
|
||||
}
|
||||
return calloc(count, size);
|
||||
}
|
||||
|
||||
void *
|
||||
ddsrt_realloc(void *memblk, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = ddsrt_realloc_s(memblk, size);
|
||||
|
||||
if (ptr == NULL){
|
||||
/* Heap exhausted */
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *
|
||||
ddsrt_realloc_s(void *memblk, size_t size)
|
||||
{
|
||||
/* Even though newmem = realloc(mem, 0) is equivalent to calling free(mem),
|
||||
not all platforms will return newmem == NULL. We consistently do, so the
|
||||
result of a non-failing ddsrt_realloc_s always needs to be free'd, like
|
||||
ddsrt_malloc_s(0). */
|
||||
return realloc(memblk, size ? size : 1);
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_free(void *ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
free (ptr);
|
||||
}
|
||||
}
|
||||
147
src/ddsrt/src/heap/vxworks/heap.c
Normal file
147
src/ddsrt/src/heap/vxworks/heap.c
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/** \file os/vxworks/os_platform_heap.c
|
||||
* \brief VxWorks heap memory management
|
||||
*
|
||||
* Implements heap memory management for VxWorks
|
||||
* by including the common implementation
|
||||
*/
|
||||
#if defined(OS_USE_ALLIGNED_MALLOC)
|
||||
#ifndef NDEBUG
|
||||
#include "os/os.h"
|
||||
atomic_t os__reallocdoublecopycount = 0;
|
||||
#endif
|
||||
|
||||
void *
|
||||
ddsrt_malloc(
|
||||
size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
void *origptr;
|
||||
|
||||
origptr = malloc(size+12);
|
||||
ptr=origptr;
|
||||
if (!ptr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
assert ( ((char *)ptr - (char *)0) % 4 == 0 );
|
||||
|
||||
if ( ((char *)ptr - (char *)0) % 8 != 0 )
|
||||
{
|
||||
/* malloc returned memory not 8 byte aligned */
|
||||
/* move pointer by 4 so that it will be aligned again */
|
||||
ptr=((uint32_t *)ptr) + 1;
|
||||
}
|
||||
|
||||
/* Store requested size */
|
||||
/* 8 bytes before the pointer we return */
|
||||
*(((size_t *)ptr)) = size;
|
||||
ptr=((size_t *)ptr) + 1;
|
||||
|
||||
/* Store pointer to result of malloc "before" the allocation */
|
||||
/* 4 bytes before the pointer we return */
|
||||
*((void **)ptr)= origptr;
|
||||
ptr=((uint32_t *)ptr) + 1;
|
||||
|
||||
assert ( ((char *)ptr - (char *)0) % 8 == 0 );
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ddsrt_realloc(
|
||||
void *ptr,
|
||||
size_t size)
|
||||
{
|
||||
void *newptr; /* Address returned from system realloc */
|
||||
void *origptr; /* Address returned by previous *alloc */
|
||||
void *olddata; /* Address of original user data immediately after realloc. */
|
||||
void *newdata; /* Address user data will be at on return. */
|
||||
size_t origsize; /* Size before realloc */
|
||||
|
||||
if ( ptr == NULL )
|
||||
{
|
||||
return (ddsrt_malloc(size));
|
||||
}
|
||||
|
||||
assert ( ((char *)ptr - (char *)0) % 8 == 0 );
|
||||
|
||||
origptr = *(((void **)ptr)-1);
|
||||
if ( size == 0 )
|
||||
{
|
||||
/* really a free */
|
||||
realloc(origptr, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
origsize = *(((size_t *)ptr)-2);
|
||||
newptr = realloc(origptr, size+12);
|
||||
if ( newptr == NULL )
|
||||
{
|
||||
/* realloc failed, everything is left untouched */
|
||||
return NULL;
|
||||
}
|
||||
olddata = (char *)newptr + ((char *)ptr - (char *)origptr);
|
||||
|
||||
assert ( ((char *)newptr - (char *)0) % 4 == 0 );
|
||||
|
||||
if ( ((char *)newptr - (char *)0) % 8 == 0 )
|
||||
{
|
||||
/* Allow space for size and pointer */
|
||||
newdata = ((uint32_t *)newptr)+2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* malloc returned memory not 8 byte aligned */
|
||||
/* realign, and Allow space for size and pointer */
|
||||
newdata = ((uint32_t *)newptr)+3;
|
||||
}
|
||||
|
||||
assert ( ((char *)newdata - (char *)0) % 8 == 0 );
|
||||
|
||||
if ( (((char *)newptr - (char *)0) % 8) != (((char *)origptr - (char *)0) % 8) )
|
||||
{
|
||||
/* realloc returned memory with different alignment */
|
||||
assert ( ((char *)newdata)+4 == ((char *)olddata)
|
||||
||((char *)olddata)+4 == ((char *)newdata));
|
||||
#ifndef NDEBUG
|
||||
vxAtomicInc( &os__reallocdoublecopycount);
|
||||
#endif
|
||||
memmove(newdata, olddata, origsize < size ? origsize : size);
|
||||
}
|
||||
|
||||
/* Store requested size */
|
||||
/* 8 bytes before the pointer we return */
|
||||
*(((size_t *)newdata)-2) = size;
|
||||
|
||||
/* Store pointer to result of realloc "before" the allocation */
|
||||
/* 4 bytes before the pointer we return */
|
||||
*(((void **)newdata)-1) = newptr;
|
||||
|
||||
return newdata;
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_free(
|
||||
void *ptr)
|
||||
{
|
||||
assert ( ((char *)ptr - (char *)0) % 8 == 0 );
|
||||
free(*(((void **)ptr)-1));
|
||||
}
|
||||
#else
|
||||
/* For 64bit use the native ops align to 8 bytes */
|
||||
#include "../snippets/code/os_heap.c"
|
||||
|
||||
#endif /* OS_USE_ALLIGNED_MALLOC */
|
||||
|
||||
30
src/ddsrt/src/ifaddrs.c
Normal file
30
src/ddsrt/src/ifaddrs.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/ifaddrs.h"
|
||||
|
||||
void
|
||||
ddsrt_freeifaddrs(ddsrt_ifaddrs_t *ifa)
|
||||
{
|
||||
ddsrt_ifaddrs_t *next;
|
||||
|
||||
while (ifa != NULL) {
|
||||
next = ifa->next;
|
||||
ddsrt_free(ifa->name);
|
||||
ddsrt_free(ifa->addr);
|
||||
ddsrt_free(ifa->netmask);
|
||||
ddsrt_free(ifa->broadaddr);
|
||||
ddsrt_free(ifa);
|
||||
ifa = next;
|
||||
}
|
||||
}
|
||||
|
||||
135
src/ddsrt/src/ifaddrs/posix/ifaddrs.c
Normal file
135
src/ddsrt/src/ifaddrs/posix/ifaddrs.c
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/ifaddrs.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
extern const int *const os_supp_afs;
|
||||
|
||||
static dds_retcode_t
|
||||
copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_OK;
|
||||
ddsrt_ifaddrs_t *ifa;
|
||||
size_t sz;
|
||||
|
||||
assert(ifap != NULL);
|
||||
assert(sys_ifa != NULL);
|
||||
|
||||
sz = ddsrt_sockaddr_get_size(sys_ifa->ifa_addr);
|
||||
ifa = ddsrt_calloc_s(1, sizeof(*ifa));
|
||||
if (ifa == NULL) {
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ifa->index = if_nametoindex(sys_ifa->ifa_name);
|
||||
ifa->flags = sys_ifa->ifa_flags;
|
||||
if ((ifa->name = ddsrt_strdup(sys_ifa->ifa_name)) == NULL ||
|
||||
(ifa->addr = ddsrt_memdup(sys_ifa->ifa_addr, sz)) == NULL ||
|
||||
(sys_ifa->ifa_netmask != NULL &&
|
||||
(ifa->netmask = ddsrt_memdup(sys_ifa->ifa_netmask, sz)) == NULL) ||
|
||||
(sys_ifa->ifa_broadaddr != NULL &&
|
||||
(sys_ifa->ifa_flags & IFF_BROADCAST) &&
|
||||
(ifa->broadaddr = ddsrt_memdup(sys_ifa->ifa_broadaddr, sz)) == NULL))
|
||||
{
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
/* Seen on macOS using OpenVPN: netmask without an address family,
|
||||
in which case copy it from the interface address */
|
||||
if (ifa->addr && ifa->netmask && ifa->netmask->sa_family == 0) {
|
||||
ifa->netmask->sa_family = ifa->addr->sa_family;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
*ifap = ifa;
|
||||
} else {
|
||||
ddsrt_freeifaddrs(ifa);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const int *afs)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_OK;
|
||||
int use;
|
||||
ddsrt_ifaddrs_t *ifa, *ifa_root, *ifa_next;
|
||||
struct ifaddrs *sys_ifa, *sys_ifa_root;
|
||||
struct sockaddr *sa;
|
||||
|
||||
assert(ifap != NULL);
|
||||
|
||||
if (afs == NULL) {
|
||||
afs = os_supp_afs;
|
||||
}
|
||||
|
||||
if (getifaddrs(&sys_ifa_root) == -1) {
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
err = DDS_RETCODE_NOT_ALLOWED;
|
||||
break;
|
||||
case ENOMEM:
|
||||
case ENOBUFS:
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
break;
|
||||
default:
|
||||
err = DDS_RETCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ifa = ifa_root = NULL;
|
||||
|
||||
for (sys_ifa = sys_ifa_root;
|
||||
sys_ifa != NULL && err == 0;
|
||||
sys_ifa = sys_ifa->ifa_next)
|
||||
{
|
||||
sa = sys_ifa->ifa_addr;
|
||||
if (sa != NULL) {
|
||||
use = 0;
|
||||
for (int i = 0; !use && afs[i] != DDSRT_AF_TERM; i++) {
|
||||
use = (sa->sa_family == afs[i]);
|
||||
}
|
||||
|
||||
if (use) {
|
||||
err = copyaddr(&ifa_next, sys_ifa);
|
||||
if (err == DDS_RETCODE_OK) {
|
||||
if (ifa == NULL) {
|
||||
ifa = ifa_root = ifa_next;
|
||||
} else {
|
||||
ifa->next = ifa_next;
|
||||
ifa = ifa_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(sys_ifa_root);
|
||||
|
||||
if (err == 0) {
|
||||
*ifap = ifa_root;
|
||||
} else {
|
||||
ddsrt_freeifaddrs(ifa_root);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
283
src/ddsrt/src/ifaddrs/windows/ifaddrs.c
Normal file
283
src/ddsrt/src/ifaddrs/windows/ifaddrs.c
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/ifaddrs.h"
|
||||
#include "dds/ddsrt/io.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
extern const int *const os_supp_afs;
|
||||
|
||||
static dds_retcode_t
|
||||
getifaces(PIP_ADAPTER_ADDRESSES *ptr)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
PIP_ADAPTER_ADDRESSES buf = NULL;
|
||||
ULONG bufsz = 0; /* Size is determined on first iteration. */
|
||||
ULONG ret;
|
||||
size_t i;
|
||||
|
||||
static const size_t max = 2;
|
||||
static const ULONG filter = GAA_FLAG_INCLUDE_PREFIX |
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER;
|
||||
|
||||
assert(ptr != NULL);
|
||||
|
||||
for (i = 0; err == DDS_RETCODE_NOT_ENOUGH_SPACE && i < max; i++) {
|
||||
ret = GetAdaptersAddresses(AF_UNSPEC, filter, NULL, buf, &bufsz);
|
||||
assert(ret != ERROR_INVALID_PARAMETER);
|
||||
switch (ret) {
|
||||
case ERROR_BUFFER_OVERFLOW:
|
||||
err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
ddsrt_free(buf);
|
||||
if ((buf = (IP_ADAPTER_ADDRESSES *)ddsrt_malloc(bufsz)) == NULL) {
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
break;
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
break;
|
||||
case ERROR_SUCCESS:
|
||||
case ERROR_ADDRESS_NOT_ASSOCIATED: /* No address associated yet. */
|
||||
case ERROR_NO_DATA: /* No adapters that match the filter. */
|
||||
default:
|
||||
err = DDS_RETCODE_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == DDS_RETCODE_OK) {
|
||||
*ptr = buf;
|
||||
} else {
|
||||
ddsrt_free(buf);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static dds_retcode_t
|
||||
getaddrtable(PMIB_IPADDRTABLE *ptr)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
PMIB_IPADDRTABLE buf = NULL;
|
||||
ULONG bufsz = 0;
|
||||
DWORD ret;
|
||||
size_t i;
|
||||
|
||||
static const size_t max = 2;
|
||||
|
||||
assert(ptr != NULL);
|
||||
|
||||
for (i = 0; err == DDS_RETCODE_NOT_ENOUGH_SPACE && i < max; i++) {
|
||||
ret = GetIpAddrTable(buf, &bufsz, 0);
|
||||
assert(ret != ERROR_INVALID_PARAMETER &&
|
||||
ret != ERROR_NOT_SUPPORTED);
|
||||
switch (ret) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
ddsrt_free(buf);
|
||||
if ((buf = (PMIB_IPADDRTABLE)ddsrt_malloc(bufsz)) == NULL) {
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
break;
|
||||
case NO_ERROR:
|
||||
err = DDS_RETCODE_OK;
|
||||
break;
|
||||
default:
|
||||
err = DDS_RETCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
*ptr = buf;
|
||||
} else {
|
||||
ddsrt_free(buf);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
getflags(const PIP_ADAPTER_ADDRESSES iface)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (iface->OperStatus == IfOperStatusUp) {
|
||||
flags |= IFF_UP;
|
||||
}
|
||||
if (!(iface->Flags & IP_ADAPTER_NO_MULTICAST) &&
|
||||
(iface->IfType != IF_TYPE_SOFTWARE_LOOPBACK))
|
||||
{
|
||||
/* multicast over loopback doesn't seem to work despite the NO_MULTICAST
|
||||
flag being clear assuming an interface is multicast-capable when in fact
|
||||
it isn't is disastrous, so it makes more sense to err by assuming it
|
||||
won't work as there is always the AssumeMulticastCapable setting to
|
||||
overrule it */
|
||||
flags |= IFF_MULTICAST;
|
||||
}
|
||||
|
||||
switch (iface->IfType) {
|
||||
case IF_TYPE_SOFTWARE_LOOPBACK:
|
||||
flags |= IFF_LOOPBACK;
|
||||
break;
|
||||
case IF_TYPE_ETHERNET_CSMACD:
|
||||
case IF_TYPE_IEEE80211:
|
||||
case IF_TYPE_IEEE1394:
|
||||
case IF_TYPE_ISO88025_TOKENRING:
|
||||
flags |= IFF_BROADCAST;
|
||||
break;
|
||||
default:
|
||||
flags |= IFF_POINTTOPOINT;
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int
|
||||
copyaddr(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const PIP_ADAPTER_ADDRESSES iface,
|
||||
const PMIB_IPADDRTABLE addrtable,
|
||||
const PIP_ADAPTER_UNICAST_ADDRESS addr)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_OK;
|
||||
ddsrt_ifaddrs_t *ifa;
|
||||
struct sockaddr *sa;
|
||||
size_t sz;
|
||||
|
||||
assert(iface != NULL);
|
||||
assert(addrtable != NULL);
|
||||
assert(addr != NULL);
|
||||
|
||||
sa = (struct sockaddr *)addr->Address.lpSockaddr;
|
||||
sz = (size_t)addr->Address.iSockaddrLength;
|
||||
|
||||
if ((ifa = ddsrt_calloc_s(1, sizeof(*ifa))) == NULL) {
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ifa->flags = getflags(iface);
|
||||
ifa->addr = ddsrt_memdup(sa, sz);
|
||||
(void)ddsrt_asprintf(&ifa->name, "%wS", iface->FriendlyName);
|
||||
if (ifa->addr == NULL || ifa->name == NULL) {
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else if (ifa->addr->sa_family == AF_INET6) {
|
||||
ifa->index = iface->Ipv6IfIndex;
|
||||
|
||||
/* Address is not in addrtable if the interface is not connected. */
|
||||
} else if (ifa->addr->sa_family == AF_INET && (ifa->flags & IFF_UP)) {
|
||||
DWORD i = 0;
|
||||
struct sockaddr_in nm, bc, *sin = (struct sockaddr_in *)sa;
|
||||
|
||||
assert(sz == sizeof(nm));
|
||||
memset(&nm, 0, sz);
|
||||
memset(&bc, 0, sz);
|
||||
nm.sin_family = bc.sin_family = AF_INET;
|
||||
|
||||
for (; i < addrtable->dwNumEntries; i++) {
|
||||
if (sin->sin_addr.s_addr == addrtable->table[i].dwAddr) {
|
||||
ifa->index = addrtable->table[i].dwIndex;
|
||||
nm.sin_addr.s_addr = addrtable->table[i].dwMask;
|
||||
bc.sin_addr.s_addr = sin->sin_addr.s_addr | ~(nm.sin_addr.s_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(i < addrtable->dwNumEntries);
|
||||
|
||||
if ((ifa->netmask = ddsrt_memdup(&nm, sz)) == NULL ||
|
||||
(ifa->broadaddr = ddsrt_memdup(&bc, sz)) == NULL)
|
||||
{
|
||||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
*ifap = ifa;
|
||||
} else {
|
||||
ddsrt_freeifaddrs(ifa);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const int *afs)
|
||||
{
|
||||
int err = 0;
|
||||
int use;
|
||||
PIP_ADAPTER_ADDRESSES ifaces = NULL, iface;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS addr = NULL;
|
||||
PMIB_IPADDRTABLE addrtable = NULL;
|
||||
ddsrt_ifaddrs_t *ifa, *ifa_root, *ifa_next;
|
||||
struct sockaddr *sa;
|
||||
|
||||
assert(ifap != NULL);
|
||||
|
||||
if (afs == NULL) {
|
||||
afs = os_supp_afs;
|
||||
}
|
||||
|
||||
ifa = ifa_root = ifa_next = NULL;
|
||||
|
||||
if ((err = getifaces(&ifaces)) == DDS_RETCODE_OK &&
|
||||
(err = getaddrtable(&addrtable)) == DDS_RETCODE_OK)
|
||||
{
|
||||
for (iface = ifaces; !err && iface != NULL; iface = iface->Next) {
|
||||
for (addr = iface->FirstUnicastAddress;
|
||||
addr != NULL;
|
||||
addr = addr->Next)
|
||||
{
|
||||
sa = (struct sockaddr *)addr->Address.lpSockaddr;
|
||||
use = 0;
|
||||
for (int i = 0; !use && afs[i] != DDSRT_AF_TERM; i++) {
|
||||
use = (afs[i] == sa->sa_family);
|
||||
}
|
||||
|
||||
if (use) {
|
||||
err = copyaddr(&ifa_next, iface, addrtable, addr);
|
||||
if (err == DDS_RETCODE_OK) {
|
||||
if (ifa == NULL) {
|
||||
ifa = ifa_root = ifa_next;
|
||||
} else {
|
||||
ifa->next = ifa_next;
|
||||
ifa = ifa_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_free(ifaces);
|
||||
ddsrt_free(addrtable);
|
||||
|
||||
if (err == DDS_RETCODE_OK) {
|
||||
*ifap = ifa_root;
|
||||
} else {
|
||||
ddsrt_freeifaddrs(ifa_root);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
72
src/ddsrt/src/io.c
Normal file
72
src/ddsrt/src/io.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/io.h"
|
||||
|
||||
int
|
||||
ddsrt_asprintf(
|
||||
char **strp,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
int ret;
|
||||
unsigned int len;
|
||||
char buf[1] = { '\0' };
|
||||
char *str = NULL;
|
||||
va_list args1, args2;
|
||||
|
||||
assert(strp != NULL);
|
||||
assert(fmt != NULL);
|
||||
|
||||
va_start(args1, fmt);
|
||||
va_copy(args2, args1); /* va_list cannot be reused */
|
||||
|
||||
if ((ret = vsnprintf(buf, sizeof(buf), fmt, args1)) >= 0) {
|
||||
len = (unsigned int)ret; /* +1 for null byte */
|
||||
if ((str = ddsrt_malloc(len + 1)) == NULL) {
|
||||
ret = -1;
|
||||
} else if ((ret = vsnprintf(str, len + 1, fmt, args2)) >= 0) {
|
||||
assert(((unsigned int)ret) == len);
|
||||
*strp = str;
|
||||
} else {
|
||||
ddsrt_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args1);
|
||||
va_end(args2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
int
|
||||
snprintf(
|
||||
char *str,
|
||||
size_t size,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
int cnt;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
cnt = vsnprintf(str, size, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
#endif
|
||||
302
src/ddsrt/src/log.c
Normal file
302
src/ddsrt/src/log.c
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
#define MAX_TIMESTAMP_LEN (10 + 1 + 6)
|
||||
#define MAX_TID_LEN (10)
|
||||
#define HDR_LEN (MAX_TIMESTAMP_LEN + 1 + MAX_TID_LEN + 2)
|
||||
|
||||
#define BUF_OFFSET HDR_LEN
|
||||
|
||||
typedef struct {
|
||||
char buf[2048];
|
||||
size_t pos;
|
||||
} log_buffer_t;
|
||||
|
||||
typedef struct {
|
||||
dds_log_write_fn_t funcs[2];
|
||||
void *ptr;
|
||||
FILE *out;
|
||||
} log_sink_t;
|
||||
|
||||
static ddsrt_thread_local log_buffer_t log_buffer;
|
||||
|
||||
static ddsrt_once_t lock_inited = DDSRT_ONCE_INIT;
|
||||
static ddsrt_rwlock_t lock;
|
||||
|
||||
static uint32_t log_mask = DDS_LC_ERROR | DDS_LC_WARNING;
|
||||
|
||||
static void default_sink(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
fwrite(data->message - HDR_LEN, 1, HDR_LEN + data->size + 1, (FILE *)ptr);
|
||||
fflush((FILE *)ptr);
|
||||
}
|
||||
|
||||
static void nop_sink(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)data;
|
||||
return;
|
||||
}
|
||||
|
||||
#define LOG (0)
|
||||
#define TRACE (1)
|
||||
#define USE (0)
|
||||
#define SET (1)
|
||||
|
||||
static log_sink_t sinks[] = {
|
||||
/* Log */
|
||||
{ .funcs = { default_sink, default_sink }, .ptr = NULL, .out = NULL },
|
||||
/* Trace */
|
||||
{ .funcs = { nop_sink, default_sink }, .ptr = NULL, .out = NULL }
|
||||
};
|
||||
|
||||
uint32_t *const dds_log_mask = &log_mask;
|
||||
|
||||
#define RDLOCK (1)
|
||||
#define WRLOCK (2)
|
||||
|
||||
static void init_lock(void)
|
||||
{
|
||||
ddsrt_rwlock_init(&lock);
|
||||
sinks[LOG].ptr = sinks[TRACE].ptr = stderr;
|
||||
sinks[LOG].out = sinks[TRACE].out = stderr;
|
||||
}
|
||||
|
||||
static void lock_sink(int type)
|
||||
{
|
||||
assert(type == RDLOCK || type == WRLOCK);
|
||||
ddsrt_once(&lock_inited, &init_lock);
|
||||
|
||||
if (type == RDLOCK) {
|
||||
ddsrt_rwlock_read(&lock);
|
||||
} else {
|
||||
ddsrt_rwlock_write(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void unlock_sink(void)
|
||||
{
|
||||
ddsrt_rwlock_unlock(&lock);
|
||||
}
|
||||
|
||||
static void set_active_log_sinks(void)
|
||||
{
|
||||
if (dds_get_log_mask() & DDS_LOG_MASK) {
|
||||
sinks[LOG].funcs[USE] = sinks[LOG].funcs[SET];
|
||||
} else {
|
||||
sinks[LOG].funcs[USE] = nop_sink;
|
||||
}
|
||||
if (dds_get_log_mask() & DDS_TRACE_MASK) {
|
||||
sinks[TRACE].funcs[USE] = sinks[TRACE].funcs[SET];
|
||||
} else {
|
||||
sinks[TRACE].funcs[USE] = nop_sink;
|
||||
}
|
||||
if (sinks[LOG].funcs[USE] == sinks[TRACE].funcs[USE] &&
|
||||
sinks[LOG].ptr == sinks[TRACE].ptr)
|
||||
{
|
||||
sinks[LOG].funcs[USE] = nop_sink;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_log_sink(
|
||||
log_sink_t *sink,
|
||||
dds_log_write_fn_t func,
|
||||
void *ptr)
|
||||
{
|
||||
assert(sink != NULL);
|
||||
|
||||
/* No life cycle management is done for log sinks, the caller is
|
||||
responsible for that. Ensure this operation is deterministic and that on
|
||||
return, no thread in the DDS stack still uses the deprecated sink. */
|
||||
lock_sink(WRLOCK);
|
||||
|
||||
if (func == 0) {
|
||||
sink->funcs[SET] = default_sink;
|
||||
sink->ptr = sink->out;
|
||||
} else {
|
||||
sink->funcs[SET] = func;
|
||||
sink->ptr = ptr;
|
||||
}
|
||||
|
||||
set_active_log_sinks();
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
/* dds_set_log_file must be considered private. */
|
||||
void dds_set_log_file(FILE *file)
|
||||
{
|
||||
lock_sink(WRLOCK);
|
||||
sinks[LOG].out = (file == NULL ? stderr : file);
|
||||
if (sinks[LOG].funcs[SET] == default_sink) {
|
||||
sinks[LOG].ptr = sinks[LOG].out;
|
||||
}
|
||||
set_active_log_sinks();
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
void dds_set_trace_file(FILE *file)
|
||||
{
|
||||
lock_sink(WRLOCK);
|
||||
sinks[TRACE].out = (file == NULL ? stderr : file);
|
||||
if (sinks[TRACE].funcs[SET] == default_sink) {
|
||||
sinks[TRACE].ptr = sinks[TRACE].out;
|
||||
}
|
||||
set_active_log_sinks();
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
void dds_set_log_sink(
|
||||
dds_log_write_fn_t callback,
|
||||
void *userdata)
|
||||
{
|
||||
set_log_sink(&sinks[LOG], callback, userdata);
|
||||
}
|
||||
|
||||
void dds_set_trace_sink(
|
||||
dds_log_write_fn_t callback,
|
||||
void *userdata)
|
||||
{
|
||||
set_log_sink(&sinks[TRACE], callback, userdata);
|
||||
}
|
||||
|
||||
extern inline uint32_t
|
||||
dds_get_log_mask(void);
|
||||
|
||||
void
|
||||
dds_set_log_mask(uint32_t cats)
|
||||
{
|
||||
lock_sink(WRLOCK);
|
||||
*dds_log_mask = (cats & (DDS_LOG_MASK | DDS_TRACE_MASK));
|
||||
set_active_log_sinks();
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
static void print_header(char *str)
|
||||
{
|
||||
int cnt;
|
||||
char *tid, buf[MAX_TID_LEN+1] = { 0 };
|
||||
static const char fmt[] = "%10u.%06d/%*.*s:";
|
||||
dds_time_t time;
|
||||
unsigned sec;
|
||||
int usec;
|
||||
|
||||
(void)ddsrt_thread_getname(buf, sizeof(buf));
|
||||
tid = (buf[0] == '\0' ? "(anon)" : buf);
|
||||
time = dds_time();
|
||||
sec = (unsigned)(time / DDS_NSECS_IN_SEC);
|
||||
usec = (int)((time % DDS_NSECS_IN_SEC) / DDS_NSECS_IN_USEC);
|
||||
|
||||
cnt = snprintf(
|
||||
str, HDR_LEN, fmt, sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid);
|
||||
assert(cnt == (HDR_LEN - 1));
|
||||
str[cnt] = ' '; /* Replace snprintf null byte by space. */
|
||||
}
|
||||
|
||||
static void vlog(
|
||||
uint32_t cat,
|
||||
const char *file,
|
||||
uint32_t line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
int n, trunc = 0;
|
||||
size_t nrem;
|
||||
log_buffer_t *lb;
|
||||
dds_log_data_t data;
|
||||
|
||||
if (*fmt == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock_sink(RDLOCK);
|
||||
lb = &log_buffer;
|
||||
|
||||
/* Thread-local buffer is always initialized with all zeroes. The pos
|
||||
member must always be greater or equal to BUF_OFFSET. */
|
||||
if (lb->pos < BUF_OFFSET) {
|
||||
lb->pos = BUF_OFFSET;
|
||||
lb->buf[lb->pos] = 0;
|
||||
}
|
||||
nrem = sizeof (lb->buf) - lb->pos;
|
||||
if (nrem > 0) {
|
||||
n = vsnprintf(lb->buf + lb->pos, nrem, fmt, ap);
|
||||
if (n >= 0 && (size_t) n < nrem) {
|
||||
lb->pos += (size_t) n;
|
||||
} else {
|
||||
lb->pos += nrem;
|
||||
trunc = 1;
|
||||
}
|
||||
if (trunc) {
|
||||
static const char msg[] = "(trunc)\n";
|
||||
const size_t msglen = sizeof (msg) - 1;
|
||||
assert(lb->pos <= sizeof (lb->buf));
|
||||
assert(lb->pos >= msglen);
|
||||
memcpy(lb->buf + lb->pos - msglen, msg, msglen);
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt[strlen (fmt) - 1] == '\n') {
|
||||
print_header(lb->buf);
|
||||
|
||||
data.priority = cat;
|
||||
data.file = file;
|
||||
data.function = func;
|
||||
data.line = line;
|
||||
data.message = lb->buf + BUF_OFFSET;
|
||||
data.size = strlen(data.message) - 1;
|
||||
|
||||
for (size_t i = (cat & DDS_LOG_MASK) ? LOG : TRACE;
|
||||
i < sizeof(sinks) / sizeof(sinks[0]);
|
||||
i++)
|
||||
{
|
||||
sinks[i].funcs[USE](sinks[i].ptr, &data);
|
||||
}
|
||||
|
||||
lb->pos = BUF_OFFSET;
|
||||
lb->buf[lb->pos] = 0;
|
||||
}
|
||||
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
int
|
||||
dds_log(
|
||||
uint32_t cat,
|
||||
const char *file,
|
||||
uint32_t line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
if ((dds_get_log_mask() & cat) || (cat & DDS_LC_FATAL)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vlog(cat, file, line, func, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
if (cat & DDS_LC_FATAL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
src/ddsrt/src/process.c
Normal file
27
src/ddsrt/src/process.c
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "dds/ddsrt/process.h"
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
ddsrt_pid_t
|
||||
ddsrt_getpid(void)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return GetCurrentProcessId();
|
||||
#else
|
||||
/* Mapped to taskIdSelf() in VxWorks kernel mode. */
|
||||
return getpid();
|
||||
#endif
|
||||
}
|
||||
44
src/ddsrt/src/random.c
Normal file
44
src/ddsrt/src/random.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dds/ddsrt/random.h"
|
||||
|
||||
#if _WIN32
|
||||
#define _CRT_RAND_S
|
||||
#include <errno.h>
|
||||
|
||||
long random (void)
|
||||
{
|
||||
/* rand() is a really terribly bad PRNG */
|
||||
/* FIXME: Indeed (especially if not seeded), use rand_s instead. */
|
||||
union { long x; unsigned char c[4]; } t;
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
t.c[i] = (unsigned char) ((rand () >> 4) & 0xff);
|
||||
#if RAND_MAX == INT32_MAX || RAND_MAX == 0x7fff
|
||||
t.x &= RAND_MAX;
|
||||
#elif RAND_MAX <= 0x7ffffffe
|
||||
t.x %= (RAND_MAX+1);
|
||||
#else
|
||||
#error "RAND_MAX out of range"
|
||||
#endif
|
||||
return t.x;
|
||||
}
|
||||
#endif
|
||||
|
||||
long ddsrt_random(void)
|
||||
{
|
||||
/* FIXME: Not MT-safe, should use random_r (or a real PRNG) instead. */
|
||||
return random();
|
||||
}
|
||||
60
src/ddsrt/src/retcode.c
Normal file
60
src/ddsrt/src/retcode.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
static const char *retcodes[] =
|
||||
{
|
||||
"Success",
|
||||
"Error",
|
||||
"Unsupported",
|
||||
"Bad Parameter",
|
||||
"Precondition Not Met",
|
||||
"Out Of Resources",
|
||||
"Not Enabled",
|
||||
"Immutable Policy",
|
||||
"Inconsistent Policy",
|
||||
"Already Deleted",
|
||||
"Timeout",
|
||||
"No Data",
|
||||
"Illegal Operation",
|
||||
"Not Allowed By Security"
|
||||
};
|
||||
|
||||
static const char *xretcodes[] = {
|
||||
"Operation in progress",
|
||||
"Try again",
|
||||
"Interrupted",
|
||||
"Not allowed",
|
||||
"Host not found",
|
||||
"Network not available",
|
||||
"Connection not available",
|
||||
"No space left",
|
||||
"Result too large",
|
||||
"Not found"
|
||||
};
|
||||
|
||||
const char *
|
||||
dds_strretcode (dds_retcode_t rc)
|
||||
{
|
||||
if (rc >= 0 &&
|
||||
rc < (dds_retcode_t)(sizeof(retcodes) / sizeof(retcodes[0])))
|
||||
{
|
||||
return retcodes[rc];
|
||||
} else if (rc >= (DDS_XRETCODE_BASE) &&
|
||||
rc < (dds_retcode_t)(DDS_XRETCODE_BASE + (sizeof(xretcodes) / sizeof(xretcodes[0]))))
|
||||
{
|
||||
return xretcodes[rc - DDS_XRETCODE_BASE];
|
||||
}
|
||||
|
||||
return "Unknown return code";
|
||||
}
|
||||
|
||||
101
src/ddsrt/src/rusage/posix/rusage.c
Normal file
101
src/ddsrt/src/rusage/posix/rusage.c
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#define _GNU_SOURCE /* Required for RUSAGE_THREAD. */
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/mach_port.h>
|
||||
#include <mach/thread_act.h>
|
||||
#endif
|
||||
|
||||
#include "dds/ddsrt/rusage.h"
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getrusage(int who, ddsrt_rusage_t *usage)
|
||||
{
|
||||
int err = 0;
|
||||
struct rusage buf;
|
||||
dds_retcode_t rc;
|
||||
|
||||
assert(who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD);
|
||||
assert(usage != NULL);
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
|
||||
#if defined(__linux)
|
||||
if ((who == DDSRT_RUSAGE_SELF && getrusage(RUSAGE_SELF, &buf) == -1) ||
|
||||
(who == DDSRT_RUSAGE_THREAD && getrusage(RUSAGE_THREAD, &buf) == -1))
|
||||
{
|
||||
err = errno;
|
||||
} else {
|
||||
buf.ru_maxrss *= 1024;
|
||||
}
|
||||
#else
|
||||
if (getrusage(RUSAGE_SELF, &buf) == -1) {
|
||||
err = errno;
|
||||
} else if (who == DDSRT_RUSAGE_THREAD) {
|
||||
memset(&buf.ru_utime, 0, sizeof(buf.ru_utime));
|
||||
memset(&buf.ru_stime, 0, sizeof(buf.ru_stime));
|
||||
buf.ru_nvcsw = 0;
|
||||
buf.ru_nivcsw = 0;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
kern_return_t ret;
|
||||
mach_port_t thr;
|
||||
mach_msg_type_number_t cnt;
|
||||
thread_basic_info_data_t info;
|
||||
|
||||
thr = mach_thread_self();
|
||||
assert(thr != MACH_PORT_DEAD);
|
||||
if (thr == MACH_PORT_NULL) {
|
||||
/* Resource shortage prevented reception of send right. */
|
||||
err = ENOMEM;
|
||||
} else {
|
||||
cnt = THREAD_BASIC_INFO_COUNT;
|
||||
ret = thread_info(
|
||||
thr, THREAD_BASIC_INFO, (thread_info_t)&info, &cnt);
|
||||
assert(ret != KERN_INVALID_ARGUMENT);
|
||||
/* Assume MIG_ARRAY_TOO_LARGE will not happen. */
|
||||
buf.ru_utime.tv_sec = info.user_time.seconds;
|
||||
buf.ru_utime.tv_usec = info.user_time.microseconds;
|
||||
buf.ru_stime.tv_sec = info.system_time.seconds;
|
||||
buf.ru_stime.tv_usec = info.system_time.microseconds;
|
||||
mach_port_deallocate(mach_task_self(), thr);
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
}
|
||||
#endif /* __linux */
|
||||
|
||||
if (err == 0) {
|
||||
rc = DDS_RETCODE_OK;
|
||||
usage->utime =
|
||||
(buf.ru_utime.tv_sec * DDS_NSECS_IN_SEC) +
|
||||
(buf.ru_utime.tv_usec * DDS_NSECS_IN_USEC);
|
||||
usage->stime =
|
||||
(buf.ru_stime.tv_sec * DDS_NSECS_IN_SEC) +
|
||||
(buf.ru_stime.tv_usec * DDS_NSECS_IN_USEC);
|
||||
usage->maxrss = (size_t)buf.ru_maxrss;
|
||||
usage->idrss = (size_t)buf.ru_idrss;
|
||||
usage->nvcsw = (size_t)buf.ru_nvcsw;
|
||||
usage->nivcsw = (size_t)buf.ru_nivcsw;
|
||||
} else if (err == ENOMEM) {
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
rc = DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
53
src/ddsrt/src/rusage/windows/rusage.c
Normal file
53
src/ddsrt/src/rusage/windows/rusage.c
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/rusage.h"
|
||||
|
||||
#include <psapi.h>
|
||||
|
||||
dds_time_t
|
||||
filetime_to_time(const FILETIME *ft)
|
||||
{
|
||||
/* FILETIME structures express times in 100-nanosecond time units. */
|
||||
return ((ft->dwHighDateTime << 31) + (ft->dwLowDateTime)) * 100;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getrusage(int who, ddsrt_rusage_t *usage)
|
||||
{
|
||||
FILETIME stime, utime, ctime, etime;
|
||||
PROCESS_MEMORY_COUNTERS pmctrs;
|
||||
|
||||
assert(who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD);
|
||||
assert(usage != NULL);
|
||||
|
||||
/* Memory counters are per process, but populate them if thread resource
|
||||
usage is requested to keep in sync with Linux. */
|
||||
if ((!GetProcessMemoryInfo(GetCurrentProcess(), &pmctrs, sizeof(pmctrs)))
|
||||
|| (who == DDSRT_RUSAGE_SELF &&
|
||||
!GetProcessTimes(GetCurrentProcess(), &ctime, &etime, &stime, &utime))
|
||||
|| (who == DDSRT_RUSAGE_THREAD &&
|
||||
!GetThreadTimes(GetCurrentThread(), &ctime, &etime, &stime, &utime)))
|
||||
{
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
memset(usage, 0, sizeof(*usage));
|
||||
usage->stime = filetime_to_time(&stime);
|
||||
usage->utime = filetime_to_time(&utime);
|
||||
usage->maxrss = pmctrs.PeakWorkingSetSize;
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
354
src/ddsrt/src/sockets.c
Normal file
354
src/ddsrt/src/sockets.c
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
# if defined(__linux)
|
||||
# include <linux/if_packet.h> /* sockaddr_ll */
|
||||
# endif /* __linux */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/sockets_priv.h"
|
||||
|
||||
extern inline struct timeval *
|
||||
ddsrt_duration_to_timeval_ceil(dds_duration_t reltime, struct timeval *tv);
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
const struct in6_addr ddsrt_in6addr_any = IN6ADDR_ANY_INIT;
|
||||
const struct in6_addr ddsrt_in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
||||
#endif
|
||||
|
||||
const int afs[] = {
|
||||
#ifdef __linux
|
||||
AF_PACKET,
|
||||
#endif /* __linux */
|
||||
#if DDSRT_HAVE_IPV6
|
||||
AF_INET6,
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
AF_INET,
|
||||
DDSRT_AF_TERM /* Terminator */
|
||||
};
|
||||
|
||||
const int *const os_supp_afs = afs;
|
||||
|
||||
socklen_t
|
||||
ddsrt_sockaddr_get_size(const struct sockaddr *const sa)
|
||||
{
|
||||
socklen_t sz;
|
||||
|
||||
assert(sa != NULL);
|
||||
|
||||
switch(sa->sa_family) {
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6:
|
||||
sz = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
#ifdef __linux
|
||||
case AF_PACKET:
|
||||
sz = sizeof(struct sockaddr_ll);
|
||||
break;
|
||||
#endif /* __linux */
|
||||
default:
|
||||
assert(sa->sa_family == AF_INET);
|
||||
sz = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
uint16_t ddsrt_sockaddr_get_port(const struct sockaddr *const sa)
|
||||
{
|
||||
unsigned short port = 0;
|
||||
|
||||
switch(sa->sa_family) {
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6:
|
||||
port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
|
||||
break;
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
default:
|
||||
assert(sa->sa_family == AF_INET);
|
||||
port = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||||
break;
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_sockaddr_isunspecified(const struct sockaddr *__restrict sa)
|
||||
{
|
||||
assert(sa != NULL);
|
||||
|
||||
switch(sa->sa_family) {
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6*)sa)->sin6_addr);
|
||||
#endif
|
||||
case AF_INET:
|
||||
return (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_sockaddr_isloopback(const struct sockaddr *__restrict sa)
|
||||
{
|
||||
assert(sa != NULL);
|
||||
|
||||
switch (sa->sa_family) {
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_LOOPBACK(
|
||||
&((const struct sockaddr_in6 *)sa)->sin6_addr);
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
case AF_INET:
|
||||
return (((const struct sockaddr_in *)sa)->sin_addr.s_addr
|
||||
== htonl(INADDR_LOOPBACK));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_sockaddr_insamesubnet(
|
||||
const struct sockaddr *sa1,
|
||||
const struct sockaddr *sa2,
|
||||
const struct sockaddr *mask)
|
||||
{
|
||||
bool eq = false;
|
||||
|
||||
if (sa1->sa_family != sa2->sa_family ||
|
||||
sa1->sa_family != mask->sa_family)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (sa1->sa_family) {
|
||||
case AF_INET: {
|
||||
eq = ((((struct sockaddr_in *)sa1)->sin_addr.s_addr &
|
||||
((struct sockaddr_in *)mask)->sin_addr.s_addr)
|
||||
==
|
||||
(((struct sockaddr_in *)sa2)->sin_addr.s_addr &
|
||||
((struct sockaddr_in *)mask)->sin_addr.s_addr));
|
||||
} break;
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sin61, *sin62, *mask6;
|
||||
size_t i, n = sizeof(sin61->sin6_addr.s6_addr);
|
||||
sin61 = (struct sockaddr_in6 *)sa1;
|
||||
sin62 = (struct sockaddr_in6 *)sa2;
|
||||
mask6 = (struct sockaddr_in6 *)mask;
|
||||
eq = true;
|
||||
for (i = 0; eq && i < n; i++) {
|
||||
eq = ((sin61->sin6_addr.s6_addr[i] &
|
||||
mask6->sin6_addr.s6_addr[i])
|
||||
==
|
||||
(sin62->sin6_addr.s6_addr[i] &
|
||||
mask6->sin6_addr.s6_addr[i]));
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_sockaddrfromstr(int af, const char *str, void *sa)
|
||||
{
|
||||
assert(str != NULL);
|
||||
assert(sa != NULL);
|
||||
|
||||
switch (af) {
|
||||
case AF_INET: {
|
||||
struct in_addr buf;
|
||||
if (inet_pton(af, str, &buf) != 1) {
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
} else {
|
||||
memset(sa, 0, sizeof(struct sockaddr_in));
|
||||
((struct sockaddr_in *)sa)->sin_family = AF_INET;
|
||||
memcpy(&((struct sockaddr_in *)sa)->sin_addr, &buf, sizeof(buf));
|
||||
}
|
||||
} break;
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6: {
|
||||
struct in6_addr buf;
|
||||
if (inet_pton(af, str, &buf) != 1) {
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
} else {
|
||||
memset(sa, 0, sizeof(struct sockaddr_in6));
|
||||
((struct sockaddr_in6 *)sa)->sin6_family = AF_INET6;
|
||||
memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &buf, sizeof(buf));
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
default:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size)
|
||||
{
|
||||
const char *ptr;
|
||||
|
||||
assert(sa != NULL);
|
||||
assert(buf != NULL);
|
||||
|
||||
switch (((struct sockaddr *)sa)->sa_family) {
|
||||
case AF_INET:
|
||||
ptr = inet_ntop(
|
||||
AF_INET, &((struct sockaddr_in *)sa)->sin_addr, buf, (socklen_t)size);
|
||||
break;
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6:
|
||||
ptr = inet_ntop(
|
||||
AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, buf, (socklen_t)size);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
if (ptr == NULL) {
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
#if DDSRT_HAVE_DNS
|
||||
dds_retcode_t
|
||||
ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp)
|
||||
{
|
||||
int gai_err = 0;
|
||||
struct addrinfo hints, *res = NULL;
|
||||
ddsrt_hostent_t *hent = NULL;
|
||||
|
||||
assert(name != NULL);
|
||||
assert(hentp != NULL);
|
||||
|
||||
switch (af) {
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6:
|
||||
#endif
|
||||
case AF_INET:
|
||||
case AF_UNSPEC:
|
||||
break;
|
||||
default:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* Windows returns all registered addresses on the local computer if the
|
||||
"nodename" parameter is an empty string. *NIX return HOST_NOT_FOUND.
|
||||
Deny empty hostnames to keep behavior across platforms consistent. */
|
||||
if (strlen(name) == 0) {
|
||||
return DDS_RETCODE_HOST_NOT_FOUND;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = af;
|
||||
|
||||
gai_err = getaddrinfo(name, NULL, &hints, &res);
|
||||
/* gai_strerror cannot be used because Windows does not offer a thread-safe
|
||||
implementation and lwIP (there maybe others as well) does not offer an
|
||||
implementation at all.
|
||||
|
||||
NOTE: Error codes returned by getaddrinfo map directly onto Windows
|
||||
Socket error codes and WSAGetLastError can be used instead. */
|
||||
DDS_TRACE("getaddrinfo for %s returned %d\n", name, gai_err);
|
||||
switch (gai_err) {
|
||||
#if defined(EAI_AGAIN)
|
||||
case EAI_AGAIN:
|
||||
/* Name server returned a temporary failure indication. */
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
#endif
|
||||
case EAI_FAIL:
|
||||
/* Name server returned a permanent failure indication. */
|
||||
return DDS_RETCODE_ERROR;
|
||||
/* Windows defines EAI_NODATA to EAI_NONAME. */
|
||||
#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
|
||||
case EAI_NODATA:
|
||||
/* Host exists, but does not have any network addresses defined. */
|
||||
return DDS_RETCODE_NO_DATA;
|
||||
#endif
|
||||
#if defined(EAI_ADDRFAMILY)
|
||||
case EAI_ADDRFAMILY: /* Host has no addresses in requested family. */
|
||||
#endif
|
||||
#if defined(EAI_NOSECURENAME) /* Windows */
|
||||
case EAI_NOSECURENAME:
|
||||
#endif
|
||||
case EAI_NONAME:
|
||||
/* Host does not exist. */
|
||||
return DDS_RETCODE_HOST_NOT_FOUND;
|
||||
case EAI_MEMORY:
|
||||
/* Out of memory. */
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
#if defined(EAI_SYSTEM)
|
||||
case EAI_SYSTEM:
|
||||
/* Other system error. */
|
||||
return DDS_RETCODE_ERROR;
|
||||
#endif
|
||||
case EAI_BADFLAGS: /* Invalid flags in hints.ai_flags. */
|
||||
case EAI_FAMILY: /* Address family not supported. */
|
||||
case EAI_SERVICE: /* Service not available for socket type. */
|
||||
case EAI_SOCKTYPE: /* Socket type not supported. */
|
||||
case 0: {
|
||||
struct addrinfo *ai;
|
||||
size_t addrno, naddrs, size;
|
||||
|
||||
assert(gai_err == 0);
|
||||
assert(res != NULL);
|
||||
|
||||
naddrs = 0;
|
||||
for (ai = res; ai != NULL; ai = ai->ai_next) {
|
||||
naddrs++;
|
||||
}
|
||||
|
||||
size = sizeof(*hent) + (naddrs * sizeof(hent->addrs[0]));
|
||||
if ((hent = ddsrt_calloc_s(1, size)) != NULL) {
|
||||
hent->naddrs = naddrs;
|
||||
for (addrno = 0, ai = res;
|
||||
addrno < naddrs && ai != NULL;
|
||||
addrno++, ai = ai->ai_next)
|
||||
{
|
||||
memcpy(&hent->addrs[addrno], res->ai_addr, res->ai_addrlen);
|
||||
}
|
||||
} else {
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
} break;
|
||||
default:
|
||||
DDS_ERROR("getaddrinfo returned unkown error %d\n", gai_err);
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
*hentp = hent;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
#endif /* DDSRT_HAVE_DNS */
|
||||
82
src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h
Normal file
82
src/ddsrt/src/sockets/include/dds/ddsrt/sockets_priv.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_SOCKETS_PRIV_H
|
||||
#define DDSRT_SOCKETS_PRIV_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
typedef long ddsrt_tv_sec_t;
|
||||
typedef long ddsrt_tv_usec_t;
|
||||
#else
|
||||
typedef time_t ddsrt_tv_sec_t;
|
||||
typedef suseconds_t ddsrt_tv_usec_t;
|
||||
#endif
|
||||
|
||||
#define DDSRT_TIME_T_MAX \
|
||||
(DDSRT_MAX_INTEGER(ddsrt_tv_sec_t))
|
||||
|
||||
/**
|
||||
* @brief Convert a relative time to a timeval rounding up.
|
||||
*
|
||||
* @param[in] reltime Relative time to convert.
|
||||
* @param[out] tv struct timeval* where timeout is stored.
|
||||
*
|
||||
* @returns NULL if @reltime was @DDS_INFINITY, the value of @tv otherwise.
|
||||
*/
|
||||
inline struct timeval *
|
||||
ddsrt_duration_to_timeval_ceil(dds_duration_t reltime, struct timeval *tv)
|
||||
{
|
||||
assert(tv != NULL);
|
||||
|
||||
if (reltime == DDS_INFINITY) {
|
||||
tv->tv_sec = 0;
|
||||
tv->tv_usec = 0;
|
||||
return NULL;
|
||||
} else if (reltime > 0) {
|
||||
dds_duration_t max_nsecs;
|
||||
if (DDS_INFINITY > DDSRT_TIME_T_MAX) {
|
||||
assert(DDSRT_TIME_T_MAX == INT32_MAX);
|
||||
max_nsecs = INT32_MAX * DDS_NSECS_IN_SEC;
|
||||
} else {
|
||||
max_nsecs = DDSRT_TIME_T_MAX / DDS_NSECS_IN_SEC;
|
||||
}
|
||||
|
||||
if (reltime < (max_nsecs - DDS_NSECS_IN_USEC - 1)) {
|
||||
reltime += (DDS_NSECS_IN_USEC - 1);
|
||||
tv->tv_sec = (ddsrt_tv_sec_t)(reltime / DDS_NSECS_IN_SEC);
|
||||
tv->tv_usec = (ddsrt_tv_usec_t)((reltime % DDS_NSECS_IN_SEC) / DDS_NSECS_IN_USEC);
|
||||
} else {
|
||||
tv->tv_sec = DDSRT_TIME_T_MAX;
|
||||
tv->tv_usec = 999999;
|
||||
}
|
||||
} else {
|
||||
tv->tv_sec = 0;
|
||||
tv->tv_usec = 0;
|
||||
}
|
||||
|
||||
return tv;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_SOCKETS_PRIV_H */
|
||||
61
src/ddsrt/src/sockets/posix/gethostname.c
Normal file
61
src/ddsrt/src/sockets/posix/gethostname.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__VXWORKS__)
|
||||
#include <hostLib.h>
|
||||
#endif /* __VXWORKS__ */
|
||||
|
||||
#if !defined(HOST_NAME_MAX) && defined(_POSIX_HOST_NAME_MAX)
|
||||
# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
|
||||
#endif
|
||||
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_gethostname(
|
||||
char *name,
|
||||
size_t len)
|
||||
{
|
||||
char buf[HOST_NAME_MAX + 1 /* '\0' */];
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (gethostname(buf, HOST_NAME_MAX) == 0) {
|
||||
/* If truncation occurrs, no error is returned whether or not the buffer
|
||||
is null-terminated. */
|
||||
if (buf[HOST_NAME_MAX - 1] != '\0' ||
|
||||
ddsrt_strlcpy(name, buf, len) >= len)
|
||||
{
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
} else {
|
||||
switch (errno) {
|
||||
case EFAULT: /* Invalid address (cannot happen). */
|
||||
return DDS_RETCODE_ERROR;
|
||||
case EINVAL: /* Negative length (cannot happen). */
|
||||
return DDS_RETCODE_ERROR;
|
||||
case ENAMETOOLONG:
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
530
src/ddsrt/src/sockets/posix/socket.c
Normal file
530
src/ddsrt/src/sockets/posix/socket.c
Normal file
|
|
@ -0,0 +1,530 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__VXWORKS__)
|
||||
#include <vxWorks.h>
|
||||
#include <sockLib.h>
|
||||
#include <ioLib.h>
|
||||
#else
|
||||
#include <sys/fcntl.h>
|
||||
#endif /* __VXWORKS__ */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sockio.h>
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/sockets_priv.h"
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol)
|
||||
{
|
||||
ddsrt_socket_t sock;
|
||||
|
||||
assert(sockptr != NULL);
|
||||
|
||||
sock = socket(domain, type, protocol);
|
||||
if (sock != -1) {
|
||||
*sockptr = sock;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case EAFNOSUPPORT:
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case EMFILE:
|
||||
case ENFILE:
|
||||
case ENOBUFS:
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_close(
|
||||
ddsrt_socket_t sock)
|
||||
{
|
||||
if (close(sock) != -1)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case EINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_bind(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
if (bind(sock, addr, addrlen) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case EADDRINUSE:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case EBADF:
|
||||
case EINVAL:
|
||||
case ENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_listen(
|
||||
ddsrt_socket_t sock,
|
||||
int backlog)
|
||||
{
|
||||
if (listen(sock, backlog) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EADDRINUSE:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case EBADF:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ENOTSOCK:
|
||||
case EOPNOTSUPP:
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_connect(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
if (connect(sock, addr, addrlen) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
case EISCONN:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case EADDRINUSE:
|
||||
case EADDRNOTAVAIL:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case EAFNOSUPPORT:
|
||||
case EBADF:
|
||||
case ENOTSOCK:
|
||||
case EPROTOTYPE:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case EAGAIN:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case EALREADY:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case ECONNREFUSED:
|
||||
case ENETUNREACH:
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case EINPROGRESS:
|
||||
return DDS_RETCODE_IN_PROGRESS;
|
||||
case EINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case ETIMEDOUT:
|
||||
return DDS_RETCODE_TIMEOUT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_accept(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen,
|
||||
ddsrt_socket_t *connptr)
|
||||
{
|
||||
ddsrt_socket_t conn;
|
||||
|
||||
if ((conn = accept(sock, addr, addrlen)) != -1) {
|
||||
*connptr = conn;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case EBADF:
|
||||
case EFAULT:
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ECONNABORTED:
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case EINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case EMFILE:
|
||||
case ENFILE:
|
||||
case ENOBUFS:
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case ENOTSOCK:
|
||||
case EOPNOTSUPP:
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
case EPROTO:
|
||||
return DDS_RETCODE_ERROR;
|
||||
case EPERM:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getsockname(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
if (getsockname(sock, addr, addrlen) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
case EFAULT:
|
||||
case EINVAL:
|
||||
case ENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ENOBUFS:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
int32_t optname,
|
||||
void *optval,
|
||||
socklen_t *optlen)
|
||||
{
|
||||
if (getsockopt(sock, level, optname, optval, optlen) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
case EFAULT:
|
||||
case EINVAL:
|
||||
case ENOPROTOOPT:
|
||||
case ENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_setsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
int32_t optname,
|
||||
const void *optval,
|
||||
socklen_t optlen)
|
||||
{
|
||||
switch (optname) {
|
||||
case SO_SNDBUF:
|
||||
case SO_RCVBUF:
|
||||
/* optlen == 4 && optval == 0 does not work. */
|
||||
if (!(optlen == 4 && *((unsigned *)optval) == 0)) {
|
||||
break;
|
||||
}
|
||||
/* falls through */
|
||||
case SO_DONTROUTE:
|
||||
/* SO_DONTROUTE causes problems on macOS (e.g. no multicasting). */
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, level, optname, optval, optlen) == -1) {
|
||||
goto err_setsockopt;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
if (level == SOL_SOCKET && optname == SO_REUSEADDR &&
|
||||
setsockopt(sock, level, SO_REUSEPORT, optval, optlen) == -1)
|
||||
{
|
||||
goto err_setsockopt;
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
err_setsockopt:
|
||||
switch (errno) {
|
||||
case EBADF:
|
||||
case EINVAL:
|
||||
case ENOPROTOOPT:
|
||||
case ENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_setsocknonblocking(
|
||||
ddsrt_socket_t sock,
|
||||
bool nonblock)
|
||||
{
|
||||
int flags;
|
||||
|
||||
flags = fcntl(sock, F_GETFL, 0);
|
||||
if (flags == -1) {
|
||||
goto err_fcntl;
|
||||
} else {
|
||||
if (nonblock) {
|
||||
flags |= O_NONBLOCK;
|
||||
} else {
|
||||
flags &= ~O_NONBLOCK;
|
||||
}
|
||||
if (fcntl(sock, F_SETFL, flags) == -1) {
|
||||
goto err_fcntl;
|
||||
}
|
||||
}
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
err_fcntl:
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
case EAGAIN:
|
||||
case EPERM:
|
||||
return DDS_RETCODE_ERROR;
|
||||
case EBADF:
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
static inline dds_retcode_t
|
||||
recv_error_to_retcode(int errnum)
|
||||
{
|
||||
switch (errnum) {
|
||||
case EAGAIN:
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case EBADF:
|
||||
case EFAULT:
|
||||
case EINVAL:
|
||||
case ENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ECONNREFUSED:
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case EINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case ENOTCONN:
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_recv(
|
||||
ddsrt_socket_t sock,
|
||||
void *buf,
|
||||
size_t len,
|
||||
int flags,
|
||||
ssize_t *rcvd)
|
||||
{
|
||||
ssize_t n;
|
||||
|
||||
if ((n = recv(sock, buf, len, flags)) != -1) {
|
||||
assert(n >= 0);
|
||||
*rcvd = n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
return recv_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_recvmsg(
|
||||
ddsrt_socket_t sock,
|
||||
ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *rcvd)
|
||||
{
|
||||
ssize_t n;
|
||||
|
||||
if ((n = recvmsg(sock, msg, flags)) != -1) {
|
||||
assert(n >= 0);
|
||||
*rcvd = n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
return recv_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
static inline dds_retcode_t
|
||||
send_error_to_retcode(int errnum)
|
||||
{
|
||||
switch (errnum) {
|
||||
case EACCES:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case EAGAIN:
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
case EALREADY:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case EBADF:
|
||||
case EFAULT:
|
||||
case EINVAL:
|
||||
case ENOTSOCK:
|
||||
case EOPNOTSUPP:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ECONNRESET:
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case EDESTADDRREQ:
|
||||
case EISCONN:
|
||||
case ENOTCONN:
|
||||
case EPIPE:
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
case EINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case EMSGSIZE:
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
case ENOBUFS:
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_send(
|
||||
ddsrt_socket_t sock,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
int flags,
|
||||
ssize_t *sent)
|
||||
{
|
||||
ssize_t n;
|
||||
|
||||
if ((n = send(sock, buf, len, flags)) != -1) {
|
||||
assert(n >= 0);
|
||||
*sent = n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
return send_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_sendmsg(
|
||||
ddsrt_socket_t sock,
|
||||
const ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *sent)
|
||||
{
|
||||
ssize_t n;
|
||||
|
||||
if ((n = sendmsg(sock, msg, flags)) != -1) {
|
||||
assert(n >= 0);
|
||||
*sent = n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
return send_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_select(
|
||||
int32_t nfds,
|
||||
fd_set *readfds,
|
||||
fd_set *writefds,
|
||||
fd_set *errorfds,
|
||||
dds_duration_t reltime,
|
||||
int32_t *ready)
|
||||
{
|
||||
int n;
|
||||
struct timeval tv, *tvp = NULL;
|
||||
|
||||
tvp = ddsrt_duration_to_timeval_ceil(reltime, &tv);
|
||||
if ((n = select(nfds, readfds, writefds, errorfds, tvp)) != -1) {
|
||||
*ready = n;
|
||||
return (n == 0 ? DDS_RETCODE_TIMEOUT : DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
case EINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case EBADF:
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ENOMEM:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
42
src/ddsrt/src/sockets/windows/gethostname.c
Normal file
42
src/ddsrt/src/sockets/windows/gethostname.c
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
|
||||
ddsrt_gethostname(
|
||||
char *name,
|
||||
size_t len)
|
||||
{
|
||||
assert(name != NULL);
|
||||
assert(len <= INT_MAX);
|
||||
|
||||
if (len == 0) {
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
} else if (gethostname(name, (int)len) == 0) {
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
switch(WSAGetLastError()) {
|
||||
case WSAEFAULT:
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_IN_PROGRESS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
680
src/ddsrt/src/sockets/windows/socket.c
Normal file
680
src/ddsrt/src/sockets/windows/socket.c
Normal file
|
|
@ -0,0 +1,680 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <winerror.h>
|
||||
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/sockets_priv.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
#ifdef ddsrt_select
|
||||
#undef ddsrt_select /* See sockets.h for details. */
|
||||
#endif
|
||||
|
||||
void
|
||||
ddsrt_winsock_init(void)
|
||||
{
|
||||
int err;
|
||||
WSADATA wsa_data;
|
||||
|
||||
err = WSAStartup(MAKEWORD(2,0), &wsa_data);
|
||||
if (err != 0) {
|
||||
DDS_FATAL("WSAStartup(2.0, ...) failed with %d\n", err);
|
||||
}
|
||||
|
||||
/* Confirm Windows Socket version 2.0 is supported. If versions greater
|
||||
than 2.0 in addition to 2.0 are supported, 2.0 will still be returned as
|
||||
that is the requested version. */
|
||||
if (LOBYTE(wsa_data.wVersion) != 2 ||
|
||||
HIBYTE(wsa_data.wVersion) != 0)
|
||||
{
|
||||
WSACleanup();
|
||||
DDS_FATAL("WSAStartup(2.0, ...) failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_winsock_fini(void)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol)
|
||||
{
|
||||
int err;
|
||||
dds_retcode_t ret = DDS_RETCODE_OK;
|
||||
ddsrt_socket_t sock = DDSRT_INVALID_SOCKET;
|
||||
|
||||
assert(sockptr != NULL);
|
||||
|
||||
sock = socket(domain, type, protocol);
|
||||
if (sock != INVALID_SOCKET) {
|
||||
*sockptr = sock;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
assert(err != WSAEINVALIDPROCTABLE);
|
||||
assert(err != WSAEINVALIDPROVIDER);
|
||||
assert(err != WSAEPROVIDERFAILEDINIT);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEINVAL:
|
||||
case WSAEAFNOSUPPORT:
|
||||
case WSAEPROTONOSUPPORT:
|
||||
case WSAEPROTOTYPE:
|
||||
case WSAESOCKTNOSUPPORT:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAEMFILE:
|
||||
case WSAENOBUFS:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_close(ddsrt_socket_t sock)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (closesocket(sock) != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINPROGRESS:
|
||||
case WSAEWOULDBLOCK:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAEINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_accept(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen,
|
||||
ddsrt_socket_t *connptr)
|
||||
{
|
||||
int err;
|
||||
ddsrt_socket_t conn;
|
||||
|
||||
if ((conn = accept(sock, addr, addrlen)) != INVALID_SOCKET) {
|
||||
*connptr = conn;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAECONNRESET:
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case WSAEFAULT:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case WSAEINVAL:
|
||||
case WSAENOTSOCK:
|
||||
case WSAEOPNOTSUPP:
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_IN_PROGRESS;
|
||||
case WSAEMFILE:
|
||||
case WSAENOBUFS:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case WSAEWOULDBLOCK:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_bind(ddsrt_socket_t sock, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (bind(sock, addr, addrlen) != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEACCES:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case WSAEADDRINUSE:
|
||||
case WSAEADDRNOTAVAIL:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case WSAEFAULT:
|
||||
case WSAEINVAL:
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAENOBUFS:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_listen(
|
||||
ddsrt_socket_t sock,
|
||||
int backlog)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (listen(sock, backlog) != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEADDRINUSE:
|
||||
case WSAEINVAL:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAEMFILE:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case WSAENOTSOCK:
|
||||
case WSAEOPNOTSUPP:
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_connect(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (connect(sock, addr, addrlen) != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEADDRINUSE:
|
||||
case WSAEADDRNOTAVAIL:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case WSAEINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case WSAEINPROGRESS:
|
||||
case WSAEALREADY:
|
||||
case WSAEWOULDBLOCK:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAEAFNOSUPPORT:
|
||||
case WSAEFAULT:
|
||||
case WSAEINVAL:
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAECONNREFUSED:
|
||||
case WSAENETUNREACH:
|
||||
case WSAEHOSTUNREACH:
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case WSAEISCONN:
|
||||
case WSAEACCES:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case WSAENOBUFS:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case WSAETIMEDOUT:
|
||||
return DDS_RETCODE_TIMEOUT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getsockname(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(sock != INVALID_SOCKET);
|
||||
assert(addr != NULL);
|
||||
|
||||
if (getsockname(sock, addr, addrlen) != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEFAULT: /* addrlen parameter is too small. */
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINVAL:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
int32_t optname,
|
||||
void *optval,
|
||||
socklen_t *optlen)
|
||||
{
|
||||
int err, ret;
|
||||
|
||||
if (level == IPPROTO_IP && (optname == IP_MULTICAST_TTL ||
|
||||
optname == IP_MULTICAST_LOOP))
|
||||
{
|
||||
/* IP_MULTICAST_TTL and IP_MULTICAST_LOOP take a DWORD* rather than a
|
||||
char* on Windows. */
|
||||
int dwoptlen = sizeof(DWORD);
|
||||
DWORD dwoptval = *((unsigned char *)optval);
|
||||
ret = getsockopt(sock, level, optname, (char *)&dwoptval, &dwoptlen);
|
||||
if (ret != SOCKET_ERROR) {
|
||||
assert(dwoptlen == sizeof(DWORD));
|
||||
*((unsigned char *)optval) = (unsigned char)dwoptval;
|
||||
*optlen = sizeof( unsigned char );
|
||||
}
|
||||
} else {
|
||||
ret = getsockopt(sock, level, optname, optval, (int *)optlen);
|
||||
}
|
||||
|
||||
if (ret != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEFAULT:
|
||||
case WSAEINVAL:
|
||||
case WSAENOPROTOOPT:
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_setsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
int32_t optname,
|
||||
const void *optval,
|
||||
socklen_t optlen)
|
||||
{
|
||||
int err, ret;
|
||||
DWORD dwoptval;
|
||||
|
||||
if (level == IPPROTO_IP && (optname == IP_MULTICAST_TTL ||
|
||||
optname == IP_MULTICAST_LOOP))
|
||||
{
|
||||
/* On win32 IP_MULTICAST_TTL and IP_MULTICAST_LOOP take DWORD * param
|
||||
rather than char * */
|
||||
dwoptval = *((unsigned char *)optval);
|
||||
optval = &dwoptval;
|
||||
optlen = sizeof(DWORD);
|
||||
ret = setsockopt(sock, level, optname, optval, (int)optlen);
|
||||
} else {
|
||||
ret = setsockopt(sock, level, optname, optval, (int)optlen);
|
||||
}
|
||||
|
||||
if (ret != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEFAULT:
|
||||
case WSAEINVAL:
|
||||
case WSAENOPROTOOPT:
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_IN_PROGRESS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_setsocknonblocking(
|
||||
ddsrt_socket_t sock,
|
||||
bool nonblock)
|
||||
{
|
||||
int err;
|
||||
u_long mode;
|
||||
|
||||
/* If mode = 0, blocking is enabled,
|
||||
* if mode != 0, non-blocking is enabled. */
|
||||
mode = nonblock ? 1 : 0;
|
||||
|
||||
if (ioctlsocket(sock, FIONBIO, &mode) != SOCKET_ERROR)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
static dds_retcode_t recv_error_to_retcode(int errnum)
|
||||
{
|
||||
assert(errnum != WSANOTINITIALISED);
|
||||
switch (errnum) {
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEFAULT:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAENOTCONN:
|
||||
case WSAEINVAL:
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case WSAEINTR:
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case WSAEINPROGRESS:
|
||||
case WSAEWOULDBLOCK:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAENETRESET:
|
||||
case WSAECONNABORTED:
|
||||
case WSAECONNRESET:
|
||||
case WSAETIMEDOUT:
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case WSAEISCONN:
|
||||
case WSAENOTSOCK:
|
||||
case WSAEOPNOTSUPP:
|
||||
case WSAESHUTDOWN:
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
case WSAEMSGSIZE:
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_recv(
|
||||
ddsrt_socket_t sock,
|
||||
void *buf,
|
||||
size_t len,
|
||||
int flags,
|
||||
ssize_t *rcvd)
|
||||
{
|
||||
ssize_t n;
|
||||
|
||||
assert(len < INT_MAX);
|
||||
|
||||
if ((n = recv(sock, (char *)buf, (int)len, flags)) != SOCKET_ERROR) {
|
||||
*rcvd = n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
return recv_error_to_retcode(WSAGetLastError());
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_recvmsg(
|
||||
ddsrt_socket_t sock,
|
||||
ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *rcvd)
|
||||
{
|
||||
int err, n;
|
||||
|
||||
assert(msg != NULL);
|
||||
assert(msg->msg_iovlen == 1);
|
||||
assert(msg->msg_controllen == 0);
|
||||
|
||||
msg->msg_flags = 0;
|
||||
n = recvfrom(
|
||||
sock,
|
||||
msg->msg_iov[0].iov_base,
|
||||
msg->msg_iov[0].iov_len,
|
||||
flags,
|
||||
msg->msg_name,
|
||||
&msg->msg_namelen);
|
||||
|
||||
if (n != -1) {
|
||||
*rcvd = n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
err = WSAGetLastError();
|
||||
if (err == WSAEMSGSIZE) {
|
||||
/* Windows returns an error for too-large messages, UNIX expects the
|
||||
original size and the MSG_TRUNC flag. MSDN states it is truncated, which
|
||||
presumably means it returned as much of the message as it could. Return
|
||||
that the message was one byte larger than the available space and set
|
||||
MSG_TRUNC. */
|
||||
*rcvd = msg->msg_iov[0].iov_len + 1;
|
||||
msg->msg_flags |= MSG_TRUNC;
|
||||
}
|
||||
|
||||
return recv_error_to_retcode(err);
|
||||
}
|
||||
|
||||
static dds_retcode_t
|
||||
send_error_to_retcode(int errnum)
|
||||
{
|
||||
assert(errnum != WSANOTINITIALISED);
|
||||
switch (errnum) {
|
||||
case WSAENETDOWN: /* Network subsystem failed. */
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEACCES: /* Remote address is a broadcast address. */
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case WSAEINTR: /* Blocking sockets call was cancelled. */
|
||||
return DDS_RETCODE_INTERRUPTED;
|
||||
case WSAEINPROGRESS: /* Blocking sockets call in progress. */
|
||||
case WSA_IO_PENDING: /* Operation pending (WSASentTo). */
|
||||
return DDS_RETCODE_IN_PROGRESS;
|
||||
case WSAEFAULT: /* A parameter was not part of the user address space or
|
||||
destination address was to small (WSASendTo). */
|
||||
case WSAEADDRNOTAVAIL: /* Remote address is not valid (WSASentTo). */
|
||||
case WSAEAFNOSUPPORT: /* Remote address is in wrong family (WSASentTo). */
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAENETRESET: /* Time to live expired. */
|
||||
case WSAEHOSTUNREACH: /* Host is unreachable. */
|
||||
case WSAECONNABORTED: /* Time-out or other failure (send). */
|
||||
case WSAETIMEDOUT: /* Network or remote host failure (send). */
|
||||
case WSAENETUNREACH: /* Network is unreachable. (WSASentTo). */
|
||||
case WSA_OPERATION_ABORTED: /* Socket was closed (WSASentTo). */
|
||||
return DDS_RETCODE_NO_CONNECTION;
|
||||
case WSAENOBUFS:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case WSAENOTCONN: /* Socket is not connected. */
|
||||
case WSAEINVAL: /* Socket has not been bound. */
|
||||
return DDS_RETCODE_PRECONDITION_NOT_MET;
|
||||
case WSAENOTSOCK: /* Descriptor is not a socket. */
|
||||
case WSAEOPNOTSUPP: /* Operation not supported (send). */
|
||||
case WSAESHUTDOWN: /* Socket shut down. */
|
||||
return DDS_RETCODE_ILLEGAL_OPERATION;
|
||||
case WSAEWOULDBLOCK: /* Socket is nonblocking and call would block. */
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
case WSAEMSGSIZE: /* Message is larger than transport maximum. */
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_send(
|
||||
ddsrt_socket_t sock,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
int flags,
|
||||
ssize_t *sent)
|
||||
{
|
||||
int n;
|
||||
|
||||
assert(buf != NULL);
|
||||
assert(len <= INT_MAX);
|
||||
assert(sent != NULL);
|
||||
|
||||
if ((n = send(sock, buf, (int)len, flags)) != SOCKET_ERROR) {
|
||||
*sent = n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
return send_error_to_retcode(WSAGetLastError());
|
||||
}
|
||||
|
||||
/* Compile time check to ensure iovec matches WSABUF. */
|
||||
struct iovec_matches_WSABUF {
|
||||
char sizeof_matches[sizeof(ddsrt_iovec_t) == sizeof(WSABUF) ? 1 : -1];
|
||||
char base_off_matches[offsetof(ddsrt_iovec_t, iov_base) == offsetof(WSABUF, buf) ? 1 : -1];
|
||||
char base_size_matches[sizeof(((ddsrt_iovec_t *)8)->iov_base) == sizeof(((WSABUF *)8)->buf) ? 1 : -1];
|
||||
char len_off_matches[offsetof(ddsrt_iovec_t, iov_len) == offsetof(WSABUF, len) ? 1 : -1];
|
||||
char len_size_matches[sizeof(((ddsrt_iovec_t *)8)->iov_len) == sizeof(((WSABUF *)8)->len) ? 1 : -1];
|
||||
};
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_sendmsg(
|
||||
ddsrt_socket_t sock,
|
||||
const ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *sent)
|
||||
{
|
||||
int ret;
|
||||
DWORD n;
|
||||
|
||||
assert(msg != NULL);
|
||||
assert(msg->msg_controllen == 0);
|
||||
|
||||
ret = WSASendTo(
|
||||
sock,
|
||||
(WSABUF *)msg->msg_iov,
|
||||
(DWORD)msg->msg_iovlen,
|
||||
&n,
|
||||
flags,
|
||||
(SOCKADDR *)msg->msg_name,
|
||||
msg->msg_namelen,
|
||||
NULL,
|
||||
NULL);
|
||||
if (ret != SOCKET_ERROR) {
|
||||
*sent = (ssize_t)n;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
return send_error_to_retcode(WSAGetLastError());
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_select(
|
||||
int32_t nfds,
|
||||
fd_set *readfds,
|
||||
fd_set *writefds,
|
||||
fd_set *errorfds,
|
||||
dds_duration_t reltime,
|
||||
int32_t *ready)
|
||||
{
|
||||
int err;
|
||||
int32_t n;
|
||||
struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }, *tvp = NULL;
|
||||
|
||||
(void)nfds;
|
||||
|
||||
tvp = ddsrt_duration_to_timeval_ceil(reltime, &tv);
|
||||
if ((n = select(-1, readfds, writefds, errorfds, tvp)) != SOCKET_ERROR) {
|
||||
*ready = n;
|
||||
return (n == 0 ? DDS_RETCODE_TIMEOUT : DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
err = WSAGetLastError();
|
||||
assert(err != WSANOTINITIALISED);
|
||||
switch (err) {
|
||||
case WSAEFAULT:
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
case WSAENETDOWN:
|
||||
return DDS_RETCODE_NO_NETWORK;
|
||||
case WSAEINVAL:
|
||||
case WSAENOTSOCK:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case WSAEINPROGRESS:
|
||||
return DDS_RETCODE_TRY_AGAIN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
180
src/ddsrt/src/string.c
Normal file
180
src/ddsrt/src/string.c
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
#define _DLIB_ADD_EXTRA_SYMBOLS /* Export strtok_r. */
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
int
|
||||
ddsrt_strcasecmp(
|
||||
const char *s1,
|
||||
const char *s2)
|
||||
{
|
||||
int cr;
|
||||
|
||||
while (*s1 && *s2) {
|
||||
cr = tolower((unsigned char)*s1) - tolower((unsigned char)*s2);
|
||||
if (cr) {
|
||||
return cr;
|
||||
}
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
cr = tolower((unsigned char)*s1) - tolower((unsigned char)*s2);
|
||||
return cr;
|
||||
}
|
||||
|
||||
int
|
||||
ddsrt_strncasecmp(
|
||||
const char *s1,
|
||||
const char *s2,
|
||||
size_t n)
|
||||
{
|
||||
int cr = 0;
|
||||
|
||||
assert(s1 != NULL);
|
||||
assert(s2 != NULL);
|
||||
|
||||
while (*s1 && *s2 && n) {
|
||||
cr = tolower((unsigned char)*s1) - tolower((unsigned char)*s2);
|
||||
if (cr) {
|
||||
return cr;
|
||||
}
|
||||
s1++;
|
||||
s2++;
|
||||
n--;
|
||||
}
|
||||
if (n) {
|
||||
cr = tolower((unsigned char)*s1) - tolower((unsigned char)*s2);
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
char *
|
||||
ddsrt_strtok_r(
|
||||
char *str,
|
||||
const char *delim,
|
||||
char **saveptr)
|
||||
{
|
||||
#if _WIN32
|
||||
return strtok_s(str, delim, saveptr);
|
||||
#else
|
||||
return strtok_r(str, delim, saveptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
ddsrt_strsep(char **str, const char *sep)
|
||||
{
|
||||
char *ret;
|
||||
if (**str == '\0')
|
||||
return 0;
|
||||
ret = *str;
|
||||
while (**str && strchr (sep, **str) == 0)
|
||||
(*str)++;
|
||||
if (**str != '\0')
|
||||
{
|
||||
**str = '\0';
|
||||
(*str)++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ddsrt_strlcpy(
|
||||
char * __restrict dest,
|
||||
const char * __restrict src,
|
||||
size_t size)
|
||||
{
|
||||
size_t srclen = 0;
|
||||
|
||||
assert(dest != NULL);
|
||||
assert(src != NULL);
|
||||
|
||||
/* strlcpy must return the number of bytes that (would) have been written,
|
||||
i.e. the length of src. */
|
||||
srclen = strlen(src);
|
||||
if (size > 0) {
|
||||
size_t len = srclen;
|
||||
if (size <= srclen) {
|
||||
len = size - 1;
|
||||
}
|
||||
memcpy(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
}
|
||||
|
||||
return srclen;
|
||||
}
|
||||
|
||||
/* NOTE: ddsrt_strlcat does not forward to strlcat too avoid a bug in the macOS
|
||||
implementation where it does not return the right result if dest
|
||||
contains more characters than the size specified if size is either
|
||||
0 or 1. */
|
||||
size_t
|
||||
ddsrt_strlcat(
|
||||
char * __restrict dest,
|
||||
const char * __restrict src,
|
||||
size_t size)
|
||||
{
|
||||
size_t destlen, srclen;
|
||||
|
||||
assert(dest != NULL);
|
||||
assert(src != NULL);
|
||||
|
||||
/* strlcat must return the number of bytes that (would) have been written,
|
||||
i.e. the length of dest plus the length of src. */
|
||||
destlen = strlen(dest);
|
||||
srclen = strlen(src);
|
||||
if (SIZE_MAX == destlen) {
|
||||
srclen = 0;
|
||||
} else if ((SIZE_MAX - destlen) <= srclen) {
|
||||
srclen = (SIZE_MAX - destlen) - 1;
|
||||
}
|
||||
if (size > 0 && --size > destlen) {
|
||||
size_t len = srclen;
|
||||
size -= destlen;
|
||||
if (size <= srclen) {
|
||||
len = size;
|
||||
}
|
||||
memcpy(dest + destlen, src, len);
|
||||
dest[destlen + len] = '\0';
|
||||
}
|
||||
|
||||
return destlen + srclen;
|
||||
}
|
||||
|
||||
void *
|
||||
ddsrt_memdup(const void *src, size_t n)
|
||||
{
|
||||
void *dest = NULL;
|
||||
|
||||
if (n != 0 && (dest = ddsrt_malloc_s(n)) != NULL) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *
|
||||
ddsrt_strdup(
|
||||
const char *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
||||
return ddsrt_memdup(str, strlen(str) + 1);
|
||||
}
|
||||
43
src/ddsrt/src/string/posix/strerror.c
Normal file
43
src/ddsrt/src/string/posix/strerror.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
/* Make sure we get the XSI compliant version of strerror_r */
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
#undef _GNU_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_strerror_r(int errnum, char *buf, size_t buflen)
|
||||
{
|
||||
assert(buf != NULL);
|
||||
assert(buflen > 0);
|
||||
|
||||
switch (strerror_r(errnum, buf, buflen)) {
|
||||
case 0: /* Success */
|
||||
buf[buflen - 1] = '\0'; /* Always null-terminate, just to be safe. */
|
||||
return DDS_RETCODE_OK;
|
||||
case EINVAL:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
case ERANGE:
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
69
src/ddsrt/src/string/vxworks/strerror.c
Normal file
69
src/ddsrt/src/string/vxworks/strerror.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#ifdef _WRS_KERNEL
|
||||
|
||||
extern char *strerrorIf(int errcode);
|
||||
|
||||
/* VxWorks has a non-compliant strerror_r in kernel mode which only takes a
|
||||
buffer and an error number. Providing a buffer smaller than NAME_MAX + 1
|
||||
(256) may result in a buffer overflow. See target/src/libc/strerror.c for
|
||||
details. NAME_MAX is defined in limits.h. */
|
||||
|
||||
int
|
||||
ddsrt_strerror_r(int errnum, char *buf, size_t buflen)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
assert(buf != NULL);
|
||||
assert(buflen > 0);
|
||||
|
||||
if (buflen < (NAME_MAX + 1))
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
if (strerrorIf(errnum) == NULL)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
(void)strerror_r(errnum, buf);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
ddsrt_strerror_r(int errnum, char *buf, size_t buflen)
|
||||
{
|
||||
int err;
|
||||
const char *str;
|
||||
|
||||
assert(buf != NULL);
|
||||
assert(buflen > 0);
|
||||
|
||||
/* VxWorks's strerror_r always returns 0 (zero), so the only way to decide
|
||||
if the error was truncated is to check if the last position in the buffer
|
||||
is overwritten by strerror_r. */
|
||||
err = 0;
|
||||
buf[buflen - 1] = 'x';
|
||||
(void)strerror_r(errnum, buf, buflen);
|
||||
if (buf[buflen - 1] != 'x')
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
|
||||
buf[buflen - 1] = '\0'; /* Always null terminate, just to be safe. */
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
#endif /* _WRS_KERNEL */
|
||||
71
src/ddsrt/src/string/windows/strerror.c
Normal file
71
src/ddsrt/src/string/windows/strerror.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include "dds/ddsrt/types.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
/* WSAGetLastError, GetLastError and errno
|
||||
|
||||
Windows supports errno (The Microsoft c Run-Time Library for Windows CE
|
||||
does so since version 15 (Visual Studio 2008)). Error codes set by the
|
||||
Windows Sockets implementation, however, are NOT made available via the
|
||||
errno variable.
|
||||
|
||||
WSAGetLastError used to be the thread-safe version of GetLastError, but
|
||||
nowadays is just an an alias for GetLastError as intended by Microsoft:
|
||||
http://www.sockets.com/winsock.htm#Deviation_ErrorCodes
|
||||
|
||||
There is no relationship between GetLastError and errno.
|
||||
GetLastError returns the last error that occurred in a Windows API function
|
||||
(for the current thread). errno contains the last error that occurred in the C
|
||||
runtime library. Normally if a WinAPI call fails, e.g. CreateFile, GetLastError
|
||||
should be used to retrieve the error. If a C runtime library function fails,
|
||||
e.g. fopen, errno contains the error number. */
|
||||
|
||||
int
|
||||
ddsrt_strerror_r(
|
||||
int errnum,
|
||||
char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
int orig_err;
|
||||
DWORD cnt;
|
||||
|
||||
assert(buf != NULL);
|
||||
assert(buflen > 0);
|
||||
|
||||
orig_err = GetLastError();
|
||||
cnt = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||
NULL,
|
||||
errnum,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)buf,
|
||||
(DWORD)buflen,
|
||||
NULL);
|
||||
|
||||
if (cnt == 0) {
|
||||
if (GetLastError() == ERROR_MORE_DATA) {
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
} else {
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
/* ddsrt_strerror_r should not modify errno itself. */
|
||||
SetLastError(orig_err);
|
||||
buf[buflen - 1] = '\0'; /* Always null-terminate, just to be safe. */
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
208
src/ddsrt/src/strtod.c
Normal file
208
src/ddsrt/src/strtod.c
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/io.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/strtod.h"
|
||||
|
||||
/*
|
||||
* Determine the maximum size that a string should have to be
|
||||
* able to contain a double.
|
||||
* See the following site for the calculation explanation:
|
||||
* http://stackoverflow.com/questions/1701055/what-is-the-maximum-length-in-chars-needed-to-represent-any-double-value
|
||||
*/
|
||||
#include <float.h>
|
||||
#define DOUBLE_STRING_MAX_LENGTH (3 + DBL_MANT_DIG - DBL_MIN_EXP)
|
||||
|
||||
/*
|
||||
* VALID_DOUBLE_CHAR(c) is used to determine if the given char
|
||||
* can be valid when it appears in a string that should represent
|
||||
* a double.
|
||||
* It is used to detect the end of a double string representation.
|
||||
* Because it doesn't consider context, it is possible that more
|
||||
* characters are detected after the double (fi. when a few white
|
||||
* spaces tail the double). This isn't that bad, because the call
|
||||
* to strtod itself will handle these extra characters properly.
|
||||
*/
|
||||
#define VALID_DOUBLE_CHAR(c) ( (isspace((unsigned char)(c))) || /* (leading) whitespaces */ \
|
||||
(isxdigit((unsigned char)(c))) || /* (hexa)decimal digits */ \
|
||||
((c) == '.') || /* ospl LC_NUMERIC */ \
|
||||
((c) == os_lcNumericGet()) || /* locale LC_NUMERIC */ \
|
||||
((c) == '+') || ((c) == '-') || /* signs */ \
|
||||
((c) == 'x') || ((c) == 'X') || /* hexadecimal indication */ \
|
||||
((c) == 'e') || ((c) == 'E') || /* exponent chars */ \
|
||||
((c) == 'p') || ((c) == 'P') || /* binary exponent chars */ \
|
||||
((c) == 'a') || ((c) == 'A') || /* char for NaN */ \
|
||||
((c) == 'n') || ((c) == 'N') || /* char for NaN & INFINITY */ \
|
||||
((c) == 'i') || ((c) == 'I') || /* char for INFINITY */ \
|
||||
((c) == 'f') || ((c) == 'F') || /* char for INFINITY */ \
|
||||
((c) == 't') || ((c) == 'T') || /* char for INFINITY */ \
|
||||
((c) == 'y') || ((c) == 'Y')) /* char for INFINITY */
|
||||
|
||||
|
||||
|
||||
/** \brief Detect and return the LC_NUMERIC char of the locale.
|
||||
*/
|
||||
static char
|
||||
os_lcNumericGet(void)
|
||||
{
|
||||
static char lcNumeric = ' ';
|
||||
|
||||
/* Detect lcNumeric only once. */
|
||||
if (lcNumeric == ' ') {
|
||||
/* There could be multiple threads here, but it is still save and works.
|
||||
* Only side effect is that possibly multiple os_reports are traced. */
|
||||
char num[] = { '\0', '\0', '\0', '\0' };
|
||||
(void) snprintf(num, 4, "%3.1f", 2.2);
|
||||
lcNumeric = num [1];
|
||||
if (lcNumeric != '.') {
|
||||
DDS_WARNING("Locale with LC_NUMERIC \'%c\' detected, which is not '.'. "
|
||||
"This can decrease performance.", lcNumeric);
|
||||
}
|
||||
}
|
||||
|
||||
return lcNumeric;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Replace lcNumeric char with '.' in floating point string when locale dependent
|
||||
* functions use a non '.' LC_NUMERIC, while we want locale indepenent '.'.
|
||||
*/
|
||||
static void
|
||||
os_lcNumericReplace(char *str) {
|
||||
/* We only need to replace when standard functions
|
||||
* did not put a '.' in the result string. */
|
||||
char lcNumeric = os_lcNumericGet();
|
||||
if (lcNumeric != '.') {
|
||||
str = strchr(str, lcNumeric);
|
||||
if (str != NULL) {
|
||||
*str = '.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_strtod(const char *nptr, char **endptr, double *dblptr)
|
||||
{
|
||||
double dbl;
|
||||
int orig_errno;
|
||||
dds_retcode_t ret = DDS_RETCODE_OK;
|
||||
|
||||
assert(nptr != NULL);
|
||||
assert(dblptr != NULL);
|
||||
|
||||
orig_errno = errno;
|
||||
errno = 0;
|
||||
|
||||
if (os_lcNumericGet() == '.') {
|
||||
/* The current locale uses '.', so strtod can be used as is. */
|
||||
dbl = strtod(nptr, endptr);
|
||||
} else {
|
||||
/* The current locale uses ',', so we can not use the standard functions as
|
||||
is, but have to do extra work because ospl uses "x.x" doubles (notice
|
||||
the dot). Just copy the string and replace the LC_NUMERIC. */
|
||||
char nptrCopy[DOUBLE_STRING_MAX_LENGTH];
|
||||
char *nptrCopyIdx;
|
||||
char *nptrCopyEnd;
|
||||
char *nptrIdx;
|
||||
|
||||
/* It is possible that the given nptr just starts with a double
|
||||
representation but continues with other data. To be able to copy not too
|
||||
much and not too little, we have to scan across nptr until we detect the
|
||||
doubles' end. */
|
||||
nptrIdx = (char*)nptr;
|
||||
nptrCopyIdx = nptrCopy;
|
||||
nptrCopyEnd = nptrCopyIdx + DOUBLE_STRING_MAX_LENGTH - 1;
|
||||
while (VALID_DOUBLE_CHAR(*nptrIdx) && (nptrCopyIdx < nptrCopyEnd)) {
|
||||
if (*nptrIdx == '.') {
|
||||
/* Replace '.' with locale LC_NUMERIC to get strtod to work. */
|
||||
*nptrCopyIdx = os_lcNumericGet();
|
||||
} else {
|
||||
*nptrCopyIdx = *nptrIdx;
|
||||
}
|
||||
nptrIdx++;
|
||||
nptrCopyIdx++;
|
||||
}
|
||||
*nptrCopyIdx = '\0';
|
||||
|
||||
/* Now that we have a copy with the proper locale LC_NUMERIC, we can use
|
||||
strtod() for the conversion. */
|
||||
dbl = strtod(nptrCopy, &nptrCopyEnd);
|
||||
|
||||
/* Calculate the proper end char when needed. */
|
||||
if (endptr != NULL) {
|
||||
*endptr = (char*)nptr + (nptrCopyEnd - nptrCopy);
|
||||
}
|
||||
}
|
||||
|
||||
if ((dbl == HUGE_VALF || dbl == HUGE_VALL || dbl == 0) && errno == ERANGE) {
|
||||
ret = DDS_RETCODE_OUT_OF_RANGE;
|
||||
} else {
|
||||
errno = orig_errno;
|
||||
}
|
||||
|
||||
*dblptr = dbl;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_strtof(const char *nptr, char **endptr, float *fltptr)
|
||||
{
|
||||
/* Just use os_strtod(). */
|
||||
/* FIXME: This will have to do for now, but a single-precision floating
|
||||
point number is definitely not a double-precision floating point
|
||||
number. */
|
||||
double dbl = 0.0;
|
||||
dds_retcode_t ret;
|
||||
|
||||
assert(nptr != NULL);
|
||||
assert(fltptr != NULL);
|
||||
|
||||
ret = ddsrt_strtod(nptr, endptr, &dbl);
|
||||
*fltptr = (float)dbl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ddsrt_dtostr(double src, char *str, size_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
/* Use locale dependent standard function. */
|
||||
i = snprintf(str, size, "%0.15g", src);
|
||||
/* Make sure the result is a locale independent "x.x" double. */
|
||||
os_lcNumericReplace(str);
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
ddsrt_ftostr(float src, char *str, size_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
/* Use locale dependent standard function. */
|
||||
i = snprintf(str, size, "%0.7g", src);
|
||||
/* Make sure the result is a locale independent "x.x" float. */
|
||||
os_lcNumericReplace(str);
|
||||
return i;
|
||||
}
|
||||
276
src/ddsrt/src/strtol.c
Normal file
276
src/ddsrt/src/strtol.c
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/strtol.h"
|
||||
|
||||
int ddsrt_todigit(const int chr)
|
||||
{
|
||||
if (chr >= '0' && chr <= '9') {
|
||||
return chr - '0';
|
||||
} else if (chr >= 'a' && chr <= 'z') {
|
||||
return 10 + (chr - 'a');
|
||||
} else if (chr >= 'A' && chr <= 'Z') {
|
||||
return 10 + (chr - 'A');
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static dds_retcode_t
|
||||
ullfstr(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
int32_t base,
|
||||
unsigned long long *ullng,
|
||||
unsigned long long max)
|
||||
{
|
||||
dds_retcode_t rc = DDS_RETCODE_OK;
|
||||
int num;
|
||||
size_t cnt = 0;
|
||||
unsigned long long tot = 0;
|
||||
|
||||
assert(str != NULL);
|
||||
assert(ullng != NULL);
|
||||
|
||||
if (base == 0) {
|
||||
if (str[0] == '0') {
|
||||
if ((str[1] == 'x' || str[1] == 'X') && ddsrt_todigit(str[2]) < 16) {
|
||||
base = 16;
|
||||
cnt = 2;
|
||||
} else {
|
||||
base = 8;
|
||||
}
|
||||
} else {
|
||||
base = 10;
|
||||
}
|
||||
} else if (base == 16) {
|
||||
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
|
||||
cnt = 2;
|
||||
}
|
||||
} else if (base < 2 || base > 36) {
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
while ((rc == DDS_RETCODE_OK) &&
|
||||
(num = ddsrt_todigit(str[cnt])) >= 0 && num < base)
|
||||
{
|
||||
if (tot <= (max / (unsigned) base)) {
|
||||
tot *= (unsigned) base;
|
||||
tot += (unsigned) num;
|
||||
cnt++;
|
||||
} else {
|
||||
rc = DDS_RETCODE_OUT_OF_RANGE;
|
||||
tot = max;
|
||||
}
|
||||
}
|
||||
|
||||
if (endptr != NULL) {
|
||||
*endptr = (char *)str + cnt;
|
||||
}
|
||||
|
||||
*ullng = tot;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_strtoll(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
int32_t base,
|
||||
long long *llng)
|
||||
{
|
||||
dds_retcode_t rc = DDS_RETCODE_OK;
|
||||
size_t cnt = 0;
|
||||
long long tot = 1;
|
||||
unsigned long long ullng = 0, max = INT64_MAX;
|
||||
|
||||
assert(str != NULL);
|
||||
assert(llng != NULL);
|
||||
|
||||
for (; isspace((unsigned char)str[cnt]); cnt++) {
|
||||
/* Ignore leading whitespace. */
|
||||
}
|
||||
|
||||
if (str[cnt] == '-') {
|
||||
tot = -1;
|
||||
max++;
|
||||
cnt++;
|
||||
} else if (str[cnt] == '+') {
|
||||
cnt++;
|
||||
}
|
||||
|
||||
rc = ullfstr(str + cnt, endptr, base, &ullng, max);
|
||||
if (endptr && *endptr == (str + cnt))
|
||||
*endptr = (char *)str;
|
||||
if (rc != DDS_RETCODE_BAD_PARAMETER)
|
||||
*llng = tot * (long long)ullng;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_strtoull(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
int32_t base,
|
||||
unsigned long long *ullng)
|
||||
{
|
||||
dds_retcode_t rc = DDS_RETCODE_OK;
|
||||
size_t cnt = 0;
|
||||
unsigned long long tot = 1;
|
||||
unsigned long long max = UINT64_MAX;
|
||||
|
||||
assert(str != NULL);
|
||||
assert(ullng != NULL);
|
||||
|
||||
for (; isspace((unsigned char)str[cnt]); cnt++) {
|
||||
/* ignore leading whitespace */
|
||||
}
|
||||
|
||||
if (str[cnt] == '-') {
|
||||
tot = (unsigned long long) -1;
|
||||
cnt++;
|
||||
} else if (str[cnt] == '+') {
|
||||
cnt++;
|
||||
}
|
||||
|
||||
rc = ullfstr(str + cnt, endptr, base, ullng, max);
|
||||
if (endptr && *endptr == (str + cnt))
|
||||
*endptr = (char *)str;
|
||||
if (rc != DDS_RETCODE_BAD_PARAMETER)
|
||||
*ullng *= tot;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_atoll(
|
||||
const char *str,
|
||||
long long *llng)
|
||||
{
|
||||
return ddsrt_strtoll(str, NULL, 10, llng);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_atoull(
|
||||
const char *str,
|
||||
unsigned long long *ullng)
|
||||
{
|
||||
return ddsrt_strtoull(str, NULL, 10, ullng);
|
||||
}
|
||||
|
||||
char *
|
||||
ddsrt_ulltostr(
|
||||
unsigned long long num,
|
||||
char *str,
|
||||
size_t len,
|
||||
char **endptr)
|
||||
{
|
||||
char chr, *ptr;
|
||||
size_t cnt;
|
||||
size_t lim = 0;
|
||||
size_t tot = 0;
|
||||
|
||||
assert (str != NULL);
|
||||
|
||||
if (len > 1) {
|
||||
lim = len - 1;
|
||||
|
||||
do {
|
||||
str[tot] = (char)('0' + (int)(num % 10));
|
||||
num /= 10;
|
||||
|
||||
if (tot == (lim - 1)) {
|
||||
if (num > 0ULL) {
|
||||
/* Simply using memmove would have been easier, but the function is
|
||||
safe to use in asynchronous code like this. Normally this code
|
||||
should not affect performance, because ideally the buffer is
|
||||
sufficiently large enough. */
|
||||
for (cnt = 0; cnt < tot; cnt++) {
|
||||
str[cnt] = str[cnt + 1];
|
||||
}
|
||||
}
|
||||
} else if (num > 0ULL) {
|
||||
tot++;
|
||||
}
|
||||
} while (num > 0ULL);
|
||||
|
||||
lim = tot + 1;
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < (tot - cnt); cnt++) {
|
||||
chr = str[tot - cnt];
|
||||
str[tot - cnt] = str[cnt];
|
||||
str[cnt] = chr;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
str = NULL;
|
||||
ptr = NULL;
|
||||
} else {
|
||||
str[lim] = '\0';
|
||||
ptr = str + lim;
|
||||
}
|
||||
|
||||
if (endptr != NULL) {
|
||||
*endptr = ptr;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char *
|
||||
ddsrt_lltostr(
|
||||
long long num,
|
||||
char *str,
|
||||
size_t len,
|
||||
char **endptr)
|
||||
{
|
||||
unsigned long long pos;
|
||||
char *ptr;
|
||||
size_t cnt = 0;
|
||||
|
||||
assert (str != NULL);
|
||||
|
||||
if (len == 0) {
|
||||
str = NULL;
|
||||
ptr = NULL;
|
||||
} else if (len == 1) {
|
||||
str[0] = '\0';
|
||||
ptr = str;
|
||||
} else {
|
||||
if (num < 0LL) {
|
||||
if (num == INT64_MIN) {
|
||||
pos = (unsigned long long)INT64_MAX + 1;
|
||||
} else {
|
||||
pos = (unsigned long long) -num;
|
||||
}
|
||||
|
||||
str[cnt++] = '-';
|
||||
} else {
|
||||
pos = (unsigned long long) num;
|
||||
}
|
||||
|
||||
(void)ddsrt_ulltostr(pos, str + cnt, len - cnt, &ptr);
|
||||
}
|
||||
|
||||
if (endptr != NULL) {
|
||||
*endptr = ptr;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
236
src/ddsrt/src/sync/posix/sync.c
Normal file
236
src/ddsrt/src/sync/posix/sync.c
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/timeconv.h"
|
||||
|
||||
void ddsrt_mutex_init (ddsrt_mutex_t *mutex)
|
||||
{
|
||||
int shared;
|
||||
assert (mutex != NULL);
|
||||
|
||||
pthread_mutex_init (&mutex->mutex, NULL);
|
||||
(void)shared;
|
||||
}
|
||||
|
||||
void ddsrt_mutex_destroy (ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert (mutex != NULL);
|
||||
|
||||
if (pthread_mutex_destroy (&mutex->mutex) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void ddsrt_mutex_lock (ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert (mutex != NULL);
|
||||
|
||||
if (pthread_mutex_lock (&mutex->mutex) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_mutex_trylock (ddsrt_mutex_t *mutex)
|
||||
{
|
||||
int err;
|
||||
assert (mutex != NULL);
|
||||
|
||||
err = pthread_mutex_trylock (&mutex->mutex);
|
||||
if (err != 0 && err != EBUSY)
|
||||
abort();
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_mutex_unlock (ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert (mutex != NULL);
|
||||
|
||||
if (pthread_mutex_unlock (&mutex->mutex) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_cond_init (ddsrt_cond_t *cond)
|
||||
{
|
||||
assert (cond != NULL);
|
||||
|
||||
pthread_cond_init (&cond->cond, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_cond_destroy (ddsrt_cond_t *cond)
|
||||
{
|
||||
assert (cond != NULL);
|
||||
|
||||
if (pthread_cond_destroy (&cond->cond) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_cond_wait (ddsrt_cond_t *cond, ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert (cond != NULL);
|
||||
assert (mutex != NULL);
|
||||
|
||||
if (pthread_cond_wait (&cond->cond, &mutex->mutex) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_cond_waituntil(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_time_t abstime)
|
||||
{
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
|
||||
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
if (abstime == DDS_NEVER) {
|
||||
ddsrt_cond_wait(cond, mutex);
|
||||
return true;
|
||||
}
|
||||
if (abstime > 0) {
|
||||
ts.tv_sec = abstime / DDS_NSECS_IN_SEC;
|
||||
ts.tv_nsec = abstime % DDS_NSECS_IN_SEC;
|
||||
}
|
||||
|
||||
switch (pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts)) {
|
||||
case 0:
|
||||
return true;
|
||||
case ETIMEDOUT:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_cond_waitfor(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_duration_t reltime)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
return ddsrt_cond_waituntil(
|
||||
cond, mutex, ddsrt_time_add_duration(dds_time(), reltime));
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_cond_signal (ddsrt_cond_t *cond)
|
||||
{
|
||||
assert (cond != NULL);
|
||||
|
||||
if (pthread_cond_signal (&cond->cond) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_cond_broadcast (ddsrt_cond_t *cond)
|
||||
{
|
||||
assert (cond != NULL);
|
||||
|
||||
if (pthread_cond_broadcast (&cond->cond) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_rwlock_init (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
|
||||
/* process-shared attribute is set to PTHREAD_PROCESS_PRIVATE by default */
|
||||
if ((err = pthread_rwlock_init(&rwlock->rwlock, NULL)) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_rwlock_destroy (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
if ((err = pthread_rwlock_destroy (&rwlock->rwlock)) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_read (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_rwlock_rdlock(&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_write (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_rwlock_wrlock(&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
bool ddsrt_rwlock_tryread (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_rwlock_tryrdlock(&rwlock->rwlock);
|
||||
assert(err == 0 || err == EBUSY);
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
bool ddsrt_rwlock_trywrite (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_rwlock_trywrlock(&rwlock->rwlock);
|
||||
assert(err == 0 || err == EBUSY);
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_unlock (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_rwlock_unlock(&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
void ddsrt_once (ddsrt_once_t *control, ddsrt_once_fn init_fn)
|
||||
{
|
||||
/* There are no defined errors that can be returned by pthread_once */
|
||||
(void)pthread_once(control, init_fn);
|
||||
}
|
||||
214
src/ddsrt/src/sync/windows/sync.c
Normal file
214
src/ddsrt/src/sync/windows/sync.c
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/timeconv.h"
|
||||
|
||||
void ddsrt_mutex_init(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
InitializeSRWLock(&mutex->lock);
|
||||
}
|
||||
|
||||
void ddsrt_mutex_destroy(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
}
|
||||
|
||||
void ddsrt_mutex_lock(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
AcquireSRWLockExclusive(&mutex->lock);
|
||||
}
|
||||
|
||||
bool ddsrt_mutex_trylock(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
return TryAcquireSRWLockExclusive(&mutex->lock);
|
||||
}
|
||||
|
||||
void ddsrt_mutex_unlock(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
ReleaseSRWLockExclusive(&mutex->lock);
|
||||
}
|
||||
|
||||
void ddsrt_cond_init (ddsrt_cond_t *cond)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
InitializeConditionVariable(&cond->cond);
|
||||
}
|
||||
|
||||
void ddsrt_cond_destroy(ddsrt_cond_t *cond)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_cond_wait(ddsrt_cond_t *cond, ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
if (!SleepConditionVariableSRW(&cond->cond, &mutex->lock, INFINITE, 0)) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_cond_waituntil(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_time_t abstime)
|
||||
{
|
||||
dds_duration_t reltime;
|
||||
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
if (abstime == DDS_NEVER) {
|
||||
reltime = DDS_INFINITY;
|
||||
} else {
|
||||
dds_time_t time = dds_time();
|
||||
reltime = (abstime > time ? abstime - time : 0);
|
||||
}
|
||||
|
||||
return ddsrt_cond_waitfor(cond, mutex, reltime);
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_cond_waitfor(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_duration_t reltime)
|
||||
{
|
||||
dds_time_t abstime;
|
||||
DWORD msecs;
|
||||
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
if (reltime == DDS_INFINITY) {
|
||||
ddsrt_cond_wait(cond, mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
abstime = ddsrt_time_add_duration(dds_time(), reltime);
|
||||
msecs = ddsrt_duration_to_msecs_ceil(reltime);
|
||||
if (SleepConditionVariableSRW(&cond->cond, &mutex->lock, msecs, 0)) {
|
||||
return true;
|
||||
} else if (GetLastError() != ERROR_TIMEOUT) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return (dds_time() >= abstime) ? false : true;
|
||||
}
|
||||
|
||||
void ddsrt_cond_signal (ddsrt_cond_t *cond)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
WakeConditionVariable(&cond->cond);
|
||||
}
|
||||
|
||||
void ddsrt_cond_broadcast (ddsrt_cond_t *cond)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
WakeAllConditionVariable(&cond->cond);
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_init (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock);
|
||||
InitializeSRWLock(&rwlock->lock);
|
||||
rwlock->state = 0;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_destroy (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock);
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_read (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock);
|
||||
AcquireSRWLockShared(&rwlock->lock);
|
||||
rwlock->state = 1;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_write(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock);
|
||||
AcquireSRWLockExclusive(&rwlock->lock);
|
||||
rwlock->state = -1;
|
||||
}
|
||||
|
||||
bool ddsrt_rwlock_tryread (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock);
|
||||
if (TryAcquireSRWLockShared(&rwlock->lock)) {
|
||||
rwlock->state = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ddsrt_rwlock_trywrite (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock);
|
||||
if (TryAcquireSRWLockExclusive(&rwlock->lock)) {
|
||||
rwlock->state = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_unlock (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock);
|
||||
assert(rwlock->state != 0);
|
||||
if (rwlock->state > 0) {
|
||||
ReleaseSRWLockShared(&rwlock->lock);
|
||||
} else {
|
||||
ReleaseSRWLockExclusive(&rwlock->lock);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ddsrt_once_fn init_fn;
|
||||
} once_arg_t;
|
||||
|
||||
static BOOL WINAPI
|
||||
once_wrapper(
|
||||
PINIT_ONCE InitOnce,
|
||||
PVOID Parameter,
|
||||
PVOID *Context)
|
||||
{
|
||||
once_arg_t *wrap = (once_arg_t *)Parameter;
|
||||
|
||||
assert(Parameter != NULL);
|
||||
assert(Context == NULL);
|
||||
|
||||
wrap->init_fn();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_once(
|
||||
ddsrt_once_t *control,
|
||||
ddsrt_once_fn init_fn)
|
||||
{
|
||||
once_arg_t wrap = { .init_fn = init_fn };
|
||||
(void) InitOnceExecuteOnce(control, &once_wrapper, &wrap, NULL);
|
||||
}
|
||||
24
src/ddsrt/src/threads.c
Normal file
24
src/ddsrt/src/threads.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
void
|
||||
ddsrt_threadattr_init (
|
||||
ddsrt_threadattr_t *tattr)
|
||||
{
|
||||
assert(tattr != NULL);
|
||||
tattr->schedClass = DDSRT_SCHED_DEFAULT;
|
||||
tattr->schedPriority = 0;
|
||||
tattr->stackSize = 0;
|
||||
}
|
||||
30
src/ddsrt/src/threads/include/dds/ddsrt/threads_priv.h
Normal file
30
src/ddsrt/src/threads/include/dds/ddsrt/threads_priv.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef DDSRT_THREAD_TYPES_H
|
||||
#define DDSRT_THREAD_TYPES_H
|
||||
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
ddsrt_thread_routine_t routine;
|
||||
void *arg;
|
||||
} thread_context_t;
|
||||
|
||||
/** \brief Internal structure used to store cleanup handlers (private) */
|
||||
typedef struct {
|
||||
void *prev;
|
||||
void (*routine)(void *);
|
||||
void *arg;
|
||||
} thread_cleanup_t;
|
||||
|
||||
#endif /* DDSRT_THREAD_TYPES_H */
|
||||
447
src/ddsrt/src/threads/posix/threads.c
Normal file
447
src/ddsrt/src/threads/posix/threads.c
Normal file
|
|
@ -0,0 +1,447 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
|
||||
/* _GNU_SOURCE is required for pthread_getname_np and pthread_setname_np. */
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsrt/threads_priv.h"
|
||||
#include "dds/ddsrt/types.h"
|
||||
|
||||
#if defined(__linux)
|
||||
#include <sys/syscall.h>
|
||||
#define MAXTHREADNAMESIZE (15) /* 16 bytes including null-terminating byte. */
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach/thread_info.h> /* MAXTHREADNAMESIZE */
|
||||
#elif defined(__sun)
|
||||
#define MAXTHREADNAMESIZE (31)
|
||||
#elif defined(__FreeBSD__)
|
||||
/* Required for pthread_get_name_np and pthread_set_name_np. */
|
||||
#include <pthread_np.h>
|
||||
#include <sys/thr.h>
|
||||
#define MAXTHREADNAMESIZE (MAXCOMLEN)
|
||||
#elif defined(__VXWORKS__)
|
||||
#include <taskLib.h>
|
||||
/* VX_TASK_NAME_LENGTH is the maximum number of bytes, excluding
|
||||
null-terminating byte, for a thread name. */
|
||||
#define MAXTHREADNAMESIZE (VX_TASK_NAME_LENGTH)
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
size_t
|
||||
ddsrt_thread_getname(char *str, size_t size)
|
||||
{
|
||||
char buf[MAXTHREADNAMESIZE + 1] = "";
|
||||
size_t cnt = 0;
|
||||
|
||||
assert(str != NULL);
|
||||
assert(size > 0);
|
||||
|
||||
#if defined(__linux)
|
||||
/* Thread names are limited to 16 bytes on Linux. ERANGE is returned if the
|
||||
buffer is smaller than 16 bytes. Use an intermediate buffer. */
|
||||
(void)pthread_getname_np(pthread_self(), buf, sizeof(buf));
|
||||
cnt = ddsrt_strlcpy(str, buf, size);
|
||||
#elif defined(__APPLE__)
|
||||
/* pthread_getname_np on APPLE uses strlcpy to copy the thread name, but
|
||||
does not return the number of bytes (that would have been) written. Use
|
||||
an intermediate buffer. */
|
||||
(void)pthread_getname_np(pthread_self(), buf, sizeof(buf));
|
||||
cnt = ddsrt_strlcpy(str, buf, size);
|
||||
#elif defined(__FreeBSD__)
|
||||
(void)pthread_get_name_np(pthread_self(), buf, sizeof(buf));
|
||||
cnt = ddsrt_strlcpy(str, buf, size);
|
||||
#elif defined(__sun)
|
||||
(void)pthread_getname_np(pthread_self(), buf, sizeof(buf));
|
||||
cnt = ddsrt_strlcpy(str, buf, size);
|
||||
#elif defined(__VXWORKS__)
|
||||
{
|
||||
char *ptr;
|
||||
/* VxWorks does not support retrieving the name of a task through the
|
||||
POSIX thread API, but the task API offers it through taskName. */
|
||||
/* Do not free the pointer returned by taskName. See
|
||||
src/wind/taskInfo.c for details. */
|
||||
ptr = taskName(taskIdSelf());
|
||||
if (ptr == NULL) {
|
||||
ptr = buf;
|
||||
}
|
||||
cnt = ddsrt_strlcpy(str, ptr, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Thread identifier is used as fall back if thread name lookup is not
|
||||
supported or the thread name is empty. */
|
||||
if (cnt == 0) {
|
||||
ddsrt_tid_t tid = ddsrt_gettid();
|
||||
cnt = (size_t)snprintf(str, size, "%"PRIdTID, tid);
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_thread_setname(const char *__restrict name)
|
||||
{
|
||||
assert(name != NULL);
|
||||
|
||||
#if defined(__linux)
|
||||
/* Thread names are limited to 16 bytes on Linux. ERANGE is returned if the
|
||||
name exceeds the limit, so silently truncate. */
|
||||
char buf[MAXTHREADNAMESIZE + 1] = "";
|
||||
ddsrt_strlcpy(buf, name, sizeof(buf));
|
||||
(void)pthread_setname_np(pthread_self(), name);
|
||||
#elif defined(__APPLE__)
|
||||
(void)pthread_setname_np(name);
|
||||
#elif defined(__FreeBSD__)
|
||||
(void)pthread_set_name_np(pthread_self(), name);
|
||||
#elif defined(__sun)
|
||||
/* Thread names are limited to 31 bytes on Solaris. Excess bytes are
|
||||
silently truncated. */
|
||||
(void)pthread_setname_np(pthread_self(), name);
|
||||
#else
|
||||
/* VxWorks does not support the task name to be set after a task is created.
|
||||
Setting the name of a task can be done through pthread_attr_setname. */
|
||||
#warning "ddsrt_thread_setname is not supported"
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Wrap thread start routine
|
||||
*
|
||||
* \b os_startRoutineWrapper wraps a threads starting routine.
|
||||
* before calling the user routine, it sets the threads name
|
||||
* in the context of the thread. With \b pthread_getspecific,
|
||||
* the name can be retreived for different purposes.
|
||||
*/
|
||||
static void *os_startRoutineWrapper (void *threadContext)
|
||||
{
|
||||
thread_context_t *context = threadContext;
|
||||
uintptr_t resultValue;
|
||||
|
||||
ddsrt_thread_setname(context->name);
|
||||
|
||||
/* Call the user routine */
|
||||
resultValue = context->routine (context->arg);
|
||||
|
||||
/* Free the thread context resources, arguments is responsibility */
|
||||
/* for the caller of os_procCreate */
|
||||
ddsrt_free(context->name);
|
||||
ddsrt_free(context);
|
||||
|
||||
#if defined(__VXWORKS__) && !defined(_WRS_KERNEL)
|
||||
struct sched_param sched_param;
|
||||
int max, policy = 0;
|
||||
|
||||
/* There is a known issue in pthread_join on VxWorks 6.x RTP mode.
|
||||
|
||||
WindRiver: When pthread_join returns, it does not indicate end of a
|
||||
thread in 100% of the situations. If the thread that calls pthread_join
|
||||
has a higher priority than the thread that is currently terminating,
|
||||
pthread_join could return before pthread_exit has finished. This
|
||||
conflicts with the POSIX specification that dictates that pthread_join
|
||||
must only return when the thread is really terminated. The workaround
|
||||
suggested by WindRiver support is to increase the priority of the thread
|
||||
(task) to be terminated before handing back the semaphore to ensure the
|
||||
thread exits before pthread_join returns.
|
||||
|
||||
This bug was submitted to WindRiver as TSR 815826. */
|
||||
|
||||
/* Note that any possible errors raised here are not terminal since the
|
||||
thread may have exited at this point anyway. */
|
||||
if (pthread_getschedparam(thread.v, &policy, &sched_param) == 0) {
|
||||
max = sched_get_priority_max(policy);
|
||||
if (max != -1) {
|
||||
(void)pthread_setschedprio(thread.v, max);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* return the result of the user routine */
|
||||
return (void *)resultValue;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_thread_create (
|
||||
ddsrt_thread_t *threadptr,
|
||||
const char *name,
|
||||
const ddsrt_threadattr_t *threadAttr,
|
||||
uint32_t (*start_routine) (void *),
|
||||
void *arg)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
thread_context_t *ctx;
|
||||
ddsrt_threadattr_t tattr;
|
||||
int result, create_ret;
|
||||
|
||||
assert (threadptr != NULL);
|
||||
assert (name != NULL);
|
||||
assert (threadAttr != NULL);
|
||||
assert (start_routine != NULL);
|
||||
tattr = *threadAttr;
|
||||
|
||||
if (pthread_attr_init (&attr) != 0)
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
#if defined(__VXWORKS__)
|
||||
/* pthread_setname_np is not available on VxWorks. Use pthread_attr_setname
|
||||
instead (proprietary VxWorks extension). */
|
||||
(void)pthread_attr_setname (&attr, name);
|
||||
#endif
|
||||
|
||||
if (pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM) != 0 ||
|
||||
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE) != 0)
|
||||
goto err;
|
||||
|
||||
if (tattr.stackSize != 0)
|
||||
{
|
||||
#ifdef PTHREAD_STACK_MIN
|
||||
if (tattr.stackSize < PTHREAD_STACK_MIN)
|
||||
tattr.stackSize = PTHREAD_STACK_MIN;
|
||||
#endif
|
||||
if ((result = pthread_attr_setstacksize (&attr, tattr.stackSize)) != 0)
|
||||
{
|
||||
DDS_ERROR ("ddsrt_thread_create(%s): pthread_attr_setstacksize(%"PRIu32") failed with error %d\n", name, tattr.stackSize, result);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (tattr.schedClass == DDSRT_SCHED_DEFAULT)
|
||||
{
|
||||
if (tattr.schedPriority != 0)
|
||||
{
|
||||
/* If caller doesn't set the class, he must not try to set the priority, which we
|
||||
approximate by expecting a 0. FIXME: should do this as part of config validation */
|
||||
DDS_ERROR("ddsrt_thread_create(%s): schedClass DEFAULT but priority != 0 is unsupported\n", name);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int policy;
|
||||
struct sched_param sched_param;
|
||||
if ((result = pthread_getschedparam (pthread_self (), &policy, &sched_param) != 0) != 0)
|
||||
{
|
||||
DDS_ERROR("ddsrt_thread_create(%s): pthread_attr_getschedparam(self) failed with error %d\n", name, result);
|
||||
goto err;
|
||||
}
|
||||
switch (tattr.schedClass)
|
||||
{
|
||||
case DDSRT_SCHED_DEFAULT:
|
||||
assert (0);
|
||||
break;
|
||||
case DDSRT_SCHED_REALTIME:
|
||||
policy = SCHED_FIFO;
|
||||
break;
|
||||
case DDSRT_SCHED_TIMESHARE:
|
||||
policy = SCHED_OTHER;
|
||||
break;
|
||||
}
|
||||
if ((result = pthread_attr_setschedpolicy (&attr, policy)) != 0)
|
||||
{
|
||||
DDS_ERROR("ddsrt_thread_create(%s): pthread_attr_setschedpolicy(%d) failed with error %d\n", name, policy, result);
|
||||
goto err;
|
||||
}
|
||||
sched_param.sched_priority = tattr.schedPriority;
|
||||
if ((result = pthread_attr_setschedparam (&attr, &sched_param)) != 0)
|
||||
{
|
||||
DDS_ERROR("ddsrt_thread_create(%s): pthread_attr_setschedparam(priority = %d) failed with error %d\n", name, tattr.schedPriority, result);
|
||||
goto err;
|
||||
}
|
||||
if ((result = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED)) != 0)
|
||||
{
|
||||
DDS_ERROR("ddsrt_thread_create(%s): pthread_attr_setinheritsched(EXPLICIT) failed with error %d\n", name, result);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct context structure & start thread */
|
||||
ctx = ddsrt_malloc (sizeof (thread_context_t));
|
||||
ctx->name = ddsrt_malloc (strlen (name) + 1);
|
||||
strcpy (ctx->name, name);
|
||||
ctx->routine = start_routine;
|
||||
ctx->arg = arg;
|
||||
if ((create_ret = pthread_create (&threadptr->v, &attr, os_startRoutineWrapper, ctx)) != 0)
|
||||
{
|
||||
DDS_ERROR ("os_threadCreate(%s): pthread_create failed with error %d\n", name, create_ret);
|
||||
goto err_create;
|
||||
}
|
||||
pthread_attr_destroy (&attr);
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
err_create:
|
||||
ddsrt_free (ctx->name);
|
||||
ddsrt_free (ctx);
|
||||
err:
|
||||
pthread_attr_destroy (&attr);
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
ddsrt_tid_t
|
||||
ddsrt_gettid(void)
|
||||
{
|
||||
ddsrt_tid_t tid;
|
||||
|
||||
#if defined(__linux)
|
||||
tid = syscall(SYS_gettid);
|
||||
#elif defined(__FreeBSD__) && (__FreeBSD_version >= 900031)
|
||||
/* FreeBSD >= 9.0 */
|
||||
tid = pthread_getthreadid_np();
|
||||
#elif defined(__APPLE__) && !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED < 1060)
|
||||
/* macOS >= 10.6 */
|
||||
pthread_threadid_np(NULL, &tid);
|
||||
#elif defined(__VXWORKS__)
|
||||
tid = taskIdSelf();
|
||||
#else
|
||||
tid = (uintmax_t)((uintptr_t)pthread_self());
|
||||
#endif
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
ddsrt_thread_t
|
||||
ddsrt_thread_self(void)
|
||||
{
|
||||
ddsrt_thread_t id = {.v = pthread_self ()};
|
||||
return id;
|
||||
}
|
||||
|
||||
bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b)
|
||||
{
|
||||
return (pthread_equal(a.v, b.v) != 0);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result)
|
||||
{
|
||||
int err;
|
||||
void *vthread_result;
|
||||
|
||||
assert (thread.v);
|
||||
|
||||
|
||||
if ((err = pthread_join (thread.v, &vthread_result)) != 0)
|
||||
{
|
||||
DDS_TRACE ("pthread_join(0x%"PRIxMAX") failed with error %d\n", (uintmax_t)((uintptr_t)thread.v), err);
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
if (thread_result)
|
||||
*thread_result = (uint32_t) ((uintptr_t) vthread_result);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
|
||||
static pthread_key_t thread_cleanup_key;
|
||||
static pthread_once_t thread_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void thread_cleanup_fini(void *arg);
|
||||
|
||||
static void thread_init_once(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_key_create(&thread_cleanup_key, &thread_cleanup_fini);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
static void thread_init(void)
|
||||
{
|
||||
(void)pthread_once(&thread_once, &thread_init_once);
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_thread_cleanup_push (void (*routine) (void *), void *arg)
|
||||
{
|
||||
int err;
|
||||
thread_cleanup_t *prev, *tail;
|
||||
|
||||
assert(routine != NULL);
|
||||
|
||||
thread_init();
|
||||
if ((tail = ddsrt_calloc(1, sizeof(*tail))) != NULL) {
|
||||
prev = pthread_getspecific(thread_cleanup_key);
|
||||
tail->prev = prev;
|
||||
tail->routine = routine;
|
||||
tail->arg = arg;
|
||||
if ((err = pthread_setspecific(thread_cleanup_key, tail)) != 0) {
|
||||
assert(err != EINVAL);
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_thread_cleanup_pop (int execute)
|
||||
{
|
||||
int err;
|
||||
thread_cleanup_t *tail;
|
||||
|
||||
thread_init();
|
||||
if ((tail = pthread_getspecific(thread_cleanup_key)) != NULL) {
|
||||
if ((err = pthread_setspecific(thread_cleanup_key, tail->prev)) != 0) {
|
||||
assert(err != EINVAL);
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
if (execute) {
|
||||
tail->routine(tail->arg);
|
||||
}
|
||||
ddsrt_free(tail);
|
||||
}
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static void thread_cleanup_fini(void *arg)
|
||||
{
|
||||
thread_cleanup_t *tail, *prev;
|
||||
|
||||
tail = (thread_cleanup_t *)arg;
|
||||
while (tail != NULL) {
|
||||
prev = tail->prev;
|
||||
assert(tail->routine != NULL);
|
||||
tail->routine(tail->arg);
|
||||
ddsrt_free(tail);
|
||||
tail = prev;
|
||||
}
|
||||
|
||||
/* Thread-specific value associated with thread_cleanup_key will already be
|
||||
nullified if invoked as destructor, i.e. not from ddsrt_thread_fini. */
|
||||
}
|
||||
|
||||
void ddsrt_thread_init(void)
|
||||
{
|
||||
thread_init();
|
||||
}
|
||||
|
||||
void ddsrt_thread_fini(void)
|
||||
{
|
||||
thread_cleanup_t *tail;
|
||||
|
||||
thread_init();
|
||||
if ((tail = pthread_getspecific(thread_cleanup_key)) != NULL) {
|
||||
thread_cleanup_fini(tail);
|
||||
(void)pthread_setspecific(thread_cleanup_key, NULL);
|
||||
}
|
||||
}
|
||||
303
src/ddsrt/src/threads/windows/threads.c
Normal file
303
src/ddsrt/src/threads/windows/threads.c
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsrt/threads_priv.h"
|
||||
|
||||
static uint32_t
|
||||
os_startRoutineWrapper(
|
||||
void *threadContext)
|
||||
{
|
||||
thread_context_t *context = threadContext;
|
||||
uint32_t resultValue = 0;
|
||||
|
||||
ddsrt_thread_setname(context->name);
|
||||
|
||||
/* Call the user routine */
|
||||
resultValue = context->routine(context->arg);
|
||||
|
||||
/* Free the thread context resources, arguments is responsibility */
|
||||
/* for the caller of os_threadCreate */
|
||||
ddsrt_free(context->name);
|
||||
ddsrt_free(context);
|
||||
|
||||
/* return the result of the user routine */
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_thread_create(
|
||||
ddsrt_thread_t *thrptr,
|
||||
const char *name,
|
||||
const ddsrt_threadattr_t *attr,
|
||||
ddsrt_thread_routine_t start_routine,
|
||||
void *arg)
|
||||
{
|
||||
ddsrt_thread_t thr;
|
||||
thread_context_t *ctx;
|
||||
int32_t prio;
|
||||
|
||||
assert(thrptr != NULL);
|
||||
assert(name != NULL);
|
||||
assert(attr != NULL);
|
||||
assert(start_routine != NULL);
|
||||
|
||||
if ((ctx = ddsrt_malloc(sizeof(*ctx))) == NULL ||
|
||||
(ctx->name = ddsrt_strdup(name)) == NULL)
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
|
||||
ctx->routine = start_routine;
|
||||
ctx->arg = arg;
|
||||
thr.handle = CreateThread(NULL,
|
||||
(SIZE_T)attr->stackSize,
|
||||
(LPTHREAD_START_ROUTINE)os_startRoutineWrapper,
|
||||
(LPVOID)ctx,
|
||||
(DWORD)0,
|
||||
&thr.tid);
|
||||
|
||||
if (thr.handle == NULL)
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
*thrptr = thr;
|
||||
|
||||
/* Windows thread priorities are in the range below:
|
||||
-15 : THREAD_PRIORITY_IDLE
|
||||
-2 : THREAD_PRIORITY_LOWEST
|
||||
-1 : THREAD_PRIORITY_BELOW_NORMAL
|
||||
0 : THREAD_PRIORITY_NORMAL
|
||||
1 : THREAD_PRIORITY_ABOVE_NORMAL
|
||||
2 : THREAD_PRIORITY_HIGHEST
|
||||
15 : THREAD_PRIORITY_TIME_CRITICAL
|
||||
For realtime threads additional values are allowed: */
|
||||
|
||||
/* PROCESS_QUERY_INFORMATION rights required to call GetPriorityClass
|
||||
Ensure that priorities are effectively in the allowed range depending
|
||||
on GetPriorityClass result. */
|
||||
/* FIXME: The logic here might be incorrect.
|
||||
https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setthreadpriority */
|
||||
prio = attr->schedPriority;
|
||||
if (GetPriorityClass(GetCurrentProcess()) == REALTIME_PRIORITY_CLASS) {
|
||||
if (attr->schedPriority < -7)
|
||||
prio = THREAD_PRIORITY_IDLE;
|
||||
else if (attr->schedPriority > 6)
|
||||
prio = THREAD_PRIORITY_TIME_CRITICAL;
|
||||
} else {
|
||||
if (attr->schedPriority < THREAD_PRIORITY_LOWEST)
|
||||
prio = THREAD_PRIORITY_IDLE;
|
||||
else if (attr->schedPriority > THREAD_PRIORITY_HIGHEST)
|
||||
prio = THREAD_PRIORITY_TIME_CRITICAL;
|
||||
}
|
||||
|
||||
if (SetThreadPriority(thr.handle, prio) == 0) {
|
||||
DDS_WARNING("SetThreadPriority failed with %i\n", GetLastError());
|
||||
}
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
ddsrt_tid_t
|
||||
ddsrt_gettid(void)
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
ddsrt_thread_t
|
||||
ddsrt_thread_self(
|
||||
void)
|
||||
{
|
||||
ddsrt_thread_t thr;
|
||||
thr.tid = GetCurrentThreadId();
|
||||
thr.handle = GetCurrentThread(); /* pseudo HANDLE, no need to close it */
|
||||
|
||||
return thr;
|
||||
}
|
||||
|
||||
bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b)
|
||||
{
|
||||
return a.tid == b.tid;
|
||||
}
|
||||
|
||||
/* ES: dds2086: Close handle should not be performed here. Instead the handle
|
||||
* should not be closed until the os_threadWaitExit(...) call is called.
|
||||
* CloseHandle (threadHandle);
|
||||
*/
|
||||
dds_retcode_t
|
||||
ddsrt_thread_join(
|
||||
ddsrt_thread_t thread,
|
||||
uint32_t *thread_result)
|
||||
{
|
||||
DWORD tr;
|
||||
DWORD waitres;
|
||||
BOOL status;
|
||||
|
||||
if (thread.handle == NULL) {
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
waitres = WaitForSingleObject(thread.handle, INFINITE);
|
||||
if (waitres != WAIT_OBJECT_0) {
|
||||
//err = GetLastError();
|
||||
//OS_DEBUG_1("os_threadWaitExit", "WaitForSingleObject Failed %d", err);
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
status = GetExitCodeThread(thread.handle, &tr);
|
||||
if (!status) {
|
||||
//err = GetLastError();
|
||||
//OS_DEBUG_1("os_threadWaitExit", "GetExitCodeThread Failed %d", err);
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
assert(tr != STILL_ACTIVE);
|
||||
if (thread_result) {
|
||||
*thread_result = tr;
|
||||
}
|
||||
CloseHandle(thread.handle);
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
/* Thread names on Linux are limited to 16 bytes, no reason to provide
|
||||
more storage than that as internal threads must adhere to that limit. */
|
||||
static ddsrt_thread_local char thread_name[16] = "";
|
||||
|
||||
size_t
|
||||
ddsrt_thread_getname(
|
||||
char *__restrict str,
|
||||
size_t size)
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
if ((cnt = ddsrt_strlcpy(str, thread_name, size)) == 0) {
|
||||
ddsrt_tid_t tid = ddsrt_gettid();
|
||||
cnt = (size_t)snprintf(str, size, "%"PRIdTID, tid);
|
||||
assert(cnt >= 0);
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static const DWORD MS_VC_EXCEPTION=0x406D1388;
|
||||
|
||||
#pragma pack(push,8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; /** Must be 0x1000. */
|
||||
LPCSTR szName; /** Pointer to name (in user addr space). */
|
||||
DWORD dwThreadID; /** Thread ID (-1=caller thread). */
|
||||
DWORD dwFlags; /** Reserved for future use, must be zero. */
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
/** \brief Wrap thread start routine
|
||||
*
|
||||
* \b os_startRoutineWrapper wraps a threads starting routine.
|
||||
* before calling the user routine. It tries to set a thread name
|
||||
* that will be visible if the process is running under the MS
|
||||
* debugger.
|
||||
*/
|
||||
void
|
||||
ddsrt_thread_setname(
|
||||
const char *__restrict name)
|
||||
{
|
||||
assert(name != NULL);
|
||||
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name;
|
||||
info.dwThreadID = -1;
|
||||
info.dwFlags = 0;
|
||||
|
||||
/* Empty try/except that catches everything on purpose to set the thread
|
||||
name. See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx. */
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6320 6322)
|
||||
__try
|
||||
{
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Suppress warnings. */
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
ddsrt_strlcpy(thread_name, name, sizeof(thread_name));
|
||||
}
|
||||
|
||||
|
||||
static ddsrt_thread_local thread_cleanup_t *thread_cleanup = NULL;
|
||||
|
||||
dds_retcode_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg)
|
||||
{
|
||||
thread_cleanup_t *tail;
|
||||
|
||||
assert(routine != NULL);
|
||||
|
||||
if ((tail = ddsrt_malloc(sizeof(thread_cleanup_t))) != NULL) {
|
||||
tail->prev = thread_cleanup;
|
||||
thread_cleanup = tail;
|
||||
assert(tail != NULL);
|
||||
tail->routine = routine;
|
||||
tail->arg = arg;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_thread_cleanup_pop(int execute)
|
||||
{
|
||||
thread_cleanup_t *tail;
|
||||
|
||||
if ((tail = thread_cleanup) != NULL) {
|
||||
thread_cleanup = tail->prev;
|
||||
if (execute) {
|
||||
tail->routine(tail->arg);
|
||||
}
|
||||
ddsrt_free(tail);
|
||||
}
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
thread_cleanup_fini(void)
|
||||
{
|
||||
thread_cleanup_t *tail, *prev;
|
||||
|
||||
tail = thread_cleanup;
|
||||
while (tail != NULL) {
|
||||
prev = tail->prev;
|
||||
assert(tail->routine != NULL);
|
||||
tail->routine(tail->arg);
|
||||
ddsrt_free(tail);
|
||||
tail = prev;
|
||||
}
|
||||
|
||||
thread_cleanup = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_thread_init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_thread_fini(void)
|
||||
{
|
||||
thread_cleanup_fini();
|
||||
}
|
||||
74
src/ddsrt/src/time.c
Normal file
74
src/ddsrt/src/time.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "dds/ddsrt/timeconv.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
extern inline dds_time_t
|
||||
ddsrt_time_add_duration(dds_time_t abstime, dds_duration_t reltime);
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <errno.h>
|
||||
|
||||
void dds_sleepfor(dds_duration_t n)
|
||||
{
|
||||
struct timespec t, r;
|
||||
|
||||
if (n >= 0) {
|
||||
t.tv_sec = n / DDS_NSECS_IN_SEC;
|
||||
t.tv_nsec = n % DDS_NSECS_IN_SEC;
|
||||
while (nanosleep(&t, &r) == -1 && errno == EINTR) {
|
||||
t = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void dds_sleepuntil(dds_time_t abstime)
|
||||
{
|
||||
dds_time_t now = dds_time();
|
||||
|
||||
if (abstime > now)
|
||||
dds_sleepfor (abstime - now);
|
||||
}
|
||||
|
||||
size_t
|
||||
ddsrt_ctime(dds_time_t n, char *str, size_t size)
|
||||
{
|
||||
struct tm tm;
|
||||
static const char fmt[] = "%Y-%m-%d %H:%M:%S%z";
|
||||
char buf[] = "YYYY-mm-dd HH:MM:SS.hh:mm"; /* RFC 3339 */
|
||||
size_t cnt;
|
||||
time_t sec = (time_t)(n / DDS_NSECS_IN_SEC);
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
#if _WIN32
|
||||
(void)localtime_s(&tm, &sec);
|
||||
#else
|
||||
(void)localtime_r(&sec, &tm);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
cnt = strftime(buf, sizeof(buf), fmt, &tm);
|
||||
assert(cnt == (sizeof(buf) - 2 /* ':' + '\0' */));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
buf[sizeof(buf) - 2] = buf[sizeof(buf) - 3];
|
||||
buf[sizeof(buf) - 3] = buf[sizeof(buf) - 4];
|
||||
buf[sizeof(buf) - 4] = ':';
|
||||
|
||||
(void)cnt;
|
||||
|
||||
return ddsrt_strlcpy(str, buf, size);
|
||||
}
|
||||
|
||||
58
src/ddsrt/src/time/darwin/time.c
Normal file
58
src/ddsrt/src/time/darwin/time.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
dds_time_t dds_time(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
|
||||
return ((tv.tv_sec * DDS_NSECS_IN_SEC) + (tv.tv_usec * DDS_NSECS_IN_USEC));
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_monotonic(void)
|
||||
{
|
||||
static mach_timebase_info_data_t timeInfo;
|
||||
uint64_t mt;
|
||||
|
||||
/* The Mach absolute time returned by mach_absolute_time is very similar to
|
||||
* the QueryPerformanceCounter on Windows. The update-rate isn't fixed, so
|
||||
* that information needs to be resolved to provide a clock with real-time
|
||||
* progression.
|
||||
*
|
||||
* The mach_absolute_time does include time spent during sleep (on Intel
|
||||
* CPU's, not on PPC), but not the time spent during suspend.
|
||||
*
|
||||
* The result is not adjusted based on NTP, so long-term progression by
|
||||
* this clock may not match the time progression made by the real-time
|
||||
* clock. */
|
||||
mt = mach_absolute_time();
|
||||
|
||||
if (timeInfo.denom == 0) {
|
||||
(void)mach_timebase_info(&timeInfo);
|
||||
}
|
||||
|
||||
return (dds_time_t)(mt * timeInfo.numer / timeInfo.denom);
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_elapsed(void)
|
||||
{
|
||||
/* Elapsed time clock not (yet) supported on this platform. */
|
||||
return ddsrt_time_monotonic();
|
||||
}
|
||||
68
src/ddsrt/src/time/include/dds/ddsrt/timeconv.h
Normal file
68
src/ddsrt/src/time/include/dds/ddsrt/timeconv.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
/**
|
||||
* @brief Calculate a time given an offset time and a duration.
|
||||
*
|
||||
* Negative time can become positive by adding a large enough duration, of
|
||||
* course a positive time can become negative given a large enough negative
|
||||
* duration.
|
||||
*
|
||||
* @param[in] abstime Timestamp in nanoseconds since UNIX Epoch.
|
||||
* @param[in] reltime Relative time in nanoseconds.
|
||||
*
|
||||
* @returns A timestamp in nanoseconds since UNIX Epoch.
|
||||
*/
|
||||
inline dds_time_t
|
||||
ddsrt_time_add_duration(dds_time_t abstime, dds_duration_t reltime)
|
||||
{
|
||||
assert(abstime >= 0);
|
||||
assert(reltime >= 0);
|
||||
|
||||
return (reltime >= DDS_NEVER - abstime ? DDS_NEVER : abstime + reltime);
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
/**
|
||||
* @brief Convert a relative time to microseconds rounding up.
|
||||
*
|
||||
* @param[in] reltime Relative time to convert.
|
||||
*
|
||||
* @returns INFINITE if @reltime was @DDS_INIFINITY, relative time converted to
|
||||
* microseconds otherwise.
|
||||
*/
|
||||
inline DWORD
|
||||
ddsrt_duration_to_msecs_ceil(dds_duration_t reltime)
|
||||
{
|
||||
if (reltime == DDS_INFINITY) {
|
||||
return INFINITE;
|
||||
} else if (reltime > 0) {
|
||||
assert(INFINITE < (DDS_INFINITY / DDS_NSECS_IN_MSEC));
|
||||
dds_duration_t max_nsecs = (INFINITE - 1) * DDS_NSECS_IN_MSEC;
|
||||
|
||||
if (reltime < (max_nsecs - (DDS_NSECS_IN_MSEC - 1))) {
|
||||
reltime += (DDS_NSECS_IN_MSEC - 1);
|
||||
} else {
|
||||
reltime = max_nsecs;
|
||||
}
|
||||
|
||||
return (DWORD)(reltime / DDS_NSECS_IN_MSEC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
41
src/ddsrt/src/time/posix/time.c
Normal file
41
src/ddsrt/src/time/posix/time.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
dds_time_t dds_time(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
(void)clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return (ts.tv_sec * DDS_NSECS_IN_SEC) + ts.tv_nsec;
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_monotonic(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (ts.tv_sec * DDS_NSECS_IN_SEC) + ts.tv_nsec;
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_elapsed(void)
|
||||
{
|
||||
/* Elapsed time clock not worth the bother for now. */
|
||||
return ddsrt_time_monotonic();
|
||||
}
|
||||
161
src/ddsrt/src/time/windows/time.c
Normal file
161
src/ddsrt/src/time/windows/time.c
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "dds/ddsrt/timeconv.h"
|
||||
|
||||
extern inline DWORD
|
||||
ddsrt_duration_to_msecs_ceil(dds_duration_t reltime);
|
||||
|
||||
/* GetSystemTimePreciseAsFileTime was introduced with Windows 8, so
|
||||
starting from _WIN32_WINNET = 0x0602. When building for an older
|
||||
version we can still check dynamically. */
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602
|
||||
#define UseGetSystemTimePreciseAsFileTime
|
||||
#else
|
||||
static VOID (WINAPI *GetSystemTimeAsFileTimeFunc)(LPFILTETIME) = GetSystemTimeAsFileTime;
|
||||
static HANDLE Kernel32ModuleHandle;
|
||||
#endif
|
||||
|
||||
/* GetSystemTimeAsFileTime returns the number of 100ns intervals that have elapsed
|
||||
* since January 1, 1601 (UTC). There are 11,644,473,600 seconds between 1601 and
|
||||
* the Unix epoch (January 1, 1970 (UTC)), which is the reference that is used for
|
||||
* dds_time.
|
||||
*/
|
||||
#define FILETIME_EPOCH_OFFSET_SECS (11644473600)
|
||||
#define SECS_IN_100_NSECS (1000 * 1000 * 10)
|
||||
|
||||
dds_time_t dds_time(void)
|
||||
{
|
||||
FILETIME ft;
|
||||
ULARGE_INTEGER ns100;
|
||||
|
||||
/* GetSystemTime(Precise)AsFileTime returns the number of 100-nanosecond
|
||||
* intervals since January 1, 1601 (UTC).
|
||||
* GetSystemTimeAsFileTime has a resolution of approximately the
|
||||
* TimerResolution (~15.6ms) on Windows XP. On Windows 7 it appears to have
|
||||
* sub-millisecond resolution. GetSystemTimePreciseAsFileTime (available on
|
||||
* Windows 8) has sub-microsecond resolution.
|
||||
*
|
||||
* This call appears to be significantly (factor 8) cheaper than the
|
||||
* QueryPerformanceCounter (on the systems performance was measured on).
|
||||
*
|
||||
* TODO: When the API is extended to support retrieval of clock-properties,
|
||||
* then the actual resolution of this clock can be retrieved using the
|
||||
* GetSystemTimeAdjustment.
|
||||
*/
|
||||
#ifdef UseGetSystemTimePreciseAsFileTime
|
||||
GetSystemTimePreciseAsFileTime(&ft);
|
||||
#else
|
||||
GetSystemTimeAsFileTimeFunc(&ft);
|
||||
#endif
|
||||
ns100.LowPart = ft.dwLowDateTime;
|
||||
ns100.HighPart = ft.dwHighDateTime;
|
||||
ns100.QuadPart -= (FILETIME_EPOCH_OFFSET_SECS * SECS_IN_100_NSECS);
|
||||
|
||||
return (dds_time_t)(ns100.QuadPart * 100);
|
||||
}
|
||||
|
||||
void ddsrt_time_init(void)
|
||||
{
|
||||
#ifndef UseGetSystemTimePreciseAsFileTime
|
||||
/* Resolve the time-functions from the Kernel32-library. */
|
||||
VOID (WINAPI *f) (LPFILTETIME);
|
||||
|
||||
/* This os_timeModuleInit is currently called from DllMain. This means
|
||||
* we're not allowed to do LoadLibrary. One exception is "Kernel32.DLL",
|
||||
* since that library is per definition loaded (LoadLibrary itself
|
||||
* lives there). And since we're only resolving stuff, not actually
|
||||
* invoking, this is considered safe.
|
||||
*/
|
||||
Kernel32ModuleHandle = LoadLibrary("Kernel32.DLL");
|
||||
assert(Kernel32ModuleHandle);
|
||||
|
||||
f = GetProcAddress(Kernel32ModuleHandle, "GetSystemTimePreciseAsFileTime");
|
||||
if (f != 0) {
|
||||
GetSystemTimeAsFileTimeFunc = f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ddsrt_time_fini(void)
|
||||
{
|
||||
#ifndef UseGetSystemTimePreciseAsFileTime
|
||||
if (Kernel32ModuleHandle) {
|
||||
GetSystemTimeAsFileTimeFunc = GetSystemTimeAsFileTime;
|
||||
FreeLibrary(Kernel32ModuleHandle);
|
||||
Kernel32ModuleHandle = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_monotonic(void)
|
||||
{
|
||||
ULONGLONG ubit;
|
||||
|
||||
(void)QueryUnbiasedInterruptTime(&ubit); /* 100ns ticks */
|
||||
|
||||
return (dds_time_t)(ubit * 100);
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_elapsed(void)
|
||||
{
|
||||
LARGE_INTEGER qpc;
|
||||
static LONGLONG qpc_freq; /* Counts per nanosecond. */
|
||||
|
||||
/* The QueryPerformanceCounter has a bad reputation, since it didn't behave
|
||||
* very well on older hardware. On recent OS's (Windows XP SP2 and later)
|
||||
* things have become much better, especially when combined with new hard-
|
||||
* ware.
|
||||
*
|
||||
* There is currently one bug which is not fixed, which may cause forward
|
||||
* jumps. This is currently not really important, since a forward jump may
|
||||
* be observed anyway due to the system going to standby. There is a work-
|
||||
* around available (comparing the progress with the progress made by
|
||||
* GetTickCount), but for now we live with a risk of a forward jump on buggy
|
||||
* hardware. Since Microsoft does maintain a list of hardware which exhibits
|
||||
* the behaviour, it is possible to only have the workaround in place only
|
||||
* on the faulty hardware (see KB274323 for a list and more info).
|
||||
*
|
||||
* TODO: When the API is extended to support retrieval of clock-properties,
|
||||
* then the discontinuous nature (when sleeping/hibernating) of this
|
||||
* clock and the drift tendency should be reported. */
|
||||
|
||||
if (qpc_freq == 0){
|
||||
/* This block is idempotent, so don't bother with synchronisation. */
|
||||
LARGE_INTEGER frequency;
|
||||
|
||||
if (QueryPerformanceFrequency(&frequency)) {
|
||||
/* Performance-counter frequency is in counts per second. */
|
||||
qpc_freq = DDS_NSECS_IN_SEC / frequency.QuadPart;
|
||||
}
|
||||
/* Since Windows XP SP2 the QueryPerformanceCounter is abstracted,
|
||||
* so QueryPerformanceFrequency is not expected to ever return 0.
|
||||
* That't why there is no fall-back for the case when no
|
||||
* QueryPerformanceCounter is available. */
|
||||
}
|
||||
assert(qpc_freq);
|
||||
|
||||
/* The QueryPerformanceCounter tends to drift quite a bit, so in order to
|
||||
* accurately measure longer periods with it, there may be a need to sync
|
||||
* the time progression to actual time progression. */
|
||||
QueryPerformanceCounter(&qpc);
|
||||
|
||||
return (dds_time_t)(qpc.QuadPart * qpc_freq);
|
||||
}
|
||||
|
||||
void dds_sleepfor(dds_duration_t reltime)
|
||||
{
|
||||
Sleep(ddsrt_duration_to_msecs_ceil(reltime));
|
||||
}
|
||||
43
src/ddsrt/tests/CMakeLists.txt
Normal file
43
src/ddsrt/tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
#
|
||||
# This program and the accompanying materials are made available under the
|
||||
# terms of the Eclipse Public License v. 2.0 which is available at
|
||||
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
# v. 1.0 which is available at
|
||||
# http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
#
|
||||
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
#
|
||||
include(CUnit)
|
||||
|
||||
set(sources
|
||||
"atomics.c"
|
||||
"environ.c"
|
||||
"heap.c"
|
||||
"ifaddrs.c"
|
||||
"sync.c"
|
||||
"strtoll.c"
|
||||
"thread.c"
|
||||
"thread_cleanup.c"
|
||||
"string.c"
|
||||
"log.c"
|
||||
"strlcpy.c"
|
||||
"socket.c"
|
||||
"select.c")
|
||||
|
||||
add_cunit_executable(cunit_ddsrt ${sources})
|
||||
target_link_libraries(cunit_ddsrt PRIVATE ddsrt)
|
||||
|
||||
# Create a dummy export header. generate_export_header can only be used with
|
||||
# library targets, but since the targets are linked statically,
|
||||
# __declspec(dllimport) is not required anyway.
|
||||
set(export_dir "${CMAKE_CURRENT_BINARY_DIR}/include/dds")
|
||||
set(export_header "${export_dir}/export.h")
|
||||
if(NOT EXISTS "${export_header}")
|
||||
file(MAKE_DIRECTORY "${export_dir}")
|
||||
file(WRITE "${export_header}" "#define DDS_EXPORT\n")
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
cunit_ddsrt PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>")
|
||||
393
src/ddsrt/tests/atomics.c
Normal file
393
src/ddsrt/tests/atomics.c
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "CUnit/Test.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
|
||||
uint32_t _osuint32 = 0;
|
||||
uint64_t _osuint64 = 0;
|
||||
uintptr_t _osaddress = 0;
|
||||
ptrdiff_t _ptrdiff = 0;
|
||||
void * _osvoidp = (uintptr_t *)0;
|
||||
|
||||
CU_Test(ddsrt_atomics, load_store)
|
||||
{
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(5);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(5);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(5);
|
||||
volatile ddsrt_atomic_voidp_t voidp = DDSRT_ATOMIC_VOIDP_INIT((uintptr_t)5);
|
||||
|
||||
/* Test uint32 LD-ST */
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == 5); /* Returns contents of uint32 */
|
||||
ddsrt_atomic_st32 (&uint32, _osuint32); /* Writes os_uint32 into uint32 */
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == _osuint32);
|
||||
|
||||
/* Test uint64 LD-ST */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == 5);
|
||||
ddsrt_atomic_st64 (&uint64, _osuint64);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == _osuint64);
|
||||
#endif
|
||||
|
||||
/* Test uintptr LD-ST */
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == 5);
|
||||
ddsrt_atomic_stptr (&uintptr, _osaddress);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == _osaddress);
|
||||
|
||||
/* Test uintvoidp LD-ST */
|
||||
CU_ASSERT (ddsrt_atomic_ldvoidp (&voidp) == (uintptr_t*)5);
|
||||
ddsrt_atomic_stvoidp (&voidp, _osvoidp);
|
||||
CU_ASSERT (ddsrt_atomic_ldvoidp (&voidp) == (uintptr_t*)_osvoidp);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_atomics, compare_and_swap)
|
||||
{
|
||||
/* Compare and Swap if (ptr == expected) { ptr = newval; } */
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(0);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(0);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(0);
|
||||
volatile ddsrt_atomic_voidp_t uintvoidp = DDSRT_ATOMIC_VOIDP_INIT((uintptr_t)0);
|
||||
_osuint32 = 1;
|
||||
_osuint64 = 1;
|
||||
_osaddress = 1;
|
||||
_osvoidp = (uintptr_t *)1;
|
||||
uint32_t expected = 0, newval = 5;
|
||||
uintptr_t addr_expected = 0, addr_newval = 5;
|
||||
void *void_expected = (uintptr_t*)0;
|
||||
void *void_newval = (uintptr_t*)5;
|
||||
int ret = 0;
|
||||
|
||||
/* Test ddsrt_atomic_cas32 */
|
||||
ret = ddsrt_atomic_cas32 (&uint32, expected, newval);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == newval && ret == 1);
|
||||
ddsrt_atomic_st32 (&uint32, _osuint32);
|
||||
ret = ddsrt_atomic_cas32 (&uint32, expected, newval);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) != newval && ret == 0);
|
||||
|
||||
/* Test ddsrt_atomic_cas64 */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ret = ddsrt_atomic_cas64 (&uint64, expected, newval);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == newval && ret == 1);
|
||||
ddsrt_atomic_st64 (&uint64, _osuint64);
|
||||
ret = ddsrt_atomic_cas64 (&uint64, expected, newval);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) != newval && ret == 0);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_casptr */
|
||||
ret = ddsrt_atomic_casptr (&uintptr, addr_expected, addr_newval);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == addr_newval && ret == 1);
|
||||
ddsrt_atomic_stptr (&uintptr, _osaddress);
|
||||
ret = ddsrt_atomic_casptr (&uintptr, addr_expected, addr_newval);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) != addr_newval && ret == 0);
|
||||
|
||||
/* Test ddsrt_atomic_casvoidp */
|
||||
ret = ddsrt_atomic_casvoidp (&uintvoidp, void_expected, void_newval);
|
||||
CU_ASSERT (ddsrt_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)void_newval && ret == 1);
|
||||
ddsrt_atomic_stvoidp (&uintvoidp, _osvoidp);
|
||||
ret = ddsrt_atomic_casvoidp (&uintvoidp, void_expected, void_newval);
|
||||
CU_ASSERT (ddsrt_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)1 && ret == 0);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_atomics, increment)
|
||||
{
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(0);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(0);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(0);
|
||||
_osuint32 = 0;
|
||||
_osuint64 = 0;
|
||||
_osaddress = 0;
|
||||
_osvoidp = (uintptr_t *)0;
|
||||
|
||||
/* Test os_inc32 */
|
||||
ddsrt_atomic_inc32 (&uint32);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == 1);
|
||||
|
||||
/* Test os_inc64 */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_inc64 (&uint64);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == 1);
|
||||
#endif
|
||||
|
||||
/* Test os_incptr */
|
||||
ddsrt_atomic_incptr (&uintptr);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == 1);
|
||||
|
||||
/* Test ddsrt_atomic_inc32_nv */
|
||||
ddsrt_atomic_st32 (&uint32, _osuint32);
|
||||
CU_ASSERT (ddsrt_atomic_inc32_nv (&uint32) == 1);
|
||||
|
||||
/* Test ddsrt_atomic_inc64_nv */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_st64 (&uint64, _osuint64);
|
||||
CU_ASSERT (ddsrt_atomic_inc64_nv (&uint64) == 1);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_incptr_nv */
|
||||
ddsrt_atomic_stptr (&uintptr, _osaddress);
|
||||
CU_ASSERT (ddsrt_atomic_incptr_nv(&uintptr) == 1);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_atomics, decrement)
|
||||
{
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(1);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(1);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(1);
|
||||
_osuint32 = 1;
|
||||
_osuint64 = 1;
|
||||
_osaddress = 1;
|
||||
_osvoidp = (uintptr_t *)1;
|
||||
|
||||
/* Test ddsrt_atomic_dec32 */
|
||||
ddsrt_atomic_dec32 (&uint32);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == 0);
|
||||
|
||||
/* Test ddsrt_atomic_dec64 */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_dec64 (&uint64);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == 0);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_decptr */
|
||||
ddsrt_atomic_decptr (&uintptr);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == 0);
|
||||
|
||||
/* Test ddsrt_atomic_dec32_nv */
|
||||
ddsrt_atomic_st32 (&uint32, _osuint32);
|
||||
CU_ASSERT (ddsrt_atomic_dec32_nv (&uint32) == 0);
|
||||
|
||||
/* Test ddsrt_atomic_dec64_nv */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_st64 (&uint64, _osuint64);
|
||||
CU_ASSERT (ddsrt_atomic_dec64_nv (&uint64) == 0);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_decptr_nv */
|
||||
ddsrt_atomic_stptr (&uintptr, _osaddress);
|
||||
CU_ASSERT (ddsrt_atomic_decptr_nv(&uintptr) == 0);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_atomics, add)
|
||||
{
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(1);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(1);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(1);
|
||||
volatile ddsrt_atomic_voidp_t uintvoidp = DDSRT_ATOMIC_VOIDP_INIT((uintptr_t)1);
|
||||
_osuint32 = 2;
|
||||
_osuint64 = 2;
|
||||
_osaddress = 2;
|
||||
_ptrdiff = 2;
|
||||
|
||||
/* Test ddsrt_atomic_add32 */
|
||||
ddsrt_atomic_add32 (&uint32, _osuint32);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_add64 */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_add64 (&uint64, _osuint64);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == 3);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_addptr */
|
||||
ddsrt_atomic_addptr (&uintptr, _osaddress);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_addvoidp */
|
||||
ddsrt_atomic_addvoidp (&uintvoidp, _ptrdiff);
|
||||
CU_ASSERT (ddsrt_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)3);
|
||||
|
||||
/* Test ddsrt_atomic_add32_nv */
|
||||
ddsrt_atomic_st32 (&uint32, 1);
|
||||
CU_ASSERT (ddsrt_atomic_add32_nv (&uint32, _osuint32) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_add64_nv */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_st64 (&uint64, 1);
|
||||
CU_ASSERT (ddsrt_atomic_add64_nv (&uint64, _osuint64) == 3);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_addptr_nv */
|
||||
ddsrt_atomic_stptr (&uintptr, 1);
|
||||
CU_ASSERT (ddsrt_atomic_addptr_nv (&uintptr, _osaddress) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_addvoidp_nv */
|
||||
ddsrt_atomic_stvoidp (&uintvoidp, (uintptr_t*)1);
|
||||
CU_ASSERT (ddsrt_atomic_addvoidp_nv (&uintvoidp, _ptrdiff) == (uintptr_t*)3);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_atomics, subtract)
|
||||
{
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(5);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(5);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(5);
|
||||
volatile ddsrt_atomic_voidp_t uintvoidp = DDSRT_ATOMIC_VOIDP_INIT((uintptr_t)5);
|
||||
_osuint32 = 2;
|
||||
_osuint64 = 2;
|
||||
_osaddress = 2;
|
||||
_ptrdiff = 2;
|
||||
|
||||
/* Test ddsrt_atomic_sub32 */
|
||||
ddsrt_atomic_sub32 (&uint32, _osuint32);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_sub64 */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_sub64 (&uint64, _osuint64);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == 3);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_subptr */
|
||||
ddsrt_atomic_subptr (&uintptr, _osaddress);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_subvoidp */
|
||||
ddsrt_atomic_subvoidp (&uintvoidp, _ptrdiff);
|
||||
CU_ASSERT (ddsrt_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)3);
|
||||
|
||||
/* Test ddsrt_atomic_sub32_nv */
|
||||
ddsrt_atomic_st32 (&uint32, 5);
|
||||
CU_ASSERT (ddsrt_atomic_sub32_nv (&uint32, _osuint32) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_sub64_nv */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_st64 (&uint64, 5);
|
||||
CU_ASSERT (ddsrt_atomic_sub64_nv (&uint64, _osuint64) == 3);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_subptr_nv */
|
||||
ddsrt_atomic_stptr (&uintptr, 5);
|
||||
CU_ASSERT (ddsrt_atomic_subptr_nv (&uintptr, _osaddress) == 3);
|
||||
|
||||
/* Test ddsrt_atomic_subvoidp_nv */
|
||||
ddsrt_atomic_stvoidp (&uintvoidp, (uintptr_t*)5);
|
||||
CU_ASSERT (ddsrt_atomic_subvoidp_nv (&uintvoidp, _ptrdiff) == (void *)3);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_atomics, and)
|
||||
{
|
||||
/* AND Operation:
|
||||
|
||||
150 010010110
|
||||
500 111110100
|
||||
|
||||
148 010010100 */
|
||||
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(150);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(150);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(150);
|
||||
_osuint32 = 500;
|
||||
_osuint64 = 500;
|
||||
_osaddress = 500;
|
||||
|
||||
/* Test ddsrt_atomic_and32 */
|
||||
ddsrt_atomic_and32 (&uint32, _osuint32);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == 148);
|
||||
|
||||
/* Test ddsrt_atomic_and64 */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_and64 (&uint64, _osuint64);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == 148);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_andptr */
|
||||
ddsrt_atomic_andptr (&uintptr, _osaddress);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == 148);
|
||||
|
||||
/* Test ddsrt_atomic_and32_ov */
|
||||
CU_ASSERT (ddsrt_atomic_and32_ov (&uint32, _osuint32) == 148);
|
||||
|
||||
/* Test ddsrt_atomic_and64_ov */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
CU_ASSERT (ddsrt_atomic_and64_ov (&uint64, _osuint64) == 148);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_andptr_ov */
|
||||
CU_ASSERT (ddsrt_atomic_andptr_ov (&uintptr, _osaddress) == 148);
|
||||
|
||||
/* Test ddsrt_atomic_and32_nv */
|
||||
CU_ASSERT (ddsrt_atomic_and32_nv (&uint32, _osuint32) == 148);
|
||||
|
||||
/* Test ddsrt_atomic_and64_nv */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
CU_ASSERT (ddsrt_atomic_and64_nv (&uint64, _osuint64) == 148);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_andptr_nv */
|
||||
CU_ASSERT (ddsrt_atomic_andptr_nv (&uintptr, _osaddress) == 148);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_atomics, or)
|
||||
{
|
||||
/* OR Operation:
|
||||
|
||||
150 010010110
|
||||
500 111110100
|
||||
|
||||
502 111110110 */
|
||||
|
||||
volatile ddsrt_atomic_uint32_t uint32 = DDSRT_ATOMIC_UINT32_INIT(150);
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
volatile ddsrt_atomic_uint64_t uint64 = DDSRT_ATOMIC_UINT64_INIT(150);
|
||||
#endif
|
||||
volatile ddsrt_atomic_uintptr_t uintptr = DDSRT_ATOMIC_UINTPTR_INIT(150);
|
||||
_osuint32 = 500;
|
||||
_osuint64 = 500;
|
||||
_osaddress = 500;
|
||||
|
||||
/* Test ddsrt_atomic_or32 */
|
||||
ddsrt_atomic_or32 (&uint32, _osuint32);
|
||||
CU_ASSERT (ddsrt_atomic_ld32 (&uint32) == 502);
|
||||
|
||||
/* Test ddsrt_atomic_or64 */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
ddsrt_atomic_or64 (&uint64, _osuint64);
|
||||
CU_ASSERT (ddsrt_atomic_ld64 (&uint64) == 502);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_orptr */
|
||||
ddsrt_atomic_orptr (&uintptr, _osaddress);
|
||||
CU_ASSERT (ddsrt_atomic_ldptr (&uintptr) == 502);
|
||||
|
||||
/* Test ddsrt_atomic_or32_ov */
|
||||
CU_ASSERT (ddsrt_atomic_or32_ov (&uint32, _osuint32) == 502);
|
||||
|
||||
/* Test ddsrt_atomic_or64_ov */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
CU_ASSERT (ddsrt_atomic_or64_ov (&uint64, _osuint64) == 502);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_orptr_ov */
|
||||
CU_ASSERT (ddsrt_atomic_orptr_ov (&uintptr, _osaddress) == 502);
|
||||
|
||||
/* Test ddsrt_atomic_or32_nv */
|
||||
CU_ASSERT (ddsrt_atomic_or32_nv (&uint32, _osuint32) == 502);
|
||||
|
||||
/* Test ddsrt_atomic_or64_nv */
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
CU_ASSERT (ddsrt_atomic_or64_nv (&uint64, _osuint64) == 502);
|
||||
#endif
|
||||
|
||||
/* Test ddsrt_atomic_orptr_nv */
|
||||
CU_ASSERT (ddsrt_atomic_orptr_nv (&uintptr, _osaddress) == 502);
|
||||
}
|
||||
98
src/ddsrt/tests/environ.c
Normal file
98
src/ddsrt/tests/environ.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "CUnit/Theory.h"
|
||||
#include "dds/ddsrt/environ.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_environ, bad_name) = {
|
||||
CU_DataPoints(const char *, "", "foo=")
|
||||
};
|
||||
|
||||
CU_Theory((const char *name), ddsrt_environ, bad_name)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
static const char value[] = "bar";
|
||||
static char dummy[] = "foobar";
|
||||
char *ptr;
|
||||
|
||||
rc = ddsrt_setenv(name, value);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_BAD_PARAMETER);
|
||||
rc = ddsrt_unsetenv(name);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_BAD_PARAMETER);
|
||||
ptr = dummy;
|
||||
rc = ddsrt_getenv(name, &ptr);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_BAD_PARAMETER);
|
||||
CU_ASSERT_PTR_EQUAL(ptr, dummy);
|
||||
}
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4996)
|
||||
CU_Test(ddsrt_environ, setenv)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
static const char name[] = "foo";
|
||||
static char value[] = "bar";
|
||||
char *ptr;
|
||||
|
||||
rc = ddsrt_setenv(name, value);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
ptr = getenv(name);
|
||||
CU_ASSERT_PTR_NOT_NULL(ptr);
|
||||
CU_ASSERT_STRING_EQUAL(ptr, "bar");
|
||||
/* Ensure value is copied into the environment. */
|
||||
value[2] = 'z';
|
||||
ptr = getenv(name);
|
||||
CU_ASSERT_PTR_NOT_NULL(ptr);
|
||||
CU_ASSERT_STRING_EQUAL(ptr, "bar");
|
||||
rc = ddsrt_setenv(name, "");
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
ptr = getenv(name);
|
||||
CU_ASSERT_PTR_NULL(ptr);
|
||||
}
|
||||
DDSRT_WARNING_MSVC_ON(4996)
|
||||
|
||||
CU_Test(ddsrt_environ, getenv)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
static const char name[] = "foo";
|
||||
static const char value[] = "bar";
|
||||
static char dummy[] = "foobar";
|
||||
char *ptr;
|
||||
|
||||
/* Ensure "not found" is returned. */
|
||||
rc = ddsrt_unsetenv(name);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
ptr = dummy;
|
||||
rc = ddsrt_getenv(name, &ptr);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_NOT_FOUND);
|
||||
CU_ASSERT_PTR_EQUAL(ptr, dummy);
|
||||
|
||||
/* Ensure "ok" is returned and value is what it should be. */
|
||||
rc = ddsrt_setenv(name, value);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
ptr = dummy;
|
||||
rc = ddsrt_getenv(name, &ptr);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_PTR_NOT_EQUAL(ptr, dummy);
|
||||
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL);
|
||||
if (ptr != NULL) {
|
||||
CU_ASSERT_STRING_EQUAL(ptr, "bar");
|
||||
}
|
||||
|
||||
/* Ensure environement is as it was. */
|
||||
rc = ddsrt_unsetenv(name);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
156
src/ddsrt/tests/heap.c
Normal file
156
src/ddsrt/tests/heap.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "CUnit/Test.h"
|
||||
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
|
||||
CU_Init(ddsrt_heap)
|
||||
{
|
||||
ddsrt_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Clean(ddsrt_heap)
|
||||
{
|
||||
ddsrt_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const size_t allocsizes[] = {0, 1, 2, 3, 4, 5, 10, 20, 257, 1024};
|
||||
static const size_t nof_allocsizes = sizeof allocsizes / sizeof *allocsizes;
|
||||
|
||||
CU_Test(ddsrt_heap, malloc)
|
||||
{
|
||||
for(size_t i = 0; i < nof_allocsizes; i++) {
|
||||
for(size_t j = 0; j < nof_allocsizes; j++) {
|
||||
size_t s = allocsizes[i] * allocsizes[j]; /* Allocates up to 1MB */
|
||||
void *ptr = ddsrt_malloc(s);
|
||||
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL); /* ddsrt_malloc is supposed to abort on failure */
|
||||
memset(ptr, 0, s); /* This potentially segfaults if the actual allocated block is too small */
|
||||
ddsrt_free(ptr);
|
||||
}
|
||||
}
|
||||
CU_PASS("ddsrt_malloc");
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_heap, calloc)
|
||||
{
|
||||
for(size_t i = 0; i < nof_allocsizes; i++) {
|
||||
for(size_t j = 0; j < nof_allocsizes; j++) {
|
||||
char *ptr = ddsrt_calloc(allocsizes[i], allocsizes[j]);
|
||||
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL); /* ddsrt_calloc is supposed to abort on failure */
|
||||
if(allocsizes[i] * allocsizes[j] > 0) {
|
||||
CU_ASSERT (ptr[0] == 0 && !memcmp(ptr, ptr + 1, (allocsizes[i] * allocsizes[j]) - 1)); /* ddsrt_calloc should memset properly */
|
||||
}
|
||||
ddsrt_free(ptr);
|
||||
}
|
||||
}
|
||||
CU_PASS("ddsrt_calloc");
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_heap, realloc)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
size_t unchanged, s, prevs = 0;
|
||||
|
||||
for(size_t i = 0; i < nof_allocsizes; i++) {
|
||||
for(size_t j = 0; j < nof_allocsizes; j++) {
|
||||
s = allocsizes[i] * allocsizes[j]; /* Allocates up to 1MB */
|
||||
printf("ddsrt_realloc(%p) %zu -> %zu\n", ptr, prevs, s);
|
||||
ptr = ddsrt_realloc(ptr, s);
|
||||
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL); /* ddsrt_realloc is supposed to abort on failure */
|
||||
unchanged = (prevs < s) ? prevs : s;
|
||||
if(unchanged) {
|
||||
CU_ASSERT (ptr[0] == 1 && !memcmp(ptr, ptr + 1, unchanged - 1)); /* ddsrt_realloc shouldn't change memory */
|
||||
}
|
||||
memset(ptr, 1, s); /* This potentially segfaults if the actual allocated block is too small */
|
||||
prevs = s;
|
||||
}
|
||||
}
|
||||
ddsrt_free(ptr);
|
||||
CU_PASS("ddsrt_realloc");
|
||||
}
|
||||
|
||||
static const size_t allocsizes_s[] = {0, 1, 2, 3, 4, 5, 10, 20, 257, 1024, 8192};
|
||||
static const size_t nof_allocsizes_s = sizeof allocsizes_s / sizeof *allocsizes_s;
|
||||
|
||||
CU_Test(ddsrt_heap, malloc_s)
|
||||
{
|
||||
for(size_t i = 0; i < nof_allocsizes_s; i++) {
|
||||
for(size_t j = 0; j < nof_allocsizes_s; j++) {
|
||||
size_t s = allocsizes_s[i] * allocsizes_s[j]; /* Allocates up to 8MB */
|
||||
void *ptr = ddsrt_malloc_s(s); /* If s == 0, ddsrt_malloc_s should still return a pointer */
|
||||
if(ptr) {
|
||||
memset(ptr, 0, s); /* This potentially segfaults if the actual allocated block is too small */
|
||||
} else if (s <= 16) {
|
||||
/* Failure to allocate can't be considered a test fault really,
|
||||
* except that a malloc(<=16) would fail is unlikely. */
|
||||
CU_FAIL("ddsrt_malloc_s(<=16) returned NULL");
|
||||
}
|
||||
ddsrt_free(ptr);
|
||||
}
|
||||
}
|
||||
CU_PASS("ddsrt_malloc_s");
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_heap, calloc_s)
|
||||
{
|
||||
for(size_t i = 0; i < nof_allocsizes_s; i++) {
|
||||
for(size_t j = 0; j < nof_allocsizes_s; j++) {
|
||||
size_t s = allocsizes_s[i] * allocsizes_s[j];
|
||||
char *ptr = ddsrt_calloc_s(allocsizes_s[i], allocsizes_s[j]); /* If either one is 0, ddsrt_calloc_s should still return a pointer */
|
||||
if(ptr) {
|
||||
if(s) {
|
||||
CU_ASSERT (ptr[0] == 0 && !memcmp(ptr, ptr + 1, s - 1)); /* malloc_0_s should memset properly */
|
||||
}
|
||||
} else if (s <= 16) {
|
||||
/* Failure to allocate can't be considered a test fault really,
|
||||
* except that a calloc(<=16) would fail is unlikely. */
|
||||
CU_FAIL("ddsrt_calloc_s(<=16) returned NULL");
|
||||
}
|
||||
ddsrt_free(ptr);
|
||||
}
|
||||
}
|
||||
CU_PASS("ddsrt_calloc_s");
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_heap, ddsrt_realloc_s)
|
||||
{
|
||||
char *newptr, *ptr = NULL;
|
||||
size_t unchanged, s, prevs = 0;
|
||||
|
||||
for(size_t i = 0; i < nof_allocsizes_s; i++) {
|
||||
for(size_t j = 0; j < nof_allocsizes_s; j++) {
|
||||
s = allocsizes_s[i] * allocsizes_s[j]; /* Allocates up to 8MB */
|
||||
newptr = ddsrt_realloc_s(ptr, s);
|
||||
printf("%p = ddsrt_realloc_s(%p) %zu -> %zu\n", newptr, ptr, prevs, s);
|
||||
if (s <= 16) {
|
||||
/* Failure to allocate can't be considered a test fault really,
|
||||
* except that a ddsrt_realloc_s(0 < s <=16) would fail is unlikely. */
|
||||
CU_ASSERT_PTR_NOT_EQUAL(newptr, NULL);
|
||||
}
|
||||
if(newptr){
|
||||
unchanged = (prevs < s) ? prevs : s;
|
||||
if(unchanged) {
|
||||
CU_ASSERT (newptr[0] == 1 && !memcmp(newptr, newptr + 1, unchanged - 1)); /* ddsrt_realloc_s shouldn't change memory */
|
||||
}
|
||||
memset(newptr, 1, s); /* This potentially segfaults if the actual allocated block is too small */
|
||||
}
|
||||
prevs = s;
|
||||
ptr = newptr;
|
||||
}
|
||||
}
|
||||
ddsrt_free(ptr);
|
||||
CU_PASS("ddsrt_realloc_s");
|
||||
}
|
||||
187
src/ddsrt/tests/ifaddrs.c
Normal file
187
src/ddsrt/tests/ifaddrs.c
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "CUnit/Test.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/ifaddrs.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
/* FIXME: It's not possible to predict what network interfaces are available
|
||||
on a given host. To properly test all combinations the abstracted
|
||||
operating system functions must be mocked. */
|
||||
|
||||
/* FIXME: It's possible that IPv6 is available in the network stack, but
|
||||
disabled in the kernel. Travis CI for example has build environments
|
||||
that do not have IPv6 enabled. */
|
||||
|
||||
#ifdef DDSRT_HAVE_IPV6
|
||||
static int ipv6_enabled = 1;
|
||||
#endif
|
||||
|
||||
CU_Init(ddsrt_getifaddrs)
|
||||
{
|
||||
ddsrt_init();
|
||||
|
||||
#ifdef DDSRT_HAVE_IPV6
|
||||
#ifdef __linux
|
||||
FILE *fh;
|
||||
const char *const *path;
|
||||
static const char *const paths[] = {
|
||||
"/proc/sys/net/ipv6/conf/all/disable_ipv6",
|
||||
"/proc/sys/net/ipv6/conf/default/disable_ipv6",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (path = paths; ipv6_enabled == 1 && *path != NULL; path++) {
|
||||
if ((fh = fopen(*path, "r")) != NULL) {
|
||||
ipv6_enabled = (fgetc(fh) == '0');
|
||||
fclose(fh);
|
||||
fh = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* __linux */
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Clean(ddsrt_getifaddrs)
|
||||
{
|
||||
ddsrt_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume every test machine has at least one IPv4 enabled interface. This
|
||||
simple test verifies an interface can at least be found and that the
|
||||
IFF_LOOPBACK flags are properly set. */
|
||||
CU_Test(ddsrt_getifaddrs, ipv4)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
int seen = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
const int afs[] = { AF_INET, DDSRT_AF_TERM };
|
||||
|
||||
ret = ddsrt_getifaddrs(&ifa_root, afs);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
for (ifa = ifa_root; ifa; ifa = ifa->next) {
|
||||
CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL);
|
||||
CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET);
|
||||
if (ifa->addr->sa_family == AF_INET) {
|
||||
if (ifa->flags & IFF_LOOPBACK) {
|
||||
CU_ASSERT(ddsrt_sockaddr_isloopback(ifa->addr));
|
||||
} else {
|
||||
CU_ASSERT(!ddsrt_sockaddr_isloopback(ifa->addr));
|
||||
}
|
||||
seen = 1;
|
||||
}
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(seen, 1);
|
||||
ddsrt_freeifaddrs(ifa_root);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_getifaddrs, null_filter)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
int cnt = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
|
||||
ret = ddsrt_getifaddrs(&ifa_root, NULL);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
for (ifa = ifa_root; ifa; ifa = ifa->next) {
|
||||
CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
CU_ASSERT(cnt > 0);
|
||||
ddsrt_freeifaddrs(ifa_root);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_getifaddrs, empty_filter)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
ddsrt_ifaddrs_t *ifa_root;
|
||||
const int afs[] = { DDSRT_AF_TERM };
|
||||
|
||||
ret = ddsrt_getifaddrs(&ifa_root, afs);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_PTR_EQUAL(ifa_root, NULL);
|
||||
ddsrt_freeifaddrs(ifa_root);
|
||||
}
|
||||
|
||||
#ifdef DDSRT_HAVE_IPV6
|
||||
CU_Test(ddsrt_getifaddrs, ipv6)
|
||||
{
|
||||
if (ipv6_enabled == 1) {
|
||||
dds_retcode_t ret;
|
||||
int have_ipv6 = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
const int afs[] = { AF_INET6, DDSRT_AF_TERM };
|
||||
|
||||
ret = ddsrt_getifaddrs(&ifa_root, afs);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
for (ifa = ifa_root; ifa; ifa = ifa->next) {
|
||||
CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL);
|
||||
CU_ASSERT_EQUAL(ifa->addr->sa_family, AF_INET6);
|
||||
if (ifa->addr->sa_family == AF_INET6) {
|
||||
have_ipv6 = 1;
|
||||
/* macOS assigns a link-local address to the loopback interface, so
|
||||
the loopback address must be assigned to the loopback interface,
|
||||
but the loopback interface can have addresses other than the
|
||||
loopback address assigned. */
|
||||
if (ddsrt_sockaddr_isloopback(ifa->addr)) {
|
||||
CU_ASSERT(ifa->flags & IFF_LOOPBACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(have_ipv6, 1);
|
||||
ddsrt_freeifaddrs(ifa_root);
|
||||
CU_PASS("IPv6 enabled in test environment");
|
||||
} else {
|
||||
CU_PASS("IPv6 disabled in test environment");
|
||||
}
|
||||
}
|
||||
|
||||
/* Assume at least one IPv4 and one IPv6 interface are available when IPv6 is
|
||||
available on the platform. */
|
||||
CU_Test(ddsrt_getifaddrs, ipv4_n_ipv6)
|
||||
{
|
||||
if (ipv6_enabled == 1) {
|
||||
dds_retcode_t ret;
|
||||
int have_ipv4 = 0;
|
||||
int have_ipv6 = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
const int afs[] = { AF_INET, AF_INET6, DDSRT_AF_TERM };
|
||||
|
||||
ret = ddsrt_getifaddrs(&ifa_root, afs);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
for (ifa = ifa_root; ifa; ifa = ifa->next) {
|
||||
CU_ASSERT_PTR_NOT_EQUAL_FATAL(ifa->addr, NULL);
|
||||
CU_ASSERT(ifa->addr->sa_family == AF_INET ||
|
||||
ifa->addr->sa_family == AF_INET6);
|
||||
if (ifa->addr->sa_family == AF_INET) {
|
||||
have_ipv4 = 1;
|
||||
} else if (ifa->addr->sa_family == AF_INET6) {
|
||||
have_ipv6 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(have_ipv4, 1);
|
||||
CU_ASSERT_EQUAL(have_ipv6, 1);
|
||||
ddsrt_freeifaddrs(ifa_root);
|
||||
CU_PASS("IPv6 enabled in test environment");
|
||||
} else {
|
||||
CU_PASS("IPv6 disabled in test environment");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
366
src/ddsrt/tests/log.c
Normal file
366
src/ddsrt/tests/log.c
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <pthread.h>
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#include "CUnit/Test.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
static FILE *fh = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
|
||||
/* Windows does not support opening a stream to a buffer like fmemopen on
|
||||
* Linux does. A temporary file that will never be flushed to disk is created
|
||||
* instead. See the link below for more detail.
|
||||
*
|
||||
* https://blogs.msdn.microsoft.com/larryosterman/2004/04/19/its-only-temporary/
|
||||
*/
|
||||
|
||||
FILE *fmemopen(void *buf, size_t size, const char *mode)
|
||||
{
|
||||
int err = 0;
|
||||
int fd = -1;
|
||||
DWORD ret;
|
||||
FILE *fh = NULL;
|
||||
HANDLE hdl = INVALID_HANDLE_VALUE;
|
||||
/* GetTempFileName will fail if the directory is be longer than MAX_PATH-14
|
||||
characters */
|
||||
char tmpdir[(MAX_PATH + 1) - 14];
|
||||
char tmpfile[MAX_PATH + 1];
|
||||
static const int max = 1000;
|
||||
static const char pfx[] = "cyclone"; /* Up to first three are used. */
|
||||
|
||||
(void)buf;
|
||||
(void)size;
|
||||
|
||||
ret = GetTempPath(sizeof(tmpdir), tmpdir);
|
||||
if (ret == 0) {
|
||||
err = GetLastError();
|
||||
} else if (ret > sizeof(tmpdir)) {
|
||||
err = ENOMEM;
|
||||
}
|
||||
|
||||
if (GetTempFileName(tmpdir, pfx, 0, tmpfile) == 0) {
|
||||
err = GetLastError();
|
||||
assert(err != ERROR_BUFFER_OVERFLOW);
|
||||
} else {
|
||||
/* The combination of FILE_ATTRIBUTE_TEMPORARY and
|
||||
FILE_FLAG_DELETE_ON_CLOSE hints to the filesystem that the file should
|
||||
never be flushed to disk. */
|
||||
hdl = CreateFile(
|
||||
tmpfile,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY,
|
||||
NULL);
|
||||
if (hdl == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
} else {
|
||||
DDSRT_WARNING_MSVC_OFF(4996);
|
||||
if ((fd = _open_osfhandle((intptr_t)hdl, _O_APPEND)) == -1) {
|
||||
/* errno set by _open_osfhandle. */
|
||||
CloseHandle(hdl);
|
||||
} else if ((fh = fdopen(fd, mode)) == NULL) {
|
||||
/* errno set by fdopen. */
|
||||
_close(fd); /* Automatically closes underlying handle. */
|
||||
} else {
|
||||
return fh;
|
||||
}
|
||||
DDSRT_WARNING_MSVC_ON(4996);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
static void count(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
(void)data;
|
||||
*(int *)ptr += 1;
|
||||
}
|
||||
|
||||
static void copy(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
*(char **)ptr = ddsrt_strdup(data->message);
|
||||
}
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
fh = fmemopen(NULL, 1024, "wb+");
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(fh);
|
||||
}
|
||||
|
||||
static void teardown(void)
|
||||
{
|
||||
(void)fclose(fh);
|
||||
}
|
||||
|
||||
/* By default only DDS_LC_FATAL and DDS_LC_ERROR are set. This means setting a
|
||||
trace sink should not have any effect, because no trace categories are
|
||||
enabled. The message should end up in the log file. */
|
||||
CU_Test(dds_log, only_log_file, .init=setup, .fini=teardown)
|
||||
{
|
||||
char buf[1024], *ptr;
|
||||
int cnt = 0;
|
||||
size_t nbytes;
|
||||
|
||||
dds_set_log_file(fh);
|
||||
dds_set_trace_sink(&count, &cnt);
|
||||
DDS_ERROR("foo%s\n", "bar");
|
||||
(void)fseek(fh, 0L, SEEK_SET);
|
||||
nbytes = fread(buf, 1, sizeof(buf) - 1, fh);
|
||||
/* At least foobar should have been printed to the log file. */
|
||||
CU_ASSERT_FATAL(nbytes > 6);
|
||||
buf[nbytes] = '\0';
|
||||
ptr = strstr(buf, "foobar\n");
|
||||
CU_ASSERT_PTR_NOT_NULL(ptr);
|
||||
/* No trace categories are enabled by default, verify trace callback was
|
||||
not invoked. */
|
||||
CU_ASSERT_EQUAL(cnt, 0);
|
||||
}
|
||||
|
||||
/* Messages must be printed to the trace file if at least one trace category
|
||||
is enabled. Messages must not be written twice if the trace file is the
|
||||
same as the log file. */
|
||||
CU_Test(dds_log, same_file, .init=setup, .fini=teardown)
|
||||
{
|
||||
char buf[1024], *ptr;
|
||||
size_t nbytes;
|
||||
|
||||
dds_set_log_mask(DDS_LC_ALL);
|
||||
dds_set_log_file(fh);
|
||||
dds_set_trace_file(fh);
|
||||
DDS_ERROR("foo%s\n", "bar");
|
||||
(void)fseek(fh, 0L, SEEK_SET);
|
||||
nbytes = fread(buf, 1, sizeof(buf) - 1, fh);
|
||||
/* At least foobar should have been written to the trace file. */
|
||||
CU_ASSERT_FATAL(nbytes > 6);
|
||||
buf[nbytes] = '\0';
|
||||
ptr = strstr(buf, "foobar\n");
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(ptr);
|
||||
/* The message should only have been printed once, verify foobar does not
|
||||
occur again. */
|
||||
ptr = strstr(ptr + 1, "foobar\n");
|
||||
CU_ASSERT_PTR_NULL(ptr);
|
||||
}
|
||||
|
||||
/* The sinks are considered to be the same only if the callback and userdata
|
||||
both are an exact match. If the userdata is different, the function should
|
||||
be called twice for log messages. */
|
||||
CU_Test(dds_log, same_sink_function)
|
||||
{
|
||||
int log_cnt = 0, trace_cnt = 0;
|
||||
|
||||
dds_set_log_mask(DDS_LC_ALL);
|
||||
dds_set_log_sink(&count, &log_cnt);
|
||||
dds_set_trace_sink(&count, &trace_cnt);
|
||||
DDS_ERROR("foo%s\n", "bar");
|
||||
CU_ASSERT_EQUAL(log_cnt, 1);
|
||||
CU_ASSERT_EQUAL(trace_cnt, 1);
|
||||
}
|
||||
|
||||
CU_Test(dds_log, exact_same_sink)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
dds_set_log_mask(DDS_LC_ALL);
|
||||
dds_set_log_sink(&count, &cnt);
|
||||
dds_set_trace_sink(&count, &cnt);
|
||||
DDS_ERROR("foo%s\n", "bar");
|
||||
CU_ASSERT_EQUAL(cnt, 1);
|
||||
}
|
||||
|
||||
/* The log file must be restored if the sink is unregistered, verify the log
|
||||
file is not used while the sink is registered. Verify use of the log file is
|
||||
restored again when the sink is unregistered. */
|
||||
CU_Test(dds_log, no_sink, .init=setup, .fini=teardown)
|
||||
{
|
||||
int ret;
|
||||
char buf[1024], *ptr = NULL;
|
||||
size_t cnt[2] = {0, 0};
|
||||
|
||||
/* Set the destination log file and verify the message is written. */
|
||||
dds_set_log_file(fh);
|
||||
DDS_ERROR("foobar\n");
|
||||
ret = fseek(fh, 0L, SEEK_SET);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 0);
|
||||
buf[0] = '\0';
|
||||
cnt[0] = fread(buf, 1, sizeof(buf) - 1, fh);
|
||||
buf[cnt[0]] = '\0';
|
||||
ptr = strstr(buf, "foobar\n");
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(ptr);
|
||||
|
||||
/* Register a custom sink and verify it receives the message. */
|
||||
ptr = NULL;
|
||||
dds_set_log_sink(©, &ptr);
|
||||
DDS_ERROR("foobaz\n");
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(ptr);
|
||||
CU_ASSERT(strcmp(ptr, "foobaz\n") == 0);
|
||||
ddsrt_free(ptr);
|
||||
ptr = NULL;
|
||||
/* Verify it has not been written to the stream. */
|
||||
ret = fseek(fh, 0L, SEEK_SET);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 0);
|
||||
buf[0] = '\0';
|
||||
cnt[1] = fread(buf, 1, sizeof(buf) - 1, fh);
|
||||
buf[cnt[1]] = '\0';
|
||||
ptr = strstr(buf, "foobaz\n");
|
||||
CU_ASSERT_PTR_NULL_FATAL(ptr);
|
||||
|
||||
/* Unregister the custom sink and verify the default is restored. */
|
||||
dds_set_log_sink(0, NULL);
|
||||
ret = fseek(fh, 0, SEEK_SET);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, 0);
|
||||
ptr = NULL;
|
||||
DDS_ERROR("foobaz\n");
|
||||
ret = fseek(fh, 0, SEEK_SET);
|
||||
CU_ASSERT_PTR_NULL(ptr);
|
||||
if (ptr != NULL) {
|
||||
ddsrt_free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
buf[0]= '\0';
|
||||
cnt[1] = fread(buf, 1, sizeof(buf) - 1, fh);
|
||||
#ifdef _WIN32
|
||||
/* Write on Windows appends. */
|
||||
CU_ASSERT_EQUAL(cnt[1], cnt[0] * 2);
|
||||
#else
|
||||
CU_ASSERT_EQUAL(cnt[1], cnt[0]);
|
||||
#endif
|
||||
buf[cnt[1]] = '\0';
|
||||
ptr = strstr(buf, "foobaz\n");
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(ptr);
|
||||
}
|
||||
|
||||
/* A newline terminates the message. Until that a newline is encountered, the
|
||||
messages must be concatenated in the buffer. The newline is replaced by a
|
||||
NULL byte if it is flushed to a sink. */
|
||||
CU_Test(dds_log, newline_terminates)
|
||||
{
|
||||
char *msg = NULL;
|
||||
|
||||
dds_set_log_sink(©, &msg);
|
||||
DDS_ERROR("foo");
|
||||
CU_ASSERT_PTR_NULL_FATAL(msg);
|
||||
DDS_ERROR("bar");
|
||||
CU_ASSERT_PTR_NULL_FATAL(msg);
|
||||
DDS_ERROR("baz\n");
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(msg);
|
||||
CU_ASSERT(strcmp(msg, "foobarbaz\n") == 0);
|
||||
ddsrt_free(msg);
|
||||
}
|
||||
|
||||
/* Nothing must be written unless a category is enabled. */
|
||||
CU_Test(dds_log, disabled_categories_discarded)
|
||||
{
|
||||
char *msg = NULL;
|
||||
|
||||
dds_set_log_sink(©, &msg);
|
||||
DDS_INFO("foobar\n");
|
||||
CU_ASSERT_PTR_NULL_FATAL(msg);
|
||||
dds_set_log_mask(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_INFO);
|
||||
DDS_INFO("foobar\n");
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(msg);
|
||||
CU_ASSERT(strcmp(msg, "foobar\n") == 0);
|
||||
ddsrt_free(msg);
|
||||
}
|
||||
|
||||
|
||||
static ddsrt_cond_t cond;
|
||||
static ddsrt_mutex_t mutex;
|
||||
|
||||
struct arg {
|
||||
ddsrt_cond_t *cond;
|
||||
ddsrt_mutex_t *mutex;
|
||||
dds_time_t stamp;
|
||||
dds_duration_t pause;
|
||||
};
|
||||
|
||||
static void dummy(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)data;
|
||||
}
|
||||
|
||||
static void block(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
(void)data;
|
||||
struct arg *arg = (struct arg *)ptr;
|
||||
ddsrt_mutex_lock(arg->mutex);
|
||||
arg->stamp = dds_time();
|
||||
ddsrt_cond_broadcast(arg->cond);
|
||||
ddsrt_mutex_unlock(arg->mutex);
|
||||
dds_sleepfor(arg->pause);
|
||||
}
|
||||
|
||||
static uint32_t run(void *ptr)
|
||||
{
|
||||
(void)ptr;
|
||||
|
||||
DDS_ERROR("foobar\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Log and trace sinks can be changed at runtime. However, the operation must
|
||||
be synchronous! Verify the dds_set_log_sink blocks while other threads
|
||||
reside in the log or trace sinks. */
|
||||
CU_Test(dds_log, synchronous_sink_changes)
|
||||
{
|
||||
struct arg arg;
|
||||
dds_time_t diff, stamp;
|
||||
ddsrt_thread_t tid;
|
||||
ddsrt_threadattr_t tattr;
|
||||
dds_retcode_t ret;
|
||||
|
||||
ddsrt_mutex_init(&mutex);
|
||||
ddsrt_cond_init(&cond);
|
||||
(void)memset(&arg, 0, sizeof(arg));
|
||||
arg.mutex = &mutex;
|
||||
arg.cond = &cond;
|
||||
arg.pause = 1000000;
|
||||
|
||||
ddsrt_mutex_lock(&mutex);
|
||||
dds_set_log_sink(&block, &arg);
|
||||
ddsrt_threadattr_init(&tattr);
|
||||
ret = ddsrt_thread_create(&tid, "foobar", &tattr, &run, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
ddsrt_cond_wait(&cond, &mutex);
|
||||
dds_set_log_sink(dummy, NULL);
|
||||
stamp = dds_time();
|
||||
|
||||
CU_ASSERT(arg.stamp < stamp);
|
||||
diff = stamp - arg.stamp;
|
||||
CU_ASSERT(arg.pause < diff);
|
||||
}
|
||||
325
src/ddsrt/tests/select.c
Normal file
325
src/ddsrt/tests/select.c
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "CUnit/Theory.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/sockets_priv.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
CU_Init(ddsrt_select)
|
||||
{
|
||||
ddsrt_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Clean(ddsrt_select)
|
||||
{
|
||||
ddsrt_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct timeval tv_init = { .tv_sec = -2, .tv_usec = -2 };
|
||||
|
||||
#define CU_ASSERT_TIMEVAL_EQUAL(tv, secs, usecs) \
|
||||
CU_ASSERT((tv.tv_sec == secs) && (tv.tv_usec == usecs))
|
||||
|
||||
/* Simple test to validate that duration to timeval conversion is correct. */
|
||||
CU_Test(ddsrt_select, duration_to_timeval)
|
||||
{
|
||||
struct timeval tv, *tvptr;
|
||||
dds_duration_t nsecs_max;
|
||||
dds_duration_t secs_max = DDSRT_MAX_INTEGER(ddsrt_tv_sec_t);
|
||||
dds_duration_t usecs_max = 999999;
|
||||
|
||||
if (DDS_INFINITY > secs_max) {
|
||||
CU_ASSERT_EQUAL_FATAL(secs_max, INT32_MAX);
|
||||
nsecs_max = DDS_INFINITY * secs_max;
|
||||
} else {
|
||||
CU_ASSERT_EQUAL_FATAL(secs_max, DDS_INFINITY);
|
||||
nsecs_max = DDS_INFINITY / DDS_NSECS_IN_SEC;
|
||||
}
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(INT64_MIN, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, 0, 0);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(INT64_MIN + 1, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, 0, 0);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(-2, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, 0, 0);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(-1, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, 0, 0);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(0, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, 0, 0);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(nsecs_max - 1, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, secs_max, usecs_max);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(nsecs_max, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, secs_max, usecs_max);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(nsecs_max + 1, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, secs_max, usecs_max);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(DDS_INFINITY - 1, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, &tv);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, secs_max, usecs_max);
|
||||
|
||||
tv = tv_init;
|
||||
tvptr = ddsrt_duration_to_timeval_ceil(DDS_INFINITY, &tv);
|
||||
CU_ASSERT_PTR_EQUAL(tvptr, NULL);
|
||||
CU_ASSERT_TIMEVAL_EQUAL(tv, 0, 0);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
dds_duration_t delay;
|
||||
dds_duration_t skew;
|
||||
ddsrt_socket_t sock;
|
||||
} thread_arg_t;
|
||||
|
||||
static void
|
||||
sockets_pipe(ddsrt_socket_t socks[2])
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
ddsrt_socket_t sock;
|
||||
int reuseaddr = 1;
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.sin_port = htons(54321);
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(socks);
|
||||
rc = ddsrt_socket(&sock, AF_INET, SOCK_STREAM, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
rc = ddsrt_setsockopt(
|
||||
sock, SOL_SOCKET, SO_REUSEADDR, (void*)&reuseaddr, sizeof(reuseaddr));
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
rc = ddsrt_socket(&socks[1], AF_INET, SOCK_STREAM, 0);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
rc = ddsrt_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
rc = ddsrt_listen(sock, 1);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
rc = ddsrt_connect(socks[1], (struct sockaddr *)&addr, sizeof(addr));
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
rc = ddsrt_accept(sock, NULL, NULL, &socks[0]);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
ddsrt_close(sock);
|
||||
}
|
||||
|
||||
static const char mesg[] = "foobar";
|
||||
|
||||
static uint32_t select_timeout_routine(void *ptr)
|
||||
{
|
||||
int cnt = -1;
|
||||
dds_retcode_t rc;
|
||||
dds_time_t before, after;
|
||||
dds_duration_t delay;
|
||||
fd_set rdset;
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
uint32_t res = 0;
|
||||
|
||||
FD_ZERO(&rdset);
|
||||
FD_SET(arg->sock, &rdset);
|
||||
|
||||
before = dds_time();
|
||||
rc = ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &cnt);
|
||||
after = dds_time();
|
||||
delay = after - before;
|
||||
|
||||
fprintf(stderr, "Waited for %"PRId64" (nanoseconds)\n", delay);
|
||||
fprintf(stderr, "Expected to wait %"PRId64" (nanoseconds)\n", arg->delay);
|
||||
fprintf(stderr, "ddsrt_select returned %d\n", rc);
|
||||
fprintf(stderr, "ddsrt_select reported %d ready\n", cnt);
|
||||
|
||||
if (rc == DDS_RETCODE_TIMEOUT) {
|
||||
res = (((after - delay) >= (arg->delay - arg->skew)) && (cnt == 0));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_select, timeout)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
ddsrt_socket_t socks[2];
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg;
|
||||
uint32_t res = 0;
|
||||
|
||||
sockets_pipe(socks);
|
||||
|
||||
arg.delay = DDS_MSECS(100);
|
||||
/* Allow the delay to be off by x microseconds (arbitrarily chosen) for
|
||||
systems with a really poor clock. This test is just to get some
|
||||
confidence that time calculation is not completely broken, it is by
|
||||
no means proof that time calculation is entirely correct! */
|
||||
arg.skew = DDS_MSECS(20);
|
||||
arg.sock = socks[0];
|
||||
|
||||
ddsrt_threadattr_init(&attr);
|
||||
rc = ddsrt_thread_create(&thr, "select_timeout", &attr, &select_timeout_routine, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
/* Allow the thread some time to get ready. */
|
||||
dds_sleepfor(arg.delay * 2);
|
||||
/* Send data to the read socket to avoid blocking indefinitely. */
|
||||
ssize_t sent = 0;
|
||||
rc = ddsrt_send(socks[1], mesg, sizeof(mesg), 0, &sent);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
rc = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
|
||||
(void)ddsrt_close(socks[0]);
|
||||
(void)ddsrt_close(socks[1]);
|
||||
}
|
||||
|
||||
static uint32_t recv_routine(void *ptr)
|
||||
{
|
||||
thread_arg_t *arg = (thread_arg_t*)ptr;
|
||||
|
||||
int nfds = 0;
|
||||
fd_set rdset;
|
||||
ssize_t rcvd = -1;
|
||||
char buf[sizeof(mesg)];
|
||||
|
||||
FD_ZERO(&rdset);
|
||||
FD_SET(arg->sock, &rdset);
|
||||
|
||||
(void)ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &nfds);
|
||||
|
||||
if (ddsrt_recv(arg->sock, buf, sizeof(buf), 0, &rcvd) == DDS_RETCODE_OK) {
|
||||
return (rcvd == sizeof(mesg) && strcmp(buf, mesg) == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_select, send_recv)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
ddsrt_socket_t socks[2];
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg;
|
||||
uint32_t res = 0;
|
||||
|
||||
sockets_pipe(socks);
|
||||
|
||||
arg.delay = DDS_SECS(1);
|
||||
arg.skew = 0;
|
||||
arg.sock = socks[0];
|
||||
|
||||
ddsrt_threadattr_init(&attr);
|
||||
rc = ddsrt_thread_create(&thr, "recv", &attr, &recv_routine, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
ssize_t sent = 0;
|
||||
rc = ddsrt_send(socks[1], mesg, sizeof(mesg), 0, &sent);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(sent, sizeof(mesg));
|
||||
|
||||
rc = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
|
||||
(void)ddsrt_close(socks[0]);
|
||||
(void)ddsrt_close(socks[1]);
|
||||
}
|
||||
|
||||
static uint32_t recvmsg_routine(void *ptr)
|
||||
{
|
||||
thread_arg_t *arg = (thread_arg_t*)ptr;
|
||||
|
||||
int nfds = 0;
|
||||
fd_set rdset;
|
||||
ssize_t rcvd = -1;
|
||||
char buf[sizeof(mesg)];
|
||||
ddsrt_msghdr_t msg;
|
||||
ddsrt_iovec_t iov;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof(buf);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
FD_ZERO(&rdset);
|
||||
FD_SET(arg->sock, &rdset);
|
||||
|
||||
(void)ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &nfds);
|
||||
|
||||
if (ddsrt_recvmsg(arg->sock, &msg, 0, &rcvd) == DDS_RETCODE_OK) {
|
||||
return (rcvd == sizeof(mesg) && strcmp(buf, mesg) == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_select, sendmsg_recvmsg)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
ddsrt_socket_t socks[2];
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg;
|
||||
uint32_t res = 0;
|
||||
|
||||
sockets_pipe(socks);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.sock = socks[0];
|
||||
|
||||
ddsrt_threadattr_init(&attr);
|
||||
rc = ddsrt_thread_create(&thr, "recvmsg", &attr, &recvmsg_routine, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
ssize_t sent = 0;
|
||||
ddsrt_msghdr_t msg;
|
||||
ddsrt_iovec_t iov;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
iov.iov_base = (void*)mesg;
|
||||
iov.iov_len = (ddsrt_iov_len_t)sizeof(mesg);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
rc = ddsrt_sendmsg(socks[1], &msg, 0, &sent);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(sent, sizeof(mesg));
|
||||
|
||||
rc = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
|
||||
(void)ddsrt_close(socks[0]);
|
||||
(void)ddsrt_close(socks[1]);
|
||||
}
|
||||
198
src/ddsrt/tests/socket.c
Normal file
198
src/ddsrt/tests/socket.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "CUnit/Theory.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/endian.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4305)
|
||||
#if DDSRT_ENDIAN == DDSRT_BIG_ENDIAN
|
||||
static const struct sockaddr_in ipv4_loopback =
|
||||
{ .sin_family = AF_INET, .sin_addr = { .s_addr = 0x7f000001 } };
|
||||
#else
|
||||
static const struct sockaddr_in ipv4_loopback =
|
||||
{ .sin_family = AF_INET, .sin_addr = { .s_addr = 0x0100007f } };
|
||||
#endif /* DDSRT_ENDIAN */
|
||||
DDSRT_WARNING_MSVC_ON(4305)
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
static const struct sockaddr_in6 ipv6_loopback =
|
||||
{ .sin6_family = AF_INET6, .sin6_addr = IN6ADDR_LOOPBACK_INIT };
|
||||
#endif
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
ddsrt_init();
|
||||
}
|
||||
|
||||
static void teardown(void)
|
||||
{
|
||||
ddsrt_fini();
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sockaddrfromstr, bad_family)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
struct sockaddr_storage sa;
|
||||
rc = ddsrt_sockaddrfromstr(AF_UNSPEC, "127.0.0.1", &sa);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
static void sockaddrfromstr_test(char *str, int af, dds_retcode_t exp)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
struct sockaddr_storage ss;
|
||||
rc = ddsrt_sockaddrfromstr(af, str, &ss);
|
||||
CU_ASSERT_EQUAL(rc, exp);
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
CU_ASSERT_EQUAL(ss.ss_family, af);
|
||||
}
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv4) = {
|
||||
CU_DataPoints(char *, "127.0.0.1", "0.0.0.0",
|
||||
"nip"),
|
||||
CU_DataPoints(int, AF_INET, AF_INET,
|
||||
AF_INET),
|
||||
CU_DataPoints(dds_retcode_t, DDS_RETCODE_OK, DDS_RETCODE_OK,
|
||||
DDS_RETCODE_BAD_PARAMETER)
|
||||
};
|
||||
|
||||
CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv4, .init=setup, .fini=teardown)
|
||||
{
|
||||
sockaddrfromstr_test(str, af, exp);
|
||||
}
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv6) = {
|
||||
CU_DataPoints(char *, "127.0.0.1", "::1",
|
||||
"::1", "::",
|
||||
"nip"),
|
||||
CU_DataPoints(int, AF_INET6, AF_INET6,
|
||||
AF_INET, AF_INET6,
|
||||
AF_INET6),
|
||||
CU_DataPoints(dds_retcode_t, DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK,
|
||||
DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK,
|
||||
DDS_RETCODE_BAD_PARAMETER)
|
||||
};
|
||||
|
||||
CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv6, .init=setup, .fini=teardown)
|
||||
{
|
||||
sockaddrfromstr_test(str, af, exp);
|
||||
}
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
|
||||
CU_Test(ddsrt_sockaddrtostr, bad_sockaddr, .init=setup, .fini=teardown)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
char buf[128] = { 0 };
|
||||
struct sockaddr_in sa;
|
||||
memcpy(&sa, &ipv4_loopback, sizeof(ipv4_loopback));
|
||||
sa.sin_family = AF_UNSPEC;
|
||||
rc = ddsrt_sockaddrtostr(&sa, buf, sizeof(buf));
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sockaddrtostr, no_space, .init=setup, .fini=teardown)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
char buf[1] = { 0 };
|
||||
rc = ddsrt_sockaddrtostr(&ipv4_loopback, buf, sizeof(buf));
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_NOT_ENOUGH_SPACE);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sockaddrtostr, ipv4)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
char buf[128] = { 0 };
|
||||
rc = ddsrt_sockaddrtostr(&ipv4_loopback, buf, sizeof(buf));
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_STRING_EQUAL(buf, "127.0.0.1");
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sockaddrtostr, ipv6)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
char buf[128] = { 0 };
|
||||
rc = ddsrt_sockaddrtostr(&ipv6_loopback, buf, sizeof(buf));
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_STRING_EQUAL(buf, "::1");
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sockets, gethostname)
|
||||
{
|
||||
int ret;
|
||||
dds_retcode_t rc;
|
||||
char sysbuf[200], buf[200];
|
||||
|
||||
buf[0] = '\0';
|
||||
rc = ddsrt_gethostname(buf, sizeof(buf));
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
sysbuf[0] = '\0';
|
||||
ret = gethostname(sysbuf, sizeof(sysbuf));
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
CU_ASSERT(strcmp(buf, sysbuf) == 0);
|
||||
|
||||
rc = ddsrt_gethostname(buf, strlen(buf) - 1);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_NOT_ENOUGH_SPACE);
|
||||
}
|
||||
|
||||
#if DDSRT_HAVE_DNS
|
||||
static void gethostbyname_test(char *name, int af, dds_retcode_t exp)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
ddsrt_hostent_t *hent = NULL;
|
||||
rc = ddsrt_gethostbyname(name, af, &hent);
|
||||
CU_ASSERT_EQUAL(rc, exp);
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
CU_ASSERT_FATAL(hent->naddrs > 0);
|
||||
if (af != AF_UNSPEC) {
|
||||
CU_ASSERT_EQUAL(hent->addrs[0].ss_family, af);
|
||||
}
|
||||
}
|
||||
ddsrt_free(hent);
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_gethostbyname, ipv4) = {
|
||||
CU_DataPoints(char *, "", "127.0.0.1", "127.0.0.1"),
|
||||
CU_DataPoints(int, AF_UNSPEC, AF_INET, AF_UNSPEC),
|
||||
CU_DataPoints(dds_retcode_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK)
|
||||
};
|
||||
|
||||
CU_Theory((char *name, int af, dds_retcode_t exp), ddsrt_gethostbyname, ipv4, .init=setup, .fini=teardown)
|
||||
{
|
||||
gethostbyname_test(name, af, exp);
|
||||
}
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
/* Lookup of IPv4 address and specifying AF_INET6 is not invalid as it may
|
||||
return an IPV4-mapped IPv6 address. */
|
||||
CU_TheoryDataPoints(ddsrt_gethostbyname, ipv6) = {
|
||||
CU_DataPoints(char *, "::1", "::1", "::1"),
|
||||
CU_DataPoints(int, AF_INET, AF_INET6, AF_UNSPEC),
|
||||
CU_DataPoints(dds_retcode_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK)
|
||||
};
|
||||
|
||||
CU_Theory((char *name, int af, dds_retcode_t exp), ddsrt_gethostbyname, ipv6, .init=setup, .fini=teardown)
|
||||
{
|
||||
gethostbyname_test(name, af, exp);
|
||||
}
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
#endif /* DDSRT_HAVE_DNS */
|
||||
101
src/ddsrt/tests/string.c
Normal file
101
src/ddsrt/tests/string.c
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "CUnit/Theory.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
typedef enum { eq, lt, gt } eq_t;
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_strcasecmp, basic) = {
|
||||
CU_DataPoints(const char *, "a", "aa", "a", "a", "A", "a", "b", "a", "B", "A", "", "a"),
|
||||
CU_DataPoints(const char *, "a", "a", "aa", "A", "a", "b", "a", "b", "A", "B", "a", ""),
|
||||
CU_DataPoints(eq_t, eq, gt, lt, eq, eq, lt, gt, lt, gt, lt, lt, gt)
|
||||
};
|
||||
|
||||
CU_Theory((const char *s1, const char *s2, eq_t e), ddsrt_strcasecmp, basic)
|
||||
{
|
||||
int r = ddsrt_strcasecmp(s1, s2);
|
||||
CU_ASSERT((e == eq && r == 0) || (e == lt && r < 0) || (e == gt && r > 0));
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_strncasecmp, basic) = {
|
||||
CU_DataPoints(const char *, "a", "aa", "a", "A", "a", "b", "a", "B", "A", "", "a"),
|
||||
CU_DataPoints(const char *, "a", "a", "aa", "a", "A", "a", "b", "A", "B", "a", ""),
|
||||
CU_DataPoints(size_t, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1),
|
||||
CU_DataPoints(eq_t, eq, gt, lt, eq, eq, gt, lt, gt, lt, lt, gt)
|
||||
};
|
||||
|
||||
CU_Theory((const char *s1, const char *s2, size_t n, eq_t e), ddsrt_strncasecmp, basic)
|
||||
{
|
||||
int r = ddsrt_strncasecmp(s1, s2, n);
|
||||
CU_ASSERT((e == eq && r == 0) || (e == lt && r < 0) || (e == gt && r > 0));
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_strncasecmp, empty) = {
|
||||
CU_DataPoints(const char *, "a", "", "a", "", "a", ""),
|
||||
CU_DataPoints(const char *, "", "a", "", "a", "", "a"),
|
||||
CU_DataPoints(size_t, 1, 1, 0, 0, 2, 2),
|
||||
CU_DataPoints(eq_t, gt, lt, eq, eq, gt, lt)
|
||||
};
|
||||
|
||||
CU_Theory((const char *s1, const char *s2, size_t n, eq_t e), ddsrt_strncasecmp, empty)
|
||||
{
|
||||
int r = ddsrt_strncasecmp(s1, s2, n);
|
||||
CU_ASSERT((e == eq && r == 0) || (e == lt && r < 0) || (e == gt && r > 0));
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_strncasecmp, length) = {
|
||||
CU_DataPoints(const char *, "aBcD", "AbCX", "aBcD", "AbCX", "aBcD"),
|
||||
CU_DataPoints(const char *, "AbCX", "aBcD", "AbCX", "aBcD", "AbCd"),
|
||||
CU_DataPoints(size_t, 3, 3, 4, 4, 5, 5),
|
||||
CU_DataPoints(eq_t, eq, eq, lt, gt, eq, eq)
|
||||
};
|
||||
|
||||
CU_Theory((const char *s1, const char *s2, size_t n, eq_t e), ddsrt_strncasecmp, length)
|
||||
{
|
||||
int r = ddsrt_strncasecmp(s1, s2, n);
|
||||
CU_ASSERT((e == eq && r == 0) || (e == lt && r < 0) || (e == gt && r > 0));
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_string, strtok_r)
|
||||
{
|
||||
char *res;
|
||||
char *saveptr;
|
||||
char ts1[] = "123,234";
|
||||
char ts2[] = ",;,123abc,,456,:,";
|
||||
char ts3[] = ",,,123,,456,789,,,";
|
||||
|
||||
res = ddsrt_strtok_r(ts1, ",", &saveptr);
|
||||
CU_ASSERT(strcmp(res, "123") == 0);
|
||||
res = ddsrt_strtok_r( NULL, ",", &saveptr);
|
||||
CU_ASSERT(strcmp(res, "234") == 0);
|
||||
res = ddsrt_strtok_r( NULL, ",", &saveptr);
|
||||
CU_ASSERT(res == NULL);
|
||||
|
||||
res = ddsrt_strtok_r(ts2, ",;", &saveptr);
|
||||
CU_ASSERT(strcmp(res, "123abc") == 0);
|
||||
res = ddsrt_strtok_r( NULL, ",", &saveptr);
|
||||
CU_ASSERT(strcmp(res, "456") == 0);
|
||||
res = ddsrt_strtok_r( NULL, ",:", &saveptr);
|
||||
CU_ASSERT(res == NULL);
|
||||
|
||||
res = ddsrt_strtok_r(ts3, ",", &saveptr);
|
||||
CU_ASSERT(strcmp(res, "123") == 0);
|
||||
res = ddsrt_strtok_r( NULL, ",", &saveptr);
|
||||
CU_ASSERT(strcmp(res, "456") == 0);
|
||||
res = ddsrt_strtok_r( NULL, ",", &saveptr);
|
||||
CU_ASSERT(strcmp(res, "789") == 0);
|
||||
res = ddsrt_strtok_r( NULL, ",:", &saveptr);
|
||||
CU_ASSERT(res == NULL);
|
||||
}
|
||||
|
||||
80
src/ddsrt/tests/strlcpy.c
Normal file
80
src/ddsrt/tests/strlcpy.c
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "CUnit/Theory.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_strlcpy, dest_size) = {
|
||||
CU_DataPoints(char *, "foo", "foo", "foo", "foo", "foo", "", "", ""),
|
||||
CU_DataPoints(size_t, 0, 1, 3, 4, 5, 0, 1, 2)
|
||||
};
|
||||
|
||||
CU_Theory((char *src, size_t size), ddsrt_strlcpy, dest_size)
|
||||
{
|
||||
char dest[] = "................";
|
||||
size_t len, srclen;
|
||||
|
||||
srclen = strlen(src);
|
||||
len = ddsrt_strlcpy(dest, src, size);
|
||||
CU_ASSERT_EQUAL(len, srclen);
|
||||
if (size > 0) {
|
||||
if ((size - 1) < len) {
|
||||
len = size - 1;
|
||||
}
|
||||
CU_ASSERT_EQUAL(dest[len], '\0');
|
||||
CU_ASSERT_EQUAL(dest[len+1], '.');
|
||||
CU_ASSERT((strncmp(dest, src, len) == 0));
|
||||
} else {
|
||||
CU_ASSERT_EQUAL(dest[0], '.');
|
||||
}
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_strlcat, dest_size) = {
|
||||
CU_DataPoints(char *, "", "", "", "", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "", "", "foo", "foo", "foo"),
|
||||
CU_DataPoints(char *, "bar", "bar", "bar", "bar", "bar", "bar", "bar", "bar", "bar", "bar", "bar", "", "", "", "", ""),
|
||||
CU_DataPoints(size_t, 0, 1, 3, 4, 0, 1, 3, 4, 5, 6, 7, 0, 1, 3, 4, 5)
|
||||
};
|
||||
|
||||
CU_Theory((char *seed, char *src, size_t size), ddsrt_strlcat, dest_size)
|
||||
{
|
||||
char dest[] = "................";
|
||||
size_t len, seedlen, srclen;
|
||||
seedlen = strlen(seed);
|
||||
srclen = strlen(src);
|
||||
memcpy(dest, seed, seedlen);
|
||||
dest[seedlen] = '\0';
|
||||
|
||||
len = ddsrt_strlcat(dest, src, size);
|
||||
CU_ASSERT_EQUAL(len, (seedlen + srclen));
|
||||
if (size > 0) {
|
||||
char foobar[sizeof(dest)];
|
||||
|
||||
if ((size - 1) <= seedlen) {
|
||||
len = seedlen;
|
||||
} else if ((size - 1) <= len) {
|
||||
len = size - 1;
|
||||
}
|
||||
|
||||
CU_ASSERT_EQUAL(dest[len], '\0');
|
||||
|
||||
if (seedlen < (size - 1)) {
|
||||
CU_ASSERT_EQUAL(dest[len+1], '.');
|
||||
}
|
||||
|
||||
(void)snprintf(foobar, len+1, "%s%s", seed, src);
|
||||
CU_ASSERT((strncmp(dest, foobar, len) == 0));
|
||||
} else {
|
||||
CU_ASSERT((strcmp(dest, seed) == 0));
|
||||
}
|
||||
}
|
||||
343
src/ddsrt/tests/strtoll.c
Normal file
343
src/ddsrt/tests/strtoll.c
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "CUnit/Test.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/strtol.h"
|
||||
|
||||
const char *str;
|
||||
char *ptr;
|
||||
char buf[100];
|
||||
char str_llmin[100];
|
||||
char str_llmax[100];
|
||||
char str_ullmax[100];
|
||||
char str_llrange[100];
|
||||
char str_ullrange[100];
|
||||
|
||||
char str_xllmin[99], str_xllmax[99];
|
||||
|
||||
/* Really test with the maximum values supported on a platform, not some
|
||||
made up number. */
|
||||
long long llmin = DDSRT_MIN_INTEGER(long long);
|
||||
long long llmax = DDSRT_MAX_INTEGER(long long);
|
||||
unsigned long long ullmax = DDSRT_MAX_INTEGER(unsigned long long);
|
||||
|
||||
CU_Init(ddsrt_strtoll)
|
||||
{
|
||||
ddsrt_init();
|
||||
(void)snprintf (str_llmin, sizeof(str_llmin), "%lld", llmin);
|
||||
(void)snprintf (str_llmax, sizeof(str_llmax), "%lld", llmax);
|
||||
(void)snprintf (str_llrange, sizeof(str_llrange), "%lld1", llmax);
|
||||
(void)snprintf (str_ullmax, sizeof(str_ullmax), "%llu", ullmax);
|
||||
(void)snprintf (str_ullrange, sizeof(str_ullrange), "%llu1", ullmax);
|
||||
(void)snprintf (str_xllmin, sizeof(str_xllmin), "-%llx", llmin);
|
||||
(void)snprintf (str_xllmax, sizeof(str_xllmax), "+%llx", llmax);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Clean(ddstr_strtoll)
|
||||
{
|
||||
ddsrt_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_strtoll, strtoll)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
long long ll;
|
||||
static char dummy[] = "dummy";
|
||||
|
||||
str = "gibberish";
|
||||
ll = -1;
|
||||
rc = ddsrt_strtoll(str, &ptr, 0, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0 && ptr == str);
|
||||
|
||||
str = "+gibberish";
|
||||
ll = -2;
|
||||
rc = ddsrt_strtoll(str, &ptr, 0, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0 && ptr == str);
|
||||
|
||||
str = "-gibberish";
|
||||
ll = -3;
|
||||
rc = ddsrt_strtoll(str, &ptr, 0, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0 && ptr == str);
|
||||
|
||||
str = "gibberish";
|
||||
ptr = NULL;
|
||||
ll = -4;
|
||||
rc = ddsrt_strtoll(str, &ptr, 36, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 46572948005345 && ptr && *ptr == '\0');
|
||||
|
||||
str = "1050505055";
|
||||
ptr = dummy;
|
||||
ll = -5;
|
||||
rc = ddsrt_strtoll(str, &ptr, 37, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_BAD_PARAMETER);
|
||||
CU_ASSERT (ll == -5 && ptr == dummy);
|
||||
|
||||
str = " \t \n 1050505055";
|
||||
ll = -6;
|
||||
rc = ddsrt_strtoll(str, NULL, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 1050505055LL);
|
||||
|
||||
str = " \t \n -1050505055";
|
||||
ptr = NULL;
|
||||
ll = -7;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == -1050505055LL);
|
||||
|
||||
str = " \t \n - \t \n 1050505055";
|
||||
ptr = NULL;
|
||||
ll = -8;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0LL && ptr == str);
|
||||
|
||||
str = "10x";
|
||||
ptr = NULL;
|
||||
ll = -9;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 10LL && ptr && *ptr == 'x');
|
||||
|
||||
str = "+10x";
|
||||
ll = -10;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 10LL && ptr && *ptr == 'x');
|
||||
|
||||
str = "-10x";
|
||||
ll = -11;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == -10LL && ptr && *ptr == 'x');
|
||||
|
||||
str = (const char *)str_llmax;
|
||||
ll = -12;
|
||||
rc = ddsrt_strtoll(str, NULL, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == llmax);
|
||||
|
||||
str = (const char *)str_llmin;
|
||||
ll = -13;
|
||||
rc = ddsrt_strtoll(str, NULL, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == llmin);
|
||||
|
||||
str = (const char *)str_llrange;
|
||||
ll = -14;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OUT_OF_RANGE);
|
||||
CU_ASSERT (ll == llmax && *ptr == '1');
|
||||
|
||||
str = "0x100";
|
||||
ll = -15;
|
||||
rc = ddsrt_strtoll(str, NULL, 16, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0x100LL);
|
||||
|
||||
str = "0X100";
|
||||
ll = -16;
|
||||
rc = ddsrt_strtoll(str, NULL, 16, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0x100LL);
|
||||
|
||||
str = "0x1DEFCAB";
|
||||
ll = -17;
|
||||
rc = ddsrt_strtoll(str, NULL, 16, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0x1DEFCABLL);
|
||||
|
||||
str = "0x1defcab";
|
||||
ll = -18;
|
||||
rc = ddsrt_strtoll(str, NULL, 16, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0x1DEFCABLL);
|
||||
|
||||
str = (char *)str_xllmin;
|
||||
ll = -19;
|
||||
rc = ddsrt_strtoll(str, NULL, 16, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == llmin);
|
||||
|
||||
str = (char *)str_xllmax;
|
||||
ll = -20;
|
||||
rc = ddsrt_strtoll(str, NULL, 16, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == llmax);
|
||||
|
||||
str = "0x100";
|
||||
ll = -21;
|
||||
rc = ddsrt_strtoll(str, NULL, 0, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0x100LL);
|
||||
|
||||
str = "100";
|
||||
ll = -22;
|
||||
rc = ddsrt_strtoll(str, NULL, 16, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0x100LL);
|
||||
|
||||
/* calling os_strtoll with \"%s\" and base 10, expected result 0 */
|
||||
str = "0x100";
|
||||
ll = -23;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 0 && ptr && *ptr == 'x');
|
||||
|
||||
/* calling os_strtoll with \"%s\" and base 0, expected result 256 */
|
||||
str = "0x100g";
|
||||
ll = -24;
|
||||
rc = ddsrt_strtoll(str, &ptr, 0, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 256 && ptr && *ptr == 'g');
|
||||
|
||||
str = "0100";
|
||||
ll = -25;
|
||||
rc = ddsrt_strtoll(str, NULL, 0, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 64LL);
|
||||
|
||||
str = "0100";
|
||||
ll = -26;
|
||||
rc = ddsrt_strtoll(str, NULL, 8, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 64LL);
|
||||
|
||||
str = "100";
|
||||
ll = -27;
|
||||
rc = ddsrt_strtoll(str, NULL, 8, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 64LL);
|
||||
|
||||
/* calling os_strtoll with \"%s\" and base 10, expected result 100 */
|
||||
str = "0100";
|
||||
ll = -28;
|
||||
rc = ddsrt_strtoll(str, &ptr, 10, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 100);
|
||||
|
||||
/* calling os_strtoll with \"%s\" and base 0, expected result 64 */
|
||||
str = "01008";
|
||||
ll = -29;
|
||||
rc = ddsrt_strtoll(str, &ptr, 8, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 64LL && ptr && *ptr == '8');
|
||||
|
||||
str = "00001010";
|
||||
ll = -30;
|
||||
rc = ddsrt_strtoll(str, NULL, 2, &ll);
|
||||
CU_ASSERT (rc == DDS_RETCODE_OK);
|
||||
CU_ASSERT (ll == 10LL);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_strtoll, strtoull)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
unsigned long long ull;
|
||||
|
||||
str = "0xffffffffffffffff";
|
||||
ull = 1;
|
||||
rc = ddsrt_strtoull(str, NULL, 0, &ull);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT(ull == ullmax);
|
||||
|
||||
str = "-1";
|
||||
ull = 2;
|
||||
rc = ddsrt_strtoull(str, NULL, 0, &ull);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT(ull == ullmax);
|
||||
|
||||
str = "-2";
|
||||
ull = 3;
|
||||
rc = ddsrt_strtoull(str, NULL, 0, &ull);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT(ull == (ullmax - 1));
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_strtoll, atoll)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
long long ll;
|
||||
|
||||
str = "10";
|
||||
ll = -1;
|
||||
rc = ddsrt_atoll(str, &ll);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT(ll == 10);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_strtoll, atoull)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
unsigned long long ull;
|
||||
|
||||
str = "10";
|
||||
ull = 1;
|
||||
rc = ddsrt_atoull(str, &ull);
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT(ull == 10);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_strtoll, lltostr)
|
||||
{
|
||||
long long ll;
|
||||
|
||||
ll = llmax;
|
||||
ptr = ddsrt_lltostr(ll, buf, 0, NULL);
|
||||
CU_ASSERT(ptr == NULL);
|
||||
|
||||
/* calling os_lltostr with %lld with buffer size of 5, expected result \"5432\" */
|
||||
ll = 54321;
|
||||
ptr = ddsrt_lltostr(ll, buf, 5, NULL);
|
||||
CU_ASSERT(strcmp(ptr, "5432") == 0);
|
||||
|
||||
ll = llmax;
|
||||
ptr = ddsrt_lltostr(ll, buf, sizeof(buf), NULL);
|
||||
CU_ASSERT(strcmp(ptr, str_llmax) == 0);
|
||||
|
||||
ll = llmin;
|
||||
ptr = ddsrt_lltostr(ll, buf, sizeof(buf), NULL);
|
||||
CU_ASSERT(strcmp(ptr, str_llmin) == 0);
|
||||
|
||||
ll = 1;
|
||||
ptr = ddsrt_lltostr(ll, buf, sizeof(buf), NULL);
|
||||
CU_ASSERT(strcmp(ptr, "1") == 0);
|
||||
|
||||
ll = 0;
|
||||
ptr = ddsrt_lltostr(ll, buf, sizeof(buf), NULL);
|
||||
CU_ASSERT(strcmp(ptr, "0") == 0);
|
||||
|
||||
ll = -1;
|
||||
ptr = ddsrt_lltostr(ll, buf, sizeof(buf), NULL);
|
||||
CU_ASSERT(strcmp(ptr, "-1") == 0);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_strtoll, ulltostr)
|
||||
{
|
||||
unsigned long long ull;
|
||||
|
||||
ull = ullmax;
|
||||
ptr = ddsrt_ulltostr(ull, buf, sizeof(buf), NULL);
|
||||
CU_ASSERT(strcmp(ptr, str_ullmax) == 0);
|
||||
|
||||
ull = 0ULL;
|
||||
ptr = ddsrt_ulltostr(ull, buf, sizeof(buf), NULL);
|
||||
CU_ASSERT(strcmp(ptr, "0") == 0);
|
||||
}
|
||||
|
||||
357
src/ddsrt/tests/sync.c
Normal file
357
src/ddsrt/tests/sync.c
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "CUnit/Theory.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
CU_Init(ddsrt_sync)
|
||||
{
|
||||
ddsrt_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Clean(ddsrt_sync)
|
||||
{
|
||||
ddsrt_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ddsrt_atomic_uint32_t cnt;
|
||||
ddsrt_mutex_t lock;
|
||||
ddsrt_rwlock_t rwlock;
|
||||
ddsrt_cond_t cond;
|
||||
dds_time_t abstime;
|
||||
dds_time_t reltime;
|
||||
} thread_arg_t;
|
||||
|
||||
static uint32_t mutex_lock_routine(void *ptr)
|
||||
{
|
||||
int res;
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
|
||||
ddsrt_atomic_inc32(&arg->cnt);
|
||||
ddsrt_mutex_lock(&arg->lock);
|
||||
res = ddsrt_atomic_cas32(&arg->cnt, 2UL, 4UL);
|
||||
ddsrt_mutex_unlock(&arg->lock);
|
||||
return (uint32_t)res;
|
||||
}
|
||||
|
||||
/* This test is merely best-effort, the scheduler might schedule the main
|
||||
main thread before a lock operation is attempted by the second thread. */
|
||||
CU_Test(ddsrt_sync, mutex_lock_conc)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(0) };
|
||||
uint32_t res = 0;
|
||||
|
||||
ddsrt_mutex_init(&arg.lock);
|
||||
ddsrt_mutex_lock(&arg.lock);
|
||||
ddsrt_threadattr_init(&attr);
|
||||
ret = ddsrt_thread_create(&thr, "mutex_lock_conc", &attr, &mutex_lock_routine, &arg);
|
||||
CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK);
|
||||
while (ddsrt_atomic_ld32(&arg.cnt) == 0)
|
||||
/* Wait for thread to be scheduled. */ ;
|
||||
ddsrt_atomic_inc32(&arg.cnt);
|
||||
ddsrt_mutex_unlock(&arg.lock);
|
||||
ret = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
CU_ASSERT_EQUAL(ddsrt_atomic_ld32(&arg.cnt), 4UL);
|
||||
ddsrt_mutex_destroy(&arg.lock);
|
||||
}
|
||||
|
||||
static uint32_t mutex_trylock_routine(void *ptr)
|
||||
{
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
|
||||
if (ddsrt_mutex_trylock(&arg->lock)) {
|
||||
ddsrt_atomic_inc32(&arg->cnt);
|
||||
}
|
||||
|
||||
return ddsrt_atomic_ld32(&arg->cnt);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sync, mutex_trylock)
|
||||
{
|
||||
bool locked;
|
||||
ddsrt_mutex_t lock;
|
||||
|
||||
ddsrt_mutex_init(&lock);
|
||||
locked = ddsrt_mutex_trylock(&lock);
|
||||
CU_ASSERT(locked == true);
|
||||
locked = ddsrt_mutex_trylock (&lock);
|
||||
/* NOTE: On VxWorks RTP mutexes seemingly can be locked recursively. Still,
|
||||
behavior should be consistent across targets. If this fails, fix
|
||||
the implementation instead. */
|
||||
CU_ASSERT(locked == false);
|
||||
ddsrt_mutex_unlock(&lock);
|
||||
ddsrt_mutex_destroy(&lock);
|
||||
}
|
||||
|
||||
static uint32_t rwlock_tryread_routine(void *ptr)
|
||||
{
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
|
||||
if (ddsrt_rwlock_tryread(&arg->rwlock)) {
|
||||
ddsrt_atomic_inc32(&arg->cnt);
|
||||
ddsrt_rwlock_unlock(&arg->rwlock);
|
||||
}
|
||||
|
||||
return ddsrt_atomic_ld32(&arg->cnt);
|
||||
}
|
||||
|
||||
static uint32_t rwlock_trywrite_routine(void *ptr)
|
||||
{
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
|
||||
/* This operation should never succeed in the test, but if it does the
|
||||
result must reflect it. */
|
||||
if (ddsrt_rwlock_trywrite(&arg->rwlock)) {
|
||||
ddsrt_atomic_inc32(&arg->cnt);
|
||||
ddsrt_rwlock_unlock(&arg->rwlock);
|
||||
}
|
||||
|
||||
return ddsrt_atomic_ld32(&arg->cnt);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sync, mutex_trylock_conc)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(1) };
|
||||
uint32_t res = 0;
|
||||
|
||||
ddsrt_mutex_init(&arg.lock);
|
||||
ddsrt_mutex_lock(&arg.lock);
|
||||
ddsrt_threadattr_init(&attr);
|
||||
ret = ddsrt_thread_create(&thr, "mutex_trylock_conc", &attr, &mutex_trylock_routine, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
ret = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
ddsrt_mutex_unlock(&arg.lock);
|
||||
ddsrt_mutex_destroy(&arg.lock);
|
||||
}
|
||||
|
||||
#define READ (1)
|
||||
#define TRYREAD (2)
|
||||
#define WRITE (3)
|
||||
#define TRYWRITE (4)
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_sync, rwlock_trylock_conc) = {
|
||||
CU_DataPoints(uint32_t, READ, READ, WRITE, WRITE),
|
||||
CU_DataPoints(uint32_t, TRYREAD, TRYWRITE, TRYREAD, TRYWRITE),
|
||||
CU_DataPoints(uint32_t, 2, 1, 1, 1)
|
||||
};
|
||||
|
||||
CU_Theory((uint32_t lock, uint32_t trylock, uint32_t exp), ddsrt_sync, rwlock_trylock_conc)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
ddsrt_thread_routine_t func;
|
||||
thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(1) };
|
||||
uint32_t res = 0;
|
||||
|
||||
ddsrt_rwlock_init(&arg.rwlock);
|
||||
if (lock == READ) {
|
||||
ddsrt_rwlock_read(&arg.rwlock);
|
||||
} else {
|
||||
ddsrt_rwlock_write(&arg.rwlock);
|
||||
}
|
||||
|
||||
if (trylock == TRYREAD) {
|
||||
func = &rwlock_tryread_routine;
|
||||
} else {
|
||||
func = &rwlock_trywrite_routine;
|
||||
}
|
||||
|
||||
ddsrt_threadattr_init(&attr);
|
||||
ret = ddsrt_thread_create(&thr, "rwlock_trylock_conc", &attr, func, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
ret = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
ddsrt_rwlock_unlock(&arg.rwlock);
|
||||
CU_ASSERT_EQUAL(res, exp);
|
||||
ddsrt_rwlock_destroy(&arg.rwlock);
|
||||
}
|
||||
|
||||
/* An atomic read is used for synchronization because it is important that the
|
||||
threads try to access the once control concurrently as much as possible. Of
|
||||
course, this is only best-effort as there is no guarantee that
|
||||
initialization is actually tried concurrently. */
|
||||
static ddsrt_atomic_uint32_t once_count = DDSRT_ATOMIC_UINT32_INIT(0);
|
||||
static ddsrt_once_t once_control = DDSRT_ONCE_INIT;
|
||||
|
||||
#define ONCE_THREADS (8)
|
||||
|
||||
static void do_once(void)
|
||||
{
|
||||
ddsrt_atomic_inc32(&once_count);
|
||||
}
|
||||
|
||||
static uint32_t once_routine(void *ptr)
|
||||
{
|
||||
(void)ptr;
|
||||
while (ddsrt_atomic_ld32(&once_count) == 0)
|
||||
/* Wait for the go-ahead. */ ;
|
||||
ddsrt_once(&once_control, &do_once);
|
||||
return ddsrt_atomic_ld32(&once_count);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sync, once_conc)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
ddsrt_thread_t thrs[ONCE_THREADS];
|
||||
ddsrt_threadattr_t attr;
|
||||
uint32_t res;
|
||||
char buf[32];
|
||||
|
||||
ddsrt_threadattr_init(&attr);
|
||||
for (int i = 0; i < ONCE_THREADS; i++) {
|
||||
(void)snprintf(buf, sizeof(buf), "once_conc%d", i + 1);
|
||||
ret = ddsrt_thread_create(&thrs[i], buf, &attr, &once_routine, NULL);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
}
|
||||
|
||||
ddsrt_atomic_st32(&once_count, 1);
|
||||
|
||||
for (int i = 0; i < ONCE_THREADS; i++) {
|
||||
res = 0;
|
||||
ret = ddsrt_thread_join(thrs[i], &res);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 2);
|
||||
}
|
||||
|
||||
ddsrt_once(&once_control, &do_once);
|
||||
CU_ASSERT_EQUAL(ddsrt_atomic_ld32(&once_count), 2);
|
||||
}
|
||||
|
||||
static uint32_t waitfor_routine(void *ptr)
|
||||
{
|
||||
dds_time_t before, after;
|
||||
dds_duration_t reltime;
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
uint32_t cnt = 0, res = 0;
|
||||
|
||||
while (ddsrt_atomic_ld32(&arg->cnt) == 0)
|
||||
/* Wait for go-ahead. */ ;
|
||||
ddsrt_mutex_lock(&arg->lock);
|
||||
before = dds_time();
|
||||
reltime = arg->reltime;
|
||||
while (ddsrt_cond_waitfor(&arg->cond, &arg->lock, reltime)) {
|
||||
after = dds_time();
|
||||
if ((after - before) < arg->reltime && (after - before) > 0) {
|
||||
reltime = arg->reltime - (after - before);
|
||||
} else {
|
||||
reltime = 0;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
after = dds_time();
|
||||
reltime = after - before;
|
||||
fprintf(stderr, "waited for %"PRId64" (nanoseconds)\n", reltime);
|
||||
fprintf(stderr, "expected to wait %"PRId64" (nanoseconds)\n", arg->reltime);
|
||||
fprintf(stderr, "woke up %u times\n", cnt);
|
||||
ddsrt_mutex_unlock(&arg->lock);
|
||||
if (reltime >= arg->reltime) {
|
||||
/* Ensure that the condition variable at least waited for the amount of
|
||||
time so that time calculation is not (too) broken.*/
|
||||
res = cnt < 3; /* An arbitrary number to ensure the implementation
|
||||
did not just spin, aka is completely broken. */
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sync, cond_waitfor)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(0), .reltime = DDS_MSECS(100) };
|
||||
uint32_t res = 0;
|
||||
|
||||
ddsrt_mutex_init(&arg.lock);
|
||||
ddsrt_cond_init(&arg.cond);
|
||||
ddsrt_mutex_lock(&arg.lock);
|
||||
ddsrt_threadattr_init(&attr);
|
||||
rc = ddsrt_thread_create(&thr, "cond_waitfor", &attr, &waitfor_routine, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
ddsrt_mutex_unlock(&arg.lock);
|
||||
/* Give go-ahead. */
|
||||
ddsrt_atomic_inc32(&arg.cnt);
|
||||
/* Wait a little longer than the waiting thread. */
|
||||
dds_sleepfor(arg.reltime * 2);
|
||||
/* Send a signal too avoid blocking indefinitely. */
|
||||
ddsrt_cond_signal(&arg.cond);
|
||||
rc = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
}
|
||||
|
||||
static uint32_t waituntil_routine(void *ptr)
|
||||
{
|
||||
dds_time_t after;
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
uint32_t cnt = 0, res = 0;
|
||||
|
||||
ddsrt_mutex_lock(&arg->lock);
|
||||
while(ddsrt_cond_waituntil(&arg->cond, &arg->lock, arg->abstime)) {
|
||||
cnt++;
|
||||
}
|
||||
after = dds_time();
|
||||
ddsrt_mutex_unlock(&arg->lock);
|
||||
fprintf(stderr, "waited until %"PRId64" (nanoseconds)\n", after);
|
||||
fprintf(stderr, "expected to wait until %"PRId64" (nanoseconds)\n", arg->abstime);
|
||||
fprintf(stderr, "woke up %u times\n", cnt);
|
||||
if (after > arg->abstime) {
|
||||
res = cnt < 3; /* An arbitrary number to ensure the implementation
|
||||
did not just spin, aka is completely broken. */
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sync, cond_waituntil)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_duration_t delay = DDS_MSECS(100);
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg = { .cnt = DDSRT_ATOMIC_UINT32_INIT(0) };
|
||||
uint32_t res = 0;
|
||||
|
||||
arg.abstime = dds_time() + delay;
|
||||
ddsrt_mutex_init(&arg.lock);
|
||||
ddsrt_cond_init(&arg.cond);
|
||||
ddsrt_mutex_lock(&arg.lock);
|
||||
ddsrt_threadattr_init(&attr);
|
||||
rc = ddsrt_thread_create(&thr, "cond_waituntil", &attr, &waituntil_routine, &arg);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
ddsrt_mutex_unlock(&arg.lock);
|
||||
dds_sleepfor(delay * 2);
|
||||
/* Send a signal too avoid blocking indefinitely. */
|
||||
ddsrt_cond_signal(&arg.cond);
|
||||
rc = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
}
|
||||
233
src/ddsrt/tests/thread.c
Normal file
233
src/ddsrt/tests/thread.c
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#if !defined(_WIN32)
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "CUnit/Theory.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
static int32_t min_fifo_prio = 250;
|
||||
static int32_t max_fifo_prio = 250;
|
||||
static int32_t max_other_prio = 60;
|
||||
static int32_t min_other_prio = 250;
|
||||
|
||||
CU_Init(ddsrt_thread)
|
||||
{
|
||||
ddsrt_init();
|
||||
#if defined(WIN32)
|
||||
max_fifo_prio = THREAD_PRIORITY_HIGHEST;
|
||||
min_fifo_prio = THREAD_PRIORITY_LOWEST;
|
||||
max_other_prio = THREAD_PRIORITY_HIGHEST;
|
||||
min_other_prio = THREAD_PRIORITY_LOWEST;
|
||||
#else
|
||||
min_fifo_prio = sched_get_priority_min(SCHED_FIFO);
|
||||
max_fifo_prio = sched_get_priority_max(SCHED_FIFO);
|
||||
# if !defined(_WRS_KERNEL)
|
||||
max_other_prio = sched_get_priority_max(SCHED_OTHER);
|
||||
min_other_prio = sched_get_priority_min(SCHED_OTHER);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Clean(ddsrt_thread)
|
||||
{
|
||||
ddsrt_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int res;
|
||||
int ret;
|
||||
ddsrt_threadattr_t *attr;
|
||||
} thread_arg_t;
|
||||
|
||||
uint32_t thread_main(void *ptr)
|
||||
{
|
||||
thread_arg_t *arg = (thread_arg_t *)ptr;
|
||||
ddsrt_threadattr_t *attr;
|
||||
|
||||
assert(arg != NULL);
|
||||
|
||||
attr = arg->attr;
|
||||
|
||||
#if _WIN32
|
||||
int prio = GetThreadPriority(GetCurrentThread());
|
||||
if (prio == THREAD_PRIORITY_ERROR_RETURN)
|
||||
abort();
|
||||
if (prio == attr->schedPriority) {
|
||||
arg->res = 1;
|
||||
}
|
||||
#else
|
||||
int err;
|
||||
int policy;
|
||||
struct sched_param sched;
|
||||
|
||||
err = pthread_getschedparam(pthread_self(), &policy, &sched);
|
||||
if (err != 0) {
|
||||
abort();
|
||||
}
|
||||
if (((policy == SCHED_OTHER && attr->schedClass == DDSRT_SCHED_TIMESHARE) ||
|
||||
(policy == SCHED_FIFO && attr->schedClass == DDSRT_SCHED_REALTIME))
|
||||
&& (sched.sched_priority == attr->schedPriority))
|
||||
{
|
||||
arg->res = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (uint32_t)arg->ret;
|
||||
}
|
||||
|
||||
CU_TheoryDataPoints(ddsrt_thread, create_and_join) = {
|
||||
CU_DataPoints(ddsrt_sched_t, DDSRT_SCHED_TIMESHARE, DDSRT_SCHED_TIMESHARE,
|
||||
DDSRT_SCHED_REALTIME, DDSRT_SCHED_REALTIME),
|
||||
CU_DataPoints(int32_t *, &min_other_prio, &max_other_prio,
|
||||
&min_fifo_prio, &max_fifo_prio),
|
||||
CU_DataPoints(uint32_t, 10101, 20202,
|
||||
30303, 40404)
|
||||
};
|
||||
|
||||
CU_Theory((ddsrt_sched_t sched, int32_t *prio, uint32_t exp), ddsrt_thread, create_and_join)
|
||||
{
|
||||
int skip = 0;
|
||||
uint32_t res = 50505;
|
||||
dds_retcode_t ret;
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
thread_arg_t arg;
|
||||
|
||||
#if defined(__VXWORKS__)
|
||||
# if defined(_WRS_KERNEL)
|
||||
if (sched == DDSRT_SCHED_TIMESHARE) {
|
||||
skip = 1;
|
||||
CU_PASS("VxWorks DKM only supports SCHED_FIFO");
|
||||
}
|
||||
# endif
|
||||
#elif !defined(_WIN32)
|
||||
if (sched == DDSRT_SCHED_REALTIME && (getuid() != 0 && geteuid() != 0)) {
|
||||
skip = 1;
|
||||
CU_PASS("SCHED_FIFO requires root privileges");
|
||||
}
|
||||
#endif
|
||||
if (!skip) {
|
||||
ddsrt_threadattr_init(&attr);
|
||||
attr.schedClass = sched;
|
||||
attr.schedPriority = *prio;
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.ret = (int32_t)exp;
|
||||
arg.attr = &attr;
|
||||
ret = ddsrt_thread_create(&thr, "thread", &attr, &thread_main, &arg);
|
||||
CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK);
|
||||
if (ret == DDS_RETCODE_OK) {
|
||||
ret = ddsrt_thread_join (thr, &res);
|
||||
CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, exp);
|
||||
if (ret == DDS_RETCODE_OK) {
|
||||
CU_ASSERT_EQUAL(arg.res, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_thread, thread_id)
|
||||
{
|
||||
int eq = 0;
|
||||
ddsrt_thread_t thr;
|
||||
#if defined(_WIN32)
|
||||
DWORD _tid;
|
||||
#else
|
||||
pthread_t _thr;
|
||||
#endif
|
||||
|
||||
thr = ddsrt_thread_self();
|
||||
|
||||
#if defined(_WIN32)
|
||||
_tid = GetCurrentThreadId();
|
||||
eq = (thr.tid == _tid);
|
||||
#else
|
||||
_thr = pthread_self();
|
||||
eq = pthread_equal(thr.v, _thr);
|
||||
#endif
|
||||
|
||||
CU_ASSERT_NOT_EQUAL(eq, 0);
|
||||
}
|
||||
|
||||
|
||||
static ddsrt_mutex_t locks[2];
|
||||
|
||||
uint32_t thread_main_waitforme(void *ptr)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
(void)ptr;
|
||||
ddsrt_mutex_lock(&locks[0]);
|
||||
ret = 10101;
|
||||
ddsrt_mutex_unlock(&locks[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t thread_main_waitforit(void *ptr)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
ddsrt_thread_t *thr = (ddsrt_thread_t *)ptr;
|
||||
ddsrt_mutex_lock(&locks[1]);
|
||||
(void)ddsrt_thread_join(*thr, &res);
|
||||
ddsrt_mutex_unlock(&locks[1]);
|
||||
return res + 20202;
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_thread, stacked_join)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
ddsrt_thread_t thrs[2];
|
||||
ddsrt_threadattr_t attr;
|
||||
uint32_t res = 0;
|
||||
|
||||
ddsrt_mutex_init(&locks[0]);
|
||||
ddsrt_mutex_init(&locks[1]);
|
||||
ddsrt_mutex_lock(&locks[0]);
|
||||
ddsrt_mutex_lock(&locks[1]);
|
||||
ddsrt_threadattr_init(&attr);
|
||||
ret = ddsrt_thread_create(&thrs[0], "", &attr, &thread_main_waitforme, NULL);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
ret = ddsrt_thread_create(&thrs[1], "", &attr, &thread_main_waitforit, &thrs[0]);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
||||
ddsrt_mutex_unlock(&locks[1]);
|
||||
dds_sleepfor(DDS_MSECS(100)); /* 100ms */
|
||||
ddsrt_mutex_unlock(&locks[0]);
|
||||
|
||||
ddsrt_thread_join(thrs[1], &res);
|
||||
|
||||
CU_ASSERT_EQUAL(res, 30303);
|
||||
|
||||
ddsrt_mutex_destroy(&locks[0]);
|
||||
ddsrt_mutex_destroy(&locks[1]);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_thread, attribute)
|
||||
{
|
||||
ddsrt_threadattr_t attr;
|
||||
|
||||
ddsrt_threadattr_init(&attr);
|
||||
CU_ASSERT_EQUAL(attr.schedClass, DDSRT_SCHED_DEFAULT);
|
||||
CU_ASSERT_EQUAL(attr.schedPriority, 0);
|
||||
CU_ASSERT_EQUAL(attr.stackSize, 0);
|
||||
}
|
||||
|
||||
286
src/ddsrt/tests/thread_cleanup.c
Normal file
286
src/ddsrt/tests/thread_cleanup.c
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "CUnit/Test.h"
|
||||
#include "dds/ddsrt/cdtors.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
CU_Init(ddsrt_thread_cleanup)
|
||||
{
|
||||
ddsrt_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Clean(ddsrt_thread_cleanup)
|
||||
{
|
||||
ddsrt_fini();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define THREAD_RESET_1 (1<<0)
|
||||
#define THREAD_RESET_2 (1<<1)
|
||||
#define THREAD_RUN_OFFSET (4)
|
||||
#define THREAD_RUN_1 (1<<(THREAD_RUN_OFFSET))
|
||||
#define THREAD_RUN_2 (1<<(THREAD_RUN_OFFSET + 1))
|
||||
|
||||
struct thread_argument {
|
||||
int flags;
|
||||
int pop;
|
||||
int one;
|
||||
int two;
|
||||
int executed;
|
||||
int cancelled;
|
||||
int block;
|
||||
ddsrt_mutex_t *mutex;
|
||||
ddsrt_thread_t thread;
|
||||
};
|
||||
|
||||
static struct thread_argument *
|
||||
make_thread_argument(
|
||||
int flags, int pop, int one, int two)
|
||||
{
|
||||
struct thread_argument *targ = ddsrt_malloc(sizeof(*targ));
|
||||
memset(targ, 0, sizeof(*targ));
|
||||
targ->flags = flags;
|
||||
targ->pop = pop;
|
||||
targ->one = one;
|
||||
targ->two = two;
|
||||
|
||||
return targ;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_one(
|
||||
void *arg)
|
||||
{
|
||||
struct thread_argument *targ = (struct thread_argument *)arg;
|
||||
targ->one = 0;
|
||||
targ->executed++;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_two(
|
||||
void *arg)
|
||||
{
|
||||
struct thread_argument *targ = (struct thread_argument *)arg;
|
||||
targ->two = 0;
|
||||
targ->executed++;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
thread_main(
|
||||
void *arg)
|
||||
{
|
||||
int pushed = 0;
|
||||
int popped = 0;
|
||||
int execute = 0;
|
||||
struct thread_argument *targ = (struct thread_argument *)arg;
|
||||
|
||||
if (targ->flags & THREAD_RESET_1) {
|
||||
ddsrt_thread_cleanup_push(&reset_one, arg);
|
||||
pushed++;
|
||||
}
|
||||
if (targ->flags & THREAD_RESET_2) {
|
||||
ddsrt_thread_cleanup_push(&reset_two, arg);
|
||||
pushed++;
|
||||
}
|
||||
|
||||
assert(targ->pop <= pushed);
|
||||
|
||||
if (targ->block) {
|
||||
ddsrt_mutex_lock(targ->mutex);
|
||||
}
|
||||
|
||||
while (popped < targ->pop) {
|
||||
execute = 1 << (THREAD_RUN_OFFSET + (targ->pop - (popped + 1)));
|
||||
ddsrt_thread_cleanup_pop(targ->flags & execute);
|
||||
targ->cancelled++;
|
||||
popped++;
|
||||
}
|
||||
|
||||
if (targ->block) {
|
||||
ddsrt_mutex_unlock(targ->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
setup(
|
||||
struct thread_argument *arg)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
|
||||
uint32_t tres = 0;
|
||||
|
||||
ddsrt_threadattr_init(&attr);
|
||||
rc = ddsrt_thread_create(&thr, "", &attr, &thread_main, (void *)arg);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
arg->thread = thr;
|
||||
if (!arg->block) {
|
||||
rc = ddsrt_thread_join(thr, &tres);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* verify the cleanup routine is called */
|
||||
CU_Test(ddsrt_thread_cleanup, push_one)
|
||||
{
|
||||
int flags = THREAD_RESET_1;
|
||||
struct thread_argument *targ = make_thread_argument(flags, 0, 1, 2);
|
||||
setup(targ);
|
||||
|
||||
CU_ASSERT_EQUAL(targ->one, 0);
|
||||
CU_ASSERT_EQUAL(targ->two, 2);
|
||||
CU_ASSERT_EQUAL(targ->executed, 1);
|
||||
CU_ASSERT_EQUAL(targ->cancelled, 0);
|
||||
|
||||
ddsrt_free(targ);
|
||||
}
|
||||
|
||||
/* verify all cleanup routines are called if multiple are registered */
|
||||
CU_Test(ddsrt_thread_cleanup, push_two)
|
||||
{
|
||||
int flags = THREAD_RESET_1 | THREAD_RESET_2;
|
||||
struct thread_argument *targ = make_thread_argument(flags, 0, 1, 2);
|
||||
setup(targ);
|
||||
|
||||
CU_ASSERT_EQUAL(targ->one, 0);
|
||||
CU_ASSERT_EQUAL(targ->two, 0);
|
||||
CU_ASSERT_EQUAL(targ->executed, 2);
|
||||
CU_ASSERT_EQUAL(targ->cancelled, 0);
|
||||
|
||||
ddsrt_free(targ);
|
||||
}
|
||||
|
||||
/* verify the first cleanup routine is still called if second got popped */
|
||||
CU_Test(ddsrt_thread_cleanup, push_two_pop_one_no_exec)
|
||||
{
|
||||
int flags = THREAD_RESET_1 | THREAD_RESET_2;
|
||||
struct thread_argument *targ = make_thread_argument(flags, 1, 1, 2);
|
||||
setup(targ);
|
||||
|
||||
CU_ASSERT_EQUAL(targ->one, 0);
|
||||
CU_ASSERT_EQUAL(targ->two, 2);
|
||||
CU_ASSERT_EQUAL(targ->executed, 1);
|
||||
CU_ASSERT_EQUAL(targ->cancelled, 1);
|
||||
|
||||
ddsrt_free(targ);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_thread_cleanup, push_two_pop_one_exec)
|
||||
{
|
||||
int flags = THREAD_RESET_1 | THREAD_RESET_2 | THREAD_RUN_1;
|
||||
struct thread_argument *targ = make_thread_argument(flags, 1, 1, 2);
|
||||
setup(targ);
|
||||
|
||||
CU_ASSERT_EQUAL(targ->one, 0);
|
||||
CU_ASSERT_EQUAL(targ->two, 0);
|
||||
CU_ASSERT_EQUAL(targ->executed, 2);
|
||||
CU_ASSERT_EQUAL(targ->cancelled, 1);
|
||||
|
||||
ddsrt_free(targ);
|
||||
}
|
||||
|
||||
/* verify no cleanup routines are called if all got popped */
|
||||
CU_Test(ddsrt_thread_cleanup, push_two_pop_two_no_exec)
|
||||
{
|
||||
int flags = THREAD_RESET_1 | THREAD_RESET_2;
|
||||
struct thread_argument *targ = make_thread_argument(flags, 2, 1, 2);
|
||||
setup(targ);
|
||||
|
||||
CU_ASSERT_EQUAL(targ->one, 1);
|
||||
CU_ASSERT_EQUAL(targ->two, 2);
|
||||
CU_ASSERT_EQUAL(targ->executed, 0);
|
||||
CU_ASSERT_EQUAL(targ->cancelled, 2);
|
||||
|
||||
ddsrt_free(targ);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_thread_cleanup, push_two_pop_two_exec_one)
|
||||
{
|
||||
int flags = THREAD_RESET_1 | THREAD_RESET_2 | THREAD_RUN_1;
|
||||
struct thread_argument *targ = make_thread_argument(flags, 2, 1, 2);
|
||||
setup(targ);
|
||||
|
||||
CU_ASSERT_EQUAL(targ->one, 0);
|
||||
CU_ASSERT_EQUAL(targ->two, 2);
|
||||
CU_ASSERT_EQUAL(targ->executed, 1);
|
||||
CU_ASSERT_EQUAL(targ->cancelled, 2);
|
||||
|
||||
ddsrt_free(targ);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_thread_cleanup, push_two_pop_two_exec_both)
|
||||
{
|
||||
int flags = THREAD_RESET_1 | THREAD_RESET_2 | THREAD_RUN_1 | THREAD_RUN_2;
|
||||
struct thread_argument *targ = make_thread_argument(flags, 2, 1, 2);
|
||||
setup(targ);
|
||||
|
||||
CU_ASSERT_EQUAL(targ->one, 0);
|
||||
CU_ASSERT_EQUAL(targ->two, 0);
|
||||
CU_ASSERT_EQUAL(targ->executed, 2);
|
||||
CU_ASSERT_EQUAL(targ->cancelled, 2);
|
||||
|
||||
ddsrt_free(targ);
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_thread_cleanup, no_interference)
|
||||
{
|
||||
int flags = THREAD_RESET_1 | THREAD_RESET_2;
|
||||
struct thread_argument *targ1 = make_thread_argument(flags, 0, 1, 2);
|
||||
struct thread_argument *targ2 = make_thread_argument(flags, 2, 1, 2);
|
||||
ddsrt_mutex_t mutex1, mutex2;
|
||||
|
||||
ddsrt_mutex_init(&mutex1);
|
||||
ddsrt_mutex_init(&mutex2);
|
||||
ddsrt_mutex_lock(&mutex1);
|
||||
ddsrt_mutex_lock(&mutex2);
|
||||
|
||||
targ1->mutex = &mutex1;
|
||||
targ1->block = 1;
|
||||
targ2->mutex = &mutex2;
|
||||
targ2->block = 1;
|
||||
|
||||
setup(targ1);
|
||||
setup(targ2);
|
||||
|
||||
/* ensure thread 2 pops it's cleanup routines while thread 1 blocks */
|
||||
ddsrt_mutex_unlock(&mutex2);
|
||||
ddsrt_thread_join(targ2->thread, NULL);
|
||||
|
||||
CU_ASSERT_EQUAL(targ2->one, 1);
|
||||
CU_ASSERT_EQUAL(targ2->two, 2);
|
||||
CU_ASSERT_EQUAL(targ2->executed, 0);
|
||||
CU_ASSERT_EQUAL(targ2->cancelled, 2);
|
||||
|
||||
/* instruct thread 1 to continue */
|
||||
ddsrt_mutex_unlock(&mutex1);
|
||||
ddsrt_thread_join(targ1->thread, NULL);
|
||||
|
||||
CU_ASSERT_EQUAL(targ1->one, 0);
|
||||
CU_ASSERT_EQUAL(targ1->two, 0);
|
||||
CU_ASSERT_EQUAL(targ1->executed, 2);
|
||||
CU_ASSERT_EQUAL(targ1->cancelled, 0);
|
||||
|
||||
ddsrt_mutex_destroy(&mutex1);
|
||||
ddsrt_mutex_destroy(&mutex2);
|
||||
ddsrt_free(targ1);
|
||||
ddsrt_free(targ2);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue