Skip to content

Commit 011617e

Browse files
committed
Remove atomics for thread sanitizedr, add mutex alternate option for reference counting.
1 parent a780f6b commit 011617e

11 files changed

+356
-6
lines changed

source/reflect/source/reflect_class.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ klass class_create(const char *name, enum accessor_type_id accessor, class_impl
108108

109109
cls->impl = impl;
110110
cls->accessor = accessor;
111-
threading_atomic_ref_count_store(&cls->ref, 0);
111+
threading_atomic_ref_count_initialize(&cls->ref);
112112
cls->interface = singleton ? singleton() : NULL;
113113
cls->constructors = vector_create_type(constructor);
114114
cls->methods = map_create(&hash_callback_str, &comparable_callback_str);
@@ -901,6 +901,8 @@ void class_destroy(klass cls)
901901
set_destroy(cls->static_attributes);
902902
}
903903

904+
threading_atomic_ref_count_destroy(&cls->ref);
905+
904906
free(cls);
905907

906908
reflect_memory_tracker_deallocation(class_stats);

source/reflect/source/reflect_exception.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ exception exception_create(char *message, char *label, int64_t code, char *stack
5858
ex->stacktrace = stacktrace;
5959
ex->id = thread_id_get_current();
6060

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

6363
reflect_memory_tracker_allocation(exception_stats);
6464

@@ -131,7 +131,7 @@ exception exception_create_const(const char *message, const char *label, int64_t
131131
ex->code = code;
132132
ex->id = thread_id_get_current();
133133

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

136136
reflect_memory_tracker_allocation(exception_stats);
137137

@@ -252,6 +252,8 @@ void exception_destroy(exception ex)
252252
free(ex->stacktrace);
253253
}
254254

255+
threading_atomic_ref_count_destroy(&ex->ref);
256+
255257
free(ex);
256258

257259
reflect_memory_tracker_deallocation(exception_stats);

source/reflect/source/reflect_function.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ function function_create(const char *name, size_t args_count, function_impl impl
9191
goto function_create_error;
9292
}
9393

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

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

@@ -731,6 +731,8 @@ void function_destroy(function func)
731731
free(func->name);
732732
}
733733

734+
threading_atomic_ref_count_destroy(&func->ref);
735+
734736
free(func);
735737

736738
reflect_memory_tracker_deallocation(function_stats);

source/reflect/source/reflect_object.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ object object_create(const char *name, enum accessor_type_id accessor, object_im
8181

8282
obj->impl = impl;
8383
obj->accessor = accessor;
84-
threading_atomic_ref_count_store(&obj->ref, 0);
84+
threading_atomic_ref_count_initialize(&obj->ref);
8585

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

@@ -419,6 +419,8 @@ void object_destroy(object obj)
419419
free(obj->name);
420420
}
421421

422+
threading_atomic_ref_count_destroy(&obj->ref);
423+
422424
free(obj);
423425

424426
reflect_memory_tracker_deallocation(object_stats);

source/tests/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ add_subdirectory(metacall_node_async_resources_test)
146146
add_subdirectory(metacall_node_await_chain_test)
147147
add_subdirectory(metacall_node_exception_test)
148148
add_subdirectory(metacall_node_python_deadlock_test)
149-
add_subdirectory(metacall_node_signal_handler_test)
149+
# 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
150150
add_subdirectory(metacall_node_native_code_test)
151151
add_subdirectory(metacall_node_extension_test)
152152
add_subdirectory(metacall_distributable_test)

source/threading/CMakeLists.txt

+18
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ set(headers
3838
${include_path}/threading_atomic.h
3939
${include_path}/threading_thread_id.h
4040
${include_path}/threading_atomic_ref_count.h
41+
${include_path}/threading_mutex.h
4142
)
4243

