* @brief This function will pop data from the data queue. If the data queue is empty,the thread * will suspend for the specified amount of time. * * @note When the number of data in the data queue is less than lwm(low water mark), will * wake up the thread waiting for write data. * * @param queue is a pointer to the data queue object. * * @param data_ptr is
| 208 | * When the return value is -RT_ETIMEOUT, it means the specified time out. |
| 209 | */ |
| 210 | rt_err_t rt_data_queue_pop(struct rt_data_queue *queue, |
| 211 | const void **data_ptr, |
| 212 | rt_size_t *size, |
| 213 | rt_int32_t timeout) |
| 214 | { |
| 215 | rt_base_t level; |
| 216 | rt_thread_t thread; |
| 217 | rt_err_t result; |
| 218 | |
| 219 | RT_ASSERT(queue != RT_NULL); |
| 220 | RT_ASSERT(queue->magic == DATAQUEUE_MAGIC); |
| 221 | RT_ASSERT(data_ptr != RT_NULL); |
| 222 | RT_ASSERT(size != RT_NULL); |
| 223 | |
| 224 | /* current context checking */ |
| 225 | RT_DEBUG_SCHEDULER_AVAILABLE(timeout != 0); |
| 226 | |
| 227 | result = RT_EOK; |
| 228 | thread = rt_thread_self(); |
| 229 | |
| 230 | level = rt_spin_lock_irqsave(&(queue->spinlock)); |
| 231 | while (queue->is_empty) |
| 232 | { |
| 233 | /* queue is empty */ |
| 234 | if (timeout == 0) |
| 235 | { |
| 236 | result = -RT_ETIMEOUT; |
| 237 | goto __exit; |
| 238 | } |
| 239 | |
| 240 | /* reset thread error number */ |
| 241 | thread->error = RT_EOK; |
| 242 | |
| 243 | /* suspend thread on the pop list */ |
| 244 | result = rt_thread_suspend_to_list(thread, &queue->suspended_pop_list, |
| 245 | RT_IPC_FLAG_FIFO, RT_UNINTERRUPTIBLE); |
| 246 | if (result == RT_EOK) |
| 247 | { |
| 248 | /* start timer */ |
| 249 | if (timeout > 0) |
| 250 | { |
| 251 | rt_tick_t timeout_tick = timeout; |
| 252 | /* reset the timeout of thread timer and start it */ |
| 253 | rt_timer_control(&(thread->thread_timer), |
| 254 | RT_TIMER_CTRL_SET_TIME, |
| 255 | &timeout_tick); |
| 256 | rt_timer_start(&(thread->thread_timer)); |
| 257 | } |
| 258 | |
| 259 | /* enable interrupt */ |
| 260 | rt_spin_unlock_irqrestore(&(queue->spinlock), level); |
| 261 | |
| 262 | /* do schedule */ |
| 263 | rt_schedule(); |
| 264 | |
| 265 | /* thread is waked up */ |
| 266 | level = rt_spin_lock_irqsave(&(queue->spinlock)); |
| 267 | result = thread->error; |
no test coverage detected