Commit 3926d7a1 by Marcus Winter

full implementation of threading analysis mode

parent 8aa76fe9
......@@ -68,8 +68,6 @@ int compute1_() {
}
PT_MAIN("Algorithms") {
embb_atomic_initialize();
embb::mtapi::Node::Initialize(THIS_DOMAIN_ID, THIS_NODE_ID);
PT_RUN(PartitionerTest);
......@@ -85,6 +83,4 @@ PT_MAIN("Algorithms") {
embb::mtapi::Node::Finalize();
PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
}
......@@ -295,6 +295,12 @@ extern "C" {
#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
......@@ -304,13 +310,20 @@ 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)
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))
#define EMBB_ATOMIC_INIT_CHECK(variable) assert(variable->marker == 0x12345678)
#else
#define EMBB_ATOMIC_MUTEX_LOCK
#define EMBB_ATOMIC_MUTEX_UNLOCK
#define EMBB_ATOMIC_MUTEX_LOCK(mutex)
#define EMBB_ATOMIC_MUTEX_UNLOCK(mutex)
#endif
......@@ -318,6 +331,8 @@ int embb_mutex_unlock(
#include <embb/base/c/internal/atomic/atomic_sizes.h>
#include <embb/base/c/internal/atomic/atomic_variables.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/and_assign.h>
#include <embb/base/c/internal/atomic/store.h>
......
......@@ -69,12 +69,10 @@
#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_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" \
: "+m" (*pointer_to_value), "+q" (value) \
: \
: "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
}
#else
#error "No atomic fetch and store implementation found"
......@@ -154,8 +152,11 @@ EMBB_DEFINE_AND_ASSIGN(4, "")
EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
EMBB_CAT2(embb_internal__atomic_and_assign_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) \
(&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
}
#undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
......@@ -41,6 +41,8 @@
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);
EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(char, char)
......@@ -58,16 +60,4 @@ EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(size_t, size_t)
EMBB_ATOMIC_INTERNAL_DEFINE_VARIABLE(ptrdiff_t, ptrdiff_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_
......@@ -58,7 +58,6 @@
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_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) desired) { \
EMBB_ATOMIC_MUTEX_LOCK; \
char result; \
__asm__ __volatile__ ("lock cmpxchg" EMBB_ATOMIC_X86_SIZE_SUFFIX\
" %3, %0 \n\t" \
......@@ -66,7 +65,6 @@
: "+m" (*pointer_to_value), "+a" (*expected), "=q" (result) \
: "q" (desired) \
: "memory", "cc" ); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return result; \
}
#else
......@@ -140,8 +138,12 @@ EMBB_DEFINE_COMPARE_AND_SWAP(4, "")
EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE* expected, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE desired) {\
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) desired_pun;\
memcpy(&desired_pun, &desired, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\
return EMBB_CAT2(embb_internal__atomic_compare_and_swap_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) \
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
int result = EMBB_CAT2(embb_internal__atomic_compare_and_swap_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) \
(&(variable->internal_variable)), (EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *) expected, desired_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
return result;\
}
#undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
/*
* 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_
......@@ -57,12 +57,10 @@
#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_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" \
: "+m" (*pointer_to_value), "+q" (new_value) \
: \
: "memory", "cc" ); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return new_value; \
}
#else
......@@ -109,9 +107,6 @@ EMBB_DEFINE_FETCH_AND_ADD(8, "q")
: "memory", "cc" ); \
return result; \
}
/* return __sync_fetch_and_add( \
pointer_to_value, new_value); \
}*/
#else
#error "No atomic fetch and store implementation found"
#endif
......@@ -133,9 +128,12 @@ EMBB_DEFINE_FETCH_AND_ADD(4, "")
EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) return_val = EMBB_CAT2(embb_internal__atomic_fetch_and_add_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)(\
(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\
(&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \
memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
return return_val_pun; \
......
/*
* 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 <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_MUTEX_INIT(variable->internal_mutex); \
variable->marker = 0x12345678; \
}
#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_
......@@ -58,14 +58,12 @@
#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_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 */ \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) result; \
__asm__ __volatile__("mov" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "=q" (result) \
: "m" (*pointer_to_value) \
: "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return result; \
}
#else
......@@ -121,10 +119,13 @@ EMBB_DEFINE_LOAD(4, "")
*/
#define EMBB_ATOMIC_INTERNAL_DEFINE_LOAD_METHOD(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \
EMBB_PLATFORM_INLINE EMBB_ATOMIC_PARAMETER_TYPE_NATIVE EMBB_CAT2(embb_atomic_load_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(\
const EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable) { \
EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable) { \
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \
return_val = (EMBB_CAT2(embb_internal__atomic_load_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)(\
(EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)(&(variable->internal_variable)))); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \
memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
return return_val_pun; \
......
......@@ -56,12 +56,10 @@
#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_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" \
: "+m" (*pointer_to_value), "+q" (value) \
: \
: "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
}
#else
......@@ -125,8 +123,11 @@ EMBB_DEFINE_OR_ASSIGN(4, "")
EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_atomic_or_assign_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
EMBB_CAT2(embb_internal__atomic_or_assign_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\
(&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
}
#undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
......@@ -57,13 +57,11 @@
#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_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_PARAMETER_SIZE_BYTE) new_value) {\
EMBB_ATOMIC_MUTEX_LOCK; \
/*the lock prefix is implicit for xchg*/ \
__asm__ __volatile__("xchg" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (new_value) \
: \
: "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
}
#else
#error "No atomic fetch and store implementation found"
......@@ -120,8 +118,11 @@ EMBB_DEFINE_STORE(4, "")
EMBB_PLATFORM_INLINE void EMBB_CAT2(embb_atomic_store_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)(EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
EMBB_CAT2(embb_internal__atomic_store_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\
(&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
}
#undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
......@@ -58,13 +58,11 @@
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_ATOMIC_MUTEX_LOCK; \
/*the lock prefix is implicit for xchg*/ \
__asm__ __volatile__("xchg" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (new_value) \
: \
: "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
return new_value; \
}
#else
......@@ -129,8 +127,11 @@ EMBB_DEFINE_SWAP(4, "")
EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun; \
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) \
return_val = EMBB_CAT2(embb_internal__atomic_swap_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)(&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
EMBB_ATOMIC_PARAMETER_TYPE_NATIVE return_val_pun; \
memcpy(&return_val_pun, &return_val, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE)); \
return return_val_pun; \
......
......@@ -57,12 +57,10 @@
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) value) { \
EMBB_ATOMIC_MUTEX_LOCK; \
__asm__ __volatile__("lock xor" EMBB_ATOMIC_X86_SIZE_SUFFIX " %1, %0" \
: "+m" (*pointer_to_value), "+q" (value) \
: \
: "memory"); \
EMBB_ATOMIC_MUTEX_UNLOCK; \
}
#else
......@@ -127,8 +125,11 @@ EMBB_DEFINE_XOR_ASSIGN(4, "")
EMBB_CAT2(embb_atomic_, EMBB_ATOMIC_PARAMETER_ATOMIC_TYPE_SUFFIX)* variable, EMBB_ATOMIC_PARAMETER_TYPE_NATIVE value) { \
EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) value_pun;\
memcpy(&value_pun, &value, sizeof(EMBB_ATOMIC_PARAMETER_TYPE_NATIVE));\
EMBB_ATOMIC_INIT_CHECK(variable); \
EMBB_ATOMIC_MUTEX_LOCK(variable->internal_mutex); \
EMBB_CAT2(embb_internal__atomic_xor_assign_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE)((EMBB_CAT2(EMBB_BASE_BASIC_TYPE_SIZE_, EMBB_ATOMIC_PARAMETER_TYPE_SIZE) volatile *)\
(&(variable->internal_variable)), value_pun); \
EMBB_ATOMIC_MUTEX_UNLOCK(variable->internal_mutex); \
}
#undef EMBB_ATOMIC_METHOD_TO_GENERATE
......
......@@ -46,17 +46,3 @@ void __embb_atomic_internal_compile_time_checks() {
BUILD_BUG_ON(sizeof(ptrdiff_t) != EMBB_PTRDIFF_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
......@@ -33,6 +33,7 @@ int embb_counter_init(embb_counter_t* counter) {
if (counter == NULL) {
return EMBB_ERROR;
}
embb_atomic_init_unsigned_int(&(counter->value));
embb_atomic_store_unsigned_int(&(counter->value), 0);
return EMBB_SUCCESS;
}
......@@ -55,7 +56,7 @@ unsigned int embb_counter_decrement(embb_counter_t* counter) {
void embb_counter_destroy(embb_counter_t* counter) {
assert(counter != NULL);
EMBB_UNUSED_IN_RELEASE(counter);
embb_atomic_destroy_unsigned_int(&(counter->value));
}
......@@ -40,18 +40,18 @@
* This function has local scope.
*/
static int embb_max_number_thread_indices_max = 0;
static embb_atomic_int embb_max_number_thread_indices_flag = { 0 };
static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_max_number_thread_indices_flag = 0;
unsigned int* embb_max_number_thread_indices() {
int compare_to = 0;
if (embb_atomic_load_int(&embb_max_number_thread_indices_flag) != 2) {
if (embb_atomic_compare_and_swap_int(
EMBB_BASE_BASIC_TYPE_SIZE_4 compare_to = 0;
if (embb_internal__atomic_load_4(&embb_max_number_thread_indices_flag) != 2) {
if (embb_internal__atomic_compare_and_swap_4(
&embb_max_number_thread_indices_flag, &compare_to, 1)) {
embb_max_number_thread_indices_max =
(int)(embb_core_count_available() * 2);
embb_atomic_store_int(&embb_max_number_thread_indices_flag, 2);
embb_internal__atomic_store_4(&embb_max_number_thread_indices_flag, 2);
}
while (embb_atomic_load_int(&embb_max_number_thread_indices_flag) != 2) {}
while (embb_internal__atomic_load_4(&embb_max_number_thread_indices_flag) != 2) {}
}
return (unsigned int*) &embb_max_number_thread_indices_max;
}
......@@ -61,17 +61,17 @@ unsigned int* embb_max_number_thread_indices() {
*
* This function has local scope.
*/
static embb_atomic_int embb_thread_index_counter_flag = { 0 };
static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_thread_index_counter_flag = 0;
static embb_counter_t embb_thread_index_counter_index;
embb_counter_t* embb_thread_index_counter() {
int compare_to = 0;
if (embb_atomic_load_int(&embb_thread_index_counter_flag) != 2) {
if (embb_atomic_compare_and_swap_int(
EMBB_BASE_BASIC_TYPE_SIZE_4 compare_to = 0;
if (embb_internal__atomic_load_4(&embb_thread_index_counter_flag) != 2) {
if (embb_internal__atomic_compare_and_swap_4(
&embb_thread_index_counter_flag, &compare_to, 1)) {
embb_counter_init(&embb_thread_index_counter_index);
embb_atomic_store_int(&embb_thread_index_counter_flag, 2);
embb_internal__atomic_store_4(&embb_thread_index_counter_flag, 2);
}
while (embb_atomic_load_int(&embb_thread_index_counter_flag) != 2) {}
while (embb_internal__atomic_load_4(&embb_thread_index_counter_flag) != 2) {}
}
return &embb_thread_index_counter_index;
}
......
......@@ -33,7 +33,7 @@
#ifdef EMBB_DEBUG
static embb_atomic_long embb_bytes_allocated = { 0 };
static EMBB_BASE_BASIC_TYPE_SIZE_4 embb_bytes_allocated = 0;
enum {
// Make the marking unlikely to be something else
......@@ -49,7 +49,7 @@ void* embb_alloc(size_t bytes) {
if (allocated == NULL)
return NULL;
embb_atomic_fetch_and_add_long(
embb_internal__atomic_fetch_and_add_4(
&embb_bytes_allocated, (long)bytes_to_allocate);
size_t* x_as_size_type = (size_t*)allocated;
......@@ -72,7 +72,7 @@ void embb_free(void * ptr) {
(*alloc_type) = (size_t)INVALID_ALLOCATION;
embb_atomic_fetch_and_add_long(
embb_internal__atomic_fetch_and_add_4(
&embb_bytes_allocated, (long)(0 - (size_t)(*bytes_allocated)));
free((size_t*)ptr - 2);
......@@ -127,7 +127,7 @@ void* embb_alloc_aligned(size_t alignment, size_t size) {
x_as_size_type[-2] = (size_t)allocated;
x_as_size_type[-3] = bytes_to_allocate;
embb_atomic_fetch_and_add_long(
embb_internal__atomic_fetch_and_add_4(
&embb_bytes_allocated, (long)bytes_to_allocate);
return x;
......@@ -144,14 +144,14 @@ void embb_free_aligned(void* ptr) {
ptr_conv[-1] = (size_t)INVALID_ALLOCATION;
embb_atomic_fetch_and_add_long(
embb_internal__atomic_fetch_and_add_4(
&embb_bytes_allocated, (long)((long)0 - ptr_conv[-3]));
free((void*)ptr_conv[-2]);
}
size_t embb_get_bytes_allocated() {
return (size_t)(embb_atomic_load_long(&embb_bytes_allocated));
return (size_t)(embb_internal__atomic_load_4(&embb_bytes_allocated));
}
#else // EMBB_DEBUG
......
......@@ -149,6 +149,7 @@ int embb_spin_init(embb_spinlock_t* spinlock) {
}
// For now, store the initial value. In the future will use atomic init
// function (as soon as available).
embb_atomic_init_int(&spinlock->atomic_spin_variable_);
embb_atomic_store_int(&spinlock->atomic_spin_variable_, 0);
return EMBB_SUCCESS;
}
......@@ -207,7 +208,5 @@ int embb_spin_unlock(embb_spinlock_t* spinlock) {
void embb_spin_destroy(embb_spinlock_t* spinlock) {
assert(NULL != spinlock);
// for now, doing nothing here... in future, will call the respective
// destroy function for atomics...
EMBB_UNUSED(spinlock);
embb_atomic_destroy_int(&spinlock->atomic_spin_variable_);
}
......@@ -55,8 +55,6 @@ using embb::base::test::ThreadTest;
using embb::base::test::ThreadSpecificStorageTest;
PT_MAIN("Base C") {
embb_atomic_initialize();
embb_log_set_log_level(EMBB_LOG_LEVEL_WARNING);
unsigned int max_threads =
static_cast<unsigned int>(2 * partest::TestSuite::GetDefaultNumThreads());
......@@ -74,6 +72,4 @@ PT_MAIN("Base C") {
PT_RUN(ThreadTest);
PT_RUN(ThreadSpecificStorageTest);
PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
}
......@@ -36,13 +36,22 @@ namespace embb {
namespace base {
namespace test {
embb_atomic_int flag;
ThreadIndexTest::ThreadIndexTest()
: number_threads_(partest::TestSuite::GetDefaultNumThreads()) {
embb_atomic_init_int(&flag);
embb_atomic_store_int(&flag, 1);
CreateUnit("Test 0 indices").Add(&ThreadIndexTest::Test0, this);
CreateUnit("Test 1 index").Add(&ThreadIndexTest::Test1, this);
CreateUnit("Test N indices").Add(&ThreadIndexTest::TestN, this, 1);
}
ThreadIndexTest::~ThreadIndexTest() {
embb_atomic_destroy_int(&flag);
}
void ThreadIndexTest::Test0() {
embb_internal_thread_index_reset();
unsigned int old_max = embb_thread_get_max_count();
......@@ -78,8 +87,6 @@ void ThreadIndexTest::Test1() {
embb_internal_thread_index_set_max(old_max);
}
embb_atomic_int flag = { 1 };
void ThreadIndexTest::TestN() {
embb_internal_thread_index_reset();
unsigned int old_max = embb_thread_get_max_count();
......@@ -106,6 +113,8 @@ void ThreadIndexTest::TestN() {
embb_thread_join(&thread, NULL);
delete[] threads;
embb_internal_thread_index_set_max(old_max);
embb_atomic_destroy_int(&flag);
}
int ThreadStart(void* arg) {
......
......@@ -36,10 +36,15 @@ namespace test {
class ThreadIndexTest : public partest::TestCase {
public:
/**
* Adds test methods.
* Adds test methods and allocates temporary data.
*/
ThreadIndexTest();
/**
* Destroys temporary data.
*/
~ThreadIndexTest();
private:
/**
* Tests 0 available indices.
......
......@@ -117,8 +117,10 @@ FetchAndAdd(DifferenceType val) {
NativeType native_desired;
memcpy(&native_desired, &desired, sizeof(desired));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
NativeType storage_value = fetch_and_add_implementation<NativeType>::
fetch_and_add(&this->AtomicValue, native_desired);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
memcpy(&return_value, &storage_value, sizeof(return_value));
return return_value;
......
......@@ -58,6 +58,10 @@ class AtomicBase {
mutable NativeType AtomicValue;
#ifdef EMBB_THREADING_ANALYSIS_MODE
embb_mutex_t internal_mutex;
#endif
public:
/**
* Default constructor.
......@@ -73,36 +77,48 @@ class AtomicBase {
*/
explicit AtomicBase(BaseType val);
/**
* Destructor.
*/
~AtomicBase();
// The members below are documented in atomic.h
BaseType operator=(BaseType val);
operator BaseType() const;
operator BaseType();
bool IsLockFree() const;
bool IsArithmetic() const;
bool IsInteger() const;
bool IsPointer() const;
void Store(BaseType val);
BaseType Load() const;
BaseType Load();
BaseType Swap(BaseType val);
bool CompareAndSwap(BaseType& expected, BaseType desired);
};
template<typename BaseType>
inline AtomicBase<BaseType>::AtomicBase() : AtomicValue(0) {
EMBB_ATOMIC_MUTEX_INIT(internal_mutex);
}
template<typename BaseType>
inline AtomicBase<BaseType>::AtomicBase(BaseType val) /*: AtomicValue(val)*/ {
EMBB_ATOMIC_MUTEX_INIT(internal_mutex);
memcpy(&AtomicValue, &val, sizeof(AtomicValue));
}
template<typename BaseType>
inline AtomicBase<BaseType>::~AtomicBase() {
EMBB_ATOMIC_MUTEX_DESTROY(internal_mutex);
}
template<typename BaseType>
inline BaseType AtomicBase<BaseType>::operator=(BaseType val) {
Store(val);
return val;
}
template<typename BaseType>
inline AtomicBase<BaseType>::operator BaseType() const {
inline AtomicBase<BaseType>::operator BaseType() {
return Load();
}
......@@ -132,16 +148,20 @@ inline void AtomicBase<BaseType>::Store(BaseType val) {
// anyway...
memcpy(&storage_value, &val, sizeof(storage_value));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
store_implementation< NativeType >
::Store(&AtomicValue, storage_value);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
}
template<typename BaseType>
inline BaseType AtomicBase<BaseType>::Load() const {
inline BaseType AtomicBase<BaseType>::Load() {
BaseType return_value;
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
NativeType storage_value =
load_implementation< NativeType >::Load(&AtomicValue);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
memcpy(&return_value, &storage_value, sizeof(return_value));
......@@ -155,8 +175,10 @@ inline BaseType AtomicBase<BaseType>::Swap(BaseType val) {
memcpy(&storage_value, &val, sizeof(storage_value));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
NativeType storage_value2 = swap_implementation< NativeType >
::Swap(&AtomicValue, storage_value);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
memcpy(&return_value, &storage_value2, sizeof(return_value));
......@@ -172,10 +194,12 @@ CompareAndSwap(BaseType& expected, BaseType desired) {
memcpy(&native_expected, &expected, sizeof(expected));
memcpy(&native_desired, &desired, sizeof(desired));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
bool return_val =
(compare_and_swap_implementation<NativeType>::
compare_and_swap(&AtomicValue, &native_expected, native_desired)) !=0
? true : false;
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
memcpy(&expected, &native_expected, sizeof(expected));
......
......@@ -93,8 +93,10 @@ inline void AtomicInteger<BaseType>::operator&=(BaseType val) {
NativeType native_operand;
memcpy(&native_operand, &val, sizeof(val));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
and_assign_implementation<NativeType>::
and_assign(&this->AtomicValue, native_operand);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
}
template<typename BaseType>
......@@ -102,8 +104,10 @@ inline void AtomicInteger<BaseType>::operator|=(BaseType val) {
NativeType native_operand;
memcpy(&native_operand, &val, sizeof(val));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
or_assign_implementation<NativeType>::
or_assign(&this->AtomicValue, native_operand);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
}
template<typename BaseType>
......@@ -111,8 +115,10 @@ inline void AtomicInteger<BaseType>::operator^=(BaseType val) {
NativeType native_operand;
memcpy(&native_operand, &val, sizeof(val));
EMBB_ATOMIC_MUTEX_LOCK(internal_mutex);
xor_assign_implementation<NativeType>::
xor_assign(&this->AtomicValue, native_operand);
EMBB_ATOMIC_MUTEX_UNLOCK(internal_mutex);
}
} // namespace atomic
......
......@@ -65,8 +65,8 @@ class AtomicPointer : public AtomicArithmetic<BaseType*, DifferenceType, S> {
bool IsPointer() const;
// The methods below are documented in atomic.h
BaseType* operator->() const;
BaseType& operator*() const;
BaseType* operator->();
BaseType& operator*();
};
template<typename BaseType, typename DifferenceType, size_t S>
......@@ -93,13 +93,13 @@ inline bool AtomicPointer<BaseType, DifferenceType, S>::
template<typename BaseType, typename DifferenceType, size_t S>
inline BaseType* AtomicPointer<BaseType, DifferenceType, S>::
operator->() const {
operator->() {
return this->Load();
}
template<typename BaseType, typename DifferenceType, size_t S>
inline BaseType& AtomicPointer<BaseType, DifferenceType, S>::
operator*() const {
operator*() {
return *(this->Load());
}
......
......@@ -51,8 +51,6 @@ using embb::base::test::ThreadTest;
using embb::base::test::LogTest;
PT_MAIN("Base C++") {
embb_atomic_initialize();
unsigned int max_threads =
static_cast<unsigned int>(2 * partest::TestSuite::GetDefaultNumThreads());
embb_thread_set_max_count(max_threads);
......@@ -69,6 +67,4 @@ PT_MAIN("Base C++") {
PT_RUN(LogTest);
PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
}
......@@ -72,8 +72,6 @@ using embb::containers::test::ObjectPoolTest;
using embb::containers::test::HazardPointerTest2;
PT_MAIN("Data Structures C++") {
embb_atomic_initialize();
unsigned int max_threads = static_cast<unsigned int>(
2 * partest::TestSuite::GetDefaultNumThreads());
embb_thread_set_max_count(max_threads);
......@@ -90,6 +88,4 @@ PT_MAIN("Data Structures C++") {
PT_RUN(ObjectPoolTest< WaitFreeArrayValuePool<bool COMMA false> >);
PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
}
......@@ -84,13 +84,16 @@ class Inputs<T1, embb::base::internal::Nil, embb::base::internal::Nil,
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 1;
new(count_+ii) embb::base::Atomic<int>(1);
}
}
this->template Get<0>().SetSlices(slices_);
}
~Inputs() {
if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_);
}
}
......@@ -150,7 +153,7 @@ class Inputs<T1, T2, embb::base::internal::Nil,
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 2;
new(count_ + ii) embb::base::Atomic<int>(2);
}
}
this->template Get<0>().SetSlices(slices_);
......@@ -158,6 +161,9 @@ class Inputs<T1, T2, embb::base::internal::Nil,
}
~Inputs() {
if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_);
}
}
......@@ -222,7 +228,7 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil,
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 3;
new(count_ + ii) embb::base::Atomic<int>(3);
}
}
this->template Get<0>().SetSlices(slices_);
......@@ -231,6 +237,9 @@ class Inputs<T1, T2, T3, embb::base::internal::Nil,
}
~Inputs() {
if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_);
}
}
......@@ -299,7 +308,7 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil>
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 4;
new(count_ + ii) embb::base::Atomic<int>(4);
}
}
this->template Get<0>().SetSlices(slices_);
......@@ -309,6 +318,9 @@ class Inputs<T1, T2, T3, T4, embb::base::internal::Nil>
}
~Inputs() {
if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_);
}
}
......@@ -383,7 +395,7 @@ class Inputs
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
count_[ii] = 5;
new(count_ + ii) embb::base::Atomic<int>(5);
}
}
this->template Get<0>().SetSlices(slices_);
......@@ -394,6 +406,9 @@ class Inputs
}
~Inputs() {
if (NULL != count_) {
for (int ii = 0; ii < slices_; ii++) {
count_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(count_);
}
}
......
......@@ -802,6 +802,9 @@ class Network : public internal::ClockListener {
sched_ = NULL;
}
if (NULL != sink_counter_) {
for (int ii = 0; ii < slices_; ii++) {
sink_counter_[ii].~Atomic<int>();
}
embb::base::Allocation::Free(sink_counter_);
sink_counter_ = NULL;
}
......@@ -1111,7 +1114,7 @@ class Network : public internal::ClockListener {
embb::base::Allocation::Allocate(
sizeof(embb::base::Atomic<int>)*slices_));
for (int ii = 0; ii < slices_; ii++) {
sink_counter_[ii] = 0;
new(sink_counter_+ii) embb::base::Atomic<int>(0);
}
}
};
......
......@@ -34,10 +34,6 @@
#include <embb/base/c/atomic.h>
PT_MAIN("Dataflow C++") {
embb_atomic_initialize();
PT_RUN(SimpleTest);
PT_RUN(TupleTest);
embb_atomic_finalize();
}
......@@ -62,6 +62,7 @@ mtapi_action_hndl_t mtapi_ext_plugin_action_create(
new_action->node_local_data_size = node_local_data_size;
new_action->enabled = MTAPI_TRUE;
new_action->is_plugin_action = MTAPI_TRUE;
embb_atomic_init_int(&new_action->num_tasks);
embb_atomic_store_int(&new_action->num_tasks, 0);
new_action->plugin_task_start_function = task_start_function;
......@@ -87,6 +88,7 @@ mtapi_action_hndl_t mtapi_ext_plugin_action_create(
action_handle = new_action->handle;
embb_mtapi_job_add_action(job, new_action);
} else {
embb_mtapi_action_finalize(new_action);
embb_mtapi_action_pool_deallocate(node->action_pool, new_action);
}
} else {
......
......@@ -49,6 +49,8 @@ embb_mtapi_pool_implementation(action)
/* ---- CLASS MEMBERS ------------------------------------------------------ */
void embb_mtapi_action_initialize(embb_mtapi_action_t* that) {
assert(MTAPI_NULL != that);
that->action_function = NULL;
that->job_id = MTAPI_JOB_ID_INVALID;
that->domain_id = MTAPI_DOMAIN_ID_INVALID;
......@@ -57,15 +59,26 @@ void embb_mtapi_action_initialize(embb_mtapi_action_t* that) {
that->node_local_data = NULL;
that->node_local_data_size = 0;
that->plugin_data = MTAPI_NULL;
embb_atomic_init_int(&that->num_tasks);
embb_atomic_store_int(&that->num_tasks, 0);
}
void embb_mtapi_action_finalize(embb_mtapi_action_t* that) {
assert(MTAPI_NULL != that);
if (that->is_plugin_action) {
// TODO(mw): check status
that->plugin_action_finalize_function(that->handle, NULL);
}
embb_mtapi_action_initialize(that);
that->action_function = NULL;
that->job_id = MTAPI_JOB_ID_INVALID;
that->domain_id = MTAPI_DOMAIN_ID_INVALID;
that->node_id = MTAPI_NODE_ID_INVALID;
that->enabled = MTAPI_FALSE;
that->node_local_data = NULL;
that->node_local_data_size = 0;
that->plugin_data = MTAPI_NULL;
embb_atomic_destroy_int(&that->num_tasks);
}
static mtapi_boolean_t embb_mtapi_action_delete_visitor(
......@@ -140,6 +153,7 @@ mtapi_action_hndl_t mtapi_action_create(
new_action->node_local_data_size = node_local_data_size;
new_action->enabled = MTAPI_TRUE;
new_action->is_plugin_action = MTAPI_FALSE;
embb_atomic_init_int(&new_action->num_tasks);
embb_atomic_store_int(&new_action->num_tasks, 0);
new_action->action_function = action_function;
......@@ -162,6 +176,7 @@ mtapi_action_hndl_t mtapi_action_create(
action_handle = new_action->handle;
embb_mtapi_job_add_action(job, new_action);
} else {
embb_mtapi_action_finalize(new_action);
embb_mtapi_action_pool_deallocate(node->action_pool, new_action);
}
} else {
......@@ -337,8 +352,7 @@ void mtapi_action_delete(
node, local_action->job_id);
embb_mtapi_job_remove_action(local_job, local_action);
}
/* this is done by pool deallocate:
embb_mtapi_action_finalize(local_action); */
embb_mtapi_action_finalize(local_action);
embb_mtapi_action_pool_deallocate(node->action_pool, local_action);
} else {
local_status = MTAPI_ERR_ACTION_INVALID;
......
......@@ -30,12 +30,12 @@
#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 * ptr = embb_alloc(bytes);
if (ptr != NULL) {
embb_atomic_fetch_and_add_unsigned_int(
embb_internal__atomic_fetch_and_add_4(
&embb_mtapi_alloc_bytes_allocated, sizeof(unsigned int)+bytes);
}
return ptr;
......@@ -48,9 +48,9 @@ void embb_mtapi_alloc_deallocate(void * ptr) {
}
void embb_mtapi_alloc_reset_bytes_allocated() {
embb_atomic_store_unsigned_int(&embb_mtapi_alloc_bytes_allocated, 0);
embb_internal__atomic_store_4(&embb_mtapi_alloc_bytes_allocated, 0);
}
unsigned int embb_mtapi_alloc_get_bytes_allocated() {
return embb_atomic_load_unsigned_int(&embb_mtapi_alloc_bytes_allocated);
return embb_internal__atomic_load_4(&embb_mtapi_alloc_bytes_allocated);
}
......@@ -55,8 +55,10 @@ void embb_mtapi_group_initialize(embb_mtapi_group_t * that) {
assert(MTAPI_NULL != that);
that->group_id = MTAPI_GROUP_ID_NONE;
embb_atomic_init_int(&that->deleted);
embb_atomic_store_int(&that->deleted, MTAPI_FALSE);
that->num_tasks.internal_variable = 0;
embb_atomic_init_int(&that->num_tasks);
embb_atomic_store_int(&that->num_tasks, 0);
embb_mtapi_task_queue_initialize(&that->queue);
}
......@@ -67,8 +69,10 @@ void embb_mtapi_group_initialize_with_node(
assert(MTAPI_NULL != node);
that->group_id = MTAPI_GROUP_ID_NONE;
embb_atomic_init_int(&that->deleted);
embb_atomic_store_int(&that->deleted, MTAPI_FALSE);
that->num_tasks.internal_variable = 0;
embb_atomic_init_int(&that->num_tasks);
embb_atomic_store_int(&that->num_tasks, 0);
embb_mtapi_task_queue_initialize_with_capacity(
&that->queue, node->attributes.queue_limit);
}
......@@ -77,7 +81,9 @@ void embb_mtapi_group_finalize(embb_mtapi_group_t * that) {
assert(MTAPI_NULL != that);
embb_atomic_store_int(&that->deleted, MTAPI_TRUE);
that->num_tasks.internal_variable = 0;
embb_atomic_destroy_int(&that->deleted);
embb_atomic_store_int(&that->num_tasks, 0);
embb_atomic_destroy_int(&that->num_tasks);
embb_mtapi_task_queue_finalize(&that->queue);
}
......
......@@ -105,6 +105,7 @@ void mtapi_initialize(
}
if (MTAPI_SUCCESS == local_status) {
embb_atomic_init_int(&node->is_scheduler_running);
embb_atomic_store_int(&node->is_scheduler_running, MTAPI_FALSE);
/* initialize storage */
......@@ -199,6 +200,8 @@ void mtapi_finalize(MTAPI_OUT mtapi_status_t* status) {
embb_mtapi_job_finalize_list(node);
}
embb_atomic_destroy_int(&node->is_scheduler_running);
/* free system instance */
embb_mtapi_alloc_deallocate(node);
embb_mtapi_node_instance = MTAPI_NULL;
......
......@@ -66,8 +66,6 @@ mtapi_boolean_t embb_mtapi_##TYPE##_pool_initialize( \
that->storage[ii].handle.id = EMBB_MTAPI_IDPOOL_INVALID_ID; \
that->storage[ii].handle.tag = 0; \
} \
/* use entry 0 as invalid */ \
embb_mtapi_##TYPE##_initialize(that->storage); \
return MTAPI_TRUE; \
} else { \
that->id_pool.ids_available = 0; \
......@@ -96,7 +94,6 @@ void embb_mtapi_##TYPE##_pool_deallocate( \
embb_mtapi_##TYPE##_pool_t * that, \
embb_mtapi_##TYPE##_t * object) { \
mtapi_uint_t pool_id = object->handle.id; \
embb_mtapi_##TYPE##_finalize(object); \
object->handle.id = EMBB_MTAPI_IDPOOL_INVALID_ID; \
object->handle.tag++; \
embb_mtapi_id_pool_deallocate(&that->id_pool, pool_id); \
......
......@@ -56,7 +56,9 @@ void embb_mtapi_queue_initialize(embb_mtapi_queue_t* that) {
mtapi_queueattr_init(&that->attributes, MTAPI_NULL);
that->queue_id = MTAPI_QUEUE_ID_NONE;
embb_atomic_init_char(&that->enabled);
embb_atomic_store_char(&that->enabled, MTAPI_FALSE);
embb_atomic_init_int(&that->num_tasks);
embb_atomic_store_int(&that->num_tasks, 0);
that->job_handle.id = 0;
that->job_handle.tag = 0;
......@@ -71,7 +73,9 @@ void embb_mtapi_queue_initialize_with_attributes_and_job(
that->attributes = *attributes;
that->queue_id = MTAPI_QUEUE_ID_NONE;
embb_atomic_init_char(&that->enabled);
embb_atomic_store_char(&that->enabled, MTAPI_TRUE);
embb_atomic_init_int(&that->num_tasks);
embb_atomic_store_int(&that->num_tasks, 0);
that->job_handle = job;
}
......@@ -81,6 +85,8 @@ void embb_mtapi_queue_finalize(embb_mtapi_queue_t* that) {
that->job_handle.id = 0;
that->job_handle.tag = 0;
embb_atomic_destroy_int(&that->num_tasks);
embb_atomic_destroy_char(&that->enabled);
embb_mtapi_queue_initialize(that);
}
......
......@@ -473,6 +473,7 @@ mtapi_boolean_t embb_mtapi_scheduler_initialize_with_mode(
assert(MTAPI_NULL != that);
assert(MTAPI_NULL != node);
embb_atomic_init_int(&that->affine_task_counter);
embb_atomic_store_int(&that->affine_task_counter, 0);
/* Paranoia sanitizing of scheduler mode */
......@@ -555,6 +556,8 @@ void embb_mtapi_scheduler_finalize(embb_mtapi_scheduler_t * that) {
embb_mtapi_alloc_deallocate(that->worker_contexts);
that->worker_contexts = MTAPI_NULL;
}
embb_atomic_destroy_int(&that->affine_task_counter);
}
embb_mtapi_scheduler_t * embb_mtapi_scheduler_new() {
......
......@@ -79,20 +79,31 @@ void embb_mtapi_task_initialize(embb_mtapi_task_t* that) {
that->action.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->job.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
embb_atomic_init_int(&that->state);
embb_atomic_store_int(&that->state, MTAPI_TASK_ERROR);
that->task_id = MTAPI_TASK_ID_NONE;
that->group.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->queue.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->error_code = MTAPI_SUCCESS;
embb_atomic_init_unsigned_int(&that->current_instance);
embb_atomic_store_unsigned_int(&that->current_instance, 0);
embb_spin_init(&that->state_lock);
embb_atomic_init_unsigned_int(&that->instances_todo);
}
void embb_mtapi_task_finalize(embb_mtapi_task_t* that) {
assert(MTAPI_NULL != that);
embb_mtapi_task_initialize(that);
that->action.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->job.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
embb_atomic_destroy_int(&that->state);
that->task_id = MTAPI_TASK_ID_NONE;
that->group.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->queue.id = EMBB_MTAPI_IDPOOL_INVALID_ID;
that->error_code = MTAPI_SUCCESS;
embb_atomic_destroy_unsigned_int(&that->current_instance);
embb_spin_destroy(&that->state_lock);
embb_atomic_destroy_unsigned_int(&that->instances_todo);
}
mtapi_boolean_t embb_mtapi_task_execute(
......
......@@ -58,7 +58,12 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize(
that->thread_priority = priority;
that->is_main_thread = (worker_index == 0) ?
node->attributes.reuse_main_thread : MTAPI_FALSE;
embb_atomic_init_int(&that->run);
embb_atomic_init_int(&that->is_sleeping);
embb_atomic_store_int(&that->run, 0);
embb_atomic_store_int(&that->is_sleeping, 0);
that->queue = (embb_mtapi_task_queue_t**)embb_mtapi_alloc_allocate(
sizeof(embb_mtapi_task_queue_t)*that->priorities);
......@@ -101,7 +106,6 @@ mtapi_boolean_t embb_mtapi_thread_context_initialize(
embb_mutex_init(&that->work_available_mutex, EMBB_MUTEX_PLAIN);
embb_condition_init(&that->work_available);
embb_atomic_store_int(&that->is_sleeping, 0);
that->is_initialized = MTAPI_TRUE;
......@@ -208,6 +212,9 @@ void embb_mtapi_thread_context_finalize(embb_mtapi_thread_context_t* that) {
that->private_queue = MTAPI_NULL;
}
embb_atomic_destroy_int(&that->is_sleeping);
embb_atomic_destroy_int(&that->run);
that->priorities = 0;
that->is_initialized = MTAPI_FALSE;
......
......@@ -733,8 +733,12 @@ void TestContext() {
}
void ErrorTest::TestBasic() {
embb_atomic_init_int(&wait);
TestNodeNotInit();
TestParameter();
TestLimits();
TestContext();
embb_atomic_destroy_int(&wait);
}
......@@ -84,7 +84,9 @@ void plugin_initialize(
plugin_task.id = 0;
plugin_task.tag = 0;
embb_atomic_init_int(&plugin_running);
embb_atomic_store_int(&plugin_running, 1);
embb_atomic_init_int(&plugin_task_available);
embb_atomic_store_int(&plugin_task_available, 0);
err = embb_thread_create(&plugin_thread, NULL, plugin_thread_function, NULL);
......@@ -108,6 +110,9 @@ void plugin_finalize(
local_status = MTAPI_SUCCESS;
}
embb_atomic_destroy_int(&plugin_task_available);
embb_atomic_destroy_int(&plugin_running);
mtapi_status_set(status, local_status);
}
......
......@@ -43,8 +43,6 @@
#include <embb/base/c/atomic.h>
PT_MAIN("MTAPI C") {
embb_atomic_initialize();
embb_log_set_log_level(EMBB_LOG_LEVEL_NONE);
embb_thread_set_max_count(1024);
......@@ -57,6 +55,4 @@ PT_MAIN("MTAPI C") {
PT_RUN(IdPoolTest);
PT_EXPECT(embb_get_bytes_allocated() == 0);
embb_atomic_finalize();
}
......@@ -35,13 +35,9 @@
PT_MAIN("MTAPI C++") {
embb_atomic_initialize();
embb_thread_set_max_count(1024);
PT_RUN(TaskTest);
PT_RUN(GroupTest);
PT_RUN(QueueTest);
embb_atomic_finalize();
}
......@@ -654,14 +654,17 @@ void mtapi_network_plugin_initialize(
plugin->socket_count = 0;
plugin->buffer_size = 0;
plugin->sockets = NULL;
embb_atomic_store_int(&plugin->run, 0);
err = embb_mtapi_network_initialize();
if (0 == err) return;
embb_atomic_init_int(&plugin->run);
embb_atomic_store_int(&plugin->run, 0);
err = embb_mtapi_network_buffer_initialize(
&plugin->recv_buffer, (int)buffer_size);
if (0 == err) {
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
return;
}
......@@ -670,6 +673,7 @@ void mtapi_network_plugin_initialize(
&plugin->send_buffer, (int)buffer_size);
if (0 == err) {
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
return;
}
......@@ -684,6 +688,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
return;
}
......@@ -695,6 +700,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
return;
}
......@@ -707,6 +713,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
return;
}
......@@ -723,6 +730,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
return;
}
......@@ -741,6 +749,7 @@ void mtapi_network_plugin_initialize(
embb_mtapi_network_buffer_finalize(&plugin->send_buffer);
embb_mtapi_network_buffer_finalize(&plugin->recv_buffer);
plugin->buffer_size = 0;
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
return;
}
......@@ -764,6 +773,9 @@ void mtapi_network_plugin_finalize(
embb_mtapi_network_socket_finalize(&plugin->sockets[0]);
embb_free(plugin->sockets);
embb_atomic_destroy_int(&plugin->run);
embb_mtapi_network_finalize();
mtapi_status_set(status, local_status);
......
......@@ -33,11 +33,7 @@
#include <embb/base/c/atomic.h>
PT_MAIN("MTAPI NETWORK") {
embb_atomic_initialize();
PT_RUN(NetworkBufferTest);
PT_RUN(NetworkSocketTest);
PT_RUN(NetworkTaskTest);
embb_atomic_finalize();
}
......@@ -32,10 +32,6 @@
#include <embb/base/c/atomic.h>
PT_MAIN("MTAPI OPENCL") {
embb_atomic_initialize();
PT_RUN(LinkerTest);
PT_RUN(TaskTest);
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