MCPcopy Create free account
hub / github.com/RT-Thread/rt-thread / _rt_sem_take

Function _rt_sem_take

src/ipc.c:558–643  ·  view source on GitHub ↗

* @brief This function will take a semaphore, if the semaphore is unavailable, the thread shall wait for * the semaphore up to a specified time. * * @note When this function is called, the count value of the sem->value will decrease 1 until it is equal to 0. * When the sem->value is 0, it means that the semaphore is unavailable. At this time, it will suspend the *

Source from the content-addressed store, hash-verified

556 * @warning This function can ONLY be called in the thread context. It MUST NOT BE called in interrupt context.
557 */
558static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t timeout, int suspend_flag)
559{
560 rt_base_t level;
561 struct rt_thread *thread;
562 rt_err_t ret;
563
564 /* parameter check */
565 RT_ASSERT(sem != RT_NULL);
566 RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
567
568 RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(sem->parent.parent)));
569
570 /* current context checking */
571 RT_DEBUG_SCHEDULER_AVAILABLE(1);
572
573 level = rt_spin_lock_irqsave(&(sem->spinlock));
574
575 LOG_D("thread %s take sem:%s, which value is: %d",
576 rt_thread_self()->parent.name,
577 sem->parent.parent.name,
578 sem->value);
579
580 if (sem->value > 0)
581 {
582 /* semaphore is available */
583 sem->value --;
584 rt_spin_unlock_irqrestore(&(sem->spinlock), level);
585 }
586 else
587 {
588 /* no waiting, return with timeout */
589 if (timeout == 0)
590 {
591 rt_spin_unlock_irqrestore(&(sem->spinlock), level);
592 return -RT_ETIMEOUT;
593 }
594 else
595 {
596 /* semaphore is unavailable, push to suspend list */
597 /* get current thread */
598 thread = rt_thread_self();
599
600 /* reset thread error number */
601 thread->error = RT_EINTR;
602
603 LOG_D("sem take: suspend thread - %s", thread->parent.name);
604
605 /* suspend thread */
606 ret = rt_thread_suspend_to_list(thread, &(sem->parent.suspend_thread),
607 sem->parent.parent.flag, suspend_flag);
608 if (ret != RT_EOK)
609 {
610 rt_spin_unlock_irqrestore(&(sem->spinlock), level);
611 return ret;
612 }
613
614 /* has waiting time, start thread timer */
615 if (timeout > 0)

Callers 3

rt_sem_takeFunction · 0.85
rt_sem_take_killableFunction · 0.85

Calls 8

rt_object_get_typeFunction · 0.85
rt_thread_selfFunction · 0.85
rt_timer_controlFunction · 0.85
rt_timer_startFunction · 0.85
rt_spin_lock_irqsaveFunction · 0.70
rt_scheduleFunction · 0.70

Tested by

no test coverage detected