* @brief This function will set some extra attributions of a semaphore object. * * @note Currently this function only supports the RT_IPC_CMD_RESET command to reset the semaphore. * * @param sem is a pointer to a semaphore object. * * @param cmd is a command word used to configure some attributions of the semaphore. * * @param arg is the argument of the function to execute
| 758 | * If the return value is any other values, it means that this function failed to execute. |
| 759 | */ |
| 760 | rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) |
| 761 | { |
| 762 | rt_base_t level; |
| 763 | |
| 764 | /* parameter check */ |
| 765 | RT_ASSERT(sem != RT_NULL); |
| 766 | RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore); |
| 767 | |
| 768 | if (cmd == RT_IPC_CMD_RESET) |
| 769 | { |
| 770 | rt_ubase_t value; |
| 771 | |
| 772 | /* get value */ |
| 773 | value = (rt_uintptr_t)arg; |
| 774 | level = rt_spin_lock_irqsave(&(sem->spinlock)); |
| 775 | |
| 776 | /* resume all waiting thread */ |
| 777 | rt_susp_list_resume_all(&sem->parent.suspend_thread, RT_ERROR); |
| 778 | |
| 779 | /* set new value */ |
| 780 | sem->value = (rt_uint16_t)value; |
| 781 | rt_spin_unlock_irqrestore(&(sem->spinlock), level); |
| 782 | rt_schedule(); |
| 783 | |
| 784 | return RT_EOK; |
| 785 | } |
| 786 | else if (cmd == RT_IPC_CMD_SET_VLIMIT) |
| 787 | { |
| 788 | rt_ubase_t max_value; |
| 789 | rt_bool_t need_schedule = RT_FALSE; |
| 790 | |
| 791 | max_value = (rt_uint16_t)((rt_uintptr_t)arg); |
| 792 | if (max_value > RT_SEM_VALUE_MAX || max_value < 1) |
| 793 | { |
| 794 | return -RT_EINVAL; |
| 795 | } |
| 796 | |
| 797 | level = rt_spin_lock_irqsave(&(sem->spinlock)); |
| 798 | if (max_value < sem->value) |
| 799 | { |
| 800 | if (!rt_list_isempty(&sem->parent.suspend_thread)) |
| 801 | { |
| 802 | /* resume all waiting thread */ |
| 803 | rt_susp_list_resume_all(&sem->parent.suspend_thread, RT_ERROR); |
| 804 | need_schedule = RT_TRUE; |
| 805 | } |
| 806 | } |
| 807 | /* set new value */ |
| 808 | sem->max_value = max_value; |
| 809 | rt_spin_unlock_irqrestore(&(sem->spinlock), level); |
| 810 | |
| 811 | if (need_schedule) |
| 812 | { |
| 813 | rt_schedule(); |
| 814 | } |
| 815 | |
| 816 | return RT_EOK; |
| 817 | } |