rtx_mempool.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. /*
  2. * Copyright (c) 2013-2018 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. #if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)))
  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. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
  163. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  164. return NULL;
  165. }
  166. b_count = block_count;
  167. b_size = (block_size + 3U) & ~3UL;
  168. if ((__CLZ(b_count) + __CLZ(b_size)) < 32U) {
  169. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
  170. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  171. return NULL;
  172. }
  173. size = b_count * b_size;
  174. // Process attributes
  175. if (attr != NULL) {
  176. name = attr->name;
  177. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  178. mp = attr->cb_mem;
  179. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  180. mp_mem = attr->mp_mem;
  181. mp_size = attr->mp_size;
  182. if (mp != NULL) {
  183. //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
  184. if ((((uint32_t)mp & 3U) != 0U) || (attr->cb_size < sizeof(os_memory_pool_t))) {
  185. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
  186. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  187. return NULL;
  188. }
  189. } else {
  190. if (attr->cb_size != 0U) {
  191. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
  192. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  193. return NULL;
  194. }
  195. }
  196. if (mp_mem != NULL) {
  197. //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
  198. if ((((uint32_t)mp_mem & 3U) != 0U) || (mp_size < size)) {
  199. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
  200. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  201. return NULL;
  202. }
  203. } else {
  204. if (mp_size != 0U) {
  205. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
  206. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  207. return NULL;
  208. }
  209. }
  210. } else {
  211. name = NULL;
  212. mp = NULL;
  213. mp_mem = NULL;
  214. }
  215. // Allocate object memory if not provided
  216. if (mp == NULL) {
  217. if (osRtxInfo.mpi.memory_pool != NULL) {
  218. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  219. mp = osRtxMemoryPoolAlloc(osRtxInfo.mpi.memory_pool);
  220. } else {
  221. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  222. mp = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_memory_pool_t), 1U);
  223. }
  224. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  225. if (mp != NULL) {
  226. uint32_t used;
  227. osRtxMemoryPoolMemUsage.cnt_alloc++;
  228. used = osRtxMemoryPoolMemUsage.cnt_alloc - osRtxMemoryPoolMemUsage.cnt_free;
  229. if (osRtxMemoryPoolMemUsage.max_used < used) {
  230. osRtxMemoryPoolMemUsage.max_used = used;
  231. }
  232. }
  233. #endif
  234. flags = osRtxFlagSystemObject;
  235. } else {
  236. flags = 0U;
  237. }
  238. // Allocate data memory if not provided
  239. if ((mp != NULL) && (mp_mem == NULL)) {
  240. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  241. mp_mem = osRtxMemoryAlloc(osRtxInfo.mem.mp_data, size, 0U);
  242. if (mp_mem == NULL) {
  243. if ((flags & osRtxFlagSystemObject) != 0U) {
  244. if (osRtxInfo.mpi.memory_pool != NULL) {
  245. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
  246. } else {
  247. (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
  248. }
  249. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  250. osRtxMemoryPoolMemUsage.cnt_free++;
  251. #endif
  252. }
  253. mp = NULL;
  254. } else {
  255. memset(mp_mem, 0, size);
  256. }
  257. flags |= osRtxFlagSystemMemory;
  258. }
  259. if (mp != NULL) {
  260. // Initialize control block
  261. mp->id = osRtxIdMemoryPool;
  262. mp->flags = flags;
  263. mp->name = name;
  264. mp->thread_list = NULL;
  265. (void)osRtxMemoryPoolInit(&mp->mp_info, b_count, b_size, mp_mem);
  266. // Register post ISR processing function
  267. osRtxInfo.post_process.memory_pool = osRtxMemoryPoolPostProcess;
  268. EvrRtxMemoryPoolCreated(mp, mp->name);
  269. } else {
  270. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorNoMemory);
  271. }
  272. return mp;
  273. }
  274. /// Get name of a Memory Pool object.
  275. /// \note API identical to osMemoryPoolGetName
  276. static const char *svcRtxMemoryPoolGetName (osMemoryPoolId_t mp_id) {
  277. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  278. // Check parameters
  279. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  280. EvrRtxMemoryPoolGetName(mp, NULL);
  281. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  282. return NULL;
  283. }
  284. EvrRtxMemoryPoolGetName(mp, mp->name);
  285. return mp->name;
  286. }
  287. /// Allocate a memory block from a Memory Pool.
  288. /// \note API identical to osMemoryPoolAlloc
  289. static void *svcRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  290. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  291. void *block;
  292. // Check parameters
  293. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  294. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  295. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  296. return NULL;
  297. }
  298. // Allocate memory
  299. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  300. if (block != NULL) {
  301. EvrRtxMemoryPoolAllocated(mp, block);
  302. } else {
  303. // No memory available
  304. if (timeout != 0U) {
  305. EvrRtxMemoryPoolAllocPending(mp, timeout);
  306. // Suspend current Thread
  307. if (osRtxThreadWaitEnter(osRtxThreadWaitingMemoryPool, timeout)) {
  308. osRtxThreadListPut(osRtxObject(mp), osRtxThreadGetRunning());
  309. } else {
  310. EvrRtxMemoryPoolAllocTimeout(mp);
  311. }
  312. } else {
  313. EvrRtxMemoryPoolAllocFailed(mp);
  314. }
  315. }
  316. return block;
  317. }
  318. /// Return an allocated memory block back to a Memory Pool.
  319. /// \note API identical to osMemoryPoolFree
  320. static osStatus_t svcRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  321. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  322. void *block0;
  323. os_thread_t *thread;
  324. osStatus_t status;
  325. // Check parameters
  326. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  327. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  328. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  329. return osErrorParameter;
  330. }
  331. // Free memory
  332. status = osRtxMemoryPoolFree(&mp->mp_info, block);
  333. if (status == osOK) {
  334. EvrRtxMemoryPoolDeallocated(mp, block);
  335. // Check if Thread is waiting to allocate memory
  336. if (mp->thread_list != NULL) {
  337. // Allocate memory
  338. block0 = osRtxMemoryPoolAlloc(&mp->mp_info);
  339. if (block0 != NULL) {
  340. // Wakeup waiting Thread with highest Priority
  341. thread = osRtxThreadListGet(osRtxObject(mp));
  342. //lint -e{923} "cast from pointer to unsigned int"
  343. osRtxThreadWaitExit(thread, (uint32_t)block0, TRUE);
  344. EvrRtxMemoryPoolAllocated(mp, block0);
  345. }
  346. }
  347. } else {
  348. EvrRtxMemoryPoolFreeFailed(mp, block);
  349. }
  350. return status;
  351. }
  352. /// Get maximum number of memory blocks in a Memory Pool.
  353. /// \note API identical to osMemoryPoolGetCapacity
  354. static uint32_t svcRtxMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
  355. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  356. // Check parameters
  357. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  358. EvrRtxMemoryPoolGetCapacity(mp, 0U);
  359. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  360. return 0U;
  361. }
  362. EvrRtxMemoryPoolGetCapacity(mp, mp->mp_info.max_blocks);
  363. return mp->mp_info.max_blocks;
  364. }
  365. /// Get memory block size in a Memory Pool.
  366. /// \note API identical to osMemoryPoolGetBlockSize
  367. static uint32_t svcRtxMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
  368. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  369. // Check parameters
  370. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  371. EvrRtxMemoryPoolGetBlockSize(mp, 0U);
  372. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  373. return 0U;
  374. }
  375. EvrRtxMemoryPoolGetBlockSize(mp, mp->mp_info.block_size);
  376. return mp->mp_info.block_size;
  377. }
  378. /// Get number of memory blocks used in a Memory Pool.
  379. /// \note API identical to osMemoryPoolGetCount
  380. static uint32_t svcRtxMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
  381. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  382. // Check parameters
  383. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  384. EvrRtxMemoryPoolGetCount(mp, 0U);
  385. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  386. return 0U;
  387. }
  388. EvrRtxMemoryPoolGetCount(mp, mp->mp_info.used_blocks);
  389. return mp->mp_info.used_blocks;
  390. }
  391. /// Get number of memory blocks available in a Memory Pool.
  392. /// \note API identical to osMemoryPoolGetSpace
  393. static uint32_t svcRtxMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
  394. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  395. // Check parameters
  396. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  397. EvrRtxMemoryPoolGetSpace(mp, 0U);
  398. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  399. return 0U;
  400. }
  401. EvrRtxMemoryPoolGetSpace(mp, mp->mp_info.max_blocks - mp->mp_info.used_blocks);
  402. return (mp->mp_info.max_blocks - mp->mp_info.used_blocks);
  403. }
  404. /// Delete a Memory Pool object.
  405. /// \note API identical to osMemoryPoolDelete
  406. static osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id) {
  407. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  408. os_thread_t *thread;
  409. // Check parameters
  410. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  411. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  412. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  413. return osErrorParameter;
  414. }
  415. // Unblock waiting threads
  416. if (mp->thread_list != NULL) {
  417. do {
  418. thread = osRtxThreadListGet(osRtxObject(mp));
  419. osRtxThreadWaitExit(thread, 0U, FALSE);
  420. } while (mp->thread_list != NULL);
  421. osRtxThreadDispatch(NULL);
  422. }
  423. // Mark object as invalid
  424. mp->id = osRtxIdInvalid;
  425. // Free data memory
  426. if ((mp->flags & osRtxFlagSystemMemory) != 0U) {
  427. (void)osRtxMemoryFree(osRtxInfo.mem.mp_data, mp->mp_info.block_base);
  428. }
  429. // Free object memory
  430. if ((mp->flags & osRtxFlagSystemObject) != 0U) {
  431. if (osRtxInfo.mpi.memory_pool != NULL) {
  432. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
  433. } else {
  434. (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
  435. }
  436. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  437. osRtxMemoryPoolMemUsage.cnt_free++;
  438. #endif
  439. }
  440. EvrRtxMemoryPoolDestroyed(mp);
  441. return osOK;
  442. }
  443. // Service Calls definitions
  444. //lint ++flb "Library Begin" [MISRA Note 11]
  445. SVC0_3(MemoryPoolNew, osMemoryPoolId_t, uint32_t, uint32_t, const osMemoryPoolAttr_t *)
  446. SVC0_1(MemoryPoolGetName, const char *, osMemoryPoolId_t)
  447. SVC0_2(MemoryPoolAlloc, void *, osMemoryPoolId_t, uint32_t)
  448. SVC0_2(MemoryPoolFree, osStatus_t, osMemoryPoolId_t, void *)
  449. SVC0_1(MemoryPoolGetCapacity, uint32_t, osMemoryPoolId_t)
  450. SVC0_1(MemoryPoolGetBlockSize, uint32_t, osMemoryPoolId_t)
  451. SVC0_1(MemoryPoolGetCount, uint32_t, osMemoryPoolId_t)
  452. SVC0_1(MemoryPoolGetSpace, uint32_t, osMemoryPoolId_t)
  453. SVC0_1(MemoryPoolDelete, osStatus_t, osMemoryPoolId_t)
  454. //lint --flb "Library End"
  455. // ==== ISR Calls ====
  456. /// Allocate a memory block from a Memory Pool.
  457. /// \note API identical to osMemoryPoolAlloc
  458. __STATIC_INLINE
  459. void *isrRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  460. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  461. void *block;
  462. // Check parameters
  463. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool) || (timeout != 0U)) {
  464. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  465. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  466. return NULL;
  467. }
  468. // Allocate memory
  469. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  470. if (block == NULL) {
  471. EvrRtxMemoryPoolAllocFailed(mp);
  472. } else {
  473. EvrRtxMemoryPoolAllocated(mp, block);
  474. }
  475. return block;
  476. }
  477. /// Return an allocated memory block back to a Memory Pool.
  478. /// \note API identical to osMemoryPoolFree
  479. __STATIC_INLINE
  480. osStatus_t isrRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  481. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  482. osStatus_t status;
  483. // Check parameters
  484. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  485. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  486. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  487. return osErrorParameter;
  488. }
  489. // Free memory
  490. status = osRtxMemoryPoolFree(&mp->mp_info, block);
  491. if (status == osOK) {
  492. // Register post ISR processing
  493. osRtxPostProcess(osRtxObject(mp));
  494. EvrRtxMemoryPoolDeallocated(mp, block);
  495. } else {
  496. EvrRtxMemoryPoolFreeFailed(mp, block);
  497. }
  498. return status;
  499. }
  500. // ==== Public API ====
  501. /// Create and Initialize a Memory Pool object.
  502. osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
  503. osMemoryPoolId_t mp_id;
  504. EvrRtxMemoryPoolNew(block_count, block_size, attr);
  505. if (IsIrqMode() || IsIrqMasked()) {
  506. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorISR);
  507. mp_id = NULL;
  508. } else {
  509. mp_id = __svcMemoryPoolNew(block_count, block_size, attr);
  510. }
  511. return mp_id;
  512. }
  513. /// Get name of a Memory Pool object.
  514. const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
  515. const char *name;
  516. if (IsIrqMode() || IsIrqMasked()) {
  517. EvrRtxMemoryPoolGetName(mp_id, NULL);
  518. name = NULL;
  519. } else {
  520. name = __svcMemoryPoolGetName(mp_id);
  521. }
  522. return name;
  523. }
  524. /// Allocate a memory block from a Memory Pool.
  525. void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  526. void *memory;
  527. EvrRtxMemoryPoolAlloc(mp_id, timeout);
  528. if (IsIrqMode() || IsIrqMasked()) {
  529. memory = isrRtxMemoryPoolAlloc(mp_id, timeout);
  530. } else {
  531. memory = __svcMemoryPoolAlloc(mp_id, timeout);
  532. }
  533. return memory;
  534. }
  535. /// Return an allocated memory block back to a Memory Pool.
  536. osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  537. osStatus_t status;
  538. EvrRtxMemoryPoolFree(mp_id, block);
  539. if (IsIrqMode() || IsIrqMasked()) {
  540. status = isrRtxMemoryPoolFree(mp_id, block);
  541. } else {
  542. status = __svcMemoryPoolFree(mp_id, block);
  543. }
  544. return status;
  545. }
  546. /// Get maximum number of memory blocks in a Memory Pool.
  547. uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
  548. uint32_t capacity;
  549. if (IsIrqMode() || IsIrqMasked()) {
  550. capacity = svcRtxMemoryPoolGetCapacity(mp_id);
  551. } else {
  552. capacity = __svcMemoryPoolGetCapacity(mp_id);
  553. }
  554. return capacity;
  555. }
  556. /// Get memory block size in a Memory Pool.
  557. uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
  558. uint32_t block_size;
  559. if (IsIrqMode() || IsIrqMasked()) {
  560. block_size = svcRtxMemoryPoolGetBlockSize(mp_id);
  561. } else {
  562. block_size = __svcMemoryPoolGetBlockSize(mp_id);
  563. }
  564. return block_size;
  565. }
  566. /// Get number of memory blocks used in a Memory Pool.
  567. uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
  568. uint32_t count;
  569. if (IsIrqMode() || IsIrqMasked()) {
  570. count = svcRtxMemoryPoolGetCount(mp_id);
  571. } else {
  572. count = __svcMemoryPoolGetCount(mp_id);
  573. }
  574. return count;
  575. }
  576. /// Get number of memory blocks available in a Memory Pool.
  577. uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
  578. uint32_t space;
  579. if (IsIrqMode() || IsIrqMasked()) {
  580. space = svcRtxMemoryPoolGetSpace(mp_id);
  581. } else {
  582. space = __svcMemoryPoolGetSpace(mp_id);
  583. }
  584. return space;
  585. }
  586. /// Delete a Memory Pool object.
  587. osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
  588. osStatus_t status;
  589. EvrRtxMemoryPoolDelete(mp_id);
  590. if (IsIrqMode() || IsIrqMasked()) {
  591. EvrRtxMemoryPoolError(mp_id, (int32_t)osErrorISR);
  592. status = osErrorISR;
  593. } else {
  594. status = __svcMemoryPoolDelete(mp_id);
  595. }
  596. return status;
  597. }