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 THREAD_NUM 3
11 #define BLOCK_SIZE 16
12 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
13 
14 struct k_sem sync_sema;
15 static K_THREAD_STACK_ARRAY_DEFINE(tstack, THREAD_NUM, STACK_SIZE);
16 static struct k_thread tdata[THREAD_NUM];
17 static void *pool_blocks[BLK_NUM_MAX];
18 
19 /*test cases*/
20 
21 /**
22  * @brief The test validates k_calloc() API.
23  *
24  * @ingroup kernel_heap_tests
25  *
26  * @details The 8 blocks of memory of size 16 bytes are allocated
27  * by k_calloc() API. When allocated using k_calloc() the memory buffers
28  * have to be zeroed. Check is done, if the blocks are memset to 0 and
29  * read/write is allowed. The test is then teared up by freeing all the
30  * blocks allocated.
31  *
32  * @see k_malloc(), k_free()
33  */
ZTEST(mheap_api,test_mheap_malloc_align4)34 ZTEST(mheap_api, test_mheap_malloc_align4)
35 {
36 	void *block[BLK_NUM_MAX];
37 
38 	/**
39 	 * TESTPOINT: The address of the allocated chunk is guaranteed to be
40 	 * aligned on a word boundary (4 or 8 bytes).
41 	 */
42 	for (int i = 0; i < BLK_NUM_MAX; i++) {
43 		block[i] = k_malloc(i);
44 		zassert_not_null(block[i], NULL);
45 		zassert_false((uintptr_t)block[i] % sizeof(void *));
46 	}
47 
48 	/* test case tear down*/
49 	for (int i = 0; i < BLK_NUM_MAX; i++) {
50 		k_free(block[i]);
51 	}
52 }
53 
tmheap_handler(void * p1,void * p2,void * p3)54 static void tmheap_handler(void *p1, void *p2, void *p3)
55 {
56 	int thread_id = POINTER_TO_INT(p1);
57 
58 	pool_blocks[thread_id] = k_malloc(BLOCK_SIZE);
59 
60 	zassert_not_null(pool_blocks[thread_id], "memory is not allocated");
61 
62 	k_sem_give(&sync_sema);
63 }
64 
65 /**
66  * @brief Verify alloc from multiple equal priority threads
67  *
68  * @details Test creates three preemptive threads of equal priority.
69  * In each child thread , call k_malloc() to alloc a block of memory.
70  * Check These four threads can share the same heap space without
71  * interfering with each other.
72  *
73  * @ingroup kernel_memory_slab_tests
74  */
ZTEST(mheap_api,test_mheap_threadsafe)75 ZTEST(mheap_api, test_mheap_threadsafe)
76 {
77 	if (!IS_ENABLED(CONFIG_MULTITHREADING)) {
78 		return;
79 	}
80 
81 	k_tid_t tid[THREAD_NUM];
82 
83 	k_sem_init(&sync_sema, 0, THREAD_NUM);
84 
85 	/* create multiple threads to invoke same memory heap APIs*/
86 	for (int i = 0; i < THREAD_NUM; i++) {
87 		tid[i] = k_thread_create(&tdata[i], tstack[i], STACK_SIZE,
88 					 tmheap_handler, INT_TO_POINTER(i), NULL, NULL,
89 					 K_PRIO_PREEMPT(1), 0, K_NO_WAIT);
90 	}
91 
92 	for (int i = 0; i < THREAD_NUM; i++) {
93 		k_sem_take(&sync_sema, K_FOREVER);
94 	}
95 
96 	for (int i = 0; i < THREAD_NUM; i++) {
97 		/* verify free mheap in main thread */
98 		k_free(pool_blocks[i]);
99 		k_thread_abort(tid[i]);
100 	}
101 }
102