blob: 42dc189fee0f086b1e72b98dc2bbad6d644c7382 [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @addtogroup t_mslab
* @{
* @defgroup t_mslab_concept test_mslab_concept
* @brief TestPurpose: verify memory slab concepts.
* @details All TESTPOINTs extracted from kernel documentation.
* TESTPOINTs cover testable kernel behaviours that preserve across internal
* implementation change or kernel version change.
* As a black-box test, TESTPOINTs do not cover internal operations.
*
* TESTPOINTs duplicated to <kernel.h> are covered in API test:
* - TESTPOINT: ensure that all memory blocks in the buffer are similarly
* aligned to this boundary
* - TESTPOINT: A memory slab must be initialized before it can be used. This
* marks all of its blocks as unused.
*
* TESTPOINTS related to multiple instances are covered in re-entrance test:
* - TESTPOINT: Unlike a heap, more than one memory slab can be defined, if
* needed.
* @}
*/
#include <ztest.h>
#include "test_mslab.h"
#define THREAD_NUM 3
#define STACK_SIZE 512
K_MEM_SLAB_DEFINE(mslab1, BLK_SIZE, BLK_NUM, BLK_ALIGN);
static char __noinit __stack tstack[THREAD_NUM][STACK_SIZE];
static struct k_sem sync_sema;
static void *block_ok;
/*thread entry*/
void tmslab_alloc_wait_timeout(void *p1, void *p2, void *p3)
{
void *block;
assert_true(k_mem_slab_alloc(&mslab1, &block, TIMEOUT) == -EAGAIN,
NULL);
k_sem_give(&sync_sema);
}
void tmslab_alloc_wait_ok(void *p1, void *p2, void *p3)
{
assert_true(k_mem_slab_alloc(&mslab1, &block_ok, TIMEOUT) == 0, NULL);
k_sem_give(&sync_sema);
}
/*test cases*/
void test_mslab_alloc_wait_prio(void)
{
void *block[BLK_NUM];
k_tid_t tid[THREAD_NUM];
k_sem_init(&sync_sema, 0, THREAD_NUM);
/*allocated up all blocks*/
for (int i = 0; i < BLK_NUM; i++) {
assert_equal(k_mem_slab_alloc(&mslab1, &block[i], K_NO_WAIT),
0, NULL);
}
/**
* TESTPOINT: Any number of threads may wait on an empty memory slab
* simultaneously; when a memory block becomes available, it is given to
* the highest-priority thread that has waited the longest.
*/
/**
* TESTPOINT: If all the blocks are currently in use, a thread can
* optionally wait for one to become available.
*/
/*the low-priority thread*/
tid[0] = k_thread_spawn(tstack[0], STACK_SIZE,
tmslab_alloc_wait_timeout, NULL, NULL, NULL,
K_PRIO_PREEMPT(1), 0, 0);
/*the highest-priority thread that has waited the longest*/
tid[1] = k_thread_spawn(tstack[1], STACK_SIZE,
tmslab_alloc_wait_ok, NULL, NULL, NULL,
K_PRIO_PREEMPT(0), 0, 10);
/*the highest-priority thread that has waited shorter*/
tid[2] = k_thread_spawn(tstack[2], STACK_SIZE,
tmslab_alloc_wait_timeout, NULL, NULL, NULL,
K_PRIO_PREEMPT(0), 0, 20);
/*relinquish CPU for above threads to start */
k_sleep(30);
/*free one block, expected to unblock thread "tid[1]"*/
k_mem_slab_free(&mslab1, &block[0]);
/*wait for all threads exit*/
for (int i = 0; i < THREAD_NUM; i++) {
k_sem_take(&sync_sema, K_FOREVER);
}
/*test case tear down*/
for (int i = 0; i < THREAD_NUM; i++) {
k_thread_abort(tid[i]);
}
k_mem_slab_free(&mslab1, &block_ok);
for (int i = 1; i < BLK_NUM; i++) {
k_mem_slab_free(&mslab1, &block[i]);
}
}