* @brief This function will release a semaphore. If there is thread suspended on the semaphore, it will get resumed. * * @note If there are threads suspended on this semaphore, the first thread in the list of this semaphore object * will be resumed, and a thread scheduling (rt_schedule) will be executed. * If no threads are suspended on this semaphore, the count valu
| 694 | * If the return value is any other values, it means that the semaphore release failed. |
| 695 | */ |
| 696 | rt_err_t rt_sem_release(rt_sem_t sem) |
| 697 | { |
| 698 | rt_base_t level; |
| 699 | rt_bool_t need_schedule; |
| 700 | |
| 701 | /* parameter check */ |
| 702 | RT_ASSERT(sem != RT_NULL); |
| 703 | RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore); |
| 704 | |
| 705 | RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(sem->parent.parent))); |
| 706 | |
| 707 | need_schedule = RT_FALSE; |
| 708 | |
| 709 | level = rt_spin_lock_irqsave(&(sem->spinlock)); |
| 710 | |
| 711 | LOG_D("thread %s releases sem:%s, which value is: %d", |
| 712 | rt_thread_self()->parent.name, |
| 713 | sem->parent.parent.name, |
| 714 | sem->value); |
| 715 | |
| 716 | if (!rt_list_isempty(&sem->parent.suspend_thread)) |
| 717 | { |
| 718 | /* resume the suspended thread */ |
| 719 | rt_susp_list_dequeue(&(sem->parent.suspend_thread), RT_EOK); |
| 720 | need_schedule = RT_TRUE; |
| 721 | } |
| 722 | else |
| 723 | { |
| 724 | if(sem->value < sem->max_value) |
| 725 | { |
| 726 | sem->value ++; /* increase value */ |
| 727 | } |
| 728 | else |
| 729 | { |
| 730 | rt_spin_unlock_irqrestore(&(sem->spinlock), level); |
| 731 | return -RT_EFULL; /* value overflowed */ |
| 732 | } |
| 733 | } |
| 734 | |
| 735 | rt_spin_unlock_irqrestore(&(sem->spinlock), level); |
| 736 | |
| 737 | /* resume a thread, re-schedule */ |
| 738 | if (need_schedule == RT_TRUE) |
| 739 | rt_schedule(); |
| 740 | |
| 741 | return RT_EOK; |
| 742 | } |
| 743 | RTM_EXPORT(rt_sem_release); |
| 744 | |
| 745 |