Skip to content

Commit

Permalink
Remove atomics for thread sanitizedr, add mutex alternate option for …
Browse files Browse the repository at this point in the history
…reference counting.
  • Loading branch information
viferga committed Jan 27, 2023
1 parent a780f6b commit 011617e
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 6 deletions.
4 changes: 3 additions & 1 deletion source/reflect/source/reflect_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ klass class_create(const char *name, enum accessor_type_id accessor, class_impl

cls->impl = impl;
cls->accessor = accessor;
threading_atomic_ref_count_store(&cls->ref, 0);
threading_atomic_ref_count_initialize(&cls->ref);
cls->interface = singleton ? singleton() : NULL;
cls->constructors = vector_create_type(constructor);
cls->methods = map_create(&hash_callback_str, &comparable_callback_str);
Expand Down Expand Up @@ -901,6 +901,8 @@ void class_destroy(klass cls)
set_destroy(cls->static_attributes);
}

threading_atomic_ref_count_destroy(&cls->ref);

free(cls);

reflect_memory_tracker_deallocation(class_stats);
Expand Down
6 changes: 4 additions & 2 deletions source/reflect/source/reflect_exception.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ exception exception_create(char *message, char *label, int64_t code, char *stack
ex->stacktrace = stacktrace;
ex->id = thread_id_get_current();

threading_atomic_ref_count_store(&ex->ref, 0);
threading_atomic_ref_count_initialize(&ex->ref);

reflect_memory_tracker_allocation(exception_stats);

Expand Down Expand Up @@ -131,7 +131,7 @@ exception exception_create_const(const char *message, const char *label, int64_t
ex->code = code;
ex->id = thread_id_get_current();

threading_atomic_ref_count_store(&ex->ref, 0);
threading_atomic_ref_count_initialize(&ex->ref);

reflect_memory_tracker_allocation(exception_stats);

Expand Down Expand Up @@ -252,6 +252,8 @@ void exception_destroy(exception ex)
free(ex->stacktrace);
}

threading_atomic_ref_count_destroy(&ex->ref);

free(ex);

reflect_memory_tracker_deallocation(exception_stats);
Expand Down
4 changes: 3 additions & 1 deletion source/reflect/source/reflect_function.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function function_create(const char *name, size_t args_count, function_impl impl
goto function_create_error;
}

threading_atomic_ref_count_store(&func->ref, 0);
threading_atomic_ref_count_initialize(&func->ref);

func->interface = singleton ? singleton() : NULL;

Expand Down Expand Up @@ -731,6 +731,8 @@ void function_destroy(function func)
free(func->name);
}

threading_atomic_ref_count_destroy(&func->ref);

free(func);

reflect_memory_tracker_deallocation(function_stats);
Expand Down
4 changes: 3 additions & 1 deletion source/reflect/source/reflect_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ object object_create(const char *name, enum accessor_type_id accessor, object_im

obj->impl = impl;
obj->accessor = accessor;
threading_atomic_ref_count_store(&obj->ref, 0);
threading_atomic_ref_count_initialize(&obj->ref);

obj->interface = singleton ? singleton() : NULL;

Expand Down Expand Up @@ -419,6 +419,8 @@ void object_destroy(object obj)
free(obj->name);
}

threading_atomic_ref_count_destroy(&obj->ref);

free(obj);

reflect_memory_tracker_deallocation(object_stats);
Expand Down
2 changes: 1 addition & 1 deletion source/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ add_subdirectory(metacall_node_async_resources_test)
add_subdirectory(metacall_node_await_chain_test)
add_subdirectory(metacall_node_exception_test)
add_subdirectory(metacall_node_python_deadlock_test)
add_subdirectory(metacall_node_signal_handler_test)
# add_subdirectory(metacall_node_signal_handler_test) # Note: Not used anymore but leaving it here for reference to solve this: https://github.com/metacall/core/issues/121
add_subdirectory(metacall_node_native_code_test)
add_subdirectory(metacall_node_extension_test)
add_subdirectory(metacall_distributable_test)
Expand Down
18 changes: 18 additions & 0 deletions source/threading/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ set(headers
${include_path}/threading_atomic.h
${include_path}/threading_thread_id.h
${include_path}/threading_atomic_ref_count.h
${include_path}/threading_mutex.h
)

