queue.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * FreeRTOS Kernel V10.4.6
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. * this software and associated documentation files (the "Software"), to deal in
  9. * the Software without restriction, including without limitation the rights to
  10. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. * the Software, and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in all
  15. * copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. *
  24. * https://www.FreeRTOS.org
  25. * https://github.com/FreeRTOS
  26. *
  27. */
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include "FreeRTOS.h"
  31. #include "queue.h"
  32. /* Semaphores do not actually store or copy data, so have an item size of
  33. * zero. */
  34. #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 )
  35. #define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U )
  36. typedef struct QueueDefinition
  37. {
  38. struct rt_ipc_object *rt_ipc;
  39. } xQUEUE;
  40. typedef xQUEUE Queue_t;
  41. static volatile rt_uint8_t mutex_index = 0;
  42. /*-----------------------------------------------------------*/
  43. #if 0
  44. //#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  45. QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength,
  46. const UBaseType_t uxItemSize,
  47. uint8_t * pucQueueStorage,
  48. StaticQueue_t * pxStaticQueue,
  49. const uint8_t ucQueueType )
  50. {
  51. Queue_t * pxNewQueue = NULL;
  52. char name[RT_NAME_MAX] = {0};
  53. if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
  54. ( pxStaticQueue != NULL ) &&
  55. /* A queue storage area should be provided if the item size is not 0, and
  56. * should not be provided if the item size is 0. */
  57. ( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ) &&
  58. ( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ) )
  59. {
  60. /* The address of a statically allocated queue was passed in, use it.
  61. * The address of a statically allocated storage area was also passed in
  62. * but is already set. */
  63. pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
  64. if ( ( ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX ) )
  65. {
  66. rt_snprintf( name, RT_NAME_MAX - 1, "mutex%02d", mutex_index++ );
  67. rt_mutex_init( ( rt_mutex_t ) &pxNewQueue->u.mutex, name, RT_IPC_FLAG_PRIO );
  68. }
  69. }
  70. return pxNewQueue;
  71. }
  72. #endif /* configSUPPORT_STATIC_ALLOCATION */
  73. /*-----------------------------------------------------------*/
  74. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  75. QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
  76. const UBaseType_t uxItemSize,
  77. const uint8_t ucQueueType )
  78. {
  79. Queue_t * pxNewQueue = NULL;
  80. char name[RT_NAME_MAX] = {0};
  81. if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
  82. /* Check for multiplication overflow. */
  83. ( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) &&
  84. /* Check for addition overflow. */
  85. ( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( uxQueueLength * uxItemSize ) ) )
  86. {
  87. if ( ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX )
  88. {
  89. rt_snprintf( name, RT_NAME_MAX - 1, "mutex%02d", mutex_index++ );
  90. pxNewQueue = (Queue_t *) RT_KERNEL_MALLOC( sizeof( Queue_t ) );
  91. if ( pxNewQueue == NULL)
  92. {
  93. return ( QueueHandle_t ) pxNewQueue;
  94. }
  95. pxNewQueue->rt_ipc = ( struct rt_ipc_object * ) rt_mutex_create( name, RT_IPC_FLAG_PRIO );
  96. }
  97. }
  98. return ( QueueHandle_t ) pxNewQueue;
  99. }
  100. #endif /* configSUPPORT_STATIC_ALLOCATION */
  101. /*-----------------------------------------------------------*/
  102. #if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
  103. QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
  104. {
  105. QueueHandle_t xNewQueue;
  106. const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
  107. xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
  108. return xNewQueue;
  109. }
  110. #endif /* configUSE_MUTEXES */
  111. /*-----------------------------------------------------------*/
  112. #if 0
  113. //#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  114. QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType,
  115. StaticQueue_t * pxStaticQueue )
  116. {
  117. QueueHandle_t xNewQueue;
  118. const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
  119. xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );
  120. return xNewQueue;
  121. }
  122. #endif /* configUSE_MUTEXES */
  123. /*-----------------------------------------------------------*/
  124. #if ( configUSE_RECURSIVE_MUTEXES == 1 )
  125. BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
  126. {
  127. Queue_t * const pxMutex = ( Queue_t * ) xMutex;
  128. configASSERT( pxMutex );
  129. return xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
  130. }
  131. #endif /* configUSE_RECURSIVE_MUTEXES */
  132. /*-----------------------------------------------------------*/
  133. #if ( configUSE_RECURSIVE_MUTEXES == 1 )
  134. BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
  135. TickType_t xTicksToWait )
  136. {
  137. Queue_t * const pxMutex = ( Queue_t * ) xMutex;
  138. configASSERT( pxMutex );
  139. return xQueueSemaphoreTake( pxMutex, xTicksToWait );
  140. }
  141. #endif /* configUSE_RECURSIVE_MUTEXES */
  142. /*-----------------------------------------------------------*/
  143. BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
  144. const void * const pvItemToQueue,
  145. TickType_t xTicksToWait,
  146. const BaseType_t xCopyPosition )
  147. {
  148. Queue_t * const pxQueue = xQueue;
  149. struct rt_ipc_object *pipc;
  150. rt_uint8_t type;
  151. rt_err_t err = -RT_ERROR;
  152. configASSERT( pxQueue );
  153. configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
  154. configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
  155. #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
  156. {
  157. configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
  158. }
  159. #endif
  160. pipc = pxQueue->rt_ipc;
  161. RT_ASSERT( pipc != RT_NULL );
  162. type = rt_object_get_type( &pipc->parent );
  163. if ( type == RT_Object_Class_Mutex )
  164. {
  165. err = rt_mutex_release( ( rt_mutex_t ) pipc );
  166. }
  167. return rt_err_to_freertos( err );
  168. }
  169. /*-----------------------------------------------------------*/
  170. BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
  171. TickType_t xTicksToWait )
  172. {
  173. Queue_t * const pxQueue = xQueue;
  174. struct rt_ipc_object *pipc;
  175. rt_uint8_t type;
  176. rt_err_t err = -RT_ERROR;
  177. /* Check the queue pointer is not NULL. */
  178. configASSERT( ( pxQueue ) );
  179. /* Cannot block if the scheduler is suspended. */
  180. #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
  181. {
  182. configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
  183. }
  184. #endif
  185. pipc = pxQueue->rt_ipc;
  186. RT_ASSERT( pipc != RT_NULL );
  187. type = rt_object_get_type( &pipc->parent );
  188. if ( type == RT_Object_Class_Mutex )
  189. {
  190. err = rt_mutex_take( ( rt_mutex_t ) pipc, ( rt_int32_t ) xTicksToWait );
  191. }
  192. return rt_err_to_freertos( err );
  193. }
  194. /*-----------------------------------------------------------*/
  195. void vQueueDelete( QueueHandle_t xQueue )
  196. {
  197. Queue_t * const pxQueue = xQueue;
  198. struct rt_ipc_object *pipc;
  199. rt_uint8_t type;
  200. configASSERT( pxQueue );
  201. pipc = pxQueue->rt_ipc;
  202. RT_ASSERT( pipc != RT_NULL );
  203. type = rt_object_get_type( &pipc->parent );
  204. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  205. if ( rt_object_is_systemobject( ( rt_object_t ) pipc ) )
  206. #endif
  207. {
  208. #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
  209. if ( type == RT_Object_Class_Mutex )
  210. {
  211. rt_mutex_detach( ( rt_mutex_t ) pipc );
  212. }
  213. else if ( type == RT_Object_Class_Semaphore )
  214. {
  215. rt_sem_detach( ( rt_sem_t ) pipc );
  216. }
  217. else if ( type == RT_Object_Class_MailBox )
  218. {
  219. rt_mb_detach( ( rt_mailbox_t ) pipc );
  220. }
  221. #endif
  222. #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
  223. }
  224. else
  225. {
  226. #endif
  227. #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
  228. if ( type == RT_Object_Class_Mutex )
  229. {
  230. rt_mutex_delete( ( rt_mutex_t ) pipc );
  231. }
  232. else if ( type == RT_Object_Class_Semaphore )
  233. {
  234. rt_sem_delete( ( rt_sem_t ) pipc );
  235. }
  236. else if ( type == RT_Object_Class_MailBox )
  237. {
  238. rt_mb_delete( ( rt_mailbox_t ) pipc );
  239. }
  240. else
  241. {
  242. return;
  243. }
  244. RT_KERNEL_FREE( pxQueue );
  245. #endif
  246. }
  247. }
  248. /*-----------------------------------------------------------*/