rtx_mempool.c 26 KB

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