GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tests/gatecore_test/test_threading.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 155 155 100.0%
Functions: 10 10 100.0%
Branches: 89 168 53.0%

Line Branch Exec Source
1 #include "test_threading.h"
2
3 #include "gate/threading.h"
4 #include "gate/synchronization.h"
5 #include "gate/tests.h"
6
7
8 1 GATE_TEST_FUNCTION(test_mutex)
9 {
10 1 gate_mutex_t mutex = GATE_INIT_EMPTY;
11
12 1 GATE_TEST_UNIT_BEGIN(test_mutex);
13
14
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_mutex_create(&mutex));
15
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_acquire(&mutex));
16
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_release(&mutex));
17
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_destroy(&mutex));
18
19 1 GATE_TEST_UNIT_END;
20 }
21
22 1 GATE_TEST_FUNCTION(test_semaphore)
23 {
24 1 gate_semaphore_t sema = GATE_INIT_EMPTY;
25
26 1 GATE_TEST_UNIT_BEGIN(test_semaphore);
27
28
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_semaphore_create(&sema, 2));
29
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_acquire(&sema));
30
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_timed_acquire(&sema, 500));
31
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_release(&sema));
32
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_release(&sema));
33
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_destroy(&sema));
34
35
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_semaphore_create(&sema, 1));
36
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_acquire(&sema));
37
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_RESULT(GATE_RESULT_TIMEOUT, gate_semaphore_timed_acquire(&sema, 200));
38
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_release(&sema));
39
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_semaphore_destroy(&sema));
40
41 1 GATE_TEST_UNIT_END;
42 }
43
44 1 GATE_TEST_FUNCTION(test_syncevent)
45 {
46 1 gate_syncevent_t evt = GATE_INIT_EMPTY;
47
48 1 GATE_TEST_UNIT_BEGIN(test_syncevent);
49
50
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_syncevent_create(&evt, false));
51
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_syncevent_set(&evt));
52
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_syncevent_timed_wait(&evt, 0));
53
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_syncevent_reset(&evt));
54
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_RESULT(GATE_RESULT_TIMEOUT, gate_syncevent_timed_wait(&evt, 2000));
55
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_syncevent_destroy(&evt));
56
57 1 GATE_TEST_UNIT_END;
58 }
59
60 1 gate_bool_t test_synccondition()
61 {
62 1 gate_mutex_t cond_mutex = GATE_INIT_EMPTY;
63 1 gate_synccondition_t cond = GATE_INIT_EMPTY;
64
65 1 GATE_TEST_UNIT_BEGIN(test_synccondition);
66
67
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_mutex_create(&cond_mutex));
68
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_synccondition_create(&cond));
69
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_acquire(&cond_mutex));
70
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_RESULT(GATE_RESULT_TIMEOUT, gate_synccondition_timed_wait(&cond, &cond_mutex, 0));
71
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_release(&cond_mutex));
72
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_synccondition_signal_one(&cond));
73
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_synccondition_destroy(&cond));
74
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_destroy(&cond_mutex));
75
76 1 GATE_TEST_UNIT_END;
77 }
78
79
80
81 1 gate_bool_t test_atomics()
82 {
83 1 gate_atomic_flag_t flag_atom = GATE_ATOMIC_FLAG_INIT;
84 gate_atomic_int_t int_atom;
85 gate_atomic_int64_t int64_atom;
86 gate_atomic_ptr_t ptr_atom;
87 1 int dummy1 = 42;
88 1 int dummy2 = 24;
89 1 gate_atomic_lock_t lock_atom = GATE_ATOMIC_LOCK_INIT;
90
91 1 GATE_TEST_UNIT_BEGIN(test_atomic);
92
93
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_flag_set(&flag_atom), false);
94
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_flag_set(&flag_atom), true);
95 1 gate_atomic_flag_clear(&flag_atom);
96
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_flag_set(&flag_atom), false);
97
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_flag_set(&flag_atom), true);
98
99 1 gate_atomic_int_init(&int_atom, 1);
100
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_get(&int_atom), 1);
101
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_inc(&int_atom), 2);
102
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_dec(&int_atom), 1);
103
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_set(&int_atom, 10), 1);
104
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_add(&int_atom, 10), 20);
105
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_xchg_if(&int_atom, 10, 100), 20);
106
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_get(&int_atom), 20);
107
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_xchg_if(&int_atom, 20, 100), 20);
108
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int_get(&int_atom), 100);
109
110 1 gate_atomic_int64_init(&int64_atom, 1);
111
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_get(&int64_atom), 1);
112
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_inc(&int64_atom), 2);
113
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_dec(&int64_atom), 1);
114
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_set(&int64_atom, 10), 1);
115
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_add(&int64_atom, 10), 20);
116
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_xchg_if(&int64_atom, 10, 100), 20);
117
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_get(&int64_atom), 20);
118
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_xchg_if(&int64_atom, 20, 100), 20);
119
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_int64_get(&int64_atom), 100);
120
121 1 gate_atomic_ptr_init(&ptr_atom, NULL);
122
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_ptr_set(&ptr_atom, &dummy1), NULL);
123
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_ptr_get(&ptr_atom), &dummy1);
124
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_ptr_xchg_if(&ptr_atom, NULL, &dummy2), &dummy1);
125
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_ptr_get(&ptr_atom), &dummy1);
126
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_ptr_xchg_if(&ptr_atom, &dummy1, &dummy2), &dummy1);
127
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_ptr_get(&ptr_atom), &dummy2);
128
129
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_EQUAL(gate_atomic_lock_acquire_spin(&lock_atom, 1), true);
130 1 gate_atomic_lock_release(&lock_atom);
131
132 1 GATE_TEST_UNIT_END;
133 }
134
135
136 1 static gate_thread_native_return_type GATE_THREAD_API test_thread_entry(gate_thread_native_param_type param)
137 {
138 1 gate_bool_t* ptr_checkpoint_reached = (gate_bool_t*)param;
139 1 gate_thread_sleep(10);
140 1 *ptr_checkpoint_reached = true;
141 1 return (gate_thread_native_return_type)GATE_RESULT_OK;
142 }
143
144 1 static gate_bool_t test_thread_start_join()
145 {
146 1 gate_bool_t checkpoint_reached = false;
147 1 gate_thread_t thread_handle = GATE_INIT_EMPTY;
148 1 gate_thread_id_t thread_id = 0;
149 1 gate_result_t result = GATE_RESULT_FAILED;
150
151
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_thread_start_native(&test_thread_entry, &checkpoint_reached, &thread_handle, &thread_id));
152
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_thread_join(&thread_handle, &result));
153
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(result, GATE_RESULT_OK);
154
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(checkpoint_reached, true);
155 1 return true;
156 }
157
158 typedef struct test_thread_param
159 {
160 gate_synccondition_t cond;
161 gate_mutex_t mutex;
162 gate_size_t input_data[16];
163 gate_size_t input_index;
164 gate_size_t output_data[16];
165 gate_size_t output_index;
166 gate_bool_t completed;
167 } test_thread_param_t;
168
169 1 static gate_thread_native_return_type GATE_THREAD_API test_thread_worker(gate_thread_native_param_type param)
170 {
171 1 test_thread_param_t* ptr_shared = (test_thread_param_t*)param;
172 gate_size_t sz, ndx;
173 1 sz = sizeof(ptr_shared->input_data) / sizeof(ptr_shared->input_data[0]);
174
175 1 ndx = 0;
176 1 gate_mutex_acquire(&ptr_shared->mutex);
177
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
19 while (ndx < sz)
178 {
179
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (ndx < ptr_shared->input_index)
180 {
181 16 ptr_shared->output_data[ndx] = ptr_shared->input_data[ndx];
182 16 ++ptr_shared->output_index;
183 16 ++ndx;
184 }
185 else
186 {
187 2 gate_synccondition_wait(&ptr_shared->cond, &ptr_shared->mutex);
188 }
189 }
190 1 gate_mutex_release(&ptr_shared->mutex);
191
192 1 gate_thread_yield();
193 {
194 1 gate_mutex_acquire(&ptr_shared->mutex);
195 1 ptr_shared->completed = true;
196 1 gate_synccondition_signal_one(&ptr_shared->cond);
197 1 gate_mutex_release(&ptr_shared->mutex);
198 }
199 1 return (gate_thread_native_return_type)GATE_RESULT_OK;
200 }
201 1 static gate_bool_t test_thread_worker_sync()
202 {
203 1 test_thread_param_t shared = GATE_INIT_EMPTY;
204 gate_size_t ndx, sz;
205 1 gate_thread_t thread_handle = GATE_INIT_EMPTY;
206 1 gate_thread_id_t thread_id = 0;
207 1 gate_result_t result = GATE_RESULT_FAILED;
208
209
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_mutex_create(&shared.mutex));
210
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_synccondition_create(&shared.cond));
211
212 1 shared.input_index = 0;
213 1 shared.output_index = 0;
214 1 sz = sizeof(shared.input_data) / sizeof(shared.input_data[0]);
215
216
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_REQUIRE_OK(gate_thread_start_native(&test_thread_worker, &shared, &thread_handle, &thread_id));
217
218
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
17 for (ndx = 0; ndx != sz; ++ndx)
219 {
220
1/2
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
16 GATE_TEST_CHECK_OK(gate_mutex_acquire(&shared.mutex));
221 16 shared.input_data[shared.input_index++] = ndx;
222
1/2
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
16 GATE_TEST_CHECK_OK(gate_synccondition_signal_one(&shared.cond));
223
1/2
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
16 GATE_TEST_CHECK_OK(gate_mutex_release(&shared.mutex));
224 16 gate_thread_yield();
225 }
226
227 {
228
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_acquire(&shared.mutex));
229
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (!shared.completed)
230 {
231
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_synccondition_wait(&shared.cond, &shared.mutex));
232 }
233
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_release(&shared.mutex));
234 }
235
236
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_thread_join(&thread_handle, &result));
237
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 GATE_TEST_CHECK_EQUAL(result, GATE_RESULT_OK);
238
239
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
17 for (ndx = 0; ndx != sz; ++ndx)
240 {
241
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 GATE_TEST_CHECK_EQUAL(shared.input_data[ndx], shared.output_data[ndx]);
242 }
243
244
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_synccondition_destroy(&shared.cond));
245
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK_OK(gate_mutex_destroy(&shared.mutex));
246
247 1 return true;
248 }
249
250
251 1 gate_bool_t test_threads()
252 {
253 int thread_model;
254
255 1 GATE_TEST_UNIT_BEGIN(test_thread);
256
257 1 thread_model = gate_thread_model();
258
259
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (thread_model == GATE_THREAD_MODEL_NATIVE)
260 {
261
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK(test_thread_start_join());
262
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 GATE_TEST_CHECK(test_thread_worker_sync());
263 }
264
265 1 GATE_TEST_UNIT_END;
266 }
267
268