Skip to content

Commit 771c177

Browse files
dcpleungnashif
authored andcommitted
tests: k_heap_api: make alloc pending tests a bit more robust
Both alloc_pending tests requires the main thread to utilize the heap so that child threads must pend on memory allocations. However, the previous implementation was not SMP friendly where the child threads could run and succeeded in memory allocation on other CPUs while the main thread continued to allocate memory. The main thread would fail to allocate memory if the child thread (on other CPU) has not freed the memory yet. Not to mention that, in this scenario, the child thread was not pending on memory allocation which defeated the purpose of the test. So to fix this, make sure the main thread allocates enough memory so future allocations must go into pending. Also, check that the child thread cannot allocation memory when first entered so it is actually going into pending. Signed-off-by: Daniel Leung <[email protected]>
1 parent f647201 commit 771c177

File tree

1 file changed

+52
-16
lines changed

1 file changed

+52
-16
lines changed

tests/kernel/mem_heap/k_heap_api/src/test_kheap_api.c

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,35 @@ static void tIsr_kheap_alloc_nowait(void *data)
3030

3131
static void thread_alloc_heap(void *p1, void *p2, void *p3)
3232
{
33+
char *p;
34+
3335
k_timeout_t timeout = Z_TIMEOUT_MS(200);
3436

35-
char *p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_2, timeout);
37+
p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_2, K_NO_WAIT);
38+
39+
zassert_is_null(p, "k_heap_alloc should fail but did not");
40+
41+
p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_2, timeout);
42+
43+
zassert_not_null(p, "k_heap_alloc failed to allocate memory");
3644

37-
zassert_not_null(p, "k_heap_alloc operation failed");
3845
k_heap_free(&k_heap_test, p);
3946
}
4047

4148
static void thread_alloc_heap_null(void *p1, void *p2, void *p3)
4249
{
50+
char *p;
51+
4352
k_timeout_t timeout = Z_TIMEOUT_MS(200);
4453

45-
char *p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_2, timeout);
54+
p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_2, K_NO_WAIT);
55+
56+
zassert_is_null(p, "k_heap_alloc should fail but did not");
57+
58+
p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_2, timeout);
59+
60+
zassert_is_null(p, "k_heap_alloc should fail but did not");
4661

47-
zassert_is_null(p, "k_heap_alloc_null operation failed");
4862
k_heap_free(&k_heap_test, p);
4963
}
5064

@@ -186,16 +200,26 @@ void test_kheap_alloc_in_isr_nowait(void)
186200
*/
187201
void test_k_heap_alloc_pending(void)
188202
{
189-
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
190-
thread_alloc_heap, NULL, NULL, NULL,
191-
K_PRIO_PREEMPT(5), 0, K_NO_WAIT);
192-
203+
/*
204+
* Allocate first to make sure subsequent allocations
205+
* either fail (K_NO_WAIT) or pend.
206+
*/
193207
char *p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_2, K_NO_WAIT);
194208

195209
zassert_not_null(p, "k_heap_alloc operation failed");
196210

197-
/* make the child thread run */
198-
k_msleep(1);
211+
/* Create a thread which will pend on allocation */
212+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
213+
thread_alloc_heap, NULL, NULL, NULL,
214+
K_PRIO_PREEMPT(5), 0, K_NO_WAIT);
215+
216+
/* Sleep long enough for child thread to go into pending */
217+
k_msleep(5);
218+
219+
/*
220+
* Free memory so the child thread can finish memory allocation
221+
* without failing.
222+
*/
199223
k_heap_free(&k_heap_test, p);
200224

201225
k_thread_join(tid, K_FOREVER);
@@ -213,19 +237,31 @@ void test_k_heap_alloc_pending(void)
213237
*/
214238
void test_k_heap_alloc_pending_null(void)
215239
{
216-
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
217-
thread_alloc_heap_null, NULL, NULL, NULL,
218-
K_PRIO_PREEMPT(5), 0, K_NO_WAIT);
219-
240+
/*
241+
* Allocate first to make sure subsequent allocations
242+
* either fail (K_NO_WAIT) or pend.
243+
*/
220244
char *p = (char *)k_heap_alloc(&k_heap_test, ALLOC_SIZE_1, K_NO_WAIT);
221245
char *q = (char *)k_heap_alloc(&k_heap_test, 512, K_NO_WAIT);
222246

223247
zassert_not_null(p, "k_heap_alloc operation failed");
224248
zassert_not_null(q, "k_heap_alloc operation failed");
225-
/* make the child thread run */
226-
k_msleep(1);
249+
250+
/* Create a thread which will pend on allocation */
251+
k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE,
252+
thread_alloc_heap_null, NULL, NULL, NULL,
253+
K_PRIO_PREEMPT(5), 0, K_NO_WAIT);
254+
255+
/* Sleep long enough for child thread to go into pending */
256+
k_msleep(5);
257+
258+
/*
259+
* Free some memory but new thread will still not be able
260+
* to finish memory allocation without error.
261+
*/
227262
k_heap_free(&k_heap_test, q);
228263

229264
k_thread_join(tid, K_FOREVER);
265+
230266
k_heap_free(&k_heap_test, p);
231267
}

0 commit comments

Comments
 (0)