4344
set(sources
@@ -56,6 +57,23 @@ if(
5657
)
5758
endif()
5859

60+
if(WIN32)
61+
set(sources
62+
${sources}
63+
${source_path}/threading_mutex_win32.c
64+
)
65+
elseif(APPLE)
66+
set(sources
67+
${sources}
68+
${source_path}/threading_mutex_macos.c
69+
)
70+
else()
71+
set(sources
72+
${sources}
73+
${source_path}/threading_mutex_pthread.c
74+
)
75+
endif()
76+
5977
# Group source files
6078
set(header_group "Header Files (API)")
6179
set(source_group "Source Files")

source/threading/include/threading/threading_atomic_ref_count.h

+59
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727

2828
#include <threading/threading_atomic.h>
2929

30+
#if defined(__THREAD_SANITIZER__)
31+
#include <threading/threading_mutex.h>
32+
#endif
33+
3034
#ifdef __cplusplus
3135
extern "C" {
3236
#endif
@@ -44,7 +48,12 @@ extern "C" {
4448

4549
struct threading_atomic_ref_count_type
4650
{
51+
#if defined(__THREAD_SANITIZER__)
52+
uintmax_t count;
53+
struct threading_mutex_type m;
54+
#else
4755
atomic_uintmax_t count;
56+
#endif
4857
};
4958

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

5665
inline void threading_atomic_ref_count_store(threading_atomic_ref_count ref, uintmax_t v)
5766
{
67+
#if defined(__THREAD_SANITIZER__)
68+
threading_mutex_store(&ref->m, &ref->count, &v, sizeof(uintmax_t));
69+
#else
5870
atomic_store(&ref->count, v);
71+
#endif
72+
}
73+
74+
inline void threading_atomic_ref_count_initialize(threading_atomic_ref_count ref)
75+
{
76+
#if defined(__THREAD_SANITIZER__)
77+
uintmax_t init = THREADING_ATOMIC_REF_COUNT_MIN;
78+
79+
threading_mutex_initialize(&ref->m);
80+
81+
threading_mutex_store(&ref->m, &ref->count, &init, sizeof(uintmax_t));
82+
#else
83+
threading_atomic_ref_count_store(ref, THREADING_ATOMIC_REF_COUNT_MIN);
84+
#endif
5985
}
6086

6187
inline uintmax_t threading_atomic_ref_count_load(threading_atomic_ref_count ref)
6288
{
89+
#if defined(__THREAD_SANITIZER__)
90+
uintmax_t result = 0;
91+
92+
threading_mutex_store(&ref->m, &result, &ref->count, sizeof(uintmax_t));
93+
94+
return result;
95+
#else
6396
return atomic_load_explicit(&ref->count, memory_order_relaxed);
97+
#endif
6498
}
6599

66100
inline int threading_atomic_ref_count_increment(threading_atomic_ref_count ref)
67101
{
102+
#if defined(__THREAD_SANITIZER__)
103+
threading_mutex_lock(&ref->m);
104+
{
105+
++ref->count;
106+
}
107+
threading_mutex_unlock(&ref->m);
108+
#else
68109
if (atomic_load_explicit(&ref->count, memory_order_relaxed) == THREADING_ATOMIC_REF_COUNT_MAX)
69110
{
70111
return 1;
71112
}
72113

73114
atomic_fetch_add_explicit(&ref->count, 1, memory_order_relaxed);
115+
#endif
74116

75117
return 0;
76118
}
77119

78120
inline int threading_atomic_ref_count_decrement(threading_atomic_ref_count ref)
79121
{
122+
#if defined(__THREAD_SANITIZER__)
123+
threading_mutex_lock(&ref->m);
124+
{
125+
--ref->count;
126+
}
127+
threading_mutex_unlock(&ref->m);
128+
#else
80129
if (atomic_load_explicit(&ref->count, memory_order_relaxed) == THREADING_ATOMIC_REF_COUNT_MIN)
81130
{
82131
return 1;
@@ -88,10 +137,20 @@ inline int threading_atomic_ref_count_decrement(threading_atomic_ref_count ref)
88137
{
89138
atomic_thread_fence(memory_order_acquire);
90139
}
140+
#endif
91141

92142
return 0;
93143
}
94144

145+
inline void threading_atomic_ref_count_destroy(threading_atomic_ref_count ref)
146+
{
147+
#if defined(__THREAD_SANITIZER__)
148+
threading_mutex_destroy(&ref->m);
149+
#else
150+
(void)ref;
151+
#endif
152+
}
153+
95154
#ifdef __cplusplus
96155
}
97156
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Thrading Library by Parra Studios
3+
* A threading library providing utilities for lock-free data structures and more.
4+
*
5+
* Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia <[email protected]>
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*
19+
*/
20+
21+
#ifndef THREADING_MUTEX_H
22+
#define THREADING_MUTEX_H 1
23+
24+
/* -- Headers -- */
25+
26+
#include <threading/threading_api.h>
27+
28+
#ifdef __cplusplus
29+
extern "C" {
30+
#endif
31+
32+
/* -- Type Definitions -- */
33+
34+
#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
35+
#include <windows.h>
36+
typedef CRITICAL_SECTION threading_mutex_impl_type;
37+
#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux) || defined(__gnu_linux__) || defined(__TOS_LINUX__)) || \
38+
defined(__FreeBSD__) || \
39+
defined(__NetBSD__) || \
40+
defined(__OpenBSD__) || \
41+
(defined(bsdi) || defined(__bsdi__)) || \
42+
defined(__DragonFly__)
43+
#include <pthread.h>
44+
typedef pthread_mutex_t threading_mutex_impl_type;
45+
#elif (defined(__MACOS__) || defined(macintosh) || defined(Macintosh) || defined(__TOS_MACOS__)) || \
46+
(defined(__APPLE__) && defined(__MACH__)) || defined(__MACOSX__)
47+
#include <os/lock.h>
48+
typedef os_unfair_lock threading_mutex_impl_type;
49+
#else
50+
#error "Platform not supported for mutex implementation"
51+
#endif
52+
53+
#include <string.h>
54+
55+
/* -- Member Data -- */
56+
57+
struct threading_mutex_type
58+
{
59+
threading_mutex_impl_type impl;
60+
};
61+
62+
/* -- Type Definitions -- */
63+
64+
typedef struct threading_mutex_type *threading_mutex;
65+
66+
/* -- Methods -- */
67+
68+
int threading_mutex_initialize(threading_mutex m);
69+
70+
int threading_mutex_lock(threading_mutex m);
71+
72+
int threading_mutex_try_lock(threading_mutex m);
73+
74+
int threading_mutex_unlock(threading_mutex m);
75+
76+
int threading_mutex_destroy(threading_mutex m);
77+
78+
inline int threading_mutex_store(threading_mutex m, void *dest, void *src, size_t size)
79+
{
80+
if (threading_mutex_lock(m) != 0)
81+
{
82+
return 1;
83+
}
84+
85+
memcpy(dest, src, size);
86+
87+
return threading_mutex_unlock(m);
88+
}
89+
90+
#ifdef __cplusplus
91+
}
92+
#endif
93+
94+
#endif /* THREADING_MUTEX_H */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Abstract Data Type Library by Parra Studios
3+
* A abstract data type library providing generic containers.
4+
*
5+
* Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia <[email protected]>
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*
19+
*/
20+
21+
/* -- Headers -- */
22+
23+
#include <threading/threading_mutex.h>
24+
25+
int threading_mutex_initialize(threading_mutex m)
26+
{
27+
m->impl = 0;
28+
29+
return 0;
30+
}
31+
32+
int threading_mutex_lock(threading_mutex m)
33+
{
34+
os_unfair_lock_lock(&m->impl);
35+
36+
return 0;
37+
}
38+
39+
int threading_mutex_try_lock(threading_mutex m)
40+
{
41+
if (os_unfair_lock_trylock(&m->impl) == false)
42+
{
43+
return 1;
44+
}
45+
46+
return 0;
47+
}
48+
49+
int threading_mutex_unlock(threading_mutex m)
50+
{
51+
os_unfair_lock_unlock(&m->impl);
52+
53+
return 0;
54+
}
55+
56+
int threading_mutex_destroy(threading_mutex m)
57+
{
58+
(void)m;
59+
return 0;
60+
}

0 commit comments

Comments
 (0)