Commit acdffd5a by Marcus Winter

Merge branch 'embb517_mutex_based_atomics' into development

# Conflicts:
#	README.md
parents 56b1fd02 8d67be2e
...@@ -85,6 +85,7 @@ option(INSTALL_DOCS "Specify whether Doxygen docs should be installed" ON) ...@@ -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(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(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(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 ## LOCAL INSTALLATION OF SUBPROJECT BINARIES
# #
...@@ -106,6 +107,14 @@ else() ...@@ -106,6 +107,14 @@ else()
endif() endif()
message(" (set with command line option -DUSE_AUTOMATIC_INITIALIZATION=ON/OFF)") 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) include(CMakeCommon/SetCompilerFlags.cmake)
SetGNUCompilerFlags(compiler_libs compiler_flags) SetGNUCompilerFlags(compiler_libs compiler_flags)
SetVisualStudioCompilerFlags(compiler_libs compiler_flags) SetVisualStudioCompilerFlags(compiler_libs compiler_flags)
......
...@@ -125,6 +125,9 @@ EMB² can be built with C++ exception handling (default) or without exceptions. ...@@ -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. 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. 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`. 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`.
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#include <functional> #include <functional>
#include <embb/base/c/memory_allocation.h> #include <embb/base/c/memory_allocation.h>
#include <embb/base/c/atomic.h>
#define THIS_DOMAIN_ID 1 #define THIS_DOMAIN_ID 1
#define THIS_NODE_ID 1 #define THIS_NODE_ID 1
...@@ -81,7 +83,4 @@ PT_MAIN("Algorithms") { ...@@ -81,7 +83,4 @@ PT_MAIN("Algorithms") {
embb::mtapi::Node::Finalize(); embb::mtapi::Node::Finalize();
PT_EXPECT(embb_get_bytes_allocated() == 0); PT_EXPECT(embb_get_bytes_allocated() == 0);
// std::cout << "please press return to continue..." << std::endl;
// std::cin.get();
} }
...@@ -85,9 +85,41 @@ ...@@ -85,9 +85,41 @@
#ifdef DOXYGEN #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. * 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 * \see \ref general_desc_atomic_base "Detailed description" for general
* information and the meaning of \b TYPE. * information and the meaning of \b TYPE.
...@@ -95,12 +127,12 @@ ...@@ -95,12 +127,12 @@
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE void embb_atomic_and_assign_TYPE( void embb_atomic_and_assign_TYPE(
embb_atomic_TYPE* variable, embb_atomic_TYPE* variable,
/**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for /**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for
the "and" operation and is used to store the result. */ the "and" operation and is used to store the result. */
TYPE value 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( ...@@ -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 * to the value of \p expected. Otherwise, stores the value of \p variable in
* \p expected. * \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 * \return != 0 if the values of \p variable and \p expected were equivalent \n
* 0 otherwise * 0 otherwise
* *
...@@ -120,7 +154,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_and_assign_TYPE( ...@@ -120,7 +154,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_and_assign_TYPE(
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE int embb_atomic_compare_and_swap_TYPE( int embb_atomic_compare_and_swap_TYPE(
embb_atomic_TYPE* variable, embb_atomic_TYPE* variable,
/**< [IN,OUT] Pointer to atomic variable */ /**< [IN,OUT] Pointer to atomic variable */
TYPE* expected, TYPE* expected,
...@@ -132,6 +166,8 @@ EMBB_PLATFORM_INLINE int embb_atomic_compare_and_swap_TYPE( ...@@ -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. * 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 * \return The value before the operation
* *
* \see \ref general_desc_atomic_base "Detailed description" for general * \see \ref general_desc_atomic_base "Detailed description" for general
...@@ -140,7 +176,7 @@ EMBB_PLATFORM_INLINE int embb_atomic_compare_and_swap_TYPE( ...@@ -140,7 +176,7 @@ EMBB_PLATFORM_INLINE int embb_atomic_compare_and_swap_TYPE(
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE( TYPE embb_atomic_fetch_and_add_TYPE(
embb_atomic_TYPE* variable, embb_atomic_TYPE* variable,
/**< [IN,OUT] Pointer to atomic variable*/ /**< [IN,OUT] Pointer to atomic variable*/
TYPE value TYPE value
...@@ -150,6 +186,8 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE( ...@@ -150,6 +186,8 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE(
/** /**
* Loads the value of \p variable and returns it. * 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. * \return The value of the atomic variable.
* *
* \see \ref general_desc_atomic_base "Detailed description" for general * \see \ref general_desc_atomic_base "Detailed description" for general
...@@ -158,7 +196,7 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE( ...@@ -158,7 +196,7 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_fetch_and_add_TYPE(
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE TYPE embb_atomic_load_TYPE( TYPE embb_atomic_load_TYPE(
const embb_atomic_TYPE* variable const embb_atomic_TYPE* variable
/**< [IN] Pointer to atomic variable */ /**< [IN] Pointer to atomic variable */
); );
...@@ -169,12 +207,13 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_load_TYPE( ...@@ -169,12 +207,13 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_load_TYPE(
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \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. * 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 * \see \ref general_desc_atomic_base "Detailed description" for general
* information and the meaning of \b TYPE. * information and the meaning of \b TYPE.
...@@ -182,7 +221,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_memory_barrier(); ...@@ -182,7 +221,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_memory_barrier();
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE void embb_atomic_or_assign_TYPE( void embb_atomic_or_assign_TYPE(
embb_atomic_TYPE* variable, embb_atomic_TYPE* variable,
/**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for /**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for
the "or" operation and is used to store the result. */ the "or" operation and is used to store the result. */
...@@ -193,13 +232,15 @@ EMBB_PLATFORM_INLINE void embb_atomic_or_assign_TYPE( ...@@ -193,13 +232,15 @@ EMBB_PLATFORM_INLINE void embb_atomic_or_assign_TYPE(
/** /**
* Stores \p value in \p variable. * 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 * \see \ref general_desc_atomic_base "Detailed description" for general
* information and the meaning of \b TYPE. * information and the meaning of \b TYPE.
* *
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE( void embb_atomic_store_TYPE(
embb_atomic_TYPE* variable, embb_atomic_TYPE* variable,
/**< [IN,OUT] Pointer to atomic variable */ /**< [IN,OUT] Pointer to atomic variable */
int value int value
...@@ -209,6 +250,8 @@ EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE( ...@@ -209,6 +250,8 @@ EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE(
/** /**
* Swaps the current value of \p variable with \p value. * 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 * \return The old value of \p variable
* *
* \see \ref general_desc_atomic_base "Detailed description" for general * \see \ref general_desc_atomic_base "Detailed description" for general
...@@ -217,7 +260,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE( ...@@ -217,7 +260,7 @@ EMBB_PLATFORM_INLINE void embb_atomic_store_TYPE(
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE TYPE embb_atomic_swap_TYPE( TYPE embb_atomic_swap_TYPE(
embb_atomic_TYPE* variable, embb_atomic_TYPE* variable,
/**< [IN,OUT] Pointer to atomic variable whose value is swapped */ /**< [IN,OUT] Pointer to atomic variable whose value is swapped */
TYPE value TYPE value
...@@ -227,7 +270,8 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_swap_TYPE( ...@@ -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. * 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 * \see \ref general_desc_atomic_base "Detailed description" for general
* information and the meaning of \b TYPE. * information and the meaning of \b TYPE.
...@@ -235,7 +279,7 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_swap_TYPE( ...@@ -235,7 +279,7 @@ EMBB_PLATFORM_INLINE TYPE embb_atomic_swap_TYPE(
* \ingroup C_BASE_ATOMIC * \ingroup C_BASE_ATOMIC
* \waitfree * \waitfree
*/ */
EMBB_PLATFORM_INLINE void embb_atomic_xor_assign_TYPE( void embb_atomic_xor_assign_TYPE(
embb_atomic_TYPE* variable, embb_atomic_TYPE* variable,
/**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for /**< [IN,OUT] Pointer to atomic variable which serves as left-hand side for
the "xor" operation and is used to store the result. */ the "xor" operation and is used to store the result. */
...@@ -248,10 +292,62 @@ EMBB_PLATFORM_INLINE void embb_atomic_xor_assign_TYPE( ...@@ -248,10 +292,62 @@ EMBB_PLATFORM_INLINE void embb_atomic_xor_assign_TYPE(
extern "C" { extern "C" {
#endif #endif
#include <embb/base/c/internal/cmake_config.h>
#ifdef EMBB_THREADING_ANALYSIS_MODE
#include <embb/base/c/internal/platform.h>
#include <assert.h>
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 <embb/base/c/internal/platform.h> #include <embb/base/c/internal/platform.h>
#include <embb/base/c/internal/atomic/atomic_sizes.h> #include <embb/base/c/internal/atomic/atomic_sizes.h>
#include <embb/base/c/internal/atomic/atomic_variables.h> #include <embb/base/c/internal/atomic/atomic_variables.h>
#include <embb/base/c/internal/macro_helper.h> #include <embb/base/c/internal/macro_helper.h>
#include <embb/base/c/internal/atomic/init.h>
#include <embb/base/c/internal/atomic/destroy.h>
#include <embb/base/c/internal/atomic/load.h> #include <embb/base/c/internal/atomic/load.h>
#include <embb/base/c/internal/atomic/and_assign.h> #include <embb/base/c/internal/atomic/and_assign.h>
#include <embb/base/c/internal/atomic/store.h> #include <embb/base/c/internal/atomic/store.h>
......
...@@ -152,8 +152,11 @@ EMBB_DEFINE_AND_ASSIGN(4, "") ...@@ -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_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;\ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ 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 *) \ 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); \ (&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
} }
#undef EMBB_ATOMIC_METHOD_TO_GENERATE #undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
...@@ -29,11 +29,54 @@ ...@@ -29,11 +29,54 @@
#include <stddef.h> #include <stddef.h>
#include <embb/base/c/internal/macro_helper.h> #include <embb/base/c/internal/macro_helper.h>
#include <embb/base/c/internal/cmake_config.h>
#ifdef EMBB_PLATFORM_COMPILER_MSVC #ifdef EMBB_PLATFORM_COMPILER_MSVC
#include <intrin.h> #include <intrin.h>
#endif #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( \ #define EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE( \
EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, \
EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX) \ EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX) \
...@@ -42,6 +85,10 @@ ...@@ -42,6 +85,10 @@
volatile EMBB_ATOMIC_PARAMETER_TYPE_NATIVE internal_variable; \ volatile EMBB_ATOMIC_PARAMETER_TYPE_NATIVE internal_variable; \
} EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX); } EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX);
#endif
#endif
EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(char, char) EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(char, char)
EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(short, short) EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(short, short)
EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(unsigned short, unsigned_short) EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(unsigned short, unsigned_short)
......
...@@ -138,8 +138,12 @@ EMBB_DEFINE_COMPARE_AND_SWAP(4, "") ...@@ -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_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;\ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) desired_pun;\
memcpy(&desired_pun, &desired, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ 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); \ (&(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 #undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
/*
* 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 <embb/base/c/internal/config.h>
#include <embb/base/c/internal/atomic/atomic_sizes.h>
#include <embb/base/c/internal/macro_helper.h>
#include <embb/base/c/internal/atomic/atomic_variables.h>
#include <string.h>
/*
* 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 <embb/base/c/internal/atomic/generate_atomic_implementation_template.h>
#undef EMBB_ATOMIC_METHOD_TO_GENERATE
#endif //DOXYGEN
#endif //EMBB_BASE_C_INTERNAL_ATOMIC_INIT_H_
...@@ -107,9 +107,6 @@ EMBB_DEFINE_FETCH_AND_ADD(8, "q") ...@@ -107,9 +107,6 @@ EMBB_DEFINE_FETCH_AND_ADD(8, "q")
: "memory", "cc" ); \ : "memory", "cc" ); \
return result; \ return result; \
} }
/* return __sync_fetch_and_add( \
pointer_to_value, new_value); \
}*/
#else #else
#error "No atomic fetch and store implementation found" #error "No atomic fetch and store implementation found"
#endif #endif
...@@ -131,9 +128,12 @@ EMBB_DEFINE_FETCH_AND_ADD(4, "") ...@@ -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_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; \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ 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) 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 *)\ (EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\
(&(variable->internal_variable)), value_pun); \ (&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \
memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
return return_val_pun; \ return return_val_pun; \
......
/*
* 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 <embb/base/c/internal/config.h>
#include <embb/base/c/internal/atomic/atomic_sizes.h>
#include <embb/base/c/internal/macro_helper.h>
#include <embb/base/c/internal/atomic/atomic_variables.h>
#include <embb/base/c/internal/atomic/store.h>
#include <string.h>
/*
* 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 <embb/base/c/internal/atomic/generate_atomic_implementation_template.h>
#undef EMBB_ATOMIC_METHOD_TO_GENERATE
#endif //DOXYGEN
#endif //EMBB_BASE_C_INTERNAL_ATOMIC_INIT_H_
...@@ -119,10 +119,13 @@ EMBB_DEFINE_LOAD(4, "") ...@@ -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) \ #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)(\ 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) \ 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)(\ 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_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; \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \
memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
return return_val_pun; \ return return_val_pun; \
......
...@@ -123,8 +123,11 @@ EMBB_DEFINE_OR_ASSIGN(4, "") ...@@ -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_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;\ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ 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 *)\ 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); \ (&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
} }
#undef EMBB_ATOMIC_METHOD_TO_GENERATE #undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
...@@ -118,8 +118,11 @@ EMBB_DEFINE_STORE(4, "") ...@@ -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_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; \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ 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 *)\ 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); \ (&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
} }
#undef EMBB_ATOMIC_METHOD_TO_GENERATE #undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
...@@ -127,8 +127,11 @@ EMBB_DEFINE_SWAP(4, "") ...@@ -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_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; \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ 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) \ 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); \ 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; \ EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \
memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \ memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
return return_val_pun; \ return return_val_pun; \
......
...@@ -125,8 +125,11 @@ EMBB_DEFINE_XOR_ASSIGN(4, "") ...@@ -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_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;\ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\ 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 *)\ 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); \ (&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
} }
#undef EMBB_ATOMIC_METHOD_TO_GENERATE #undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
...@@ -53,7 +53,14 @@ ...@@ -53,7 +53,14 @@
*/ */
#cmakedefine EMBB_PLATFORM_HAS_GLIB_CPU #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_MAJOR ${EMBB_BASE_VERSION_MAJOR}
#define EMBB_BASE_VERSION_MINOR ${EMBB_BASE_VERSION_MINOR} #define EMBB_BASE_VERSION_MINOR ${EMBB_BASE_VERSION_MINOR}
#define EMBB_BASE_VERSION_PATCH ${EMBB_BASE_VERSION_PATCH} #define EMBB_BASE_VERSION_PATCH ${EMBB_BASE_VERSION_PATCH}
......
...@@ -33,7 +33,7 @@ int embb_counter_init(embb_counter_t* counter) { ...@@ -33,7 +33,7 @@ int embb_counter_init(embb_counter_t* counter) {
if (counter == NULL) { if (counter == NULL) {
return EMBB_ERROR; return EMBB_ERROR;
} }
embb_atomic_store_unsigned_int(&(counter->value), 0); embb_atomic_init_unsigned_int(&(counter->value), 0);
return EMBB_SUCCESS; return EMBB_SUCCESS;
} }
...@@ -55,7 +55,7 @@ unsigned int embb_counter_decrement(embb_counter_t* counter) { ...@@ -55,7 +55,7 @@ unsigned int embb_counter_decrement(embb_counter_t* counter) {
void embb_counter_destroy(embb_counter_t* counter) { void embb_counter_destroy(embb_counter_t* counter) {
assert(counter != NULL); assert(counter != NULL);
EMBB_UNUSED_IN_RELEASE(counter); embb_atomic_destroy_unsigned_int(&(counter->value));
} }
...@@ -40,18 +40,18 @@ ...@@ -40,18 +40,18 @@
* This function has local scope. * This function has local scope.
*/ */
static int embb_max_number_thread_indices_max = 0; 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() { unsigned int* embb_max_number_thread_indices() {
int compare_to = 0; EMBB_BASE_BASIC_TYPE_SIZE_4 compare_to = 0;
if (embb_atomic_load_int(&embb_max_number_thread_indices_flag) != 2) { if (embb_internal__atomic_load_4(&embb_max_number_thread_indices_flag) != 2) {
if (embb_atomic_compare_and_swap_int( if (embb_internal__atomic_compare_and_swap_4(
&embb_max_number_thread_indices_flag, &compare_to, 1)) { &embb_max_number_thread_indices_flag, &compare_to, 1)) {
embb_max_number_thread_indices_max = embb_max_number_thread_indices_max =
(int)(embb_core_count_available() * 2); (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; return (unsigned int*) &embb_max_number_thread_indices_max;
} }
...@@ -61,17 +61,17 @@ unsigned int* embb_max_number_thread_indices() { ...@@ -61,17 +61,17 @@ unsigned int* embb_max_number_thread_indices() {
* *
* This function has local scope. * 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; static embb_counter_t embb_thread_index_counter_index;
embb_counter_t* embb_thread_index_counter() { embb_counter_t* embb_thread_index_counter() {
int compare_to = 0; EMBB_BASE_BASIC_TYPE_SIZE_4 compare_to = 0;
if (embb_atomic_load_int(&embb_thread_index_counter_flag) != 2) { if (embb_internal__atomic_load_4(&embb_thread_index_counter_flag) != 2) {
if (embb_atomic_compare_and_swap_int( if (embb_internal__atomic_compare_and_swap_4(
&embb_thread_index_counter_flag, &compare_to, 1)) { &embb_thread_index_counter_flag, &compare_to, 1)) {
embb_counter_init(&embb_thread_index_counter_index); 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; return &embb_thread_index_counter_index;
} }
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#ifdef EMBB_DEBUG #ifdef EMBB_DEBUG
static embb_atomic_long embb_bytes_allocated = { 0 }; static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_bytes_allocated = 0;
enum { enum {
// Make the marking unlikely to be something else // Make the marking unlikely to be something else
...@@ -49,7 +49,7 @@ void* embb_alloc(size_t bytes) { ...@@ -49,7 +49,7 @@ void* embb_alloc(size_t bytes) {
if (allocated == NULL) if (allocated == NULL)
return NULL; return NULL;
embb_atomic_fetch_and_add_long( embb_internal__atomic_fetch_and_add_4(
&embb_bytes_allocated, (long)bytes_to_allocate); &embb_bytes_allocated, (long)bytes_to_allocate);
size_t* x_as_size_type = (size_t*)allocated; size_t* x_as_size_type = (size_t*)allocated;
...@@ -72,7 +72,7 @@ void embb_free(void * ptr) { ...@@ -72,7 +72,7 @@ void embb_free(void * ptr) {
(*alloc_type) = (size_t)INVALID_ALLOCATION; (*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))); &embb_bytes_allocated, (long)(0 - (size_t)(*bytes_allocated)));
free((size_t*)ptr - 2); free((size_t*)ptr - 2);
...@@ -127,7 +127,7 @@ void* embb_alloc_aligned(size_t alignment, size_t size) { ...@@ -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[-2] = (size_t)allocated;
x_as_size_type[-3] = bytes_to_allocate; 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); &embb_bytes_allocated, (long)bytes_to_allocate);
return x; return x;
...@@ -144,14 +144,14 @@ void embb_free_aligned(void* ptr) { ...@@ -144,14 +144,14 @@ void embb_free_aligned(void* ptr) {
ptr_conv[-1] = (size_t)INVALID_ALLOCATION; 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])); &embb_bytes_allocated, (long)((long)0 - ptr_conv[-3]));
free((void*)ptr_conv[-2]); free((void*)ptr_conv[-2]);
} }
size_t embb_get_bytes_allocated() { 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 #else // EMBB_DEBUG
......
...@@ -147,9 +147,7 @@ int embb_spin_init(embb_spinlock_t* spinlock) { ...@@ -147,9 +147,7 @@ int embb_spin_init(embb_spinlock_t* spinlock) {
if (NULL == spinlock) { if (NULL == spinlock) {
return EMBB_ERROR; return EMBB_ERROR;
} }
// For now, store the initial value. In the future will use atomic init embb_atomic_init_int(&spinlock->atomic_spin_variable_, 0);
// function (as soon as available).
embb_atomic_store_int(&spinlock->atomic_spin_variable_, 0);
return EMBB_SUCCESS; return EMBB_SUCCESS;
} }
...@@ -207,7 +205,5 @@ int embb_spin_unlock(embb_spinlock_t* spinlock) { ...@@ -207,7 +205,5 @@ int embb_spin_unlock(embb_spinlock_t* spinlock) {
void embb_spin_destroy(embb_spinlock_t* spinlock) { void embb_spin_destroy(embb_spinlock_t* spinlock) {
assert(NULL != spinlock); assert(NULL != spinlock);
// for now, doing nothing here... in future, will call the respective embb_atomic_destroy_int(&spinlock->atomic_spin_variable_);
// destroy function for atomics...
EMBB_UNUSED(spinlock);
} }
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <embb/base/c/log.h> #include <embb/base/c/log.h>
#include <iostream> #include <iostream>
#include <embb/base/c/atomic.h>
#include <embb/base/c/memory_allocation.h> #include <embb/base/c/memory_allocation.h>
using embb::base::test::AllocTest; using embb::base::test::AllocTest;
......
...@@ -36,13 +36,21 @@ namespace embb { ...@@ -36,13 +36,21 @@ namespace embb {
namespace base { namespace base {
namespace test { namespace test {
embb_atomic_int flag;
ThreadIndexTest::ThreadIndexTest() ThreadIndexTest::ThreadIndexTest()
: number_threads_(partest::TestSuite::GetDefaultNumThreads()) { : number_threads_(partest::TestSuite::GetDefaultNumThreads()) {
embb_atomic_init_int(&flag, 1);
CreateUnit("Test 0 indices").Add(&ThreadIndexTest::Test0, this); CreateUnit("Test 0 indices").Add(&ThreadIndexTest::Test0, this);
CreateUnit("Test 1 index").Add(&ThreadIndexTest::Test1, this); CreateUnit("Test 1 index").Add(&ThreadIndexTest::Test1, this);
CreateUnit("Test N indices").Add(&ThreadIndexTest::TestN, this, 1); CreateUnit("Test N indices").Add(&ThreadIndexTest::TestN, this, 1);
} }
ThreadIndexTest::~ThreadIndexTest() {
embb_atomic_destroy_int(&flag);
}
void ThreadIndexTest::Test0() { void ThreadIndexTest::Test0() {
embb_internal_thread_index_reset(); embb_internal_thread_index_reset();
unsigned int old_max = embb_thread_get_max_count(); unsigned int old_max = embb_thread_get_max_count();
...@@ -78,8 +86,6 @@ void ThreadIndexTest::Test1() { ...@@ -78,8 +86,6 @@ void ThreadIndexTest::Test1() {
embb_internal_thread_index_set_max(old_max); embb_internal_thread_index_set_max(old_max);
} }
embb_atomic_int flag = { 1 };
void ThreadIndexTest::TestN() { void ThreadIndexTest::TestN() {
embb_internal_thread_index_reset(); embb_internal_thread_index_reset();
unsigned int old_max = embb_thread_get_max_count(); unsigned int old_max = embb_thread_get_max_count();
...@@ -106,6 +112,8 @@ void ThreadIndexTest::TestN() { ...@@ -106,6 +112,8 @@ void ThreadIndexTest::TestN() {
embb_thread_join(&thread, NULL); embb_thread_join(&thread, NULL);
delete[] threads; delete[] threads;
embb_internal_thread_index_set_max(old_max); embb_internal_thread_index_set_max(old_max);
embb_atomic_destroy_int(&flag);
} }
int ThreadStart(void* arg) { int ThreadStart(void* arg) {
......
...@@ -36,10 +36,15 @@ namespace test { ...@@ -36,10 +36,15 @@ namespace test {
class ThreadIndexTest : public partest::TestCase { class ThreadIndexTest : public partest::TestCase {
public: public:
/** /**
* Adds test methods. * Adds test methods and allocates temporary data.
*/ */
ThreadIndexTest(); ThreadIndexTest();
/**
* Destroys temporary data.
*/
~ThreadIndexTest();
private: private:
/** /**
* Tests 0 available indices. * Tests 0 available indices.
......
...@@ -117,8 +117,10 @@ FetchAndAdd(DifferenceType val) { ...@@ -117,8 +117,10 @@ FetchAndAdd(DifferenceType val) {
NativeType native_desired; NativeType native_desired;
memcpy(&native_desired, &desired, sizeof(desired)); memcpy(&native_desired, &desired, sizeof(desired));
EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex);
NativeType storage_value = fetch_and_add_implementation<NativeType>:: NativeType storage_value = fetch_and_add_implementation<NativeType>::
fetch_and_add(&this->AtomicValue, native_desired); fetch_and_add(&this->AtomicValue, native_desired);
EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex);
memcpy(&return_value, &storage_value, sizeof(return_value)); memcpy(&return_value, &storage_value, sizeof(return_value));
return return_value; return return_value;
......
...@@ -58,6 +58,10 @@ class AtomicBase { ...@@ -58,6 +58,10 @@ class AtomicBase {
mutable NativeType AtomicValue; mutable NativeType AtomicValue;
#ifdef EMBB_THREADING_ANALYSIS_MODE
mutable embb_mutex_t internal_mutex;
#endif
public: public:
/** /**
* Default constructor. * Default constructor.
...@@ -73,6 +77,11 @@ class AtomicBase { ...@@ -73,6 +77,11 @@ class AtomicBase {
*/ */
explicit AtomicBase(BaseType val); explicit AtomicBase(BaseType val);
/**
* Destructor.
*/
~AtomicBase();
// The members below are documented in atomic.h // The members below are documented in atomic.h
BaseType operator=(BaseType val); BaseType operator=(BaseType val);
operator BaseType() const; operator BaseType() const;
...@@ -88,14 +97,21 @@ class AtomicBase { ...@@ -88,14 +97,21 @@ class AtomicBase {
template<typename BaseType> template<typename BaseType>
inline AtomicBase<BaseType>::AtomicBase() : AtomicValue(0) { inline AtomicBase<BaseType>::AtomicBase() : AtomicValue(0) {
EMBB_ATOMIC_MUTEX_INIT(internal_mutex);
} }
template<typename BaseType> template<typename BaseType>
inline AtomicBase<BaseType>::AtomicBase(BaseType val) /*: AtomicValue(val)*/ { inline AtomicBase<BaseType>::AtomicBase(BaseType val) /*: AtomicValue(val)*/ {
EMBB_ATOMIC_MUTEX_INIT(internal_mutex);
memcpy(&AtomicValue, &val, sizeof(AtomicValue)); memcpy(&AtomicValue, &val, sizeof(AtomicValue));
} }
template<typename BaseType> template<typename BaseType>
inline AtomicBase<BaseType>::~AtomicBase() {
EMBB_ATOMIC_MUTEX_DESTROY(internal_mutex);
}
template<typename BaseType>
inline BaseType AtomicBase<BaseType>::operator=(BaseType val) { inline BaseType AtomicBase<BaseType>::operator=(BaseType val) {
Store(val); Store(val);
return val; return val;
...@@ -132,16 +148,20 @@ inline void AtomicBase<BaseType>::Store(BaseType val) { ...@@ -132,16 +148,20 @@ inline void AtomicBase<BaseType>::Store(BaseType val) {
// anyway... // anyway...
memcpy(&storage_value, &val, sizeof(storage_value)); memcpy(&storage_value, &val, sizeof(storage_value));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
store_implementation< NativeType > store_implementation< NativeType >
::Store(&AtomicValue, storage_value); ::Store(&AtomicValue, storage_value);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
} }
template<typename BaseType> template<typename BaseType>
inline BaseType AtomicBase<BaseType>::Load() const { inline BaseType AtomicBase<BaseType>::Load() const {
BaseType return_value; BaseType return_value;
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
NativeType storage_value = NativeType storage_value =
load_implementation< NativeType >::Load(&AtomicValue); load_implementation< NativeType >::Load(&AtomicValue);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
memcpy(&return_value, &storage_value, sizeof(return_value)); memcpy(&return_value, &storage_value, sizeof(return_value));
...@@ -155,8 +175,10 @@ inline BaseType AtomicBase<BaseType>::Swap(BaseType val) { ...@@ -155,8 +175,10 @@ inline BaseType AtomicBase<BaseType>::Swap(BaseType val) {
memcpy(&storage_value, &val, sizeof(storage_value)); memcpy(&storage_value, &val, sizeof(storage_value));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
NativeType storage_value2 = swap_implementation< NativeType > NativeType storage_value2 = swap_implementation< NativeType >
::Swap(&AtomicValue, storage_value); ::Swap(&AtomicValue, storage_value);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
memcpy(&return_value, &storage_value2, sizeof(return_value)); memcpy(&return_value, &storage_value2, sizeof(return_value));
...@@ -172,10 +194,12 @@ CompareAndSwap(BaseType& expected, BaseType desired) { ...@@ -172,10 +194,12 @@ CompareAndSwap(BaseType& expected, BaseType desired) {
memcpy(&native_expected, &expected, sizeof(expected)); memcpy(&native_expected, &expected, sizeof(expected));
memcpy(&native_desired, &desired, sizeof(desired)); memcpy(&native_desired, &desired, sizeof(desired));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
bool return_val = bool return_val =
(compare_and_swap_implementation<NativeType>:: (compare_and_swap_implementation<NativeType>::
compare_and_swap(&AtomicValue, &native_expected, native_desired)) !=0 compare_and_swap(&AtomicValue, &native_expected, native_desired)) !=0
? true : false; ? true : false;
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
memcpy(&expected, &native_expected, sizeof(expected)); memcpy(&expected, &native_expected, sizeof(expected));
......
...@@ -93,8 +93,10 @@ inline void AtomicInteger<BaseType>::operator&=(BaseType val) { ...@@ -93,8 +93,10 @@ inline void AtomicInteger<BaseType>::operator&=(BaseType val) {
NativeType native_operand; NativeType native_operand;
memcpy(&native_operand, &val, sizeof(val)); memcpy(&native_operand, &val, sizeof(val));
EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex);
and_assign_implementation<NativeType>:: and_assign_implementation<NativeType>::
and_assign(&this->AtomicValue, native_operand); and_assign(&this->AtomicValue, native_operand);
EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex);
} }
template<typename BaseType> template<typename BaseType>
...@@ -102,8 +104,10 @@ inline void AtomicInteger<BaseType>::operator|=(BaseType val) { ...@@ -102,8 +104,10 @@ inline void AtomicInteger<BaseType>::operator|=(BaseType val) {
NativeType native_operand; NativeType native_operand;
memcpy(&native_operand, &val, sizeof(val)); memcpy(&native_operand, &val, sizeof(val));
EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex);
or_assign_implementation<NativeType>:: or_assign_implementation<NativeType>::
or_assign(&this->AtomicValue, native_operand); or_assign(&this->AtomicValue, native_operand);
EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex);
} }
template<typename BaseType> template<typename BaseType>
...@@ -111,8 +115,10 @@ inline void AtomicInteger<BaseType>::operator^=(BaseType val) { ...@@ -111,8 +115,10 @@ inline void AtomicInteger<BaseType>::operator^=(BaseType val) {
NativeType native_operand; NativeType native_operand;
memcpy(&native_operand, &val, sizeof(val)); memcpy(&native_operand, &val, sizeof(val));
EMBB_ATOMIC_MUTEX_LOCK(this->internal_mutex);
xor_assign_implementation<NativeType>:: xor_assign_implementation<NativeType>::
xor_assign(&this->AtomicValue, native_operand); xor_assign(&this->AtomicValue, native_operand);
EMBB_ATOMIC_MUTEX_UNLOCK(this->internal_mutex);
} }
} // namespace atomic } // namespace atomic
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <memory_allocation_test.h> #include <memory_allocation_test.h>
#include <log_test.h> #include <log_test.h>
#include <embb/base/c/atomic.h>
#include <embb/base/c/memory_allocation.h> #include <embb/base/c/memory_allocation.h>
using embb::base::test::CoreSetTest; using embb::base::test::CoreSetTest;
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <embb/containers/object_pool.h> #include <embb/containers/object_pool.h>
#include <embb/containers/lock_free_stack.h> #include <embb/containers/lock_free_stack.h>
#include <embb/containers/lock_free_mpmc_queue.h> #include <embb/containers/lock_free_mpmc_queue.h>
#include <embb/base/c/memory_allocation.h>
#include <embb/base/c/atomic.h>
#ifdef EMBB_PLATFORM_COMPILER_MSVC #ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(pop) // Reset warning 4548 #pragma warning(pop) // Reset warning 4548
......
...@@ -84,13 +84,16 @@ class Inputs<T1, embb::base::internal::Nil, embb::base::internal::Nil, ...@@ -84,13 +84,16 @@ class Inputs<T1, embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::Allocation::Allocate( embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_)); sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) { for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 1; new(count_+ii) embb::base::Atomic<int>(1);
} }
} }
this->template Get<0>().SetSlices(slices_); this->template Get<0>().SetSlices(slices_);
} }
~Inputs() { ~Inputs() {
if (NULL != count_) { if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_); embb::base::Allocation::Free(count_);
} }
} }
...@@ -150,7 +153,7 @@ class Inputs<T1, T2, embb::base::internal::Nil, ...@@ -150,7 +153,7 @@ class Inputs<T1, T2, embb::base::internal::Nil,
embb::base::Allocation::Allocate( embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_)); sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) { for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 2; new(count_ + ii) embb::base::Atomic<int>(2);
} }
} }
this->template Get<0>().SetSlices(slices_); this->template Get<0>().SetSlices(slices_);
...@@ -158,6 +161,9 @@ class Inputs<T1, T2, embb::base::internal::Nil, ...@@ -158,6 +161,9 @@ class Inputs<T1, T2, embb::base::internal::Nil,
} }
~Inputs() { ~Inputs() {
if (NULL != count_) { if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_); embb::base::Allocation::Free(count_);
} }
} }
...@@ -222,7 +228,7 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil, ...@@ -222,7 +228,7 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil,
embb::base::Allocation::Allocate( embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_)); sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) { for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 3; new(count_ + ii) embb::base::Atomic<int>(3);
} }
} }
this->template Get<0>().SetSlices(slices_); this->template Get<0>().SetSlices(slices_);
...@@ -231,6 +237,9 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil, ...@@ -231,6 +237,9 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil,
} }
~Inputs() { ~Inputs() {
if (NULL != count_) { if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_); embb::base::Allocation::Free(count_);
} }
} }
...@@ -299,7 +308,7 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil> ...@@ -299,7 +308,7 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil>
embb::base::Allocation::Allocate( embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_)); sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) { for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 4; new(count_ + ii) embb::base::Atomic<int>(4);
} }
} }
this->template Get<0>().SetSlices(slices_); this->template Get<0>().SetSlices(slices_);
...@@ -309,6 +318,9 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil> ...@@ -309,6 +318,9 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil>
} }
~Inputs() { ~Inputs() {
if (NULL != count_) { if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_); embb::base::Allocation::Free(count_);
} }
} }
...@@ -383,7 +395,7 @@ class Inputs ...@@ -383,7 +395,7 @@ class Inputs
embb::base::Allocation::Allocate( embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_)); sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) { for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 5; new(count_ + ii) embb::base::Atomic<int>(5);
} }
} }
this->template Get<0>().SetSlices(slices_); this->template Get<0>().SetSlices(slices_);
...@@ -394,6 +406,9 @@ class Inputs ...@@ -394,6 +406,9 @@ class Inputs
} }
~Inputs() { ~Inputs() {
if (NULL != count_) { if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_); embb::base::Allocation::Free(count_);
} }
} }
......
...@@ -802,6 +802,9 @@ class Network : public internal::ClockListener { ...@@ -802,6 +802,9 @@ class Network : public internal::ClockListener {
sched_ = NULL; sched_ = NULL;
} }
if (NULL != sink_counter_) { if (NULL != sink_counter_) {
for (int ii = 0; ii < slices_; ii++) {
sink_counter_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(sink_counter_); embb::base::Allocation::Free(sink_counter_);
sink_counter_ = NULL; sink_counter_ = NULL;
} }
...@@ -1111,7 +1114,7 @@ class Network : public internal::ClockListener { ...@@ -1111,7 +1114,7 @@ class Network : public internal::ClockListener {
embb::base::Allocation::Allocate( embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_)); sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) { for (int ii = 0; ii < slices_; ii++) {
sink_counter_[ii] = 0; new(sink_counter_+ii) embb::base::Atomic<int>(0);
} }
} }
}; };
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <dataflow_cpp_test_simple.h> #include <dataflow_cpp_test_simple.h>
#include <dataflow_cpp_test_tuple.h> #include <dataflow_cpp_test_tuple.h>
#include <embb/base/c/atomic.h>
PT_MAIN("Dataflow C++") { PT_MAIN("Dataflow C++") {
PT_RUN(SimpleTest); PT_RUN(SimpleTest);
PT_RUN(TupleTest); PT_RUN(TupleTest);
......
...@@ -62,7 +62,7 @@ mtapi_action_hndl_t mtapi_ext_plugin_action_create( ...@@ -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->node_local_data_size = node_local_data_size;
new_action->enabled = MTAPI_TRUE; new_action->enabled = MTAPI_TRUE;
new_action->is_plugin_action = 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_start_function = task_start_function;
new_action->plugin_task_cancel_function = task_cancel_function; new_action->plugin_task_cancel_function = task_cancel_function;
...@@ -87,6 +87,7 @@ mtapi_action_hndl_t mtapi_ext_plugin_action_create( ...@@ -87,6 +87,7 @@ mtapi_action_hndl_t mtapi_ext_plugin_action_create(
action_handle = new_action->handle; action_handle = new_action->handle;
embb_mtapi_job_add_action(job, new_action); embb_mtapi_job_add_action(job, new_action);
} else { } else {
embb_mtapi_action_finalize(new_action);
embb_mtapi_action_pool_deallocate(node->action_pool, new_action); embb_mtapi_action_pool_deallocate(node->action_pool, new_action);
} }
} else { } else {
......
...@@ -49,6 +49,8 @@ embb_mtapi_pool_implementation(action) ...@@ -49,6 +49,8 @@ embb_mtapi_pool_implementation(action)
/* ---- CLASS MEMBERS ------------------------------------------------------ */ /* ---- CLASS MEMBERS ------------------------------------------------------ */
void embb_mtapi_action_initialize(embb_mtapi_action_t* that) { void embb_mtapi_action_initialize(embb_mtapi_action_t* that) {
assert(MTAPI_NULL != that);
that->action_function = NULL; that->action_function = NULL;
that->job_id = MTAPI_JOB_ID_INVALID; that->job_id = MTAPI_JOB_ID_INVALID;
that->domain_id = MTAPI_DOMAIN_ID_INVALID; that->domain_id = MTAPI_DOMAIN_ID_INVALID;
...@@ -57,15 +59,25 @@ void embb_mtapi_action_initialize(embb_mtapi_action_t* that) { ...@@ -57,15 +59,25 @@ void embb_mtapi_action_initialize(embb_mtapi_action_t* that) {
that->node_local_data = NULL; that->node_local_data = NULL;
that->node_local_data_size = 0; that->node_local_data_size = 0;
that->plugin_data = MTAPI_NULL; 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) { void embb_mtapi_action_finalize(embb_mtapi_action_t* that) {
assert(MTAPI_NULL != that);
if (that->is_plugin_action) { if (that->is_plugin_action) {
// TODO(mw): check status // TODO(mw): check status
that->plugin_action_finalize_function(that->handle, NULL); 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( static mtapi_boolean_t embb_mtapi_action_delete_visitor(
...@@ -140,7 +152,7 @@ mtapi_action_hndl_t mtapi_action_create( ...@@ -140,7 +152,7 @@ mtapi_action_hndl_t mtapi_action_create(
new_action->node_local_data_size = node_local_data_size; new_action->node_local_data_size = node_local_data_size;
new_action->enabled = MTAPI_TRUE; new_action->enabled = MTAPI_TRUE;
new_action->is_plugin_action = MTAPI_FALSE; 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; new_action->action_function = action_function;
...@@ -162,6 +174,7 @@ mtapi_action_hndl_t mtapi_action_create( ...@@ -162,6 +174,7 @@ mtapi_action_hndl_t mtapi_action_create(
action_handle = new_action->handle; action_handle = new_action->handle;
embb_mtapi_job_add_action(job, new_action); embb_mtapi_job_add_action(job, new_action);
} else { } else {
embb_mtapi_action_finalize(new_action);
embb_mtapi_action_pool_deallocate(node->action_pool, new_action); embb_mtapi_action_pool_deallocate(node->action_pool, new_action);
} }
} else { } else {
...@@ -337,8 +350,7 @@ void mtapi_action_delete( ...@@ -337,8 +350,7 @@ void mtapi_action_delete(
node, local_action->job_id); node, local_action->job_id);
embb_mtapi_job_remove_action(local_job, local_action); 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); embb_mtapi_action_pool_deallocate(node->action_pool, local_action);
} else { } else {
local_status = MTAPI_ERR_ACTION_INVALID; local_status = MTAPI_ERR_ACTION_INVALID;
......
...@@ -30,12 +30,12 @@ ...@@ -30,12 +30,12 @@
#include <embb_mtapi_alloc.h> #include <embb_mtapi_alloc.h>
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 * embb_mtapi_alloc_allocate(unsigned int bytes) {
void * ptr = embb_alloc(bytes); void * ptr = embb_alloc(bytes);
if (ptr != NULL) { 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); &embb_mtapi_alloc_bytes_allocated, sizeof(unsigned int)+bytes);
} }
return ptr; return ptr;
...@@ -48,9 +48,9 @@ void embb_mtapi_alloc_deallocate(void * ptr) { ...@@ -48,9 +48,9 @@ void embb_mtapi_alloc_deallocate(void * ptr) {
} }
void embb_mtapi_alloc_reset_bytes_allocated() { 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() { 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);
} }
...@@ -55,8 +55,8 @@ void embb_mtapi_group_initialize(embb_mtapi_group_t * that) { ...@@ -55,8 +55,8 @@ void embb_mtapi_group_initialize(embb_mtapi_group_t * that) {
assert(MTAPI_NULL != that); assert(MTAPI_NULL != that);
that->group_id = MTAPI_GROUP_ID_NONE; that->group_id = MTAPI_GROUP_ID_NONE;
embb_atomic_store_int(&that->deleted, MTAPI_FALSE); embb_atomic_init_int(&that->deleted, MTAPI_FALSE);
that->num_tasks.internal_variable = 0; embb_atomic_init_int(&that->num_tasks, 0);
embb_mtapi_task_queue_initialize(&that->queue); embb_mtapi_task_queue_initialize(&that->queue);
} }
...@@ -67,8 +67,8 @@ void embb_mtapi_group_initialize_with_node( ...@@ -67,8 +67,8 @@ void embb_mtapi_group_initialize_with_node(
assert(MTAPI_NULL != node); assert(MTAPI_NULL != node);
that->group_id = MTAPI_GROUP_ID_NONE; that->group_id = MTAPI_GROUP_ID_NONE;
embb_atomic_store_int(&that->deleted, MTAPI_FALSE); embb_atomic_init_int(&that->deleted, MTAPI_FALSE);
that->num_tasks.internal_variable = 0; embb_atomic_init_int(&that->num_tasks, 0);
embb_mtapi_task_queue_initialize_with_capacity( embb_mtapi_task_queue_initialize_with_capacity(
&that->queue, node->attributes.queue_limit); &that->queue, node->attributes.queue_limit);
} }
...@@ -77,7 +77,9 @@ void embb_mtapi_group_finalize(embb_mtapi_group_t * that) { ...@@ -77,7 +77,9 @@ void embb_mtapi_group_finalize(embb_mtapi_group_t * that) {
assert(MTAPI_NULL != that); assert(MTAPI_NULL != that);
embb_atomic_store_int(&that->deleted, MTAPI_TRUE); 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); embb_mtapi_task_queue_finalize(&that->queue);
} }
......
...@@ -105,7 +105,7 @@ void mtapi_initialize( ...@@ -105,7 +105,7 @@ void mtapi_initialize(
} }
if (MTAPI_SUCCESS == local_status) { 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 */ /* initialize storage */
embb_mtapi_job_initialize_list(node); embb_mtapi_job_initialize_list(node);
...@@ -199,6 +199,8 @@ void mtapi_finalize(MTAPI_OUT mtapi_status_t* status) { ...@@ -199,6 +199,8 @@ void mtapi_finalize(MTAPI_OUT mtapi_status_t* status) {
embb_mtapi_job_finalize_list(node); embb_mtapi_job_finalize_list(node);
} }
embb_atomic_destroy_int(&node->is_scheduler_running);
/* free system instance */ /* free system instance */
embb_mtapi_alloc_deallocate(node); embb_mtapi_alloc_deallocate(node);
embb_mtapi_node_instance = MTAPI_NULL; embb_mtapi_node_instance = MTAPI_NULL;
......
...@@ -66,8 +66,6 @@ mtapi_boolean_t embb_mtapi_##TYPE##_pool_initialize( \ ...@@ -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.id = EMBB_MTAPI_IDPOOL_INVALID_ID; \
that->storage[ii].handle.tag = 0; \ that->storage[ii].handle.tag = 0; \
} \ } \
/* use entry 0 as invalid */ \
embb_mtapi_##TYPE##_initialize(that->storage); \
return MTAPI_TRUE; \ return MTAPI_TRUE; \
} else { \ } else { \
that->id_pool.ids_available = 0; \ that->id_pool.ids_available = 0; \
...@@ -96,7 +94,6 @@ void embb_mtapi_##TYPE##_pool_deallocate( \ ...@@ -96,7 +94,6 @@ void embb_mtapi_##TYPE##_pool_deallocate( \
embb_mtapi_##TYPE##_pool_t * that, \ embb_mtapi_##TYPE##_pool_t * that, \
embb_mtapi_##TYPE##_t * object) { \ embb_mtapi_##TYPE##_t * object) { \
mtapi_uint_t pool_id = object->handle.id; \ mtapi_uint_t pool_id = object->handle.id; \
embb_mtapi_##TYPE##_finalize(object); \
object->handle.id = EMBB_MTAPI_IDPOOL_INVALID_ID; \ object->handle.id = EMBB_MTAPI_IDPOOL_INVALID_ID; \
object->handle.tag++; \ object->handle.tag++; \
embb_mtapi_id_pool_deallocate(&that->id_pool, pool_id); \ embb_mtapi_id_pool_deallocate(&that->id_pool, pool_id); \
......
...@@ -56,8 +56,8 @@ void embb_mtapi_queue_initialize(embb_mtapi_queue_t* that) { ...@@ -56,8 +56,8 @@ void embb_mtapi_queue_initialize(embb_mtapi_queue_t* that) {
mtapi_queueattr_init(&that->attributes, MTAPI_NULL); mtapi_queueattr_init(&that->attributes, MTAPI_NULL);
that->queue_id = MTAPI_QUEUE_ID_NONE; that->queue_id = MTAPI_QUEUE_ID_NONE;
embb_atomic_store_char(&that->enabled, MTAPI_FALSE); embb_atomic_init_char(&that->enabled, MTAPI_FALSE);
embb_atomic_store_int(&that->num_tasks, 0); embb_atomic_init_int(&that->num_tasks, 0);
that->job_handle.id = 0; that->job_handle.id = 0;
that->job_handle.tag = 0; that->job_handle.tag = 0;
} }
...@@ -71,8 +71,8 @@ void embb_mtapi_queue_initialize_with_attributes_and_job( ...@@ -71,8 +71,8 @@ void embb_mtapi_queue_initialize_with_attributes_and_job(
that->attributes = *attributes; that->attributes = *attributes;
that->queue_id = MTAPI_QUEUE_ID_NONE; that->queue_id = MTAPI_QUEUE_ID_NONE;
embb_atomic_store_char(&that->enabled, MTAPI_TRUE); embb_atomic_init_char(&that->enabled, MTAPI_TRUE);
embb_atomic_store_int(&that->num_tasks, 0); embb_atomic_init_int(&that->num_tasks, 0);
that->job_handle = job; that->job_handle = job;
} }
...@@ -81,6 +81,8 @@ void embb_mtapi_queue_finalize(embb_mtapi_queue_t* that) { ...@@ -81,6 +81,8 @@ void embb_mtapi_queue_finalize(embb_mtapi_queue_t* that) {
that->job_handle.id = 0; that->job_handle.id = 0;
that->job_handle.tag = 0; that->job_handle.tag = 0;
embb_atomic_destroy_int(&that->num_tasks);
embb_atomic_destroy_char(&that->enabled);
embb_mtapi_queue_initialize(that); embb_mtapi_queue_initialize(that);
} }
......
...@@ -491,7 +491,7 @@ mtapi_boolean_t embb_mtapi_scheduler_initialize_with_mode( ...@@ -491,7 +491,7 @@ mtapi_boolean_t embb_mtapi_scheduler_initialize_with_mode(
assert(MTAPI_NULL != that); assert(MTAPI_NULL != that);
assert(MTAPI_NULL != node); 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 */ /* Paranoia sanitizing of scheduler mode */
if (mode >= NUM_SCHEDULER_MODES) { if (mode >= NUM_SCHEDULER_MODES) {
...@@ -573,6 +573,8 @@ void embb_mtapi_scheduler_finalize(embb_mtapi_scheduler_t * that) { ...@@ -573,6 +573,8 @@ void embb_mtapi_scheduler_finalize(embb_mtapi_scheduler_t * that) {
embb_mtapi_alloc_deallocate(that->worker_contexts); embb_mtapi_alloc_deallocate(that->worker_contexts);
that->worker_contexts = MTAPI_NULL; that->worker_contexts = MTAPI_NULL;
} }
embb_atomic_destroy_int(&that->affine_task_counter);
} }
embb_mtapi_scheduler_t * embb_mtapi_scheduler_new() { embb_mtapi_scheduler_t * embb_mtapi_scheduler_new() {
......
...@@ -79,20 +79,29 @@ void embb_mtapi_task_initialize(embb_mtapi_task_t* that) { ...@@ -79,20 +79,29 @@ void embb_mtapi_task_initialize(embb_mtapi_task_t* that) {
that->action.id = EMBB_MTAPI_IDPOOL_INVALID_ID; that->action.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->job.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->task_id = MTAPI_TASK_ID_NONE;
that->group.id = EMBB_MTAPI_IDPOOL_INVALID_ID; that->group.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->queue.id = EMBB_MTAPI_IDPOOL_INVALID_ID; that->queue.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->error_code = MTAPI_SUCCESS; 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_spin_init(&that->state_lock);
embb_atomic_init_unsigned_int(&that->instances_todo, 0);
} }
void embb_mtapi_task_finalize(embb_mtapi_task_t* that) { void embb_mtapi_task_finalize(embb_mtapi_task_t* that) {
assert(MTAPI_NULL != 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_spin_destroy(&that->state_lock);
embb_atomic_destroy_unsigned_int(&that->instances_todo);
} }
mtapi_boolean_t embb_mtapi_task_execute( mtapi_boolean_t embb_mtapi_task_execute(
......
...@@ -58,7 +58,9 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize( ...@@ -58,7 +58,9 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize(
that->thread_priority = priority; that->thread_priority = priority;
that->is_main_thread = (worker_index == 0) ? that->is_main_thread = (worker_index == 0) ?
node->attributes.reuse_main_thread : MTAPI_FALSE; 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( that->queue = (embb_mtapi_task_queue_t**)embb_mtapi_alloc_allocate(
sizeof(embb_mtapi_task_queue_t)*that->priorities); sizeof(embb_mtapi_task_queue_t)*that->priorities);
...@@ -101,7 +103,6 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize( ...@@ -101,7 +103,6 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize(
embb_mutex_init(&that->work_available_mutex, EMBB_MUTEX_PLAIN); embb_mutex_init(&that->work_available_mutex, EMBB_MUTEX_PLAIN);
embb_condition_init(&that->work_available); embb_condition_init(&that->work_available);
embb_atomic_store_int(&that->is_sleeping, 0);
that->is_initialized = MTAPI_TRUE; that->is_initialized = MTAPI_TRUE;
...@@ -208,6 +209,9 @@ void embb_mtapi_thread_context_finalize(embb_mtapi_thread_context_t* that) { ...@@ -208,6 +209,9 @@ void embb_mtapi_thread_context_finalize(embb_mtapi_thread_context_t* that) {
that->private_queue = MTAPI_NULL; that->private_queue = MTAPI_NULL;
} }
embb_atomic_destroy_int(&that->is_sleeping);
embb_atomic_destroy_int(&that->run);
that->priorities = 0; that->priorities = 0;
that->is_initialized = MTAPI_FALSE; that->is_initialized = MTAPI_FALSE;
......
...@@ -733,8 +733,12 @@ void TestContext() { ...@@ -733,8 +733,12 @@ void TestContext() {
} }
void ErrorTest::TestBasic() { void ErrorTest::TestBasic() {
embb_atomic_init_int(&wait, 0);
TestNodeNotInit(); TestNodeNotInit();
TestParameter(); TestParameter();
TestLimits(); TestLimits();
TestContext(); TestContext();
embb_atomic_destroy_int(&wait);
} }
...@@ -84,8 +84,8 @@ void plugin_initialize( ...@@ -84,8 +84,8 @@ void plugin_initialize(
plugin_task.id = 0; plugin_task.id = 0;
plugin_task.tag = 0; plugin_task.tag = 0;
embb_atomic_store_int(&plugin_running, 1); embb_atomic_init_int(&plugin_running, 1);
embb_atomic_store_int(&plugin_task_available, 0); embb_atomic_init_int(&plugin_task_available, 0);
err = embb_thread_create(&plugin_thread, NULL, plugin_thread_function, NULL); err = embb_thread_create(&plugin_thread, NULL, plugin_thread_function, NULL);
if (EMBB_SUCCESS == err) { if (EMBB_SUCCESS == err) {
...@@ -108,6 +108,9 @@ void plugin_finalize( ...@@ -108,6 +108,9 @@ void plugin_finalize(
local_status = MTAPI_SUCCESS; local_status = MTAPI_SUCCESS;
} }
embb_atomic_destroy_int(&plugin_task_available);
embb_atomic_destroy_int(&plugin_running);
mtapi_status_set(status, local_status); mtapi_status_set(status, local_status);
} }
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <embb_mtapi_test_id_pool.h> #include <embb_mtapi_test_id_pool.h>
#include <embb/base/c/memory_allocation.h> #include <embb/base/c/memory_allocation.h>
#include <embb/base/c/atomic.h>
PT_MAIN("MTAPI C") { PT_MAIN("MTAPI C") {
embb_log_set_log_level(EMBB_LOG_LEVEL_NONE); embb_log_set_log_level(EMBB_LOG_LEVEL_NONE);
......
...@@ -32,7 +32,7 @@ namespace mtapi { ...@@ -32,7 +32,7 @@ namespace mtapi {
embb::mtapi::Node * embb::mtapi::Node::node_instance_ = NULL; embb::mtapi::Node * embb::mtapi::Node::node_instance_ = NULL;
#if MTAPI_CPP_AUTOMATIC_INITIALIZE #if MTAPI_CPP_AUTOMATIC_INITIALIZE
static embb_spinlock_t init_mutex = { { 0 } }; static EMBB_BASE_BASIC_TYPE_SIZE_4 init_mutex = 0;
#endif #endif
void Node::Initialize( void Node::Initialize(
...@@ -68,13 +68,18 @@ void Node::Initialize( ...@@ -68,13 +68,18 @@ void Node::Initialize(
Node & Node::GetInstance() { Node & Node::GetInstance() {
#if MTAPI_CPP_AUTOMATIC_INITIALIZE #if MTAPI_CPP_AUTOMATIC_INITIALIZE
if (!IsInitialized()) { 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()) { if (!IsInitialized()) {
Node::Initialize( Node::Initialize(
MTAPI_CPP_AUTOMATIC_DOMAIN_ID, MTAPI_CPP_AUTOMATIC_NODE_ID); MTAPI_CPP_AUTOMATIC_DOMAIN_ID, MTAPI_CPP_AUTOMATIC_NODE_ID);
atexit(Node::Finalize); atexit(Node::Finalize);
} }
embb_spin_unlock(&init_mutex); embb_internal__atomic_store_4(&init_mutex, 0);
} }
return *node_instance_; return *node_instance_;
#else #else
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <partest/partest.h> #include <partest/partest.h>
#include <embb/base/c/thread.h> #include <embb/base/c/thread.h>
#include <embb/base/c/atomic.h>
#include <mtapi_cpp_test_task.h> #include <mtapi_cpp_test_task.h>
#include <mtapi_cpp_test_group.h> #include <mtapi_cpp_test_group.h>
......
...@@ -654,14 +654,16 @@ void mtapi_network_plugin_initialize( ...@@ -654,14 +654,16 @@ void mtapi_network_plugin_initialize(
plugin->socket_count = 0; plugin->socket_count = 0;
plugin->buffer_size = 0; plugin->buffer_size = 0;
plugin->sockets = NULL; plugin->sockets = NULL;
embb_atomic_store_int(&plugin->run, 0);
err = embb_mtapi_network_initialize(); err = embb_mtapi_network_initialize();
if (0 == err) return; if (0 == err) return;
embb_atomic_init_int(&plugin->run, 0);
err = embb_mtapi_network_buffer_initialize( err = embb_mtapi_network_buffer_initialize(
&plugin->recv_buffer, (int)buffer_size); &plugin->recv_buffer, (int)buffer_size);
if (0 == err) { if (0 == err) {
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
return; return;
} }
...@@ -670,6 +672,7 @@ void mtapi_network_plugin_initialize( ...@@ -670,6 +672,7 @@ void mtapi_network_plugin_initialize(
&plugin->send_buffer, (int)buffer_size); &plugin->send_buffer, (int)buffer_size);
if (0 == err) { if (0 == err) {
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
return; return;
} }
...@@ -684,6 +687,7 @@ void mtapi_network_plugin_initialize( ...@@ -684,6 +687,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0; plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
return; return;
} }
...@@ -695,6 +699,7 @@ void mtapi_network_plugin_initialize( ...@@ -695,6 +699,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0; plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
return; return;
} }
...@@ -707,6 +712,7 @@ void mtapi_network_plugin_initialize( ...@@ -707,6 +712,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0; plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
return; return;
} }
...@@ -723,6 +729,7 @@ void mtapi_network_plugin_initialize( ...@@ -723,6 +729,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0; plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
return; return;
} }
...@@ -741,6 +748,7 @@ void mtapi_network_plugin_initialize( ...@@ -741,6 +748,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer); embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer); embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0; plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
return; return;
} }
...@@ -764,6 +772,9 @@ void mtapi_network_plugin_finalize( ...@@ -764,6 +772,9 @@ void mtapi_network_plugin_finalize(
embb_mtapi_network_socket_finalize(&plugin->sockets[0]); embb_mtapi_network_socket_finalize(&plugin->sockets[0]);
embb_free(plugin->sockets); embb_free(plugin->sockets);
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize(); embb_mtapi_network_finalize();
mtapi_status_set(status, local_status); mtapi_status_set(status, local_status);
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <embb_mtapi_network_test_socket.h> #include <embb_mtapi_network_test_socket.h>
#include <embb_mtapi_network_test_task.h> #include <embb_mtapi_network_test_task.h>
#include <embb/base/c/atomic.h>
PT_MAIN("MTAPI NETWORK") { PT_MAIN("MTAPI NETWORK") {
PT_RUN(NetworkBufferTest); PT_RUN(NetworkBufferTest);
PT_RUN(NetworkSocketTest); PT_RUN(NetworkSocketTest);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <embb_mtapi_opencl_test_linker.h> #include <embb_mtapi_opencl_test_linker.h>
#include <embb_mtapi_opencl_test_task.h> #include <embb_mtapi_opencl_test_task.h>
#include <embb/base/c/atomic.h>
PT_MAIN("MTAPI OPENCL") { PT_MAIN("MTAPI OPENCL") {
PT_RUN(LinkerTest); PT_RUN(LinkerTest);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment