1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include "test_mslab.h"
9
10 #define THREAD_NUM 3
11 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
12
13 K_MEM_SLAB_DEFINE(mslab1, BLK_SIZE, BLK_NUM, BLK_ALIGN);
14
15 static K_THREAD_STACK_ARRAY_DEFINE(tstack, THREAD_NUM, STACK_SIZE);
16 static struct k_thread tdata[THREAD_NUM];
17 static struct k_sem sync_sema;
18 static void *block_ok;
19
20 /*thread entry*/
tmslab_alloc_wait_timeout(void * p1,void * p2,void * p3)21 void tmslab_alloc_wait_timeout(void *p1, void *p2, void *p3)
22 {
23 void *block;
24
25 zassert_true(k_mem_slab_alloc(&mslab1, &block, TIMEOUT) == -EAGAIN,
26 NULL);
27 k_sem_give(&sync_sema);
28 }
29
tmslab_alloc_wait_ok(void * p1,void * p2,void * p3)30 void tmslab_alloc_wait_ok(void *p1, void *p2, void *p3)
31 {
32 zassert_true(k_mem_slab_alloc(&mslab1, &block_ok, TIMEOUT) == 0);
33 k_sem_give(&sync_sema);
34 }
35
36 /*test cases*/
37 /**
38 * @brief Verify alloc with multiple threads
39 *
40 * @details The test allocates all blocks of memory slab and
41 * then spawns 3 threads with lowest priority and 2 more with
42 * same priority higher than first thread with delay 10ms and
43 * 20ms. Checks the behavior of alloc when requested by multiple
44 * threads
45 *
46 * @ingroup kernel_memory_slab_tests
47 *
48 * @see k_mem_slab_alloc()
49 * @see k_mem_slab_free()
50 */
ZTEST(mslab_concept,test_mslab_alloc_wait_prio)51 ZTEST(mslab_concept, test_mslab_alloc_wait_prio)
52 {
53 void *block[BLK_NUM];
54 k_tid_t tid[THREAD_NUM];
55
56 k_sem_init(&sync_sema, 0, THREAD_NUM);
57 /*allocated up all blocks*/
58 for (int i = 0; i < BLK_NUM; i++) {
59 zassert_equal(k_mem_slab_alloc(&mslab1, &block[i], K_NO_WAIT),
60 0, NULL);
61 }
62
63 /**
64 * TESTPOINT: Any number of threads may wait on an empty memory slab
65 * simultaneously; when a memory block becomes available, it is given to
66 * the highest-priority thread that has waited the longest.
67 */
68 /**
69 * TESTPOINT: If all the blocks are currently in use, a thread can
70 * optionally wait for one to become available.
71 */
72 /*the low-priority thread*/
73 tid[0] = k_thread_create(&tdata[0], tstack[0], STACK_SIZE,
74 tmslab_alloc_wait_timeout, NULL, NULL, NULL,
75 K_PRIO_PREEMPT(1), 0, K_NO_WAIT);
76 /*the highest-priority thread that has waited the longest*/
77 tid[1] = k_thread_create(&tdata[1], tstack[1], STACK_SIZE,
78 tmslab_alloc_wait_ok, NULL, NULL, NULL,
79 K_PRIO_PREEMPT(0), 0, K_MSEC(10));
80 /*the highest-priority thread that has waited shorter*/
81 tid[2] = k_thread_create(&tdata[2], tstack[2], STACK_SIZE,
82 tmslab_alloc_wait_timeout, NULL, NULL, NULL,
83 K_PRIO_PREEMPT(0), 0, K_MSEC(20));
84 /*relinquish CPU for above threads to start */
85 k_msleep(30);
86 /*free one block, expected to unblock thread "tid[1]"*/
87 k_mem_slab_free(&mslab1, block[0]);
88 /*wait for all threads exit*/
89 for (int i = 0; i < THREAD_NUM; i++) {
90 k_sem_take(&sync_sema, K_FOREVER);
91 }
92
93 /*test case tear down*/
94 for (int i = 0; i < THREAD_NUM; i++) {
95 k_thread_abort(tid[i]);
96 }
97 k_mem_slab_free(&mslab1, block_ok);
98 for (int i = 1; i < BLK_NUM; i++) {
99 k_mem_slab_free(&mslab1, block[i]);
100 }
101 }
102