diff --git a/rcl/CMakeLists.txt b/rcl/CMakeLists.txt index b600c5b..92d6b8e 100644 --- a/rcl/CMakeLists.txt +++ b/rcl/CMakeLists.txt @@ -34,7 +34,9 @@ ament_target_dependencies(${PROJECT_NAME} "rmw" "rosidl_generator_c" ) -set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-std=c11") +if(NOT WIN32) + set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-std=c11") +endif() if(AMENT_ENABLE_TESTING) find_package(ament_cmake_gtest REQUIRED) @@ -42,58 +44,64 @@ if(AMENT_ENABLE_TESTING) ament_lint_auto_find_test_dependencies() set(extra_test_libraries) + set(extra_memory_tools_env PHONY=) # Use a phony env var so there is always at least one. ament_find_gtest() # For GTEST_LIBRARIES if(APPLE) add_library(${PROJECT_NAME}_memory_tools_interpose SHARED test/memory_tools_osx_interpose.cpp) target_link_libraries(${PROJECT_NAME}_memory_tools_interpose ${GTEST_LIBRARIES}) - set_target_properties(${PROJECT_NAME}_memory_tools_interpose PROPERTIES COMPILE_FLAGS "-std=c++11") + set_target_properties(${PROJECT_NAME}_memory_tools_interpose + PROPERTIES COMPILE_FLAGS "-std=c++11") list(APPEND extra_test_libraries ${PROJECT_NAME}_memory_tools_interpose) + list(APPEND extra_memory_tools_env + DYLD_INSERT_LIBRARIES=$) endif() add_library(${PROJECT_NAME}_memory_tools SHARED test/memory_tools.cpp) - set_target_properties(${PROJECT_NAME}_memory_tools PROPERTIES COMPILE_FLAGS "-std=c++11") + if(NOT WIN32) + set_target_properties(${PROJECT_NAME}_memory_tools PROPERTIES COMPILE_FLAGS "-std=c++11") + endif() target_link_libraries(${PROJECT_NAME}_memory_tools ${GTEST_LIBRARIES} ${extra_test_libraries}) list(APPEND extra_test_libraries ${PROJECT_NAME}_memory_tools) - ament_add_gtest(test_memory_tools - test/test_memory_tools.cpp - ENV DYLD_INSERT_LIBRARIES=$) + ament_add_gtest(test_memory_tools test/test_memory_tools.cpp ENV ${extra_memory_tools_env}) if(TARGET test_memory_tools) target_include_directories(test_memory_tools PUBLIC ${rcl_interfaces_INCLUDE_DIRS} ${rmw_INCLUDE_DIRS} ) - set_target_properties(test_memory_tools PROPERTIES COMPILE_FLAGS "-std=c++11") + if(NOT WIN32) + set_target_properties(test_memory_tools PROPERTIES COMPILE_FLAGS "-std=c++11") + endif() target_link_libraries(test_memory_tools ${PROJECT_NAME} ${extra_test_libraries}) endif() - ament_add_gtest(test_allocator - test/rcl/test_allocator.cpp - ENV DYLD_INSERT_LIBRARIES=$) + ament_add_gtest(test_allocator test/rcl/test_allocator.cpp ENV ${extra_memory_tools_env}) if(TARGET test_allocator) target_include_directories(test_allocator PUBLIC ${rcl_interfaces_INCLUDE_DIRS} ${rmw_INCLUDE_DIRS} ) - set_target_properties(test_allocator PROPERTIES COMPILE_FLAGS "-std=c++11") + if(NOT WIN32) + set_target_properties(test_allocator PROPERTIES COMPILE_FLAGS "-std=c++11") + endif() target_link_libraries(test_allocator ${PROJECT_NAME} ${extra_test_libraries}) endif() - ament_add_gtest(test_time - test/rcl/test_time.cpp - ENV DYLD_INSERT_LIBRARIES=$) + ament_add_gtest(test_time test/rcl/test_time.cpp ENV ${extra_memory_tools_env}) if(TARGET test_time) target_include_directories(test_time PUBLIC ${rcl_interfaces_INCLUDE_DIRS} ${rmw_INCLUDE_DIRS} ) - set_target_properties(test_time PROPERTIES COMPILE_FLAGS "-std=c++11") + if(NOT WIN32) + set_target_properties(test_time PROPERTIES COMPILE_FLAGS "-std=c++11") + endif() target_link_libraries(test_time ${PROJECT_NAME} ${extra_test_libraries}) endif() ament_add_gtest(test_common test/rcl/test_common.cpp ENV - DYLD_INSERT_LIBRARIES=$ + ${extra_memory_tools_env} EMPTY_TEST= NORMAL_TEST=foo ) @@ -102,7 +110,9 @@ if(AMENT_ENABLE_TESTING) ${rcl_interfaces_INCLUDE_DIRS} ${rmw_INCLUDE_DIRS} ) - set_target_properties(test_common PROPERTIES COMPILE_FLAGS "-std=c++11") + if(NOT WIN32) + set_target_properties(test_common PROPERTIES COMPILE_FLAGS "-std=c++11") + endif() target_link_libraries(test_common ${PROJECT_NAME} ${extra_test_libraries}) endif() endif() diff --git a/rcl/src/rcl/common.c b/rcl/src/rcl/common.c index cae778c..89a667f 100644 --- a/rcl/src/rcl/common.c +++ b/rcl/src/rcl/common.c @@ -36,7 +36,7 @@ rcl_impl_getenv(const char * env_name, const char ** env_value) *env_value = getenv(env_name); #else size_t required_size; - error_t ret = getenv_s(&required_size, __env_buffer, sizeof(__env_buffer), env_name); + errno_t ret = getenv_s(&required_size, __env_buffer, sizeof(__env_buffer), env_name); if (ret != 0) { RCL_SET_ERROR_MSG("value in env variable too large to read in"); return RCL_RET_ERROR; diff --git a/rcl/src/rcl/rcl.c b/rcl/src/rcl/rcl.c index 53d4b25..da8c303 100644 --- a/rcl/src/rcl/rcl.c +++ b/rcl/src/rcl/rcl.c @@ -19,19 +19,23 @@ extern "C" #include "rcl/rcl.h" +#ifndef WIN32 #include +#else +#include "./stdatomic/win32/stdatomic.h" +#endif #include #include "rcl/error_handling.h" -static atomic_bool __rcl_is_initialized = false; +static atomic_bool __rcl_is_initialized = ATOMIC_VAR_INIT(false); static rcl_allocator_t __rcl_allocator = {0}; static int __rcl_argc = 0; static char ** __rcl_argv = NULL; -static atomic_uint_fast64_t __rcl_instance_id = 0; +static atomic_uint_fast64_t __rcl_instance_id = ATOMIC_VAR_INIT(0); static uint64_t __rcl_next_unique_id = 0; -static inline void +static void __clean_up_init() { if (__rcl_argv) { diff --git a/rcl/src/rcl/stdatomic_helper/win32/stdatomic.h b/rcl/src/rcl/stdatomic_helper/win32/stdatomic.h new file mode 100644 index 0000000..0fa16ac --- /dev/null +++ b/rcl/src/rcl/stdatomic_helper/win32/stdatomic.h @@ -0,0 +1,325 @@ +/* + * An implementation of C11 stdatomic.h for Win32, part borrowed from FreeBSD + * (original copyright follows), with major modifications for + * portability to Win32 systems. + * + * Caveats and limitations: + * - Only the ``_Atomic parentheses'' notation is implemented, while + * the ``_Atomic space'' one is not. + * - _Atomic types must be typedef'ed, or programs using them will + * not type check correctly (incompatible anonymous structure + * types). + * - Support is limited to 16, 32, and 64 bit types only. + * - Stripped down to only the functions used locally in rcl. + */ + +/*- + * Copyright (c) 2011 Ed Schouten + * David Chisnall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/include/stdatomic.h,v 1.10.2.2 2012/05/30 19:21:54 theraven Exp $ + */ + +#ifndef _STDATOMIC_H_ +#define _STDATOMIC_H_ + +#include + +#include +#include + +#if !defined(WIN32) +#error "this stdatomic.h does not support your compiler" +#endif + +// In MSVC, correct alignment of each type is already ensured. +#define _Atomic(T) struct { T __val; } + +/* + * 7.17.2 Initialization. + */ + +#define ATOMIC_VAR_INIT(value) { .__val = (value) } +#define atomic_init(obj, value) do { \ + (obj)->__val = (value); \ +} while (0) + +/* + * Clang and recent GCC both provide predefined macros for the memory + * orderings. If we are using a compiler that doesn't define them, use the + * clang values - these will be ignored in the fallback path. + */ + +#ifndef __ATOMIC_RELAXED +#define __ATOMIC_RELAXED 0 +#endif +#ifndef __ATOMIC_CONSUME +#define __ATOMIC_CONSUME 1 +#endif +#ifndef __ATOMIC_ACQUIRE +#define __ATOMIC_ACQUIRE 2 +#endif +#ifndef __ATOMIC_RELEASE +#define __ATOMIC_RELEASE 3 +#endif +#ifndef __ATOMIC_ACQ_REL +#define __ATOMIC_ACQ_REL 4 +#endif +#ifndef __ATOMIC_SEQ_CST +#define __ATOMIC_SEQ_CST 5 +#endif + +/* + * 7.17.3 Order and consistency. + * + * The memory_order_* constants that denote the barrier behaviour of the + * atomic operations. + */ + +enum memory_order { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +}; + +typedef enum memory_order memory_order; + +/* + * 7.17.4 Fences. + */ + +#define atomic_thread_fence(order) MemoryBarrier() +#define atomic_signal_fence(order) _ReadWriteBarrier() + +/* + * 7.17.5 Lock-free property. + */ + +#define atomic_is_lock_free(obj) (sizeof((obj)->__val) <= sizeof(void *)) + +/* + * 7.17.6 Atomic integer types. + */ + +typedef _Atomic(_Bool) atomic_bool; +typedef _Atomic(char) atomic_char; +typedef _Atomic(signed char) atomic_schar; +typedef _Atomic(unsigned char) atomic_uchar; +typedef _Atomic(short) atomic_short; +typedef _Atomic(unsigned short) atomic_ushort; +typedef _Atomic(int) atomic_int; +typedef _Atomic(unsigned int) atomic_uint; +typedef _Atomic(long) atomic_long; +typedef _Atomic(unsigned long) atomic_ulong; +typedef _Atomic(long long) atomic_llong; +typedef _Atomic(unsigned long long) atomic_ullong; +#if 0 +typedef _Atomic(char16_t) atomic_char16_t; +typedef _Atomic(char32_t) atomic_char32_t; +typedef _Atomic(wchar_t) atomic_wchar_t; +typedef _Atomic(int_least8_t) atomic_int_least8_t; +typedef _Atomic(uint_least8_t) atomic_uint_least8_t; +#endif +typedef _Atomic(int_least16_t) atomic_int_least16_t; +typedef _Atomic(uint_least16_t) atomic_uint_least16_t; +typedef _Atomic(int_least32_t) atomic_int_least32_t; +typedef _Atomic(uint_least32_t) atomic_uint_least32_t; +typedef _Atomic(int_least64_t) atomic_int_least64_t; +typedef _Atomic(uint_least64_t) atomic_uint_least64_t; +#if 0 +typedef _Atomic(int_fast8_t) atomic_int_fast8_t; +typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t; +#endif +typedef _Atomic(int_fast16_t) atomic_int_fast16_t; +typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t; +typedef _Atomic(int_fast32_t) atomic_int_fast32_t; +typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t; +typedef _Atomic(int_fast64_t) atomic_int_fast64_t; +typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t; +typedef _Atomic(intptr_t) atomic_intptr_t; +typedef _Atomic(uintptr_t) atomic_uintptr_t; +typedef _Atomic(size_t) atomic_size_t; +typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t; +typedef _Atomic(intmax_t) atomic_intmax_t; +typedef _Atomic(uintmax_t) atomic_uintmax_t; + +/* + * 7.17.7 Operations on atomic types. (pruned modified for Windows' crappy C compiler) + */ + +#define rcl_win32_atomic_compare_exchange_strong(object, out, expected, desired) \ + do { \ + switch(sizeof(object)) { \ + case sizeof(uint64_t): \ + out = _InterlockedCompareExchange64((LONGLONG *) object, desired, expected); \ + break; \ + case sizeof(uint32_t): \ + out = _InterlockedCompareExchange((LONG *) object, desired, expected); \ + break; \ + case sizeof(uint16_t): \ + out = _InterlockedCompareExchange16((SHORT *) object, desired, expected); \ + break; \ + default: \ + break; \ + }; \ + } while(0) + +#define rcl_win32_atomic_compare_exchange_weak(object, out, expected, desired) \ + rcl_win32_atomic_compare_exchange_strong(object, out, expected, desired) + +#define rcl_win32_atomic_exchange((object), out, desired) \ + do { \ + switch(sizeof(object)) { \ + case sizeof(uint64_t): \ + out = _InterlockedExchange64((LONGLONG *) object, desired); \ + break; \ + case sizeof(uint32_t): \ + out = _InterlockedExchange((LONG *) object, desired); \ + break; \ + case sizeof(uint16_t): \ + out = _InterlockedExchange16((SHORT *) object, desired); \ + break; \ + default: \ + break; \ + }; \ + } while(0) + +#define rcl_win32_atomic_fetch_add(object, out, operand) \ + do { \ + switch(sizeof(object)) { \ + case sizeof(uint64_t): \ + out = _InterlockedExchangeAdd64((LONGLONG *) object, operand); \ + break; \ + case sizeof(uint32_t): \ + out = _InterlockedExchangeAdd((LONG *) object, operand); \ + break; \ + case sizeof(uint16_t): \ + out = _InterlockedExchangeAdd16((SHORT *) object, operand); \ + break; \ + default: \ + break; \ + }; \ + } while(0) + +#define rcl_win32_atomic_fetch_and(object, out, operand) \ + do { \ + switch(sizeof(object)) { \ + case sizeof(uint64_t): \ + out = _InterlockedAnd64((LONGLONG *) object, operand); \ + break; \ + case sizeof(uint32_t): \ + out = _InterlockedAnd((LONG *) object, operand); \ + break; \ + case sizeof(uint16_t): \ + out = _InterlockedAnd16((SHORT *) object, operand); \ + break; \ + default: \ + break; \ + }; \ + } while(0) + +#define rcl_win32_atomic_fetch_or(object, out, operand) \ + do { \ + switch(sizeof(object)) { \ + case sizeof(uint64_t): \ + out = _InterlockedOr64((LONGLONG *) object, operand); \ + break; \ + case sizeof(uint32_t): \ + out = _InterlockedOr((LONG *) object, operand); \ + break; \ + case sizeof(uint16_t): \ + out = _InterlockedOr16((SHORT *) object, operand); \ + break; \ + default: \ + break; \ + }; \ + } while(0) + +#define rcl_win32_atomic_fetch_sub(object, out, operand) \ + rcl_win32_atomic_fetch_add(object, out, -(operand)) + +#define rcl_win32_atomic_fetch_xor(object, out, operand) \ + do { \ + switch(sizeof(object)) { \ + case sizeof(uint64_t): \ + out = _InterlockedXor64((LONGLONG *) object, operand); \ + break; \ + case sizeof(uint32_t): \ + out = _InterlockedXor((LONG *) object, operand); \ + break; \ + case sizeof(uint16_t): \ + out = _InterlockedXor16((SHORT *) object, operand); \ + break; \ + default: \ + break; \ + }; \ + } while(0) + +#define rcl_win32_atomic_load(object) \ + do { \ + switch(sizeof(object)) { \ + case sizeof(uint64_t): \ + out = _InterlockedExchangeAdd64((LONGLONG *) object, 0); \ + break; \ + case sizeof(uint32_t): \ + out = _InterlockedExchangeAdd((LONG *) object, 0); \ + break; \ + case sizeof(uint16_t): \ + out = _InterlockedExchangeAdd16((SHORT *) object, 0); \ + break; \ + default: \ + break; \ + }; \ + } while(0) + +#define rcl_win32_atomic_store(object, desired) \ + do { \ + MemoryBarrier(); \ + object = (desired); \ + MemoryBarrier(); \ + } while (0) + +/* + * 7.17.8 Atomic flag type and operations. (disabled for now) + */ + +// typedef atomic_bool atomic_flag; + +// #define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0) + +// #define atomic_flag_clear_explicit(object, order) \ +// atomic_store_explicit(object, 0, order) +// #define atomic_flag_test_and_set_explicit(object, order) \ +// atomic_compare_exchange_strong_explicit(object, 0, 1, order, order) + +// #define atomic_flag_clear(object) \ +// atomic_flag_clear_explicit(object, memory_order_seq_cst) +// #define atomic_flag_test_and_set(object) \ +// atomic_flag_test_and_set_explicit(object, memory_order_seq_cst) + +#endif /* !_STDATOMIC_H_ */ diff --git a/rcl/src/rcl/stdatomics_helper.h b/rcl/src/rcl/stdatomics_helper.h new file mode 100644 index 0000000..a7d2352 --- /dev/null +++ b/rcl/src/rcl/stdatomics_helper.h @@ -0,0 +1,26 @@ +// Copyright 2015 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCL__STDATOMICS_HELPER_H_ +#define RCL__STDATOMICS_HELPER_H_ + +#if !defined(WIN32) + + + +#else + +#endif + +#endif // RCL__STDATOMICS_HELPER_H_