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