diff --git a/CMakeLists.txt b/CMakeLists.txt index c443536..a6458fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,7 @@ option(INSTALL_DOCS "Specify whether Doxygen docs should be installed" ON) option(WARNINGS_ARE_ERRORS "Specify whether warnings should be treated as errors" OFF) option(USE_AUTOMATIC_INITIALIZATION "Specify whether the MTAPI C++ interface, algorithms and dataflow should automatically intialize the MTAPI node if no explicit initialization is present" ON) option(BUILD_OPENCL_PLUGIN "Specify whether the MTAPI OpenCL plugin should be built" OFF) +option(THREADING_ANALYSIS_MODE "Replaces lock-free synchronization constructs by mutex-based implementations to support threading analysis tools" OFF) ## LOCAL INSTALLATION OF SUBPROJECT BINARIES # @@ -106,6 +107,14 @@ else() endif() message(" (set with command line option -DUSE_AUTOMATIC_INITIALIZATION=ON/OFF)") +if (THREADING_ANALYSIS_MODE STREQUAL ON) + set(EMBB_THREADING_ANALYSIS_MODE 1) + message("-- Threading analysis mode enabled") +else() + message("-- Threading analysis mode disabled (default") +endif() +message(" (set with command line option -DTHREADING_ANALYSIS_MODE=ON/OFF)") + include(CMakeCommon/SetCompilerFlags.cmake) SetGNUCompilerFlags(compiler_libs compiler_flags) SetVisualStudioCompilerFlags(compiler_libs compiler_flags) diff --git a/README.md b/README.md index 1d3ef9f..cfd367d 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,9 @@ EMB² can be built with C++ exception handling (default) or without exceptions. Similarly, automatic initialization of the task scheduler by the MTAPI C++ interface can be disabled with `-DUSE_AUTOMATIC_INITIALIZATION=OFF`. This way, unexpected delays after startup can be avoided, e.g. for timing measurements. +Furthermore, EMB² can be built to work with threading analysis tools such as Helgrind or ThreadSanitizer with -DTHREADING_ANALYSIS_MODE=ON. This uses mutexes around atomics to avoid false positives but degrades performance significantly. + + The tutorial of EMB² comes with a number of examples in `doc/examples/`. These can be built with the other source files using the option `-DBUILD_EXAMPLES=ON`. Note, however, that the examples use C++11 features and require an appropriate compiler. By default, the included unit tests are built as part of the installation process. To override the default behavior, add the option `-DBUILD_TESTS=OFF`. diff --git a/algorithms_cpp/test/main.cc b/algorithms_cpp/test/main.cc index 3d5a733..dcebf96 100644 --- a/algorithms_cpp/test/main.cc +++ b/algorithms_cpp/test/main.cc @@ -46,6 +46,8 @@ #include #include +#include + #define THIS_DOMAIN_ID 1 #define THIS_NODE_ID 1 @@ -81,7 +83,4 @@ PT_MAIN("Algorithms") { embb::mtapi::Node::Finalize(); PT_EXPECT(embb_get_bytes_allocated() == 0); - - // std::cout << "please press return to continue..." << std::endl; - // std::cin.get(); } diff --git a/base_c/include/embb/base/c/atomic.h b/base_c/include/embb/base/c/atomic.h index b00b337..c32e563 100644 --- a/base_c/include/embb/base/c/atomic.h +++ b/base_c/include/embb/base/c/atomic.h @@ -85,9 +85,41 @@ #ifdef DOXYGEN /** + * Initializes an atomic variable. + * + * \pre The atomic variable has not been initialized. + * \post The atomic variable has the value \c initial_value and can be used in + * atomic operations. + * + * \ingroup C_BASE_ATOMIC + * \notthreadsafe + */ +void embb_atomic_init_TYPE( + emb_atomic_TYPE* variable, + /**< [IN,OUT] Pointer to atomic variable to be initialized. */ + TYPE initial_value + /**< [IN] Initial value to be assigned to atomic variable. */ + ); + +/** + * Destroys an atomic variable and frees its resources. + * + * \pre The atomic variable has been initialized. + * \post The atomic variable is uninitialized. + * + * \ingroup C_BASE_ATOMIC + * \notthreadsafe + */ +void embb_atomic_destroy_TYPE( + emb_atomic_TYPE* variable + /**< [IN,OUT] Pointer to atomic variable to be destroyed. */ + ); + +/** * Computes the logical "and" of the value stored in \p variable and \c value. * - * The result is stored in \p variable. + * \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE + * \post The result is stored in \p variable. * * \see \ref general_desc_atomic_base "Detailed description" for general * information and the meaning of \b TYPE. @@ -95,12 +127,12 @@ * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE void embb_atomic_and_assign_TYPE( +void embb_atomic_and_assign_TYPE( embb_atomic_TYPE* variable, /**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for the "and" operation and is used to store the result. */ TYPE value - /** [IN] Right-hand side of "and" operation, passed by value */ + /**< [IN] Right-hand side of "and" operation, passed by value */ ); /** @@ -111,6 +143,8 @@ EMBB_PLATFORM_INLINE void embb_atomic_and_assign_TYPE( * to the value of \p expected. Otherwise, stores the value of \p variable in * \p expected. * + * \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE + * * \return != 0 if the values of \p variable and \p expected were equivalent \n * 0 otherwise * @@ -120,7 +154,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_and_assign_TYPE( * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE int embb_atomic_compare_and_swap_TYPE( +int embb_atomic_compare_and_swap_TYPE( embb_atomic_TYPE* variable, /**< [IN,OUT] Pointer to atomic variable */ TYPE* expected, @@ -132,6 +166,8 @@ EMBB_PLATFORM_INLINE int embb_atomic_compare_and_swap_TYPE( /** * Adds \p value to \p variable and returns its old value. * + * \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE + * * \return The value before the operation * * \see \ref general_desc_atomic_base "Detailed description" for general @@ -140,7 +176,7 @@ EMBB_PLATFORM_INLINE int embb_atomic_compare_and_swap_TYPE( * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE( +TYPE embb_atomic_fetch_and_add_TYPE( embb_atomic_TYPE* variable, /**< [IN,OUT] Pointer to atomic variable*/ TYPE value @@ -150,6 +186,8 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE( /** * Loads the value of \p variable and returns it. * + * \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE + * * \return The value of the atomic variable. * * \see \ref general_desc_atomic_base "Detailed description" for general @@ -158,7 +196,7 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE( * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE TYPE embb_atomic_load_TYPE( +TYPE embb_atomic_load_TYPE( const embb_atomic_TYPE* variable /**< [IN] Pointer to atomic variable */ ); @@ -169,12 +207,13 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_load_TYPE( * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE void embb_atomic_memory_barrier(); +void embb_atomic_memory_barrier(); /** * Computes the logical "or" of the value stored in \p variable and \c value. * - * The result is stored in \p variable. + * \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE + * \post The result is stored in \p variable. * * \see \ref general_desc_atomic_base "Detailed description" for general * information and the meaning of \b TYPE. @@ -182,7 +221,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_memory_barrier(); * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE void embb_atomic_or_assign_TYPE( +void embb_atomic_or_assign_TYPE( embb_atomic_TYPE* variable, /**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for the "or" operation and is used to store the result. */ @@ -193,13 +232,15 @@ EMBB_PLATFORM_INLINE void embb_atomic_or_assign_TYPE( /** * Stores \p value in \p variable. * + * \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE + * * \see \ref general_desc_atomic_base "Detailed description" for general * information and the meaning of \b TYPE. * * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE( +void embb_atomic_store_TYPE( embb_atomic_TYPE* variable, /**< [IN,OUT] Pointer to atomic variable */ int value @@ -209,6 +250,8 @@ EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE( /** * Swaps the current value of \p variable with \p value. * + * \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE + * * \return The old value of \p variable * * \see \ref general_desc_atomic_base "Detailed description" for general @@ -217,7 +260,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE( * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE TYPE embb_atomic_swap_TYPE( +TYPE embb_atomic_swap_TYPE( embb_atomic_TYPE* variable, /**< [IN,OUT] Pointer to atomic variable whose value is swapped */ TYPE value @@ -227,7 +270,8 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_swap_TYPE( /** * Computes the logical "xor" of the value stored in \p variable and \c value. * -* The result is stored in \p variable. +* \pre The atomic variable has been initialized with \c embb_atomic_init_TYPE +* \post The result is stored in \p variable. * * \see \ref general_desc_atomic_base "Detailed description" for general * information and the meaning of \b TYPE. @@ -235,7 +279,7 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_swap_TYPE( * \ingroup C_BASE_ATOMIC * \waitfree */ -EMBB_PLATFORM_INLINE void embb_atomic_xor_assign_TYPE( +void embb_atomic_xor_assign_TYPE( embb_atomic_TYPE* variable, /**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for the "xor" operation and is used to store the result. */ @@ -248,10 +292,62 @@ EMBB_PLATFORM_INLINE void embb_atomic_xor_assign_TYPE( extern "C" { #endif +#include + +#ifdef EMBB_THREADING_ANALYSIS_MODE + +#include +#include + +int embb_mutex_init( + embb_mutex_t* mutex, + int type + ); + +int embb_mutex_lock( + embb_mutex_t* mutex + ); + +int embb_mutex_unlock( + embb_mutex_t* mutex + ); + +void embb_mutex_destroy( + embb_mutex_t* mutex + ); + +#define EMBB_ATOMIC_MUTEX_INIT(mutex) embb_mutex_init(&(mutex), 0) +#define EMBB_ATOMIC_MUTEX_LOCK(mutex) embb_mutex_lock(&(mutex)) +#define EMBB_ATOMIC_MUTEX_UNLOCK(mutex) embb_mutex_unlock(&(mutex)) +#define EMBB_ATOMIC_MUTEX_DESTROY(mutex) embb_mutex_destroy(&(mutex)) + +#else + +#define EMBB_ATOMIC_MUTEX_INIT(...) +#define EMBB_ATOMIC_MUTEX_LOCK(...) +#define EMBB_ATOMIC_MUTEX_UNLOCK(...) +#define EMBB_ATOMIC_MUTEX_DESTROY(...) + +#endif + +#ifdef EMBB_DEBUG + +#define EMBB_ATOMIC_INIT_CHECK(variable) assert(variable->marker == 0x12345678) +#define EMBB_ATOMIC_INIT_MARKER(variable) variable->marker = 0x12345678 + +#else + +#define EMBB_ATOMIC_INIT_CHECK(variable) (void)(variable) +#define EMBB_ATOMIC_INIT_MARKER(variable) (void)(variable) + +#endif + #include #include #include #include +#include +#include #include #include #include diff --git a/base_c/include/embb/base/c/internal/atomic/and_assign.h b/base_c/include/embb/base/c/internal/atomic/and_assign.h index 48871ca..63a8712 100644 --- a/base_c/include/embb/base/c/internal/atomic/and_assign.h +++ b/base_c/include/embb/base/c/internal/atomic/and_assign.h @@ -152,8 +152,11 @@ EMBB_DEFINE_AND_ASSIGN(4, "") EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\ memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ EMBB_CAT2(embb_internal__atomic_and_assign_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) \ (&(variable->internal_variable)), value_pun); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ } #undef EMBB_ATOMIC_METHOD_TO_GENERATE diff --git a/base_c/include/embb/base/c/internal/atomic/atomic_variables.h b/base_c/include/embb/base/c/internal/atomic/atomic_variables.h index 4c35b1e..e0fa02e 100644 --- a/base_c/include/embb/base/c/internal/atomic/atomic_variables.h +++ b/base_c/include/embb/base/c/internal/atomic/atomic_variables.h @@ -29,11 +29,54 @@ #include #include +#include #ifdef EMBB_PLATFORM_COMPILER_MSVC #include #endif +#ifdef EMBB_DEBUG + +#ifdef EMBB_THREADING_ANALYSIS_MODE + +#define EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE( \ + EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, \ + EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX) \ + typedef struct \ +{ \ + volatile EMBB_ATOMIC_PARAMETER_TYPE_NATIVE internal_variable; \ + embb_mutex_t internal_mutex; \ + uint32_t marker; \ +} EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX); + +#else + +#define EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE( \ + EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, \ + EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX) \ + typedef struct \ +{ \ + volatile EMBB_ATOMIC_PARAMETER_TYPE_NATIVE internal_variable; \ + uint32_t marker; \ +} EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX); + +#endif + +#else + +#ifdef EMBB_THREADING_ANALYSIS_MODE + +#define EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE( \ + EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, \ + EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX) \ + typedef struct \ +{ \ + volatile EMBB_ATOMIC_PARAMETER_TYPE_NATIVE internal_variable; \ + embb_mutex_t internal_mutex; \ +} EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX); + +#else + #define EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE( \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, \ EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX) \ @@ -42,6 +85,10 @@ volatile EMBB_ATOMIC_PARAMETER_TYPE_NATIVE internal_variable; \ } EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX); +#endif + +#endif + EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(char, char) EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(short, short) EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(unsigned short, unsigned_short) diff --git a/base_c/include/embb/base/c/internal/atomic/compare_and_swap.h b/base_c/include/embb/base/c/internal/atomic/compare_and_swap.h index 8de4e09..d815227 100644 --- a/base_c/include/embb/base/c/internal/atomic/compare_and_swap.h +++ b/base_c/include/embb/base/c/internal/atomic/compare_and_swap.h @@ -138,8 +138,12 @@ EMBB_DEFINE_COMPARE_AND_SWAP(4, "") EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE* expected, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE desired) {\ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) desired_pun;\ memcpy(&desired_pun, &desired, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ - return EMBB_CAT2(embb_internal__atomic_compare_and_swap_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) \ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ + int result = EMBB_CAT2(embb_internal__atomic_compare_and_swap_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) \ (&(variable->internal_variable)), (EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) expected, desired_pun); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ + return result;\ } #undef EMBB_ATOMIC_METHOD_TO_GENERATE diff --git a/base_c/include/embb/base/c/internal/atomic/destroy.h b/base_c/include/embb/base/c/internal/atomic/destroy.h new file mode 100644 index 0000000..33dfc94 --- /dev/null +++ b/base_c/include/embb/base/c/internal/atomic/destroy.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014-2016, Siemens AG. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#ifndef EMBB_BASE_C_INTERNAL_ATOMIC_DESTROY_H_ +#define EMBB_BASE_C_INTERNAL_ATOMIC_DESTROY_H_ + +#ifndef DOXYGEN + +#include +#include +#include +#include +#include + +/* +* See file and_assign.h for a detailed (and operation independent) description +* of the following macro. +*/ +#define EMBB_ATOMIC_INTERNAL_DEFINE_DESTROY_METHOD(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \ + EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_atomic_destroy_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(\ + EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable) { \ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_DESTROY(variable->internal_mutex); \ + } + +#undef EMBB_ATOMIC_METHOD_TO_GENERATE +#define EMBB_ATOMIC_METHOD_TO_GENERATE DESTROY_METHOD +#include +#undef EMBB_ATOMIC_METHOD_TO_GENERATE + +#endif //DOXYGEN + +#endif //EMBB_BASE_C_INTERNAL_ATOMIC_INIT_H_ + diff --git a/base_c/include/embb/base/c/internal/atomic/fetch_and_add.h b/base_c/include/embb/base/c/internal/atomic/fetch_and_add.h index a165744..7dff961 100644 --- a/base_c/include/embb/base/c/internal/atomic/fetch_and_add.h +++ b/base_c/include/embb/base/c/internal/atomic/fetch_and_add.h @@ -107,9 +107,6 @@ EMBB_DEFINE_FETCH_AND_ADD(8, "q") : "memory", "cc" ); \ return result; \ } -/* return __sync_fetch_and_add( \ - pointer_to_value, new_value); \ - }*/ #else #error "No atomic fetch and store implementation found" #endif @@ -131,9 +128,12 @@ EMBB_DEFINE_FETCH_AND_ADD(4, "") EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \ memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) return_val = EMBB_CAT2(embb_internal__atomic_fetch_and_add_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)(\ (EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\ (&(variable->internal_variable)), value_pun); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \ memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ return return_val_pun; \ diff --git a/base_c/include/embb/base/c/internal/atomic/init.h b/base_c/include/embb/base/c/internal/atomic/init.h new file mode 100644 index 0000000..6199493 --- /dev/null +++ b/base_c/include/embb/base/c/internal/atomic/init.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014-2016, Siemens AG. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#ifndef EMBB_BASE_C_INTERNAL_ATOMIC_INIT_H_ +#define EMBB_BASE_C_INTERNAL_ATOMIC_INIT_H_ + +#ifndef DOXYGEN + +#include +#include +#include +#include +#include +#include + +/* +* See file and_assign.h for a detailed (and operation independent) description +* of the following macro. +*/ +#define EMBB_ATOMIC_INTERNAL_DEFINE_INIT_METHOD(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \ + EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_atomic_init_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(\ + EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, \ + EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \ + EMBB_ATOMIC_MUTEX_INIT(variable->internal_mutex); \ + EMBB_ATOMIC_INIT_MARKER(variable); \ + EMBB_CAT2(embb_atomic_store_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(variable, value); \ + } + +#undef EMBB_ATOMIC_METHOD_TO_GENERATE +#define EMBB_ATOMIC_METHOD_TO_GENERATE INIT_METHOD +#include +#undef EMBB_ATOMIC_METHOD_TO_GENERATE + +#endif //DOXYGEN + +#endif //EMBB_BASE_C_INTERNAL_ATOMIC_INIT_H_ + diff --git a/base_c/include/embb/base/c/internal/atomic/load.h b/base_c/include/embb/base/c/internal/atomic/load.h index 20094b5..c5457ca 100644 --- a/base_c/include/embb/base/c/internal/atomic/load.h +++ b/base_c/include/embb/base/c/internal/atomic/load.h @@ -119,10 +119,13 @@ EMBB_DEFINE_LOAD(4, "") */ #define EMBB_ATOMIC_INTERNAL_DEFINE_LOAD_METHOD(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \ EMBB_PLATFORM_INLINE EMBB_ATOMIC_PARAMETER_TYPE_NATIVE EMBB_CAT2(embb_atomic_load_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(\ - const EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable) { \ + EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable) { \ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \ return_val = (EMBB_CAT2(embb_internal__atomic_load_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)(\ (EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)(&(variable->internal_variable)))); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \ memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ return return_val_pun; \ diff --git a/base_c/include/embb/base/c/internal/atomic/or_assign.h b/base_c/include/embb/base/c/internal/atomic/or_assign.h index 9c76cf8..1fb02e0 100644 --- a/base_c/include/embb/base/c/internal/atomic/or_assign.h +++ b/base_c/include/embb/base/c/internal/atomic/or_assign.h @@ -123,8 +123,11 @@ EMBB_DEFINE_OR_ASSIGN(4, "") EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_atomic_or_assign_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\ memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ EMBB_CAT2(embb_internal__atomic_or_assign_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\ (&(variable->internal_variable)), value_pun); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ } #undef EMBB_ATOMIC_METHOD_TO_GENERATE diff --git a/base_c/include/embb/base/c/internal/atomic/store.h b/base_c/include/embb/base/c/internal/atomic/store.h index fdb6a40..2897e56 100644 --- a/base_c/include/embb/base/c/internal/atomic/store.h +++ b/base_c/include/embb/base/c/internal/atomic/store.h @@ -118,8 +118,11 @@ EMBB_DEFINE_STORE(4, "") EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_atomic_store_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \ memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ EMBB_CAT2(embb_internal__atomic_store_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\ (&(variable->internal_variable)), value_pun); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ } #undef EMBB_ATOMIC_METHOD_TO_GENERATE diff --git a/base_c/include/embb/base/c/internal/atomic/swap.h b/base_c/include/embb/base/c/internal/atomic/swap.h index 70c397c..f37738f 100644 --- a/base_c/include/embb/base/c/internal/atomic/swap.h +++ b/base_c/include/embb/base/c/internal/atomic/swap.h @@ -127,8 +127,11 @@ EMBB_DEFINE_SWAP(4, "") EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \ memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \ return_val = EMBB_CAT2(embb_internal__atomic_swap_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)(&(variable->internal_variable)), value_pun); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \ memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ return return_val_pun; \ diff --git a/base_c/include/embb/base/c/internal/atomic/xor_assign.h b/base_c/include/embb/base/c/internal/atomic/xor_assign.h index 8de71fe..e09863f 100644 --- a/base_c/include/embb/base/c/internal/atomic/xor_assign.h +++ b/base_c/include/embb/base/c/internal/atomic/xor_assign.h @@ -125,8 +125,11 @@ EMBB_DEFINE_XOR_ASSIGN(4, "") EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\ memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ + EMBB_ATOMIC_INIT_CHECK(variable); \ + EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \ EMBB_CAT2(embb_internal__atomic_xor_assign_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\ (&(variable->internal_variable)), value_pun); \ + EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \ } #undef EMBB_ATOMIC_METHOD_TO_GENERATE diff --git a/base_c/include/embb/base/c/internal/cmake_config.h.in b/base_c/include/embb/base/c/internal/cmake_config.h.in index f86d3e6..876ceed 100644 --- a/base_c/include/embb/base/c/internal/cmake_config.h.in +++ b/base_c/include/embb/base/c/internal/cmake_config.h.in @@ -53,7 +53,14 @@ */ #cmakedefine EMBB_PLATFORM_HAS_GLIB_CPU +/** + * Enables mutex-based implementation of all synchronization constructs. + */ +#cmakedefine EMBB_THREADING_ANALYSIS_MODE +/** + * Version defines. + */ #define EMBB_BASE_VERSION_MAJOR ${EMBB_BASE_VERSION_MAJOR} #define EMBB_BASE_VERSION_MINOR ${EMBB_BASE_VERSION_MINOR} #define EMBB_BASE_VERSION_PATCH ${EMBB_BASE_VERSION_PATCH} diff --git a/base_c/src/counter.c b/base_c/src/counter.c index 7b96fc9..47e985c 100644 --- a/base_c/src/counter.c +++ b/base_c/src/counter.c @@ -33,7 +33,7 @@ int embb_counter_init(embb_counter_t* counter) { if (counter == NULL) { return EMBB_ERROR; } - embb_atomic_store_unsigned_int(&(counter->value), 0); + embb_atomic_init_unsigned_int(&(counter->value), 0); return EMBB_SUCCESS; } @@ -55,7 +55,7 @@ unsigned int embb_counter_decrement(embb_counter_t* counter) { void embb_counter_destroy(embb_counter_t* counter) { assert(counter != NULL); - EMBB_UNUSED_IN_RELEASE(counter); + embb_atomic_destroy_unsigned_int(&(counter->value)); } diff --git a/base_c/src/internal/thread_index.c b/base_c/src/internal/thread_index.c index b4c1a75..71bb583 100644 --- a/base_c/src/internal/thread_index.c +++ b/base_c/src/internal/thread_index.c @@ -40,18 +40,18 @@ * This function has local scope. */ static int embb_max_number_thread_indices_max = 0; -static embb_atomic_int embb_max_number_thread_indices_flag = { 0 }; +static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_max_number_thread_indices_flag = 0; unsigned int* embb_max_number_thread_indices() { - int compare_to = 0; - if (embb_atomic_load_int(&embb_max_number_thread_indices_flag) != 2) { - if (embb_atomic_compare_and_swap_int( + EMBB_BASE_BASIC_TYPE_SIZE_4 compare_to = 0; + if (embb_internal__atomic_load_4(&embb_max_number_thread_indices_flag) != 2) { + if (embb_internal__atomic_compare_and_swap_4( &embb_max_number_thread_indices_flag, &compare_to, 1)) { embb_max_number_thread_indices_max = (int)(embb_core_count_available() * 2); - embb_atomic_store_int(&embb_max_number_thread_indices_flag, 2); + embb_internal__atomic_store_4(&embb_max_number_thread_indices_flag, 2); } - while (embb_atomic_load_int(&embb_max_number_thread_indices_flag) != 2) {} + while (embb_internal__atomic_load_4(&embb_max_number_thread_indices_flag) != 2) {} } return (unsigned int*) &embb_max_number_thread_indices_max; } @@ -61,17 +61,17 @@ unsigned int* embb_max_number_thread_indices() { * * This function has local scope. */ -static embb_atomic_int embb_thread_index_counter_flag = { 0 }; +static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_thread_index_counter_flag = 0; static embb_counter_t embb_thread_index_counter_index; embb_counter_t* embb_thread_index_counter() { - int compare_to = 0; - if (embb_atomic_load_int(&embb_thread_index_counter_flag) != 2) { - if (embb_atomic_compare_and_swap_int( + EMBB_BASE_BASIC_TYPE_SIZE_4 compare_to = 0; + if (embb_internal__atomic_load_4(&embb_thread_index_counter_flag) != 2) { + if (embb_internal__atomic_compare_and_swap_4( &embb_thread_index_counter_flag, &compare_to, 1)) { embb_counter_init(&embb_thread_index_counter_index); - embb_atomic_store_int(&embb_thread_index_counter_flag, 2); + embb_internal__atomic_store_4(&embb_thread_index_counter_flag, 2); } - while (embb_atomic_load_int(&embb_thread_index_counter_flag) != 2) {} + while (embb_internal__atomic_load_4(&embb_thread_index_counter_flag) != 2) {} } return &embb_thread_index_counter_index; } diff --git a/base_c/src/memory_allocation.c b/base_c/src/memory_allocation.c index 46f2828..07468b2 100644 --- a/base_c/src/memory_allocation.c +++ b/base_c/src/memory_allocation.c @@ -33,7 +33,7 @@ #ifdef EMBB_DEBUG -static embb_atomic_long embb_bytes_allocated = { 0 }; +static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_bytes_allocated = 0; enum { // Make the marking unlikely to be something else @@ -49,7 +49,7 @@ void* embb_alloc(size_t bytes) { if (allocated == NULL) return NULL; - embb_atomic_fetch_and_add_long( + embb_internal__atomic_fetch_and_add_4( &embb_bytes_allocated, (long)bytes_to_allocate); size_t* x_as_size_type = (size_t*)allocated; @@ -72,7 +72,7 @@ void embb_free(void * ptr) { (*alloc_type) = (size_t)INVALID_ALLOCATION; - embb_atomic_fetch_and_add_long( + embb_internal__atomic_fetch_and_add_4( &embb_bytes_allocated, (long)(0 - (size_t)(*bytes_allocated))); free((size_t*)ptr - 2); @@ -127,7 +127,7 @@ void* embb_alloc_aligned(size_t alignment, size_t size) { x_as_size_type[-2] = (size_t)allocated; x_as_size_type[-3] = bytes_to_allocate; - embb_atomic_fetch_and_add_long( + embb_internal__atomic_fetch_and_add_4( &embb_bytes_allocated, (long)bytes_to_allocate); return x; @@ -144,14 +144,14 @@ void embb_free_aligned(void* ptr) { ptr_conv[-1] = (size_t)INVALID_ALLOCATION; - embb_atomic_fetch_and_add_long( + embb_internal__atomic_fetch_and_add_4( &embb_bytes_allocated, (long)((long)0 - ptr_conv[-3])); free((void*)ptr_conv[-2]); } size_t embb_get_bytes_allocated() { - return (size_t)(embb_atomic_load_long(&embb_bytes_allocated)); + return (size_t)(embb_internal__atomic_load_4(&embb_bytes_allocated)); } #else // EMBB_DEBUG diff --git a/base_c/src/mutex.c b/base_c/src/mutex.c index 5ccb0ab..158af1d 100644 --- a/base_c/src/mutex.c +++ b/base_c/src/mutex.c @@ -147,9 +147,7 @@ int embb_spin_init(embb_spinlock_t* spinlock) { if (NULL == spinlock) { return EMBB_ERROR; } - // For now, store the initial value. In the future will use atomic init - // function (as soon as available). - embb_atomic_store_int(&spinlock->atomic_spin_variable_, 0); + embb_atomic_init_int(&spinlock->atomic_spin_variable_, 0); return EMBB_SUCCESS; } @@ -207,7 +205,5 @@ int embb_spin_unlock(embb_spinlock_t* spinlock) { void embb_spin_destroy(embb_spinlock_t* spinlock) { assert(NULL != spinlock); - // for now, doing nothing here... in future, will call the respective - // destroy function for atomics... - EMBB_UNUSED(spinlock); + embb_atomic_destroy_int(&spinlock->atomic_spin_variable_); } diff --git a/base_c/test/main.cc b/base_c/test/main.cc index ad864c8..c8147b7 100644 --- a/base_c/test/main.cc +++ b/base_c/test/main.cc @@ -39,6 +39,7 @@ #include #include +#include #include using embb::base::test::AllocTest; diff --git a/base_c/test/thread_index_test.cc b/base_c/test/thread_index_test.cc index baf2f75..8ac3e40 100644 --- a/base_c/test/thread_index_test.cc +++ b/base_c/test/thread_index_test.cc @@ -36,13 +36,21 @@ namespace embb { namespace base { namespace test { +embb_atomic_int flag; + ThreadIndexTest::ThreadIndexTest() : number_threads_(partest::TestSuite::GetDefaultNumThreads()) { + embb_atomic_init_int(&flag, 1); + CreateUnit("Test 0 indices").Add(&ThreadIndexTest::Test0, this); CreateUnit("Test 1 index").Add(&ThreadIndexTest::Test1, this); CreateUnit("Test N indices").Add(&ThreadIndexTest::TestN, this, 1); } +ThreadIndexTest::~ThreadIndexTest() { + embb_atomic_destroy_int(&flag); +} + void ThreadIndexTest::Test0() { embb_internal_thread_index_reset(); unsigned int old_max = embb_thread_get_max_count(); @@ -78,8 +86,6 @@ void ThreadIndexTest::Test1() { embb_internal_thread_index_set_max(old_max); } -embb_atomic_int flag = { 1 }; - void ThreadIndexTest::TestN() { embb_internal_thread_index_reset(); unsigned int old_max = embb_thread_get_max_count(); @@ -106,6 +112,8 @@ void ThreadIndexTest::TestN() { embb_thread_join(&thread, NULL); delete[] threads; embb_internal_thread_index_set_max(old_max); + + embb_atomic_destroy_int(&flag); } int ThreadStart(void* arg) { diff --git a/base_c/test/thread_index_test.h b/base_c/test/thread_index_test.h index 3452a41..9bb1b93 100644 --- a/base_c/test/thread_index_test.h +++ b/base_c/test/thread_index_test.h @@ -36,10 +36,15 @@ namespace test { class ThreadIndexTest : public partest::TestCase { public: /** - * Adds test methods. + * Adds test methods and allocates temporary data. */ ThreadIndexTest(); + /** + * Destroys temporary data. + */ + ~ThreadIndexTest(); + private: /** * Tests 0 available indices. diff --git a/base_cpp/include/embb/base/internal/atomic/atomic_arithmetic.h b/base_cpp/include/embb/base/internal/atomic/atomic_arithmetic.h index f9cdd25..9b50c20 100644 --- a/base_cpp/include/embb/base/internal/atomic/atomic_arithmetic.h +++ b/base_cpp/include/embb/base/internal/atomic/atomic_arithmetic.h @@ -117,8 +117,10 @@ FetchAndAdd(DifferenceType val) { NativeType native_desired; memcpy(&native_desired, &desired, sizeof(desired)); + EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex); NativeType storage_value = fetch_and_add_implementation:: fetch_and_add(&this->AtomicValue, native_desired); + EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex); memcpy(&return_value, &storage_value, sizeof(return_value)); return return_value; diff --git a/base_cpp/include/embb/base/internal/atomic/atomic_base.h b/base_cpp/include/embb/base/internal/atomic/atomic_base.h index bfa3dd6..54381ec 100644 --- a/base_cpp/include/embb/base/internal/atomic/atomic_base.h +++ b/base_cpp/include/embb/base/internal/atomic/atomic_base.h @@ -58,6 +58,10 @@ class AtomicBase { mutable NativeType AtomicValue; +#ifdef EMBB_THREADING_ANALYSIS_MODE + mutable embb_mutex_t internal_mutex; +#endif + public: /** * Default constructor. @@ -73,6 +77,11 @@ class AtomicBase { */ explicit AtomicBase(BaseType val); + /** + * Destructor. + */ + ~AtomicBase(); + // The members below are documented in atomic.h BaseType operator=(BaseType val); operator BaseType() const; @@ -88,14 +97,21 @@ class AtomicBase { template inline AtomicBase::AtomicBase() : AtomicValue(0) { + EMBB_ATOMIC_MUTEX_INIT(internal_mutex); } template inline AtomicBase::AtomicBase(BaseType val) /*: AtomicValue(val)*/ { + EMBB_ATOMIC_MUTEX_INIT(internal_mutex); memcpy(&AtomicValue, &val, sizeof(AtomicValue)); } template +inline AtomicBase::~AtomicBase() { + EMBB_ATOMIC_MUTEX_DESTROY(internal_mutex); +} + +template inline BaseType AtomicBase::operator=(BaseType val) { Store(val); return val; @@ -132,16 +148,20 @@ inline void AtomicBase::Store(BaseType val) { // anyway... memcpy(&storage_value, &val, sizeof(storage_value)); + EMBB_ATOMIC_MUTEX_LOCK(internal_mutex); store_implementation< NativeType > ::Store(&AtomicValue, storage_value); + EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex); } template inline BaseType AtomicBase::Load() const { BaseType return_value; + EMBB_ATOMIC_MUTEX_LOCK(internal_mutex); NativeType storage_value = load_implementation< NativeType >::Load(&AtomicValue); + EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex); memcpy(&return_value, &storage_value, sizeof(return_value)); @@ -155,8 +175,10 @@ inline BaseType AtomicBase::Swap(BaseType val) { memcpy(&storage_value, &val, sizeof(storage_value)); + EMBB_ATOMIC_MUTEX_LOCK(internal_mutex); NativeType storage_value2 = swap_implementation< NativeType > ::Swap(&AtomicValue, storage_value); + EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex); memcpy(&return_value, &storage_value2, sizeof(return_value)); @@ -172,10 +194,12 @@ CompareAndSwap(BaseType& expected, BaseType desired) { memcpy(&native_expected, &expected, sizeof(expected)); memcpy(&native_desired, &desired, sizeof(desired)); + EMBB_ATOMIC_MUTEX_LOCK(internal_mutex); bool return_val = (compare_and_swap_implementation:: compare_and_swap(&AtomicValue, &native_expected, native_desired)) !=0 ? true : false; + EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex); memcpy(&expected, &native_expected, sizeof(expected)); diff --git a/base_cpp/include/embb/base/internal/atomic/atomic_integer.h b/base_cpp/include/embb/base/internal/atomic/atomic_integer.h index c609bd9..d426f49 100644 --- a/base_cpp/include/embb/base/internal/atomic/atomic_integer.h +++ b/base_cpp/include/embb/base/internal/atomic/atomic_integer.h @@ -93,8 +93,10 @@ inline void AtomicInteger::operator&=(BaseType val) { NativeType native_operand; memcpy(&native_operand, &val, sizeof(val)); + EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex); and_assign_implementation:: and_assign(&this->AtomicValue, native_operand); + EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex); } template @@ -102,8 +104,10 @@ inline void AtomicInteger::operator|=(BaseType val) { NativeType native_operand; memcpy(&native_operand, &val, sizeof(val)); + EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex); or_assign_implementation:: or_assign(&this->AtomicValue, native_operand); + EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex); } template @@ -111,8 +115,10 @@ inline void AtomicInteger::operator^=(BaseType val) { NativeType native_operand; memcpy(&native_operand, &val, sizeof(val)); + EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex); xor_assign_implementation:: xor_assign(&this->AtomicValue, native_operand); + EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex); } } // namespace atomic diff --git a/base_cpp/test/main.cc b/base_cpp/test/main.cc index 31b57d2..c24850c 100644 --- a/base_cpp/test/main.cc +++ b/base_cpp/test/main.cc @@ -36,6 +36,7 @@ #include #include +#include #include using embb::base::test::CoreSetTest; diff --git a/containers_cpp/test/main.cc b/containers_cpp/test/main.cc index f63e957..23d976e 100644 --- a/containers_cpp/test/main.cc +++ b/containers_cpp/test/main.cc @@ -39,6 +39,8 @@ #include #include #include +#include +#include #ifdef EMBB_PLATFORM_COMPILER_MSVC #pragma warning(pop) // Reset warning 4548 diff --git a/dataflow_cpp/include/embb/dataflow/internal/inputs.h b/dataflow_cpp/include/embb/dataflow/internal/inputs.h index 813bac8..8850a06 100644 --- a/dataflow_cpp/include/embb/dataflow/internal/inputs.h +++ b/dataflow_cpp/include/embb/dataflow/internal/inputs.h @@ -84,13 +84,16 @@ class Inputs)*slices_)); for (int ii = 0; ii < slices_; ii++) { - count_[ii] = 1; + new(count_+ii) embb::base::Atomic(1); } } this->template Get<0>().SetSlices(slices_); } ~Inputs() { if (NULL != count_) { + for (int ii = 0; ii < slices_; ii++) { + count_[ii].~Atomic(); + } embb::base::Allocation::Free(count_); } } @@ -150,7 +153,7 @@ class Inputs)*slices_)); for (int ii = 0; ii < slices_; ii++) { - count_[ii] = 2; + new(count_ + ii) embb::base::Atomic(2); } } this->template Get<0>().SetSlices(slices_); @@ -158,6 +161,9 @@ class Inputs(); + } embb::base::Allocation::Free(count_); } } @@ -222,7 +228,7 @@ class Inputs)*slices_)); for (int ii = 0; ii < slices_; ii++) { - count_[ii] = 3; + new(count_ + ii) embb::base::Atomic(3); } } this->template Get<0>().SetSlices(slices_); @@ -231,6 +237,9 @@ class Inputs(); + } embb::base::Allocation::Free(count_); } } @@ -299,7 +308,7 @@ class Inputs embb::base::Allocation::Allocate( sizeof(embb::base::Atomic)*slices_)); for (int ii = 0; ii < slices_; ii++) { - count_[ii] = 4; + new(count_ + ii) embb::base::Atomic(4); } } this->template Get<0>().SetSlices(slices_); @@ -309,6 +318,9 @@ class Inputs } ~Inputs() { if (NULL != count_) { + for (int ii = 0; ii < slices_; ii++) { + count_[ii].~Atomic(); + } embb::base::Allocation::Free(count_); } } @@ -383,7 +395,7 @@ class Inputs embb::base::Allocation::Allocate( sizeof(embb::base::Atomic)*slices_)); for (int ii = 0; ii < slices_; ii++) { - count_[ii] = 5; + new(count_ + ii) embb::base::Atomic(5); } } this->template Get<0>().SetSlices(slices_); @@ -394,6 +406,9 @@ class Inputs } ~Inputs() { if (NULL != count_) { + for (int ii = 0; ii < slices_; ii++) { + count_[ii].~Atomic(); + } embb::base::Allocation::Free(count_); } } diff --git a/dataflow_cpp/include/embb/dataflow/network.h b/dataflow_cpp/include/embb/dataflow/network.h index b37e44e..5b2c102 100644 --- a/dataflow_cpp/include/embb/dataflow/network.h +++ b/dataflow_cpp/include/embb/dataflow/network.h @@ -802,6 +802,9 @@ class Network : public internal::ClockListener { sched_ = NULL; } if (NULL != sink_counter_) { + for (int ii = 0; ii < slices_; ii++) { + sink_counter_[ii].~Atomic(); + } embb::base::Allocation::Free(sink_counter_); sink_counter_ = NULL; } @@ -1111,7 +1114,7 @@ class Network : public internal::ClockListener { embb::base::Allocation::Allocate( sizeof(embb::base::Atomic)*slices_)); for (int ii = 0; ii < slices_; ii++) { - sink_counter_[ii] = 0; + new(sink_counter_+ii) embb::base::Atomic(0); } } }; diff --git a/dataflow_cpp/test/main.cc b/dataflow_cpp/test/main.cc index 7e09ac1..39dc02e 100644 --- a/dataflow_cpp/test/main.cc +++ b/dataflow_cpp/test/main.cc @@ -31,6 +31,8 @@ #include #include +#include + PT_MAIN("Dataflow C++") { PT_RUN(SimpleTest); PT_RUN(TupleTest); diff --git a/mtapi_c/src/embb_mtapi_action_plugin_t.c b/mtapi_c/src/embb_mtapi_action_plugin_t.c index 447beed..0649548 100644 --- a/mtapi_c/src/embb_mtapi_action_plugin_t.c +++ b/mtapi_c/src/embb_mtapi_action_plugin_t.c @@ -62,7 +62,7 @@ mtapi_action_hndl_t mtapi_ext_plugin_action_create( new_action->node_local_data_size = node_local_data_size; new_action->enabled = MTAPI_TRUE; new_action->is_plugin_action = MTAPI_TRUE; - embb_atomic_store_int(&new_action->num_tasks, 0); + embb_atomic_init_int(&new_action->num_tasks, 0); new_action->plugin_task_start_function = task_start_function; new_action->plugin_task_cancel_function = task_cancel_function; @@ -87,6 +87,7 @@ mtapi_action_hndl_t mtapi_ext_plugin_action_create( action_handle = new_action->handle; embb_mtapi_job_add_action(job, new_action); } else { + embb_mtapi_action_finalize(new_action); embb_mtapi_action_pool_deallocate(node->action_pool, new_action); } } else { diff --git a/mtapi_c/src/embb_mtapi_action_t.c b/mtapi_c/src/embb_mtapi_action_t.c index c4d1714..a2426b7 100644 --- a/mtapi_c/src/embb_mtapi_action_t.c +++ b/mtapi_c/src/embb_mtapi_action_t.c @@ -49,6 +49,8 @@ embb_mtapi_pool_implementation(action) /* ---- CLASS MEMBERS ------------------------------------------------------ */ void embb_mtapi_action_initialize(embb_mtapi_action_t* that) { + assert(MTAPI_NULL != that); + that->action_function = NULL; that->job_id = MTAPI_JOB_ID_INVALID; that->domain_id = MTAPI_DOMAIN_ID_INVALID; @@ -57,15 +59,25 @@ void embb_mtapi_action_initialize(embb_mtapi_action_t* that) { that->node_local_data = NULL; that->node_local_data_size = 0; that->plugin_data = MTAPI_NULL; - embb_atomic_store_int(&that->num_tasks, 0); + embb_atomic_init_int(&that->num_tasks, 0); } void embb_mtapi_action_finalize(embb_mtapi_action_t* that) { + assert(MTAPI_NULL != that); + if (that->is_plugin_action) { // TODO(mw): check status that->plugin_action_finalize_function(that->handle, NULL); } - embb_mtapi_action_initialize(that); + that->action_function = NULL; + that->job_id = MTAPI_JOB_ID_INVALID; + that->domain_id = MTAPI_DOMAIN_ID_INVALID; + that->node_id = MTAPI_NODE_ID_INVALID; + that->enabled = MTAPI_FALSE; + that->node_local_data = NULL; + that->node_local_data_size = 0; + that->plugin_data = MTAPI_NULL; + embb_atomic_destroy_int(&that->num_tasks); } static mtapi_boolean_t embb_mtapi_action_delete_visitor( @@ -140,7 +152,7 @@ mtapi_action_hndl_t mtapi_action_create( new_action->node_local_data_size = node_local_data_size; new_action->enabled = MTAPI_TRUE; new_action->is_plugin_action = MTAPI_FALSE; - embb_atomic_store_int(&new_action->num_tasks, 0); + embb_atomic_init_int(&new_action->num_tasks, 0); new_action->action_function = action_function; @@ -162,6 +174,7 @@ mtapi_action_hndl_t mtapi_action_create( action_handle = new_action->handle; embb_mtapi_job_add_action(job, new_action); } else { + embb_mtapi_action_finalize(new_action); embb_mtapi_action_pool_deallocate(node->action_pool, new_action); } } else { @@ -337,8 +350,7 @@ void mtapi_action_delete( node, local_action->job_id); embb_mtapi_job_remove_action(local_job, local_action); } - /* this is done by pool deallocate: - embb_mtapi_action_finalize(local_action); */ + embb_mtapi_action_finalize(local_action); embb_mtapi_action_pool_deallocate(node->action_pool, local_action); } else { local_status = MTAPI_ERR_ACTION_INVALID; diff --git a/mtapi_c/src/embb_mtapi_alloc.c b/mtapi_c/src/embb_mtapi_alloc.c index 5b02614..8a9e800 100644 --- a/mtapi_c/src/embb_mtapi_alloc.c +++ b/mtapi_c/src/embb_mtapi_alloc.c @@ -30,12 +30,12 @@ #include -static embb_atomic_unsigned_int embb_mtapi_alloc_bytes_allocated = { 0 }; +static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_mtapi_alloc_bytes_allocated = 0; void * embb_mtapi_alloc_allocate(unsigned int bytes) { void * ptr = embb_alloc(bytes); if (ptr != NULL) { - embb_atomic_fetch_and_add_unsigned_int( + embb_internal__atomic_fetch_and_add_4( &embb_mtapi_alloc_bytes_allocated, sizeof(unsigned int)+bytes); } return ptr; @@ -48,9 +48,9 @@ void embb_mtapi_alloc_deallocate(void * ptr) { } void embb_mtapi_alloc_reset_bytes_allocated() { - embb_atomic_store_unsigned_int(&embb_mtapi_alloc_bytes_allocated, 0); + embb_internal__atomic_store_4(&embb_mtapi_alloc_bytes_allocated, 0); } unsigned int embb_mtapi_alloc_get_bytes_allocated() { - return embb_atomic_load_unsigned_int(&embb_mtapi_alloc_bytes_allocated); + return embb_internal__atomic_load_4(&embb_mtapi_alloc_bytes_allocated); } diff --git a/mtapi_c/src/embb_mtapi_group_t.c b/mtapi_c/src/embb_mtapi_group_t.c index 10c41b8..9fa9efc 100644 --- a/mtapi_c/src/embb_mtapi_group_t.c +++ b/mtapi_c/src/embb_mtapi_group_t.c @@ -55,8 +55,8 @@ void embb_mtapi_group_initialize(embb_mtapi_group_t * that) { assert(MTAPI_NULL != that); that->group_id = MTAPI_GROUP_ID_NONE; - embb_atomic_store_int(&that->deleted, MTAPI_FALSE); - that->num_tasks.internal_variable = 0; + embb_atomic_init_int(&that->deleted, MTAPI_FALSE); + embb_atomic_init_int(&that->num_tasks, 0); embb_mtapi_task_queue_initialize(&that->queue); } @@ -67,8 +67,8 @@ void embb_mtapi_group_initialize_with_node( assert(MTAPI_NULL != node); that->group_id = MTAPI_GROUP_ID_NONE; - embb_atomic_store_int(&that->deleted, MTAPI_FALSE); - that->num_tasks.internal_variable = 0; + embb_atomic_init_int(&that->deleted, MTAPI_FALSE); + embb_atomic_init_int(&that->num_tasks, 0); embb_mtapi_task_queue_initialize_with_capacity( &that->queue, node->attributes.queue_limit); } @@ -77,7 +77,9 @@ void embb_mtapi_group_finalize(embb_mtapi_group_t * that) { assert(MTAPI_NULL != that); embb_atomic_store_int(&that->deleted, MTAPI_TRUE); - that->num_tasks.internal_variable = 0; + embb_atomic_destroy_int(&that->deleted); + embb_atomic_store_int(&that->num_tasks, 0); + embb_atomic_destroy_int(&that->num_tasks); embb_mtapi_task_queue_finalize(&that->queue); } diff --git a/mtapi_c/src/embb_mtapi_node_t.c b/mtapi_c/src/embb_mtapi_node_t.c index 130fc64..32126ce 100644 --- a/mtapi_c/src/embb_mtapi_node_t.c +++ b/mtapi_c/src/embb_mtapi_node_t.c @@ -105,7 +105,7 @@ void mtapi_initialize( } if (MTAPI_SUCCESS == local_status) { - embb_atomic_store_int(&node->is_scheduler_running, MTAPI_FALSE); + embb_atomic_init_int(&node->is_scheduler_running, MTAPI_FALSE); /* initialize storage */ embb_mtapi_job_initialize_list(node); @@ -199,6 +199,8 @@ void mtapi_finalize(MTAPI_OUT mtapi_status_t* status) { embb_mtapi_job_finalize_list(node); } + embb_atomic_destroy_int(&node->is_scheduler_running); + /* free system instance */ embb_mtapi_alloc_deallocate(node); embb_mtapi_node_instance = MTAPI_NULL; diff --git a/mtapi_c/src/embb_mtapi_pool_template-inl.h b/mtapi_c/src/embb_mtapi_pool_template-inl.h index 7754952..9fdfca2 100644 --- a/mtapi_c/src/embb_mtapi_pool_template-inl.h +++ b/mtapi_c/src/embb_mtapi_pool_template-inl.h @@ -66,8 +66,6 @@ mtapi_boolean_t embb_mtapi_##TYPE##_pool_initialize( \ that->storage[ii].handle.id = EMBB_MTAPI_IDPOOL_INVALID_ID; \ that->storage[ii].handle.tag = 0; \ } \ - /* use entry 0 as invalid */ \ - embb_mtapi_##TYPE##_initialize(that->storage); \ return MTAPI_TRUE; \ } else { \ that->id_pool.ids_available = 0; \ @@ -96,7 +94,6 @@ void embb_mtapi_##TYPE##_pool_deallocate( \ embb_mtapi_##TYPE##_pool_t * that, \ embb_mtapi_##TYPE##_t * object) { \ mtapi_uint_t pool_id = object->handle.id; \ - embb_mtapi_##TYPE##_finalize(object); \ object->handle.id = EMBB_MTAPI_IDPOOL_INVALID_ID; \ object->handle.tag++; \ embb_mtapi_id_pool_deallocate(&that->id_pool, pool_id); \ diff --git a/mtapi_c/src/embb_mtapi_queue_t.c b/mtapi_c/src/embb_mtapi_queue_t.c index be85611..36b5e83 100644 --- a/mtapi_c/src/embb_mtapi_queue_t.c +++ b/mtapi_c/src/embb_mtapi_queue_t.c @@ -56,8 +56,8 @@ void embb_mtapi_queue_initialize(embb_mtapi_queue_t* that) { mtapi_queueattr_init(&that->attributes, MTAPI_NULL); that->queue_id = MTAPI_QUEUE_ID_NONE; - embb_atomic_store_char(&that->enabled, MTAPI_FALSE); - embb_atomic_store_int(&that->num_tasks, 0); + embb_atomic_init_char(&that->enabled, MTAPI_FALSE); + embb_atomic_init_int(&that->num_tasks, 0); that->job_handle.id = 0; that->job_handle.tag = 0; } @@ -71,8 +71,8 @@ void embb_mtapi_queue_initialize_with_attributes_and_job( that->attributes = *attributes; that->queue_id = MTAPI_QUEUE_ID_NONE; - embb_atomic_store_char(&that->enabled, MTAPI_TRUE); - embb_atomic_store_int(&that->num_tasks, 0); + embb_atomic_init_char(&that->enabled, MTAPI_TRUE); + embb_atomic_init_int(&that->num_tasks, 0); that->job_handle = job; } @@ -81,6 +81,8 @@ void embb_mtapi_queue_finalize(embb_mtapi_queue_t* that) { that->job_handle.id = 0; that->job_handle.tag = 0; + embb_atomic_destroy_int(&that->num_tasks); + embb_atomic_destroy_char(&that->enabled); embb_mtapi_queue_initialize(that); } diff --git a/mtapi_c/src/embb_mtapi_scheduler_t.c b/mtapi_c/src/embb_mtapi_scheduler_t.c index 0e5d60d..e023256 100644 --- a/mtapi_c/src/embb_mtapi_scheduler_t.c +++ b/mtapi_c/src/embb_mtapi_scheduler_t.c @@ -491,7 +491,7 @@ mtapi_boolean_t embb_mtapi_scheduler_initialize_with_mode( assert(MTAPI_NULL != that); assert(MTAPI_NULL != node); - embb_atomic_store_int(&that->affine_task_counter, 0); + embb_atomic_init_int(&that->affine_task_counter, 0); /* Paranoia sanitizing of scheduler mode */ if (mode >= NUM_SCHEDULER_MODES) { @@ -573,6 +573,8 @@ void embb_mtapi_scheduler_finalize(embb_mtapi_scheduler_t * that) { embb_mtapi_alloc_deallocate(that->worker_contexts); that->worker_contexts = MTAPI_NULL; } + + embb_atomic_destroy_int(&that->affine_task_counter); } embb_mtapi_scheduler_t * embb_mtapi_scheduler_new() { diff --git a/mtapi_c/src/embb_mtapi_task_t.c b/mtapi_c/src/embb_mtapi_task_t.c index 06c4877..9345ca3 100644 --- a/mtapi_c/src/embb_mtapi_task_t.c +++ b/mtapi_c/src/embb_mtapi_task_t.c @@ -79,20 +79,29 @@ void embb_mtapi_task_initialize(embb_mtapi_task_t* that) { that->action.id = EMBB_MTAPI_IDPOOL_INVALID_ID; that->job.id = EMBB_MTAPI_IDPOOL_INVALID_ID; - embb_atomic_store_int(&that->state, MTAPI_TASK_ERROR); + embb_atomic_init_int(&that->state, MTAPI_TASK_ERROR); that->task_id = MTAPI_TASK_ID_NONE; that->group.id = EMBB_MTAPI_IDPOOL_INVALID_ID; that->queue.id = EMBB_MTAPI_IDPOOL_INVALID_ID; that->error_code = MTAPI_SUCCESS; - embb_atomic_store_unsigned_int(&that->current_instance, 0); + embb_atomic_init_unsigned_int(&that->current_instance, 0); embb_spin_init(&that->state_lock); + embb_atomic_init_unsigned_int(&that->instances_todo, 0); } void embb_mtapi_task_finalize(embb_mtapi_task_t* that) { assert(MTAPI_NULL != that); - embb_mtapi_task_initialize(that); + that->action.id = EMBB_MTAPI_IDPOOL_INVALID_ID; + that->job.id = EMBB_MTAPI_IDPOOL_INVALID_ID; + embb_atomic_destroy_int(&that->state); + that->task_id = MTAPI_TASK_ID_NONE; + that->group.id = EMBB_MTAPI_IDPOOL_INVALID_ID; + that->queue.id = EMBB_MTAPI_IDPOOL_INVALID_ID; + that->error_code = MTAPI_SUCCESS; + embb_atomic_destroy_unsigned_int(&that->current_instance); embb_spin_destroy(&that->state_lock); + embb_atomic_destroy_unsigned_int(&that->instances_todo); } mtapi_boolean_t embb_mtapi_task_execute( diff --git a/mtapi_c/src/embb_mtapi_thread_context_t.c b/mtapi_c/src/embb_mtapi_thread_context_t.c index 9645461..d550c4b 100644 --- a/mtapi_c/src/embb_mtapi_thread_context_t.c +++ b/mtapi_c/src/embb_mtapi_thread_context_t.c @@ -58,7 +58,9 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize( that->thread_priority = priority; that->is_main_thread = (worker_index == 0) ? node->attributes.reuse_main_thread : MTAPI_FALSE; - embb_atomic_store_int(&that->run, 0); + + embb_atomic_init_int(&that->run, 0); + embb_atomic_init_int(&that->is_sleeping, 0); that->queue = (embb_mtapi_task_queue_t**)embb_mtapi_alloc_allocate( sizeof(embb_mtapi_task_queue_t)*that->priorities); @@ -101,7 +103,6 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize( embb_mutex_init(&that->work_available_mutex, EMBB_MUTEX_PLAIN); embb_condition_init(&that->work_available); - embb_atomic_store_int(&that->is_sleeping, 0); that->is_initialized = MTAPI_TRUE; @@ -208,6 +209,9 @@ void embb_mtapi_thread_context_finalize(embb_mtapi_thread_context_t* that) { that->private_queue = MTAPI_NULL; } + embb_atomic_destroy_int(&that->is_sleeping); + embb_atomic_destroy_int(&that->run); + that->priorities = 0; that->is_initialized = MTAPI_FALSE; diff --git a/mtapi_c/test/embb_mtapi_test_error.cc b/mtapi_c/test/embb_mtapi_test_error.cc index d7d8d91..57cb1e0 100644 --- a/mtapi_c/test/embb_mtapi_test_error.cc +++ b/mtapi_c/test/embb_mtapi_test_error.cc @@ -733,8 +733,12 @@ void TestContext() { } void ErrorTest::TestBasic() { + embb_atomic_init_int(&wait, 0); + TestNodeNotInit(); TestParameter(); TestLimits(); TestContext(); + + embb_atomic_destroy_int(&wait); } diff --git a/mtapi_c/test/embb_mtapi_test_plugin.cc b/mtapi_c/test/embb_mtapi_test_plugin.cc index 53706e1..c5bc34f 100644 --- a/mtapi_c/test/embb_mtapi_test_plugin.cc +++ b/mtapi_c/test/embb_mtapi_test_plugin.cc @@ -84,8 +84,8 @@ void plugin_initialize( plugin_task.id = 0; plugin_task.tag = 0; - embb_atomic_store_int(&plugin_running, 1); - embb_atomic_store_int(&plugin_task_available, 0); + embb_atomic_init_int(&plugin_running, 1); + embb_atomic_init_int(&plugin_task_available, 0); err = embb_thread_create(&plugin_thread, NULL, plugin_thread_function, NULL); if (EMBB_SUCCESS == err) { @@ -108,6 +108,9 @@ void plugin_finalize( local_status = MTAPI_SUCCESS; } + embb_atomic_destroy_int(&plugin_task_available); + embb_atomic_destroy_int(&plugin_running); + mtapi_status_set(status, local_status); } diff --git a/mtapi_c/test/main.cc b/mtapi_c/test/main.cc index 6fb351e..24bf377 100644 --- a/mtapi_c/test/main.cc +++ b/mtapi_c/test/main.cc @@ -40,6 +40,7 @@ #include #include +#include PT_MAIN("MTAPI C") { embb_log_set_log_level(EMBB_LOG_LEVEL_NONE); diff --git a/mtapi_cpp/src/node.cc b/mtapi_cpp/src/node.cc index e8dbedc..dd8e2f5 100644 --- a/mtapi_cpp/src/node.cc +++ b/mtapi_cpp/src/node.cc @@ -32,7 +32,7 @@ namespace mtapi { embb::mtapi::Node * embb::mtapi::Node::node_instance_ = NULL; #if MTAPI_CPP_AUTOMATIC_INITIALIZE -static embb_spinlock_t init_mutex = { { 0 } }; +static EMBB_BASE_BASIC_TYPE_SIZE_4 init_mutex = 0; #endif void Node::Initialize( @@ -68,13 +68,18 @@ void Node::Initialize( Node & Node::GetInstance() { #if MTAPI_CPP_AUTOMATIC_INITIALIZE if (!IsInitialized()) { - embb_spin_lock(&init_mutex); + EMBB_BASE_BASIC_TYPE_SIZE_4 compare = 0; + while (0 == embb_internal__atomic_compare_and_swap_4( + &init_mutex, &compare, 1)) { + compare = 0; + embb_thread_yield(); + } if (!IsInitialized()) { Node::Initialize( MTAPI_CPP_AUTOMATIC_DOMAIN_ID, MTAPI_CPP_AUTOMATIC_NODE_ID); atexit(Node::Finalize); } - embb_spin_unlock(&init_mutex); + embb_internal__atomic_store_4(&init_mutex, 0); } return *node_instance_; #else diff --git a/mtapi_cpp/test/main.cc b/mtapi_cpp/test/main.cc index 2e5d7f5..0e947d4 100644 --- a/mtapi_cpp/test/main.cc +++ b/mtapi_cpp/test/main.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/mtapi_plugins_c/mtapi_network_c/src/embb_mtapi_network.c b/mtapi_plugins_c/mtapi_network_c/src/embb_mtapi_network.c index 25cf135..9bac593 100644 --- a/mtapi_plugins_c/mtapi_network_c/src/embb_mtapi_network.c +++ b/mtapi_plugins_c/mtapi_network_c/src/embb_mtapi_network.c @@ -654,14 +654,16 @@ void mtapi_network_plugin_initialize( plugin->socket_count = 0; plugin->buffer_size = 0; plugin->sockets = NULL; - embb_atomic_store_int(&plugin->run, 0); err = embb_mtapi_network_initialize(); if (0 == err) return; + embb_atomic_init_int(&plugin->run, 0); + err = embb_mtapi_network_buffer_initialize( &plugin->recv_buffer, (int)buffer_size); if (0 == err) { + embb_atomic_destroy_int(&plugin->run); embb_mtapi_network_finalize(); return; } @@ -670,6 +672,7 @@ void mtapi_network_plugin_initialize( &plugin->send_buffer, (int)buffer_size); if (0 == err) { embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); + embb_atomic_destroy_int(&plugin->run); embb_mtapi_network_finalize(); return; } @@ -684,6 +687,7 @@ void mtapi_network_plugin_initialize( embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); plugin->buffer_size = 0; + embb_atomic_destroy_int(&plugin->run); embb_mtapi_network_finalize(); return; } @@ -695,6 +699,7 @@ void mtapi_network_plugin_initialize( embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); plugin->buffer_size = 0; + embb_atomic_destroy_int(&plugin->run); embb_mtapi_network_finalize(); return; } @@ -707,6 +712,7 @@ void mtapi_network_plugin_initialize( embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); plugin->buffer_size = 0; + embb_atomic_destroy_int(&plugin->run); embb_mtapi_network_finalize(); return; } @@ -723,6 +729,7 @@ void mtapi_network_plugin_initialize( embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); plugin->buffer_size = 0; + embb_atomic_destroy_int(&plugin->run); embb_mtapi_network_finalize(); return; } @@ -741,6 +748,7 @@ void mtapi_network_plugin_initialize( embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); plugin->buffer_size = 0; + embb_atomic_destroy_int(&plugin->run); embb_mtapi_network_finalize(); return; } @@ -764,6 +772,9 @@ void mtapi_network_plugin_finalize( embb_mtapi_network_socket_finalize(&plugin->sockets[0]); embb_free(plugin->sockets); + + embb_atomic_destroy_int(&plugin->run); + embb_mtapi_network_finalize(); mtapi_status_set(status, local_status); diff --git a/mtapi_plugins_c/mtapi_network_c/test/main.cc b/mtapi_plugins_c/mtapi_network_c/test/main.cc index 4ddb86c..e0fc1db 100644 --- a/mtapi_plugins_c/mtapi_network_c/test/main.cc +++ b/mtapi_plugins_c/mtapi_network_c/test/main.cc @@ -30,6 +30,8 @@ #include #include +#include + PT_MAIN("MTAPI NETWORK") { PT_RUN(NetworkBufferTest); PT_RUN(NetworkSocketTest); diff --git a/mtapi_plugins_c/mtapi_opencl_c/test/main.cc b/mtapi_plugins_c/mtapi_opencl_c/test/main.cc index eab4b67..fda3578 100644 --- a/mtapi_plugins_c/mtapi_opencl_c/test/main.cc +++ b/mtapi_plugins_c/mtapi_opencl_c/test/main.cc @@ -29,6 +29,7 @@ #include #include +#include PT_MAIN("MTAPI OPENCL") { PT_RUN(LinkerTest);