rtx_mempool.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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. if (mp_info->used_blocks < mp_info->max_blocks) {
  82. mp_info->used_blocks++;
  83. block = mp_info->block_free;
  84. if (block != NULL) {
  85. //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
  86. mp_info->block_free = *((void **)block);
  87. }
  88. } else {
  89. block = NULL;
  90. }
  91. if (primask == 0U) {
  92. __enable_irq();
  93. }
  94. #else
  95. if (atomic_inc32_lt(&mp_info->used_blocks, mp_info->max_blocks) < mp_info->max_blocks) {
  96. block = atomic_link_get(&mp_info->block_free);
  97. } else {
  98. block = NULL;
  99. }
  100. #endif
  101. EvrRtxMemoryBlockAlloc(mp_info, block);
  102. return block;
  103. }
  104. /// Return an allocated memory block back to a Memory Pool.
  105. /// \param[in] mp_info memory pool info.
  106. /// \param[in] block address of the allocated memory block to be returned to the memory pool.
  107. /// \return status code that indicates the execution status of the function.
  108. osStatus_t osRtxMemoryPoolFree (os_mp_info_t *mp_info, void *block) {
  109. #if (EXCLUSIVE_ACCESS == 0)
  110. uint32_t primask = __get_PRIMASK();
  111. #endif
  112. osStatus_t status;
  113. //lint -e{946} "Relational operator applied to pointers"
  114. if ((mp_info == NULL) || (block < mp_info->block_base) || (block >= mp_info->block_lim)) {
  115. EvrRtxMemoryBlockFree(mp_info, block, (int32_t)osErrorParameter);
  116. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  117. return osErrorParameter;
  118. }
  119. #if (EXCLUSIVE_ACCESS == 0)
  120. __disable_irq();
  121. if (mp_info->used_blocks != 0U) {
  122. mp_info->used_blocks--;
  123. //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
  124. *((void **)block) = mp_info->block_free;
  125. mp_info->block_free = block;
  126. status = osOK;
  127. } else {
  128. status = osErrorResource;
  129. }
  130. if (primask == 0U) {
  131. __enable_irq();
  132. }
  133. #else
  134. if (atomic_dec32_nz(&mp_info->used_blocks) != 0U) {
  135. atomic_link_put(&mp_info->block_free, block);
  136. status = osOK;
  137. } else {
  138. status = osErrorResource;
  139. }
  140. #endif
  141. EvrRtxMemoryBlockFree(mp_info, block, (int32_t)status);
  142. return status;
  143. }
  144. // ==== Post ISR processing ====
  145. /// Memory Pool post ISR processing.
  146. /// \param[in] mp memory pool object.
  147. static void osRtxMemoryPoolPostProcess (os_memory_pool_t *mp) {
  148. void *block;
  149. os_thread_t *thread;
  150. if (mp->state == osRtxObjectInactive) {
  151. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  152. return;
  153. }
  154. // Check if Thread is waiting to allocate memory
  155. if (mp->thread_list != NULL) {
  156. // Allocate memory
  157. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  158. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  159. if (block != NULL) {
  160. // Wakeup waiting Thread with highest Priority
  161. thread = osRtxThreadListGet(osRtxObject(mp));
  162. //lint -e{923} "cast from pointer to unsigned int"
  163. osRtxThreadWaitExit(thread, (uint32_t)block, FALSE);
  164. EvrRtxMemoryPoolAllocated(mp, block);
  165. }
  166. }
  167. }
  168. // ==== Service Calls ====
  169. /// Create and Initialize a Memory Pool object.
  170. /// \note API identical to osMemoryPoolNew
  171. static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
  172. os_memory_pool_t *mp;
  173. void *mp_mem;
  174. uint32_t mp_size;
  175. uint32_t b_count;
  176. uint32_t b_size;
  177. uint32_t size;
  178. uint8_t flags;
  179. const char *name;
  180. // Check parameters
  181. if ((block_count == 0U) || (block_size == 0U)) {
  182. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
  183. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  184. return NULL;
  185. }
  186. b_count = block_count;
  187. b_size = (block_size + 3U) & ~3UL;
  188. if ((__CLZ(b_count) + __CLZ(b_size)) < 32U) {
  189. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
  190. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  191. return NULL;
  192. }
  193. size = b_count * b_size;
  194. // Process attributes
  195. if (attr != NULL) {
  196. name = attr->name;
  197. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  198. mp = attr->cb_mem;
  199. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  200. mp_mem = attr->mp_mem;
  201. mp_size = attr->mp_size;
  202. if (mp != NULL) {
  203. //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
  204. if ((((uint32_t)mp & 3U) != 0U) || (attr->cb_size < sizeof(os_memory_pool_t))) {
  205. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
  206. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  207. return NULL;
  208. }
  209. } else {
  210. if (attr->cb_size != 0U) {
  211. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
  212. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  213. return NULL;
  214. }
  215. }
  216. if (mp_mem != NULL) {
  217. //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
  218. if ((((uint32_t)mp_mem & 3U) != 0U) || (mp_size < size)) {
  219. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
  220. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  221. return NULL;
  222. }
  223. } else {
  224. if (mp_size != 0U) {
  225. EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
  226. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  227. return NULL;
  228. }
  229. }
  230. } else {
  231. name = NULL;
  232. mp = NULL;
  233. mp_mem = NULL;
  234. }
  235. // Allocate object memory if not provided
  236. if (mp == NULL) {
  237. if (osRtxInfo.mpi.memory_pool != NULL) {
  238. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  239. mp = osRtxMemoryPoolAlloc(osRtxInfo.mpi.memory_pool);
  240. } else {
  241. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  242. mp = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_memory_pool_t), 1U);
  243. }
  244. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  245. if (mp != NULL) {
  246. uint32_t used;
  247. osRtxMemoryPoolMemUsage.cnt_alloc++;
  248. used = osRtxMemoryPoolMemUsage.cnt_alloc - osRtxMemoryPoolMemUsage.cnt_free;
  249. if (osRtxMemoryPoolMemUsage.max_used < used) {
  250. osRtxMemoryPoolMemUsage.max_used = used;
  251. }
  252. }
  253. #endif
  254. flags = osRtxFlagSystemObject;
  255. } else {
  256. flags = 0U;
  257. }
  258. // Allocate data memory if not provided
  259. if ((mp != NULL) && (mp_mem == NULL)) {
  260. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  261. mp_mem = osRtxMemoryAlloc(osRtxInfo.mem.mp_data, size, 0U);
  262. if (mp_mem == NULL) {
  263. if ((flags & osRtxFlagSystemObject) != 0U) {
  264. if (osRtxInfo.mpi.memory_pool != NULL) {
  265. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
  266. } else {
  267. (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
  268. }
  269. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  270. osRtxMemoryPoolMemUsage.cnt_free++;
  271. #endif
  272. }
  273. mp = NULL;
  274. } else {
  275. memset(mp_mem, 0, size);
  276. }
  277. flags |= osRtxFlagSystemMemory;
  278. }
  279. if (mp != NULL) {
  280. // Initialize control block
  281. mp->id = osRtxIdMemoryPool;
  282. mp->state = osRtxObjectActive;
  283. mp->flags = flags;
  284. mp->name = name;
  285. mp->thread_list = NULL;
  286. (void)osRtxMemoryPoolInit(&mp->mp_info, b_count, b_size, mp_mem);
  287. // Register post ISR processing function
  288. osRtxInfo.post_process.memory_pool = osRtxMemoryPoolPostProcess;
  289. EvrRtxMemoryPoolCreated(mp, mp->name);
  290. } else {
  291. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorNoMemory);
  292. }
  293. return mp;
  294. }
  295. /// Get name of a Memory Pool object.
  296. /// \note API identical to osMemoryPoolGetName
  297. static const char *svcRtxMemoryPoolGetName (osMemoryPoolId_t mp_id) {
  298. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  299. // Check parameters
  300. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  301. EvrRtxMemoryPoolGetName(mp, NULL);
  302. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  303. return NULL;
  304. }
  305. // Check object state
  306. if (mp->state == osRtxObjectInactive) {
  307. EvrRtxMemoryPoolGetName(mp, NULL);
  308. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  309. return NULL;
  310. }
  311. EvrRtxMemoryPoolGetName(mp, mp->name);
  312. return mp->name;
  313. }
  314. /// Allocate a memory block from a Memory Pool.
  315. /// \note API identical to osMemoryPoolAlloc
  316. static void *svcRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  317. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  318. void *block;
  319. // Check parameters
  320. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  321. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  322. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  323. return NULL;
  324. }
  325. // Check object state
  326. if (mp->state == osRtxObjectInactive) {
  327. EvrRtxMemoryPoolError(mp, (int32_t)osErrorResource);
  328. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  329. return NULL;
  330. }
  331. // Allocate memory
  332. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  333. if (block != NULL) {
  334. EvrRtxMemoryPoolAllocated(mp, block);
  335. } else {
  336. // No memory available
  337. if (timeout != 0U) {
  338. EvrRtxMemoryPoolAllocPending(mp, timeout);
  339. // Suspend current Thread
  340. if (osRtxThreadWaitEnter(osRtxThreadWaitingMemoryPool, timeout)) {
  341. osRtxThreadListPut(osRtxObject(mp), osRtxThreadGetRunning());
  342. } else {
  343. EvrRtxMemoryPoolAllocTimeout(mp);
  344. }
  345. } else {
  346. EvrRtxMemoryPoolAllocFailed(mp);
  347. }
  348. }
  349. return block;
  350. }
  351. /// Return an allocated memory block back to a Memory Pool.
  352. /// \note API identical to osMemoryPoolFree
  353. static osStatus_t svcRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  354. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  355. void *block0;
  356. os_thread_t *thread;
  357. osStatus_t status;
  358. // Check parameters
  359. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  360. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  361. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  362. return osErrorParameter;
  363. }
  364. // Check object state
  365. if (mp->state == osRtxObjectInactive) {
  366. EvrRtxMemoryPoolError(mp, (int32_t)osErrorResource);
  367. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  368. return osErrorResource;
  369. }
  370. // Free memory
  371. status = osRtxMemoryPoolFree(&mp->mp_info, block);
  372. if (status == osOK) {
  373. EvrRtxMemoryPoolDeallocated(mp, block);
  374. // Check if Thread is waiting to allocate memory
  375. if (mp->thread_list != NULL) {
  376. // Allocate memory
  377. block0 = osRtxMemoryPoolAlloc(&mp->mp_info);
  378. if (block0 != NULL) {
  379. // Wakeup waiting Thread with highest Priority
  380. thread = osRtxThreadListGet(osRtxObject(mp));
  381. //lint -e{923} "cast from pointer to unsigned int"
  382. osRtxThreadWaitExit(thread, (uint32_t)block0, TRUE);
  383. EvrRtxMemoryPoolAllocated(mp, block0);
  384. }
  385. }
  386. } else {
  387. EvrRtxMemoryPoolFreeFailed(mp, block);
  388. }
  389. return status;
  390. }
  391. /// Get maximum number of memory blocks in a Memory Pool.
  392. /// \note API identical to osMemoryPoolGetCapacity
  393. static uint32_t svcRtxMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
  394. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  395. // Check parameters
  396. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  397. EvrRtxMemoryPoolGetCapacity(mp, 0U);
  398. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  399. return 0U;
  400. }
  401. // Check object state
  402. if (mp->state == osRtxObjectInactive) {
  403. EvrRtxMemoryPoolGetCapacity(mp, 0U);
  404. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  405. return 0U;
  406. }
  407. EvrRtxMemoryPoolGetCapacity(mp, mp->mp_info.max_blocks);
  408. return mp->mp_info.max_blocks;
  409. }
  410. /// Get memory block size in a Memory Pool.
  411. /// \note API identical to osMemoryPoolGetBlockSize
  412. static uint32_t svcRtxMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
  413. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  414. // Check parameters
  415. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  416. EvrRtxMemoryPoolGetBlockSize(mp, 0U);
  417. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  418. return 0U;
  419. }
  420. // Check object state
  421. if (mp->state == osRtxObjectInactive) {
  422. EvrRtxMemoryPoolGetBlockSize(mp, 0U);
  423. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  424. return 0U;
  425. }
  426. EvrRtxMemoryPoolGetBlockSize(mp, mp->mp_info.block_size);
  427. return mp->mp_info.block_size;
  428. }
  429. /// Get number of memory blocks used in a Memory Pool.
  430. /// \note API identical to osMemoryPoolGetCount
  431. static uint32_t svcRtxMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
  432. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  433. // Check parameters
  434. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  435. EvrRtxMemoryPoolGetCount(mp, 0U);
  436. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  437. return 0U;
  438. }
  439. // Check object state
  440. if (mp->state == osRtxObjectInactive) {
  441. EvrRtxMemoryPoolGetCount(mp, 0U);
  442. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  443. return 0U;
  444. }
  445. EvrRtxMemoryPoolGetCount(mp, mp->mp_info.used_blocks);
  446. return mp->mp_info.used_blocks;
  447. }
  448. /// Get number of memory blocks available in a Memory Pool.
  449. /// \note API identical to osMemoryPoolGetSpace
  450. static uint32_t svcRtxMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
  451. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  452. // Check parameters
  453. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  454. EvrRtxMemoryPoolGetSpace(mp, 0U);
  455. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  456. return 0U;
  457. }
  458. // Check object state
  459. if (mp->state == osRtxObjectInactive) {
  460. EvrRtxMemoryPoolGetSpace(mp, 0U);
  461. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  462. return 0U;
  463. }
  464. EvrRtxMemoryPoolGetSpace(mp, mp->mp_info.max_blocks - mp->mp_info.used_blocks);
  465. return (mp->mp_info.max_blocks - mp->mp_info.used_blocks);
  466. }
  467. /// Delete a Memory Pool object.
  468. /// \note API identical to osMemoryPoolDelete
  469. static osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id) {
  470. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  471. os_thread_t *thread;
  472. // Check parameters
  473. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  474. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  475. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  476. return osErrorParameter;
  477. }
  478. // Check object state
  479. if (mp->state == osRtxObjectInactive) {
  480. EvrRtxMemoryPoolError(mp, (int32_t)osErrorResource);
  481. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  482. return osErrorResource;
  483. }
  484. // Mark object as inactive
  485. mp->state = osRtxObjectInactive;
  486. // Unblock waiting threads
  487. if (mp->thread_list != NULL) {
  488. do {
  489. thread = osRtxThreadListGet(osRtxObject(mp));
  490. osRtxThreadWaitExit(thread, 0U, FALSE);
  491. } while (mp->thread_list != NULL);
  492. osRtxThreadDispatch(NULL);
  493. }
  494. // Free data memory
  495. if ((mp->flags & osRtxFlagSystemMemory) != 0U) {
  496. (void)osRtxMemoryFree(osRtxInfo.mem.mp_data, mp->mp_info.block_base);
  497. }
  498. // Free object memory
  499. if ((mp->flags & osRtxFlagSystemObject) != 0U) {
  500. if (osRtxInfo.mpi.memory_pool != NULL) {
  501. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
  502. } else {
  503. (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
  504. }
  505. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  506. osRtxMemoryPoolMemUsage.cnt_free++;
  507. #endif
  508. }
  509. EvrRtxMemoryPoolDestroyed(mp);
  510. return osOK;
  511. }
  512. // Service Calls definitions
  513. //lint ++flb "Library Begin" [MISRA Note 11]
  514. SVC0_3(MemoryPoolNew, osMemoryPoolId_t, uint32_t, uint32_t, const osMemoryPoolAttr_t *)
  515. SVC0_1(MemoryPoolGetName, const char *, osMemoryPoolId_t)
  516. SVC0_2(MemoryPoolAlloc, void *, osMemoryPoolId_t, uint32_t)
  517. SVC0_2(MemoryPoolFree, osStatus_t, osMemoryPoolId_t, void *)
  518. SVC0_1(MemoryPoolGetCapacity, uint32_t, osMemoryPoolId_t)
  519. SVC0_1(MemoryPoolGetBlockSize, uint32_t, osMemoryPoolId_t)
  520. SVC0_1(MemoryPoolGetCount, uint32_t, osMemoryPoolId_t)
  521. SVC0_1(MemoryPoolGetSpace, uint32_t, osMemoryPoolId_t)
  522. SVC0_1(MemoryPoolDelete, osStatus_t, osMemoryPoolId_t)
  523. //lint --flb "Library End"
  524. // ==== ISR Calls ====
  525. /// Allocate a memory block from a Memory Pool.
  526. /// \note API identical to osMemoryPoolAlloc
  527. __STATIC_INLINE
  528. void *isrRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  529. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  530. void *block;
  531. // Check parameters
  532. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool) || (timeout != 0U)) {
  533. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  534. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  535. return NULL;
  536. }
  537. // Check object state
  538. if (mp->state == osRtxObjectInactive) {
  539. EvrRtxMemoryPoolError(mp, (int32_t)osErrorResource);
  540. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  541. return NULL;
  542. }
  543. // Allocate memory
  544. block = osRtxMemoryPoolAlloc(&mp->mp_info);
  545. if (block == NULL) {
  546. EvrRtxMemoryPoolAllocFailed(mp);
  547. } else {
  548. EvrRtxMemoryPoolAllocated(mp, block);
  549. }
  550. return block;
  551. }
  552. /// Return an allocated memory block back to a Memory Pool.
  553. /// \note API identical to osMemoryPoolFree
  554. __STATIC_INLINE
  555. osStatus_t isrRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  556. os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
  557. osStatus_t status;
  558. // Check parameters
  559. if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
  560. EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
  561. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  562. return osErrorParameter;
  563. }
  564. // Check object state
  565. if (mp->state == osRtxObjectInactive) {
  566. EvrRtxMemoryPoolError(mp, (int32_t)osErrorResource);
  567. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  568. return osErrorResource;
  569. }
  570. // Free memory
  571. status = osRtxMemoryPoolFree(&mp->mp_info, block);
  572. if (status == osOK) {
  573. // Register post ISR processing
  574. osRtxPostProcess(osRtxObject(mp));
  575. EvrRtxMemoryPoolDeallocated(mp, block);
  576. } else {
  577. EvrRtxMemoryPoolFreeFailed(mp, block);
  578. }
  579. return status;
  580. }
  581. // ==== Public API ====
  582. /// Create and Initialize a Memory Pool object.
  583. osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
  584. osMemoryPoolId_t mp_id;
  585. EvrRtxMemoryPoolNew(block_count, block_size, attr);
  586. if (IsIrqMode() || IsIrqMasked()) {
  587. EvrRtxMemoryPoolError(NULL, (int32_t)osErrorISR);
  588. mp_id = NULL;
  589. } else {
  590. mp_id = __svcMemoryPoolNew(block_count, block_size, attr);
  591. }
  592. return mp_id;
  593. }
  594. /// Get name of a Memory Pool object.
  595. const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
  596. const char *name;
  597. if (IsIrqMode() || IsIrqMasked()) {
  598. EvrRtxMemoryPoolGetName(mp_id, NULL);
  599. name = NULL;
  600. } else {
  601. name = __svcMemoryPoolGetName(mp_id);
  602. }
  603. return name;
  604. }
  605. /// Allocate a memory block from a Memory Pool.
  606. void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
  607. void *memory;
  608. EvrRtxMemoryPoolAlloc(mp_id, timeout);
  609. if (IsIrqMode() || IsIrqMasked()) {
  610. memory = isrRtxMemoryPoolAlloc(mp_id, timeout);
  611. } else {
  612. memory = __svcMemoryPoolAlloc(mp_id, timeout);
  613. }
  614. return memory;
  615. }
  616. /// Return an allocated memory block back to a Memory Pool.
  617. osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
  618. osStatus_t status;
  619. EvrRtxMemoryPoolFree(mp_id, block);
  620. if (IsIrqMode() || IsIrqMasked()) {
  621. status = isrRtxMemoryPoolFree(mp_id, block);
  622. } else {
  623. status = __svcMemoryPoolFree(mp_id, block);
  624. }
  625. return status;
  626. }
  627. /// Get maximum number of memory blocks in a Memory Pool.
  628. uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
  629. uint32_t capacity;
  630. if (IsIrqMode() || IsIrqMasked()) {
  631. capacity = svcRtxMemoryPoolGetCapacity(mp_id);
  632. } else {
  633. capacity = __svcMemoryPoolGetCapacity(mp_id);
  634. }
  635. return capacity;
  636. }
  637. /// Get memory block size in a Memory Pool.
  638. uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
  639. uint32_t block_size;
  640. if (IsIrqMode() || IsIrqMasked()) {
  641. block_size = svcRtxMemoryPoolGetBlockSize(mp_id);
  642. } else {
  643. block_size = __svcMemoryPoolGetBlockSize(mp_id);
  644. }
  645. return block_size;
  646. }
  647. /// Get number of memory blocks used in a Memory Pool.
  648. uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
  649. uint32_t count;
  650. if (IsIrqMode() || IsIrqMasked()) {
  651. count = svcRtxMemoryPoolGetCount(mp_id);
  652. } else {
  653. count = __svcMemoryPoolGetCount(mp_id);
  654. }
  655. return count;
  656. }
  657. /// Get number of memory blocks available in a Memory Pool.
  658. uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
  659. uint32_t space;
  660. if (IsIrqMode() || IsIrqMasked()) {
  661. space = svcRtxMemoryPoolGetSpace(mp_id);
  662. } else {
  663. space = __svcMemoryPoolGetSpace(mp_id);
  664. }
  665. return space;
  666. }
  667. /// Delete a Memory Pool object.
  668. osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
  669. osStatus_t status;
  670. EvrRtxMemoryPoolDelete(mp_id);
  671. if (IsIrqMode() || IsIrqMasked()) {
  672. EvrRtxMemoryPoolError(mp_id, (int32_t)osErrorISR);
  673. status = osErrorISR;
  674. } else {
  675. status = __svcMemoryPoolDelete(mp_id);
  676. }
  677. return status;
  678. }