Merge branch 'master' into merge2
Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>
This commit is contained in:
commit
3fc777e631
477 changed files with 31941 additions and 32175 deletions
|
@ -11,12 +11,44 @@
|
|||
#
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckLibraryExists)
|
||||
include(GenerateDummyExportHeader)
|
||||
|
||||
# Lightweight IP stack can be used on non-embedded targets too, but the
|
||||
# runtime must be instructed to use it instead of the native stack. Of course
|
||||
# for embedded targets there is no "native" stack and the runtime module must
|
||||
# always be instructed to use an "alternative" stack.
|
||||
option(WITH_LWIP "Use lightweight IP stack" OFF)
|
||||
option(WITH_DNS "Enable domain name lookups" ON)
|
||||
option(WITH_FREERTOS "Build for FreeRTOS" OFF)
|
||||
|
||||
function(check_runtime_feature SOURCE_FILE)
|
||||
get_target_property(_defs ddsrt INTERFACE_COMPILE_DEFINITIONS)
|
||||
foreach(_def ${_defs})
|
||||
set(_strdefs "${_strdefs} -D${_def}")
|
||||
endforeach()
|
||||
|
||||
# Generate dummy export header required by feature tests.
|
||||
generate_dummy_export_header(
|
||||
ddsrt
|
||||
BASE_NAME dds
|
||||
EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/cmake/include/dds/export.h")
|
||||
set(_strincs "${CMAKE_CURRENT_BINARY_DIR}/cmake/include")
|
||||
|
||||
get_target_property(_incs ddsrt INTERFACE_INCLUDE_DIRECTORIES)
|
||||
foreach(_inc ${_incs})
|
||||
set(_strincs "${_strincs};${_inc}")
|
||||
endforeach()
|
||||
|
||||
if(_strincs)
|
||||
set(_strincs "-DINCLUDE_DIRECTORIES:STRING=${_strincs}")
|
||||
endif()
|
||||
|
||||
set(expr "cmake_([_a-zA-Z0-9]+)=([_a-zA-Z0-9]+)")
|
||||
try_compile(
|
||||
foo "${CMAKE_BINARY_DIR}"
|
||||
SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}"
|
||||
CMAKE_FLAGS "${_strincs}"
|
||||
COMPILE_DEFINITIONS "${_strdefs}"
|
||||
OUTPUT_VARIABLE output)
|
||||
string(REGEX MATCHALL "${expr}" matches "${output}")
|
||||
foreach(match ${matches})
|
||||
|
@ -26,7 +58,9 @@ function(check_runtime_feature SOURCE_FILE)
|
|||
endforeach()
|
||||
endfunction()
|
||||
|
||||
if(APPLE)
|
||||
if(WITH_FREERTOS)
|
||||
set(system_name freertos)
|
||||
elseif(APPLE)
|
||||
set(system_name darwin)
|
||||
else()
|
||||
string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
|
||||
|
@ -38,6 +72,15 @@ endif()
|
|||
# ship an older version, so an interface library with public sources is used
|
||||
# as a workaround for now.
|
||||
add_library(ddsrt INTERFACE)
|
||||
|
||||
foreach(opt WITH_LWIP WITH_DNS WITH_FREERTOS)
|
||||
if(${opt})
|
||||
target_compile_definitions(ddsrt INTERFACE DDSRT_${opt}=1)
|
||||
else()
|
||||
target_compile_definitions(ddsrt INTERFACE DDSRT_${opt}=0)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
target_include_directories(
|
||||
ddsrt INTERFACE
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
|
@ -69,7 +112,9 @@ list(APPEND headers
|
|||
"${include_path}/dds/ddsrt/dynlib.h"
|
||||
"${include_path}/dds/ddsrt/strtod.h"
|
||||
"${include_path}/dds/ddsrt/strtol.h"
|
||||
"${include_path}/dds/ddsrt/types.h")
|
||||
"${include_path}/dds/ddsrt/types.h"
|
||||
"${include_path}/dds/ddsrt/countargs.h"
|
||||
"${include_path}/dds/ddsrt/static_assert.h")
|
||||
|
||||
list(APPEND sources
|
||||
"${source_path}/io.c"
|
||||
|
@ -79,10 +124,10 @@ list(APPEND sources
|
|||
"${source_path}/strtol.c")
|
||||
|
||||
list(APPEND headers
|
||||
"${source_path}/dds/ddsrt/avl.h"
|
||||
"${source_path}/dds/ddsrt/fibheap.h"
|
||||
"${source_path}/dds/ddsrt/hopscotch.h"
|
||||
"${source_path}/dds/ddsrt/thread_pool.h")
|
||||
"${include_path}/dds/ddsrt/avl.h"
|
||||
"${include_path}/dds/ddsrt/fibheap.h"
|
||||
"${include_path}/dds/ddsrt/hopscotch.h"
|
||||
"${include_path}/dds/ddsrt/thread_pool.h")
|
||||
|
||||
list(APPEND sources
|
||||
"${source_path}/avl.c"
|
||||
|
@ -103,13 +148,13 @@ list(APPEND sources
|
|||
# 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 md5 process dynlib)
|
||||
sockets string sync threads time md5 process netstat dynlib)
|
||||
if(EXISTS "${include_path}/dds/ddsrt/${feature}.h")
|
||||
list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h")
|
||||
file(GLOB
|
||||
file(GLOB_RECURSE
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${include_path}/dds/ddsrt/${feature}/**.h")
|
||||
"${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
|
||||
|
@ -125,10 +170,9 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
|||
# feature does not exist in cmake, the feature is expected to be
|
||||
# implemented for all targets.
|
||||
string(TOUPPER "${feature}" feature_uc)
|
||||
set(HAVE_${feature_uc} TRUE)
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${feature}.c")
|
||||
check_runtime_feature(cmake/${feature}.c)
|
||||
else()
|
||||
set(HAVE_${feature_uc} TRUE)
|
||||
check_runtime_feature("cmake/${feature}.c")
|
||||
endif()
|
||||
|
||||
if(HAVE_${feature_uc})
|
||||
|
@ -138,24 +182,32 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
|||
list(APPEND sources "${source_path}/${feature}.c")
|
||||
endif()
|
||||
set(system_exists FALSE)
|
||||
foreach(system ${system_name} posix)
|
||||
|
||||
# Allow custom implementations for a feature. e.g. lwip as opposed to
|
||||
# windows or posix.
|
||||
set(_system_name "${system_name}")
|
||||
if(NOT HAVE_${feature_uc} MATCHES "[tT][rR][uU][eE]")
|
||||
set(_system_name "${HAVE_${feature_uc}}")
|
||||
endif()
|
||||
|
||||
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
|
||||
file(GLOB_RECURSE
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${source_path}/${feature}/include/**.h")
|
||||
list(APPEND sources ${files})
|
||||
"${source_path}/${feature}/include/*.h")
|
||||
list(APPEND headers ${files})
|
||||
target_include_directories(
|
||||
ddsrt INTERFACE
|
||||
"$<BUILD_INTERFACE:${source_path}/${feature}/include/>")
|
||||
endif()
|
||||
if(IS_DIRECTORY "${source_path}/${feature}/${system}")
|
||||
file(GLOB
|
||||
file(GLOB_RECURSE
|
||||
files
|
||||
CONFIGURE_DEPENDS
|
||||
"${source_path}/${feature}/${system}/**.c")
|
||||
"${source_path}/${feature}/${system}/*.c")
|
||||
list(APPEND sources ${files})
|
||||
set(system_exists TRUE)
|
||||
endif()
|
||||
|
@ -172,12 +224,16 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
|
|||
endif()
|
||||
endforeach()
|
||||
|
||||
target_sources(ddsrt INTERFACE ${sources})
|
||||
target_sources(ddsrt INTERFACE ${sources} ${headers})
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(ddsrt INTERFACE Threads::Threads)
|
||||
target_link_libraries(ddsrt INTERFACE ${CMAKE_DL_LIBS})
|
||||
set(HAVE_MULTI_PROCESS ${HAVE_MULTI_PROCESS} PARENT_SCOPE)
|
||||
|
||||
if(NOT WITH_FREERTOS)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(ddsrt INTERFACE Threads::Threads)
|
||||
target_link_libraries(ddsrt INTERFACE ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi bcrypt)
|
||||
|
|
23
src/ddsrt/cmake/ifaddrs.c
Normal file
23
src/ddsrt/cmake/ifaddrs.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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/ifaddrs.h"
|
||||
|
||||
#if DDSRT_WITH_LWIP
|
||||
# if LWIP_SOCKET
|
||||
# error "cmake_HAVE_IFADDRS=lwip"
|
||||
# else
|
||||
# error "cmake_HAVE_IFADDRS=false"
|
||||
# endif
|
||||
#else
|
||||
# error "cmake_HAVE_IFADDRS=true"
|
||||
#endif
|
||||
|
18
src/ddsrt/cmake/netstat.c
Normal file
18
src/ddsrt/cmake/netstat.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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/netstat.h"
|
||||
|
||||
#if DDSRT_HAVE_NETSTAT
|
||||
# error "cmake_HAVE_NETSTAT=true"
|
||||
#else
|
||||
# error "cmake_HAVE_NETSTAT=false"
|
||||
#endif
|
18
src/ddsrt/cmake/process.c
Normal file
18
src/ddsrt/cmake/process.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 DDSRT_HAVE_MULTI_PROCESS
|
||||
# error "cmake_HAVE_MULTI_PROCESS=true"
|
||||
#else
|
||||
# error "cmake_HAVE_MULTI_PROCESS=false"
|
||||
#endif
|
19
src/ddsrt/cmake/rusage.c
Normal file
19
src/ddsrt/cmake/rusage.c
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
|
||||
*/
|
||||
#include "dds/ddsrt/rusage.h"
|
||||
|
||||
#if DDSRT_HAVE_RUSAGE
|
||||
# error "cmake_HAVE_RUSAGE=TRUE"
|
||||
#else
|
||||
# error "cmake_HAVE_RUSAGE=FALSE"
|
||||
#endif
|
||||
|
|
@ -59,6 +59,34 @@ typedef ddsrt_atomic_uintptr_t ddsrt_atomic_voidp_t;
|
|||
#error "Atomic operations are not supported"
|
||||
#endif
|
||||
|
||||
#if ! DDSRT_HAVE_ATOMIC64
|
||||
/* 64-bit atomics are not supported by all hardware, but it would be a shame not to use them when
|
||||
they are available. That necessitates an alternative implementation when they are not, either in
|
||||
the form of a different implementation where it is used, or as an emulation using a mutex in
|
||||
ddsrt. It seems that the places where they'd be used end up adding a mutex, so an emulation in
|
||||
ddsrt while being able to check whether it is supported by hardware is a sensible approach. */
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x);
|
||||
DDS_EXPORT void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x);
|
||||
DDS_EXPORT void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x);
|
||||
DDS_EXPORT void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_add64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_sub64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT void ddsrt_atomic_and64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_and64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_and64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT void ddsrt_atomic_or64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_or64_ov (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT uint64_t ddsrt_atomic_or64_nv (volatile ddsrt_atomic_uint64_t *x, uint64_t v);
|
||||
DDS_EXPORT int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des);
|
||||
#endif
|
||||
|
||||
void ddsrt_atomics_init (void);
|
||||
void ddsrt_atomics_fini (void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -85,6 +85,9 @@ inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff
|
|||
inline void ddsrt_atomic_add32 (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
(void) ddsrt_atomic_add32_nv (x, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_add32_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return ddsrt_atomic_add32_nv (x, v) - v;
|
||||
}
|
||||
inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v) {
|
||||
(void) ddsrt_atomic_addptr_nv (x, v);
|
||||
}
|
||||
|
@ -115,6 +118,9 @@ inline void ddsrt_atomic_subvoidp (volatile ddsrt_atomic_voidp_t *x, ptrdiff_t v
|
|||
|
||||
/* INC */
|
||||
|
||||
inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return ddsrt_atomic_add32_nv (x, 1) - 1;
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return ddsrt_atomic_add32_nv (x, 1);
|
||||
}
|
||||
|
@ -130,6 +136,9 @@ inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
|||
|
||||
/* DEC */
|
||||
|
||||
inline uint32_t ddsrt_atomic_dec32_ov (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return ddsrt_atomic_sub32_nv (x, 1) + 1;
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_dec32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return ddsrt_atomic_sub32_nv (x, 1);
|
||||
}
|
||||
|
@ -206,6 +215,12 @@ inline void ddsrt_atomic_orptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t v)
|
|||
inline void ddsrt_atomic_fence (void) {
|
||||
__asm volatile ("dmb" : : : "memory");
|
||||
}
|
||||
inline void ddsrt_atomic_fence_ldld (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_stst (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define DDSRT_ATOMICS_GCC_H
|
||||
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
|
@ -25,19 +26,51 @@ extern "C" {
|
|||
|
||||
/* LD, ST */
|
||||
|
||||
inline uint32_t ddsrt_atomic_ld32(const volatile ddsrt_atomic_uint32_t *x) { return x->v; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
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; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
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); }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline uintptr_t ddsrt_atomic_ldptr(const volatile ddsrt_atomic_uintptr_t *x)
|
||||
{
|
||||
return x->v;
|
||||
}
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
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; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
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; }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
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); }
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline void ddsrt_atomic_stptr(volatile ddsrt_atomic_uintptr_t *x, uintptr_t v)
|
||||
{
|
||||
x->v = v;
|
||||
}
|
||||
ddsrt_attribute_no_sanitize (("thread"))
|
||||
inline void ddsrt_atomic_stvoidp(volatile ddsrt_atomic_voidp_t *x, void *v)
|
||||
{
|
||||
ddsrt_atomic_stptr(x, (uintptr_t)v);
|
||||
}
|
||||
|
||||
/* INC */
|
||||
|
||||
|
@ -52,6 +85,9 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
|
|||
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
__sync_fetch_and_add (&x->v, 1);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return __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);
|
||||
}
|
||||
|
@ -116,6 +152,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t 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_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_fetch_and_add (&x->v, 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);
|
||||
}
|
||||
|
@ -147,6 +186,9 @@ inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t 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_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return __sync_fetch_and_sub (&x->v, 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);
|
||||
}
|
||||
|
@ -284,11 +326,24 @@ inline void ddsrt_atomic_fence_ldld (void) {
|
|||
__sync_synchronize ();
|
||||
#endif
|
||||
}
|
||||
inline void ddsrt_atomic_fence_stst (void) {
|
||||
#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
|
||||
__sync_synchronize ();
|
||||
#endif
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
|
||||
ddsrt_atomic_fence ();
|
||||
#else
|
||||
asm volatile ("" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
inline void ddsrt_atomic_fence_rel (void) {
|
||||
#if !(defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64)
|
||||
ddsrt_atomic_fence ();
|
||||
#else
|
||||
asm volatile ("" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
|
|
@ -74,6 +74,9 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
|
|||
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
DDSRT_ATOMIC_PTROP (InterlockedIncrement) (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_ov (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return InterlockedIncrement (&x->v) - 1;
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return InterlockedIncrement (&x->v);
|
||||
}
|
||||
|
@ -138,6 +141,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t 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_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return InterlockedExchangeAdd (&x->v, v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_add32_nv (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return InterlockedExchangeAdd (&x->v, v) + v;
|
||||
}
|
||||
|
@ -157,46 +163,52 @@ inline void *ddsrt_atomic_addvoidp_nv (volatile ddsrt_atomic_voidp_t *x, ptrdiff
|
|||
|
||||
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)
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
InterlockedExchangeAdd (&x->v, -v);
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
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)
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
InterlockedExchangeAdd64 (&x->v, -v);
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
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_WARNING_MSVC_OFF(4146)
|
||||
DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v);
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
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_ov (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);
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
}
|
||||
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)
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
return InterlockedExchangeAdd (&x->v, -v) - v;
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
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)
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
return InterlockedExchangeAdd64 (&x->v, -v) - v;
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
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)
|
||||
DDSRT_WARNING_MSVC_OFF(4146)
|
||||
return DDSRT_ATOMIC_PTROP (InterlockedExchangeAdd) (&x->v, -v) - v;
|
||||
DDSRT_WARNING_MSVC_ON(4146)
|
||||
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);
|
||||
|
@ -280,16 +292,21 @@ 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)
|
||||
DDSRT_WARNING_MSVC_OFF(28113)
|
||||
volatile LONG tmp = 0;
|
||||
InterlockedExchange (&tmp, 0);
|
||||
DDSRT_WARNING_MSVC_ON(28113)
|
||||
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_stst (void) {
|
||||
#if !(defined _M_IX86 || defined _M_X64)
|
||||
ddsrt_atomic_fence ();
|
||||
#endif
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
ddsrt_atomic_fence ();
|
||||
}
|
||||
|
|
|
@ -40,6 +40,11 @@ inline void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
|
|||
inline void ddsrt_atomic_incptr (volatile ddsrt_atomic_uintptr_t *x) {
|
||||
atomic_inc_ulong (&x->v);
|
||||
}
|
||||
inline uint32_t ddsrt_atomic_inc32_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 uint32_t ddsrt_atomic_inc32_nv (volatile ddsrt_atomic_uint32_t *x) {
|
||||
return atomic_inc_32_nv (&x->v);
|
||||
}
|
||||
|
@ -100,6 +105,9 @@ inline void ddsrt_atomic_addptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t 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_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return atomic_add_32_nv (&x->v, 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);
|
||||
}
|
||||
|
@ -127,6 +135,9 @@ inline void ddsrt_atomic_subptr (volatile ddsrt_atomic_uintptr_t *x, uintptr_t 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_ov (volatile ddsrt_atomic_uint32_t *x, uint32_t v) {
|
||||
return atomic_add_32_nv (&x->v, -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);
|
||||
}
|
||||
|
@ -234,7 +245,10 @@ inline void ddsrt_atomic_fence (void) {
|
|||
membar_enter ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_ldld (void) {
|
||||
membar_enter ();
|
||||
membar_consumer ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_stst (void) {
|
||||
membar_producer ();
|
||||
}
|
||||
inline void ddsrt_atomic_fence_acq (void) {
|
||||
membar_enter ();
|
||||
|
|
|
@ -105,4 +105,22 @@
|
|||
# define ddsrt_attribute_assume_aligned(params)
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(packed)
|
||||
# define ddsrt_attribute_packed __attribute__ ((__packed__))
|
||||
#else
|
||||
# define ddsrt_attribute_packed
|
||||
#endif
|
||||
|
||||
#if ddsrt_has_attribute(no_sanitize)
|
||||
# define ddsrt_attribute_no_sanitize(params) __attribute__ ((__no_sanitize__ params))
|
||||
#else
|
||||
# define ddsrt_attribute_no_sanitize(params)
|
||||
#endif
|
||||
|
||||
#if defined(__has_feature)
|
||||
# define ddsrt_has_feature_thread_sanitizer __has_feature(thread_sanitizer)
|
||||
#else
|
||||
# define ddsrt_has_feature_thread_sanitizer 0
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_ATTRIBUTES_H */
|
||||
|
|
20
src/ddsrt/include/dds/ddsrt/countargs.h
Normal file
20
src/ddsrt/include/dds/ddsrt/countargs.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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_COUNTARGS_H
|
||||
#define DDSRT_COUNTARGS_H
|
||||
|
||||
#define DDSRT_COUNT_ARGS_MSVC_WORKAROUND(x) x
|
||||
#define DDSRT_COUNT_ARGS(...) DDSRT_COUNT_ARGS1 (__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1,0)
|
||||
#define DDSRT_COUNT_ARGS1(...) DDSRT_COUNT_ARGS_MSVC_WORKAROUND (DDSRT_COUNT_ARGS_ARGN (__VA_ARGS__))
|
||||
#define DDSRT_COUNT_ARGS_ARGN(a,b,c,d,e,f,g,h,i,j,n,...) n
|
||||
|
||||
#endif
|
|
@ -47,7 +47,7 @@ typedef struct ddsrt_dynlib *ddsrt_dynlib_t;
|
|||
* @param[in] translate Automatic name translation on/off.
|
||||
* @param[out] handle Library handle that will be assigned after successfull operation. It is assigned to NULL if loading fails.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Library handle was successfully loaded.
|
||||
|
@ -57,7 +57,7 @@ typedef struct ddsrt_dynlib *ddsrt_dynlib_t;
|
|||
* Loading failed.
|
||||
* Use ddsrt_dlerror() to diagnose the failure.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_dlopen(
|
||||
const char *name,
|
||||
bool translate,
|
||||
|
@ -73,7 +73,7 @@ ddsrt_dlopen(
|
|||
*
|
||||
* @param[in] handle Library handle.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Library handle was successfully closed.
|
||||
|
@ -81,7 +81,7 @@ ddsrt_dlopen(
|
|||
* Library closing failed.
|
||||
* Use ddsrt_dlerror() to diagnose the failure.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_dlclose(
|
||||
ddsrt_dynlib_t handle);
|
||||
|
||||
|
@ -95,7 +95,7 @@ ddsrt_dlclose(
|
|||
* @param[in] symbol Symbol name.
|
||||
* @param[out] address The memory address of the loaded symbol (void*).
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Symbol was found in the loaded library.
|
||||
|
@ -104,7 +104,7 @@ ddsrt_dlclose(
|
|||
* Symbol was not found.
|
||||
* Use ddsrt_dlerror() to diagnose the failure.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_dlsym(
|
||||
ddsrt_dynlib_t handle,
|
||||
const char *symbol,
|
||||
|
@ -124,14 +124,14 @@ ddsrt_dlsym(
|
|||
* function should be called immediately after calling ddsrt_dlopen or ddsrt_dlsym
|
||||
* function.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Most recent library related error returned.
|
||||
* @retval DDS_RETCODE_NOT_FOUND
|
||||
* No library related error found.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_dlerror(
|
||||
char *buf,
|
||||
size_t buflen);
|
||||
|
|
|
@ -25,7 +25,15 @@ extern "C" {
|
|||
# else
|
||||
# define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN
|
||||
# endif
|
||||
#else /* _WIN32 */
|
||||
/* _WIN32 */
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
# if __LITTLE_ENDIAN__ == 1
|
||||
# define DDSRT_ENDIAN DDSRT_LITTLE_ENDIAN
|
||||
# else
|
||||
# define DDSRT_ENDIAN DDSRT_BIG_ENDIAN
|
||||
# endif
|
||||
/* __IAR_SYSTEMS_ICC__ */
|
||||
#else
|
||||
# if defined(__BYTE_ORDER__)
|
||||
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define DDSRT_ENDIAN DDSRT_BIG_ENDIAN
|
||||
|
|
|
@ -24,13 +24,9 @@ extern "C" {
|
|||
* @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.
|
||||
* @param[out] value Alias to value of environment variable - must not be modified
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Environment variable written to @buf.
|
||||
|
@ -43,7 +39,7 @@ extern "C" {
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Unspecified error.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_getenv(
|
||||
const char *name,
|
||||
char **value)
|
||||
|
@ -58,7 +54,7 @@ ddsrt_nonnull_all;
|
|||
* @param[in] name Environment variable name.
|
||||
* @param[in] value Value to set environment variable to.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Environment variable successfully set to @value.
|
||||
|
@ -69,7 +65,7 @@ ddsrt_nonnull_all;
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Unspecified system error.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_setenv(
|
||||
const char *name,
|
||||
const char *value)
|
||||
|
@ -80,7 +76,7 @@ ddsrt_nonnull_all;
|
|||
*
|
||||
* @param[in] name Environment variable name.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Environment variable successfully unset.
|
||||
|
@ -91,7 +87,7 @@ ddsrt_nonnull_all;
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Unspecified system error.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_unsetenv(
|
||||
const char *name)
|
||||
ddsrt_nonnull_all;
|
||||
|
@ -104,6 +100,10 @@ ddsrt_nonnull_all;
|
|||
* The result string should be freed with ddsrt_free().
|
||||
*
|
||||
* @param[in] string String to expand.
|
||||
* @param[in] domid Domain id that this is relevant to
|
||||
* UINT32_MAX means none (see logging)
|
||||
* also made available as
|
||||
* ${CYCLONEDDS_DOMAIN_ID}
|
||||
*
|
||||
* @returns Allocated char*.
|
||||
*
|
||||
|
@ -115,7 +115,8 @@ ddsrt_nonnull_all;
|
|||
*/
|
||||
DDS_EXPORT char*
|
||||
ddsrt_expand_envvars(
|
||||
const char *string);
|
||||
const char *string,
|
||||
uint32_t domid);
|
||||
|
||||
/**
|
||||
* @brief Expand environment variables within string.
|
||||
|
@ -137,7 +138,8 @@ ddsrt_expand_envvars(
|
|||
*/
|
||||
DDS_EXPORT char*
|
||||
ddsrt_expand_envvars_sh(
|
||||
const char *string);
|
||||
const char *string,
|
||||
uint32_t domid);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -20,15 +20,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Concurrent version */
|
||||
struct ddsrt_chh;
|
||||
struct ddsrt_chh_bucket;
|
||||
struct ddsrt_chh_iter {
|
||||
struct ddsrt_chh_bucket *bs;
|
||||
uint32_t size;
|
||||
uint32_t cursor;
|
||||
};
|
||||
|
||||
/*
|
||||
* The hopscotch hash table is dependent on a proper functioning hash.
|
||||
* If the hash function generates a lot of hash collisions, then it will
|
||||
|
@ -39,29 +30,20 @@ struct ddsrt_chh_iter {
|
|||
* When proper distributed hash values are generated, then hopscotch
|
||||
* works nice and quickly.
|
||||
*/
|
||||
typedef uint32_t (*ddsrt_hh_hash_fn) (const void *);
|
||||
typedef uint32_t (*ddsrt_hh_hash_fn) (const void *a);
|
||||
|
||||
/*
|
||||
* Hopscotch needs to be able to compare two elements.
|
||||
* Returns 0 when not equal.
|
||||
*/
|
||||
typedef int (*ddsrt_hh_equals_fn) (const void *, const void *);
|
||||
typedef int (*ddsrt_hh_equals_fn) (const void *a, const void *b);
|
||||
|
||||
/*
|
||||
* Hopscotch is will resize its internal buckets list when needed. It will
|
||||
* call this garbage collection function with the old buckets list. The
|
||||
* caller has to delete the list when it deems it safe to do so.
|
||||
*/
|
||||
typedef void (*ddsrt_hh_buckets_gc_fn) (void *);
|
||||
|
||||
DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets);
|
||||
DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh);
|
||||
DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data);
|
||||
DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */
|
||||
void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it);
|
||||
void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it);
|
||||
typedef void (*ddsrt_hh_buckets_gc_fn) (void *bs, void *arg);
|
||||
|
||||
/* Sequential version */
|
||||
struct ddsrt_hh;
|
||||
|
@ -80,6 +62,31 @@ DDS_EXPORT void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void
|
|||
DDS_EXPORT void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter); /* may delete nodes */
|
||||
DDS_EXPORT void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter);
|
||||
|
||||
/* Concurrent version */
|
||||
struct ddsrt_chh;
|
||||
struct ddsrt_chh_bucket;
|
||||
|
||||
#if ! ddsrt_has_feature_thread_sanitizer
|
||||
struct ddsrt_chh_iter {
|
||||
struct ddsrt_chh_bucket *bs;
|
||||
uint32_t size;
|
||||
uint32_t cursor;
|
||||
};
|
||||
#else
|
||||
struct ddsrt_chh_iter {
|
||||
struct ddsrt_chh *chh;
|
||||
struct ddsrt_hh_iter it;
|
||||
};
|
||||
#endif
|
||||
|
||||
DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets, void *gc_buckets_arg);
|
||||
DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh);
|
||||
DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data);
|
||||
DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template);
|
||||
DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */
|
||||
DDS_EXPORT void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it);
|
||||
DDS_EXPORT void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it);
|
||||
/* Sequential version, embedded data */
|
||||
struct ddsrt_ehh;
|
||||
|
||||
|
|
|
@ -18,11 +18,18 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum ddsrt_iftype {
|
||||
DDSRT_IFTYPE_UNKNOWN,
|
||||
DDSRT_IFTYPE_WIRED,
|
||||
DDSRT_IFTYPE_WIFI
|
||||
};
|
||||
|
||||
struct ddsrt_ifaddrs {
|
||||
struct ddsrt_ifaddrs *next;
|
||||
char *name;
|
||||
uint32_t index;
|
||||
uint32_t flags;
|
||||
enum ddsrt_iftype type;
|
||||
struct sockaddr *addr;
|
||||
struct sockaddr *netmask;
|
||||
struct sockaddr *broadaddr;
|
||||
|
@ -30,7 +37,7 @@ struct ddsrt_ifaddrs {
|
|||
|
||||
typedef struct ddsrt_ifaddrs ddsrt_ifaddrs_t;
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const int *afs);
|
||||
|
|
|
@ -92,6 +92,8 @@ extern "C" {
|
|||
typedef struct {
|
||||
/** Log category the message falls into. */
|
||||
uint32_t priority;
|
||||
/** Log domain id, UINT32_MAX is global. */
|
||||
uint32_t domid;
|
||||
/** Filename where message was generated. */
|
||||
const char *file;
|
||||
/** Line number in file where message was generated. */
|
||||
|
@ -102,10 +104,38 @@ typedef struct {
|
|||
const char *message;
|
||||
/** Size of log message. */
|
||||
size_t size;
|
||||
/** Default log message header length */
|
||||
size_t hdrsize;
|
||||
} 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 *);
|
||||
typedef void (*dds_log_write_fn_t) (void *, const dds_log_data_t *);
|
||||
|
||||
/** Semi-opaque type for log/trace configuration. */
|
||||
struct ddsrt_log_cfg_common {
|
||||
/** Mask for testing whether the xLOG macro should forward to the
|
||||
function (and so incur the cost of constructing the parameters).
|
||||
Messages in DDS_LOG_MASK are rare, so the overhead of calling
|
||||
the function and then dropping the message is not an issue, unlike
|
||||
for messages in DDS_TRACE_MASK. */
|
||||
uint32_t mask;
|
||||
|
||||
/** The actual configured trace mask */
|
||||
uint32_t tracemask;
|
||||
|
||||
/** Domain id for reporting; UINT32_MAX = no domain */
|
||||
uint32_t domid;
|
||||
};
|
||||
|
||||
typedef struct ddsrt_log_cfg {
|
||||
struct ddsrt_log_cfg_common c;
|
||||
union {
|
||||
dds_log_write_fn_t fnptr;
|
||||
void *ptr;
|
||||
uint32_t u32;
|
||||
unsigned char pad[72];
|
||||
} u;
|
||||
} ddsrt_log_cfg_t;
|
||||
|
||||
DDS_EXPORT extern uint32_t *const dds_log_mask;
|
||||
|
||||
|
@ -186,14 +216,84 @@ dds_set_trace_sink(
|
|||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Write a log or trace message.
|
||||
* @brief Initialize a struct ddsrt_log_cfg for use with dds_log_cfg
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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[out] cfg On return, initialised to make dds_log_cfg invoked
|
||||
* with this config object behave as specified by the
|
||||
* other parameters.
|
||||
* @param[in] domid Numerical identifier in log/trace, UINT32_MAX is
|
||||
* reserved for global logging.
|
||||
* @param[in] tracemask Mask determining which traces should be written.
|
||||
* @param[in] log_fp File for default sink.
|
||||
* @param[in] trace_fp File for default sink.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_log_cfg_init(
|
||||
struct ddsrt_log_cfg *cfg,
|
||||
uint32_t domid,
|
||||
uint32_t tracemask,
|
||||
FILE *log_fp,
|
||||
FILE *trace_fp);
|
||||
|
||||
/**
|
||||
* @brief Write a log or trace message for a specific logging configuraiton
|
||||
* (categories, id, sinks).
|
||||
*
|
||||
* Direct use of #dds_log is discouraged. Use #DDS_CINFO, #DDS_CWARNING,
|
||||
* #DDS_CERROR, #DDS_CTRACE or #DDS_CLOG instead.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_log_cfg(
|
||||
const struct ddsrt_log_cfg *cfg,
|
||||
uint32_t prio,
|
||||
const char *file,
|
||||
uint32_t line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
...)
|
||||
ddsrt_attribute_format((__printf__, 6, 7));
|
||||
|
||||
/**
|
||||
* @brief Write a log or trace message to the global configuration but with
|
||||
* specific domain (intended solely for use during domain start-up, while
|
||||
* the domain-specific logging/tracing hasn't been set yet).
|
||||
*
|
||||
* Write a log or trace message to one (or both) of the currently active sinks.
|
||||
*
|
||||
* Direct use of #dds_log_id is discouraged. Use #DDS_ILOG instead.
|
||||
*/
|
||||
DDS_EXPORT void
|
||||
dds_log_id(
|
||||
uint32_t prio,
|
||||
uint32_t domid,
|
||||
const char *file,
|
||||
uint32_t line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
...)
|
||||
ddsrt_attribute_format((__printf__, 6, 7));
|
||||
|
||||
/**
|
||||
* @brief Write a log or trace message to the global log/trace.
|
||||
*
|
||||
* 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_EXPORT void
|
||||
dds_log(
|
||||
uint32_t prio,
|
||||
const char *file,
|
||||
|
@ -279,23 +379,70 @@ dds_log(
|
|||
*/
|
||||
#define DDS_LOG(cat, ...) \
|
||||
((dds_get_log_mask() & (cat)) ? \
|
||||
dds_log(cat, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
|
||||
dds_log((cat), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
|
||||
|
||||
/** Write a log message of type #DDS_LC_INFO. */
|
||||
/**
|
||||
* @brief Write a log message with a domain id override.
|
||||
*
|
||||
* 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_ILOG(cat, domid, ...) \
|
||||
((dds_get_log_mask() & (cat)) ? \
|
||||
dds_log_id((cat), (domid), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
|
||||
|
||||
/**
|
||||
* @brief Write a log message using a specific config.
|
||||
*
|
||||
* 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_CLOG(cat, cfg, ...) \
|
||||
(((cfg)->c.mask & (cat)) ? \
|
||||
dds_log_cfg((cfg), (cat), __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) : 0)
|
||||
|
||||
/** Write a log message of type #DDS_LC_INFO into global log. */
|
||||
#define DDS_INFO(...) \
|
||||
DDS_LOG(DDS_LC_INFO, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_WARNING. */
|
||||
/** Write a log message of type #DDS_LC_WARNING into global log. */
|
||||
#define DDS_WARNING(...) \
|
||||
DDS_LOG(DDS_LC_WARNING, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_ERROR. */
|
||||
/** Write a log message of type #DDS_LC_ERROR into global log. */
|
||||
#define DDS_ERROR(...) \
|
||||
DDS_LOG(DDS_LC_ERROR, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_ERROR and abort. */
|
||||
/** Write a log message of type #DDS_LC_ERROR into global log 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__)
|
||||
|
||||
/* MSVC mishandles __VA_ARGS__ while claiming to be conforming -- and even
|
||||
if they have a defensible implement, they still differ from every other
|
||||
compiler out there. An extra layer of macro expansion works around it. */
|
||||
#define DDS_CLOG_MSVC_WORKAROUND(x) x
|
||||
|
||||
/** Write a log message of type #DDS_LC_INFO using specific logging config. */
|
||||
#define DDS_CINFO(...) \
|
||||
DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_INFO, __VA_ARGS__))
|
||||
/** Write a log message of type #DDS_LC_WARNING using specific logging config. */
|
||||
#define DDS_CWARNING(...) \
|
||||
DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_WARNING, __VA_ARGS__))
|
||||
/** Write a log message of type #DDS_LC_ERROR using specific logging config. */
|
||||
#define DDS_CERROR(...) \
|
||||
DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_ERROR, __VA_ARGS__))
|
||||
/** Write a #DDS_LC_TRACE message using specific logging config. */
|
||||
#define DDS_CTRACE(...) \
|
||||
DDS_CLOG_MSVC_WORKAROUND(DDS_CLOG(DDS_LC_TRACE, __VA_ARGS__))
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
@ -18,29 +18,45 @@
|
|||
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_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
|
||||
#if defined(__clang__) || \
|
||||
defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
|
||||
# define DDSRT_STR(s) #s
|
||||
# define DDSRT_JOINSTR(x,y) DDSRT_STR(x ## y)
|
||||
# define DDSRT_DO_PRAGMA(x) _Pragma(#x)
|
||||
# define DDSRT_PRAGMA(x) DDSRT_DO_PRAGMA(GCC diagnostic x)
|
||||
|
||||
# if defined(__clang__)
|
||||
# define DDSRT_WARNING_CLANG_OFF(x) \
|
||||
DDSRT_PRAGMA(push) \
|
||||
DDSRT_PRAGMA(ignored DDSRT_JOINSTR(-W,x))
|
||||
# define DDSRT_WARNING_CLANG_ON(x) \
|
||||
DDSRT_PRAGMA(pop)
|
||||
# elif ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
|
||||
# define DDSRT_WARNING_GNUC_OFF(x) \
|
||||
DDSRT_GNUC_PRAGMA(push) \
|
||||
DDSRT_GNUC_PRAGMA(ignored DDSRT_GNUC_JOINSTR(-W,x))
|
||||
DDSRT_PRAGMA(push) \
|
||||
DDSRT_PRAGMA(ignored DDSRT_JOINSTR(-W,x))
|
||||
# define DDSRT_WARNING_GNUC_ON(x) \
|
||||
DDSRT_GNUC_PRAGMA(pop)
|
||||
DDSRT_PRAGMA(pop)
|
||||
# else
|
||||
# define DDSRT_WARNING_GNUC_OFF(x) \
|
||||
DDSRT_GNUC_PRAGMA(ignored DDSRT_GNUC_JOINSTR(-W,x))
|
||||
DDSRT_PRAGMA(ignored DDSRT_JOINSTR(-W,x))
|
||||
# define DDSRT_WARNING_GNUC_ON(x) \
|
||||
DDSRT_GNUC_PRAGMA(warning DDSRT_GNUC_JOINSTR(-W,x))
|
||||
DDSRT_PRAGMA(warning DDSRT_JOINSTR(-W,x))
|
||||
# endif
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if !defined(DDSRT_WARNING_CLANG_OFF) && \
|
||||
!defined(DDSRT_WARNING_CLANG_ON)
|
||||
# define DDSRT_WARNING_CLANG_OFF(x)
|
||||
# define DDSRT_WARNING_CLANG_ON(x)
|
||||
#endif
|
||||
|
||||
#if !defined(DDSRT_WARNING_GNUC_OFF) && \
|
||||
!defined(DDSRT_WARNING_GNUC_ON)
|
||||
# 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)) \
|
||||
|
@ -52,23 +68,6 @@ extern "C" {
|
|||
# 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
|
||||
*/
|
||||
|
|
73
src/ddsrt/include/dds/ddsrt/netstat.h
Normal file
73
src/ddsrt/include/dds/ddsrt/netstat.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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_NETSTAT_H
|
||||
#define DDSRT_NETSTAT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#if defined (__linux) || defined (__APPLE__) || defined (_WIN32)
|
||||
#define DDSRT_HAVE_NETSTAT (1)
|
||||
#else
|
||||
#define DDSRT_HAVE_NETSTAT (0)
|
||||
#endif
|
||||
|
||||
#if DDSRT_HAVE_NETSTAT
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ddsrt_netstat {
|
||||
uint64_t ipkt;
|
||||
uint64_t opkt;
|
||||
uint64_t ibytes;
|
||||
uint64_t obytes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Platform dependent control structure for network statistics
|
||||
*/
|
||||
struct ddsrt_netstat_control;
|
||||
|
||||
/**
|
||||
* @brief Prepare for gathering network statistics for specified interface.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_netstat_new (
|
||||
struct ddsrt_netstat_control **control,
|
||||
const char *device);
|
||||
|
||||
/**
|
||||
* @brief Release resources for gathering network statistics.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_netstat_free (
|
||||
struct ddsrt_netstat_control *control);
|
||||
|
||||
/**
|
||||
* @brief Get network statistics.
|
||||
*/
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_netstat_get (
|
||||
struct ddsrt_netstat_control *control,
|
||||
struct ddsrt_netstat *stats);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_HAVE_NETSTAT */
|
||||
|
||||
#endif /* DDSRT_NETSTAT_H */
|
|
@ -17,19 +17,30 @@
|
|||
#include "dds/ddsrt/types.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if DDSRT_WITH_FREERTOS
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
typedef TaskHandle_t ddsrt_pid_t; /* typedef void *TaskHandle_t */
|
||||
#define PRIdPID "p"
|
||||
#define DDSRT_HAVE_MULTI_PROCESS 0
|
||||
/* DDSRT_WITH_FREERTOS */
|
||||
#elif defined(_WIN32)
|
||||
typedef DWORD ddsrt_pid_t;
|
||||
#define PRIdPID "u"
|
||||
#else /* _WIN32 */
|
||||
#define DDSRT_HAVE_MULTI_PROCESS 1
|
||||
/* _WIN32 */
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#if defined(_WRS_KERNEL)
|
||||
typedef RTP_ID ddsrt_pid_t; /* typedef struct wind_rtp *RTP_ID */
|
||||
#define PRIdPID PRIuPTR
|
||||
#define DDSRT_HAVE_MULTI_PROCESS 0
|
||||
#else
|
||||
typedef pid_t ddsrt_pid_t;
|
||||
#define PRIdPID "d"
|
||||
#define DDSRT_HAVE_MULTI_PROCESS 1
|
||||
#endif
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
@ -44,6 +55,7 @@ extern "C" {
|
|||
DDS_EXPORT ddsrt_pid_t
|
||||
ddsrt_getpid(void);
|
||||
|
||||
#if DDSRT_HAVE_MULTI_PROCESS
|
||||
|
||||
/**
|
||||
* @brief Create new process.
|
||||
|
@ -60,7 +72,7 @@ ddsrt_getpid(void);
|
|||
* @param[in] argv Arguments array.
|
||||
* @param[out] pid ID of the created process.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Process successfully created.
|
||||
|
@ -73,7 +85,7 @@ ddsrt_getpid(void);
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Process could not be created.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_proc_create(
|
||||
const char *executable,
|
||||
char *const argv[],
|
||||
|
@ -94,10 +106,10 @@ ddsrt_proc_create(
|
|||
* See ddsrt_proc_waitpids() for waiting on all child processes.
|
||||
*
|
||||
* @param[in] pid Process ID (PID) to get the exit code from.
|
||||
* @param[in] timemout Time within the process is expected to finish.
|
||||
* @param[in] timeout Time within the process is expected to finish.
|
||||
* @param[out] code The exit code of the process.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Process has terminated and its exit code has been captured.
|
||||
|
@ -112,7 +124,7 @@ ddsrt_proc_create(
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Getting the exit code failed for an unknown reason.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_proc_waitpid(
|
||||
ddsrt_pid_t pid,
|
||||
dds_duration_t timeout,
|
||||
|
@ -133,11 +145,11 @@ ddsrt_proc_waitpid(
|
|||
*
|
||||
* See ddsrt_proc_waitpid() for waiting on a specific child process.
|
||||
*
|
||||
* @param[in] timemout Time within a process is expected to finish.
|
||||
* @param[in] timeout Time within a process is expected to finish.
|
||||
* @param[out] pid Process ID (PID) of the finished process.
|
||||
* @param[out] code The exit code of the process.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* A process has terminated.
|
||||
|
@ -153,7 +165,7 @@ ddsrt_proc_waitpid(
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Getting the exit code failed for an unknown reason.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_proc_waitpids(
|
||||
dds_duration_t timeout,
|
||||
ddsrt_pid_t *pid,
|
||||
|
@ -164,7 +176,7 @@ ddsrt_proc_waitpids(
|
|||
*
|
||||
* @param[in] pid Process ID (PID) to check if it exists.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* The process exists.
|
||||
|
@ -173,7 +185,7 @@ ddsrt_proc_waitpids(
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Determining if a process exists or not, failed.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_proc_exists(
|
||||
ddsrt_pid_t pid);
|
||||
|
||||
|
@ -190,7 +202,7 @@ ddsrt_proc_exists(
|
|||
*
|
||||
* @param[in] pid Process ID (PID) of the process to terminate.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Kill attempt has been started.
|
||||
|
@ -201,10 +213,11 @@ ddsrt_proc_exists(
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* Kill failed for an unknown reason.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_proc_kill(
|
||||
ddsrt_pid_t pid);
|
||||
|
||||
#endif /* DDSRT_HAVE_MULTI_PROCESS */
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int32_t dds_retcode_t;
|
||||
typedef int32_t dds_return_t;
|
||||
|
||||
/*
|
||||
State is unchanged following a function call returning an error
|
||||
|
@ -29,25 +29,25 @@ typedef int32_t dds_retcode_t;
|
|||
* @{
|
||||
*/
|
||||
#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 */
|
||||
#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))
|
||||
#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)
|
||||
|
@ -84,11 +84,11 @@ typedef int32_t dds_retcode_t;
|
|||
/**
|
||||
* @brief Takes the error value and outputs a string corresponding to it.
|
||||
*
|
||||
* @param[in] err Error value to be converted to a string
|
||||
* @param[in] ret 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);
|
||||
DDS_EXPORT const char *dds_strretcode(dds_return_t ret);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
@ -14,8 +14,23 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
#if DDSRT_WITH_FREERTOS
|
||||
#include <FreeRTOS.h>
|
||||
# if configUSE_TRACE_FACILITY == 1 && \
|
||||
configGENERATE_RUN_TIME_STATS == 1
|
||||
# define DDSRT_HAVE_RUSAGE 1
|
||||
# else
|
||||
# define DDSRT_HAVE_RUSAGE 0
|
||||
#endif
|
||||
#elif defined (_WIN32) || defined (__linux) || defined (__APPLE__)
|
||||
# define DDSRT_HAVE_RUSAGE 1
|
||||
#else
|
||||
# define DDSRT_HAVE_RUSAGE 0
|
||||
#endif
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
|
@ -31,8 +46,10 @@ typedef struct {
|
|||
size_t nivcsw; /* Involuntary context switches. Not maintained on Windows. */
|
||||
} ddsrt_rusage_t;
|
||||
|
||||
#define DDSRT_RUSAGE_SELF (0)
|
||||
#define DDSRT_RUSAGE_THREAD (1)
|
||||
enum ddsrt_getrusage_who {
|
||||
DDSRT_RUSAGE_SELF,
|
||||
DDSRT_RUSAGE_THREAD
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get resource usage for the current thread or process.
|
||||
|
@ -40,7 +57,7 @@ typedef struct {
|
|||
* @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.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Resource usage successfully returned in @usage.
|
||||
|
@ -49,7 +66,26 @@ typedef struct {
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* An unidentified error occurred.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage);
|
||||
DDS_EXPORT dds_return_t ddsrt_getrusage(enum ddsrt_getrusage_who who, ddsrt_rusage_t *usage);
|
||||
|
||||
#if DDSRT_HAVE_THREAD_LIST
|
||||
/**
|
||||
* @brief Get resource usage for some thread.
|
||||
*
|
||||
* @param[in] tid id of the thread of to get the resource usage for
|
||||
* @param[in] usage Structure where resource usage is returned.
|
||||
*
|
||||
* @returns A dds_return_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_return_t ddsrt_getrusage_anythread (ddsrt_thread_list_id_t tid, ddsrt_rusage_t * __restrict usage);
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#if !defined(DDSRT_WITH_DNS)
|
||||
# define DDSRT_WITH_DNS 1
|
||||
#endif
|
||||
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/types.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
@ -28,53 +32,53 @@ extern const struct in6_addr ddsrt_in6addr_loopback;
|
|||
|
||||
#define DDSRT_AF_TERM (-1)
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_gethostname(
|
||||
char *hostname,
|
||||
size_t buffersize);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_socket(
|
||||
ddsrt_socket_t *sockptr,
|
||||
int domain,
|
||||
int type,
|
||||
int protocol);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_close(
|
||||
ddsrt_socket_t sock);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_connect(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_accept(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen,
|
||||
ddsrt_socket_t *connptr);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_listen(
|
||||
ddsrt_socket_t sock,
|
||||
int backlog);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_bind(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_getsockname(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
socklen_t *addrlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_send(
|
||||
ddsrt_socket_t sock,
|
||||
const void *buf,
|
||||
|
@ -82,14 +86,14 @@ ddsrt_send(
|
|||
int flags,
|
||||
ssize_t *sent);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_sendmsg(
|
||||
ddsrt_socket_t sock,
|
||||
const ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *sent);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_recv(
|
||||
ddsrt_socket_t sock,
|
||||
void *buf,
|
||||
|
@ -97,14 +101,14 @@ ddsrt_recv(
|
|||
int flags,
|
||||
ssize_t *rcvd);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_recvmsg(
|
||||
ddsrt_socket_t sock,
|
||||
ddsrt_msghdr_t *msg,
|
||||
int flags,
|
||||
ssize_t *rcvd);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_getsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level, /* SOL_SOCKET */
|
||||
|
@ -112,7 +116,7 @@ ddsrt_getsockopt(
|
|||
void *optval,
|
||||
socklen_t *optlen);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_setsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level, /* SOL_SOCKET */
|
||||
|
@ -126,7 +130,7 @@ ddsrt_setsockopt(
|
|||
* @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.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* I/O mode successfully set to (non)blocking.
|
||||
|
@ -137,7 +141,7 @@ ddsrt_setsockopt(
|
|||
* @retval DDS_RETCODE_ERROR
|
||||
* An unknown error error occurred.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_setsocknonblocking(
|
||||
ddsrt_socket_t sock,
|
||||
bool nonblock);
|
||||
|
@ -224,11 +228,11 @@ ddsrt_sockaddr_insamesubnet(
|
|||
const struct sockaddr *mask)
|
||||
ddsrt_nonnull_all;
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_sockaddrfromstr(
|
||||
int af, const char *str, void *sa);
|
||||
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_sockaddrtostr(
|
||||
const void *sa, char *buf, size_t size);
|
||||
|
||||
|
@ -243,9 +247,9 @@ typedef struct {
|
|||
*
|
||||
* @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.
|
||||
* @param[out] hentp Structure of type ddsrt_hostent_t.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Host name successfully resolved to address(es).
|
||||
|
@ -258,7 +262,7 @@ typedef struct {
|
|||
* @retval DDS_RETCODE_TRY_AGAIN
|
||||
* Nonauthoratitative host not found.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_gethostbyname(
|
||||
const char *name,
|
||||
int af,
|
||||
|
|
|
@ -12,12 +12,17 @@
|
|||
#ifndef DDSRT_SOCKETS_POSIX_H
|
||||
#define DDSRT_SOCKETS_POSIX_H
|
||||
|
||||
#if DDSRT_WITH_LWIP
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
|
@ -27,21 +32,51 @@ 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
|
||||
#if LWIP_SOCKET
|
||||
# if LWIP_IPV6
|
||||
# define DDSRT_HAVE_IPV6 1
|
||||
# endif
|
||||
# if LWIP_DNS && LWIP_SOCKET
|
||||
# define DDSRT_HAVE_DNS DDSRT_WITH_DNS
|
||||
# define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS
|
||||
# endif
|
||||
# define DDSRT_HAVE_SSM 0
|
||||
# define DDSRT_HAVE_INET_NTOP 1
|
||||
# define DDSRT_HAVE_INET_PTON 1
|
||||
|
||||
# define IFF_UP 0x1
|
||||
# define IFF_BROADCAST 0x2
|
||||
# define IFF_LOOPBACK 0x8
|
||||
# define IFF_POINTOPOINT 0x10
|
||||
# define IFF_MULTICAST 0x1000
|
||||
#elif __SunOS_5_6
|
||||
# define DDSRT_HAVE_IPV6 0
|
||||
# define DDSRT_HAVE_DNS DDSRT_WITH_DNS
|
||||
# define DDSRT_HAVE_GETADDRINFO 0
|
||||
# define DDSRT_HAVE_SSM 0
|
||||
# define DDSRT_HAVE_INET_NTOP 0
|
||||
# define DDSRT_HAVE_INET_PTON 0
|
||||
#else /* LWIP_SOCKET */
|
||||
# define DDSRT_HAVE_IPV6 1
|
||||
# define DDSRT_HAVE_DNS DDSRT_WITH_DNS
|
||||
# define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS
|
||||
# define DDSRT_HAVE_SSM 1
|
||||
# define DDSRT_HAVE_INET_NTOP 1
|
||||
# define DDSRT_HAVE_INET_PTON 1
|
||||
#endif /* LWIP_SOCKET */
|
||||
|
||||
typedef struct iovec ddsrt_iovec_t;
|
||||
typedef size_t ddsrt_iov_len_t;
|
||||
|
||||
#if defined(__linux)
|
||||
#if defined(__linux) && !LWIP_SOCKET
|
||||
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)
|
||||
#if (defined(__sun) && !defined(_XPG4_2)) || \
|
||||
(defined(LWIP_SOCKET))
|
||||
# define DDSRT_MSGHDR_FLAGS 0
|
||||
#else
|
||||
# define DDSRT_MSGHDR_FLAGS 1
|
||||
|
|
|
@ -12,8 +12,11 @@ typedef SOCKET ddsrt_socket_t;
|
|||
#define DDSRT_INVALID_SOCKET (INVALID_SOCKET)
|
||||
#define PRIdSOCK PRIuPTR
|
||||
|
||||
#define DDSRT_HAVE_IPV6 1
|
||||
#define DDSRT_HAVE_DNS 1
|
||||
#define DDSRT_HAVE_IPV6 1
|
||||
#define DDSRT_HAVE_DNS DDSRT_WITH_DNS
|
||||
#define DDSRT_HAVE_GETADDRINFO DDSRT_WITH_DNS
|
||||
#define DDSRT_HAVE_INET_NTOP 1
|
||||
#define DDSRT_HAVE_INET_PTON 1
|
||||
|
||||
#if defined(NTDDI_VERSION) && \
|
||||
defined(_WIN32_WINNT_WS03) && \
|
||||
|
|
42
src/ddsrt/include/dds/ddsrt/static_assert.h
Normal file
42
src/ddsrt/include/dds/ddsrt/static_assert.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright(c) 2019 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_STATIC_ASSERT_H
|
||||
#define DDSRT_STATIC_ASSERT_H
|
||||
|
||||
/* There are many tricks to use a constant expression to yield an
|
||||
illegal type or expression at compile time, such as zero-sized
|
||||
arrays and duplicate case or enum labels. So this is but one of the
|
||||
many tricks. */
|
||||
|
||||
#define DDSRT_STATIC_ASSERT2(line, pred) \
|
||||
struct static_assert_##line { \
|
||||
char cond[(pred) ? 1 : -1]; \
|
||||
}
|
||||
#define DDSRT_STATIC_ASSERT1(line, pred) \
|
||||
DDSRT_STATIC_ASSERT2 (line, pred)
|
||||
#define DDSRT_STATIC_ASSERT(pred) \
|
||||
DDSRT_STATIC_ASSERT1 (__LINE__, pred)
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define DDSRT_STATIC_ASSERT_CODE(pred) do { switch(0) { case 0: case (pred): ; } } while (0)
|
||||
#else
|
||||
/* Temporarily disabling warning C6326: Potential comparison of a
|
||||
constant with another constant. */
|
||||
#define DDSRT_STATIC_ASSERT_CODE(pred) do { \
|
||||
__pragma (warning (push)) \
|
||||
__pragma (warning (disable : 6326)) \
|
||||
switch(0) { case 0: case (pred): ; } \
|
||||
__pragma (warning (pop)) \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -12,7 +12,6 @@
|
|||
#ifndef DDSRT_STRING_H
|
||||
#define DDSRT_STRING_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "dds/export.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
@ -53,21 +52,6 @@ ddsrt_strncasecmp(
|
|||
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.
|
||||
*
|
||||
|
@ -75,7 +59,7 @@ ddsrt_strtok_r(
|
|||
* @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,out] stringp String to extract token from.
|
||||
* @param[in] delim Characters that delimit a token.
|
||||
*
|
||||
* @returns The original value of @stringp.
|
||||
|
@ -154,7 +138,7 @@ ddsrt_nonnull((1,2));
|
|||
* 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,out] dest Destination buffer.
|
||||
* @param[in] src Null terminated string to append to dest.
|
||||
* @param[in] size Number of bytes available in dest.
|
||||
*
|
||||
|
@ -170,8 +154,6 @@ ddsrt_strlcat(
|
|||
size_t size)
|
||||
ddsrt_nonnull((1,2));
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get description for specified system error number.
|
||||
*
|
||||
|
@ -179,7 +161,7 @@ ddsrt_nonnull((1,2));
|
|||
* @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.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Description for @errnum was successfully copied to @buf.
|
||||
|
@ -188,7 +170,7 @@ ddsrt_nonnull((1,2));
|
|||
* @retval DDS_RETCODE_NOT_ENOUGH_SPACE
|
||||
* Buffer was not large enough to hold the description.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_strerror_r(
|
||||
int errnum,
|
||||
char *buf,
|
||||
|
|
|
@ -34,9 +34,9 @@ extern "C" {
|
|||
* character is stored.
|
||||
* @param[out] dblptr A double where the result is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_strtod(const char *nptr, char **endptr, double *dblptr);
|
||||
|
||||
/**
|
||||
|
@ -47,9 +47,9 @@ ddsrt_strtod(const char *nptr, char **endptr, double *dblptr);
|
|||
* character is stored.
|
||||
* @param[out] fltptr A float where the floating-point number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_strtof(const char *nptr, char **endptr, float *fltptr);
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,7 +37,7 @@ extern "C" {
|
|||
* determine from @str.
|
||||
* @param[out] llng A long long integer where the number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
|
@ -46,7 +46,7 @@ extern "C" {
|
|||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_strtoll(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
|
@ -69,7 +69,7 @@ ddsrt_strtoll(
|
|||
* determine from @str.
|
||||
* @param[out] ullng A long long integer where the number is stored.
|
||||
*
|
||||
* @returns A dds_retcode_t indicating success or failure.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
|
@ -78,7 +78,7 @@ ddsrt_strtoll(
|
|||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_strtoull(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
|
@ -91,7 +91,7 @@ ddsrt_strtoull(
|
|||
* @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.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
|
@ -100,7 +100,7 @@ ddsrt_strtoull(
|
|||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_atoll(
|
||||
const char *str,
|
||||
long long *llng);
|
||||
|
@ -111,7 +111,7 @@ ddsrt_atoll(
|
|||
* @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.
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* String successfully converted to an integer.
|
||||
|
@ -120,7 +120,7 @@ ddsrt_atoll(
|
|||
* @retval DDS_RETCODE_OUT_OF_RANGE
|
||||
* String converted to an integer, but was out of range.
|
||||
*/
|
||||
DDS_EXPORT dds_retcode_t
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_atoull(
|
||||
const char *str,
|
||||
unsigned long long *ullng);
|
||||
|
|
|
@ -18,8 +18,12 @@
|
|||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
|
||||
#if _WIN32
|
||||
#if DDSRT_WITH_FREERTOS
|
||||
#include "dds/ddsrt/sync/freertos.h"
|
||||
#elif _WIN32
|
||||
#include "dds/ddsrt/sync/windows.h"
|
||||
#elif __SunOS_5_6
|
||||
#include "dds/ddsrt/sync/solaris2.6.h"
|
||||
#else
|
||||
#include "dds/ddsrt/sync/posix.h"
|
||||
#endif
|
||||
|
|
93
src/ddsrt/include/dds/ddsrt/sync/freertos.h
Normal file
93
src/ddsrt/include/dds/ddsrt/sync/freertos.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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_FREERTOS_H
|
||||
#define DDSRT_SYNC_FREERTOS_H
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
#include <task.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
|
||||
#if (INCLUDE_vTaskSuspend != 1)
|
||||
/* INCLUDE_vTaskSuspend must be set to 1 to make xSemaphoreTake wait
|
||||
indefinitely when passed portMAX_DELAY. See reference manual. */
|
||||
#error "INCLUDE_vTaskSuspend != 1 in FreeRTOSConfig.h"
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t sem;
|
||||
} ddsrt_mutex_t;
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
size_t cnt;
|
||||
size_t off;
|
||||
size_t end;
|
||||
TaskHandle_t *tasks;
|
||||
} ddsrt_tasklist_t;
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t sem;
|
||||
ddsrt_tasklist_t tasks;
|
||||
} ddsrt_cond_t;
|
||||
|
||||
/* This readers-writer lock implementation does not prefer writers over readers
|
||||
or vice versa. Multiple readers are allowed to hold the lock simultaneously
|
||||
and can acquire it directly if no writers are queued. However, if a writer
|
||||
is queued, new readers and writers are queued behind it in order. Any reader
|
||||
that acquires the lock after a writer frees it, notifies the next task. If
|
||||
that task tries to acquire a write lock it waits until the reader frees the
|
||||
lock. However, if the task tries to acquire a read lock it will succeed, and
|
||||
notify the next task, etc. */
|
||||
typedef struct {
|
||||
SemaphoreHandle_t sem;
|
||||
ddsrt_tasklist_t tasks;
|
||||
int32_t state;
|
||||
uint32_t cnt;
|
||||
uint32_t rdcnt;
|
||||
uint32_t wrcnt;
|
||||
} ddsrt_rwlock_t;
|
||||
|
||||
typedef ddsrt_atomic_uint32_t ddsrt_once_t;
|
||||
#define DDSRT_ONCE_INIT { .v = (1<<0) /* ONCE_NOT_STARTED */ }
|
||||
|
||||
|
||||
/* The declarations below are here for tests and must be considered private. */
|
||||
|
||||
/* Number of buckets to grow buffer by. */
|
||||
#define DDSRT_TASKLIST_CHUNK (5)
|
||||
/* Number of buckets to allocate initially. */
|
||||
#define DDSRT_TASKLIST_INITIAL (DDSRT_TASKLIST_CHUNK * 2)
|
||||
|
||||
int ddsrt_tasklist_init(ddsrt_tasklist_t *list);
|
||||
void ddsrt_tasklist_fini(ddsrt_tasklist_t *list);
|
||||
void ddsrt_tasklist_ltrim(ddsrt_tasklist_t *list);
|
||||
void ddsrt_tasklist_rtrim(ddsrt_tasklist_t *list);
|
||||
void ddsrt_tasklist_pack(ddsrt_tasklist_t *list);
|
||||
int ddsrt_tasklist_shrink(ddsrt_tasklist_t *list);
|
||||
int ddsrt_tasklist_grow(ddsrt_tasklist_t *list);
|
||||
ssize_t ddsrt_tasklist_find(ddsrt_tasklist_t *list, TaskHandle_t task);
|
||||
TaskHandle_t ddsrt_tasklist_peek(ddsrt_tasklist_t *list, TaskHandle_t task);
|
||||
TaskHandle_t ddsrt_tasklist_pop(ddsrt_tasklist_t *list, TaskHandle_t task);
|
||||
int ddsrt_tasklist_push(ddsrt_tasklist_t *list, TaskHandle_t task);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_SYNC_FREERTOS_H */
|
44
src/ddsrt/include/dds/ddsrt/sync/solaris2.6.h
Normal file
44
src/ddsrt/include/dds/ddsrt/sync/solaris2.6.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_mutex_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 */
|
|
@ -55,7 +55,7 @@ DDS_EXPORT void ddsrt_thread_pool_purge (ddsrt_thread_pool pool);
|
|||
Note that if the pool queue has reached it's maximum DDS_RETCODE_TRY_AGAIN is returned.
|
||||
*/
|
||||
|
||||
DDS_EXPORT dds_retcode_t ddsrt_thread_pool_submit
|
||||
DDS_EXPORT dds_return_t ddsrt_thread_pool_submit
|
||||
(
|
||||
ddsrt_thread_pool pool, /* Thread pool instance */
|
||||
void (*fn) (void *arg), /* Function to be invoked by thread from pool */
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
#if _WIN32
|
||||
#if DDSRT_WITH_FREERTOS
|
||||
#include "dds/ddsrt/threads/freertos.h"
|
||||
#elif _WIN32
|
||||
#include "dds/ddsrt/threads/windows.h"
|
||||
#else
|
||||
#include "dds/ddsrt/threads/posix.h"
|
||||
|
@ -119,14 +121,14 @@ ddsrt_nonnull_all;
|
|||
* @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.
|
||||
* @returns A dds_return_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
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_thread_create(
|
||||
ddsrt_thread_t *thread,
|
||||
const char *name,
|
||||
|
@ -170,14 +172,14 @@ ddsrt_thread_equal(ddsrt_thread_t t1, ddsrt_thread_t t2);
|
|||
* @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.
|
||||
* @returns A dds_return_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
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_thread_join(
|
||||
ddsrt_thread_t thread,
|
||||
uint32_t *thread_result);
|
||||
|
@ -206,9 +208,58 @@ ddsrt_thread_getname(
|
|||
*
|
||||
* @param[in] name Name for current thread.
|
||||
*/
|
||||
#if DDSRT_HAVE_THREAD_SETNAME
|
||||
DDS_EXPORT void
|
||||
ddsrt_thread_setname(
|
||||
const char *__restrict name);
|
||||
#endif
|
||||
|
||||
#if DDSRT_HAVE_THREAD_LIST
|
||||
/**
|
||||
* @brief Get a list of threads in the calling process
|
||||
*
|
||||
* @param[out] tids Array of size elements to be filled with thread
|
||||
* identifiers, may be NULL if size is 0
|
||||
* @param[in] size The size of the tids array; 0 is allowed
|
||||
*
|
||||
* @returns A dds_return_t indicating the number of threads in the process
|
||||
* or an error code on failure.
|
||||
*
|
||||
* @retval > 0
|
||||
* Number of threads in the process, may be larger than size
|
||||
* tids[0 .. (return - 1)] are valid
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* Something went wrong, contents of tids is undefined
|
||||
* @retval DDS_RETCODE_UNSUPPORTED
|
||||
* Not supported on the platform
|
||||
*/
|
||||
DDS_EXPORT dds_return_t ddsrt_thread_list (ddsrt_thread_list_id_t * __restrict tids, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Get the name of the specified thread (in the calling process)
|
||||
*
|
||||
* @param[in] tid Thread identifier for which the name is sought
|
||||
* @param[out] name Filled with the thread name (or a synthesized one)
|
||||
* on successful return; name is silently truncated
|
||||
* if the actual name is longer than name can hold;
|
||||
* always 0-terminated if size > 0
|
||||
* @param[in] size Number of bytes of name that may be assigned, size
|
||||
* is 0 is allowed, though somewhat useless
|
||||
*
|
||||
* @returns A dds_return_t indicating success or failure.
|
||||
*
|
||||
* @retval DDS_RETCODE_OK
|
||||
* Possibly truncated name is returned as a null-terminated
|
||||
* string in name (provided size > 0).
|
||||
* @retval DDS_RETCODE_NOT_FOUND
|
||||
* Thread not found; the contents of name is unchanged
|
||||
* @retval DDS_RETCODE_ERROR
|
||||
* Unspecified failure, the contents of name is undefined
|
||||
* @retval DDS_RETCODE_UNSUPPORTED
|
||||
* Not supported on the platform
|
||||
*/
|
||||
DDS_EXPORT dds_return_t ddsrt_thread_getname_anythread (ddsrt_thread_list_id_t tid, char *__restrict name, size_t size);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Push cleanup handler onto the cleanup stack
|
||||
|
@ -220,7 +271,7 @@ ddsrt_thread_setname(
|
|||
* @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
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_thread_cleanup_push(
|
||||
void (*routine)(void*),
|
||||
void *arg);
|
||||
|
@ -231,7 +282,7 @@ ddsrt_thread_cleanup_push(
|
|||
* 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
|
||||
DDS_EXPORT dds_return_t
|
||||
ddsrt_thread_cleanup_pop(
|
||||
int execute);
|
||||
|
||||
|
|
36
src/ddsrt/include/dds/ddsrt/threads/freertos.h
Normal file
36
src/ddsrt/include/dds/ddsrt/threads/freertos.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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_THREADS_FREERTOS_H
|
||||
#define DDSRT_THREADS_FREERTOS_H
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#define DDSRT_HAVE_THREAD_SETNAME (0)
|
||||
#define DDSRT_HAVE_THREAD_LIST (0)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TaskHandle_t task;
|
||||
} ddsrt_thread_t;
|
||||
|
||||
typedef UBaseType_t ddsrt_tid_t;
|
||||
#define PRIdTID "lu"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_THREADS_FREERTOS_H */
|
|
@ -14,6 +14,17 @@
|
|||
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(__VXWORKS__)
|
||||
#define DDSRT_HAVE_THREAD_SETNAME (0)
|
||||
#else
|
||||
#define DDSRT_HAVE_THREAD_SETNAME (1)
|
||||
#endif
|
||||
#if defined (__linux) || defined (__APPLE__)
|
||||
#define DDSRT_HAVE_THREAD_LIST (1)
|
||||
#else
|
||||
#define DDSRT_HAVE_THREAD_LIST (0)
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -21,6 +32,7 @@ extern "C" {
|
|||
#if defined(__linux)
|
||||
typedef long int ddsrt_tid_t;
|
||||
#define PRIdTID "ld"
|
||||
typedef long int ddsrt_thread_list_id_t;
|
||||
/* __linux */
|
||||
#elif defined(__FreeBSD__) && (__FreeBSD_version >= 900031)
|
||||
/* FreeBSD >= 9.0 */
|
||||
|
@ -32,6 +44,8 @@ typedef int ddsrt_tid_t;
|
|||
/* macOS X >= 10.6 */
|
||||
typedef uint64_t ddsrt_tid_t;
|
||||
#define PRIdTID PRIu64
|
||||
/* ddsrt_thread_list_id_t is actually a mach_port_t */
|
||||
typedef uint32_t ddsrt_thread_list_id_t;
|
||||
/* __APPLE__ */
|
||||
#elif defined(__VXWORKS__)
|
||||
/* TODO: Verify taskIdSelf is the right function to use on VxWorks */
|
||||
|
@ -43,7 +57,7 @@ typedef TASK_ID ddsrt_tid_t;
|
|||
# endif
|
||||
/* __VXWORKS__ */
|
||||
#else
|
||||
typedef uintmax_t ddsrt_tid_t;
|
||||
typedef uintptr_t ddsrt_tid_t;
|
||||
#define PRIdTID PRIuPTR
|
||||
#endif
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
#include "dds/ddsrt/types.h"
|
||||
|
||||
#define DDSRT_HAVE_THREAD_SETNAME (1)
|
||||
#define DDSRT_HAVE_THREAD_LIST (1)
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -26,6 +29,8 @@ typedef struct {
|
|||
typedef DWORD ddsrt_tid_t;
|
||||
#define PRIdTID "u"
|
||||
|
||||
typedef HANDLE ddsrt_thread_list_id_t;
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -146,4 +146,8 @@ DDS_EXPORT size_t ddsrt_ctime(dds_time_t abstime, char *str, size_t size);
|
|||
}
|
||||
#endif
|
||||
|
||||
#if DDSRT_WITH_FREERTOS
|
||||
#include "dds/ddsrt/time/freertos.h"
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_TIME_H */
|
||||
|
|
53
src/ddsrt/include/dds/ddsrt/time/freertos.h
Normal file
53
src/ddsrt/include/dds/ddsrt/time/freertos.h
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
|
||||
*/
|
||||
#ifndef DDSRT_TIME_FREERTOS_H
|
||||
#define DDSRT_TIME_FREERTOS_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <FreeRTOS.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DDSRT_NSECS_PER_TICK (DDS_NSECS_IN_SEC / configTICK_RATE_HZ)
|
||||
|
||||
inline TickType_t
|
||||
ddsrt_duration_to_ticks_ceil(
|
||||
dds_duration_t reltime)
|
||||
{
|
||||
TickType_t ticks = 0;
|
||||
|
||||
assert(portMAX_DELAY > configTICK_RATE_HZ);
|
||||
|
||||
if (reltime == DDS_INFINITY) {
|
||||
ticks = portMAX_DELAY;
|
||||
} else if (reltime > 0) {
|
||||
dds_duration_t max_nsecs =
|
||||
(DDS_INFINITY / DDSRT_NSECS_PER_TICK < portMAX_DELAY
|
||||
? DDS_INFINITY - 1 : portMAX_DELAY * DDSRT_NSECS_PER_TICK);
|
||||
|
||||
if (reltime > max_nsecs - (DDSRT_NSECS_PER_TICK - 1)) {
|
||||
ticks = portMAX_DELAY;
|
||||
} else {
|
||||
ticks = (TickType_t)((reltime + (DDSRT_NSECS_PER_TICK - 1)) / DDSRT_NSECS_PER_TICK);
|
||||
}
|
||||
}
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_TIME_FREERTOS_H */
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
typedef long int ssize_t;
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#endif /* DDSRT_TYPES_POSIX_H */
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int (*ddsrt_xmlp_proc_elem_open_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name);
|
||||
typedef int (*ddsrt_xmlp_proc_attr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value);
|
||||
typedef int (*ddsrt_xmlp_proc_elem_data_t) (void *varg, uintptr_t eleminfo, const char *data);
|
||||
typedef int (*ddsrt_xmlp_proc_elem_close_t) (void *varg, uintptr_t eleminfo);
|
||||
typedef int (*ddsrt_xmlp_proc_elem_open_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name, int line);
|
||||
typedef int (*ddsrt_xmlp_proc_attr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value, int line);
|
||||
typedef int (*ddsrt_xmlp_proc_elem_data_t) (void *varg, uintptr_t eleminfo, const char *data, int line);
|
||||
typedef int (*ddsrt_xmlp_proc_elem_close_t) (void *varg, uintptr_t eleminfo, int line);
|
||||
typedef void (*ddsrt_xmlp_error) (void *varg, const char *msg, int line);
|
||||
|
||||
struct ddsrt_xmlp_callbacks {
|
||||
|
@ -36,9 +36,9 @@ extern "C" {
|
|||
|
||||
struct ddsrt_xmlp_state;
|
||||
|
||||
#define DDSRT_XMLP_REQUIRE_EOF 1u /* set by default; if not set, junk may follow top-level closing tag */
|
||||
#define DDSRT_XMLP_ANONYMOUS_CLOSE_TAG 2u /* clear by default; if set allow closing an element with </> instead of </name> */
|
||||
|
||||
#define DDSRT_XMLP_REQUIRE_EOF 1u /* set by default; if not set, junk may follow top-level closing tag */
|
||||
#define DDSRT_XMLP_ANONYMOUS_CLOSE_TAG 2u /* clear by default; if set allow closing an element with </> instead of </name> */
|
||||
#define DDSRT_XMLP_MISSING_CLOSE_AS_EOF 4u /* clear by default; if set, treat missing close tag as EOF */
|
||||
DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb);
|
||||
DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb);
|
||||
DDS_EXPORT void ddsrt_xmlp_set_options (struct ddsrt_xmlp_state *st, unsigned options);
|
||||
|
@ -46,8 +46,6 @@ extern "C" {
|
|||
DDS_EXPORT void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st);
|
||||
DDS_EXPORT int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st);
|
||||
|
||||
DDS_EXPORT int ddsrt_xmlUnescapeInsitu (char *buffer, size_t *n);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,7 @@ extern inline void ddsrt_atomic_inc32 (volatile ddsrt_atomic_uint32_t *x);
|
|||
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_ov (volatile ddsrt_atomic_uint32_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);
|
||||
|
@ -58,6 +59,7 @@ extern inline void ddsrt_atomic_add64 (volatile ddsrt_atomic_uint64_t *x, uint64
|
|||
#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_ov (volatile ddsrt_atomic_uint32_t *x, uint32_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);
|
||||
|
@ -71,6 +73,7 @@ extern inline void ddsrt_atomic_sub64 (volatile ddsrt_atomic_uint64_t *x, uint64
|
|||
#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_ov (volatile ddsrt_atomic_uint32_t *x, uint32_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);
|
||||
|
@ -122,6 +125,7 @@ extern inline int ddsrt_atomic_casvoidp2 (volatile ddsrt_atomic_uintptr2_t *x, u
|
|||
/* FENCES */
|
||||
extern inline void ddsrt_atomic_fence (void);
|
||||
extern inline void ddsrt_atomic_fence_ldld (void);
|
||||
extern inline void ddsrt_atomic_fence_stst (void);
|
||||
extern inline void ddsrt_atomic_fence_acq (void);
|
||||
extern inline void ddsrt_atomic_fence_rel (void);
|
||||
|
||||
|
@ -161,3 +165,182 @@ void ddsrt_atomic_lifo_pushmany (ddsrt_atomic_lifo_t *head, void *first, void *l
|
|||
} while (!ddsrt_atomic_casvoidp2 (&head->aba_head, a0, b0, a0+1, (uintptr_t)first));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* On platforms that don't provide 64-bit atomic operations, emulate them by hashing
|
||||
the variable's address to a small set of mutexes.
|
||||
|
||||
This also defines the GCC builtins on SPARCv8 for 32-bit operations. It would be
|
||||
more appropriate to simply define the ddsrt_atomic_... functions properly in that
|
||||
case and avoid squatting in the __sync_... namespace, but SPARCv8 support really
|
||||
is just for fun and it doesn't seem worth the bother right now */
|
||||
|
||||
#if DDSRT_HAVE_ATOMIC64
|
||||
|
||||
void ddsrt_atomics_init (void) { }
|
||||
void ddsrt_atomics_fini (void) { }
|
||||
|
||||
#else
|
||||
|
||||
#include "dds/ddsrt/sync.h"
|
||||
|
||||
/* SPARCv8 depends on these mutexes already for one-shot initialisation of the ddsrt
|
||||
code. Using PTHREAD_MUTEX_INITIALIZER guarantees they are properly initialized.
|
||||
Once a platform shows up that defines that macro where we don't used pthread mutexes
|
||||
something else will have to be done. */
|
||||
#define N_MUTEXES_LG2 4
|
||||
#define N_MUTEXES (1 << N_MUTEXES_LG2)
|
||||
#ifndef PTHREAD_MUTEX_INITIALIZER
|
||||
static ddsrt_mutex_t mutexes[N_MUTEXES];
|
||||
|
||||
void ddsrt_atomics_init (void)
|
||||
{
|
||||
for (int i = 0; i < N_MUTEXES; i++)
|
||||
ddsrt_mutex_init (&mutexes[i]);
|
||||
}
|
||||
|
||||
void ddsrt_atomics_fini (void)
|
||||
{
|
||||
for (int i = 0; i < N_MUTEXES; i++)
|
||||
ddsrt_mutex_destroy (&mutexes[i]);
|
||||
}
|
||||
#else
|
||||
static ddsrt_mutex_t mutexes[N_MUTEXES] = {
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
|
||||
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER }
|
||||
};
|
||||
void ddsrt_atomics_init (void) { }
|
||||
void ddsrt_atomics_fini (void) { }
|
||||
#endif
|
||||
|
||||
static uint32_t atomic64_lock_index (const volatile ddsrt_atomic_uint64_t *x)
|
||||
{
|
||||
const uint32_t u = (uint16_t) ((uintptr_t) x >> 3);
|
||||
const uint32_t v = u * 0xb4817365;
|
||||
return v >> (32 - N_MUTEXES_LG2);
|
||||
}
|
||||
|
||||
int ddsrt_atomic_cas64 (volatile ddsrt_atomic_uint64_t *x, uint64_t exp, uint64_t des)
|
||||
{
|
||||
const uint32_t idx = atomic64_lock_index (x);
|
||||
ddsrt_mutex_lock (&mutexes[idx]);
|
||||
if (x->v == exp)
|
||||
{
|
||||
x->v = des;
|
||||
ddsrt_mutex_unlock (&mutexes[idx]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ddsrt_mutex_unlock (&mutexes[idx]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define DDSRT_FAKE_ATOMIC64(name, oper, ret) \
|
||||
uint64_t ddsrt_atomic_##name##64_##ret (volatile ddsrt_atomic_uint64_t *x, uint64_t v) \
|
||||
{ \
|
||||
const uint64_t idx = atomic64_lock_index (x); \
|
||||
ddsrt_mutex_lock (&mutexes[idx]); \
|
||||
const uint64_t ov = x->v; \
|
||||
const uint64_t nv = ov oper v; \
|
||||
x->v = nv; \
|
||||
ddsrt_mutex_unlock (&mutexes[idx]); \
|
||||
return ret; \
|
||||
}
|
||||
#define DDSRT_FAKE_ATOMIC64_TRIPLET(name, oper) \
|
||||
DDSRT_FAKE_ATOMIC64(name, oper, nv) \
|
||||
DDSRT_FAKE_ATOMIC64(name, oper, ov) \
|
||||
void ddsrt_atomic_##name##64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v) { \
|
||||
(void) ddsrt_atomic_##name##64_ov (x, v); \
|
||||
}
|
||||
|
||||
uint64_t ddsrt_atomic_ld64 (const volatile ddsrt_atomic_uint64_t *x)
|
||||
{
|
||||
const uint32_t idx = atomic64_lock_index (x);
|
||||
ddsrt_mutex_lock (&mutexes[idx]);
|
||||
const uint64_t v = x->v;
|
||||
ddsrt_mutex_unlock (&mutexes[idx]);
|
||||
return v;
|
||||
}
|
||||
|
||||
void ddsrt_atomic_st64 (volatile ddsrt_atomic_uint64_t *x, uint64_t v)
|
||||
{
|
||||
const uint32_t idx = atomic64_lock_index (x);
|
||||
ddsrt_mutex_lock (&mutexes[idx]);
|
||||
x->v = v;
|
||||
ddsrt_mutex_unlock (&mutexes[idx]);
|
||||
}
|
||||
|
||||
DDSRT_FAKE_ATOMIC64_TRIPLET(add, +)
|
||||
DDSRT_FAKE_ATOMIC64_TRIPLET(sub, -)
|
||||
DDSRT_FAKE_ATOMIC64_TRIPLET(or, |)
|
||||
DDSRT_FAKE_ATOMIC64_TRIPLET(and, &)
|
||||
|
||||
void ddsrt_atomic_inc64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
ddsrt_atomic_add64 (x, 1);
|
||||
}
|
||||
uint64_t ddsrt_atomic_inc64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return ddsrt_atomic_add64_nv (x, 1);
|
||||
}
|
||||
void ddsrt_atomic_dec64 (volatile ddsrt_atomic_uint64_t *x) {
|
||||
ddsrt_atomic_sub64 (x, 1);
|
||||
}
|
||||
uint64_t ddsrt_atomic_dec64_nv (volatile ddsrt_atomic_uint64_t *x) {
|
||||
return ddsrt_atomic_sub64_nv (x, 1);
|
||||
}
|
||||
|
||||
#undef DDSRT_FAKE_ATOMIC64_TRIPLET
|
||||
#undef DDSRT_FAKE_ATOMIC64
|
||||
|
||||
/* SPARCv8 doesn't support any atomic operations beyond a simple atomic exchange. GCC happily
|
||||
compiles the __sync_* functions into library calls, and implementing them as such will do
|
||||
the trick. The rarity of SPARCv8 machines (EOL'd 2 decades ago) */
|
||||
#ifdef __sparc_v8__
|
||||
#define DDSRT_FAKE_SYNC(name, size, oper, ret) \
|
||||
unsigned __sync_##name##_##size (volatile unsigned *x, unsigned v) \
|
||||
{ \
|
||||
const uint32_t idx = atomic64_lock_index ((const volatile ddsrt_atomic_uint64_t *) x); \
|
||||
ddsrt_mutex_lock (&mutexes[idx]); \
|
||||
const uint32_t ov = *x; \
|
||||
const uint32_t nv = ov oper v; \
|
||||
*x = nv; \
|
||||
ddsrt_mutex_unlock (&mutexes[idx]); \
|
||||
return ret; \
|
||||
}
|
||||
#define DDSRT_FAKE_SYNC_PAIR(name, size, oper) \
|
||||
DDSRT_FAKE_SYNC(name##_and_fetch, size, oper, nv) \
|
||||
DDSRT_FAKE_SYNC(fetch_and_##name, size, oper, ov)
|
||||
|
||||
DDSRT_FAKE_SYNC_PAIR (add, 4, +)
|
||||
DDSRT_FAKE_SYNC_PAIR (sub, 4, -)
|
||||
DDSRT_FAKE_SYNC_PAIR (or, 4, |)
|
||||
DDSRT_FAKE_SYNC_PAIR (and, 4, &)
|
||||
|
||||
bool __sync_bool_compare_and_swap_4 (volatile unsigned *x, unsigned exp, unsigned des)
|
||||
{
|
||||
const uint32_t idx = atomic64_lock_index ((const volatile ddsrt_atomic_uint64_t *) x);
|
||||
ddsrt_mutex_lock (&mutexes[idx]);
|
||||
if (*x == exp)
|
||||
{
|
||||
*x = des;
|
||||
ddsrt_mutex_unlock (&mutexes[idx]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ddsrt_mutex_unlock (&mutexes[idx]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#undef DDSRT_FAKE_SYNC_PAIR
|
||||
#undef DDSRT_FAKE_SYNC
|
||||
#endif /* SPARCv8 hack */
|
||||
|
||||
#endif /* DDSRT_HAVE_ATOMIC64 */
|
||||
|
|
|
@ -43,6 +43,7 @@ retry:
|
|||
ddsrt_time_init();
|
||||
#endif
|
||||
ddsrt_random_init();
|
||||
ddsrt_atomics_init();
|
||||
ddsrt_atomic_or32(&init_status, INIT_STATUS_OK);
|
||||
} else {
|
||||
while (v > 1 && !(v & INIT_STATUS_OK)) {
|
||||
|
@ -68,6 +69,7 @@ void ddsrt_fini (void)
|
|||
{
|
||||
ddsrt_mutex_destroy(&init_mutex);
|
||||
ddsrt_random_fini();
|
||||
ddsrt_atomics_fini();
|
||||
#if _WIN32
|
||||
ddsrt_winsock_fini();
|
||||
ddsrt_time_fini();
|
||||
|
@ -139,6 +141,9 @@ ddsrt_cdtor(
|
|||
#pragma data_seg()
|
||||
#endif
|
||||
#else /* _WIN32 */
|
||||
void __attribute__((constructor)) ddsrt_ctor(void);
|
||||
void __attribute__((destructor)) ddsrt_dtor(void);
|
||||
|
||||
void __attribute__((constructor)) ddsrt_ctor(void)
|
||||
{
|
||||
ddsrt_init();
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/io.h"
|
||||
|
||||
dds_retcode_t ddsrt_dlopen(const char *name, bool translate,
|
||||
dds_return_t ddsrt_dlopen(const char *name, bool translate,
|
||||
ddsrt_dynlib_t *handle) {
|
||||
dds_retcode_t retcode = DDS_RETCODE_OK;
|
||||
dds_return_t retcode = DDS_RETCODE_OK;
|
||||
|
||||
assert( handle );
|
||||
*handle = NULL;
|
||||
|
@ -53,16 +53,16 @@ dds_retcode_t ddsrt_dlopen(const char *name, bool translate,
|
|||
return retcode;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_dlclose(ddsrt_dynlib_t handle) {
|
||||
dds_return_t ddsrt_dlclose(ddsrt_dynlib_t handle) {
|
||||
|
||||
assert ( handle );
|
||||
return (dlclose(handle) == 0) ? DDS_RETCODE_OK : DDS_RETCODE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol,
|
||||
dds_return_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol,
|
||||
void **address) {
|
||||
dds_retcode_t retcode = DDS_RETCODE_OK;
|
||||
dds_return_t retcode = DDS_RETCODE_OK;
|
||||
|
||||
assert( handle );
|
||||
assert( address );
|
||||
|
@ -76,10 +76,10 @@ dds_retcode_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol,
|
|||
return retcode;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_dlerror(char *buf, size_t buflen) {
|
||||
dds_return_t ddsrt_dlerror(char *buf, size_t buflen) {
|
||||
|
||||
const char *err;
|
||||
dds_retcode_t retcode = DDS_RETCODE_OK;
|
||||
dds_return_t retcode = DDS_RETCODE_OK;
|
||||
|
||||
assert (buf );
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ isenvvar(const char *name)
|
|||
return (*name == '\0' || strchr(name, '=') != NULL) == 0;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getenv(const char *name, char **value)
|
||||
{
|
||||
char *env;
|
||||
|
@ -40,7 +40,7 @@ ddsrt_getenv(const char *name, char **value)
|
|||
return DDS_RETCODE_NOT_FOUND;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_setenv(const char *name, const char *value)
|
||||
{
|
||||
assert(name != NULL);
|
||||
|
@ -65,7 +65,7 @@ ddsrt_setenv(const char *name, const char *value)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_unsetenv(const char *name)
|
||||
{
|
||||
assert(name != NULL);
|
||||
|
|
100
src/ddsrt/src/environ/solaris2.6/environ.c
Normal file
100
src/ddsrt/src/environ/solaris2.6/environ.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* 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 <stdio.h>
|
||||
|
||||
#include "dds/ddsrt/environ.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
extern char **environ;
|
||||
|
||||
static int
|
||||
isenvvar(const char *name)
|
||||
{
|
||||
return (*name == '\0' || strchr(name, '=') != NULL) == 0;
|
||||
}
|
||||
|
||||
dds_return_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_return_t
|
||||
ddsrt_setenv(const char *name, const char *value)
|
||||
{
|
||||
/* Not MT-Safe -- but it is only used in a tests to set
|
||||
CYCLONEDDS_URI, so for Solaris 2.6 support it is not worth the
|
||||
bother to do a better job. Same for a bit of leakage. */
|
||||
assert(name != NULL);
|
||||
assert(value != NULL);
|
||||
|
||||
if (strlen(value) == 0)
|
||||
return ddsrt_unsetenv(name);
|
||||
if (!isenvvar(name))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
const size_t namelen = strlen (name);
|
||||
const size_t entrysize = namelen + 1 + strlen (value) + 1;
|
||||
char *entry = malloc (entrysize);
|
||||
snprintf (entry, entrysize, "%s=%s", name, value);
|
||||
size_t n = 0;
|
||||
while (environ[n] != NULL)
|
||||
{
|
||||
if (strncmp (environ[n], name, namelen) == 0 && environ[n][namelen] == '=')
|
||||
{
|
||||
environ[n] = entry;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
environ = realloc (environ, (n + 2) * sizeof (*environ));
|
||||
environ[n] = entry;
|
||||
environ[n+1] = NULL;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_unsetenv(const char *name)
|
||||
{
|
||||
/* Same considerations as setenv. */
|
||||
assert(name != NULL);
|
||||
|
||||
if (!isenvvar(name))
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
|
||||
const size_t namelen = strlen (name);
|
||||
size_t n = 0, idx = SIZE_MAX;
|
||||
while (environ[n] != NULL)
|
||||
{
|
||||
if (idx > n && strncmp (environ[n], name, namelen) == 0 && environ[n][namelen] == '=')
|
||||
idx = n;
|
||||
n++;
|
||||
}
|
||||
if (idx < n)
|
||||
memmove (&environ[idx], &environ[idx + 1], (n - idx) * sizeof (*environ));
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
|
@ -25,7 +25,7 @@ isenvvar(const char *name)
|
|||
}
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4996)
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getenv(const char *name, char **value)
|
||||
{
|
||||
char *env;
|
||||
|
@ -43,7 +43,7 @@ ddsrt_getenv(const char *name, char **value)
|
|||
}
|
||||
DDSRT_WARNING_MSVC_ON(4996)
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_setenv(const char *name, const char *value)
|
||||
{
|
||||
assert(name != NULL);
|
||||
|
@ -65,7 +65,7 @@ ddsrt_setenv(const char *name, const char *value)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_unsetenv(const char *name)
|
||||
{
|
||||
assert(name != NULL);
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
|
||||
typedef char * (*expand_fn)(const char *src0);
|
||||
typedef char * (*expand_fn)(const char *src0, uint32_t domid);
|
||||
|
||||
static void expand_append (char **dst, size_t *sz, size_t *pos, char c)
|
||||
{
|
||||
|
@ -32,34 +33,46 @@ static void expand_append (char **dst, size_t *sz, size_t *pos, char c)
|
|||
(*pos)++;
|
||||
}
|
||||
|
||||
static char *expand_env (const char *name, char op, const char *alt, expand_fn expand)
|
||||
static char *expand_env (const char *name, char op, const char *alt, expand_fn expand, uint32_t domid)
|
||||
{
|
||||
char idstr[20];
|
||||
char *env = NULL;
|
||||
(void)ddsrt_getenv (name, &env);
|
||||
dds_return_t ret;
|
||||
|
||||
if ((ret = ddsrt_getenv (name, &env)) == DDS_RETCODE_OK) {
|
||||
/* ok */
|
||||
} else if (strcmp (name, "$") == 0 || strcmp (name, "CYCLONEDDS_PID") == 0) {
|
||||
snprintf (idstr, sizeof (idstr), "%"PRIdPID, ddsrt_getpid ());
|
||||
env = idstr;
|
||||
} else if (strcmp (name, "CYCLONEDDS_DOMAIN_ID") == 0 && domid != UINT32_MAX) {
|
||||
snprintf (idstr, sizeof (idstr), "%"PRIu32, domid);
|
||||
env = idstr;
|
||||
}
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0:
|
||||
return ddsrt_strdup (env ? env : "");
|
||||
case '-':
|
||||
return env && *env ? ddsrt_strdup (env) : expand (alt);
|
||||
return env && *env ? ddsrt_strdup (env) : expand (alt, domid);
|
||||
case '?':
|
||||
if (env && *env) {
|
||||
return ddsrt_strdup (env);
|
||||
} else {
|
||||
char *altx = expand (alt);
|
||||
DDS_ERROR("%s: %s\n", name, altx);
|
||||
char *altx = expand (alt, domid);
|
||||
DDS_ILOG (DDS_LC_ERROR, domid, "%s: %s\n", name, altx);
|
||||
ddsrt_free (altx);
|
||||
return NULL;
|
||||
}
|
||||
case '+':
|
||||
return env && *env ? expand (alt) : ddsrt_strdup ("");
|
||||
return env && *env ? expand (alt, domid) : ddsrt_strdup ("");
|
||||
default:
|
||||
abort ();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static char *expand_envbrace (const char **src, expand_fn expand)
|
||||
static char *expand_envbrace (const char **src, expand_fn expand, uint32_t domid)
|
||||
{
|
||||
const char *start = *src + 1;
|
||||
char *name, *x;
|
||||
|
@ -76,7 +89,7 @@ static char *expand_envbrace (const char **src, expand_fn expand)
|
|||
name[*src - start] = 0;
|
||||
if (**src == '}') {
|
||||
(*src)++;
|
||||
x = expand_env (name, 0, NULL, expand);
|
||||
x = expand_env (name, 0, NULL, expand, domid);
|
||||
ddsrt_free (name);
|
||||
return x;
|
||||
} else {
|
||||
|
@ -120,7 +133,7 @@ static char *expand_envbrace (const char **src, expand_fn expand)
|
|||
memcpy (alt, altstart, (size_t) (*src - altstart));
|
||||
alt[*src - altstart] = 0;
|
||||
(*src)++;
|
||||
x = expand_env (name, op, alt, expand);
|
||||
x = expand_env (name, op, alt, expand, domid);
|
||||
ddsrt_free (alt);
|
||||
ddsrt_free (name);
|
||||
return x;
|
||||
|
@ -130,7 +143,7 @@ err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static char *expand_envsimple (const char **src, expand_fn expand)
|
||||
static char *expand_envsimple (const char **src, expand_fn expand, uint32_t domid)
|
||||
{
|
||||
const char *start = *src;
|
||||
char *name, *x;
|
||||
|
@ -141,22 +154,22 @@ static char *expand_envsimple (const char **src, expand_fn expand)
|
|||
name = ddsrt_malloc ((size_t) (*src - start) + 1);
|
||||
memcpy (name, start, (size_t) (*src - start));
|
||||
name[*src - start] = 0;
|
||||
x = expand_env (name, 0, NULL, expand);
|
||||
x = expand_env (name, 0, NULL, expand, domid);
|
||||
ddsrt_free (name);
|
||||
return x;
|
||||
}
|
||||
|
||||
static char *expand_envchar (const char **src, expand_fn expand)
|
||||
static char *expand_envchar (const char **src, expand_fn expand, uint32_t domid)
|
||||
{
|
||||
char name[2];
|
||||
assert (**src);
|
||||
name[0] = **src;
|
||||
name[1] = 0;
|
||||
(*src)++;
|
||||
return expand_env (name, 0, NULL, expand);
|
||||
return expand_env (name, 0, NULL, expand, domid);
|
||||
}
|
||||
|
||||
char *ddsrt_expand_envvars_sh (const char *src0)
|
||||
char *ddsrt_expand_envvars_sh (const char *src0, uint32_t domid)
|
||||
{
|
||||
/* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms; $ and \ can be escaped with \ */
|
||||
const char *src = src0;
|
||||
|
@ -179,11 +192,11 @@ char *ddsrt_expand_envvars_sh (const char *src0)
|
|||
ddsrt_free(dst);
|
||||
return NULL;
|
||||
} else if (*src == '{') {
|
||||
x = expand_envbrace (&src, &ddsrt_expand_envvars_sh);
|
||||
x = expand_envbrace (&src, &ddsrt_expand_envvars_sh, domid);
|
||||
} else if (isalnum ((unsigned char) *src) || *src == '_') {
|
||||
x = expand_envsimple (&src, &ddsrt_expand_envvars_sh);
|
||||
x = expand_envsimple (&src, &ddsrt_expand_envvars_sh, domid);
|
||||
} else {
|
||||
x = expand_envchar (&src, &ddsrt_expand_envvars_sh);
|
||||
x = expand_envchar (&src, &ddsrt_expand_envvars_sh, domid);
|
||||
}
|
||||
if (x == NULL) {
|
||||
ddsrt_free(dst);
|
||||
|
@ -202,7 +215,7 @@ char *ddsrt_expand_envvars_sh (const char *src0)
|
|||
return dst;
|
||||
}
|
||||
|
||||
char *ddsrt_expand_envvars (const char *src0)
|
||||
char *ddsrt_expand_envvars (const char *src0, uint32_t domid)
|
||||
{
|
||||
/* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */
|
||||
const char *src = src0;
|
||||
|
@ -212,7 +225,7 @@ char *ddsrt_expand_envvars (const char *src0)
|
|||
if (*src == '$' && *(src + 1) == '{') {
|
||||
char *x, *xp;
|
||||
src++;
|
||||
x = expand_envbrace (&src, &ddsrt_expand_envvars);
|
||||
x = expand_envbrace (&src, &ddsrt_expand_envvars, domid);
|
||||
if (x == NULL) {
|
||||
ddsrt_free(dst);
|
||||
return NULL;
|
||||
|
|
|
@ -207,7 +207,7 @@ void *ddsrt_fibheap_extract_min (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap
|
|||
keys anyway to find the minimum */
|
||||
{
|
||||
ddsrt_fibheap_node_t *mark, *cursor, *newmin;
|
||||
unsigned i;
|
||||
uint32_t i;
|
||||
for (i = 0; roots[i] == NULL; i++) {
|
||||
assert (i+1 < min_degree_noninit);
|
||||
}
|
||||
|
|
136
src/ddsrt/src/heap/freertos/heap.c
Normal file
136
src/ddsrt/src/heap/freertos/heap.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 <FreeRTOS.h>
|
||||
|
||||
#if defined(configSUPPORT_DYNAMIC_ALLOCATION) && \
|
||||
(configSUPPORT_DYNAMIC_ALLOCATION == 0)
|
||||
# error Dynamic memory allocation is not supported
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static const size_t ofst = sizeof(size_t);
|
||||
|
||||
void *ddsrt_malloc_s(size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
if (size == 0) {
|
||||
size = 1;
|
||||
}
|
||||
|
||||
if ((SIZE_MAX - size) < ofst) {
|
||||
errno = ERANGE;
|
||||
} else {
|
||||
ptr = pvPortMalloc(size + ofst);
|
||||
if (ptr == NULL) {
|
||||
errno = ENOMEM;
|
||||
} else {
|
||||
*((size_t *)ptr) = size;
|
||||
ptr += ofst;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ddsrt_malloc(size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if ((ptr = ddsrt_malloc_s(size)) == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ddsrt_calloc_s(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
if (nmemb == 0 || size == 0) {
|
||||
nmemb = size = 1;
|
||||
}
|
||||
|
||||
if ((SIZE_MAX / nmemb) <= size) {
|
||||
errno = ERANGE;
|
||||
} else {
|
||||
ptr = ddsrt_malloc_s(nmemb * size);
|
||||
(void)memset(ptr, 0, nmemb * size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ddsrt_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
if ((ptr = ddsrt_calloc_s(nmemb, size)) == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* pvPortMalloc may be used instead of directly invoking malloc and free as
|
||||
offered by the standard C library. Unfortunately FreeRTOS does not offer a
|
||||
realloc compatible function and extra information must be embedded in every
|
||||
memory block in order to support reallocation of memory (otherwise the
|
||||
number of bytes that must be copied is unavailable). */
|
||||
void *ddsrt_realloc_s(void *memblk, size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
size_t origsize = 0;
|
||||
|
||||
if (memblk != NULL) {
|
||||
origsize = *((size_t *)(memblk - ofst));
|
||||
}
|
||||
|
||||
if (size != origsize || origsize == 0) {
|
||||
if ((ptr = ddsrt_malloc_s(size)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (memblk != NULL) {
|
||||
if (size > 0) {
|
||||
(void)memcpy(ptr, memblk, size > origsize ? origsize : size);
|
||||
}
|
||||
vPortFree(memblk - ofst);
|
||||
}
|
||||
memblk = ptr;
|
||||
}
|
||||
|
||||
return memblk;
|
||||
}
|
||||
|
||||
void *ddsrt_realloc(void *memblk, size_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
if ((ptr = ddsrt_realloc_s(memblk, size)) == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_free(void *ptr)
|
||||
{
|
||||
if (ptr != NULL) {
|
||||
vPortFree(ptr - ofst);
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/attributes.h"
|
||||
#include "dds/ddsrt/atomics.h"
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
|
@ -22,8 +23,255 @@
|
|||
|
||||
#define NOT_A_BUCKET (~(uint32_t)0)
|
||||
|
||||
/************* SEQUENTIAL VERSION ***************/
|
||||
|
||||
struct ddsrt_hh_bucket {
|
||||
uint32_t hopinfo;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct ddsrt_hh {
|
||||
uint32_t size; /* power of 2 */
|
||||
struct ddsrt_hh_bucket *buckets;
|
||||
ddsrt_hh_hash_fn hash;
|
||||
ddsrt_hh_equals_fn equals;
|
||||
};
|
||||
|
||||
static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
|
||||
{
|
||||
uint32_t size;
|
||||
uint32_t i;
|
||||
/* degenerate case to minimize memory use */
|
||||
if (init_size == 1) {
|
||||
size = 1;
|
||||
} else {
|
||||
size = HH_HOP_RANGE;
|
||||
while (size < init_size) {
|
||||
size *= 2;
|
||||
}
|
||||
}
|
||||
rt->hash = hash;
|
||||
rt->equals = equals;
|
||||
rt->size = size;
|
||||
rt->buckets = ddsrt_malloc (size * sizeof (*rt->buckets));
|
||||
for (i = 0; i < size; i++) {
|
||||
rt->buckets[i].hopinfo = 0;
|
||||
rt->buckets[i].data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ddsrt_hh_fini (struct ddsrt_hh *rt)
|
||||
{
|
||||
ddsrt_free (rt->buckets);
|
||||
}
|
||||
|
||||
struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
|
||||
{
|
||||
struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh));
|
||||
ddsrt_hh_init (hh, init_size, hash, equals);
|
||||
return hh;
|
||||
}
|
||||
|
||||
void ddsrt_hh_free (struct ddsrt_hh * __restrict hh)
|
||||
{
|
||||
ddsrt_hh_fini (hh);
|
||||
ddsrt_free (hh);
|
||||
}
|
||||
|
||||
static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template)
|
||||
{
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
uint32_t hopinfo = rt->buckets[bucket].hopinfo;
|
||||
uint32_t idx;
|
||||
for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = rt->buckets[bidx].data;
|
||||
if (data && rt->equals (data, template))
|
||||
return data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template)
|
||||
{
|
||||
const uint32_t hash = rt->hash (template);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t bucket = hash & idxmask;
|
||||
return ddsrt_hh_lookup_internal (rt, bucket, template);
|
||||
}
|
||||
|
||||
static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance)
|
||||
{
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
uint32_t move_bucket, free_dist;
|
||||
move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask;
|
||||
for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) {
|
||||
uint32_t move_free_distance = NOT_A_BUCKET;
|
||||
uint32_t mask = 1;
|
||||
uint32_t i;
|
||||
for (i = 0; i < free_dist; i++, mask <<= 1) {
|
||||
if (mask & rt->buckets[move_bucket].hopinfo) {
|
||||
move_free_distance = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (move_free_distance != NOT_A_BUCKET) {
|
||||
uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask;
|
||||
rt->buckets[move_bucket].hopinfo |= 1u << free_dist;
|
||||
rt->buckets[free_bucket].data = rt->buckets[new_free_bucket].data;
|
||||
rt->buckets[new_free_bucket].data = NULL;
|
||||
rt->buckets[move_bucket].hopinfo &= ~(1u << move_free_distance);
|
||||
*free_distance -= free_dist - move_free_distance;
|
||||
return new_free_bucket;
|
||||
}
|
||||
move_bucket = (move_bucket + 1) & idxmask;
|
||||
}
|
||||
return NOT_A_BUCKET;
|
||||
}
|
||||
|
||||
static void ddsrt_hh_resize (struct ddsrt_hh *rt)
|
||||
{
|
||||
if (rt->size == 1) {
|
||||
assert (rt->size == 1);
|
||||
assert (rt->buckets[0].hopinfo == 1);
|
||||
assert (rt->buckets[0].data != NULL);
|
||||
|
||||
rt->size = HH_HOP_RANGE;
|
||||
const uint32_t hash = rt->hash (rt->buckets[0].data);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t start_bucket = hash & idxmask;
|
||||
|
||||
struct ddsrt_hh_bucket *newbs = ddsrt_malloc (rt->size * sizeof (*newbs));
|
||||
for (uint32_t i = 0; i < rt->size; i++) {
|
||||
newbs[i].hopinfo = 0;
|
||||
newbs[i].data = NULL;
|
||||
}
|
||||
newbs[start_bucket] = rt->buckets[0];
|
||||
ddsrt_free (rt->buckets);
|
||||
rt->buckets = newbs;
|
||||
} else {
|
||||
struct ddsrt_hh_bucket *bs1;
|
||||
uint32_t i, idxmask0, idxmask1;
|
||||
|
||||
bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets));
|
||||
|
||||
for (i = 0; i < 2 * rt->size; i++) {
|
||||
bs1[i].hopinfo = 0;
|
||||
bs1[i].data = NULL;
|
||||
}
|
||||
idxmask0 = rt->size - 1;
|
||||
idxmask1 = 2 * rt->size - 1;
|
||||
for (i = 0; i < rt->size; i++) {
|
||||
void *data = rt->buckets[i].data;
|
||||
if (data) {
|
||||
const uint32_t hash = rt->hash (data);
|
||||
const uint32_t old_start_bucket = hash & idxmask0;
|
||||
const uint32_t new_start_bucket = hash & idxmask1;
|
||||
const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket);
|
||||
const uint32_t newb = (new_start_bucket + dist) & idxmask1;
|
||||
assert (dist < HH_HOP_RANGE);
|
||||
bs1[new_start_bucket].hopinfo |= 1u << dist;
|
||||
bs1[newb].data = data;
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_free (rt->buckets);
|
||||
rt->size *= 2;
|
||||
rt->buckets = bs1;
|
||||
}
|
||||
}
|
||||
|
||||
int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data)
|
||||
{
|
||||
const uint32_t hash = rt->hash (data);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t start_bucket = hash & idxmask;
|
||||
uint32_t free_distance, free_bucket;
|
||||
|
||||
if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
free_bucket = start_bucket;
|
||||
for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) {
|
||||
if (rt->buckets[free_bucket].data == NULL)
|
||||
break;
|
||||
free_bucket = (free_bucket + 1) & idxmask;
|
||||
}
|
||||
if (free_distance < HH_ADD_RANGE) {
|
||||
do {
|
||||
if (free_distance < HH_HOP_RANGE) {
|
||||
assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask));
|
||||
rt->buckets[start_bucket].hopinfo |= 1u << free_distance;
|
||||
rt->buckets[free_bucket].data = (void *) data;
|
||||
return 1;
|
||||
}
|
||||
free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance);
|
||||
assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask);
|
||||
} while (free_bucket != NOT_A_BUCKET);
|
||||
}
|
||||
|
||||
ddsrt_hh_resize (rt);
|
||||
return ddsrt_hh_add (rt, data);
|
||||
}
|
||||
|
||||
int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template)
|
||||
{
|
||||
const uint32_t hash = rt->hash (template);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t bucket = hash & idxmask;
|
||||
uint32_t hopinfo;
|
||||
uint32_t idx;
|
||||
hopinfo = rt->buckets[bucket].hopinfo;
|
||||
for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
|
||||
if (hopinfo & 1) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = rt->buckets[bidx].data;
|
||||
if (data && rt->equals (data, template)) {
|
||||
rt->buckets[bidx].data = NULL;
|
||||
rt->buckets[bucket].hopinfo &= ~(1u << idx);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < rt->size; i++) {
|
||||
void *data = rt->buckets[i].data;
|
||||
if (data) {
|
||||
f (data, f_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter)
|
||||
{
|
||||
iter->hh = rt;
|
||||
iter->cursor = 0;
|
||||
return ddsrt_hh_iter_next (iter);
|
||||
}
|
||||
|
||||
void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter)
|
||||
{
|
||||
struct ddsrt_hh *rt = iter->hh;
|
||||
while (iter->cursor < rt->size) {
|
||||
void *data = rt->buckets[iter->cursor].data;
|
||||
iter->cursor++;
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********** CONCURRENT VERSION ************/
|
||||
|
||||
#if ! ddsrt_has_feature_thread_sanitizer
|
||||
|
||||
#define N_BACKING_LOCKS 32
|
||||
#define N_RESIZE_LOCKS 8
|
||||
|
||||
|
@ -51,6 +299,7 @@ struct ddsrt_chh {
|
|||
ddsrt_hh_equals_fn equals;
|
||||
ddsrt_rwlock_t resize_locks[N_RESIZE_LOCKS];
|
||||
ddsrt_hh_buckets_gc_fn gc_buckets;
|
||||
void *gc_buckets_arg;
|
||||
};
|
||||
|
||||
#define CHH_MAX_TRIES 4
|
||||
|
@ -61,7 +310,7 @@ static int ddsrt_chh_data_valid_p (void *data)
|
|||
return data != NULL && data != CHH_BUSY;
|
||||
}
|
||||
|
||||
static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets)
|
||||
static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets, void *gc_buckets_arg)
|
||||
{
|
||||
uint32_t size;
|
||||
uint32_t i;
|
||||
|
@ -74,6 +323,7 @@ static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_ha
|
|||
rt->hash = hash;
|
||||
rt->equals = equals;
|
||||
rt->gc_buckets = gc_buckets;
|
||||
rt->gc_buckets_arg = gc_buckets_arg;
|
||||
|
||||
buckets = ddsrt_malloc (offsetof (struct ddsrt_chh_bucket_array, bs) + size * sizeof (*buckets->bs));
|
||||
ddsrt_atomic_stvoidp (&rt->buckets, buckets);
|
||||
|
@ -111,10 +361,10 @@ static void ddsrt_chh_fini (struct ddsrt_chh *rt)
|
|||
}
|
||||
}
|
||||
|
||||
struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets)
|
||||
struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets, void *gc_buckets_arg)
|
||||
{
|
||||
struct ddsrt_chh *hh = ddsrt_malloc (sizeof (*hh));
|
||||
if (ddsrt_chh_init (hh, init_size, hash, equals, gc_buckets) < 0) {
|
||||
if (ddsrt_chh_init (hh, init_size, hash, equals, gc_buckets, gc_buckets_arg) < 0) {
|
||||
ddsrt_free (hh);
|
||||
return NULL;
|
||||
} else {
|
||||
|
@ -228,7 +478,7 @@ static void *ddsrt_chh_lookup_internal (struct ddsrt_chh_bucket_array const * co
|
|||
|
||||
#define ddsrt_atomic_rmw32_nonatomic(var_, tmp_, expr_) do { \
|
||||
ddsrt_atomic_uint32_t *var__ = (var_); \
|
||||
uint32_t tmp_ = ddsrt_atomic_ld32 (var__); \
|
||||
uint32_t tmp_ = ddsrt_atomic_ld32 (var__); \
|
||||
ddsrt_atomic_st32 (var__, (expr_)); \
|
||||
} while (0)
|
||||
|
||||
|
@ -324,7 +574,7 @@ static void ddsrt_chh_resize (struct ddsrt_chh *rt)
|
|||
|
||||
ddsrt_atomic_fence ();
|
||||
ddsrt_atomic_stvoidp (&rt->buckets, bsary1);
|
||||
rt->gc_buckets (bsary0);
|
||||
rt->gc_buckets (bsary0, rt->gc_buckets_arg);
|
||||
}
|
||||
|
||||
int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data)
|
||||
|
@ -467,224 +717,78 @@ void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_i
|
|||
return ddsrt_chh_iter_next (it);
|
||||
}
|
||||
|
||||
/************* SEQUENTIAL VERSION ***************/
|
||||
#else
|
||||
|
||||
struct ddsrt_hh_bucket {
|
||||
uint32_t hopinfo;
|
||||
void *data;
|
||||
struct ddsrt_chh {
|
||||
ddsrt_mutex_t lock;
|
||||
struct ddsrt_hh rt;
|
||||
};
|
||||
|
||||
struct ddsrt_hh {
|
||||
uint32_t size; /* power of 2 */
|
||||
struct ddsrt_hh_bucket *buckets;
|
||||
ddsrt_hh_hash_fn hash;
|
||||
ddsrt_hh_equals_fn equals;
|
||||
};
|
||||
|
||||
static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
|
||||
struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc)
|
||||
{
|
||||
uint32_t size = HH_HOP_RANGE;
|
||||
uint32_t i;
|
||||
while (size < init_size) {
|
||||
size *= 2;
|
||||
}
|
||||
rt->hash = hash;
|
||||
rt->equals = equals;
|
||||
rt->size = size;
|
||||
rt->buckets = ddsrt_malloc (size * sizeof (*rt->buckets));
|
||||
for (i = 0; i < size; i++) {
|
||||
rt->buckets[i].hopinfo = 0;
|
||||
rt->buckets[i].data = NULL;
|
||||
}
|
||||
struct ddsrt_chh *hh = ddsrt_malloc (sizeof (*hh));
|
||||
(void) gc;
|
||||
ddsrt_mutex_init (&hh->lock);
|
||||
ddsrt_hh_init (&hh->rt, init_size, hash, equals);
|
||||
return hh;
|
||||
}
|
||||
|
||||
static void ddsrt_hh_fini (struct ddsrt_hh *rt)
|
||||
void ddsrt_chh_free (struct ddsrt_chh * __restrict hh)
|
||||
{
|
||||
ddsrt_free (rt->buckets);
|
||||
ddsrt_hh_fini (&hh->rt);
|
||||
ddsrt_mutex_destroy (&hh->lock);
|
||||
ddsrt_free (hh);
|
||||
}
|
||||
|
||||
struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals)
|
||||
void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict hh, const void * __restrict template)
|
||||
{
|
||||
struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh));
|
||||
ddsrt_hh_init (hh, init_size, hash, equals);
|
||||
return hh;
|
||||
ddsrt_mutex_lock (&hh->lock);
|
||||
void *x = ddsrt_hh_lookup (&hh->rt, template);
|
||||
ddsrt_mutex_unlock (&hh->lock);
|
||||
return x;
|
||||
}
|
||||
|
||||
void ddsrt_hh_free (struct ddsrt_hh * __restrict hh)
|
||||
int ddsrt_chh_add (struct ddsrt_chh * __restrict hh, const void * __restrict data)
|
||||
{
|
||||
ddsrt_hh_fini (hh);
|
||||
ddsrt_free (hh);
|
||||
ddsrt_mutex_lock (&hh->lock);
|
||||
int x = ddsrt_hh_add (&hh->rt, data);
|
||||
ddsrt_mutex_unlock (&hh->lock);
|
||||
return x;
|
||||
}
|
||||
|
||||
static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template)
|
||||
int ddsrt_chh_remove (struct ddsrt_chh * __restrict hh, const void * __restrict template)
|
||||
{
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
uint32_t hopinfo = rt->buckets[bucket].hopinfo;
|
||||
uint32_t idx;
|
||||
for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = rt->buckets[bidx].data;
|
||||
if (data && rt->equals (data, template))
|
||||
return data;
|
||||
}
|
||||
return NULL;
|
||||
ddsrt_mutex_lock (&hh->lock);
|
||||
int x = ddsrt_hh_remove (&hh->rt, template);
|
||||
ddsrt_mutex_unlock (&hh->lock);
|
||||
return x;
|
||||
}
|
||||
|
||||
void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template)
|
||||
void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict hh, void (*f) (void *a, void *f_arg), void *f_arg)
|
||||
{
|
||||
const uint32_t hash = rt->hash (template);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t bucket = hash & idxmask;
|
||||
return ddsrt_hh_lookup_internal (rt, bucket, template);
|
||||
ddsrt_mutex_lock (&hh->lock);
|
||||
ddsrt_hh_enum (&hh->rt, f, f_arg);
|
||||
ddsrt_mutex_unlock (&hh->lock);
|
||||
}
|
||||
|
||||
static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance)
|
||||
void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict hh, struct ddsrt_chh_iter *it)
|
||||
{
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
uint32_t move_bucket, free_dist;
|
||||
move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask;
|
||||
for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) {
|
||||
uint32_t move_free_distance = NOT_A_BUCKET;
|
||||
uint32_t mask = 1;
|
||||
uint32_t i;
|
||||
for (i = 0; i < free_dist; i++, mask <<= 1) {
|
||||
if (mask & rt->buckets[move_bucket].hopinfo) {
|
||||
move_free_distance = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (move_free_distance != NOT_A_BUCKET) {
|
||||
uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask;
|
||||
rt->buckets[move_bucket].hopinfo |= 1u << free_dist;
|
||||
rt->buckets[free_bucket].data = rt->buckets[new_free_bucket].data;
|
||||
rt->buckets[new_free_bucket].data = NULL;
|
||||
rt->buckets[move_bucket].hopinfo &= ~(1u << move_free_distance);
|
||||
*free_distance -= free_dist - move_free_distance;
|
||||
return new_free_bucket;
|
||||
}
|
||||
move_bucket = (move_bucket + 1) & idxmask;
|
||||
}
|
||||
return NOT_A_BUCKET;
|
||||
ddsrt_mutex_lock (&hh->lock);
|
||||
it->chh = hh;
|
||||
void *x = ddsrt_hh_iter_first (&hh->rt, &it->it);
|
||||
ddsrt_mutex_unlock (&hh->lock);
|
||||
return x;
|
||||
}
|
||||
|
||||
static void ddsrt_hh_resize (struct ddsrt_hh *rt)
|
||||
void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it)
|
||||
{
|
||||
struct ddsrt_hh_bucket *bs1;
|
||||
uint32_t i, idxmask0, idxmask1;
|
||||
|
||||
bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets));
|
||||
|
||||
for (i = 0; i < 2 * rt->size; i++) {
|
||||
bs1[i].hopinfo = 0;
|
||||
bs1[i].data = NULL;
|
||||
}
|
||||
idxmask0 = rt->size - 1;
|
||||
idxmask1 = 2 * rt->size - 1;
|
||||
for (i = 0; i < rt->size; i++) {
|
||||
void *data = rt->buckets[i].data;
|
||||
if (data) {
|
||||
const uint32_t hash = rt->hash (data);
|
||||
const uint32_t old_start_bucket = hash & idxmask0;
|
||||
const uint32_t new_start_bucket = hash & idxmask1;
|
||||
const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket);
|
||||
const uint32_t newb = (new_start_bucket + dist) & idxmask1;
|
||||
assert (dist < HH_HOP_RANGE);
|
||||
bs1[new_start_bucket].hopinfo |= 1u << dist;
|
||||
bs1[newb].data = data;
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_free (rt->buckets);
|
||||
rt->size *= 2;
|
||||
rt->buckets = bs1;
|
||||
ddsrt_mutex_lock (&it->chh->lock);
|
||||
void *x = ddsrt_hh_iter_next (&it->it);
|
||||
ddsrt_mutex_unlock (&it->chh->lock);
|
||||
return x;
|
||||
}
|
||||
|
||||
int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data)
|
||||
{
|
||||
const uint32_t hash = rt->hash (data);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t start_bucket = hash & idxmask;
|
||||
uint32_t free_distance, free_bucket;
|
||||
|
||||
if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
free_bucket = start_bucket;
|
||||
for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) {
|
||||
if (rt->buckets[free_bucket].data == NULL)
|
||||
break;
|
||||
free_bucket = (free_bucket + 1) & idxmask;
|
||||
}
|
||||
if (free_distance < HH_ADD_RANGE) {
|
||||
do {
|
||||
if (free_distance < HH_HOP_RANGE) {
|
||||
assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask));
|
||||
rt->buckets[start_bucket].hopinfo |= 1u << free_distance;
|
||||
rt->buckets[free_bucket].data = (void *) data;
|
||||
return 1;
|
||||
}
|
||||
free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance);
|
||||
assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask);
|
||||
} while (free_bucket != NOT_A_BUCKET);
|
||||
}
|
||||
|
||||
ddsrt_hh_resize (rt);
|
||||
return ddsrt_hh_add (rt, data);
|
||||
}
|
||||
|
||||
int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template)
|
||||
{
|
||||
const uint32_t hash = rt->hash (template);
|
||||
const uint32_t idxmask = rt->size - 1;
|
||||
const uint32_t bucket = hash & idxmask;
|
||||
uint32_t hopinfo;
|
||||
uint32_t idx;
|
||||
hopinfo = rt->buckets[bucket].hopinfo;
|
||||
for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
|
||||
if (hopinfo & 1) {
|
||||
const uint32_t bidx = (bucket + idx) & idxmask;
|
||||
void *data = rt->buckets[bidx].data;
|
||||
if (data && rt->equals (data, template)) {
|
||||
rt->buckets[bidx].data = NULL;
|
||||
rt->buckets[bucket].hopinfo &= ~(1u << idx);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < rt->size; i++) {
|
||||
void *data = rt->buckets[i].data;
|
||||
if (data) {
|
||||
f (data, f_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter)
|
||||
{
|
||||
iter->hh = rt;
|
||||
iter->cursor = 0;
|
||||
return ddsrt_hh_iter_next (iter);
|
||||
}
|
||||
|
||||
void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter)
|
||||
{
|
||||
struct ddsrt_hh *rt = iter->hh;
|
||||
while (iter->cursor < rt->size) {
|
||||
void *data = rt->buckets[iter->cursor].data;
|
||||
iter->cursor++;
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/************* SEQUENTIAL VERSION WITH EMBEDDED DATA ***************/
|
||||
|
||||
|
|
208
src/ddsrt/src/ifaddrs/lwip/ifaddrs.c
Normal file
208
src/ddsrt/src/ifaddrs/lwip/ifaddrs.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 <string.h>
|
||||
#include <lwip/inet.h>
|
||||
#include <lwip/netif.h> /* netif_list */
|
||||
#include <lwip/sockets.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/io.h"
|
||||
#include "dds/ddsrt/ifaddrs.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
extern const int *const os_supp_afs;
|
||||
|
||||
static uint32_t
|
||||
getflags(
|
||||
const struct netif *netif,
|
||||
const ip_addr_t *addr)
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (netif->flags & NETIF_FLAG_UP) {
|
||||
flags |= IFF_UP;
|
||||
}
|
||||
if (netif->flags & NETIF_FLAG_BROADCAST) {
|
||||
flags |= IFF_BROADCAST;
|
||||
}
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
flags |= IFF_MULTICAST;
|
||||
}
|
||||
if (ip_addr_isloopback(addr)) {
|
||||
flags |= IFF_LOOPBACK;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void
|
||||
sockaddr_from_ip_addr(
|
||||
struct sockaddr *sockaddr,
|
||||
const ip_addr_t *addr)
|
||||
{
|
||||
if (IP_IS_V4(addr)) {
|
||||
memset(sockaddr, 0, sizeof(struct sockaddr_in));
|
||||
((struct sockaddr_in *)sockaddr)->sin_len = sizeof(struct sockaddr_in);
|
||||
((struct sockaddr_in *)sockaddr)->sin_family = AF_INET;
|
||||
inet_addr_from_ip4addr(&((struct sockaddr_in *)sockaddr)->sin_addr, addr);
|
||||
#if DDSRT_HAVE_IPV6
|
||||
} else {
|
||||
assert(IP_IS_V6(addr));
|
||||
memset(sockaddr, 0, sizeof(struct sockaddr_in6));
|
||||
((struct sockaddr_in6 *)sockaddr)->sin6_len = sizeof(struct sockaddr_in6);
|
||||
((struct sockaddr_in6 *)sockaddr)->sin6_family = AF_INET6;
|
||||
inet6_addr_from_ip6addr(&((struct sockaddr_in6 *)sockaddr)->sin6_addr, addr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static dds_return_t
|
||||
copyaddr(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const struct netif *netif,
|
||||
const ip_addr_t *addr)
|
||||
{
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
ddsrt_ifaddrs_t *ifa;
|
||||
struct sockaddr_storage sa;
|
||||
|
||||
assert(ifap != NULL);
|
||||
assert(netif != NULL);
|
||||
assert(addr != NULL);
|
||||
|
||||
sockaddr_from_ip_addr((struct sockaddr *)&sa, addr);
|
||||
|
||||
/* Network interface name is of the form "et0", where the first two letters
|
||||
are the "name" field and the digit is the num field of the netif
|
||||
structure as described in lwip/netif.h */
|
||||
|
||||
if ((ifa = ddsrt_calloc_s(1, sizeof(*ifa))) == NULL ||
|
||||
(ifa->addr = ddsrt_memdup(&sa, sa.s2_len)) == NULL ||
|
||||
(ddsrt_asprintf(&ifa->name, "%s%d", netif->name, netif->num) == -1))
|
||||
{
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ifa->flags = getflags(netif, addr);
|
||||
ifa->index = netif->num;
|
||||
ifa->type = DDSRT_IFTYPE_UNKNOWN;
|
||||
|
||||
if (IP_IS_V4(addr)) {
|
||||
static const size_t sz = sizeof(struct sockaddr_in);
|
||||
if ((ifa->netmask = ddsrt_calloc_s(1, sz)) == NULL ||
|
||||
(ifa->broadaddr = ddsrt_calloc_s(1, sz)) == NULL)
|
||||
{
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ip_addr_t broadaddr = IPADDR4_INIT(
|
||||
ip_2_ip4(&netif->ip_addr)->addr |
|
||||
ip_2_ip4(&netif->netmask)->addr);
|
||||
|
||||
sockaddr_from_ip_addr((struct sockaddr*)ifa->netmask, &netif->netmask);
|
||||
sockaddr_from_ip_addr((struct sockaddr*)ifa->broadaddr, &broadaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
*ifap = ifa;
|
||||
} else {
|
||||
ddsrt_freeifaddrs(ifa);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const int *afs)
|
||||
{
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
int use_ip4, use_ip6;
|
||||
struct netif *netif;
|
||||
ddsrt_ifaddrs_t *ifa, *next_ifa, *root_ifa;
|
||||
|
||||
assert(ifap != NULL);
|
||||
|
||||
if (afs == NULL) {
|
||||
afs = os_supp_afs;
|
||||
}
|
||||
|
||||
use_ip4 = use_ip6 = 0;
|
||||
for (int i = 0; afs[i] != DDSRT_AF_TERM; i++) {
|
||||
if (afs[i] == AF_INET) {
|
||||
use_ip4 = 1;
|
||||
} else if (afs[i] == AF_INET6) {
|
||||
use_ip6 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ifa = next_ifa = root_ifa = NULL;
|
||||
|
||||
for (netif = netif_list;
|
||||
netif != NULL && rc == DDS_RETCODE_OK;
|
||||
netif = netif->next)
|
||||
{
|
||||
if (use_ip4 && IP_IS_V4(&netif->ip_addr)) {
|
||||
rc = copyaddr(&next_ifa, netif, &netif->ip_addr);
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
if (ifa == NULL) {
|
||||
ifa = root_ifa = next_ifa;
|
||||
} else {
|
||||
ifa->next = next_ifa;
|
||||
ifa = next_ifa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
if (use_ip6) {
|
||||
int pref = 1;
|
||||
again:
|
||||
/* List preferred IPv6 address first. */
|
||||
for (int i = 0;
|
||||
i < LWIP_IPV6_NUM_ADDRESSES && rc == DDS_RETCODE_OK;
|
||||
i++)
|
||||
{
|
||||
if ((ip6_addr_ispreferred(netif->ip_addr_state[i]) && pref) ||
|
||||
(ip6_addr_isvalid(netif->ip_addr_state[i]) && !pref))
|
||||
{
|
||||
rc = copyaddr(&next_ifa, netif, &netif->ip_addr[i]);
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
if (ifa == NULL) {
|
||||
ifa = root_ifa = next_ifa;
|
||||
} else {
|
||||
ifa->next = next_ifa;
|
||||
ifa = next_ifa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == DDS_RETCODE_OK && pref) {
|
||||
pref = 0;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
*ifap = ifa;
|
||||
} else {
|
||||
ddsrt_freeifaddrs(root_ifa);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -21,10 +21,115 @@
|
|||
|
||||
extern const int *const os_supp_afs;
|
||||
|
||||
static dds_retcode_t
|
||||
copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
|
||||
#if defined __linux
|
||||
#include <stdio.h>
|
||||
|
||||
static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_OK;
|
||||
FILE *fp;
|
||||
char ifnam[IFNAMSIZ + 1]; /* not sure whether IFNAMSIZ includes a terminating 0, can't be bothered */
|
||||
int c;
|
||||
size_t np;
|
||||
enum ddsrt_iftype type = DDSRT_IFTYPE_UNKNOWN;
|
||||
if ((fp = fopen ("/proc/net/wireless", "r")) == NULL)
|
||||
return type;
|
||||
/* expected format:
|
||||
:Inter-| sta-| Quality | Discarded packets | Missed | WE
|
||||
: face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
|
||||
: wlan0: 0000 67. -43. -256 0 0 0 0 0 0
|
||||
(where : denotes the start of the line)
|
||||
|
||||
SKIP_HEADER_1 skips up to and including the first newline; then SKIP_TO_EOL skips
|
||||
up to and including the second newline, so the first line that gets interpreted is
|
||||
the third.
|
||||
*/
|
||||
enum { SKIP_HEADER_1, SKIP_WHITE, READ_NAME, SKIP_TO_EOL } state = SKIP_HEADER_1;
|
||||
np = 0;
|
||||
while (type != DDSRT_IFTYPE_WIFI && (c = fgetc (fp)) != EOF) {
|
||||
switch (state) {
|
||||
case SKIP_HEADER_1:
|
||||
if (c == '\n') {
|
||||
state = SKIP_TO_EOL;
|
||||
}
|
||||
break;
|
||||
case SKIP_WHITE:
|
||||
if (c != ' ' && c != '\t') {
|
||||
ifnam[np++] = (char) c;
|
||||
state = READ_NAME;
|
||||
}
|
||||
break;
|
||||
case READ_NAME:
|
||||
if (c == ':') {
|
||||
ifnam[np] = 0;
|
||||
if (strcmp (ifnam, sys_ifa->ifa_name) == 0)
|
||||
type = DDSRT_IFTYPE_WIFI;
|
||||
state = SKIP_TO_EOL;
|
||||
np = 0;
|
||||
} else if (np < sizeof (ifnam) - 1) {
|
||||
ifnam[np++] = (char) c;
|
||||
}
|
||||
break;
|
||||
case SKIP_TO_EOL:
|
||||
if (c == '\n') {
|
||||
state = SKIP_WHITE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
return type;
|
||||
}
|
||||
#elif defined __APPLE__ /* probably works for all BSDs */
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
|
||||
{
|
||||
int sock;
|
||||
if ((sock = socket (sys_ifa->ifa_addr->sa_family, SOCK_DGRAM, 0)) == -1)
|
||||
return DDSRT_IFTYPE_UNKNOWN;
|
||||
|
||||
struct ifmediareq ifmr;
|
||||
enum ddsrt_iftype type;
|
||||
memset (&ifmr, 0, sizeof (ifmr));
|
||||
ddsrt_strlcpy (ifmr.ifm_name, sys_ifa->ifa_name, sizeof (ifmr.ifm_name));
|
||||
if (ioctl (sock, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
|
||||
{
|
||||
type = DDSRT_IFTYPE_UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (IFM_TYPE (ifmr.ifm_active))
|
||||
{
|
||||
case IFM_ETHER:
|
||||
case IFM_TOKEN:
|
||||
case IFM_FDDI:
|
||||
type = DDSRT_IFTYPE_WIRED;
|
||||
break;
|
||||
case IFM_IEEE80211:
|
||||
type = DDSRT_IFTYPE_WIFI;
|
||||
break;
|
||||
default:
|
||||
type = DDSRT_IFTYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
close (sock);
|
||||
return type;
|
||||
}
|
||||
#else
|
||||
static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
|
||||
{
|
||||
return DDSRT_IFTYPE_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
|
||||
static dds_return_t
|
||||
copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa, enum ddsrt_iftype type)
|
||||
{
|
||||
dds_return_t err = DDS_RETCODE_OK;
|
||||
ddsrt_ifaddrs_t *ifa;
|
||||
size_t sz;
|
||||
|
||||
|
@ -37,6 +142,7 @@ copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
|
|||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ifa->index = if_nametoindex(sys_ifa->ifa_name);
|
||||
ifa->type = type;
|
||||
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 ||
|
||||
|
@ -64,12 +170,12 @@ copyaddr(ddsrt_ifaddrs_t **ifap, const struct ifaddrs *sys_ifa)
|
|||
return err;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const int *afs)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_OK;
|
||||
dds_return_t err = DDS_RETCODE_OK;
|
||||
int use;
|
||||
ddsrt_ifaddrs_t *ifa, *ifa_root, *ifa_next;
|
||||
struct ifaddrs *sys_ifa, *sys_ifa_root;
|
||||
|
@ -109,7 +215,8 @@ ddsrt_getifaddrs(
|
|||
}
|
||||
|
||||
if (use) {
|
||||
err = copyaddr(&ifa_next, sys_ifa);
|
||||
enum ddsrt_iftype type = guess_iftype (sys_ifa);
|
||||
err = copyaddr(&ifa_next, sys_ifa, type);
|
||||
if (err == DDS_RETCODE_OK) {
|
||||
if (ifa == NULL) {
|
||||
ifa = ifa_root = ifa_next;
|
||||
|
|
84
src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c
Normal file
84
src/ddsrt/src/ifaddrs/solaris2.6/ifaddrs.c
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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/ifaddrs.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
extern const int *const os_supp_afs;
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
dds_return_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ret_ifap,
|
||||
const int *afs)
|
||||
{
|
||||
int sock;
|
||||
char *buf;
|
||||
int32_t n;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr;
|
||||
|
||||
/* get interfaces */
|
||||
buf = ddsrt_malloc (8192);
|
||||
memset (&ifc, 0, sizeof (ifc));
|
||||
ifc.ifc_len = 8192;
|
||||
ifc.ifc_buf = buf;
|
||||
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0)
|
||||
{
|
||||
perror ("ioctl (SIOCGIFCONF)");
|
||||
exit (77);
|
||||
}
|
||||
|
||||
ddsrt_ifaddrs_t **ifap, *ifa_root;
|
||||
ifap = &ifa_root; ifa_root = NULL;
|
||||
ifr = ifc.ifc_req;
|
||||
for (n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++)
|
||||
{
|
||||
ddsrt_ifaddrs_t *ifa;
|
||||
if (ifr->ifr_name[0] == '\0')
|
||||
continue; /* Forget about anonymous network devices */
|
||||
|
||||
if (ifr->ifr_addr.sa_family != AF_INET) {
|
||||
printf ("%s: not INET\n", ifr->ifr_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
ifa = ddsrt_malloc (sizeof (*ifa));
|
||||
memset (ifa, 0, sizeof (*ifa));
|
||||
ifa->index = (int) (ifr - ifc.ifc_req);
|
||||
ifa->flags = IFF_UP | ((strcmp(ifr->ifr_name, "lo0")==0) ? IFF_LOOPBACK : IFF_MULTICAST);
|
||||
ifa->name = strdup (ifr->ifr_name);
|
||||
ifa->addr = ddsrt_memdup (&ifr->ifr_addr, sizeof (struct sockaddr_in));
|
||||
ifa->netmask = ddsrt_memdup (&ifr->ifr_addr, sizeof (struct sockaddr_in));
|
||||
((struct sockaddr_in *) ifa->netmask)->sin_addr.s_addr = htonl (0xffffff00);
|
||||
ifa->broadaddr = NULL;
|
||||
ifa->next = NULL;
|
||||
*ifap = ifa;
|
||||
ifap = &ifa->next;
|
||||
}
|
||||
|
||||
ddsrt_free (buf);
|
||||
close (sock);
|
||||
*ret_ifap = ifa_root;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
|
@ -23,10 +23,10 @@
|
|||
|
||||
extern const int *const os_supp_afs;
|
||||
|
||||
static dds_retcode_t
|
||||
static dds_return_t
|
||||
getifaces(PIP_ADAPTER_ADDRESSES *ptr)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
dds_return_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
PIP_ADAPTER_ADDRESSES buf = NULL;
|
||||
ULONG bufsz = 0; /* Size is determined on first iteration. */
|
||||
ULONG ret;
|
||||
|
@ -72,10 +72,10 @@ getifaces(PIP_ADAPTER_ADDRESSES *ptr)
|
|||
return err;
|
||||
}
|
||||
|
||||
static dds_retcode_t
|
||||
static dds_return_t
|
||||
getaddrtable(PMIB_IPADDRTABLE *ptr)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
dds_return_t err = DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
PMIB_IPADDRTABLE buf = NULL;
|
||||
ULONG bufsz = 0;
|
||||
DWORD ret;
|
||||
|
@ -152,6 +152,21 @@ getflags(const PIP_ADAPTER_ADDRESSES iface)
|
|||
return flags;
|
||||
}
|
||||
|
||||
static enum ddsrt_iftype
|
||||
guess_iftype (const PIP_ADAPTER_ADDRESSES iface)
|
||||
{
|
||||
switch (iface->IfType) {
|
||||
case IF_TYPE_IEEE80211:
|
||||
return DDSRT_IFTYPE_WIFI;
|
||||
case IF_TYPE_ETHERNET_CSMACD:
|
||||
case IF_TYPE_IEEE1394:
|
||||
case IF_TYPE_ISO88025_TOKENRING:
|
||||
return DDSRT_IFTYPE_WIRED;
|
||||
default:
|
||||
return DDSRT_IFTYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
copyaddr(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
|
@ -159,7 +174,7 @@ copyaddr(
|
|||
const PMIB_IPADDRTABLE addrtable,
|
||||
const PIP_ADAPTER_UNICAST_ADDRESS addr)
|
||||
{
|
||||
dds_retcode_t err = DDS_RETCODE_OK;
|
||||
dds_return_t err = DDS_RETCODE_OK;
|
||||
ddsrt_ifaddrs_t *ifa;
|
||||
struct sockaddr *sa;
|
||||
size_t sz;
|
||||
|
@ -175,6 +190,7 @@ copyaddr(
|
|||
err = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ifa->flags = getflags(iface);
|
||||
ifa->type = guess_iftype(iface);
|
||||
ifa->addr = ddsrt_memdup(sa, sz);
|
||||
(void)ddsrt_asprintf(&ifa->name, "%wS", iface->FriendlyName);
|
||||
if (ifa->addr == NULL || ifa->name == NULL) {
|
||||
|
@ -220,7 +236,7 @@ copyaddr(
|
|||
return err;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getifaddrs(
|
||||
ddsrt_ifaddrs_t **ifap,
|
||||
const int *afs)
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
#include "dds/ddsrt/static_assert.h"
|
||||
|
||||
#define MAX_ID_LEN (10)
|
||||
#define MAX_TIMESTAMP_LEN (10 + 1 + 6)
|
||||
#define MAX_TID_LEN (10)
|
||||
#define HDR_LEN (MAX_TIMESTAMP_LEN + 1 + MAX_TID_LEN + 2)
|
||||
#define HDR_LEN (MAX_TIMESTAMP_LEN + 2 + MAX_ID_LEN + 2 + MAX_TID_LEN + 2)
|
||||
|
||||
#define BUF_OFFSET HDR_LEN
|
||||
|
||||
|
@ -31,7 +33,7 @@ typedef struct {
|
|||
} log_buffer_t;
|
||||
|
||||
typedef struct {
|
||||
dds_log_write_fn_t funcs[2];
|
||||
dds_log_write_fn_t func;
|
||||
void *ptr;
|
||||
FILE *out;
|
||||
} log_sink_t;
|
||||
|
@ -41,50 +43,58 @@ 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;
|
||||
struct ddsrt_log_cfg_impl {
|
||||
struct ddsrt_log_cfg_common c;
|
||||
FILE *sink_fps[2];
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
DDSRT_STATIC_ASSERT (sizeof (struct ddsrt_log_cfg_impl) <= sizeof (struct ddsrt_log_cfg));
|
||||
|
||||
static void nop_sink(void *ptr, const dds_log_data_t *data)
|
||||
static void default_sink (void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)data;
|
||||
return;
|
||||
if (ptr)
|
||||
{
|
||||
fwrite (data->message - data->hdrsize, 1, data->hdrsize + data->size + 1, (FILE *) ptr);
|
||||
fflush ((FILE *) ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#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 }
|
||||
static struct ddsrt_log_cfg_impl logconfig = {
|
||||
.c = {
|
||||
.mask = DDS_LC_ERROR | DDS_LC_WARNING,
|
||||
.tracemask = 0,
|
||||
.domid = UINT32_MAX
|
||||
},
|
||||
.sink_fps = {
|
||||
[LOG] = NULL,
|
||||
[TRACE] = NULL
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t *const dds_log_mask = &log_mask;
|
||||
static log_sink_t sinks[2] = {
|
||||
[LOG] = { .func = default_sink, .ptr = NULL, .out = NULL },
|
||||
[TRACE] = { .func = default_sink, .ptr = NULL, .out = NULL }
|
||||
};
|
||||
|
||||
#define RDLOCK (1)
|
||||
#define WRLOCK (2)
|
||||
uint32_t * const dds_log_mask = &logconfig.c.mask;
|
||||
|
||||
static void init_lock(void)
|
||||
static void init_lock (void)
|
||||
{
|
||||
ddsrt_rwlock_init(&lock);
|
||||
ddsrt_rwlock_init (&lock);
|
||||
sinks[LOG].ptr = sinks[TRACE].ptr = stderr;
|
||||
sinks[LOG].out = sinks[TRACE].out = stderr;
|
||||
logconfig.sink_fps[LOG] = sinks[LOG].ptr;
|
||||
logconfig.sink_fps[TRACE] = sinks[TRACE].ptr;
|
||||
}
|
||||
|
||||
static void lock_sink(int type)
|
||||
{
|
||||
assert(type == RDLOCK || type == WRLOCK);
|
||||
ddsrt_once(&lock_inited, &init_lock);
|
||||
enum lock_type { RDLOCK, WRLOCK };
|
||||
|
||||
static void lock_sink (enum lock_type type)
|
||||
{
|
||||
ddsrt_once (&lock_inited, &init_lock);
|
||||
if (type == RDLOCK) {
|
||||
ddsrt_rwlock_read(&lock);
|
||||
} else {
|
||||
|
@ -92,154 +102,134 @@ static void lock_sink(int type)
|
|||
}
|
||||
}
|
||||
|
||||
static void unlock_sink(void)
|
||||
static void unlock_sink (void)
|
||||
{
|
||||
ddsrt_rwlock_unlock(&lock);
|
||||
ddsrt_rwlock_unlock (&lock);
|
||||
}
|
||||
|
||||
static void set_active_log_sinks(void)
|
||||
static void set_log_sink (log_sink_t *sink, dds_log_write_fn_t func, void *ptr)
|
||||
{
|
||||
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);
|
||||
assert (sink != NULL);
|
||||
assert (sink == &sinks[0] || sink == &sinks[1]);
|
||||
|
||||
/* 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();
|
||||
lock_sink (WRLOCK);
|
||||
sink->func = (func != 0) ? func : default_sink;
|
||||
sink->ptr = ptr;
|
||||
unlock_sink ();
|
||||
}
|
||||
|
||||
/* dds_set_log_file must be considered private. */
|
||||
void dds_set_log_file(FILE *file)
|
||||
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();
|
||||
lock_sink (WRLOCK);
|
||||
logconfig.sink_fps[LOG] = (file == NULL ? stderr : file);
|
||||
unlock_sink ();
|
||||
}
|
||||
|
||||
void dds_set_trace_file(FILE *file)
|
||||
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();
|
||||
lock_sink (WRLOCK);
|
||||
logconfig.sink_fps[TRACE] = (file == NULL ? stderr : file);
|
||||
unlock_sink ();
|
||||
}
|
||||
|
||||
void dds_set_log_sink(
|
||||
dds_log_write_fn_t callback,
|
||||
void *userdata)
|
||||
void dds_set_log_sink (dds_log_write_fn_t callback, void *userdata)
|
||||
{
|
||||
set_log_sink(&sinks[LOG], callback, userdata);
|
||||
set_log_sink (&sinks[LOG], callback, userdata);
|
||||
}
|
||||
|
||||
void dds_set_trace_sink(
|
||||
dds_log_write_fn_t callback,
|
||||
void *userdata)
|
||||
void dds_set_trace_sink (dds_log_write_fn_t callback, void *userdata)
|
||||
{
|
||||
set_log_sink(&sinks[TRACE], callback, userdata);
|
||||
set_log_sink (&sinks[TRACE], callback, userdata);
|
||||
}
|
||||
|
||||
extern inline uint32_t
|
||||
dds_get_log_mask(void);
|
||||
extern inline uint32_t dds_get_log_mask (void);
|
||||
|
||||
void
|
||||
dds_set_log_mask(uint32_t cats)
|
||||
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();
|
||||
lock_sink (WRLOCK);
|
||||
logconfig.c.tracemask = cats & DDS_TRACE_MASK;
|
||||
logconfig.c.mask = (cats & (DDS_LOG_MASK | DDS_TRACE_MASK)) | DDS_LC_FATAL;
|
||||
unlock_sink ();
|
||||
}
|
||||
|
||||
static void print_header(char *str)
|
||||
void dds_log_cfg_init (struct ddsrt_log_cfg *cfg, uint32_t domid, uint32_t tracemask, FILE *log_fp, FILE *trace_fp)
|
||||
{
|
||||
int cnt;
|
||||
struct ddsrt_log_cfg_impl *cfgimpl = (struct ddsrt_log_cfg_impl *) cfg;
|
||||
assert (domid != UINT32_MAX); /* because that's reserved for global use */
|
||||
memset (cfgimpl, 0, sizeof (*cfgimpl));
|
||||
cfgimpl->c.mask = tracemask | DDS_LOG_MASK;
|
||||
cfgimpl->c.tracemask = tracemask;
|
||||
cfgimpl->c.domid = domid;
|
||||
cfgimpl->sink_fps[LOG] = log_fp;
|
||||
cfgimpl->sink_fps[TRACE] = trace_fp;
|
||||
}
|
||||
|
||||
static size_t print_header (char *str, uint32_t id)
|
||||
{
|
||||
int cnt, off;
|
||||
char *tid, buf[MAX_TID_LEN+1] = { 0 };
|
||||
static const char fmt[] = "%10u.%06d/%*.*s:";
|
||||
static const char fmt_no_id[] = "%10u.%06d [] %*.*s:";
|
||||
static const char fmt_with_id[] = "%10u.%06d [%"PRIu32"] %*.*s:";
|
||||
dds_time_t time;
|
||||
unsigned sec;
|
||||
int usec;
|
||||
|
||||
(void)ddsrt_thread_getname(buf, sizeof(buf));
|
||||
(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);
|
||||
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. */
|
||||
if (id == UINT32_MAX)
|
||||
{
|
||||
off = MAX_ID_LEN;
|
||||
cnt = snprintf (str + off, HDR_LEN, fmt_no_id, sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* low domain ids tend to be most used from what I have seen */
|
||||
off = 9;
|
||||
if (id >= 10)
|
||||
for (uint32_t thres = 10; off > 0 && id >= thres; off--, thres *= 10);
|
||||
cnt = snprintf (str + off, HDR_LEN, fmt_with_id, sec, usec, id, MAX_TID_LEN, MAX_TID_LEN, tid);
|
||||
}
|
||||
assert (off + cnt == (HDR_LEN - 1));
|
||||
str[off + cnt] = ' '; /* Replace snprintf null byte by space. */
|
||||
return (size_t) cnt;
|
||||
}
|
||||
|
||||
static void vlog(
|
||||
uint32_t cat,
|
||||
const char *file,
|
||||
uint32_t line,
|
||||
const char *func,
|
||||
const char *fmt,
|
||||
va_list ap)
|
||||
static void vlog1 (const struct ddsrt_log_cfg_impl *cfg, uint32_t cat, uint32_t domid, 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;
|
||||
|
||||
/* id can be used to override the id in logconfig, so that the global
|
||||
logging configuration can be used for reporting errors while inlcuding
|
||||
a domain id. This simply verifies that the id override is only ever
|
||||
used with the global one. */
|
||||
assert (domid == cfg->c.domid || cfg == &logconfig);
|
||||
|
||||
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;
|
||||
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);
|
||||
n = vsnprintf (lb->buf + lb->pos, nrem, fmt, ap);
|
||||
if (n >= 0 && (size_t) n < nrem) {
|
||||
lb->pos += (size_t) n;
|
||||
} else {
|
||||
|
@ -249,54 +239,89 @@ static void vlog(
|
|||
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);
|
||||
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);
|
||||
if (fmt[strlen (fmt) - 1] == '\n' && lb->pos > BUF_OFFSET + 1) {
|
||||
assert (lb->pos > BUF_OFFSET);
|
||||
size_t hdrsize = print_header (lb->buf, domid);
|
||||
|
||||
data.priority = cat;
|
||||
data.file = file;
|
||||
data.function = func;
|
||||
data.line = line;
|
||||
data.message = lb->buf + BUF_OFFSET;
|
||||
data.size = strlen(data.message) - 1;
|
||||
data.size = lb->pos - BUF_OFFSET - 1;
|
||||
data.hdrsize = hdrsize;
|
||||
|
||||
for (size_t i = (cat & DDS_LOG_MASK) ? LOG : TRACE;
|
||||
i < sizeof(sinks) / sizeof(sinks[0]);
|
||||
i++)
|
||||
dds_log_write_fn_t f = 0;
|
||||
void *f_arg = NULL;
|
||||
if (cat & DDS_LOG_MASK)
|
||||
{
|
||||
sinks[i].funcs[USE](sinks[i].ptr, &data);
|
||||
f = sinks[LOG].func;
|
||||
f_arg = (f == default_sink) ? cfg->sink_fps[LOG] : sinks[LOG].ptr;
|
||||
assert (f != 0);
|
||||
f (f_arg, &data);
|
||||
}
|
||||
/* if tracing is enabled, then print to trace if it matches the
|
||||
trace flags or if it got written to the log
|
||||
(mask == (tracemask | DDS_LOG_MASK)) */
|
||||
if (cfg->c.tracemask && (cat & cfg->c.mask))
|
||||
{
|
||||
dds_log_write_fn_t const g = sinks[TRACE].func;
|
||||
void * const g_arg = (g == default_sink) ? cfg->sink_fps[TRACE] : sinks[TRACE].ptr;
|
||||
assert (g != 0);
|
||||
if (g != f || g_arg != f_arg)
|
||||
g (g_arg, &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,
|
||||
...)
|
||||
static void vlog (const struct ddsrt_log_cfg_impl *cfg, uint32_t cat, uint32_t domid, const char *file, uint32_t line, const char *func, const char *fmt, va_list ap)
|
||||
{
|
||||
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) {
|
||||
lock_sink (RDLOCK);
|
||||
vlog1 (cfg, cat, domid, file, line, func, fmt, ap);
|
||||
unlock_sink ();
|
||||
if (cat & DDS_LC_FATAL)
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dds_log_cfg (const struct ddsrt_log_cfg *cfg, uint32_t cat, const char *file, uint32_t line, const char *func, const char *fmt, ...)
|
||||
{
|
||||
const struct ddsrt_log_cfg_impl *cfgimpl = (const struct ddsrt_log_cfg_impl *) cfg;
|
||||
/* cfgimpl->c.mask is too weak a test because it has all DDS_LOG_MASK bits set,
|
||||
rather than just the ones in dds_get_log_mask() (so as not to cache the latter
|
||||
and have to keep them synchronized */
|
||||
if ((cfgimpl->c.mask & cat) && ((dds_get_log_mask () | cfgimpl->c.tracemask) & cat)) {
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
vlog (cfgimpl, cat, cfgimpl->c.domid, file, line, func, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
}
|
||||
|
||||
void dds_log_id (uint32_t cat, uint32_t id, const char *file, uint32_t line, const char *func, const char *fmt, ...)
|
||||
{
|
||||
if (dds_get_log_mask () & cat) {
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
vlog (&logconfig, cat, id, file, line, func, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
}
|
||||
|
||||
void dds_log (uint32_t cat, const char *file, uint32_t line, const char *func, const char *fmt, ...)
|
||||
{
|
||||
if (dds_get_log_mask () & cat) {
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
vlog (&logconfig, cat, UINT32_MAX, file, line, func, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
}
|
||||
|
|
130
src/ddsrt/src/netstat/darwin/netstat.c
Normal file
130
src/ddsrt/src/netstat/darwin/netstat.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_mib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <dds/ddsrt/heap.h>
|
||||
#include <dds/ddsrt/string.h>
|
||||
#include <dds/ddsrt/netstat.h>
|
||||
|
||||
struct ddsrt_netstat_control {
|
||||
char *name;
|
||||
int cached_row;
|
||||
};
|
||||
|
||||
static dds_return_t ddsrt_netstat_get_int (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||
{
|
||||
int name[6];
|
||||
size_t len;
|
||||
int count;
|
||||
struct ifmibdata ifmd;
|
||||
|
||||
if (control->cached_row > 0)
|
||||
{
|
||||
name[0] = CTL_NET;
|
||||
name[1] = PF_LINK;
|
||||
name[2] = NETLINK_GENERIC;
|
||||
name[3] = IFMIB_IFDATA;
|
||||
name[4] = control->cached_row;
|
||||
name[5] = IFDATA_GENERAL;
|
||||
len = sizeof (ifmd);
|
||||
if (sysctl (name, 6, &ifmd, &len, NULL, 0) != 0)
|
||||
control->cached_row = 0;
|
||||
else if (strcmp (ifmd.ifmd_name, control->name) != 0)
|
||||
control->cached_row = 0;
|
||||
}
|
||||
|
||||
if (control->cached_row == 0)
|
||||
{
|
||||
name[0] = CTL_NET;
|
||||
name[1] = PF_LINK;
|
||||
name[2] = NETLINK_GENERIC;
|
||||
name[3] = IFMIB_SYSTEM;
|
||||
name[4] = IFMIB_IFCOUNT;
|
||||
len = sizeof (count);
|
||||
if (sysctl (name, 5, &count, &len, NULL, 0) != 0)
|
||||
goto error;
|
||||
for (int row = 1; row <= count; row++)
|
||||
{
|
||||
name[0] = CTL_NET;
|
||||
name[1] = PF_LINK;
|
||||
name[2] = NETLINK_GENERIC;
|
||||
name[3] = IFMIB_IFDATA;
|
||||
name[4] = row;
|
||||
name[5] = IFDATA_GENERAL;
|
||||
len = sizeof (ifmd);
|
||||
if (sysctl (name, 6, &ifmd, &len, NULL, 0) != 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
goto error;
|
||||
}
|
||||
else if (strcmp (control->name, ifmd.ifmd_name) == 0)
|
||||
{
|
||||
control->cached_row = row;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (control->cached_row == 0)
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
else
|
||||
{
|
||||
stats->ipkt = ifmd.ifmd_data.ifi_ipackets;
|
||||
stats->opkt = ifmd.ifmd_data.ifi_opackets;
|
||||
stats->ibytes = ifmd.ifmd_data.ifi_ibytes;
|
||||
stats->obytes = ifmd.ifmd_data.ifi_obytes;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
error:
|
||||
control->cached_row = -1;
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_new (struct ddsrt_netstat_control **control, const char *device)
|
||||
{
|
||||
struct ddsrt_netstat_control *c = ddsrt_malloc (sizeof (*c));
|
||||
struct ddsrt_netstat dummy;
|
||||
c->name = ddsrt_strdup (device);
|
||||
c->cached_row = 0;
|
||||
if (ddsrt_netstat_get_int (c, &dummy) != DDS_RETCODE_OK)
|
||||
{
|
||||
ddsrt_free (c->name);
|
||||
ddsrt_free (c);
|
||||
*control = NULL;
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
*control = c;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_free (struct ddsrt_netstat_control *control)
|
||||
{
|
||||
ddsrt_free (control->name);
|
||||
ddsrt_free (control);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_get (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||
{
|
||||
if (control->cached_row < 0)
|
||||
return DDS_RETCODE_ERROR;
|
||||
else
|
||||
return ddsrt_netstat_get_int (control, stats);
|
||||
}
|
146
src/ddsrt/src/netstat/linux/netstat.c
Normal file
146
src/ddsrt/src/netstat/linux/netstat.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <dds/ddsrt/heap.h>
|
||||
#include <dds/ddsrt/string.h>
|
||||
#include <dds/ddsrt/netstat.h>
|
||||
|
||||
struct ddsrt_netstat_control {
|
||||
char *name;
|
||||
};
|
||||
|
||||
dds_return_t ddsrt_netstat_get (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||
{
|
||||
FILE *fp;
|
||||
char save[256];
|
||||
int c;
|
||||
size_t np;
|
||||
int field = 0;
|
||||
if ((fp = fopen ("/proc/net/dev", "r")) == NULL)
|
||||
return DDS_RETCODE_ERROR;
|
||||
/* expected format: 2 header lines, then on each line, white space/interface
|
||||
name/colon and then numbers. Received bytes is 1st data field, transmitted
|
||||
bytes is 9th.
|
||||
|
||||
SKIP_HEADER_1 skips up to and including the first newline; then SKIP_TO_EOL
|
||||
skips up to and including the second newline, so the first line that gets
|
||||
interpreted is the third.
|
||||
*/
|
||||
dds_return_t res = DDS_RETCODE_NOT_FOUND;
|
||||
enum { SKIP_HEADER_1, SKIP_WHITE, READ_NAME, SKIP_TO_EOL, READ_SEP, READ_INT } state = SKIP_HEADER_1;
|
||||
np = 0;
|
||||
while (res == DDS_RETCODE_NOT_FOUND && (c = fgetc (fp)) != EOF) {
|
||||
switch (state) {
|
||||
case SKIP_HEADER_1:
|
||||
if (c == '\n') {
|
||||
state = SKIP_TO_EOL;
|
||||
}
|
||||
break;
|
||||
case SKIP_WHITE:
|
||||
if (c != ' ' && c != '\t') {
|
||||
save[np++] = (char) c;
|
||||
state = READ_NAME;
|
||||
}
|
||||
break;
|
||||
case READ_NAME:
|
||||
if (c == ':') {
|
||||
save[np] = 0;
|
||||
np = 0;
|
||||
if (strcmp (save, control->name) != 0)
|
||||
state = SKIP_TO_EOL;
|
||||
else
|
||||
state = READ_SEP;
|
||||
} else if (np < sizeof (save) - 1) {
|
||||
save[np++] = (char) c;
|
||||
}
|
||||
break;
|
||||
case SKIP_TO_EOL:
|
||||
if (c == '\n') {
|
||||
state = SKIP_WHITE;
|
||||
}
|
||||
break;
|
||||
case READ_SEP:
|
||||
if (c == '\n')
|
||||
{
|
||||
/* unexpected end of line */
|
||||
res = DDS_RETCODE_ERROR;
|
||||
}
|
||||
else if (c >= '0' && c <= '9')
|
||||
{
|
||||
field++;
|
||||
save[np++] = (char) c;
|
||||
state = READ_INT;
|
||||
}
|
||||
break;
|
||||
case READ_INT:
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
if (np == sizeof (save) - 1)
|
||||
{
|
||||
res = DDS_RETCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
save[np++] = (char) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
save[np] = 0;
|
||||
np = 0;
|
||||
if (field == 1 || field == 2 || field == 9 || field == 10)
|
||||
{
|
||||
int pos;
|
||||
uint64_t val;
|
||||
if (sscanf (save, "%"SCNu64"%n", &val, &pos) != 1 || save[pos] != 0)
|
||||
res = DDS_RETCODE_ERROR;
|
||||
else
|
||||
{
|
||||
switch (field)
|
||||
{
|
||||
case 1: stats->ibytes = val; break;
|
||||
case 2: stats->ipkt = val; break;
|
||||
case 9: stats->obytes = val; break;
|
||||
case 10: stats->opkt = val; res = DDS_RETCODE_OK; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c == '\n' && res != DDS_RETCODE_OK)
|
||||
{
|
||||
/* newline before all expected fields have been read */
|
||||
res = DDS_RETCODE_ERROR;
|
||||
}
|
||||
state = READ_SEP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
return res;
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_new (struct ddsrt_netstat_control **control, const char *device)
|
||||
{
|
||||
struct ddsrt_netstat_control *c = ddsrt_malloc (sizeof (*c));
|
||||
struct ddsrt_netstat dummy;
|
||||
c->name = ddsrt_strdup (device);
|
||||
if (ddsrt_netstat_get (c, &dummy) != DDS_RETCODE_OK)
|
||||
{
|
||||
ddsrt_free (c->name);
|
||||
ddsrt_free (c);
|
||||
*control = NULL;
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
*control = c;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_free (struct ddsrt_netstat_control *control)
|
||||
{
|
||||
ddsrt_free (control->name);
|
||||
ddsrt_free (control);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
115
src/ddsrt/src/netstat/windows/netstat.c
Normal file
115
src/ddsrt/src/netstat/windows/netstat.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
|
||||
#include <ws2def.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#include <dds/ddsrt/heap.h>
|
||||
#include <dds/ddsrt/string.h>
|
||||
#include <dds/ddsrt/netstat.h>
|
||||
|
||||
struct ddsrt_netstat_control {
|
||||
wchar_t *name;
|
||||
bool errored;
|
||||
bool have_index;
|
||||
NET_IFINDEX index;
|
||||
};
|
||||
|
||||
static void copy_data (struct ddsrt_netstat *dst, const MIB_IF_ROW2 *src)
|
||||
{
|
||||
dst->ipkt = src->InUcastPkts + src->InNUcastPkts;
|
||||
dst->opkt = src->OutUcastPkts + src->OutNUcastPkts;
|
||||
dst->ibytes = src->InOctets;
|
||||
dst->obytes = src->OutOctets;
|
||||
}
|
||||
|
||||
static bool is_desired_interface (const struct ddsrt_netstat_control *control, const MIB_IF_ROW2 *info)
|
||||
{
|
||||
return wcscmp (control->name, info->Description) == 0 || wcscmp (control->name, info->Alias) == 0;
|
||||
}
|
||||
|
||||
static dds_return_t ddsrt_netstat_get_int (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||
{
|
||||
if (control->errored)
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
if (control->have_index)
|
||||
{
|
||||
MIB_IF_ROW2 info;
|
||||
memset (&info, 0, sizeof (info));
|
||||
info.InterfaceIndex = control->index;
|
||||
if (GetIfEntry2 (&info) != NO_ERROR || !is_desired_interface (control, &info))
|
||||
control->have_index = false;
|
||||
else
|
||||
{
|
||||
copy_data (stats, &info);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
MIB_IF_TABLE2 *table;
|
||||
if (GetIfTable2 (&table) != NO_ERROR)
|
||||
goto error;
|
||||
control->have_index = false;
|
||||
for (ULONG row = 0; row < table->NumEntries; row++)
|
||||
{
|
||||
if (is_desired_interface (control, &table->Table[row]))
|
||||
{
|
||||
control->index = table->Table[row].InterfaceIndex;
|
||||
control->have_index = true;
|
||||
copy_data (stats, &table->Table[row]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
FreeMibTable (table);
|
||||
return control->have_index ? DDS_RETCODE_OK : DDS_RETCODE_NOT_FOUND;
|
||||
|
||||
error:
|
||||
control->errored = true;
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_new (struct ddsrt_netstat_control **control, const char *device)
|
||||
{
|
||||
struct ddsrt_netstat_control *c = ddsrt_malloc (sizeof (*c));
|
||||
struct ddsrt_netstat dummy;
|
||||
size_t name_size = strlen (device) + 1;
|
||||
c->name = ddsrt_malloc (name_size * sizeof (*c->name));
|
||||
size_t cnt = 0;
|
||||
mbstowcs_s (&cnt, c->name, name_size, device, _TRUNCATE);
|
||||
c->have_index = false;
|
||||
c->errored = false;
|
||||
c->index = 0;
|
||||
if (ddsrt_netstat_get_int (c, &dummy) != DDS_RETCODE_OK)
|
||||
{
|
||||
ddsrt_free (c->name);
|
||||
ddsrt_free (c);
|
||||
*control = NULL;
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
*control = c;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_free (struct ddsrt_netstat_control *control)
|
||||
{
|
||||
ddsrt_free (control->name);
|
||||
ddsrt_free (control);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t ddsrt_netstat_get (struct ddsrt_netstat_control *control, struct ddsrt_netstat *stats)
|
||||
{
|
||||
return ddsrt_netstat_get_int (control, stats);
|
||||
}
|
22
src/ddsrt/src/process/freertos/process.c
Normal file
22
src/ddsrt/src/process/freertos/process.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
ddsrt_pid_t
|
||||
ddsrt_getpid(void)
|
||||
{
|
||||
return xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ static void no_op(int sig)
|
|||
}
|
||||
|
||||
|
||||
static dds_retcode_t
|
||||
static dds_return_t
|
||||
waitpids(
|
||||
ddsrt_pid_t request_pid,
|
||||
dds_duration_t timeout,
|
||||
|
@ -81,7 +81,7 @@ waitpids(
|
|||
{
|
||||
struct sigaction sigactold;
|
||||
struct sigaction sigact;
|
||||
dds_retcode_t rv;
|
||||
dds_return_t rv;
|
||||
int options = 0;
|
||||
int ret;
|
||||
int s;
|
||||
|
@ -148,13 +148,13 @@ waitpids(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_create(
|
||||
const char *executable,
|
||||
char *const argv[],
|
||||
ddsrt_pid_t *pid)
|
||||
{
|
||||
dds_retcode_t rv;
|
||||
dds_return_t rv;
|
||||
char **exec_argv;
|
||||
int exec_fds[2];
|
||||
int exec_err;
|
||||
|
@ -253,7 +253,7 @@ fail_pipe:
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_waitpid(
|
||||
ddsrt_pid_t pid,
|
||||
dds_duration_t timeout,
|
||||
|
@ -267,7 +267,7 @@ ddsrt_proc_waitpid(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_waitpids(
|
||||
dds_duration_t timeout,
|
||||
ddsrt_pid_t *pid,
|
||||
|
@ -278,7 +278,7 @@ ddsrt_proc_waitpids(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_exists(
|
||||
ddsrt_pid_t pid)
|
||||
{
|
||||
|
@ -294,7 +294,7 @@ ddsrt_proc_exists(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_kill(
|
||||
ddsrt_pid_t pid)
|
||||
{
|
||||
|
|
|
@ -29,24 +29,24 @@ ddsrt_getpid(void)
|
|||
|
||||
|
||||
|
||||
static HANDLE pid_to_phdl (ddsrt_pid_t pid);
|
||||
static dds_retcode_t process_get_exit_code(HANDLE phdl, int32_t *code);
|
||||
static dds_retcode_t process_kill (HANDLE phdl);
|
||||
static char* commandline (const char *exe, char *const argv_in[]);
|
||||
static BOOL child_add (HANDLE phdl);
|
||||
static void child_remove (HANDLE phdl);
|
||||
static DWORD child_list (HANDLE *list, DWORD max);
|
||||
static HANDLE child_handle (ddsrt_pid_t pid);
|
||||
static HANDLE pid_to_phdl (ddsrt_pid_t pid);
|
||||
static dds_return_t process_get_exit_code(HANDLE phdl, int32_t *code);
|
||||
static dds_return_t process_kill (HANDLE phdl);
|
||||
static char* commandline (const char *exe, char *const argv_in[]);
|
||||
static BOOL child_add (HANDLE phdl);
|
||||
static void child_remove (HANDLE phdl);
|
||||
static DWORD child_list (HANDLE *list, DWORD max);
|
||||
static HANDLE child_handle (ddsrt_pid_t pid);
|
||||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_create(
|
||||
const char *executable,
|
||||
char *const argv[],
|
||||
ddsrt_pid_t *pid)
|
||||
{
|
||||
dds_retcode_t rv = DDS_RETCODE_ERROR;
|
||||
dds_return_t rv = DDS_RETCODE_ERROR;
|
||||
PROCESS_INFORMATION process_info;
|
||||
STARTUPINFO si;
|
||||
char *cmd;
|
||||
|
@ -111,13 +111,13 @@ ddsrt_proc_create(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_waitpid(
|
||||
ddsrt_pid_t pid,
|
||||
dds_duration_t timeout,
|
||||
int32_t *code)
|
||||
{
|
||||
dds_retcode_t rv = DDS_RETCODE_OK;
|
||||
dds_return_t rv = DDS_RETCODE_OK;
|
||||
HANDLE phdl;
|
||||
DWORD ret;
|
||||
|
||||
|
@ -155,13 +155,13 @@ ddsrt_proc_waitpid(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_waitpids(
|
||||
dds_duration_t timeout,
|
||||
ddsrt_pid_t *pid,
|
||||
int32_t *code)
|
||||
{
|
||||
dds_retcode_t rv = DDS_RETCODE_OK;
|
||||
dds_return_t rv = DDS_RETCODE_OK;
|
||||
HANDLE hdls[MAXIMUM_WAIT_OBJECTS];
|
||||
HANDLE phdl;
|
||||
DWORD cnt;
|
||||
|
@ -208,11 +208,11 @@ ddsrt_proc_waitpids(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_exists(
|
||||
ddsrt_pid_t pid)
|
||||
{
|
||||
dds_retcode_t rv = DDS_RETCODE_NOT_FOUND;
|
||||
dds_return_t rv = DDS_RETCODE_NOT_FOUND;
|
||||
HANDLE phdl;
|
||||
|
||||
phdl = pid_to_phdl(pid);
|
||||
|
@ -235,11 +235,11 @@ ddsrt_proc_exists(
|
|||
|
||||
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_proc_kill(
|
||||
ddsrt_pid_t pid)
|
||||
{
|
||||
dds_retcode_t rv = DDS_RETCODE_BAD_PARAMETER;
|
||||
dds_return_t rv = DDS_RETCODE_BAD_PARAMETER;
|
||||
HANDLE phdl;
|
||||
|
||||
phdl = pid_to_phdl(pid);
|
||||
|
@ -262,12 +262,12 @@ pid_to_phdl(ddsrt_pid_t pid)
|
|||
|
||||
|
||||
|
||||
static dds_retcode_t
|
||||
static dds_return_t
|
||||
process_get_exit_code(
|
||||
HANDLE phdl,
|
||||
int32_t *code)
|
||||
{
|
||||
dds_retcode_t rv = DDS_RETCODE_ERROR;
|
||||
dds_return_t rv = DDS_RETCODE_ERROR;
|
||||
DWORD tr;
|
||||
|
||||
assert(phdl != 0);
|
||||
|
@ -289,7 +289,7 @@ process_get_exit_code(
|
|||
|
||||
|
||||
/* Forcefully kill the given process. */
|
||||
static dds_retcode_t
|
||||
static dds_return_t
|
||||
process_kill(HANDLE phdl)
|
||||
{
|
||||
assert(phdl != 0);
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/process.h"
|
||||
#include "dds/ddsrt/static_assert.h"
|
||||
|
||||
#define N DDSRT_MT19937_N
|
||||
#define M 397
|
||||
|
@ -186,9 +187,7 @@ void ddsrt_random_init (void)
|
|||
if (!ddsrt_prng_makeseed (&seed))
|
||||
{
|
||||
/* Poor man's initialisation */
|
||||
struct lengthof_seed_large_enough {
|
||||
char ok[sizeof (seed.key) / sizeof (seed.key[0]) >= 3 ? 1 : -1];
|
||||
};
|
||||
DDSRT_STATIC_ASSERT (sizeof (seed.key) / sizeof (seed.key[0]) >= 3);
|
||||
memset (&seed, 0, sizeof (seed));
|
||||
dds_time_t now = dds_time ();
|
||||
seed.key[0] = (uint32_t) ddsrt_getpid ();
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
*/
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
|
||||
static const char *retcodes[] =
|
||||
{
|
||||
static const char *retcodes[] = {
|
||||
"Success",
|
||||
"Error",
|
||||
"Unsupported",
|
||||
|
@ -42,19 +41,20 @@ static const char *xretcodes[] = {
|
|||
"Not found"
|
||||
};
|
||||
|
||||
const char *
|
||||
dds_strretcode (dds_retcode_t rc)
|
||||
const char *dds_strretcode (dds_return_t rc)
|
||||
{
|
||||
if (rc >= 0 &&
|
||||
rc < (dds_retcode_t)(sizeof(retcodes) / sizeof(retcodes[0])))
|
||||
{
|
||||
const dds_return_t nretcodes = (dds_return_t) (sizeof (retcodes) / sizeof (retcodes[0]));
|
||||
const dds_return_t nxretcodes = (dds_return_t) (sizeof (xretcodes) / sizeof (xretcodes[0]));
|
||||
/* Retcodes used to be positive, but return values from the API would be a negative
|
||||
and so there are/were/may be places outside the core library where dds_strretcode
|
||||
is called with a -N for N a API return value, so ... play it safe and use the
|
||||
magnitude */
|
||||
if (rc < 0)
|
||||
rc = -rc;
|
||||
if (rc >= 0 && rc < nretcodes)
|
||||
return retcodes[rc];
|
||||
} else if (rc >= (DDS_XRETCODE_BASE) &&
|
||||
rc < (dds_retcode_t)(DDS_XRETCODE_BASE + (sizeof(xretcodes) / sizeof(xretcodes[0]))))
|
||||
{
|
||||
else if (rc >= DDS_XRETCODE_BASE && rc < DDS_XRETCODE_BASE + nxretcodes)
|
||||
return xretcodes[rc - DDS_XRETCODE_BASE];
|
||||
}
|
||||
|
||||
return "Unknown return code";
|
||||
else
|
||||
return "Unknown return code";
|
||||
}
|
||||
|
||||
|
|
106
src/ddsrt/src/rusage/freertos/rusage.c
Normal file
106
src/ddsrt/src/rusage/freertos/rusage.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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 <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/rusage.h"
|
||||
|
||||
/* Task CPU time statistics require a high resolution timer. FreeRTOS
|
||||
recommends a time base between 10 and 100 times faster than the tick
|
||||
interrupt (https://www.freertos.org/rtos-run-time-stats.html), but does not
|
||||
define a macro or function to retrieve the base. */
|
||||
|
||||
/* Require time base to be defined for conversion to nanoseconds. */
|
||||
|
||||
#define DDSRT_NSECS_IN_RUSAGE_TIME_BASE (1) /* FIXME: Make configurable! */
|
||||
|
||||
#if !defined(DDSRT_NSECS_IN_RUSAGE_TIME_BASE)
|
||||
#error "Time base for run time stats is not defined"
|
||||
#endif
|
||||
|
||||
static dds_return_t
|
||||
rusage_self(ddsrt_rusage_t *usage)
|
||||
{
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
dds_duration_t nsecs;
|
||||
UBaseType_t cnt, len;
|
||||
TaskStatus_t *states = NULL, *ptr;
|
||||
size_t size;
|
||||
|
||||
do {
|
||||
len = uxTaskGetNumberOfTasks();
|
||||
size = len * sizeof(*states);
|
||||
if ((ptr = ddsrt_realloc_s(states, size)) == NULL) {
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
states = ptr;
|
||||
/* uxTaskGetSystemState returns 0 if the TaskStatus_t buffer is not
|
||||
sufficiently large enough. */
|
||||
cnt = uxTaskGetSystemState(states, len, NULL);
|
||||
}
|
||||
} while (rc == DDS_RETCODE_OK && cnt == 0);
|
||||
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
memset(usage, 0, sizeof(*usage));
|
||||
|
||||
for (len = cnt, cnt = 0; cnt < len; cnt++) {
|
||||
nsecs = states[cnt].ulRunTimeCounter * DDSRT_NSECS_IN_RUSAGE_TIME_BASE;
|
||||
usage->stime += nsecs; /* FIXME: Protect against possible overflow! */
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_free(states);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static dds_return_t
|
||||
rusage_thread(ddsrt_rusage_t *usage)
|
||||
{
|
||||
TaskStatus_t states;
|
||||
|
||||
memset(usage, 0, sizeof(*usage));
|
||||
memset(&states, 0, sizeof(states));
|
||||
vTaskGetInfo(xTaskGetCurrentTaskHandle(), &states, pdFALSE, eInvalid);
|
||||
usage->stime = states.ulRunTimeCounter * DDSRT_NSECS_IN_RUSAGE_TIME_BASE;
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
#if ! DDSRT_HAVE_THREAD_LIST
|
||||
static
|
||||
#endif
|
||||
dds_return_t
|
||||
ddsrt_getrusage_anythread(ddsrt_thread_list_id_t tid, ddsrt_rusage_t *__restrict usage)
|
||||
{
|
||||
assert(usage != NULL);
|
||||
return rusage_thread(tid, usage);
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_getrusage(enum ddsrt_getrusage_who who, ddsrt_rusage_t *usage)
|
||||
{
|
||||
dds_return_t rc;
|
||||
|
||||
assert(who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD);
|
||||
assert(usage != NULL);
|
||||
|
||||
if (who == DDSRT_RUSAGE_THREAD) {
|
||||
rc = rusage_thread_anythread(xTaskGetCurrentTaskHandle(), usage);
|
||||
} else {
|
||||
rc = rusage_self(usage);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -15,87 +15,212 @@
|
|||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "dds/ddsrt/rusage.h"
|
||||
|
||||
#if defined __linux
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
|
||||
dds_return_t
|
||||
ddsrt_getrusage_anythread (
|
||||
ddsrt_thread_list_id_t tid,
|
||||
ddsrt_rusage_t * __restrict usage)
|
||||
{
|
||||
/* Linux' man pages happily state that the second field is the process/task name
|
||||
in parentheses, and that %s is the correct scanf conversion. As it turns out
|
||||
the process name itself can contain spaces and parentheses ... so %s is not a
|
||||
good choice for the general case. The others are spec'd as a character or a
|
||||
number, which suggests the correct procedure is to have the 2nd field start at
|
||||
the first ( and end at the last ) ...
|
||||
|
||||
RSS is per-process, so no point in populating that one
|
||||
field 14, 15: utime, stime (field 1 is first)
|
||||
|
||||
Voluntary and involuntary context switches can be found in .../status, but
|
||||
not in stat; and .../status does not give the time. Crazy. */
|
||||
const double hz = (double) sysconf (_SC_CLK_TCK);
|
||||
char file[100];
|
||||
FILE *fp;
|
||||
int pos;
|
||||
pos = snprintf (file, sizeof (file), "/proc/self/task/%lu/stat", (unsigned long) tid);
|
||||
if (pos < 0 || pos >= (int) sizeof (file))
|
||||
return DDS_RETCODE_ERROR;
|
||||
if ((fp = fopen (file, "r")) == NULL)
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
/* max 2 64-bit ints plus some whitespace; need 1 extra for detecting something
|
||||
went wrong and we ended up gobbling up garbage; 64 will do */
|
||||
char save[64];
|
||||
size_t savepos = 0;
|
||||
int prevc, c;
|
||||
int field = 1;
|
||||
for (prevc = 0; (c = fgetc (fp)) != EOF; prevc = c)
|
||||
{
|
||||
if (field == 1)
|
||||
{
|
||||
if (c == '(')
|
||||
field = 2;
|
||||
}
|
||||
else if (field >= 2)
|
||||
{
|
||||
/* each close paren resets the field counter to 3 (the first is common,
|
||||
further ones are rare and occur only if the thread name contains a
|
||||
closing parenthesis), as well as the save space for fields 14 & 15
|
||||
that we care about. */
|
||||
if (c == ')')
|
||||
{
|
||||
field = 2;
|
||||
savepos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next field on transition of whitespace to non-whitespace */
|
||||
if (c != ' ' && prevc == ' ')
|
||||
field++;
|
||||
/* save fields 14 & 15 while continuing scanning to EOF on the off-chance
|
||||
that 14&15 initially appear to be in what ultimately turns out to be
|
||||
task name */
|
||||
if (field == 14 || field == 15)
|
||||
{
|
||||
if (savepos < sizeof (save) - 1)
|
||||
save[savepos++] = (char) c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
assert (savepos < sizeof (save));
|
||||
save[savepos] = 0;
|
||||
if (savepos == sizeof (save) - 1)
|
||||
return DDS_RETCODE_ERROR;
|
||||
/* it's really integer, but the conversion from an unknown HZ value is much
|
||||
less tricky in floating-point */
|
||||
double user, sys;
|
||||
if (sscanf (save, "%lf %lf%n", &user, &sys, &pos) != 2 || (save[pos] != 0 && save[pos] != ' '))
|
||||
return DDS_RETCODE_ERROR;
|
||||
usage->utime = (dds_time_t) (1e9 * user / hz);
|
||||
usage->stime = (dds_time_t) (1e9 * sys / hz);
|
||||
usage->idrss = 0;
|
||||
usage->maxrss = 0;
|
||||
usage->nvcsw = 0;
|
||||
usage->nivcsw = 0;
|
||||
|
||||
pos = snprintf (file, sizeof (file), "/proc/self/task/%lu/status", (unsigned long) tid);
|
||||
if (pos < 0 || pos >= (int) sizeof (file))
|
||||
return DDS_RETCODE_ERROR;
|
||||
if ((fp = fopen (file, "r")) == NULL)
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
enum { ERROR, READ_HEADING, SKIP_TO_EOL, READ_VCSW, READ_IVCSW } state = READ_HEADING;
|
||||
savepos = 0;
|
||||
while (state != ERROR && (c = fgetc (fp)) != EOF)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case READ_HEADING:
|
||||
if (savepos < sizeof (save) - 1)
|
||||
save[savepos++] = (char) c;
|
||||
if (c == ':')
|
||||
{
|
||||
save[savepos] = 0;
|
||||
savepos = 0;
|
||||
if (strcmp (save, "voluntary_ctxt_switches:") == 0)
|
||||
state = READ_VCSW;
|
||||
else if (strcmp (save, "nonvoluntary_ctxt_switches:") == 0)
|
||||
state = READ_IVCSW;
|
||||
else
|
||||
state = SKIP_TO_EOL;
|
||||
}
|
||||
break;
|
||||
case SKIP_TO_EOL:
|
||||
if (c == '\n')
|
||||
state = READ_HEADING;
|
||||
break;
|
||||
case READ_VCSW:
|
||||
case READ_IVCSW:
|
||||
if (fscanf (fp, "%zu", (state == READ_VCSW) ? &usage->nvcsw : &usage->nivcsw) != 1)
|
||||
state = ERROR;
|
||||
else
|
||||
state = SKIP_TO_EOL;
|
||||
break;
|
||||
case ERROR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
return (state == ERROR) ? DDS_RETCODE_ERROR : DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_getrusage (enum ddsrt_getrusage_who who, ddsrt_rusage_t *usage)
|
||||
{
|
||||
struct rusage buf;
|
||||
|
||||
assert (who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD);
|
||||
assert (usage != NULL);
|
||||
|
||||
memset (&buf, 0, sizeof(buf));
|
||||
if (getrusage ((who == DDSRT_RUSAGE_SELF) ? RUSAGE_SELF : RUSAGE_THREAD, &buf) == -1)
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
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 = 1024 * (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;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
#elif 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)
|
||||
dds_return_t
|
||||
ddsrt_getrusage_anythread (
|
||||
ddsrt_thread_list_id_t tid,
|
||||
ddsrt_rusage_t * __restrict usage)
|
||||
{
|
||||
int err = 0;
|
||||
struct rusage buf;
|
||||
dds_retcode_t rc;
|
||||
mach_msg_type_number_t cnt;
|
||||
thread_basic_info_data_t info;
|
||||
cnt = THREAD_BASIC_INFO_COUNT;
|
||||
if (thread_info ((mach_port_t) tid, THREAD_BASIC_INFO, (thread_info_t) &info, &cnt) != KERN_SUCCESS)
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
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;
|
||||
/* Don't see an (easy) way to get context switch counts */
|
||||
usage->utime = info.user_time.seconds * DDS_NSECS_IN_SEC + info.user_time.microseconds * DDS_NSECS_IN_USEC;
|
||||
usage->stime = info.system_time.seconds * DDS_NSECS_IN_SEC + info.system_time.microseconds * DDS_NSECS_IN_USEC;
|
||||
usage->idrss = 0;
|
||||
usage->maxrss = 0;
|
||||
usage->nivcsw = 0;
|
||||
usage->nvcsw = 0;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_getrusage (enum ddsrt_getrusage_who who, ddsrt_rusage_t *usage)
|
||||
{
|
||||
struct rusage buf;
|
||||
dds_return_t rc;
|
||||
|
||||
assert (usage != NULL);
|
||||
|
||||
memset (&buf, 0, sizeof(buf));
|
||||
if (getrusage (RUSAGE_SELF, &buf) == -1)
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
switch (who) {
|
||||
case DDSRT_RUSAGE_THREAD:
|
||||
if ((rc = ddsrt_getrusage_anythread (pthread_mach_thread_np (pthread_self()), usage)) < 0)
|
||||
return rc;
|
||||
break;
|
||||
case DDSRT_RUSAGE_SELF:
|
||||
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->nvcsw = (size_t) buf.ru_nvcsw;
|
||||
usage->nivcsw = (size_t) buf.ru_nivcsw;
|
||||
break;
|
||||
}
|
||||
usage->maxrss = (size_t) buf.ru_maxrss;
|
||||
usage->idrss = (size_t) buf.ru_idrss;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,36 +18,60 @@
|
|||
#include <psapi.h>
|
||||
|
||||
dds_time_t
|
||||
filetime_to_time(const FILETIME *ft)
|
||||
filetime_to_time (const FILETIME *ft)
|
||||
{
|
||||
/* FILETIME structures express times in 100-nanosecond time units. */
|
||||
return ((ft->dwHighDateTime << 31) + (ft->dwLowDateTime)) * 100;
|
||||
return (dds_time_t) ((((uint64_t) ft->dwHighDateTime << 31) + (ft->dwLowDateTime)) * 100);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
ddsrt_getrusage(int who, ddsrt_rusage_t *usage)
|
||||
dds_return_t
|
||||
ddsrt_getrusage_anythread (ddsrt_thread_list_id_t tid, ddsrt_rusage_t * __restrict usage)
|
||||
{
|
||||
FILETIME stime, utime, ctime, etime;
|
||||
PROCESS_MEMORY_COUNTERS pmctrs;
|
||||
|
||||
assert(who == DDSRT_RUSAGE_SELF || who == DDSRT_RUSAGE_THREAD);
|
||||
assert(usage != NULL);
|
||||
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;
|
||||
if (!GetThreadTimes (tid, &ctime, &etime, &stime, &utime))
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
memset (usage, 0, sizeof (*usage));
|
||||
usage->stime = filetime_to_time (&stime);
|
||||
usage->utime = filetime_to_time (&utime);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_getrusage (enum ddsrt_getrusage_who who, ddsrt_rusage_t *usage)
|
||||
{
|
||||
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)))
|
||||
return DDS_RETCODE_ERROR;
|
||||
|
||||
if (who == DDSRT_RUSAGE_THREAD)
|
||||
{
|
||||
dds_return_t rc;
|
||||
if ((rc = ddsrt_getrusage_anythread (GetCurrentThread (), usage)) < 0)
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
FILETIME stime, utime, ctime, etime;
|
||||
if (!GetProcessTimes (GetCurrentProcess (), &ctime, &etime, &stime, &utime))
|
||||
return DDS_RETCODE_ERROR;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,19 +15,21 @@
|
|||
#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"
|
||||
|
||||
#if !LWIP_SOCKET
|
||||
# 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 */
|
||||
#endif /* LWIP_SOCKET */
|
||||
|
||||
extern inline struct timeval *
|
||||
ddsrt_duration_to_timeval_ceil(dds_duration_t reltime, struct timeval *tv);
|
||||
|
||||
|
@ -37,7 +39,7 @@ const struct in6_addr ddsrt_in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
|||
#endif
|
||||
|
||||
const int afs[] = {
|
||||
#ifdef __linux
|
||||
#if defined(__linux) && !LWIP_SOCKET
|
||||
AF_PACKET,
|
||||
#endif /* __linux */
|
||||
#if DDSRT_HAVE_IPV6
|
||||
|
@ -62,7 +64,7 @@ ddsrt_sockaddr_get_size(const struct sockaddr *const sa)
|
|||
sz = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
#ifdef __linux
|
||||
#if defined(__linux) && !LWIP_SOCKET
|
||||
case AF_PACKET:
|
||||
sz = sizeof(struct sockaddr_ll);
|
||||
break;
|
||||
|
@ -175,7 +177,7 @@ ddsrt_sockaddr_insamesubnet(
|
|||
return eq;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_sockaddrfromstr(int af, const char *str, void *sa)
|
||||
{
|
||||
assert(str != NULL);
|
||||
|
@ -184,13 +186,19 @@ ddsrt_sockaddrfromstr(int af, const char *str, void *sa)
|
|||
switch (af) {
|
||||
case AF_INET: {
|
||||
struct in_addr buf;
|
||||
#if DDSRT_HAVE_INET_PTON
|
||||
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));
|
||||
}
|
||||
#else
|
||||
buf.s_addr = inet_addr (str);
|
||||
if (buf.s_addr == (in_addr_t)-1) {
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
#endif
|
||||
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: {
|
||||
|
@ -211,17 +219,28 @@ ddsrt_sockaddrfromstr(int af, const char *str, void *sa)
|
|||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size)
|
||||
dds_return_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size)
|
||||
{
|
||||
const char *ptr;
|
||||
|
||||
assert(sa != NULL);
|
||||
assert(buf != NULL);
|
||||
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_OFF(sign-conversion)
|
||||
#endif
|
||||
switch (((struct sockaddr *)sa)->sa_family) {
|
||||
case AF_INET:
|
||||
#if DDSRT_HAVE_INET_NTOP
|
||||
ptr = inet_ntop(
|
||||
AF_INET, &((struct sockaddr_in *)sa)->sin_addr, buf, (socklen_t)size);
|
||||
#else
|
||||
{
|
||||
in_addr_t x = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
|
||||
snprintf(buf,size,"%u.%u.%u.%u",(x>>24),(x>>16)&0xff,(x>>8)&0xff,x&0xff);
|
||||
ptr = buf;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#if DDSRT_HAVE_IPV6
|
||||
case AF_INET6:
|
||||
|
@ -232,6 +251,9 @@ dds_retcode_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size)
|
|||
default:
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_ON(sign-conversion)
|
||||
#endif
|
||||
|
||||
if (ptr == NULL) {
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
|
@ -241,7 +263,8 @@ dds_retcode_t ddsrt_sockaddrtostr(const void *sa, char *buf, size_t size)
|
|||
}
|
||||
|
||||
#if DDSRT_HAVE_DNS
|
||||
dds_retcode_t
|
||||
#if DDSRT_HAVE_GETADDRINFO
|
||||
dds_return_t
|
||||
ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp)
|
||||
{
|
||||
int gai_err = 0;
|
||||
|
@ -279,7 +302,6 @@ ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp)
|
|||
|
||||
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:
|
||||
|
@ -312,10 +334,14 @@ ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp)
|
|||
/* Other system error. */
|
||||
return DDS_RETCODE_ERROR;
|
||||
#endif
|
||||
#if defined(EAI_BADFLAGS)
|
||||
case EAI_BADFLAGS: /* Invalid flags in hints.ai_flags. */
|
||||
#endif
|
||||
case EAI_FAMILY: /* Address family not supported. */
|
||||
case EAI_SERVICE: /* Service not available for socket type. */
|
||||
#if defined(EAI_SOCKTYPE)
|
||||
case EAI_SOCKTYPE: /* Socket type not supported. */
|
||||
#endif
|
||||
case 0: {
|
||||
struct addrinfo *ai;
|
||||
size_t addrno, naddrs, size;
|
||||
|
@ -344,11 +370,30 @@ ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp)
|
|||
freeaddrinfo(res);
|
||||
} break;
|
||||
default:
|
||||
DDS_ERROR("getaddrinfo returned unkown error %d\n", gai_err);
|
||||
DDS_ERROR ("getaddrinfo returned unkown error %d\n", gai_err);
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
*hentp = hent;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
#else
|
||||
dds_return_t
|
||||
ddsrt_gethostbyname(const char *name, int af, ddsrt_hostent_t **hentp)
|
||||
{
|
||||
struct hostent hest, *he;
|
||||
char buf[256];
|
||||
int err;
|
||||
he = gethostbyname_r (name, &hest, buf, sizeof (buf), &err);
|
||||
if (he == NULL) {
|
||||
return DDS_RETCODE_HOST_NOT_FOUND;
|
||||
} else {
|
||||
size_t size = sizeof(**hentp) + (1 * sizeof((*hentp)->addrs[0]));
|
||||
*hentp = ddsrt_calloc_s(1, size);
|
||||
(*hentp)->naddrs = 1;
|
||||
memcpy(&(*hentp)->addrs[0], he->h_addr, he->h_length);
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
}
|
||||
#endif /* DDSRT_HAVE_GETADDRINFO */
|
||||
#endif /* DDSRT_HAVE_DNS */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
#include "dds/ddsrt/time.h"
|
||||
#include "dds/ddsrt/static_assert.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
|
@ -27,12 +28,8 @@ 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.
|
||||
*
|
||||
|
@ -52,19 +49,21 @@ ddsrt_duration_to_timeval_ceil(dds_duration_t reltime, struct timeval *tv)
|
|||
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);
|
||||
DDSRT_STATIC_ASSERT (CHAR_BIT * sizeof (ddsrt_tv_sec_t) == 32 || CHAR_BIT * sizeof (ddsrt_tv_sec_t) == 64);
|
||||
if (CHAR_BIT * sizeof (ddsrt_tv_sec_t) == 32)
|
||||
max_nsecs = INT32_MAX * DDS_NSECS_IN_SEC;
|
||||
} else {
|
||||
max_nsecs = DDSRT_TIME_T_MAX / DDS_NSECS_IN_SEC;
|
||||
}
|
||||
else
|
||||
max_nsecs = INT64_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);
|
||||
tv->tv_usec = (int)((reltime % DDS_NSECS_IN_SEC) / DDS_NSECS_IN_USEC);
|
||||
} else {
|
||||
tv->tv_sec = DDSRT_TIME_T_MAX;
|
||||
if (CHAR_BIT * sizeof (ddsrt_tv_sec_t) == 32)
|
||||
tv->tv_sec = (ddsrt_tv_sec_t) INT32_MAX;
|
||||
else
|
||||
tv->tv_sec = (ddsrt_tv_sec_t) INT64_MAX;
|
||||
tv->tv_usec = 999999;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -10,22 +10,46 @@
|
|||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
#if !LWIP_SOCKET
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
#if !defined(HOST_NAME_MAX)
|
||||
# if LWIP_SOCKET
|
||||
# define HOST_NAME_MAX DNS_MAX_NAME_LENGTH
|
||||
# elif defined(_POSIX_HOST_NAME_MAX)
|
||||
# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "dds/ddsrt/sockets.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
dds_retcode_t
|
||||
#if LWIP_SOCKET
|
||||
dds_return_t
|
||||
ddsrt_gethostname(
|
||||
char *name,
|
||||
size_t len)
|
||||
{
|
||||
if (ddsrt_strlcpy(name, "localhost", len) >= len) {
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
}
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
#else
|
||||
#ifndef HOST_NAME_MAX
|
||||
#define HOST_NAME_MAX 256
|
||||
#endif
|
||||
|
||||
dds_return_t
|
||||
ddsrt_gethostname(
|
||||
char *name,
|
||||
size_t len)
|
||||
|
@ -59,3 +83,4 @@ ddsrt_gethostname(
|
|||
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,10 +10,14 @@
|
|||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/sockets_priv.h"
|
||||
|
||||
#if !LWIP_SOCKET
|
||||
#if defined(__VXWORKS__)
|
||||
#include <vxWorks.h>
|
||||
#include <sockLib.h>
|
||||
|
@ -21,6 +25,7 @@
|
|||
#else
|
||||
#include <sys/fcntl.h>
|
||||
#endif /* __VXWORKS__ */
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef __sun
|
||||
|
@ -30,12 +35,9 @@
|
|||
#ifdef __APPLE__
|
||||
#include <sys/sockio.h>
|
||||
#endif /* __APPLE__ */
|
||||
#endif /* LWIP_SOCKET */
|
||||
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/misc.h"
|
||||
#include "dds/ddsrt/sockets_priv.h"
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol)
|
||||
{
|
||||
ddsrt_socket_t sock;
|
||||
|
@ -66,7 +68,7 @@ ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_close(
|
||||
ddsrt_socket_t sock)
|
||||
{
|
||||
|
@ -85,7 +87,7 @@ ddsrt_close(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_bind(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
|
@ -110,7 +112,7 @@ ddsrt_bind(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_listen(
|
||||
ddsrt_socket_t sock,
|
||||
int backlog)
|
||||
|
@ -133,7 +135,7 @@ ddsrt_listen(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_connect(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
|
@ -175,7 +177,7 @@ ddsrt_connect(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_accept(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
|
@ -222,7 +224,7 @@ ddsrt_accept(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getsockname(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
|
@ -246,7 +248,7 @@ ddsrt_getsockname(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
|
@ -254,6 +256,15 @@ ddsrt_getsockopt(
|
|||
void *optval,
|
||||
socklen_t *optlen)
|
||||
{
|
||||
#if LWIP_SOCKET
|
||||
if (optname == SO_SNDBUF || optname == SO_RCVBUF)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
# if !SO_REUSE
|
||||
if (optname == SO_REUSEADDR)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
# endif /* SO_REUSE */
|
||||
#endif /* LWIP_SOCKET */
|
||||
|
||||
if (getsockopt(sock, level, optname, optval, optlen) == 0)
|
||||
return DDS_RETCODE_OK;
|
||||
|
||||
|
@ -271,7 +282,7 @@ ddsrt_getsockopt(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_setsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
|
@ -279,6 +290,15 @@ ddsrt_setsockopt(
|
|||
const void *optval,
|
||||
socklen_t optlen)
|
||||
{
|
||||
#if LWIP_SOCKET
|
||||
if (optname == SO_SNDBUF || optname == SO_RCVBUF)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
# if !SO_REUSE
|
||||
if (optname == SO_REUSEADDR)
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
# endif /* SO_REUSE */
|
||||
#endif /* LWIP_SOCKET */
|
||||
|
||||
switch (optname) {
|
||||
case SO_SNDBUF:
|
||||
case SO_RCVBUF:
|
||||
|
@ -319,7 +339,7 @@ err_setsockopt:
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_setsocknonblocking(
|
||||
ddsrt_socket_t sock,
|
||||
bool nonblock)
|
||||
|
@ -357,7 +377,7 @@ err_fcntl:
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
static inline dds_retcode_t
|
||||
static inline dds_return_t
|
||||
recv_error_to_retcode(int errnum)
|
||||
{
|
||||
switch (errnum) {
|
||||
|
@ -386,7 +406,7 @@ recv_error_to_retcode(int errnum)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_recv(
|
||||
ddsrt_socket_t sock,
|
||||
void *buf,
|
||||
|
@ -405,7 +425,25 @@ ddsrt_recv(
|
|||
return recv_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
#if LWIP_SOCKET && !defined(recvmsg)
|
||||
static ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
|
||||
{
|
||||
assert(msg->msg_iovlen == 1);
|
||||
assert(msg->msg_controllen == 0);
|
||||
|
||||
msg->msg_flags = 0;
|
||||
|
||||
return recvfrom(
|
||||
sockfd,
|
||||
msg->msg_iov[0].iov_base,
|
||||
msg->msg_iov[0].iov_len,
|
||||
flags,
|
||||
msg->msg_name,
|
||||
&msg->msg_namelen);
|
||||
}
|
||||
#endif /* LWIP_SOCKET */
|
||||
|
||||
dds_return_t
|
||||
ddsrt_recvmsg(
|
||||
ddsrt_socket_t sock,
|
||||
ddsrt_msghdr_t *msg,
|
||||
|
@ -423,11 +461,12 @@ ddsrt_recvmsg(
|
|||
return recv_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
static inline dds_retcode_t
|
||||
static inline dds_return_t
|
||||
send_error_to_retcode(int errnum)
|
||||
{
|
||||
switch (errnum) {
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
return DDS_RETCODE_NOT_ALLOWED;
|
||||
case EAGAIN:
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
|
@ -465,7 +504,7 @@ send_error_to_retcode(int errnum)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_send(
|
||||
ddsrt_socket_t sock,
|
||||
const void *buf,
|
||||
|
@ -484,7 +523,7 @@ ddsrt_send(
|
|||
return send_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_sendmsg(
|
||||
ddsrt_socket_t sock,
|
||||
const ddsrt_msghdr_t *msg,
|
||||
|
@ -502,7 +541,7 @@ ddsrt_sendmsg(
|
|||
return send_error_to_retcode(errno);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_select(
|
||||
int32_t nfds,
|
||||
fd_set *readfds,
|
||||
|
|
|
@ -52,11 +52,11 @@ ddsrt_winsock_fini(void)
|
|||
WSACleanup();
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol)
|
||||
{
|
||||
int err;
|
||||
dds_retcode_t ret = DDS_RETCODE_OK;
|
||||
dds_return_t ret = DDS_RETCODE_OK;
|
||||
ddsrt_socket_t sock = DDSRT_INVALID_SOCKET;
|
||||
|
||||
assert(sockptr != NULL);
|
||||
|
@ -93,7 +93,7 @@ ddsrt_socket(ddsrt_socket_t *sockptr, int domain, int type, int protocol)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_close(ddsrt_socket_t sock)
|
||||
{
|
||||
int err;
|
||||
|
@ -120,7 +120,7 @@ ddsrt_close(ddsrt_socket_t sock)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_accept(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
|
@ -162,7 +162,7 @@ ddsrt_accept(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_bind(ddsrt_socket_t sock, const struct sockaddr *addr, socklen_t addrlen)
|
||||
{
|
||||
int err;
|
||||
|
@ -195,7 +195,7 @@ ddsrt_bind(ddsrt_socket_t sock, const struct sockaddr *addr, socklen_t addrlen)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_listen(
|
||||
ddsrt_socket_t sock,
|
||||
int backlog)
|
||||
|
@ -227,7 +227,7 @@ ddsrt_listen(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_connect(
|
||||
ddsrt_socket_t sock,
|
||||
const struct sockaddr *addr,
|
||||
|
@ -275,7 +275,7 @@ ddsrt_connect(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getsockname(
|
||||
ddsrt_socket_t sock,
|
||||
struct sockaddr *addr,
|
||||
|
@ -309,7 +309,7 @@ ddsrt_getsockname(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_getsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
|
@ -358,7 +358,7 @@ ddsrt_getsockopt(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_setsockopt(
|
||||
ddsrt_socket_t sock,
|
||||
int32_t level,
|
||||
|
@ -404,7 +404,7 @@ ddsrt_setsockopt(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_setsocknonblocking(
|
||||
ddsrt_socket_t sock,
|
||||
bool nonblock)
|
||||
|
@ -435,7 +435,7 @@ ddsrt_setsocknonblocking(
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
static dds_retcode_t recv_error_to_retcode(int errnum)
|
||||
static dds_return_t recv_error_to_retcode(int errnum)
|
||||
{
|
||||
assert(errnum != WSANOTINITIALISED);
|
||||
switch (errnum) {
|
||||
|
@ -470,7 +470,7 @@ static dds_retcode_t recv_error_to_retcode(int errnum)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_recv(
|
||||
ddsrt_socket_t sock,
|
||||
void *buf,
|
||||
|
@ -490,7 +490,7 @@ ddsrt_recv(
|
|||
return recv_error_to_retcode(WSAGetLastError());
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_recvmsg(
|
||||
ddsrt_socket_t sock,
|
||||
ddsrt_msghdr_t *msg,
|
||||
|
@ -531,7 +531,7 @@ ddsrt_recvmsg(
|
|||
return recv_error_to_retcode(err);
|
||||
}
|
||||
|
||||
static dds_retcode_t
|
||||
static dds_return_t
|
||||
send_error_to_retcode(int errnum)
|
||||
{
|
||||
assert(errnum != WSANOTINITIALISED);
|
||||
|
@ -577,7 +577,7 @@ send_error_to_retcode(int errnum)
|
|||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_send(
|
||||
ddsrt_socket_t sock,
|
||||
const void *buf,
|
||||
|
@ -608,7 +608,7 @@ struct iovec_matches_WSABUF {
|
|||
char len_size_matches[sizeof(((ddsrt_iovec_t *)8)->iov_len) == sizeof(((WSABUF *)8)->len) ? 1 : -1];
|
||||
};
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_sendmsg(
|
||||
ddsrt_socket_t sock,
|
||||
const ddsrt_msghdr_t *msg,
|
||||
|
@ -639,7 +639,7 @@ ddsrt_sendmsg(
|
|||
return send_error_to_retcode(WSAGetLastError());
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_select(
|
||||
int32_t nfds,
|
||||
fd_set *readfds,
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
#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"
|
||||
|
@ -65,19 +62,6 @@ ddsrt_strncasecmp(
|
|||
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)
|
||||
{
|
||||
|
@ -178,4 +162,3 @@ ddsrt_strdup(
|
|||
|
||||
return ddsrt_memdup(str, strlen(str) + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_strerror_r(int errnum, char *buf, size_t buflen)
|
||||
{
|
||||
assert(buf != NULL);
|
||||
|
|
34
src/ddsrt/src/string/solaris2.6/strerror.c
Normal file
34
src/ddsrt/src/string/solaris2.6/strerror.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 <stdio.h>
|
||||
|
||||
#include "dds/ddsrt/string.h"
|
||||
|
||||
dds_return_t
|
||||
ddsrt_strerror_r(int errnum, char *buf, size_t buflen)
|
||||
{
|
||||
assert(buf != NULL);
|
||||
assert(buflen > 0);
|
||||
if (snprintf (buf, buflen, "errno=%d", errnum) >= buflen)
|
||||
return DDS_RETCODE_NOT_ENOUGH_SPACE;
|
||||
else
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
|
@ -96,12 +96,12 @@ os_lcNumericReplace(char *str) {
|
|||
}
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_strtod(const char *nptr, char **endptr, double *dblptr)
|
||||
{
|
||||
double dbl;
|
||||
int orig_errno;
|
||||
dds_retcode_t ret = DDS_RETCODE_OK;
|
||||
dds_return_t ret = DDS_RETCODE_OK;
|
||||
|
||||
assert(nptr != NULL);
|
||||
assert(dblptr != NULL);
|
||||
|
@ -161,7 +161,7 @@ ddsrt_strtod(const char *nptr, char **endptr, double *dblptr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_strtof(const char *nptr, char **endptr, float *fltptr)
|
||||
{
|
||||
/* Just use os_strtod(). */
|
||||
|
@ -169,7 +169,7 @@ ddsrt_strtof(const char *nptr, char **endptr, float *fltptr)
|
|||
point number is definitely not a double-precision floating point
|
||||
number. */
|
||||
double dbl = 0.0;
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
|
||||
assert(nptr != NULL);
|
||||
assert(fltptr != NULL);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "dds/ddsrt/strtol.h"
|
||||
|
||||
int ddsrt_todigit(const int chr)
|
||||
static int ddsrt_todigit(const int chr)
|
||||
{
|
||||
if (chr >= '0' && chr <= '9') {
|
||||
return chr - '0';
|
||||
|
@ -29,7 +29,7 @@ int ddsrt_todigit(const int chr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static dds_retcode_t
|
||||
static dds_return_t
|
||||
ullfstr(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
|
@ -37,7 +37,7 @@ ullfstr(
|
|||
unsigned long long *ullng,
|
||||
unsigned long long max)
|
||||
{
|
||||
dds_retcode_t rc = DDS_RETCODE_OK;
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
int num;
|
||||
size_t cnt = 0;
|
||||
unsigned long long tot = 0;
|
||||
|
@ -86,14 +86,14 @@ ullfstr(
|
|||
return rc;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_strtoll(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
int32_t base,
|
||||
long long *llng)
|
||||
{
|
||||
dds_retcode_t rc = DDS_RETCODE_OK;
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
size_t cnt = 0;
|
||||
long long tot = 1;
|
||||
unsigned long long ullng = 0, max = INT64_MAX;
|
||||
|
@ -122,14 +122,14 @@ ddsrt_strtoll(
|
|||
return rc;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_strtoull(
|
||||
const char *str,
|
||||
char **endptr,
|
||||
int32_t base,
|
||||
unsigned long long *ullng)
|
||||
{
|
||||
dds_retcode_t rc = DDS_RETCODE_OK;
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
size_t cnt = 0;
|
||||
unsigned long long tot = 1;
|
||||
unsigned long long max = UINT64_MAX;
|
||||
|
@ -157,7 +157,7 @@ ddsrt_strtoull(
|
|||
return rc;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_atoll(
|
||||
const char *str,
|
||||
long long *llng)
|
||||
|
@ -165,7 +165,7 @@ ddsrt_atoll(
|
|||
return ddsrt_strtoll(str, NULL, 10, llng);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_atoull(
|
||||
const char *str,
|
||||
unsigned long long *ullng)
|
||||
|
|
467
src/ddsrt/src/sync/freertos/sync.c
Normal file
467
src/ddsrt/src/sync/freertos/sync.c
Normal file
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
* 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 <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/log.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/timeconv.h"
|
||||
|
||||
void ddsrt_mutex_init(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
SemaphoreHandle_t sem;
|
||||
|
||||
assert(mutex != NULL);
|
||||
|
||||
if ((sem = xSemaphoreCreateMutex()) == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
(void)memset(mutex, 0, sizeof(*mutex));
|
||||
mutex->sem = sem;
|
||||
}
|
||||
|
||||
void ddsrt_mutex_destroy(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
|
||||
vSemaphoreDelete(mutex->sem);
|
||||
(void)memset(mutex, 0, sizeof(*mutex));
|
||||
}
|
||||
|
||||
static bool
|
||||
mutex_lock(ddsrt_mutex_t *mutex, int blk)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
|
||||
if (xSemaphoreTake(mutex->sem, (blk == 1 ? portMAX_DELAY : 0)) != pdPASS) {
|
||||
/* xSemaphoreTake will only return pdFAIL on timeout. The wait will be
|
||||
indefinite if INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h
|
||||
and portMAX_DELAY was passed. */
|
||||
assert(blk == 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ddsrt_mutex_lock(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex_lock(mutex, 1)) {
|
||||
DDS_FATAL("Failed to lock 0x%p", mutex);
|
||||
}
|
||||
}
|
||||
|
||||
bool ddsrt_mutex_trylock(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
return mutex_lock(mutex, 0);
|
||||
}
|
||||
|
||||
void ddsrt_mutex_unlock(ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(mutex != NULL);
|
||||
|
||||
if (xSemaphoreGive(mutex->sem) != pdPASS) {
|
||||
DDS_FATAL("Failed to unlock 0x%p", mutex->sem);
|
||||
}
|
||||
}
|
||||
|
||||
static dds_return_t
|
||||
cond_timedwait(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_duration_t reltime)
|
||||
{
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
dds_time_t abstime;
|
||||
TaskHandle_t task;
|
||||
TickType_t ticks = 0;
|
||||
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
abstime = ddsrt_time_add_duration(dds_time(), reltime);
|
||||
ticks = ddsrt_duration_to_ticks_ceil(reltime);
|
||||
|
||||
xSemaphoreTake(cond->sem, portMAX_DELAY);
|
||||
ddsrt_mutex_unlock(mutex);
|
||||
|
||||
task = xTaskGetCurrentTaskHandle();
|
||||
/* Register current task with condition. */
|
||||
ddsrt_tasklist_push(&cond->tasks, task);
|
||||
/* Discard pending notifications. */
|
||||
ulTaskNotifyTake(1, 0);
|
||||
|
||||
xSemaphoreGive(cond->sem);
|
||||
/* Wait to be notified. */
|
||||
switch (ulTaskNotifyTake(1, ticks)) {
|
||||
case 0:
|
||||
xSemaphoreTake(cond->sem, ticks);
|
||||
ddsrt_tasklist_pop(&cond->tasks, task);
|
||||
xSemaphoreGive(cond->sem);
|
||||
break;
|
||||
default:
|
||||
/* Task already removed from condition. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Timeout must only be returned if the time has actually passed. */
|
||||
if (dds_time() >= abstime) {
|
||||
rc = DDS_RETCODE_TIMEOUT;
|
||||
}
|
||||
|
||||
ddsrt_mutex_lock(mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ddsrt_cond_init(ddsrt_cond_t *cond)
|
||||
{
|
||||
SemaphoreHandle_t sem;
|
||||
ddsrt_tasklist_t tasks;
|
||||
|
||||
assert(cond != NULL);
|
||||
|
||||
if (ddsrt_tasklist_init(&tasks) == -1) {
|
||||
abort();
|
||||
}
|
||||
if ((sem = xSemaphoreCreateMutex()) == NULL) {
|
||||
ddsrt_tasklist_fini(&tasks);
|
||||
abort();
|
||||
}
|
||||
|
||||
(void)memset(cond, 0, sizeof(*cond));
|
||||
cond->sem = sem;
|
||||
cond->tasks = tasks;
|
||||
}
|
||||
|
||||
void ddsrt_cond_destroy(ddsrt_cond_t *cond)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
|
||||
vSemaphoreDelete(cond->sem);
|
||||
ddsrt_tasklist_fini(&cond->tasks);
|
||||
(void)memset(cond, 0, sizeof(*cond));
|
||||
}
|
||||
|
||||
void ddsrt_cond_wait(ddsrt_cond_t *cond, ddsrt_mutex_t *mutex)
|
||||
{
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
(void)cond_timedwait(cond, mutex, DDS_INFINITY);
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_cond_waitfor(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_duration_t reltime)
|
||||
{
|
||||
dds_return_t rc;
|
||||
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
switch ((rc = cond_timedwait(cond, mutex, reltime))) {
|
||||
case DDS_RETCODE_OUT_OF_RESOURCES:
|
||||
abort();
|
||||
case DDS_RETCODE_TIMEOUT:
|
||||
return false;
|
||||
default:
|
||||
assert(rc == DDS_RETCODE_OK);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ddsrt_cond_waituntil(
|
||||
ddsrt_cond_t *cond,
|
||||
ddsrt_mutex_t *mutex,
|
||||
dds_time_t abstime)
|
||||
{
|
||||
dds_return_t rc;
|
||||
dds_time_t time;
|
||||
dds_duration_t reltime;
|
||||
|
||||
assert(cond != NULL);
|
||||
assert(mutex != NULL);
|
||||
|
||||
time = dds_time();
|
||||
reltime = (abstime > time ? abstime - time : 0);
|
||||
|
||||
switch ((rc = cond_timedwait(cond, mutex, reltime))) {
|
||||
case DDS_RETCODE_OUT_OF_RESOURCES:
|
||||
abort();
|
||||
case DDS_RETCODE_TIMEOUT:
|
||||
return false;
|
||||
default:
|
||||
assert(rc == DDS_RETCODE_OK);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ddsrt_cond_signal(ddsrt_cond_t *cond)
|
||||
{
|
||||
TaskHandle_t task;
|
||||
|
||||
assert(cond != NULL);
|
||||
|
||||
xSemaphoreTake(cond->sem, portMAX_DELAY);
|
||||
if ((task = ddsrt_tasklist_pop(&cond->tasks, NULL)) != NULL) {
|
||||
xTaskNotifyGive(task);
|
||||
}
|
||||
xSemaphoreGive(cond->sem);
|
||||
}
|
||||
|
||||
void ddsrt_cond_broadcast(ddsrt_cond_t *cond)
|
||||
{
|
||||
TaskHandle_t task;
|
||||
|
||||
assert(cond != NULL);
|
||||
|
||||
xSemaphoreTake(cond->sem, portMAX_DELAY);
|
||||
while ((task = ddsrt_tasklist_pop(&cond->tasks, NULL)) != NULL) {
|
||||
xTaskNotifyGive(task);
|
||||
}
|
||||
xSemaphoreGive(cond->sem);
|
||||
}
|
||||
|
||||
#define WRITE_LOCKED (-1)
|
||||
#define UNLOCKED (0)
|
||||
#define READ_LOCKED (1)
|
||||
|
||||
void ddsrt_rwlock_init(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
SemaphoreHandle_t sem;
|
||||
ddsrt_tasklist_t tasks;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
|
||||
if (ddsrt_tasklist_init(&tasks) == -1) {
|
||||
abort();
|
||||
}
|
||||
if ((sem = xSemaphoreCreateMutex()) == NULL) {
|
||||
ddsrt_tasklist_fini(&tasks);
|
||||
abort();
|
||||
}
|
||||
|
||||
memset(rwlock, 0, sizeof(*rwlock));
|
||||
rwlock->sem = sem;
|
||||
rwlock->tasks = tasks;
|
||||
rwlock->state = UNLOCKED;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_destroy(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
assert(rwlock != NULL);
|
||||
|
||||
vSemaphoreDelete(rwlock->sem);
|
||||
ddsrt_tasklist_fini(&rwlock->tasks);
|
||||
memset(rwlock, 0, sizeof(*rwlock));
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_read(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
|
||||
assert(rwlock != NULL);
|
||||
|
||||
xSemaphoreTake(rwlock->sem, portMAX_DELAY);
|
||||
rwlock->rdcnt++;
|
||||
if (rwlock->wrcnt != 0) {
|
||||
ddsrt_tasklist_push(&rwlock->tasks, task);
|
||||
/* Discard pending notifications. */
|
||||
ulTaskNotifyTake(1, 0);
|
||||
xSemaphoreGive(rwlock->sem);
|
||||
/* Wait to be notified. */
|
||||
ulTaskNotifyTake(1, portMAX_DELAY);
|
||||
xSemaphoreTake(rwlock->sem, portMAX_DELAY);
|
||||
ddsrt_tasklist_pop(&rwlock->tasks, task);
|
||||
}
|
||||
assert(rwlock->state == UNLOCKED ||
|
||||
rwlock->state == READ_LOCKED);
|
||||
rwlock->cnt++;
|
||||
rwlock->state = READ_LOCKED;
|
||||
/* Notify next task, if any. */
|
||||
if ((task = ddsrt_tasklist_peek(&rwlock->tasks, NULL)) != NULL) {
|
||||
xTaskNotifyGive(task);
|
||||
}
|
||||
xSemaphoreGive(rwlock->sem);
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_write(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
|
||||
assert(rwlock != NULL);
|
||||
|
||||
xSemaphoreTake(rwlock->sem, portMAX_DELAY);
|
||||
rwlock->wrcnt++;
|
||||
if (rwlock->rdcnt != 0 || rwlock->wrcnt != 1) {
|
||||
ddsrt_tasklist_push(&rwlock->tasks, task);
|
||||
do {
|
||||
/* Discard pending notifications. */
|
||||
ulTaskNotifyTake(1, 0);
|
||||
xSemaphoreGive(rwlock->sem);
|
||||
/* Wait to be notified. */
|
||||
ulTaskNotifyTake(1, portMAX_DELAY);
|
||||
xSemaphoreTake(rwlock->sem, portMAX_DELAY);
|
||||
} while (rwlock->state != UNLOCKED);
|
||||
ddsrt_tasklist_pop(&rwlock->tasks, task);
|
||||
}
|
||||
assert(rwlock->cnt == 0);
|
||||
assert(rwlock->state == UNLOCKED);
|
||||
rwlock->cnt++;
|
||||
rwlock->state = WRITE_LOCKED;
|
||||
xSemaphoreGive(rwlock->sem);
|
||||
}
|
||||
|
||||
bool ddsrt_rwlock_tryread(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
bool locked = false;
|
||||
TaskHandle_t task;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
|
||||
xSemaphoreTake(rwlock->sem, portMAX_DELAY);
|
||||
if (rwlock->wrcnt == 0) {
|
||||
locked = true;
|
||||
rwlock->cnt++;
|
||||
rwlock->rdcnt++;
|
||||
rwlock->state = READ_LOCKED;
|
||||
/* Notify next task, if any. */
|
||||
if ((task = ddsrt_tasklist_peek(&rwlock->tasks, NULL)) != NULL) {
|
||||
xTaskNotifyGive(task);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(rwlock->sem);
|
||||
|
||||
return locked;
|
||||
}
|
||||
|
||||
bool ddsrt_rwlock_trywrite(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
bool locked = false;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
|
||||
xSemaphoreTake(rwlock->sem, 0);
|
||||
if (rwlock->rdcnt == 0 && rwlock->wrcnt == 0) {
|
||||
locked = true;
|
||||
rwlock->cnt++;
|
||||
rwlock->wrcnt++;
|
||||
rwlock->state = WRITE_LOCKED;
|
||||
}
|
||||
xSemaphoreGive(rwlock->sem);
|
||||
|
||||
return locked;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_unlock(ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
TaskHandle_t task;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
|
||||
xSemaphoreTake(rwlock->sem, portMAX_DELAY);
|
||||
assert(rwlock->cnt != 0);
|
||||
rwlock->cnt--;
|
||||
if (rwlock->state == READ_LOCKED) {
|
||||
assert(rwlock->rdcnt != 0);
|
||||
rwlock->rdcnt--;
|
||||
if (rwlock->rdcnt == 0) {
|
||||
rwlock->state = UNLOCKED;
|
||||
}
|
||||
} else {
|
||||
assert(rwlock->state == WRITE_LOCKED);
|
||||
assert(rwlock->wrcnt != 0);
|
||||
assert(rwlock->cnt == 0);
|
||||
rwlock->wrcnt--;
|
||||
rwlock->state = UNLOCKED;
|
||||
}
|
||||
/* Notify next task, if any. */
|
||||
if ((rwlock->state == UNLOCKED) &&
|
||||
(task = ddsrt_tasklist_peek(&rwlock->tasks, NULL)) != NULL)
|
||||
{
|
||||
assert(rwlock->rdcnt != 0 ||
|
||||
rwlock->wrcnt != 0);
|
||||
xTaskNotifyGive(task);
|
||||
}
|
||||
xSemaphoreGive(rwlock->sem);
|
||||
}
|
||||
|
||||
#define ONCE_NOT_STARTED (1<<0)
|
||||
#define ONCE_IN_PROGRESS (1<<1)
|
||||
#define ONCE_FINISHED (1<<2)
|
||||
|
||||
/* Wait one millisecond (tick) between polls. */
|
||||
static const TickType_t once_delay = (configTICK_RATE_HZ / 1000);
|
||||
|
||||
void
|
||||
ddsrt_once(
|
||||
ddsrt_once_t *control,
|
||||
ddsrt_once_fn init_fn)
|
||||
{
|
||||
int ret, brk = 0;
|
||||
uint32_t stat;
|
||||
|
||||
while (brk == 0) {
|
||||
stat = ddsrt_atomic_ld32(control);
|
||||
/* Verify once control was initialized properly. */
|
||||
assert(stat == ONCE_NOT_STARTED ||
|
||||
stat == ONCE_IN_PROGRESS ||
|
||||
stat == ONCE_FINISHED);
|
||||
|
||||
if ((stat & ONCE_FINISHED) != 0) {
|
||||
/* The initialization function has been executed. No reason to block
|
||||
execution of this thread. Continue. */
|
||||
brk = 1;
|
||||
} else if ((stat & ONCE_IN_PROGRESS) != 0) {
|
||||
/* Another thread is executing the initialization function. Wait around
|
||||
for it to be finished. The polling loop is required because FreeRTOS
|
||||
does not offer futexes. */
|
||||
vTaskDelay(once_delay);
|
||||
/* Repeat. */
|
||||
} else {
|
||||
/* No thread was executing the initialization function (one might be
|
||||
executing it now) at the time of the load. If the atomic compare and
|
||||
swap operation is successful, this thread will run the initialization
|
||||
function. */
|
||||
if (ddsrt_atomic_cas32(
|
||||
control, ONCE_NOT_STARTED, ONCE_IN_PROGRESS) != 0)
|
||||
{
|
||||
/* Function must never block or yield, see reference manual. */
|
||||
init_fn();
|
||||
|
||||
ret = (0 == ddsrt_atomic_cas32(
|
||||
control, ONCE_IN_PROGRESS, ONCE_FINISHED));
|
||||
assert(ret == 0); (void)ret;
|
||||
|
||||
brk = 1;
|
||||
} else {
|
||||
/* Another thread updated the state first. Repeat. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
396
src/ddsrt/src/sync/freertos/tasklist.c
Normal file
396
src/ddsrt/src/sync/freertos/tasklist.c
Normal file
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
|
||||
/* Task list is a buffer used to keep track of blocked tasks. The buffer is
|
||||
cyclic to avoid memory (re)allocation as much as possible. To avoid memory
|
||||
relocation, the window is allowed to be sparse too.
|
||||
|
||||
Active buckets must always reside in the window denoted by the first active
|
||||
bucket and the last active bucket.
|
||||
|
||||
A buffer with 10 buckets will be neatly packed at first.
|
||||
|
||||
X : Used bucket in window.
|
||||
o : Empty (invalidated) bucket.
|
||||
|
||||
-----------------------
|
||||
| X X X X X o o o o o | length: 10, count: 5
|
||||
--^-------^------------
|
||||
1st nth
|
||||
|
||||
As soon as the first task is unblocked.
|
||||
|
||||
-----------------------
|
||||
| o X X X X o o o o o | length: 10, count: 4
|
||||
----^-----^------------
|
||||
1st nth
|
||||
|
||||
After a while the window will wrap around.
|
||||
|
||||
-----------------------
|
||||
| X X X o o o o o X X | length: 10, count: 5
|
||||
------^-----------^----
|
||||
nth 1st
|
||||
|
||||
When a task is popped, e.g. a task was not notified in due time.
|
||||
|
||||
-----------------------
|
||||
| o X X o X X o o o o | length: 10, count: 4
|
||||
----^-------^----------
|
||||
1st nth
|
||||
*/
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
static void tasklist_assert(ddsrt_tasklist_t *list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(list != NULL);
|
||||
|
||||
if (list->cnt == 0) {
|
||||
assert(list->off == 0);
|
||||
assert(list->end == 0);
|
||||
assert(list->len == DDSRT_TASKLIST_INITIAL);
|
||||
for (i = 0; i < list->len; i++) {
|
||||
assert(list->tasks[i] == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: add more checks */
|
||||
}
|
||||
#else
|
||||
#define tasklist_assert(...)
|
||||
#endif /* NDEBUG */
|
||||
|
||||
int ddsrt_tasklist_init(ddsrt_tasklist_t *list)
|
||||
{
|
||||
TaskHandle_t *p;
|
||||
|
||||
assert(list != NULL);
|
||||
|
||||
p = ddsrt_malloc(DDSRT_TASKLIST_INITIAL * sizeof(*list->tasks));
|
||||
if (p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(list, 0, sizeof(*list));
|
||||
memset(p, 0, DDSRT_TASKLIST_INITIAL * sizeof(*list->tasks));
|
||||
list->tasks = p;
|
||||
list->len = DDSRT_TASKLIST_INITIAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ddsrt_tasklist_fini(ddsrt_tasklist_t *list)
|
||||
{
|
||||
ddsrt_free(list->tasks);
|
||||
memset(list, 0, sizeof(*list));
|
||||
}
|
||||
|
||||
void ddsrt_tasklist_ltrim(ddsrt_tasklist_t *list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(list != NULL);
|
||||
assert(list->cnt != 0);
|
||||
|
||||
i = list->off;
|
||||
for (; i < list->len - 1 && list->tasks[i] == NULL; i++) { }
|
||||
/* Take into account wrap around. */
|
||||
if (list->tasks[i] == NULL) {
|
||||
assert(i == list->len - 1);
|
||||
assert(list->off > list->end);
|
||||
i = 0;
|
||||
/* Trim invalidated buckets from head. */
|
||||
for (; i < list->len - 1 && list->tasks[i] == NULL; i++) { }
|
||||
}
|
||||
list->off = i;
|
||||
}
|
||||
|
||||
void ddsrt_tasklist_rtrim(ddsrt_tasklist_t *list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(list != NULL);
|
||||
assert(list->cnt != 0);
|
||||
|
||||
i = list->end;
|
||||
for (; i > 0 && list->tasks[i] == NULL; i--) { }
|
||||
/* Take into account wrap around. */
|
||||
if (list->tasks[i] == NULL) {
|
||||
assert(i == 0);
|
||||
assert(list->off > list->end);
|
||||
i = list->len - 1;
|
||||
/* Trim invalidated buckets from tail. */
|
||||
for (; i > 0 && list->tasks[i] == NULL; i--) { }
|
||||
}
|
||||
list->end = i;
|
||||
}
|
||||
|
||||
void ddsrt_tasklist_pack(ddsrt_tasklist_t *list)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
/* Pack operation is trickier on wrap around. */
|
||||
if (list->end < list->off) {
|
||||
/* Compress tail.
|
||||
*
|
||||
* ------------------------- -----------------------
|
||||
* | c . d . e | . a . b . | >> | c d e . . | . a . b |
|
||||
* ------------------------- -----------------------
|
||||
*/
|
||||
for (i = j = 0; i <= list->end; i++) {
|
||||
if (list->tasks[i] != NULL) {
|
||||
if (i != j) {
|
||||
list->tasks[j] = list->tasks[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
assert(j != 0);
|
||||
list->end = (j == 0 ? 0 : j - 1);
|
||||
|
||||
/* Compress head.
|
||||
*
|
||||
* ------------------------- -------------------------
|
||||
* | c d e . . | . a . b . | >> | c d e . . | . . . a b |
|
||||
* ------------------------- -------------------------
|
||||
*/
|
||||
for (i = j = list->len - 1; i >= list->off; i--) {
|
||||
if (list->tasks[i] != NULL) {
|
||||
if (i != j) {
|
||||
list->tasks[j] = list->tasks[i];
|
||||
}
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
assert(j != list->len - 1);
|
||||
list->off = (j == list->len - 1 ? list->len - 1 : j + 1);
|
||||
} else {
|
||||
/* Compress.
|
||||
*
|
||||
* ------------------------- --------------------------
|
||||
* | . . a . . | b . c d e | >> | a b c d e | . . . . . |
|
||||
* ------------------------- --------------------------
|
||||
*/
|
||||
for (i = list->off, j = 0; i <= list->end; i++) {
|
||||
if (list->tasks[i] != NULL) {
|
||||
if (i != j) {
|
||||
list->tasks[j] = list->tasks[i];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
assert(j != 0);
|
||||
list->off = 0;
|
||||
list->end = j - 1;
|
||||
assert(list->end == list->cnt - 1);
|
||||
}
|
||||
}
|
||||
|
||||
int ddsrt_tasklist_shrink(ddsrt_tasklist_t *list)
|
||||
{
|
||||
static const size_t x = DDSRT_TASKLIST_CHUNK;
|
||||
TaskHandle_t *p;
|
||||
size_t mv = 0, n;
|
||||
|
||||
assert(list != NULL);
|
||||
|
||||
/* Shrink by one chunk too, but only if the difference is at least two
|
||||
chunks to avoid memory (re)allocation if a task is pushed and popped
|
||||
just over the boundary. */
|
||||
if (list->cnt > (list->len - (x * 2)) || (list->len - x) < DDSRT_TASKLIST_INITIAL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* List can be sparse. Pack to ensure list can be compacted. */
|
||||
ddsrt_tasklist_pack(list);
|
||||
|
||||
/* Pack operation moved head to end of buffer on wrap around. Move head back
|
||||
to not discard it on reallocation. */
|
||||
if (list->off != 0) {
|
||||
assert(list->end < list->off);
|
||||
mv = (list->len - list->off) * sizeof(*p);
|
||||
memmove(list->tasks + (list->off - x), list->tasks + list->off, mv);
|
||||
list->off -= x;
|
||||
}
|
||||
|
||||
n = list->len - x;
|
||||
if ((p = ddsrt_realloc(list->tasks, n * sizeof(*p))) == NULL) {
|
||||
/* Move head back to end of buffer. */
|
||||
if (mv != 0) {
|
||||
memmove(list->tasks + (list->off + x), list->tasks + list->off, mv);
|
||||
list->off += x;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
list->tasks = p;
|
||||
list->len = n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ddsrt_tasklist_grow(ddsrt_tasklist_t *list)
|
||||
{
|
||||
static const size_t x = DDSRT_TASKLIST_CHUNK;
|
||||
TaskHandle_t *p;
|
||||
size_t n;
|
||||
|
||||
assert(list != NULL);
|
||||
/* Should not be called if room is available. */
|
||||
assert(list->cnt == list->len);
|
||||
|
||||
n = list->len + x;
|
||||
if ((p = ddsrt_realloc(list->tasks, n * sizeof(*p))) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Move head to end of newly allocated memory. */
|
||||
if (list->off != 0) {
|
||||
assert(list->end < list->off);
|
||||
memmove(p + (list->off + x), p + list->off, (list->len - list->off) * sizeof(*p));
|
||||
list->off += x;
|
||||
}
|
||||
|
||||
/* Zero newly allocated memory. */
|
||||
memset(p + (list->end + 1), 0, x * sizeof(*p));
|
||||
|
||||
list->tasks = p;
|
||||
list->len = n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t ddsrt_tasklist_find(ddsrt_tasklist_t *list, TaskHandle_t task)
|
||||
{
|
||||
size_t i, n;
|
||||
|
||||
assert(task != NULL);
|
||||
|
||||
/* No need to check if list is empty. */
|
||||
if (list->cnt != 0) {
|
||||
/* Task list is circular, so window does not have to be consecutive. */
|
||||
n = list->off <= list->end ? list->end : list->len - 1;
|
||||
for (i = list->off; i <= n; i++) {
|
||||
if (list->tasks[i] == task)
|
||||
return (ssize_t)i;
|
||||
}
|
||||
|
||||
if (list->off > list->end) {
|
||||
n = list->end;
|
||||
for (i = 0; i <= n; i++) {
|
||||
if (list->tasks[i] == task)
|
||||
return (ssize_t)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
TaskHandle_t ddsrt_tasklist_peek(ddsrt_tasklist_t *list, TaskHandle_t task)
|
||||
{
|
||||
tasklist_assert(list);
|
||||
|
||||
if (list->cnt == 0) {
|
||||
return NULL;
|
||||
} else if (task != NULL) {
|
||||
return ddsrt_tasklist_find(list, task) == -1 ? NULL : task;
|
||||
}
|
||||
|
||||
return list->tasks[list->off];
|
||||
}
|
||||
|
||||
TaskHandle_t ddsrt_tasklist_pop(ddsrt_tasklist_t *list, TaskHandle_t task)
|
||||
{
|
||||
ssize_t i;
|
||||
|
||||
tasklist_assert(list);
|
||||
|
||||
if (list->cnt == 0) {
|
||||
return NULL;
|
||||
} else if (task == NULL) {
|
||||
i = (ssize_t)list->off;
|
||||
} else if ((i = ddsrt_tasklist_find(list, task)) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
task = list->tasks[i];
|
||||
if (task != NULL) {
|
||||
/* Invalidate bucket. */
|
||||
list->tasks[i] = NULL;
|
||||
list->cnt--;
|
||||
|
||||
if (list->cnt == 0) {
|
||||
list->off = list->end = 0;
|
||||
} else if (i == (ssize_t)list->end) {
|
||||
/* Trim invalidated buckets from tail of window. */
|
||||
ddsrt_tasklist_rtrim(list);
|
||||
} else if (i == (ssize_t)list->off) {
|
||||
/* Trim invalidated buckets from head of window. */
|
||||
ddsrt_tasklist_ltrim(list);
|
||||
} else {
|
||||
/* Window is now sparse. */
|
||||
}
|
||||
|
||||
if (list->cnt <= (list->len - DDSRT_TASKLIST_CHUNK*2)) {
|
||||
/* Shrink operation failure can safely be ignored. */
|
||||
(void)ddsrt_tasklist_shrink(list);
|
||||
}
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
int ddsrt_tasklist_push(ddsrt_tasklist_t *list, TaskHandle_t task)
|
||||
{
|
||||
tasklist_assert(list);
|
||||
assert(task != NULL);
|
||||
|
||||
/* Ensure task is not listed. */
|
||||
if (ddsrt_tasklist_find(list, task) != -1) {
|
||||
return 0;
|
||||
}
|
||||
/* Grow number of buckets if none are available. */
|
||||
if (list->cnt == list->len) {
|
||||
if (ddsrt_tasklist_grow(list) == -1) {
|
||||
return -1;
|
||||
}
|
||||
list->end++;
|
||||
/* Wrap around if there is room at the head. */
|
||||
} else if (list->end == list->len - 1 && list->off != 0) {
|
||||
list->end = 0;
|
||||
} else {
|
||||
/* List can be sparse. */
|
||||
if (list->end == list->len - 1 || list->end + 1 == list->off) {
|
||||
ddsrt_tasklist_pack(list);
|
||||
}
|
||||
/* Room is guaranteed to be available at the tail. */
|
||||
list->end += (list->cnt > 0);
|
||||
}
|
||||
|
||||
list->tasks[list->end] = task;
|
||||
list->cnt++;
|
||||
|
||||
return 0;
|
||||
}
|
236
src/ddsrt/src/sync/solaris2.6/sync.c
Normal file
236
src/ddsrt/src/sync/solaris2.6/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_mutex_init(&rwlock->rwlock, NULL)) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_rwlock_destroy (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
if ((err = pthread_mutex_destroy (&rwlock->rwlock)) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_read (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_mutex_lock(&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
void ddsrt_rwlock_write (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_mutex_lock (&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
bool ddsrt_rwlock_tryread (ddsrt_rwlock_t *rwlock)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(rwlock != NULL);
|
||||
err = pthread_mutex_trylock(&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_mutex_trylock(&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_mutex_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);
|
||||
}
|
|
@ -88,13 +88,13 @@ static uint32_t ddsrt_thread_start_fn (void * arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static dds_retcode_t ddsrt_thread_pool_new_thread (ddsrt_thread_pool pool)
|
||||
static dds_return_t ddsrt_thread_pool_new_thread (ddsrt_thread_pool pool)
|
||||
{
|
||||
static unsigned char pools = 0; /* Pool counter - TODO make atomic */
|
||||
|
||||
char name [64];
|
||||
ddsrt_thread_t id;
|
||||
dds_retcode_t res;
|
||||
dds_return_t res;
|
||||
|
||||
(void) snprintf (name, sizeof (name), "OSPL-%u-%u", pools++, pool->m_count++);
|
||||
res = ddsrt_thread_create (&id, name, &pool->m_attr, &ddsrt_thread_start_fn, pool);
|
||||
|
@ -205,9 +205,9 @@ void ddsrt_thread_pool_free (ddsrt_thread_pool pool)
|
|||
ddsrt_free (pool);
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_thread_pool_submit (ddsrt_thread_pool pool, void (*fn) (void *arg), void * arg)
|
||||
dds_return_t ddsrt_thread_pool_submit (ddsrt_thread_pool pool, void (*fn) (void *arg), void * arg)
|
||||
{
|
||||
dds_retcode_t res = DDS_RETCODE_OK;
|
||||
dds_return_t res = DDS_RETCODE_OK;
|
||||
ddsi_work_queue_job_t job;
|
||||
|
||||
ddsrt_mutex_lock (&pool->m_mutex);
|
||||
|
|
545
src/ddsrt/src/threads/freertos/threads.c
Normal file
545
src/ddsrt/src/threads/freertos/threads.c
Normal file
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* 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 <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dds/ddsrt/heap.h"
|
||||
#include "dds/ddsrt/retcode.h"
|
||||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsrt/sync.h"
|
||||
#include "dds/ddsrt/threads_priv.h"
|
||||
|
||||
typedef enum {
|
||||
THREAD_STARTING = 0,
|
||||
THREAD_RUNNING,
|
||||
THREAD_EXITING /* Indicates the thread has returned from the specified
|
||||
start_routine, but FreeRTOS may not report it as deleted
|
||||
yet. */
|
||||
} thread_state_t;
|
||||
|
||||
typedef struct {
|
||||
ddsrt_thread_routine_t func;
|
||||
void *arg;
|
||||
TaskHandle_t task; /* Thread identifier for looking up thread context from
|
||||
another thread. Read-only, read by other threads. */
|
||||
thread_state_t stat;
|
||||
thread_cleanup_t *dtors; /* Cleanup routines. Private. */
|
||||
uint32_t ret; /* Return value. NULL if thread has not terminated, maybe
|
||||
NULL if thread has terminated, read by other thread(s)
|
||||
after termination. */
|
||||
TaskHandle_t blkd; /* Thread blocked until thread terminates. may or may
|
||||
not be empty when thread terminates. Written by other
|
||||
thread, protected by registry mutex. */
|
||||
} thread_context_t;
|
||||
|
||||
/* Thread registry (in combination with thread context) is required to properly
|
||||
implement thread join functionality. */
|
||||
|
||||
/* Threads have their own context. The context is automatically allocated and
|
||||
initialized, either when the thread is created (local threads) or when the
|
||||
API is first used. */
|
||||
|
||||
/* FIXME: The same mechanism more-or-less exists in DDSI, perhaps more of the
|
||||
logic in DDSI can be moved down at some point? */
|
||||
typedef struct {
|
||||
ddsrt_mutex_t mutex;
|
||||
/* The number of available spaces in the thread context array does not have
|
||||
to equal the number of used spaces. e.g. when a memory allocation for a
|
||||
new thread context array fails when destroying a context it is better to
|
||||
leave one space unused. */
|
||||
thread_context_t **ctxs;
|
||||
size_t cnt;
|
||||
size_t len;
|
||||
} thread_registry_t;
|
||||
|
||||
static ddsrt_thread_local thread_context_t *thread_context = NULL;
|
||||
|
||||
static thread_registry_t thread_registry;
|
||||
|
||||
static ddsrt_once_t thread_registry_once = DDSRT_ONCE_INIT;
|
||||
|
||||
static uint32_t non_local_thread(void *arg) { (void)arg; return 0;}
|
||||
|
||||
/* FreeRTOS documentation states vTaskGetInfo is intended for debugging because
|
||||
its use results in the scheduler remaining suspended for an extended period,
|
||||
but the scheduler is only suspended if eTaskState is not eInvalid. */
|
||||
ddsrt_tid_t
|
||||
ddsrt_gettid(void)
|
||||
{
|
||||
TaskStatus_t status;
|
||||
|
||||
vTaskGetInfo(xTaskGetCurrentTaskHandle(), &status, pdFALSE, eInvalid);
|
||||
|
||||
return status.xTaskNumber;
|
||||
}
|
||||
|
||||
ddsrt_thread_t
|
||||
ddsrt_thread_self(void)
|
||||
{
|
||||
ddsrt_thread_t thr = { .task = xTaskGetCurrentTaskHandle() };
|
||||
|
||||
return thr;
|
||||
}
|
||||
|
||||
bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b)
|
||||
{
|
||||
return (a.task == b.task);
|
||||
}
|
||||
|
||||
size_t
|
||||
ddsrt_thread_getname(char *__restrict name, size_t size)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
assert(name != NULL);
|
||||
assert(size >= 1);
|
||||
|
||||
if ((ptr = pcTaskGetName(NULL)) == NULL) {
|
||||
ptr = "";
|
||||
}
|
||||
|
||||
return ddsrt_strlcpy(name, ptr, size);
|
||||
}
|
||||
|
||||
static void
|
||||
thread_registry_init(void)
|
||||
{
|
||||
/* One time initialization guaranteed by ddsrt_once. */
|
||||
(void)memset(&thread_registry, 0, sizeof(thread_registry));
|
||||
ddsrt_mutex_init(&thread_registry.mutex);
|
||||
}
|
||||
|
||||
static thread_context_t *
|
||||
thread_context_find(TaskHandle_t task)
|
||||
{
|
||||
thread_context_t *ctx = NULL;
|
||||
|
||||
for (size_t i = 0; i < thread_registry.cnt && ctx == NULL; i++) {
|
||||
if (thread_registry.ctxs[i] != NULL &&
|
||||
thread_registry.ctxs[i]->task == task)
|
||||
{
|
||||
ctx = thread_registry.ctxs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static dds_return_t
|
||||
thread_context_create(thread_context_t **ctxptr)
|
||||
{
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
size_t len;
|
||||
thread_context_t *ctx = NULL, **ctxs = NULL;
|
||||
|
||||
assert(ctxptr != NULL);
|
||||
|
||||
ctx = ddsrt_calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
if (thread_registry.cnt < thread_registry.len) {
|
||||
len = thread_registry.len;
|
||||
ctxs = thread_registry.ctxs;
|
||||
} else {
|
||||
assert(thread_registry.cnt == thread_registry.len);
|
||||
len = thread_registry.len + 1;
|
||||
ctxs = ddsrt_realloc(thread_registry.ctxs, len * sizeof(ctx));
|
||||
}
|
||||
|
||||
if (ctxs == NULL) {
|
||||
ddsrt_free(ctx);
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ctxs[thread_registry.cnt++] = *ctxptr = ctx;
|
||||
thread_registry.len = len;
|
||||
thread_registry.ctxs = ctxs;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define thread_context_require() thread_context_acquire(NULL)
|
||||
|
||||
static dds_return_t
|
||||
thread_context_acquire(thread_context_t **ctxptr)
|
||||
{
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
thread_context_t *ctx = thread_context;
|
||||
|
||||
if (ctx == NULL) {
|
||||
/* Dynamically initialize global thread registry (exactly once). */
|
||||
ddsrt_once(&thread_registry_once, &thread_registry_init);
|
||||
|
||||
ddsrt_mutex_lock(&thread_registry.mutex);
|
||||
if ((rc = thread_context_create(&ctx)) == 0) {
|
||||
/* This situation only arises for non-native (not created in our code)
|
||||
threads. Some members must therefore still be initialized to ensure
|
||||
proper operation. */
|
||||
ctx->func = &non_local_thread;
|
||||
ctx->stat = THREAD_RUNNING;
|
||||
ctx->task = xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
ddsrt_mutex_unlock(&thread_registry.mutex);
|
||||
thread_context = ctx;
|
||||
} else {
|
||||
assert(ctx->func != NULL);
|
||||
assert(ctx->stat == THREAD_RUNNING);
|
||||
assert(ctx->task == xTaskGetCurrentTaskHandle());
|
||||
}
|
||||
|
||||
if (rc == DDS_RETCODE_OK && ctxptr != NULL) {
|
||||
assert(ctx != NULL);
|
||||
*ctxptr = ctx;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
thread_context_destroy(thread_context_t *ctx)
|
||||
{
|
||||
size_t i = 0;
|
||||
thread_context_t **arr;
|
||||
|
||||
if (ctx != NULL) {
|
||||
while (i < thread_registry.cnt && thread_registry.ctxs[i] != ctx) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < thread_registry.cnt) {
|
||||
thread_registry.ctxs[i] = NULL;
|
||||
if (i < (thread_registry.cnt - 1)) {
|
||||
(void)memmove(
|
||||
thread_registry.ctxs + (i),
|
||||
thread_registry.ctxs + (i+1),
|
||||
(thread_registry.cnt - (i+1)) * sizeof(*thread_registry.ctxs));
|
||||
}
|
||||
thread_registry.cnt--;
|
||||
|
||||
/* Free contexts when count reaches zero. */
|
||||
if (thread_registry.cnt == 0) {
|
||||
ddsrt_free(thread_registry.ctxs);
|
||||
thread_registry.ctxs = NULL;
|
||||
thread_registry.len = 0;
|
||||
} else {
|
||||
arr = ddsrt_realloc(
|
||||
thread_registry.ctxs,
|
||||
thread_registry.cnt * sizeof(*thread_registry.ctxs));
|
||||
/* Ignore allocation failure, save free spot. */
|
||||
if (arr != NULL) {
|
||||
thread_registry.ctxs = arr;
|
||||
thread_registry.len = thread_registry.cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
thread_fini(thread_context_t *ctx, uint32_t ret)
|
||||
{
|
||||
thread_cleanup_t *tail;
|
||||
|
||||
assert(ctx != NULL);
|
||||
|
||||
/* Acquire registry lock to publish task result and state. */
|
||||
ddsrt_mutex_lock(&thread_registry.mutex);
|
||||
|
||||
/* Pop all cleanup handlers from the thread's cleanup stack. */
|
||||
while ((tail = ctx->dtors) != NULL) {
|
||||
ctx->dtors = tail->prev;
|
||||
if (tail->routine != 0) {
|
||||
tail->routine(tail->arg);
|
||||
}
|
||||
ddsrt_free(tail);
|
||||
}
|
||||
|
||||
/* FreeRTOS can report task state, but doesn't register the result or
|
||||
notifies a thread that wants to join. */
|
||||
ctx->ret = ret;
|
||||
ctx->stat = THREAD_EXITING;
|
||||
|
||||
/* Thread resources will be leaked (especially for non-local threads)
|
||||
if not reclaimed by a thread join. Local threads (threads created
|
||||
within the DDS stack) are required to be joined. Thread resource
|
||||
leakage for local threads must be considered a bug. Non-local
|
||||
threads, however, are not aware that there are resources that must
|
||||
be reclaimed and local threads might not be aware that there are
|
||||
non-local threads that must be joined. Therefore, if a non-local thread
|
||||
exits, it's resources are reclaimed if no thread is waiting to join. */
|
||||
if (ctx->blkd != NULL) {
|
||||
/* Task join functionality is based on notifications, as it is
|
||||
significantly faster than using a queue, semaphore or event group to
|
||||
perform an equivalent operation.
|
||||
|
||||
When a task receives a notification, it's notification state is set to
|
||||
pending. When it reads it's notification state, the notification state
|
||||
is set to not-pending. A task can wait, with an optional time out, for
|
||||
it's notification state to become pending. */
|
||||
|
||||
/* Ignore result, there's nothing that can be done on failure and it always
|
||||
returns pdPASS. */
|
||||
(void)xTaskNotifyGive(ctx->blkd);
|
||||
} else if (ctx->func == &non_local_thread) {
|
||||
assert(ret == 0);
|
||||
thread_context_destroy(ctx);
|
||||
}
|
||||
|
||||
ddsrt_mutex_unlock(&thread_registry.mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
thread_start_routine(void *arg)
|
||||
{
|
||||
thread_context_t *ctx = (thread_context_t *)arg;
|
||||
uint32_t ret;
|
||||
|
||||
ddsrt_mutex_lock(&thread_registry.mutex);
|
||||
/* Context for the current task is always correctly initialized and
|
||||
registered at this stage. It's not strictly required to update task
|
||||
state, but the synchronization itself is. */
|
||||
ctx->stat = THREAD_RUNNING;
|
||||
ddsrt_mutex_unlock(&thread_registry.mutex);
|
||||
|
||||
/* Thread-local storage is initialized by the function that creates the
|
||||
thread because a reference to the thread's context is stored and
|
||||
synchronization is considerably easier if it's handled there. */
|
||||
|
||||
thread_context = ctx;
|
||||
ret = ctx->func(ctx->arg);
|
||||
|
||||
thread_fini(ctx, ret); /* DO NOT DEREFERENCE THREAD CONTEXT ANYMORE! */
|
||||
|
||||
/* Delete current task. */
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
/* xTaskCreate takes the stack depth in the number of words (NOT bytes). In
|
||||
practice this simply means it multiplies the given number with the size
|
||||
of StackType_t in bytes (see tasks.c). FreeRTOSConfig.h must define
|
||||
configMINIMAL_STACK_SIZE, which is the stack size in words allocated for
|
||||
the idle task. */
|
||||
#define WORD_SIZE (sizeof(StackType_t))
|
||||
/* configMINIMAL_STACK_SIZE is applied as the default stack size. Whether or
|
||||
not this is considered a sane default depends on the target. The default can
|
||||
be adjusted in FreeRTOSConfig.h Of course the configuration file also allows
|
||||
the user to change it on a per-thread basis at runtime. */
|
||||
#define MIN_STACK_SIZE ((uint16_t)(configMINIMAL_STACK_SIZE * WORD_SIZE))
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_create(
|
||||
ddsrt_thread_t *thread,
|
||||
const char *name,
|
||||
const ddsrt_threadattr_t *attr,
|
||||
ddsrt_thread_routine_t start_routine,
|
||||
void *arg)
|
||||
{
|
||||
dds_return_t rc;
|
||||
TaskHandle_t task;
|
||||
UBaseType_t prio;
|
||||
uint16_t size = MIN_STACK_SIZE;
|
||||
thread_context_t *ctx = NULL;
|
||||
|
||||
assert(thread != NULL);
|
||||
assert(name != NULL);
|
||||
assert(attr != NULL);
|
||||
assert(start_routine != 0);
|
||||
|
||||
if ((rc = thread_context_require()) != DDS_RETCODE_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Non-realtime scheduling does not exist in FreeRTOS. */
|
||||
if (attr->schedClass != DDSRT_SCHED_DEFAULT &&
|
||||
attr->schedClass != DDSRT_SCHED_REALTIME)
|
||||
{
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
} else if (attr->schedPriority < 0 ||
|
||||
attr->schedPriority > (configMAX_PRIORITIES - 1))
|
||||
{
|
||||
return DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* Stack size is quietly increased to match at least the minimum. */
|
||||
if (attr->stackSize > size) {
|
||||
size = (uint16_t)(attr->stackSize / WORD_SIZE);
|
||||
if (attr->stackSize % WORD_SIZE) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assume that when the default priority of zero (0) is specified, the user
|
||||
wants the thread to inherit the priority of the calling thread. */
|
||||
assert(0 == tskIDLE_PRIORITY);
|
||||
if (attr->schedPriority == 0) {
|
||||
prio = uxTaskPriorityGet(NULL);
|
||||
} else {
|
||||
prio = (UBaseType_t)attr->schedPriority;
|
||||
}
|
||||
|
||||
ddsrt_mutex_lock(&thread_registry.mutex);
|
||||
|
||||
/* Thread context is allocated here so that it can be handled when no more
|
||||
memory is available. Simply storing the entire context in thread-local
|
||||
storage would have been possible, but would require the implementation to
|
||||
define and allocate a separate struct in order to support thread joins. */
|
||||
if ((rc = thread_context_create(&ctx)) == DDS_RETCODE_OK) {
|
||||
ctx->func = start_routine;
|
||||
ctx->arg = arg;
|
||||
|
||||
if (pdPASS != xTaskCreate(
|
||||
&thread_start_routine, name, size, ctx, prio, &task))
|
||||
{
|
||||
thread_context_destroy(ctx);
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
thread->task = ctx->task = task;
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_mutex_unlock(&thread_registry.mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_thread_init(void)
|
||||
{
|
||||
if (thread_context_require() != DDS_RETCODE_OK) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ddsrt_thread_fini(void)
|
||||
{
|
||||
thread_context_t *ctx;
|
||||
|
||||
/* NO-OP if no context exists since thread-local storage and cleanup
|
||||
handler references are both stored in the thread context. */
|
||||
if ((ctx = thread_context) != NULL) {
|
||||
assert(ctx->func != &non_local_thread);
|
||||
thread_fini(ctx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result)
|
||||
{
|
||||
dds_return_t rc;
|
||||
thread_context_t *ctx;
|
||||
eTaskState status;
|
||||
|
||||
if ((rc = thread_context_require()) != DDS_RETCODE_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
ddsrt_mutex_lock(&thread_registry.mutex);
|
||||
ctx = thread_context_find(thread.task);
|
||||
if (ctx != NULL) {
|
||||
/* Task should never be joined by multiple tasks simultaneously */
|
||||
assert(ctx->blkd == NULL);
|
||||
rc = DDS_RETCODE_TRY_AGAIN;
|
||||
|
||||
do {
|
||||
(void)memset(&status, 0, sizeof(status));
|
||||
status = eTaskGetState(thread.task);
|
||||
if (status == eDeleted) {
|
||||
/* FreeRTOS reports the task is deleted. Require the context to exist,
|
||||
fetch the result and free the context afterwards. */
|
||||
assert(ctx != NULL);
|
||||
rc = DDS_RETCODE_OK;
|
||||
} else if (status != eInvalid) {
|
||||
assert(ctx != NULL);
|
||||
/* FreeRTOS reports the task is still active. That does not mean the
|
||||
task has not yet returned from start_routine. */
|
||||
if (ctx->stat == THREAD_EXITING) {
|
||||
/* Thread context will not be accessed by the thread itself anymore
|
||||
and it should be safe to free it. */
|
||||
rc = DDS_RETCODE_OK;
|
||||
} else {
|
||||
ctx->blkd = xTaskGetCurrentTaskHandle();
|
||||
|
||||
/* Reset notify state and counter. */
|
||||
ulTaskNotifyTake(pdTRUE, 0);
|
||||
|
||||
ddsrt_mutex_unlock(&thread_registry.mutex);
|
||||
|
||||
/* Wait to be notified. */
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
ddsrt_mutex_lock(&thread_registry.mutex);
|
||||
}
|
||||
} else {
|
||||
rc = DDS_RETCODE_BAD_PARAMETER;
|
||||
}
|
||||
} while (rc == DDS_RETCODE_TRY_AGAIN);
|
||||
|
||||
if (rc == DDS_RETCODE_OK) {
|
||||
if (thread_result != NULL) {
|
||||
*thread_result = ctx->ret;
|
||||
}
|
||||
thread_context_destroy(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
ddsrt_mutex_unlock(&thread_registry.mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg)
|
||||
{
|
||||
dds_return_t rc = DDS_RETCODE_OK;
|
||||
thread_cleanup_t *tail = NULL;
|
||||
thread_context_t *ctx;
|
||||
|
||||
assert(routine != NULL);
|
||||
|
||||
if (thread_context_acquire(&ctx) == 0) {
|
||||
if ((tail = ddsrt_malloc(sizeof(*tail))) == NULL) {
|
||||
rc = DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
tail->prev = ctx->dtors;
|
||||
tail->routine = routine;
|
||||
tail->arg = arg;
|
||||
ctx->dtors = tail;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_cleanup_pop(int execute)
|
||||
{
|
||||
thread_cleanup_t *tail;
|
||||
thread_context_t *ctx;
|
||||
|
||||
if (thread_context_acquire(&ctx) == 0) {
|
||||
if ((tail = ctx->dtors) != NULL) {
|
||||
ctx->dtors = tail->prev;
|
||||
if (execute) {
|
||||
tail->routine(tail->arg);
|
||||
}
|
||||
ddsrt_free(tail);
|
||||
}
|
||||
}
|
||||
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
|
@ -14,12 +14,6 @@
|
|||
|
||||
#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;
|
||||
|
|
|
@ -30,12 +30,24 @@
|
|||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsrt/threads_priv.h"
|
||||
#include "dds/ddsrt/types.h"
|
||||
#include "dds/ddsrt/static_assert.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
ddsrt_thread_routine_t routine;
|
||||
void *arg;
|
||||
} thread_context_t;
|
||||
|
||||
#if defined(__linux)
|
||||
#include <sys/syscall.h>
|
||||
#include <dirent.h>
|
||||
#define MAXTHREADNAMESIZE (15) /* 16 bytes including null-terminating byte. */
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/thread_info.h> /* MAXTHREADNAMESIZE */
|
||||
#include <mach/task.h>
|
||||
#include <mach/task_info.h>
|
||||
#include <mach/vm_map.h>
|
||||
#elif defined(__sun)
|
||||
#define MAXTHREADNAMESIZE (31)
|
||||
#elif defined(__FreeBSD__)
|
||||
|
@ -74,7 +86,11 @@ ddsrt_thread_getname(char *str, size_t size)
|
|||
(void)pthread_get_name_np(pthread_self(), buf, sizeof(buf));
|
||||
cnt = ddsrt_strlcpy(str, buf, size);
|
||||
#elif defined(__sun)
|
||||
#if !(__SunOS_5_6 || __SunOS_5_7 || __SunOS_5_8 || __SunOS_5_9 || __SunOS_5_10)
|
||||
(void)pthread_getname_np(pthread_self(), buf, sizeof(buf));
|
||||
#else
|
||||
buf[0] = 0;
|
||||
#endif
|
||||
cnt = ddsrt_strlcpy(str, buf, size);
|
||||
#elif defined(__VXWORKS__)
|
||||
{
|
||||
|
@ -119,7 +135,9 @@ ddsrt_thread_setname(const char *__restrict name)
|
|||
#elif defined(__sun)
|
||||
/* Thread names are limited to 31 bytes on Solaris. Excess bytes are
|
||||
silently truncated. */
|
||||
#if !(__SunOS_5_6 || __SunOS_5_7 || __SunOS_5_8 || __SunOS_5_9 || __SunOS_5_10)
|
||||
(void)pthread_setname_np(pthread_self(), name);
|
||||
#endif
|
||||
#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. */
|
||||
|
@ -181,7 +199,7 @@ static void *os_startRoutineWrapper (void *threadContext)
|
|||
return (void *)resultValue;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_thread_create (
|
||||
ddsrt_thread_t *threadptr,
|
||||
const char *name,
|
||||
|
@ -340,7 +358,7 @@ bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b)
|
|||
return (pthread_equal(a.v, b.v) != 0);
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result)
|
||||
{
|
||||
int err;
|
||||
|
@ -351,7 +369,7 @@ ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result)
|
|||
|
||||
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);
|
||||
DDS_ERROR ("pthread_join(0x%"PRIxMAX") failed with error %d\n", (uintmax_t)((uintptr_t)thread.v), err);
|
||||
return DDS_RETCODE_ERROR;
|
||||
}
|
||||
|
||||
|
@ -360,6 +378,104 @@ ddsrt_thread_join(ddsrt_thread_t thread, uint32_t *thread_result)
|
|||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
#if defined __linux
|
||||
dds_return_t
|
||||
ddsrt_thread_list (
|
||||
ddsrt_thread_list_id_t * __restrict tids,
|
||||
size_t size)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
if ((dir = opendir ("/proc/self/task")) == NULL)
|
||||
return DDS_RETCODE_ERROR;
|
||||
dds_return_t n = 0;
|
||||
while ((de = readdir (dir)) != NULL)
|
||||
{
|
||||
if (de->d_name[0] == '.' && (de->d_name[1] == 0 || (de->d_name[1] == '.' && de->d_name[2] == 0)))
|
||||
continue;
|
||||
int pos;
|
||||
long tid;
|
||||
if (sscanf (de->d_name, "%ld%n", &tid, &pos) != 1 || de->d_name[pos] != 0)
|
||||
{
|
||||
n = DDS_RETCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
if ((size_t) n < size)
|
||||
tids[n] = (ddsrt_thread_list_id_t) tid;
|
||||
n++;
|
||||
}
|
||||
closedir (dir);
|
||||
/* If there were no threads, something must've gone badly wrong */
|
||||
return (n == 0) ? DDS_RETCODE_ERROR : n;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_getname_anythread (
|
||||
ddsrt_thread_list_id_t tid,
|
||||
char *__restrict name,
|
||||
size_t size)
|
||||
{
|
||||
char file[100];
|
||||
FILE *fp;
|
||||
int pos;
|
||||
pos = snprintf (file, sizeof (file), "/proc/self/task/%lu/stat", (unsigned long) tid);
|
||||
if (pos < 0 || pos >= (int) sizeof (file))
|
||||
return DDS_RETCODE_ERROR;
|
||||
if ((fp = fopen (file, "r")) == NULL)
|
||||
return DDS_RETCODE_NOT_FOUND;
|
||||
int c;
|
||||
size_t namelen = 0, namepos = 0;
|
||||
while ((c = fgetc (fp)) != EOF)
|
||||
if (c == '(')
|
||||
break;
|
||||
while ((c = fgetc (fp)) != EOF)
|
||||
{
|
||||
if (c == ')')
|
||||
namelen = namepos;
|
||||
if (namepos + 1 < size)
|
||||
name[namepos++] = (char) c;
|
||||
}
|
||||
fclose (fp);
|
||||
assert (size == 0 || namelen < size);
|
||||
if (size > 0)
|
||||
name[namelen] = 0;
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
DDSRT_STATIC_ASSERT (sizeof (ddsrt_thread_list_id_t) == sizeof (mach_port_t));
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_list (
|
||||
ddsrt_thread_list_id_t * __restrict tids,
|
||||
size_t size)
|
||||
{
|
||||
thread_act_array_t tasks;
|
||||
mach_msg_type_number_t count;
|
||||
if (task_threads (mach_task_self (), &tasks, &count) != KERN_SUCCESS)
|
||||
return DDS_RETCODE_ERROR;
|
||||
for (mach_msg_type_number_t i = 0; i < count && (size_t) i < size; i++)
|
||||
tids[i] = (ddsrt_thread_list_id_t) tasks[i];
|
||||
vm_deallocate (mach_task_self (), (vm_address_t) tasks, count * sizeof (thread_act_t));
|
||||
return (dds_return_t) count;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_getname_anythread (
|
||||
ddsrt_thread_list_id_t tid,
|
||||
char *__restrict name,
|
||||
size_t size)
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
pthread_t pt = pthread_from_mach_thread_np ((mach_port_t) tid);
|
||||
name[0] = '\0';
|
||||
if (pt == NULL || pthread_getname_np (pt, name, size) != 0 || name[0] == 0)
|
||||
snprintf (name, size, "task%"PRIu64, (uint64_t) tid);
|
||||
}
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static pthread_key_t thread_cleanup_key;
|
||||
static pthread_once_t thread_once = PTHREAD_ONCE_INIT;
|
||||
|
@ -380,7 +496,7 @@ 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)
|
||||
dds_return_t ddsrt_thread_cleanup_push (void (*routine) (void *), void *arg)
|
||||
{
|
||||
int err;
|
||||
thread_cleanup_t *prev, *tail;
|
||||
|
@ -402,7 +518,7 @@ dds_retcode_t ddsrt_thread_cleanup_push (void (*routine) (void *), void *arg)
|
|||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_thread_cleanup_pop (int execute)
|
||||
dds_return_t ddsrt_thread_cleanup_pop (int execute)
|
||||
{
|
||||
int err;
|
||||
thread_cleanup_t *tail;
|
||||
|
|
|
@ -16,6 +16,66 @@
|
|||
#include "dds/ddsrt/string.h"
|
||||
#include "dds/ddsrt/threads_priv.h"
|
||||
|
||||
/* tlhelp32 for ddsrt_thread_list */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
/* {Get,Set}ThreadDescription is the Windows 10 interface for dealing with thread names, but it at
|
||||
least in some setups the linker can't find the symbols in kernel32.lib, even though kernel32.dll
|
||||
exports them. (Perhaps it is just a broken installation, who knows ...) Looking them up
|
||||
dynamically works fine. */
|
||||
typedef HRESULT (WINAPI *SetThreadDescription_t) (HANDLE hThread, PCWSTR lpThreadDescription);
|
||||
typedef HRESULT (WINAPI *GetThreadDescription_t) (HANDLE hThread, PWSTR *ppszThreadDescription);
|
||||
static volatile SetThreadDescription_t SetThreadDescription_ptr = 0;
|
||||
static volatile GetThreadDescription_t GetThreadDescription_ptr = 0;
|
||||
|
||||
static HRESULT WINAPI SetThreadDescription_dummy (HANDLE hThread, PCWSTR lpThreadDescription)
|
||||
{
|
||||
(void) hThread;
|
||||
(void) lpThreadDescription;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI GetThreadDescription_dummy (HANDLE hThread, PWSTR *ppszThreadDescription)
|
||||
{
|
||||
(void) hThread;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static void getset_threaddescription_addresses (void)
|
||||
{
|
||||
/* Rely on MSVC's interpretation of the meaning of volatile
|
||||
to order checking & setting the pointers */
|
||||
if (GetThreadDescription_ptr == 0)
|
||||
{
|
||||
HMODULE mod;
|
||||
FARPROC p;
|
||||
if (!GetModuleHandleExA (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, "kernel32.dll", &mod))
|
||||
{
|
||||
SetThreadDescription_ptr = SetThreadDescription_dummy;
|
||||
GetThreadDescription_ptr = GetThreadDescription_dummy;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((p = GetProcAddress (mod, "SetThreadDescription")) != 0)
|
||||
SetThreadDescription_ptr = (SetThreadDescription_t) p;
|
||||
else
|
||||
SetThreadDescription_ptr = SetThreadDescription_dummy;
|
||||
if ((p = GetProcAddress (mod, "GetThreadDescription")) != 0)
|
||||
GetThreadDescription_ptr = (GetThreadDescription_t) p;
|
||||
else
|
||||
GetThreadDescription_ptr = GetThreadDescription_dummy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
ddsrt_thread_routine_t routine;
|
||||
void *arg;
|
||||
} thread_context_t;
|
||||
|
||||
static uint32_t
|
||||
os_startRoutineWrapper(
|
||||
void *threadContext)
|
||||
|
@ -37,7 +97,7 @@ os_startRoutineWrapper(
|
|||
return resultValue;
|
||||
}
|
||||
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_thread_create(
|
||||
ddsrt_thread_t *thrptr,
|
||||
const char *name,
|
||||
|
@ -133,7 +193,7 @@ bool ddsrt_thread_equal(ddsrt_thread_t a, ddsrt_thread_t b)
|
|||
* should not be closed until the os_threadWaitExit(...) call is called.
|
||||
* CloseHandle (threadHandle);
|
||||
*/
|
||||
dds_retcode_t
|
||||
dds_return_t
|
||||
ddsrt_thread_join(
|
||||
ddsrt_thread_t thread,
|
||||
uint32_t *thread_result)
|
||||
|
@ -170,7 +230,10 @@ ddsrt_thread_join(
|
|||
}
|
||||
|
||||
/* 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. */
|
||||
more storage than that as internal threads must adhere to that limit.
|
||||
Use the thread-local variable instead of relying on GetThreadDescription
|
||||
to avoid the dynamic memory allocation, as the thread name is used by
|
||||
the logging code and the overhead there matters. */
|
||||
static ddsrt_thread_local char thread_name[16] = "";
|
||||
|
||||
size_t
|
||||
|
@ -191,6 +254,16 @@ ddsrt_thread_getname(
|
|||
return cnt;
|
||||
}
|
||||
|
||||
/** \brief Set thread name for debugging and system monitoring
|
||||
*
|
||||
* Windows 10 introduced the SetThreadDescription function, which is
|
||||
* obviously the sane interface. For reasons unknown to me, the
|
||||
* linker claims to have no knowledge of the function, even though
|
||||
* they appear present, and so it seems to sensible to retain the
|
||||
* old exception-based trick as a fall-back mechanism. At least
|
||||
* until the reason for {Get,Set}Description's absence from the
|
||||
* regular libraries.
|
||||
*/
|
||||
static const DWORD MS_VC_EXCEPTION=0x406D1388;
|
||||
|
||||
#pragma pack(push,8)
|
||||
|
@ -203,19 +276,23 @@ typedef struct tagTHREADNAME_INFO
|
|||
} 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);
|
||||
|
||||
assert (name != NULL);
|
||||
getset_threaddescription_addresses ();
|
||||
if (SetThreadDescription_ptr != SetThreadDescription_dummy)
|
||||
{
|
||||
size_t size = strlen (name) + 1;
|
||||
wchar_t *wname = malloc (size * sizeof (*wname));
|
||||
size_t cnt = 0;
|
||||
mbstowcs_s (&cnt, wname, size, name, _TRUNCATE);
|
||||
SetThreadDescription_ptr (GetCurrentThread (), wname);
|
||||
free (wname);
|
||||
}
|
||||
else
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name;
|
||||
|
@ -235,14 +312,77 @@ ddsrt_thread_setname(
|
|||
/* Suppress warnings. */
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
ddsrt_strlcpy(thread_name, name, sizeof(thread_name));
|
||||
}
|
||||
ddsrt_strlcpy (thread_name, name, sizeof (thread_name));
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_list (
|
||||
ddsrt_thread_list_id_t * __restrict tids,
|
||||
size_t size)
|
||||
{
|
||||
HANDLE hThreadSnap;
|
||||
THREADENTRY32 te32;
|
||||
const DWORD pid = GetCurrentProcessId ();
|
||||
int32_t n = 0;
|
||||
|
||||
if ((hThreadSnap = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0)) == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
memset (&te32, 0, sizeof (te32));
|
||||
te32.dwSize = sizeof (THREADENTRY32);
|
||||
if (!Thread32First (hThreadSnap, &te32))
|
||||
{
|
||||
CloseHandle (hThreadSnap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
if (te32.th32OwnerProcessID != pid)
|
||||
continue;
|
||||
if ((size_t) n < size)
|
||||
{
|
||||
/* get a handle to the thread, not counting the thread the thread if no such
|
||||
handle is obtainable */
|
||||
if ((tids[n] = OpenThread (THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID)) == NULL)
|
||||
continue;
|
||||
}
|
||||
n++;
|
||||
} while (Thread32Next (hThreadSnap, &te32));
|
||||
CloseHandle (hThreadSnap);
|
||||
return n;
|
||||
}
|
||||
|
||||
dds_return_t
|
||||
ddsrt_thread_getname_anythread (
|
||||
ddsrt_thread_list_id_t tid,
|
||||
char * __restrict name,
|
||||
size_t size)
|
||||
{
|
||||
getset_threaddescription_addresses ();
|
||||
if (size > 0)
|
||||
{
|
||||
PWSTR data;
|
||||
HRESULT hr = GetThreadDescription_ptr (tid, &data);
|
||||
if (! SUCCEEDED (hr))
|
||||
name[0] = 0;
|
||||
else
|
||||
{
|
||||
size_t cnt;
|
||||
wcstombs_s (&cnt, name, size, data, _TRUNCATE);
|
||||
LocalFree (data);
|
||||
}
|
||||
if (name[0] == 0)
|
||||
{
|
||||
snprintf (name, sizeof (name), "%"PRIdTID, GetThreadId (tid));
|
||||
}
|
||||
}
|
||||
return DDS_RETCODE_OK;
|
||||
}
|
||||
|
||||
static ddsrt_thread_local thread_cleanup_t *thread_cleanup = NULL;
|
||||
|
||||
dds_retcode_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg)
|
||||
dds_return_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg)
|
||||
{
|
||||
thread_cleanup_t *tail;
|
||||
|
||||
|
@ -259,7 +399,7 @@ dds_retcode_t ddsrt_thread_cleanup_push(void (*routine)(void *), void *arg)
|
|||
return DDS_RETCODE_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
dds_retcode_t ddsrt_thread_cleanup_pop(int execute)
|
||||
dds_return_t ddsrt_thread_cleanup_pop(int execute)
|
||||
{
|
||||
thread_cleanup_t *tail;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
extern inline dds_time_t
|
||||
ddsrt_time_add_duration(dds_time_t abstime, dds_duration_t reltime);
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#if !_WIN32 && !DDSRT_WITH_FREERTOS
|
||||
#include <errno.h>
|
||||
|
||||
void dds_sleepfor(dds_duration_t n)
|
||||
|
@ -47,7 +47,12 @@ size_t
|
|||
ddsrt_ctime(dds_time_t n, char *str, size_t size)
|
||||
{
|
||||
struct tm tm;
|
||||
#if __SunOS_5_6
|
||||
/* Solaris 2.6 doesn't recognize %z so we just leave it out */
|
||||
static const char fmt[] = "%Y-%m-%d %H:%M:%S";
|
||||
#else
|
||||
static const char fmt[] = "%Y-%m-%d %H:%M:%S%z";
|
||||
#endif
|
||||
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);
|
||||
|
@ -61,12 +66,14 @@ ddsrt_ctime(dds_time_t n, char *str, size_t size)
|
|||
#endif /* _WIN32 */
|
||||
|
||||
cnt = strftime(buf, sizeof(buf), fmt, &tm);
|
||||
#if ! __SunOS_5_6
|
||||
/* %z is without a separator between hours and minutes, fixup */
|
||||
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] = ':';
|
||||
|
||||
#endif
|
||||
(void)cnt;
|
||||
|
||||
return ddsrt_strlcpy(str, buf, size);
|
||||
|
|
|
@ -13,21 +13,29 @@
|
|||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
dds_time_t dds_time(void)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
|
||||
return (int64_t) clock_gettime_nsec_np (CLOCK_REALTIME);
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
|
||||
return ((tv.tv_sec * DDS_NSECS_IN_SEC) + (tv.tv_usec * DDS_NSECS_IN_USEC));
|
||||
#endif
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_monotonic(void)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
|
||||
return (int64_t) clock_gettime_nsec_np (CLOCK_UPTIME_RAW);
|
||||
#else
|
||||
static mach_timebase_info_data_t timeInfo;
|
||||
uint64_t mt;
|
||||
|
||||
|
@ -49,10 +57,15 @@ dds_time_t ddsrt_time_monotonic(void)
|
|||
}
|
||||
|
||||
return (dds_time_t)(mt * timeInfo.numer / timeInfo.denom);
|
||||
#endif
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_elapsed(void)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
|
||||
return (int64_t) clock_gettime_nsec_np (CLOCK_MONOTONIC_RAW);
|
||||
#else
|
||||
/* Elapsed time clock not (yet) supported on this platform. */
|
||||
return ddsrt_time_monotonic();
|
||||
#endif
|
||||
}
|
||||
|
|
53
src/ddsrt/src/time/freertos/time.c
Normal file
53
src/ddsrt/src/time/freertos/time.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 <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#define _POSIX_TIMERS
|
||||
#include <time.h>
|
||||
|
||||
#include "dds/ddsrt/time.h"
|
||||
|
||||
extern inline TickType_t ddsrt_duration_to_ticks_ceil(dds_duration_t reltime);
|
||||
|
||||
dds_time_t dds_time(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
timespec_get(&ts, TIME_UTC);
|
||||
#else
|
||||
(void)clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#endif
|
||||
|
||||
return (ts.tv_sec * DDS_NSECS_IN_SEC) + ts.tv_nsec;
|
||||
}
|
||||
|
||||
#define NSECS_PER_TICK (DDS_NSECS_IN_SEC / configTICK_RATE_HZ)
|
||||
|
||||
dds_time_t ddsrt_time_monotonic (void)
|
||||
{
|
||||
return (xTaskGetTickCount() * NSECS_PER_TICK);
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_elapsed (void)
|
||||
{
|
||||
/* Elapsed time clock not (yet) supported on this platform. */
|
||||
return ddsrt_time_monotonic ();
|
||||
}
|
||||
|
||||
void dds_sleepfor (dds_duration_t reltime)
|
||||
{
|
||||
TickType_t ticks;
|
||||
|
||||
ticks = ddsrt_duration_to_ticks_ceil(reltime);
|
||||
vTaskDelay(ticks);
|
||||
}
|
38
src/ddsrt/src/time/solaris2.6/time.c
Normal file
38
src/ddsrt/src/time/solaris2.6/time.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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)
|
||||
{
|
||||
return gethrtime ();
|
||||
}
|
||||
|
||||
dds_time_t ddsrt_time_elapsed(void)
|
||||
{
|
||||
/* Elapsed time clock not worth the bother for now. */
|
||||
return ddsrt_time_monotonic();
|
||||
}
|
|
@ -35,6 +35,7 @@ struct ddsrt_xmlp_state {
|
|||
size_t cbufn; /* number of bytes in cbuf (cbufp <= cbufn) */
|
||||
size_t cbufmax; /* allocated size of cbuf (cbufn <= cbufmax) */
|
||||
size_t cbufmark; /* NORMARKER or marker position (cbufmark <= cbufp) for rewinding */
|
||||
int eof; /* fake EOF (for treating missing close tags as EOF) */
|
||||
char *cbuf; /* parser input buffer */
|
||||
FILE *fp; /* file to refill cbuf from, or NULL if parsing a string */
|
||||
int line; /* current line number */
|
||||
|
@ -53,36 +54,40 @@ struct ddsrt_xmlp_state {
|
|||
struct ddsrt_xmlp_callbacks cb; /* user-supplied callbacks (or stubs) */
|
||||
};
|
||||
|
||||
static int cb_null_elem_open (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name)
|
||||
static int cb_null_elem_open (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name, int line)
|
||||
{
|
||||
DDSRT_UNUSED_ARG (varg);
|
||||
DDSRT_UNUSED_ARG (parentinfo);
|
||||
DDSRT_UNUSED_ARG (eleminfo);
|
||||
DDSRT_UNUSED_ARG (name);
|
||||
DDSRT_UNUSED_ARG (line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cb_null_attr (void *varg, uintptr_t eleminfo, const char *name, const char *value)
|
||||
static int cb_null_attr (void *varg, uintptr_t eleminfo, const char *name, const char *value, int line)
|
||||
{
|
||||
DDSRT_UNUSED_ARG (varg);
|
||||
DDSRT_UNUSED_ARG (eleminfo);
|
||||
DDSRT_UNUSED_ARG (name);
|
||||
DDSRT_UNUSED_ARG (value);
|
||||
DDSRT_UNUSED_ARG (line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cb_null_elem_data (void *varg, uintptr_t eleminfo, const char *data)
|
||||
static int cb_null_elem_data (void *varg, uintptr_t eleminfo, const char *data, int line)
|
||||
{
|
||||
DDSRT_UNUSED_ARG (varg);
|
||||
DDSRT_UNUSED_ARG (eleminfo);
|
||||
DDSRT_UNUSED_ARG (data);
|
||||
DDSRT_UNUSED_ARG (line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cb_null_elem_close (void *varg, uintptr_t eleminfo)
|
||||
static int cb_null_elem_close (void *varg, uintptr_t eleminfo, int line)
|
||||
{
|
||||
DDSRT_UNUSED_ARG (varg);
|
||||
DDSRT_UNUSED_ARG (eleminfo);
|
||||
DDSRT_UNUSED_ARG (line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -97,6 +102,7 @@ static void ddsrt_xmlp_new_common (struct ddsrt_xmlp_state *st)
|
|||
{
|
||||
st->cbufp = 0;
|
||||
st->cbufmark = NOMARKER;
|
||||
st->eof = 0;
|
||||
st->tpp = 0;
|
||||
st->tpescp = 0;
|
||||
st->tpsz = 1024;
|
||||
|
@ -170,6 +176,9 @@ void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st)
|
|||
static int make_chars_available (struct ddsrt_xmlp_state *st, size_t nmin)
|
||||
{
|
||||
size_t n, pos;
|
||||
if (st->eof) {
|
||||
return 0;
|
||||
}
|
||||
pos = (st->cbufmark != NOMARKER) ? st->cbufmark : st->cbufp;
|
||||
assert (st->cbufn >= st->cbufp);
|
||||
assert (st->cbufmax >= st->cbufn);
|
||||
|
@ -215,6 +224,11 @@ static void discard_input_marker (struct ddsrt_xmlp_state *st)
|
|||
st->linemark = 0;
|
||||
}
|
||||
|
||||
static int have_input_marker (struct ddsrt_xmlp_state *st)
|
||||
{
|
||||
return (st->cbufmark != NOMARKER);
|
||||
}
|
||||
|
||||
static void rewind_to_input_marker (struct ddsrt_xmlp_state *st)
|
||||
{
|
||||
assert (st->cbufmark != NOMARKER);
|
||||
|
@ -295,9 +309,9 @@ static char *unescape_into_utf8 (char *dst, unsigned cp)
|
|||
return dst;
|
||||
}
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4996);
|
||||
static int unescape_insitu (char *buffer, size_t *n)
|
||||
{
|
||||
DDSRT_WARNING_MSVC_OFF(4996);
|
||||
const char *src = buffer;
|
||||
char const * const srcend = buffer + *n;
|
||||
char *dst = buffer;
|
||||
|
@ -351,8 +365,8 @@ static int unescape_insitu (char *buffer, size_t *n)
|
|||
}
|
||||
*n = (size_t) (dst - buffer);
|
||||
return 0;
|
||||
DDSRT_WARNING_MSVC_ON(4996);
|
||||
}
|
||||
DDSRT_WARNING_MSVC_ON(4996);
|
||||
|
||||
static void discard_payload (struct ddsrt_xmlp_state *st)
|
||||
{
|
||||
|
@ -596,7 +610,7 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo)
|
|||
PE_LOCAL_ERROR ("expecting '<'", 0);
|
||||
}
|
||||
|
||||
if ((ret = st->cb.elem_open (st->varg, parentinfo, &eleminfo, name)) < 0) {
|
||||
if ((ret = st->cb.elem_open (st->varg, parentinfo, &eleminfo, name, st->line)) < 0) {
|
||||
PE_ERROR ("failed in element open callback", name);
|
||||
}
|
||||
|
||||
|
@ -610,7 +624,7 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo)
|
|||
ddsrt_free (content);
|
||||
PE_LOCAL_ERROR ("expecting string value for attribute", aname);
|
||||
}
|
||||
ret = st->cb.attr (st->varg, eleminfo, aname, content);
|
||||
ret = st->cb.attr (st->varg, eleminfo, aname, content, st->line);
|
||||
ddsrt_free (content);
|
||||
if (ret < 0) {
|
||||
PE_ERROR2 ("failed in attribute callback", name, aname);
|
||||
|
@ -623,7 +637,7 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo)
|
|||
switch (tok)
|
||||
{
|
||||
case TOK_SHORTHAND_CLOSE_TAG:
|
||||
ret = st->cb.elem_close (st->varg, eleminfo);
|
||||
ret = st->cb.elem_close (st->varg, eleminfo, st->line);
|
||||
goto ok;
|
||||
case '>':
|
||||
st->nest++;
|
||||
|
@ -668,8 +682,8 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo)
|
|||
if (save_payload (&content, st, 1) < 0) {
|
||||
PE_ERROR ("invalid character sequence", 0);
|
||||
} else if (content != NULL) {
|
||||
if(*content != '\0') {
|
||||
ret = st->cb.elem_data (st->varg, eleminfo, content);
|
||||
if (*content != '\0') {
|
||||
ret = st->cb.elem_data (st->varg, eleminfo, content, st->line);
|
||||
ddsrt_free (content);
|
||||
if (ret < 0) {
|
||||
PE_ERROR ("failed in data callback", 0);
|
||||
|
@ -680,13 +694,23 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo)
|
|||
}
|
||||
}
|
||||
st->nest--;
|
||||
set_input_marker (st);
|
||||
if (((tok = next_token (st, &ename)) != TOK_CLOSE_TAG && tok != TOK_SHORTHAND_CLOSE_TAG) || next_char (st) != '>') {
|
||||
PE_LOCAL_ERROR ("expecting closing tag", name);
|
||||
if (!(st->options & DDSRT_XMLP_MISSING_CLOSE_AS_EOF)) {
|
||||
PE_LOCAL_ERROR ("expecting closing tag", name);
|
||||
} else {
|
||||
rewind_to_input_marker (st);
|
||||
st->eof = 1;
|
||||
tok = TOK_SHORTHAND_CLOSE_TAG;
|
||||
}
|
||||
}
|
||||
if (tok != TOK_SHORTHAND_CLOSE_TAG && strcmp (name, ename) != 0) {
|
||||
PE_LOCAL_ERROR ("open/close tag mismatch", ename);
|
||||
}
|
||||
ret = st->cb.elem_close (st->varg, eleminfo);
|
||||
if (have_input_marker (st)) {
|
||||
discard_input_marker (st);
|
||||
}
|
||||
ret = st->cb.elem_close (st->varg, eleminfo, st->line);
|
||||
goto ok;
|
||||
default:
|
||||
PE_LOCAL_ERROR ("expecting '/>' or '>'", 0);
|
||||
|
@ -722,7 +746,3 @@ int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ddsrt_xmlUnescapeInsitu (char *buffer, size_t *n) {
|
||||
return unescape_insitu (buffer, n);
|
||||
}
|
||||
|
|
|
@ -10,65 +10,38 @@
|
|||
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
#
|
||||
include(CUnit)
|
||||
include(GenerateExportHeader)
|
||||
include(GenerateDummyExportHeader)
|
||||
|
||||
set(sources
|
||||
"atomics.c"
|
||||
"dynlib.c"
|
||||
"environ.c"
|
||||
"heap.c"
|
||||
"ifaddrs.c"
|
||||
"sync.c"
|
||||
"strtoll.c"
|
||||
"thread.c"
|
||||
"thread_cleanup.c"
|
||||
"string.c"
|
||||
"log.c"
|
||||
"random.c"
|
||||
"strlcpy.c"
|
||||
"socket.c"
|
||||
"process.c"
|
||||
"select.c")
|
||||
list(APPEND sources
|
||||
"atomics.c"
|
||||
"dynlib.c"
|
||||
"environ.c"
|
||||
"heap.c"
|
||||
"ifaddrs.c"
|
||||
"sync.c"
|
||||
"strtoll.c"
|
||||
"thread.c"
|
||||
"thread_cleanup.c"
|
||||
"string.c"
|
||||
"log.c"
|
||||
"random.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")
|
||||
if(HAVE_MULTI_PROCESS)
|
||||
list(APPEND sources "process.c")
|
||||
endif()
|
||||
if(WITH_FREERTOS)
|
||||
list(APPEND sources "tasklist.c")
|
||||
endif()
|
||||
|
||||
add_cunit_executable(cunit_ddsrt ${sources})
|
||||
target_link_libraries(
|
||||
cunit_ddsrt PRIVATE ddsrt)
|
||||
target_include_directories(
|
||||
cunit_ddsrt PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>")
|
||||
|
||||
# Create a separate test application that will be used to
|
||||
# test process management.
|
||||
add_executable(process_app process_app.c)
|
||||
target_link_libraries(process_app PRIVATE ddsrt)
|
||||
target_include_directories(
|
||||
process_app
|
||||
PRIVATE
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>")
|
||||
# Force the app to be at the same location, no matter what platform or build type.
|
||||
set_target_properties(
|
||||
process_app
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
# Let the cunit application know the location and name of the test application.
|
||||
set(process_app_name "${CMAKE_CURRENT_BINARY_DIR}/process_app${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
configure_file(
|
||||
"process_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/process_test.h" @ONLY)
|
||||
|
||||
|
||||
|
||||
# Create a separate shared library that will be used to
|
||||
# test dynamic library loading.
|
||||
|
@ -89,7 +62,7 @@ set_target_properties(
|
|||
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR}
|
||||
LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
# Use proper export for this test lib.
|
||||
generate_export_header(${test_lib_name} BASE_NAME LIB_TEST)
|
||||
#generate_dummy_export_header(${test_lib_name} BASE_NAME dds LIB_TEST)
|
||||
target_include_directories(${test_lib_name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
# Let the cunit application know the location and name of the library.
|
||||
file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" test_lib_native_dir)
|
||||
|
@ -112,3 +85,38 @@ foreach(libtest ${test_lib_tests})
|
|||
endif()
|
||||
endforeach()
|
||||
|
||||
generate_dummy_export_header(
|
||||
cunit_ddsrt
|
||||
BASE_NAME dds
|
||||
EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/export.h")
|
||||
|
||||
generate_dummy_export_header(
|
||||
${test_lib_name}
|
||||
BASE_NAME lib_test
|
||||
EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/lib_test_export.h")
|
||||
|
||||
if(HAVE_MULTI_PROCESS)
|
||||
# A separate application is required to test process management.
|
||||
add_executable(process_app process_app.c)
|
||||
target_link_libraries(process_app PRIVATE ddsrt)
|
||||
target_include_directories(
|
||||
process_app
|
||||
PRIVATE
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>")
|
||||
# Force the app to be at the same location, no matter what platform or build type.
|
||||
# FIXME: What if custom targets are added?
|
||||
# FIXME: What debug and release builds are mixed on Windows and macOS?
|
||||
set_target_properties(
|
||||
process_app
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
# Let the cunit application know the location and name of the test application.
|
||||
set(process_app_name "${CMAKE_CURRENT_BINARY_DIR}/process_app${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
configure_file(
|
||||
"process_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/process_test.h" @ONLY)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
|
||||
static int g_val = -1;
|
||||
|
||||
LIB_TEST_EXPORT void set_int(int val)
|
||||
LIB_TEST_EXPORT void set_int(int val);
|
||||
void set_int(int val)
|
||||
{
|
||||
g_val = val;
|
||||
}
|
||||
|
||||
LIB_TEST_EXPORT int get_int(void)
|
||||
LIB_TEST_EXPORT int get_int(void);
|
||||
int get_int(void)
|
||||
{
|
||||
return g_val;
|
||||
}
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#define TEST_ABORT_IF_NULL(var, msg) \
|
||||
do { \
|
||||
if (var == NULL) { \
|
||||
char buffer[256]; \
|
||||
r = ddsrt_dlerror(buffer, sizeof(buffer)); \
|
||||
char err[256]; \
|
||||
r = ddsrt_dlerror(err, sizeof(err)); \
|
||||
CU_ASSERT_EQUAL_FATAL(r, DDS_RETCODE_OK); \
|
||||
printf("\n%s", buffer); \
|
||||
printf("\n%s", err); \
|
||||
CU_FAIL_FATAL(msg); \
|
||||
} \
|
||||
} while(0)
|
||||
|
@ -39,7 +39,7 @@ do { \
|
|||
*/
|
||||
CU_Test(ddsrt_library, dlopen_path)
|
||||
{
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
|
||||
printf("Absolute lib: %s\n", TEST_LIB_ABSOLUTE);
|
||||
|
@ -54,7 +54,7 @@ CU_Test(ddsrt_library, dlopen_path)
|
|||
|
||||
CU_Test(ddsrt_library, dlopen_file)
|
||||
{
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
|
||||
r = ddsrt_dlopen(TEST_LIB_FILE, false, &l);
|
||||
|
@ -68,7 +68,7 @@ CU_Test(ddsrt_library, dlopen_file)
|
|||
|
||||
CU_Test(ddsrt_library, dlopen_name)
|
||||
{
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
|
||||
r = ddsrt_dlopen(TEST_LIB_NAME, true, &l);
|
||||
|
@ -83,7 +83,7 @@ CU_Test(ddsrt_library, dlopen_name)
|
|||
CU_Test(ddsrt_library, dlopen_unknown)
|
||||
{
|
||||
char buffer[256];
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
|
||||
r = ddsrt_dlopen("UnknownLib", false, &l);
|
||||
|
@ -97,7 +97,7 @@ CU_Test(ddsrt_library, dlopen_unknown)
|
|||
|
||||
CU_Test(ddsrt_library, dlsym)
|
||||
{
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
void* f;
|
||||
|
||||
|
@ -118,7 +118,7 @@ CU_Test(ddsrt_library, dlsym)
|
|||
CU_Test(ddsrt_library, dlsym_unknown)
|
||||
{
|
||||
char buffer[256];
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
void* f;
|
||||
|
||||
|
@ -146,7 +146,7 @@ CU_Test(ddsrt_library, call)
|
|||
int set_int = 1234;
|
||||
func_get_int f_get;
|
||||
func_set_int f_set;
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
|
||||
r = ddsrt_dlopen(TEST_LIB_NAME, true, &l);
|
||||
|
@ -171,7 +171,7 @@ CU_Test(ddsrt_library, call)
|
|||
|
||||
CU_Test(ddsrt_library, dlclose_error)
|
||||
{
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dynlib_t l;
|
||||
|
||||
r = ddsrt_dlopen(TEST_LIB_NAME, true, &l);
|
||||
|
@ -189,9 +189,10 @@ CU_Test(ddsrt_library, dlclose_error)
|
|||
CU_Test(ddsrt_library, dlerror_notfound)
|
||||
{
|
||||
char buffer[256];
|
||||
dds_retcode_t r;
|
||||
dds_return_t r;
|
||||
ddsrt_dlerror(buffer, sizeof(buffer));
|
||||
r = ddsrt_dlerror(buffer, sizeof(buffer));
|
||||
CU_ASSERT_EQUAL(r, DDS_RETCODE_NOT_FOUND);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ CU_TheoryDataPoints(ddsrt_environ, bad_name) = {
|
|||
|
||||
CU_Theory((const char *name), ddsrt_environ, bad_name)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
static const char value[] = "bar";
|
||||
static char dummy[] = "foobar";
|
||||
char *ptr;
|
||||
|
@ -40,7 +40,7 @@ CU_Theory((const char *name), ddsrt_environ, bad_name)
|
|||
DDSRT_WARNING_MSVC_OFF(4996)
|
||||
CU_Test(ddsrt_environ, setenv)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
static const char name[] = "foo";
|
||||
static char value[] = "bar";
|
||||
char *ptr;
|
||||
|
@ -64,7 +64,7 @@ DDSRT_WARNING_MSVC_ON(4996)
|
|||
|
||||
CU_Test(ddsrt_environ, getenv)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
static const char name[] = "foo";
|
||||
static const char value[] = "bar";
|
||||
static char dummy[] = "foobar";
|
||||
|
@ -111,7 +111,7 @@ CU_TheoryDataPoints(ddsrt_environ, expand) = {
|
|||
};
|
||||
CU_Theory((const char *var, const char *expect), ddsrt_environ, expand)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
static const char x_name[] = "X";
|
||||
static const char x_value[] = "TEST";
|
||||
static const char y_name[] = "Y";
|
||||
|
@ -131,7 +131,7 @@ CU_Theory((const char *var, const char *expect), ddsrt_environ, expand)
|
|||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
/* Expand a string with available environment variables. */
|
||||
ptr = ddsrt_expand_envvars(var);
|
||||
ptr = ddsrt_expand_envvars(var,UINT32_MAX);
|
||||
if (ptr) {
|
||||
/* printf("==== %10s: expand(%s), expect(%s))\n", var, ptr, expect); */
|
||||
CU_ASSERT_STRING_EQUAL(ptr, expect);
|
||||
|
@ -163,7 +163,7 @@ CU_TheoryDataPoints(ddsrt_environ, expand_sh) = {
|
|||
};
|
||||
CU_Theory((const char *var, const char *expect), ddsrt_environ, expand_sh)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
static const char x_name[] = "X";
|
||||
static const char x_value[] = "TEST";
|
||||
static const char y_name[] = "Y";
|
||||
|
@ -183,7 +183,7 @@ CU_Theory((const char *var, const char *expect), ddsrt_environ, expand_sh)
|
|||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
/* Expand a string with available environment variables. */
|
||||
ptr = ddsrt_expand_envvars_sh(var);
|
||||
ptr = ddsrt_expand_envvars_sh(var,UINT32_MAX);
|
||||
if (ptr) {
|
||||
/* printf("==== %10s: expand(%s), expect(%s))\n", var, ptr, expect); */
|
||||
CU_ASSERT_STRING_EQUAL(ptr, expect);
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
*
|
||||
* 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"
|
||||
#include "CUnit/Test.h"
|
||||
|
||||
/* FIXME: It's not possible to predict what network interfaces are available
|
||||
on a given host. To properly test all combinations the abstracted
|
||||
|
@ -64,7 +64,7 @@ CU_Clean(ddsrt_getifaddrs)
|
|||
IFF_LOOPBACK flags are properly set. */
|
||||
CU_Test(ddsrt_getifaddrs, ipv4)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
int seen = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
const int afs[] = { AF_INET, DDSRT_AF_TERM };
|
||||
|
@ -90,7 +90,7 @@ CU_Test(ddsrt_getifaddrs, ipv4)
|
|||
|
||||
CU_Test(ddsrt_getifaddrs, null_filter)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
int cnt = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
|
||||
|
@ -107,7 +107,7 @@ CU_Test(ddsrt_getifaddrs, null_filter)
|
|||
|
||||
CU_Test(ddsrt_getifaddrs, empty_filter)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_ifaddrs_t *ifa_root;
|
||||
const int afs[] = { DDSRT_AF_TERM };
|
||||
|
||||
|
@ -117,11 +117,11 @@ CU_Test(ddsrt_getifaddrs, empty_filter)
|
|||
ddsrt_freeifaddrs(ifa_root);
|
||||
}
|
||||
|
||||
#ifdef DDSRT_HAVE_IPV6
|
||||
CU_Test(ddsrt_getifaddrs, ipv6)
|
||||
{
|
||||
#ifdef DDSRT_HAVE_IPV6
|
||||
if (ipv6_enabled == 1) {
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
int have_ipv6 = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
const int afs[] = { AF_INET6, DDSRT_AF_TERM };
|
||||
|
@ -149,14 +149,18 @@ CU_Test(ddsrt_getifaddrs, ipv6)
|
|||
} else {
|
||||
CU_PASS("IPv6 disabled in test environment");
|
||||
}
|
||||
#else
|
||||
CU_PASS("IPv6 is not supported");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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 DDSRT_HAVE_IPV6
|
||||
if (ipv6_enabled == 1) {
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
int have_ipv4 = 0;
|
||||
int have_ipv6 = 0;
|
||||
ddsrt_ifaddrs_t *ifa_root, *ifa;
|
||||
|
@ -182,6 +186,8 @@ CU_Test(ddsrt_getifaddrs, ipv4_n_ipv6)
|
|||
} else {
|
||||
CU_PASS("IPv6 disabled in test environment");
|
||||
}
|
||||
#else
|
||||
CU_PASS("IPv6 is not supported");
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
}
|
||||
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
|
|
|
@ -311,8 +311,8 @@ static ddsrt_mutex_t mutex;
|
|||
struct arg {
|
||||
ddsrt_cond_t *cond;
|
||||
ddsrt_mutex_t *mutex;
|
||||
dds_time_t stamp;
|
||||
dds_duration_t pause;
|
||||
dds_time_t before;
|
||||
dds_time_t after;
|
||||
};
|
||||
|
||||
static void dummy(void *ptr, const dds_log_data_t *data)
|
||||
|
@ -326,10 +326,10 @@ 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();
|
||||
arg->before = dds_time();
|
||||
ddsrt_cond_broadcast(arg->cond);
|
||||
ddsrt_mutex_unlock(arg->mutex);
|
||||
dds_sleepfor(arg->pause);
|
||||
arg->after = dds_time();
|
||||
}
|
||||
|
||||
static uint32_t run(void *ptr)
|
||||
|
@ -347,17 +347,15 @@ static uint32_t run(void *ptr)
|
|||
CU_Test(dds_log, synchronous_sink_changes, .fini=reset)
|
||||
{
|
||||
struct arg arg;
|
||||
dds_time_t diff, stamp;
|
||||
ddsrt_thread_t tid;
|
||||
ddsrt_threadattr_t tattr;
|
||||
dds_retcode_t ret;
|
||||
dds_return_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);
|
||||
|
@ -366,9 +364,7 @@ CU_Test(dds_log, synchronous_sink_changes, .fini=reset)
|
|||
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);
|
||||
CU_ASSERT(arg.before < arg.after);
|
||||
CU_ASSERT(arg.after < dds_time());
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
static void create_and_test_exit(const char *arg, int code)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_pid_t pid;
|
||||
int32_t status;
|
||||
char *argv[] = { NULL, NULL };
|
||||
|
@ -64,7 +64,7 @@ CU_Test(ddsrt_process, create)
|
|||
*/
|
||||
CU_Test(ddsrt_process, kill)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_pid_t pid;
|
||||
|
||||
/* Sleep for 20 seconds. It should be killed before then. */
|
||||
|
@ -98,7 +98,7 @@ CU_Test(ddsrt_process, kill)
|
|||
*/
|
||||
CU_Test(ddsrt_process, pid)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_pid_t pid;
|
||||
int32_t status;
|
||||
char *argv[] = { TEST_PID_ARG, NULL };
|
||||
|
@ -126,7 +126,7 @@ CU_Test(ddsrt_process, pid)
|
|||
*/
|
||||
CU_Test(ddsrt_process, env)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
|
||||
ret = ddsrt_setenv(TEST_ENV_VAR_NAME, TEST_ENV_VAR_VALUE);
|
||||
CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK);
|
||||
|
@ -141,7 +141,7 @@ CU_Test(ddsrt_process, env)
|
|||
*/
|
||||
CU_Test(ddsrt_process, invalid)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_pid_t pid;
|
||||
|
||||
ret = ddsrt_proc_create("ProbablyNotAnValidExecutable", NULL, &pid);
|
||||
|
@ -177,7 +177,7 @@ CU_Test(ddsrt_process, arg_dquote)
|
|||
*/
|
||||
CU_Test(ddsrt_process, waitpids)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_pid_t child;
|
||||
ddsrt_pid_t pid1 = 0;
|
||||
ddsrt_pid_t pid2 = 0;
|
||||
|
@ -225,7 +225,7 @@ CU_Test(ddsrt_process, waitpids)
|
|||
*/
|
||||
CU_Test(ddsrt_process, waitpid_timeout)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_pid_t pid;
|
||||
|
||||
/* Sleep for 20 seconds. We should have a timeout before then. */
|
||||
|
@ -238,7 +238,7 @@ CU_Test(ddsrt_process, waitpid_timeout)
|
|||
ret = ddsrt_proc_waitpid(pid, 0, NULL);
|
||||
CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
|
||||
/* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */
|
||||
/* Valid timeout should return DDS_RETURN_TIMEOUT when alive. */
|
||||
ret = ddsrt_proc_waitpid(pid, DDS_SECS(1), NULL);
|
||||
CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT);
|
||||
|
||||
|
@ -257,7 +257,7 @@ CU_Test(ddsrt_process, waitpid_timeout)
|
|||
*/
|
||||
CU_Test(ddsrt_process, waitpids_timeout)
|
||||
{
|
||||
dds_retcode_t ret;
|
||||
dds_return_t ret;
|
||||
ddsrt_pid_t pid;
|
||||
|
||||
/* Sleep for 20 seconds. We should have a timeout before then. */
|
||||
|
@ -270,7 +270,7 @@ CU_Test(ddsrt_process, waitpids_timeout)
|
|||
ret = ddsrt_proc_waitpids(0, NULL, NULL);
|
||||
CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET);
|
||||
|
||||
/* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */
|
||||
/* Valid timeout should return DDS_RETURN_TIMEOUT when alive. */
|
||||
ret = ddsrt_proc_waitpids(DDS_SECS(1), NULL, NULL);
|
||||
CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT);
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
*
|
||||
* 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/cdtors.h"
|
||||
#include "dds/ddsrt/threads.h"
|
||||
#include "CUnit/Theory.h"
|
||||
|
||||
CU_Init(ddsrt_select)
|
||||
{
|
||||
|
@ -36,8 +36,13 @@ 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;
|
||||
dds_duration_t secs_max;
|
||||
DDSRT_STATIC_ASSERT (CHAR_BIT * sizeof (ddsrt_tv_sec_t) == 32 || CHAR_BIT * sizeof (ddsrt_tv_sec_t) == 64);
|
||||
if (CHAR_BIT * sizeof (ddsrt_tv_sec_t) == 32)
|
||||
secs_max = INT32_MAX;
|
||||
else
|
||||
secs_max = INT64_MAX;
|
||||
|
||||
if (DDS_INFINITY > secs_max) {
|
||||
CU_ASSERT_EQUAL_FATAL(secs_max, INT32_MAX);
|
||||
|
@ -107,40 +112,45 @@ typedef struct {
|
|||
static void
|
||||
sockets_pipe(ddsrt_socket_t socks[2])
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
ddsrt_socket_t sock;
|
||||
int reuseaddr = 1;
|
||||
|
||||
socklen_t addrlen;
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.sin_port = htons(54321);
|
||||
addr.sin_port = 0;
|
||||
|
||||
fprintf (stderr, "sockets_pipe ... begin\n");
|
||||
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);
|
||||
addrlen = (socklen_t) sizeof(addr);
|
||||
rc = ddsrt_getsockname(sock, (struct sockaddr *)&addr, &addrlen);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
fprintf (stderr, "sockets_pipe ... listen\n");
|
||||
rc = ddsrt_listen(sock, 1);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
fprintf (stderr, "sockets_pipe ... connect\n");
|
||||
rc = ddsrt_connect(socks[1], (struct sockaddr *)&addr, sizeof(addr));
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
fprintf (stderr, "sockets_pipe ... accept\n");
|
||||
rc = ddsrt_accept(sock, NULL, NULL, &socks[0]);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
ddsrt_close(sock);
|
||||
fprintf (stderr, "sockets_pipe ... done\n");
|
||||
}
|
||||
|
||||
static const char mesg[] = "foobar";
|
||||
|
||||
static uint32_t select_timeout_routine(void *ptr)
|
||||
{
|
||||
int cnt = -1;
|
||||
dds_retcode_t rc;
|
||||
int32_t cnt = -1;
|
||||
dds_return_t rc;
|
||||
dds_time_t before, after;
|
||||
dds_duration_t delay;
|
||||
fd_set rdset;
|
||||
|
@ -148,7 +158,13 @@ static uint32_t select_timeout_routine(void *ptr)
|
|||
uint32_t res = 0;
|
||||
|
||||
FD_ZERO(&rdset);
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_OFF(sign-conversion)
|
||||
#endif
|
||||
FD_SET(arg->sock, &rdset);
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_ON(sign-conversion)
|
||||
#endif
|
||||
|
||||
before = dds_time();
|
||||
rc = ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &cnt);
|
||||
|
@ -157,11 +173,15 @@ static uint32_t select_timeout_routine(void *ptr)
|
|||
|
||||
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);
|
||||
fprintf(stderr, "ddsrt_select returned %"PRId32"\n", rc);
|
||||
fprintf(stderr, "ddsrt_select reported %"PRId32" ready\n", cnt);
|
||||
|
||||
if (rc == DDS_RETCODE_TIMEOUT) {
|
||||
res = (((after - delay) >= (arg->delay - arg->skew)) && (cnt == 0));
|
||||
/* Running in the FreeRTOS simulator causes some trouble as interrupts are
|
||||
simulated using signals causing the select call to be interrupted. */
|
||||
} else if (rc == DDS_RETCODE_INTERRUPTED) {
|
||||
res = (cnt == -1);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -169,7 +189,7 @@ static uint32_t select_timeout_routine(void *ptr)
|
|||
|
||||
CU_Test(ddsrt_select, timeout)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
ddsrt_socket_t socks[2];
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
|
@ -178,23 +198,26 @@ CU_Test(ddsrt_select, timeout)
|
|||
|
||||
sockets_pipe(socks);
|
||||
|
||||
arg.delay = DDS_MSECS(100);
|
||||
arg.delay = DDS_MSECS(300);
|
||||
/* 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.skew = DDS_MSECS(50);
|
||||
arg.sock = socks[0];
|
||||
|
||||
fprintf (stderr, "create thread\n");
|
||||
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. */
|
||||
fprintf (stderr, "write data\n");
|
||||
ssize_t sent = 0;
|
||||
rc = ddsrt_send(socks[1], mesg, sizeof(mesg), 0, &sent);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
fprintf (stderr, "join thread\n");
|
||||
rc = ddsrt_thread_join(thr, &res);
|
||||
CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK);
|
||||
CU_ASSERT_EQUAL(res, 1);
|
||||
|
@ -207,13 +230,19 @@ static uint32_t recv_routine(void *ptr)
|
|||
{
|
||||
thread_arg_t *arg = (thread_arg_t*)ptr;
|
||||
|
||||
int nfds = 0;
|
||||
int32_t nfds = 0;
|
||||
fd_set rdset;
|
||||
ssize_t rcvd = -1;
|
||||
char buf[sizeof(mesg)];
|
||||
|
||||
FD_ZERO(&rdset);
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_OFF(sign-conversion)
|
||||
#endif
|
||||
FD_SET(arg->sock, &rdset);
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_ON(sign-conversion)
|
||||
#endif
|
||||
|
||||
(void)ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &nfds);
|
||||
|
||||
|
@ -226,7 +255,7 @@ static uint32_t recv_routine(void *ptr)
|
|||
|
||||
CU_Test(ddsrt_select, send_recv)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
ddsrt_socket_t socks[2];
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
|
@ -260,7 +289,7 @@ static uint32_t recvmsg_routine(void *ptr)
|
|||
{
|
||||
thread_arg_t *arg = (thread_arg_t*)ptr;
|
||||
|
||||
int nfds = 0;
|
||||
int32_t nfds = 0;
|
||||
fd_set rdset;
|
||||
ssize_t rcvd = -1;
|
||||
char buf[sizeof(mesg)];
|
||||
|
@ -274,7 +303,13 @@ static uint32_t recvmsg_routine(void *ptr)
|
|||
msg.msg_iovlen = 1;
|
||||
|
||||
FD_ZERO(&rdset);
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_OFF(sign-conversion)
|
||||
#endif
|
||||
FD_SET(arg->sock, &rdset);
|
||||
#if LWIP_SOCKET
|
||||
DDSRT_WARNING_GNUC_ON(sign-conversion)
|
||||
#endif
|
||||
|
||||
(void)ddsrt_select(arg->sock + 1, &rdset, NULL, NULL, arg->delay, &nfds);
|
||||
|
||||
|
@ -287,7 +322,7 @@ static uint32_t recvmsg_routine(void *ptr)
|
|||
|
||||
CU_Test(ddsrt_select, sendmsg_recvmsg)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
ddsrt_socket_t socks[2];
|
||||
ddsrt_thread_t thr;
|
||||
ddsrt_threadattr_t attr;
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
*
|
||||
* 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/sockets.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"
|
||||
#include "dds/ddsrt/string.h"
|
||||
#include "CUnit/Theory.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
DDSRT_WARNING_MSVC_OFF(4305)
|
||||
#if DDSRT_ENDIAN == DDSRT_BIG_ENDIAN
|
||||
|
@ -48,15 +48,15 @@ static void teardown(void)
|
|||
|
||||
CU_Test(ddsrt_sockaddrfromstr, bad_family)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_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)
|
||||
static void sockaddrfromstr_test(char *str, int af, dds_return_t exp)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
struct sockaddr_storage ss;
|
||||
rc = ddsrt_sockaddrfromstr(af, str, &ss);
|
||||
CU_ASSERT_EQUAL(rc, exp);
|
||||
|
@ -70,37 +70,44 @@ CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv4) = {
|
|||
"nip"),
|
||||
CU_DataPoints(int, AF_INET, AF_INET,
|
||||
AF_INET),
|
||||
CU_DataPoints(dds_retcode_t, DDS_RETCODE_OK, DDS_RETCODE_OK,
|
||||
CU_DataPoints(dds_return_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)
|
||||
CU_Theory((char *str, int af, dds_return_t exp), ddsrt_sockaddrfromstr, ipv4, .init=setup, .fini=teardown)
|
||||
{
|
||||
sockaddrfromstr_test(str, af, exp);
|
||||
}
|
||||
|
||||
#if DDSRT_HAVE_IPV6
|
||||
CU_TheoryDataPoints(ddsrt_sockaddrfromstr, ipv6) = {
|
||||
#if DDSRT_HAVE_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,
|
||||
CU_DataPoints(dds_return_t, DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK,
|
||||
DDS_RETCODE_BAD_PARAMETER, DDS_RETCODE_OK,
|
||||
DDS_RETCODE_BAD_PARAMETER)
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
};
|
||||
|
||||
CU_Theory((char *str, int af, dds_retcode_t exp), ddsrt_sockaddrfromstr, ipv6, .init=setup, .fini=teardown)
|
||||
CU_Theory((char *str, int af, dds_return_t exp), ddsrt_sockaddrfromstr, ipv6, .init=setup, .fini=teardown)
|
||||
{
|
||||
#if DDSRT_HAVE_IPV6
|
||||
sockaddrfromstr_test(str, af, exp);
|
||||
}
|
||||
#else
|
||||
(void)str;
|
||||
(void)af;
|
||||
(void)exp;
|
||||
CU_PASS("IPV6 is not supported");
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sockaddrtostr, bad_sockaddr, .init=setup, .fini=teardown)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
char buf[128] = { 0 };
|
||||
struct sockaddr_in sa;
|
||||
memcpy(&sa, &ipv4_loopback, sizeof(ipv4_loopback));
|
||||
|
@ -111,7 +118,7 @@ CU_Test(ddsrt_sockaddrtostr, bad_sockaddr, .init=setup, .fini=teardown)
|
|||
|
||||
CU_Test(ddsrt_sockaddrtostr, no_space, .init=setup, .fini=teardown)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
char buf[1] = { 0 };
|
||||
rc = ddsrt_sockaddrtostr(&ipv4_loopback, buf, sizeof(buf));
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_NOT_ENOUGH_SPACE);
|
||||
|
@ -119,7 +126,7 @@ CU_Test(ddsrt_sockaddrtostr, no_space, .init=setup, .fini=teardown)
|
|||
|
||||
CU_Test(ddsrt_sockaddrtostr, ipv4)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
char buf[128] = { 0 };
|
||||
rc = ddsrt_sockaddrtostr(&ipv4_loopback, buf, sizeof(buf));
|
||||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
|
@ -128,17 +135,20 @@ CU_Test(ddsrt_sockaddrtostr, ipv4)
|
|||
|
||||
CU_Test(ddsrt_sockaddrtostr, ipv6)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
#if DDSRT_HAVE_IPV6
|
||||
dds_return_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");
|
||||
#else
|
||||
CU_PASS("IPv6 is not supported");
|
||||
#endif
|
||||
}
|
||||
|
||||
CU_Test(ddsrt_sockets, gethostname)
|
||||
{
|
||||
int ret;
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
char sysbuf[200], buf[200];
|
||||
|
||||
buf[0] = '\0';
|
||||
|
@ -146,8 +156,12 @@ CU_Test(ddsrt_sockets, gethostname)
|
|||
CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK);
|
||||
|
||||
sysbuf[0] = '\0';
|
||||
ret = gethostname(sysbuf, sizeof(sysbuf));
|
||||
#if LWIP_SOCKET
|
||||
ddsrt_strlcpy(sysbuf, "localhost", sizeof(sysbuf));
|
||||
#else
|
||||
int ret = gethostname(sysbuf, sizeof(sysbuf));
|
||||
CU_ASSERT_EQUAL(ret, 0);
|
||||
#endif
|
||||
CU_ASSERT(strcmp(buf, sysbuf) == 0);
|
||||
|
||||
rc = ddsrt_gethostname(buf, strlen(buf) - 1);
|
||||
|
@ -155,9 +169,9 @@ CU_Test(ddsrt_sockets, gethostname)
|
|||
}
|
||||
|
||||
#if DDSRT_HAVE_DNS
|
||||
static void gethostbyname_test(char *name, int af, dds_retcode_t exp)
|
||||
static void gethostbyname_test(char *name, int af, dds_return_t exp)
|
||||
{
|
||||
dds_retcode_t rc;
|
||||
dds_return_t rc;
|
||||
ddsrt_hostent_t *hent = NULL;
|
||||
rc = ddsrt_gethostbyname(name, af, &hent);
|
||||
CU_ASSERT_EQUAL(rc, exp);
|
||||
|
@ -169,30 +183,44 @@ static void gethostbyname_test(char *name, int af, dds_retcode_t exp)
|
|||
}
|
||||
ddsrt_free(hent);
|
||||
}
|
||||
#endif
|
||||
|
||||
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_DataPoints(dds_return_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)
|
||||
CU_Theory((char *name, int af, dds_return_t exp), ddsrt_gethostbyname, ipv4, .init=setup, .fini=teardown)
|
||||
{
|
||||
#if DDSRT_HAVE_DNS
|
||||
gethostbyname_test(name, af, exp);
|
||||
#else
|
||||
(void)name;
|
||||
(void)af;
|
||||
(void)exp;
|
||||
CU_PASS("DNS is not supported");
|
||||
#endif
|
||||
}
|
||||
|
||||
#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) = {
|
||||
#if DDSRT_HAVE_IPV6 && DDSRT_HAVE_DNS
|
||||
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_DataPoints(dds_return_t, DDS_RETCODE_HOST_NOT_FOUND, DDS_RETCODE_OK, DDS_RETCODE_OK)
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
};
|
||||
|
||||
CU_Theory((char *name, int af, dds_retcode_t exp), ddsrt_gethostbyname, ipv6, .init=setup, .fini=teardown)
|
||||
CU_Theory((char *name, int af, dds_return_t exp), ddsrt_gethostbyname, ipv6, .init=setup, .fini=teardown)
|
||||
{
|
||||
#if DDSRT_HAVE_IPV6 && DDSRT_HAVE_DNS
|
||||
gethostbyname_test(name, af, exp);
|
||||
}
|
||||
#else
|
||||
(void)name;
|
||||
(void)af;
|
||||
(void)exp;
|
||||
CU_PASS("DNS and IPv6 are not supported");
|
||||
#endif /* DDSRT_HAVE_IPV6 */
|
||||
#endif /* DDSRT_HAVE_DNS */
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue