|  | /* | 
|  | * Copyright (c) 2018 Intel Corporation | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <kernel.h> | 
|  | #include <string.h> | 
|  | #include "wrapper.h" | 
|  |  | 
|  | #define TIME_OUT_TICKS  10 | 
|  |  | 
|  | K_MEM_SLAB_DEFINE(cv2_mem_slab, sizeof(struct cv2_mslab), | 
|  | CONFIG_CMSIS_V2_MEM_SLAB_MAX_COUNT, 4); | 
|  |  | 
|  | static const osMemoryPoolAttr_t init_mslab_attrs = { | 
|  | .name = "ZephyrMemPool", | 
|  | .attr_bits = 0, | 
|  | .cb_mem = NULL, | 
|  | .cb_size = 0, | 
|  | .mp_mem = NULL, | 
|  | .mp_size = 0, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief Create and Initialize a memory pool. | 
|  | */ | 
|  | osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size, | 
|  | const osMemoryPoolAttr_t *attr) | 
|  | { | 
|  | struct cv2_mslab *mslab; | 
|  |  | 
|  | BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE >= | 
|  | CONFIG_CMSIS_V2_MEM_SLAB_MAX_DYNAMIC_SIZE, | 
|  | "heap must be configured to be at least the max dynamic size"); | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if ((attr != NULL) && (attr->mp_size < block_count * block_size)) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if (attr == NULL) { | 
|  | attr = &init_mslab_attrs; | 
|  | } | 
|  |  | 
|  | if (k_mem_slab_alloc(&cv2_mem_slab, (void **)&mslab, K_MSEC(100)) == 0) { | 
|  | (void)memset(mslab, 0, sizeof(struct cv2_mslab)); | 
|  | } else { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if (attr->mp_mem == NULL) { | 
|  | __ASSERT((block_count * block_size) <= | 
|  | CONFIG_CMSIS_V2_MEM_SLAB_MAX_DYNAMIC_SIZE, | 
|  | "memory slab/pool size exceeds dynamic maximum"); | 
|  |  | 
|  | mslab->pool = k_calloc(block_count, block_size); | 
|  | if (mslab->pool == NULL) { | 
|  | k_mem_slab_free(&cv2_mem_slab, (void *) &mslab); | 
|  | return NULL; | 
|  | } | 
|  | mslab->is_dynamic_allocation = TRUE; | 
|  | } else { | 
|  | mslab->pool = attr->mp_mem; | 
|  | mslab->is_dynamic_allocation = FALSE; | 
|  | } | 
|  |  | 
|  | k_mem_slab_init(&mslab->z_mslab, mslab->pool, block_size, block_count); | 
|  |  | 
|  | if (attr->name == NULL) { | 
|  | strncpy(mslab->name, init_mslab_attrs.name, | 
|  | sizeof(mslab->name) - 1); | 
|  | } else { | 
|  | strncpy(mslab->name, attr->name, sizeof(mslab->name) - 1); | 
|  | } | 
|  |  | 
|  | return (osMemoryPoolId_t)mslab; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Allocate a memory block from a memory pool. | 
|  | */ | 
|  | void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  | int retval; | 
|  | void *ptr; | 
|  |  | 
|  | if (mslab == NULL) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /* Can be called from ISRs only if timeout is set to 0 */ | 
|  | if (timeout > 0 && k_is_in_isr()) { | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | if (timeout == 0U) { | 
|  | retval = k_mem_slab_alloc( | 
|  | (struct k_mem_slab *)(&mslab->z_mslab), | 
|  | (void **)&ptr, K_NO_WAIT); | 
|  | } else if (timeout == osWaitForever) { | 
|  | retval = k_mem_slab_alloc( | 
|  | (struct k_mem_slab *)(&mslab->z_mslab), | 
|  | (void **)&ptr, K_FOREVER); | 
|  | } else { | 
|  | retval = k_mem_slab_alloc( | 
|  | (struct k_mem_slab *)(&mslab->z_mslab), | 
|  | (void **)&ptr, k_ticks_to_ms_floor64(timeout)); | 
|  | } | 
|  |  | 
|  | if (retval == 0) { | 
|  | return ptr; | 
|  | } else { | 
|  | return NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Return an allocated memory block back to a specific memory pool. | 
|  | */ | 
|  | osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  |  | 
|  | if (mslab == NULL) { | 
|  | return osErrorParameter; | 
|  | } | 
|  |  | 
|  | /* Note: Below error code is not supported. | 
|  | *       osErrorResource: the memory pool specified by parameter mp_id | 
|  | *       is in an invalid memory pool state. | 
|  | */ | 
|  |  | 
|  | k_mem_slab_free((struct k_mem_slab *)(&mslab->z_mslab), (void *)&block); | 
|  |  | 
|  | return osOK; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Get name of a Memory Pool object. | 
|  | */ | 
|  | const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  |  | 
|  | if (!k_is_in_isr() && (mslab != NULL)) { | 
|  | return mslab->name; | 
|  | } else { | 
|  | return NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Get maximum number of memory blocks in a Memory Pool. | 
|  | */ | 
|  | uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  |  | 
|  | if (mslab == NULL) { | 
|  | return 0; | 
|  | } else { | 
|  | return mslab->z_mslab.num_blocks; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Get memory block size in a Memory Pool. | 
|  | */ | 
|  | uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  |  | 
|  | if (mslab == NULL) { | 
|  | return 0; | 
|  | } else { | 
|  | return mslab->z_mslab.block_size; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Get number of memory blocks used in a Memory Pool. | 
|  | */ | 
|  | uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  |  | 
|  | if (mslab == NULL) { | 
|  | return 0; | 
|  | } else { | 
|  | return k_mem_slab_num_used_get(&mslab->z_mslab); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Get number of memory blocks available in a Memory Pool. | 
|  | */ | 
|  | uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  |  | 
|  | if (mslab == NULL) { | 
|  | return 0; | 
|  | } else { | 
|  | return k_mem_slab_num_free_get(&mslab->z_mslab); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @brief Delete a Memory Pool object. | 
|  | */ | 
|  | osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id) | 
|  | { | 
|  | struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id; | 
|  |  | 
|  | if (mslab == NULL) { | 
|  | return osErrorParameter; | 
|  | } | 
|  |  | 
|  | if (k_is_in_isr()) { | 
|  | return osErrorISR; | 
|  | } | 
|  |  | 
|  | /* The status code "osErrorResource" (the memory pool specified by | 
|  | * parameter mp_id is in an invalid memory pool state) is not | 
|  | * supported in Zephyr. | 
|  | */ | 
|  |  | 
|  | if (mslab->is_dynamic_allocation) { | 
|  | k_free(mslab->pool); | 
|  | } | 
|  | k_mem_slab_free(&cv2_mem_slab, (void *)&mslab); | 
|  |  | 
|  | return osOK; | 
|  | } |