Commit 5c3d5fbb by Marcus Winter

added threading analysis mode for linux

parent 9653c63b
...@@ -83,6 +83,7 @@ option(INSTALL_DOCS "Specify whether Doxygen docs should be installed" ON) ...@@ -83,6 +83,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
# #
...@@ -104,6 +105,14 @@ else() ...@@ -104,6 +105,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)
......
...@@ -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
...@@ -66,6 +68,8 @@ int compute1_() { ...@@ -66,6 +68,8 @@ int compute1_() {
} }
PT_MAIN("Algorithms") { PT_MAIN("Algorithms") {
embb_atomic_initialize();
embb::tasks::Node::Initialize(THIS_DOMAIN_ID, THIS_NODE_ID); embb::tasks::Node::Initialize(THIS_DOMAIN_ID, THIS_NODE_ID);
PT_RUN(PartitionerTest); PT_RUN(PartitionerTest);
...@@ -82,6 +86,5 @@ PT_MAIN("Algorithms") { ...@@ -82,6 +86,5 @@ PT_MAIN("Algorithms") {
PT_EXPECT(embb_get_bytes_allocated() == 0); PT_EXPECT(embb_get_bytes_allocated() == 0);
// std::cout << "please press return to continue..." << std::endl; embb_atomic_finalize();
// std::cin.get();
} }
...@@ -292,11 +292,32 @@ void embb_atomic_xor_assign_TYPE( ...@@ -292,11 +292,32 @@ 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>
int embb_mutex_lock(
embb_mutex_t* mutex
);
int embb_mutex_unlock(
embb_mutex_t* mutex
);
#define EMBB_ATOMIC_MUTEX_LOCK embb_mutex_lock(&embb_atomic_mutex)
#define EMBB_ATOMIC_MUTEX_UNLOCK embb_mutex_unlock(&embb_atomic_mutex)
#else
#define EMBB_ATOMIC_MUTEX_LOCK
#define EMBB_ATOMIC_MUTEX_UNLOCK
#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_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>
......
...@@ -69,10 +69,12 @@ ...@@ -69,10 +69,12 @@
#define EMBB_DEFINE_AND_ASSIGN(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX)\ #define EMBB_DEFINE_AND_ASSIGN(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX)\
EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_and_assign_, \ EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_and_assign_, \
EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) value) { \ EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) value) { \
EMBB_ATOMIC_MUTEX_LOCK; \
__asm__ __volatile__("lock and" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \ __asm__ __volatile__("lock and" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (value) \ : "+m" (*pointer_to_value), "+q" (value) \
: \ : \
: "memory"); \ : "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
} }
#else #else
#error "No atomic fetch and store implementation found" #error "No atomic fetch and store implementation found"
...@@ -133,7 +135,7 @@ EMBB_DEFINE_AND_ASSIGN(4, "") ...@@ -133,7 +135,7 @@ EMBB_DEFINE_AND_ASSIGN(4, "")
/* /*
* Now, using the basic functions above, we generate the respective functions * Now, using the basic functions above, we generate the respective functions
* for all basic data types, like "unsigned short". For that purpose, the * for all basic data types, like "unsigned short". For that purpose, the
* following generator macro is used. This macro is called by the macros in the * following generator macro is used. This macro is calleuild-work-Desktop-Defaultd by the macros in the
* generator header, defining the implementation for the basic data types. * generator header, defining the implementation for the basic data types.
* *
* For unsigned short and for and_assign.h, the following method would be * For unsigned short and for and_assign.h, the following method would be
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#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>
...@@ -57,4 +58,16 @@ EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(size_t, size_t) ...@@ -57,4 +58,16 @@ EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(size_t, size_t)
EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(ptrdiff_t, ptrdiff_t) EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(ptrdiff_t, ptrdiff_t)
EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(uintmax_t, uintmax_t) EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(uintmax_t, uintmax_t)
#ifdef EMBB_THREADING_ANALYSIS_MODE
#include <embb/base/c/mutex.h>
extern embb_mutex_t embb_atomic_mutex;
void embb_atomic_initialize();
void embb_atomic_finalize();
#else
#define embb_atomic_initialize()
#define embb_atomic_finalize()
#endif
#endif //EMBB_BASE_C_INTERNAL_ATOMIC_ATOMIC_VARIABLES_H_ #endif //EMBB_BASE_C_INTERNAL_ATOMIC_ATOMIC_VARIABLES_H_
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
EMBB_PLATFORM_INLINE int EMBB_CAT2(embb_internal__atomic_compare_and_swap_, \ EMBB_PLATFORM_INLINE int EMBB_CAT2(embb_internal__atomic_compare_and_swap_, \
EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* expected, \ EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* expected, \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) desired) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) desired) { \
EMBB_ATOMIC_MUTEX_LOCK; \
char result; \ char result; \
__asm__ __volatile__ ("lock cmpxchg" EMBB_ATOMIC_X86_SIZE_SUFFIX\ __asm__ __volatile__ ("lock cmpxchg" EMBB_ATOMIC_X86_SIZE_SUFFIX\
" %3, %0 \n\t" \ " %3, %0 \n\t" \
...@@ -65,6 +66,7 @@ ...@@ -65,6 +66,7 @@
: "+m" (*pointer_to_value), "+a" (*expected), "=q" (result) \ : "+m" (*pointer_to_value), "+a" (*expected), "=q" (result) \
: "q" (desired) \ : "q" (desired) \
: "memory", "cc" ); \ : "memory", "cc" ); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return result; \ return result; \
} }
#else #else
......
...@@ -57,10 +57,12 @@ ...@@ -57,10 +57,12 @@
#define EMBB_DEFINE_FETCH_AND_ADD(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \ #define EMBB_DEFINE_FETCH_AND_ADD(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \
EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) EMBB_CAT2(embb_internal__atomic_fetch_and_add_, EMBB_PARAMETER_SIZE_BYTE) \ EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) EMBB_CAT2(embb_internal__atomic_fetch_and_add_, EMBB_PARAMETER_SIZE_BYTE) \
(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) { \ (EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) { \
EMBB_ATOMIC_MUTEX_LOCK; \
__asm__ __volatile__ ("lock xadd" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \ __asm__ __volatile__ ("lock xadd" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (new_value) \ : "+m" (*pointer_to_value), "+q" (new_value) \
: \ : \
: "memory", "cc" ); \ : "memory", "cc" ); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return new_value; \ return new_value; \
} }
#else #else
......
/*
* Copyright (c) 2014-2015, 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_
// TODO implementation of embb_atomic_init()
#endif // EMBB_BASE_C_INTERNAL_ATOMIC_INIT_H_
...@@ -58,12 +58,14 @@ ...@@ -58,12 +58,14 @@
#define EMBB_DEFINE_LOAD(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \ #define EMBB_DEFINE_LOAD(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \
EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) \ EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) \
EMBB_CAT2(embb_internal__atomic_load_, EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value) { \ EMBB_CAT2(embb_internal__atomic_load_, EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value) { \
EMBB_ATOMIC_MUTEX_LOCK; \
/* no fence required for loads */ \ /* no fence required for loads */ \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) result; \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) result; \
__asm__ __volatile__("mov" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \ __asm__ __volatile__("mov" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "=q" (result) \ : "=q" (result) \
: "m" (*pointer_to_value) \ : "m" (*pointer_to_value) \
: "memory"); \ : "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return result; \ return result; \
} }
#else #else
......
...@@ -56,10 +56,12 @@ ...@@ -56,10 +56,12 @@
#define EMBB_DEFINE_OR_ASSIGN(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \ #define EMBB_DEFINE_OR_ASSIGN(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX) \
EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_or_assign_, EMBB_PARAMETER_SIZE_BYTE)(\ EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_or_assign_, EMBB_PARAMETER_SIZE_BYTE)(\
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) value) { \
EMBB_ATOMIC_MUTEX_LOCK; \
__asm__ __volatile__("lock or" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \ __asm__ __volatile__("lock or" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (value) \ : "+m" (*pointer_to_value), "+q" (value) \
: \ : \
: "memory"); \ : "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
} }
#else #else
......
...@@ -57,11 +57,13 @@ ...@@ -57,11 +57,13 @@
#define EMBB_DEFINE_STORE(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX)\ #define EMBB_DEFINE_STORE(EMBB_PARAMETER_SIZE_BYTE, EMBB_ATOMIC_X86_SIZE_SUFFIX)\
EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_store_, EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, \ EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_store_, EMBB_PARAMETER_SIZE_BYTE)(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) {\ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) {\
EMBB_ATOMIC_MUTEX_LOCK; \
/*the lock prefix is implicit for xchg*/ \ /*the lock prefix is implicit for xchg*/ \
__asm__ __volatile__("xchg" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \ __asm__ __volatile__("xchg" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (new_value) \ : "+m" (*pointer_to_value), "+q" (new_value) \
: \ : \
: "memory"); \ : "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
} }
#else #else
#error "No atomic fetch and store implementation found" #error "No atomic fetch and store implementation found"
......
...@@ -58,11 +58,13 @@ ...@@ -58,11 +58,13 @@
EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) EMBB_CAT2(embb_internal__atomic_swap_, EMBB_PARAMETER_SIZE_BYTE)(\ EMBB_PLATFORM_INLINE EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) EMBB_CAT2(embb_internal__atomic_swap_, EMBB_PARAMETER_SIZE_BYTE)(\
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value)\ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value)\
{ \ { \
EMBB_ATOMIC_MUTEX_LOCK; \
/*the lock prefix is implicit for xchg*/ \ /*the lock prefix is implicit for xchg*/ \
__asm__ __volatile__("xchg" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \ __asm__ __volatile__("xchg" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (new_value) \ : "+m" (*pointer_to_value), "+q" (new_value) \
: \ : \
: "memory"); \ : "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return new_value; \ return new_value; \
} }
#else #else
......
...@@ -57,10 +57,12 @@ ...@@ -57,10 +57,12 @@
EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_xor_assign_, EMBB_PARAMETER_SIZE_BYTE)(\ EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_internal__atomic_xor_assign_, EMBB_PARAMETER_SIZE_BYTE)(\
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) volatile* pointer_to_value, \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) value) { \ EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) value) { \
EMBB_ATOMIC_MUTEX_LOCK; \
__asm__ __volatile__("lock xor" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \ __asm__ __volatile__("lock xor" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (value) \ : "+m" (*pointer_to_value), "+q" (value) \
: \ : \
: "memory"); \ : "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
} }
#else #else
......
...@@ -53,4 +53,9 @@ ...@@ -53,4 +53,9 @@
*/ */
#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
#endif /* EMBB_BASE_INTERNAL_CMAKE_CONFIG_H_ */ #endif /* EMBB_BASE_INTERNAL_CMAKE_CONFIG_H_ */
...@@ -46,3 +46,17 @@ void __embb_atomic_internal_compile_time_checks() { ...@@ -46,3 +46,17 @@ void __embb_atomic_internal_compile_time_checks() {
BUILD_BUG_ON(sizeof(ptrdiff_t) != EMBB_PTRDIFF_T_TYPE_SIZE); BUILD_BUG_ON(sizeof(ptrdiff_t) != EMBB_PTRDIFF_T_TYPE_SIZE);
BUILD_BUG_ON(sizeof(uintmax_t) != EMBB_UINTMAX_T_TYPE_SIZE); BUILD_BUG_ON(sizeof(uintmax_t) != EMBB_UINTMAX_T_TYPE_SIZE);
} }
#ifdef EMBB_THREADING_ANALYSIS_MODE
embb_mutex_t embb_atomic_mutex;
void embb_atomic_initialize() {
embb_mutex_init(&embb_atomic_mutex, EMBB_MUTEX_PLAIN);
}
void embb_atomic_finalize() {
embb_mutex_destroy(&embb_atomic_mutex);
}
#endif
...@@ -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;
...@@ -54,6 +55,8 @@ using embb::base::test::ThreadTest; ...@@ -54,6 +55,8 @@ using embb::base::test::ThreadTest;
using embb::base::test::ThreadSpecificStorageTest; using embb::base::test::ThreadSpecificStorageTest;
PT_MAIN("Base C") { PT_MAIN("Base C") {
embb_atomic_initialize();
embb_log_set_log_level(EMBB_LOG_LEVEL_WARNING); embb_log_set_log_level(EMBB_LOG_LEVEL_WARNING);
unsigned int max_threads = unsigned int max_threads =
static_cast<unsigned int>(2 * partest::TestSuite::GetDefaultNumThreads()); static_cast<unsigned int>(2 * partest::TestSuite::GetDefaultNumThreads());
...@@ -71,4 +74,6 @@ PT_MAIN("Base C") { ...@@ -71,4 +74,6 @@ PT_MAIN("Base C") {
PT_RUN(ThreadTest); PT_RUN(ThreadTest);
PT_RUN(ThreadSpecificStorageTest); PT_RUN(ThreadSpecificStorageTest);
PT_EXPECT(embb_get_bytes_allocated() == 0); PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
} }
...@@ -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;
...@@ -50,6 +51,8 @@ using embb::base::test::ThreadTest; ...@@ -50,6 +51,8 @@ using embb::base::test::ThreadTest;
using embb::base::test::LogTest; using embb::base::test::LogTest;
PT_MAIN("Base C++") { PT_MAIN("Base C++") {
embb_atomic_initialize();
unsigned int max_threads = unsigned int max_threads =
static_cast<unsigned int>(2 * partest::TestSuite::GetDefaultNumThreads()); static_cast<unsigned int>(2 * partest::TestSuite::GetDefaultNumThreads());
embb_thread_set_max_count(max_threads); embb_thread_set_max_count(max_threads);
...@@ -66,4 +69,6 @@ PT_MAIN("Base C++") { ...@@ -66,4 +69,6 @@ PT_MAIN("Base C++") {
PT_RUN(LogTest); PT_RUN(LogTest);
PT_EXPECT(embb_get_bytes_allocated() == 0); PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
} }
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#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/memory_allocation.h>
#include <embb/base/c/atomic.h>
#include <partest/partest.h> #include <partest/partest.h>
#include <embb/base/thread.h> #include <embb/base/thread.h>
...@@ -58,6 +59,8 @@ using embb::containers::test::ObjectPoolTest; ...@@ -58,6 +59,8 @@ using embb::containers::test::ObjectPoolTest;
using embb::containers::test::HazardPointerTest2; using embb::containers::test::HazardPointerTest2;
PT_MAIN("Data Structures C++") { PT_MAIN("Data Structures C++") {
embb_atomic_initialize();
unsigned int max_threads = static_cast<unsigned int>( unsigned int max_threads = static_cast<unsigned int>(
2 * partest::TestSuite::GetDefaultNumThreads()); 2 * partest::TestSuite::GetDefaultNumThreads());
embb_thread_set_max_count(max_threads); embb_thread_set_max_count(max_threads);
...@@ -74,4 +77,6 @@ PT_MAIN("Data Structures C++") { ...@@ -74,4 +77,6 @@ PT_MAIN("Data Structures C++") {
PT_RUN(ObjectPoolTest< WaitFreeArrayValuePool<bool COMMA false> >); PT_RUN(ObjectPoolTest< WaitFreeArrayValuePool<bool COMMA false> >);
PT_EXPECT(embb_get_bytes_allocated() == 0); PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
} }
...@@ -31,7 +31,13 @@ ...@@ -31,7 +31,13 @@
#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++") {
embb_atomic_initialize();
PT_RUN(SimpleTest); PT_RUN(SimpleTest);
PT_RUN(TupleTest); PT_RUN(TupleTest);
embb_atomic_finalize();
} }
...@@ -40,8 +40,11 @@ ...@@ -40,8 +40,11 @@
#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_atomic_initialize();
embb_log_set_log_level(EMBB_LOG_LEVEL_NONE); embb_log_set_log_level(EMBB_LOG_LEVEL_NONE);
embb_thread_set_max_count(1024); embb_thread_set_max_count(1024);
...@@ -54,4 +57,6 @@ PT_MAIN("MTAPI C") { ...@@ -54,4 +57,6 @@ PT_MAIN("MTAPI C") {
PT_RUN(IdPoolTest); PT_RUN(IdPoolTest);
PT_EXPECT(embb_get_bytes_allocated() == 0); PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
} }
...@@ -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>
...@@ -34,9 +35,13 @@ ...@@ -34,9 +35,13 @@
PT_MAIN("MTAPI C++") { PT_MAIN("MTAPI C++") {
embb_atomic_initialize();
embb_thread_set_max_count(1024); embb_thread_set_max_count(1024);
PT_RUN(TaskTest); PT_RUN(TaskTest);
PT_RUN(GroupTest); PT_RUN(GroupTest);
PT_RUN(QueueTest); PT_RUN(QueueTest);
embb_atomic_finalize();
} }
...@@ -30,8 +30,14 @@ ...@@ -30,8 +30,14 @@
#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") {
embb_atomic_initialize();
PT_RUN(NetworkBufferTest); PT_RUN(NetworkBufferTest);
PT_RUN(NetworkSocketTest); PT_RUN(NetworkSocketTest);
PT_RUN(NetworkTaskTest); PT_RUN(NetworkTaskTest);
embb_atomic_finalize();
} }
...@@ -29,8 +29,13 @@ ...@@ -29,8 +29,13 @@
#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") {
embb_atomic_initialize();
PT_RUN(LinkerTest); PT_RUN(LinkerTest);
PT_RUN(TaskTest); PT_RUN(TaskTest);
embb_atomic_finalize();
} }
...@@ -32,9 +32,15 @@ ...@@ -32,9 +32,15 @@
#include <tasks_cpp_test_group.h> #include <tasks_cpp_test_group.h>
#include <tasks_cpp_test_queue.h> #include <tasks_cpp_test_queue.h>
#include <embb/base/c/atomic.h>
PT_MAIN("TASKS") { PT_MAIN("TASKS") {
embb_atomic_initialize();
PT_RUN(TaskTest); PT_RUN(TaskTest);
PT_RUN(GroupTest); PT_RUN(GroupTest);
PT_RUN(QueueTest); PT_RUN(QueueTest);
embb_atomic_finalize();
} }
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