1 /*
2 * Copyright (c) 2016, 2020 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include "test_mheap.h"
9
10 #define THREADSAFE_THREAD_NUM 3
11 #define THREADSAFE_BLOCK_SIZE 16
12 #define THREADSAFE_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
13 #define MALLOC_ALIGN4_STACK_SIZE (512 + (BLK_NUM_MAX * sizeof(void *)))
14
15 struct k_sem threadsafe_sema;
16 static K_THREAD_STACK_ARRAY_DEFINE(threadsafe_tstack, THREADSAFE_THREAD_NUM, THREADSAFE_STACK_SIZE);
17 static struct k_thread threadsafe_tdata[THREADSAFE_THREAD_NUM];
18
19 static void *threadsafe_pool_blocks[BLK_NUM_MAX];
20
21 static K_THREAD_STACK_DEFINE(malloc_align4_tstack, MALLOC_ALIGN4_STACK_SIZE);
22 static struct k_thread malloc_align4_tdata;
23
24 /*test cases*/
25
tmheap_malloc_align4_handler(void * p1,void * p2,void * p3)26 static void tmheap_malloc_align4_handler(void *p1, void *p2, void *p3)
27 {
28 void *block[BLK_NUM_MAX];
29 int i;
30
31 /**
32 * TESTPOINT: The address of the allocated chunk is guaranteed to be
33 * aligned on a word boundary (4 or 8 bytes).
34 */
35 for (i = 0; i < BLK_NUM_MAX; i++) {
36 block[i] = k_malloc(i);
37 if (block[i] == NULL) {
38 break;
39 }
40 zassert_false((uintptr_t)block[i] % sizeof(void *));
41 }
42
43 /* test case tear down*/
44 for (int j = 0; j < i; j++) {
45 k_free(block[j]);
46 }
47 }
48
49 /**
50 * @brief The test validates k_calloc() API.
51 *
52 * @ingroup kernel_heap_tests
53 *
54 * @details The 8 blocks of memory of size 16 bytes are allocated
55 * by k_calloc() API. When allocated using k_calloc() the memory buffers
56 * have to be zeroed. Check is done, if the blocks are memset to 0 and
57 * read/write is allowed. The test is then teared up by freeing all the
58 * blocks allocated.
59 *
60 * @see k_malloc(), k_free()
61 */
ZTEST(mheap_api,test_mheap_malloc_align4)62 ZTEST(mheap_api, test_mheap_malloc_align4)
63 {
64 if (!IS_ENABLED(CONFIG_MULTITHREADING)) {
65 return;
66 }
67
68 k_tid_t tid = k_thread_create(&malloc_align4_tdata, malloc_align4_tstack,
69 MALLOC_ALIGN4_STACK_SIZE,
70 tmheap_malloc_align4_handler,
71 NULL, NULL, NULL,
72 K_PRIO_PREEMPT(1), 0, K_NO_WAIT);
73
74 k_thread_join(tid, K_FOREVER);
75 }
76
tmheap_threadsafe_handler(void * p1,void * p2,void * p3)77 static void tmheap_threadsafe_handler(void *p1, void *p2, void *p3)
78 {
79 int thread_id = POINTER_TO_INT(p1);
80
81 threadsafe_pool_blocks[thread_id] = k_malloc(THREADSAFE_BLOCK_SIZE);
82
83 zassert_not_null(threadsafe_pool_blocks[thread_id], "memory is not allocated");
84
85 k_sem_give(&threadsafe_sema);
86 }
87
88 /**
89 * @brief Verify alloc from multiple equal priority threads
90 *
91 * @details Test creates three preemptive threads of equal priority.
92 * In each child thread , call k_malloc() to alloc a block of memory.
93 * Check These four threads can share the same heap space without
94 * interfering with each other.
95 *
96 * @ingroup kernel_memory_slab_tests
97 */
ZTEST(mheap_api,test_mheap_threadsafe)98 ZTEST(mheap_api, test_mheap_threadsafe)
99 {
100 if (!IS_ENABLED(CONFIG_MULTITHREADING)) {
101 return;
102 }
103
104 k_tid_t tid[THREADSAFE_THREAD_NUM];
105
106 k_sem_init(&threadsafe_sema, 0, THREADSAFE_THREAD_NUM);
107
108 /* create multiple threads to invoke same memory heap APIs*/
109 for (int i = 0; i < THREADSAFE_THREAD_NUM; i++) {
110 tid[i] = k_thread_create(&threadsafe_tdata[i], threadsafe_tstack[i],
111 THREADSAFE_STACK_SIZE, tmheap_threadsafe_handler,
112 INT_TO_POINTER(i), NULL, NULL,
113 K_PRIO_PREEMPT(1), 0, K_NO_WAIT);
114 }
115
116 for (int i = 0; i < THREADSAFE_THREAD_NUM; i++) {
117 k_sem_take(&threadsafe_sema, K_FOREVER);
118 }
119
120 for (int i = 0; i < THREADSAFE_THREAD_NUM; i++) {
121 /* verify free mheap in main thread */
122 k_free(threadsafe_pool_blocks[i]);
123 k_thread_abort(tid[i]);
124 }
125 }
126