* @brief This function will join a thread to the specified waiting queue, the thread will holds a wait or * timeout return on the specified wait queue. * * @param queue is a pointer to the wait queue. * * @param condition is parameters compatible with POSIX standard interface (currently meaningless, just pass in 0). * * @param msec is the timeout value, unit is millise
| 197 | * @return Return 0 if the thread is woken up. |
| 198 | */ |
| 199 | static int _rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec, int suspend_flag) |
| 200 | { |
| 201 | rt_tick_t tick; |
| 202 | rt_thread_t tid = rt_thread_self(); |
| 203 | rt_timer_t tmr = &(tid->thread_timer); |
| 204 | struct rt_wqueue_node __wait; |
| 205 | rt_base_t level; |
| 206 | rt_err_t ret; |
| 207 | |
| 208 | /* current context checking */ |
| 209 | RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE); |
| 210 | |
| 211 | tick = rt_tick_from_millisecond(msec); |
| 212 | |
| 213 | if ((condition) || (tick == 0)) |
| 214 | return 0; |
| 215 | |
| 216 | __wait.polling_thread = rt_thread_self(); |
| 217 | __wait.key = 0; |
| 218 | __wait.wakeup = __wqueue_default_wake; |
| 219 | __wait.wqueue = queue; |
| 220 | rt_list_init(&__wait.list); |
| 221 | |
| 222 | level = rt_spin_lock_irqsave(&(queue->spinlock)); |
| 223 | |
| 224 | /* reset thread error */ |
| 225 | tid->error = RT_EOK; |
| 226 | |
| 227 | if (queue->flag == RT_WQ_FLAG_WAKEUP) |
| 228 | { |
| 229 | /* already wakeup */ |
| 230 | goto __exit_wakeup; |
| 231 | } |
| 232 | |
| 233 | ret = rt_thread_suspend_with_flag(tid, suspend_flag); |
| 234 | if (ret != RT_EOK) |
| 235 | { |
| 236 | rt_spin_unlock_irqrestore(&(queue->spinlock), level); |
| 237 | /* suspend failed */ |
| 238 | return -RT_EINTR; |
| 239 | } |
| 240 | |
| 241 | rt_list_insert_before(&(queue->waiting_list), &(__wait.list)); |
| 242 | |
| 243 | /* start timer */ |
| 244 | if (tick != (rt_tick_t)RT_WAITING_FOREVER) |
| 245 | { |
| 246 | rt_timer_control(tmr, |
| 247 | RT_TIMER_CTRL_SET_TIME, |
| 248 | &tick); |
| 249 | |
| 250 | rt_timer_start(tmr); |
| 251 | } |
| 252 | rt_spin_unlock_irqrestore(&(queue->spinlock), level); |
| 253 | |
| 254 | rt_schedule(); |
| 255 | |
| 256 | level = rt_spin_lock_irqsave(&(queue->spinlock)); |
no test coverage detected