set(sources
Expand All @@ -56,6 +57,23 @@ if(
)
endif()

if(WIN32)
set(sources
${sources}
${source_path}/threading_mutex_win32.c
)
elseif(APPLE)
set(sources
${sources}
${source_path}/threading_mutex_macos.c
)
else()
set(sources
${sources}
${source_path}/threading_mutex_pthread.c
)
endif()

# Group source files
set(header_group "Header Files (API)")
set(source_group "Source Files")
Expand Down
59 changes: 59 additions & 0 deletions source/threading/include/threading/threading_atomic_ref_count.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@

#include <threading/threading_atomic.h>

#if defined(__THREAD_SANITIZER__)
#include <threading/threading_mutex.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -44,7 +48,12 @@ extern "C" {

struct threading_atomic_ref_count_type
{
#if defined(__THREAD_SANITIZER__)
uintmax_t count;
struct threading_mutex_type m;
#else
atomic_uintmax_t count;
#endif
};

/* -- Type Definitions -- */
Expand All @@ -55,28 +64,68 @@ typedef struct threading_atomic_ref_count_type *threading_atomic_ref_count;

inline void threading_atomic_ref_count_store(threading_atomic_ref_count ref, uintmax_t v)
{
#if defined(__THREAD_SANITIZER__)
threading_mutex_store(&ref->m, &ref->count, &v, sizeof(uintmax_t));
#else
atomic_store(&ref->count, v);
#endif
}

inline void threading_atomic_ref_count_initialize(threading_atomic_ref_count ref)
{
#if defined(__THREAD_SANITIZER__)
uintmax_t init = THREADING_ATOMIC_REF_COUNT_MIN;

threading_mutex_initialize(&ref->m);

threading_mutex_store(&ref->m, &ref->count, &init, sizeof(uintmax_t));
#else
threading_atomic_ref_count_store(ref, THREADING_ATOMIC_REF_COUNT_MIN);
#endif
}

inline uintmax_t threading_atomic_ref_count_load(threading_atomic_ref_count ref)
{
#if defined(__THREAD_SANITIZER__)
uintmax_t result = 0;

threading_mutex_store(&ref->m, &result, &ref->count, sizeof(uintmax_t));

return result;
#else
return atomic_load_explicit(&ref->count, memory_order_relaxed);
#endif
}

inline int threading_atomic_ref_count_increment(threading_atomic_ref_count ref)
{
#if defined(__THREAD_SANITIZER__)
threading_mutex_lock(&ref->m);
{
++ref->count;
}
threading_mutex_unlock(&ref->m);
#else
if (atomic_load_explicit(&ref->count, memory_order_relaxed) == THREADING_ATOMIC_REF_COUNT_MAX)
{
return 1;
}

atomic_fetch_add_explicit(&ref->count, 1, memory_order_relaxed);
#endif

return 0;
}

inline int threading_atomic_ref_count_decrement(threading_atomic_ref_count ref)
{
#if defined(__THREAD_SANITIZER__)
threading_mutex_lock(&ref->m);
{
--ref->count;
}
threading_mutex_unlock(&ref->m);
#else
if (atomic_load_explicit(&ref->count, memory_order_relaxed) == THREADING_ATOMIC_REF_COUNT_MIN)
{
return 1;
Expand All @@ -88,10 +137,20 @@ inline int threading_atomic_ref_count_decrement(threading_atomic_ref_count ref)
{
atomic_thread_fence(memory_order_acquire);
}
#endif

return 0;
}

inline void threading_atomic_ref_count_destroy(threading_atomic_ref_count ref)
{
#if defined(__THREAD_SANITIZER__)
threading_mutex_destroy(&ref->m);
#else
(void)ref;
#endif
}

#ifdef __cplusplus
}
#endif
Expand Down
94 changes: 94 additions & 0 deletions source/threading/include/threading/threading_mutex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Thrading Library by Parra Studios
* A threading library providing utilities for lock-free data structures and more.
*
* Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef THREADING_MUTEX_H
#define THREADING_MUTEX_H 1

/* -- Headers -- */

#include <threading/threading_api.h>

#ifdef __cplusplus
extern "C" {
#endif

/* -- Type Definitions -- */

#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
#include <windows.h>
typedef CRITICAL_SECTION threading_mutex_impl_type;
#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux) || defined(__gnu_linux__) || defined(__TOS_LINUX__)) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__) || \
(defined(bsdi) || defined(__bsdi__)) || \
defined(__DragonFly__)
#include <pthread.h>
typedef pthread_mutex_t threading_mutex_impl_type;
#elif (defined(__MACOS__) || defined(macintosh) || defined(Macintosh) || defined(__TOS_MACOS__)) || \
(defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__)
#include <os/lock.h>
typedef os_unfair_lock threading_mutex_impl_type;
#else
#error "Platform not supported for mutex implementation"
#endif

#include <string.h>

/* -- Member Data -- */

struct threading_mutex_type
{
threading_mutex_impl_type impl;
};

/* -- Type Definitions -- */

typedef struct threading_mutex_type *threading_mutex;

/* -- Methods -- */

int threading_mutex_initialize(threading_mutex m);

int threading_mutex_lock(threading_mutex m);

int threading_mutex_try_lock(threading_mutex m);

int threading_mutex_unlock(threading_mutex m);

int threading_mutex_destroy(threading_mutex m);

inline int threading_mutex_store(threading_mutex m, void *dest, void *src, size_t size)
{
if (threading_mutex_lock(m) != 0)
{
return 1;
}

memcpy(dest, src, size);

return threading_mutex_unlock(m);
}

#ifdef __cplusplus
}
#endif

#endif /* THREADING_MUTEX_H */
60 changes: 60 additions & 0 deletions source/threading/source/threading_mutex_macos.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Abstract Data Type Library by Parra Studios
* A abstract data type library providing generic containers.
*
* Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

/* -- Headers -- */

#include <threading/threading_mutex.h>

int threading_mutex_initialize(threading_mutex m)
{
m->impl = 0;

return 0;
}

int threading_mutex_lock(threading_mutex m)
{
os_unfair_lock_lock(&m->impl);

return 0;
}

int threading_mutex_try_lock(threading_mutex m)
{
if (os_unfair_lock_trylock(&m->impl) == false)
{
return 1;
}

return 0;
}

int threading_mutex_unlock(threading_mutex m)
{
os_unfair_lock_unlock(&m->impl);

return 0;
}

int threading_mutex_destroy(threading_mutex m)
{
(void)m;
return 0;
}
Loading

0 comments on commit 011617e

Please sign in to comment.