rtx_mempool.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. /*
  2. * Copyright (c) 2013-2021 Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * -----------------------------------------------------------------------------
  19. *
  20. * Project: CMSIS-RTOS RTX
  21. * Title: Memory Pool functions
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. #include "rtx_lib.h"
  26. // OS Runtime Object Memory Usage
  27. #ifdef RTX_OBJ_MEM_USAGE
  28. osRtxObjectMemUsage_t osRtxMemoryPoolMemUsage \
  29. __attribute__((section(".data.os.mempool.obj"))) =
  30. { 0U, 0U, 0U };
  31. #endif
  32. // ==== Library functions ====
  33. /// Initialize Memory Pool.
  34. /// \param[in] mp_info memory pool info.
  35. /// \param[in] block_count maximum number of memory blocks in memory pool.
  36. /// \param[in] block_size size of a memory block in bytes.
  37. /// \param[in] block_mem pointer to memory for block storage.
  38. /// \return 1 - success, 0 - failure.
  39. uint32_t osRtxMemoryPoolInit (os_mp_info_t *mp_info, uint32_t block_count, uint32_t block_size, void *block_mem) {
  40. //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  41. void *mem;
  42. void *block;
  43. // Check parameters
  44. if ((mp_info == NULL) || (block_count == 0U) || (block_size == 0U) || (block_mem == NULL)) {
  45. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  46. return 0U;
  47. }
  48. // Initialize information structure
  49. mp_info->max_blocks = block_count;
  50. mp_info->used_blocks = 0U;
  51. mp_info->block_size = block_size;
  52. mp_info->block_base = block_mem;
  53. mp_info->block_free = block_mem;
  54. mp_info->block_lim = &(((uint8_t *)block_mem)[block_count * block_size]);
  55. EvrRtxMemoryBlockInit(mp_info, block_count, block_size, block_mem);
  56. // Link all free blocks
  57. mem = block_mem;
  58. while (--block_count != 0U) {
  59. block = &((uint8_t *)mem)[block_size];
  60. *((void **)mem) = block;
  61. mem = block;
  62. }
  63. *((void **)mem) = NULL;
  64. return 1U;
  65. }
  66. /// Allocate a memory block from a Memory Pool.
  67. /// \param[in] mp_info memory pool info.
  68. /// \return address of the allocated memory block or NULL in case of no memory is available.
  69. void *osRtxMemoryPoolAlloc (os_mp_info_t *mp_info) {
  70. #if (EXCLUSIVE_ACCESS == 0)
  71. uint32_t primask = __get_PRIMASK();
  72. #endif
  73. void *block;
  74. if (mp_info == NULL) {
  75. EvrRtxMemoryBlockAlloc(NULL, NULL);
  76. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  77. return NULL;
  78. }
  79. #if (EXCLUSIVE_ACCESS == 0)
  80. __disable_irq();
  81. block = mp_info->block_free;
  82. if (block != NULL) {
  83. //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
  84. mp_info->block_free = *((void **)block);
  85. mp_info->used_blocks++;
  86. }
  87. if (primask == 0U) {
  88. __enable_irq();
  89. }
  90. #else
  91. block = atomic_link_get(&mp_info->block_free);
  92. if (block != NULL) {
  93. (void)atomic_inc32(&mp_info->used_blocks);
  94. }
  95. #endif
  96. EvrRtxMemoryBlockAlloc(mp_info, block);
  97. return block;
  98. }
  99. /// Return an allocated memory block back to a Memory Pool.
  100. /// \param[in] mp_info memory pool info.
  101. /// \param[in] block address of the allocated memory block to be returned to the memory pool.
  102. /// \return status code that indicates the execution status of the function.
  103. osStatus_t osRtxMemoryPoolFree (os_mp_info_t *mp_info, void *block) {
  104. #if (EXCLUSIVE_ACCESS == 0)
  105. uint32_t primask = __get_PRIMASK();
  106. #endif
  107. //lint -e{946} "Relational operator applied to pointers"
  108. if ((mp_info == NULL) || (block < mp_info->block_base) || (block >= mp_info->block_lim)) {
  109. EvrRtxMemoryBlockFree(mp_info, block, (int32_t)osErrorParameter);
  110. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  111. return osErrorParameter;
  112. }
  113. #if (EXCLUSIVE_ACCESS == 0)
  114. __disable_irq();
  115. //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
  116. *((void **)block) = mp_info->block_free;
  117. mp_info->block_free = block;
  118. mp_info->used_blocks--;
  119. if (primask == 0U) {
  120. __enable_irq();
  121. }
  122. #else
  123. atomic_link_put(&mp_info->block_free, block);
  124. (void)atomic_dec32(&mp_info->used_blocks);
  125. #endif
  126. EvrRtxMemoryBlockFree(mp_info, block, (int32_t)osOK);
  127. return osOK;
  128. }
  129. // ==== Post ISR processing ====
  130. /// Memory Pool post ISR processing.
  131. /// \param[in] mp memory pool object.
  132. static void osRtxMemoryPoolPostProcess (os_memory_pool_t *mp) {
  133. void *block;
  134. os_thread_t *thread;
  135. // Check if Thread is waiting to allocate memory
  136. if (mp->thread_list != NULL) {
  137. // Allocate memory
  138. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  139. if (block != NULL) {
  140. // Wakeup waiting Thread with highest Priority
  141. thread = osRtxThreadListGet(osRtxObject(mp));
  142. //lint -e{923} "cast from pointer to unsigned int"
  143. osRtxThreadWaitExit(thread, (uint32_t)block, FALSE);
  144. EvrRtxMemoryPoolAllocated(mp, block);
  145. }
  146. }
  147. }
  148. // ==== Service Calls ====
  149. /// Create and Initialize a Memory Pool object.
  150. /// \note API identical to osMemoryPoolNew
  151. static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
  152. os_memory_pool_t *mp;
  153. void *mp_mem;
  154. uint32_t mp_size;
  155. uint32_t b_count;
  156. uint32_t b_size;
  157. uint32_t size;
  158. uint8_t flags;
  159. const char *name;
  160. // Check parameters
  161. if ((block_count == 0U) || (block_size == 0U) ||
  162. ((__CLZ(block_count) + __CLZ(block_size)) < 32U)) {
  163. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
  164. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  165. return NULL;
  166. }
  167. b_count = block_count;
  168. b_size = (block_size + 3U) & ~3UL;
  169. size = b_count * b_size;
  170. // Process attributes
  171. if (attr != NULL) {
  172. name = attr->name;
  173. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  174. mp = attr->cb_mem;
  175. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  176. mp_mem = attr->mp_mem;
  177. mp_size = attr->mp_size;
  178. if (mp != NULL) {
  179. //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
  180. if ((((uint32_t)mp & 3U) != 0U) || (attr->cb_size < sizeof(os_memory_pool_t))) {
  181. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
  182. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  183. return NULL;
  184. }
  185. } else {
  186. if (attr->cb_size != 0U) {
  187. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
  188. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  189. return NULL;
  190. }
  191. }
  192. if (mp_mem != NULL) {
  193. //lint -e{923} "cast from pointer to unsigned int" [MISRA Note 7]
  194. if ((((uint32_t)mp_mem & 3U) != 0U) || (mp_size < size)) {
  195. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
  196. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  197. return NULL;
  198. }
  199. } else {
  200. if (mp_size != 0U) {
  201. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
  202. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  203. return NULL;
  204. }
  205. }
  206. } else {
  207. name = NULL;
  208. mp = NULL;
  209. mp_mem = NULL;
  210. }
  211. // Allocate object memory if not provided
  212. if (mp == NULL) {
  213. if (osRtxInfo.mpi.memory_pool != NULL) {
  214. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  215. mp = osRtxMemoryPoolAlloc(osRtxInfo.mpi.memory_pool);
  216. } else {
  217. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  218. mp = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_memory_pool_t), 1U);
  219. }
  220. #ifdef RTX_OBJ_MEM_USAGE
  221. if (mp != NULL) {
  222. uint32_t used;
  223. osRtxMemoryPoolMemUsage.cnt_alloc++;
  224. used = osRtxMemoryPoolMemUsage.cnt_alloc - osRtxMemoryPoolMemUsage.cnt_free;
  225. if (osRtxMemoryPoolMemUsage.max_used < used) {
  226. osRtxMemoryPoolMemUsage.max_used = used;
  227. }
  228. }
  229. #endif
  230. flags = osRtxFlagSystemObject;
  231. } else {
  232. flags = 0U;
  233. }
  234. // Allocate data memory if not provided
  235. if ((mp != NULL) && (mp_mem == NULL)) {
  236. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  237. mp_mem = osRtxMemoryAlloc(osRtxInfo.mem.mp_data, size, 0U);
  238. if (mp_mem == NULL) {
  239. if ((flags & osRtxFlagSystemObject) != 0U) {
  240. if (osRtxInfo.mpi.memory_pool != NULL) {
  241. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
  242. } else {
  243. (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
  244. }
  245. #ifdef RTX_OBJ_MEM_USAGE
  246. osRtxMemoryPoolMemUsage.cnt_free++;
  247. #endif
  248. }
  249. mp = NULL;
  250. } else {
  251. (void)memset(mp_mem, 0, size);
  252. }
  253. flags |= osRtxFlagSystemMemory;
  254. }
  255. if (mp != NULL) {
  256. // Initialize control block
  257. mp->id = osRtxIdMemoryPool;
  258. mp->flags = flags;
  259. mp->name = name;
  260. mp->thread_list = NULL;
  261. (void)osRtxMemoryPoolInit(&mp->mp_info, b_count, b_size, mp_mem);
  262. // Register post ISR processing function
  263. osRtxInfo.post_process.memory_pool = osRtxMemoryPoolPostProcess;
  264. EvrRtxMemoryPoolCreated(mp, mp->name);
  265. } else {
  266. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorNoMemory);
  267. }
  268. return mp;
  269. }
  270. /// Get name of a Memory Pool object.
  271. /// \note API identical to osMemoryPoolGetName
  272. static const char *svcRtxMemoryPoolGetName (osMemoryPoolId_t mp_id) {
  273. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  274. // Check parameters
  275. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  276. EvrRtxMemoryPoolGetName(mp, NULL);
  277. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  278. return NULL;
  279. }
  280. EvrRtxMemoryPoolGetName(mp, mp->name);
  281. return mp->name;
  282. }
  283. /// Allocate a memory block from a Memory Pool.
  284. /// \note API identical to osMemoryPoolAlloc
  285. static void *svcRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  286. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  287. void *block;
  288. // Check parameters
  289. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  290. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  291. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  292. return NULL;
  293. }
  294. // Allocate memory
  295. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  296. if (block != NULL) {
  297. EvrRtxMemoryPoolAllocated(mp, block);
  298. } else {
  299. // No memory available
  300. if (timeout != 0U) {
  301. EvrRtxMemoryPoolAllocPending(mp, timeout);
  302. // Suspend current Thread
  303. if (osRtxThreadWaitEnter(osRtxThreadWaitingMemoryPool, timeout)) {
  304. osRtxThreadListPut(osRtxObject(mp), osRtxThreadGetRunning());
  305. } else {
  306. EvrRtxMemoryPoolAllocTimeout(mp);
  307. }
  308. } else {
  309. EvrRtxMemoryPoolAllocFailed(mp);
  310. }
  311. }
  312. return block;
  313. }
  314. /// Return an allocated memory block back to a Memory Pool.
  315. /// \note API identical to osMemoryPoolFree
  316. static osStatus_t svcRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  317. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  318. void *block0;
  319. os_thread_t *thread;
  320. osStatus_t status;
  321. // Check parameters
  322. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  323. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  324. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  325. return osErrorParameter;
  326. }
  327. // Free memory
  328. status = osRtxMemoryPoolFree(&mp->mp_info, block);
  329. if (status == osOK) {
  330. EvrRtxMemoryPoolDeallocated(mp, block);
  331. // Check if Thread is waiting to allocate memory
  332. if (mp->thread_list != NULL) {
  333. // Allocate memory
  334. block0 = osRtxMemoryPoolAlloc(&mp->mp_info);
  335. if (block0 != NULL) {
  336. // Wakeup waiting Thread with highest Priority
  337. thread = osRtxThreadListGet(osRtxObject(mp));
  338. //lint -e{923} "cast from pointer to unsigned int"
  339. osRtxThreadWaitExit(thread, (uint32_t)block0, TRUE);
  340. EvrRtxMemoryPoolAllocated(mp, block0);
  341. }
  342. }
  343. } else {
  344. EvrRtxMemoryPoolFreeFailed(mp, block);
  345. }
  346. return status;
  347. }
  348. /// Get maximum number of memory blocks in a Memory Pool.
  349. /// \note API identical to osMemoryPoolGetCapacity
  350. static uint32_t svcRtxMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
  351. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  352. // Check parameters
  353. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  354. EvrRtxMemoryPoolGetCapacity(mp, 0U);
  355. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  356. return 0U;
  357. }
  358. EvrRtxMemoryPoolGetCapacity(mp, mp->mp_info.max_blocks);
  359. return mp->mp_info.max_blocks;
  360. }
  361. /// Get memory block size in a Memory Pool.
  362. /// \note API identical to osMemoryPoolGetBlockSize
  363. static uint32_t svcRtxMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
  364. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  365. // Check parameters
  366. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  367. EvrRtxMemoryPoolGetBlockSize(mp, 0U);
  368. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  369. return 0U;
  370. }
  371. EvrRtxMemoryPoolGetBlockSize(mp, mp->mp_info.block_size);
  372. return mp->mp_info.block_size;
  373. }
  374. /// Get number of memory blocks used in a Memory Pool.
  375. /// \note API identical to osMemoryPoolGetCount
  376. static uint32_t svcRtxMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
  377. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  378. // Check parameters
  379. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  380. EvrRtxMemoryPoolGetCount(mp, 0U);
  381. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  382. return 0U;
  383. }
  384. EvrRtxMemoryPoolGetCount(mp, mp->mp_info.used_blocks);
  385. return mp->mp_info.used_blocks;
  386. }
  387. /// Get number of memory blocks available in a Memory Pool.
  388. /// \note API identical to osMemoryPoolGetSpace
  389. static uint32_t svcRtxMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
  390. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  391. // Check parameters
  392. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  393. EvrRtxMemoryPoolGetSpace(mp, 0U);
  394. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  395. return 0U;
  396. }
  397. EvrRtxMemoryPoolGetSpace(mp, mp->mp_info.max_blocks - mp->mp_info.used_blocks);
  398. return (mp->mp_info.max_blocks - mp->mp_info.used_blocks);
  399. }
  400. /// Delete a Memory Pool object.
  401. /// \note API identical to osMemoryPoolDelete
  402. static osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id) {
  403. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  404. os_thread_t *thread;
  405. // Check parameters
  406. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  407. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  408. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  409. return osErrorParameter;
  410. }
  411. // Unblock waiting threads
  412. if (mp->thread_list != NULL) {
  413. do {
  414. thread = osRtxThreadListGet(osRtxObject(mp));
  415. osRtxThreadWaitExit(thread, 0U, FALSE);
  416. } while (mp->thread_list != NULL);
  417. osRtxThreadDispatch(NULL);
  418. }
  419. // Mark object as invalid
  420. mp->id = osRtxIdInvalid;
  421. // Free data memory
  422. if ((mp->flags & osRtxFlagSystemMemory) != 0U) {
  423. (void)osRtxMemoryFree(osRtxInfo.mem.mp_data, mp->mp_info.block_base);
  424. }
  425. // Free object memory
  426. if ((mp->flags & osRtxFlagSystemObject) != 0U) {
  427. if (osRtxInfo.mpi.memory_pool != NULL) {
  428. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
  429. } else {
  430. (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
  431. }
  432. #ifdef RTX_OBJ_MEM_USAGE
  433. osRtxMemoryPoolMemUsage.cnt_free++;
  434. #endif
  435. }
  436. EvrRtxMemoryPoolDestroyed(mp);
  437. return osOK;
  438. }
  439. // Service Calls definitions
  440. //lint ++flb "Library Begin" [MISRA Note 11]
  441. SVC0_3(MemoryPoolNew, osMemoryPoolId_t, uint32_t, uint32_t, const osMemoryPoolAttr_t *)
  442. SVC0_1(MemoryPoolGetName, const char *, osMemoryPoolId_t)
  443. SVC0_2(MemoryPoolAlloc, void *, osMemoryPoolId_t, uint32_t)
  444. SVC0_2(MemoryPoolFree, osStatus_t, osMemoryPoolId_t, void *)
  445. SVC0_1(MemoryPoolGetCapacity, uint32_t, osMemoryPoolId_t)
  446. SVC0_1(MemoryPoolGetBlockSize, uint32_t, osMemoryPoolId_t)
  447. SVC0_1(MemoryPoolGetCount, uint32_t, osMemoryPoolId_t)
  448. SVC0_1(MemoryPoolGetSpace, uint32_t, osMemoryPoolId_t)
  449. SVC0_1(MemoryPoolDelete, osStatus_t, osMemoryPoolId_t)
  450. //lint --flb "Library End"
  451. // ==== ISR Calls ====
  452. /// Allocate a memory block from a Memory Pool.
  453. /// \note API identical to osMemoryPoolAlloc
  454. __STATIC_INLINE
  455. void *isrRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  456. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  457. void *block;
  458. // Check parameters
  459. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool) || (timeout != 0U)) {
  460. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  461. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  462. return NULL;
  463. }
  464. // Allocate memory
  465. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  466. if (block == NULL) {
  467. EvrRtxMemoryPoolAllocFailed(mp);
  468. } else {
  469. EvrRtxMemoryPoolAllocated(mp, block);
  470. }
  471. return block;
  472. }
  473. /// Return an allocated memory block back to a Memory Pool.
  474. /// \note API identical to osMemoryPoolFree
  475. __STATIC_INLINE
  476. osStatus_t isrRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  477. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  478. osStatus_t status;
  479. // Check parameters
  480. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  481. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  482. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  483. return osErrorParameter;
  484. }
  485. // Free memory
  486. status = osRtxMemoryPoolFree(&mp->mp_info, block);
  487. if (status == osOK) {
  488. // Register post ISR processing
  489. osRtxPostProcess(osRtxObject(mp));
  490. EvrRtxMemoryPoolDeallocated(mp, block);
  491. } else {
  492. EvrRtxMemoryPoolFreeFailed(mp, block);
  493. }
  494. return status;
  495. }
  496. // ==== Public API ====
  497. /// Create and Initialize a Memory Pool object.
  498. osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
  499. osMemoryPoolId_t mp_id;
  500. EvrRtxMemoryPoolNew(block_count, block_size, attr);
  501. if (IsException() || IsIrqMasked()) {
  502. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorISR);
  503. mp_id = NULL;
  504. } else {
  505. mp_id = __svcMemoryPoolNew(block_count, block_size, attr);
  506. }
  507. return mp_id;
  508. }
  509. /// Get name of a Memory Pool object.
  510. const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
  511. const char *name;
  512. if (IsException() || IsIrqMasked()) {
  513. EvrRtxMemoryPoolGetName(mp_id, NULL);
  514. name = NULL;
  515. } else {
  516. name = __svcMemoryPoolGetName(mp_id);
  517. }
  518. return name;
  519. }
  520. /// Allocate a memory block from a Memory Pool.
  521. void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  522. void *memory;
  523. EvrRtxMemoryPoolAlloc(mp_id, timeout);
  524. if (IsException() || IsIrqMasked()) {
  525. memory = isrRtxMemoryPoolAlloc(mp_id, timeout);
  526. } else {
  527. memory = __svcMemoryPoolAlloc(mp_id, timeout);
  528. }
  529. return memory;
  530. }
  531. /// Return an allocated memory block back to a Memory Pool.
  532. osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  533. osStatus_t status;
  534. EvrRtxMemoryPoolFree(mp_id, block);
  535. if (IsException() || IsIrqMasked()) {
  536. status = isrRtxMemoryPoolFree(mp_id, block);
  537. } else {
  538. status = __svcMemoryPoolFree(mp_id, block);
  539. }
  540. return status;
  541. }
  542. /// Get maximum number of memory blocks in a Memory Pool.
  543. uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
  544. uint32_t capacity;
  545. if (IsException() || IsIrqMasked()) {
  546. capacity = svcRtxMemoryPoolGetCapacity(mp_id);
  547. } else {
  548. capacity = __svcMemoryPoolGetCapacity(mp_id);
  549. }
  550. return capacity;
  551. }
  552. /// Get memory block size in a Memory Pool.
  553. uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
  554. uint32_t block_size;
  555. if (IsException() || IsIrqMasked()) {
  556. block_size = svcRtxMemoryPoolGetBlockSize(mp_id);
  557. } else {
  558. block_size = __svcMemoryPoolGetBlockSize(mp_id);
  559. }
  560. return block_size;
  561. }
  562. /// Get number of memory blocks used in a Memory Pool.
  563. uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
  564. uint32_t count;
  565. if (IsException() || IsIrqMasked()) {
  566. count = svcRtxMemoryPoolGetCount(mp_id);
  567. } else {
  568. count = __svcMemoryPoolGetCount(mp_id);
  569. }
  570. return count;
  571. }
  572. /// Get number of memory blocks available in a Memory Pool.
  573. uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
  574. uint32_t space;
  575. if (IsException() || IsIrqMasked()) {
  576. space = svcRtxMemoryPoolGetSpace(mp_id);
  577. } else {
  578. space = __svcMemoryPoolGetSpace(mp_id);
  579. }
  580. return space;
  581. }
  582. /// Delete a Memory Pool object.
  583. osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
  584. osStatus_t status;
  585. EvrRtxMemoryPoolDelete(mp_id);
  586. if (IsException() || IsIrqMasked()) {
  587. EvrRtxMemoryPoolError(mp_id, (int32_t)osErrorISR);
  588. status = osErrorISR;
  589. } else {
  590. status = __svcMemoryPoolDelete(mp_id);
  591. }
  592. return status;
  593. }