From 3dfafcd1d982c09b1718f36c956263fd1ef507db Mon Sep 17 00:00:00 2001 From: geniusgogo <2041245+geniusgogo@users.noreply.github.com> Date: Thu, 21 Dec 2023 10:31:27 +0800 Subject: add semaphore max value control. (#8390) --- src/ipc.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/ipc.c b/src/ipc.c index 75bdb2eafc..4736aaf2ff 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -271,6 +271,23 @@ rt_inline rt_err_t _ipc_list_resume_all(rt_list_t *list) * @{ */ +static void _sem_object_init(rt_sem_t sem, + rt_uint16_t value, + rt_uint8_t flag, + rt_uint16_t max_value) +{ + /* initialize ipc object */ + _ipc_object_init(&(sem->parent)); + + sem->max_value = max_value; + /* set initial value */ + sem->value = value; + + /* set parent */ + sem->parent.parent.flag = flag; + rt_spin_lock_init(&(sem->spinlock)); +} + /** * @brief This function will initialize a static semaphore object. * @@ -321,15 +338,7 @@ rt_err_t rt_sem_init(rt_sem_t sem, /* initialize object */ rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name); - /* initialize ipc object */ - _ipc_object_init(&(sem->parent)); - - /* set initial value */ - sem->value = (rt_uint16_t)value; - - /* set parent */ - sem->parent.parent.flag = flag; - rt_spin_lock_init(&(sem->spinlock)); + _sem_object_init(sem, value, flag, RT_SEM_VALUE_MAX); return RT_EOK; } @@ -422,15 +431,7 @@ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag) if (sem == RT_NULL) return sem; - /* initialize ipc object */ - _ipc_object_init(&(sem->parent)); - - /* set initial value */ - sem->value = value; - - /* set parent */ - sem->parent.parent.flag = flag; - rt_spin_lock_init(&(sem->spinlock)); + _sem_object_init(sem, value, flag, RT_SEM_VALUE_MAX); return sem; } @@ -670,7 +671,7 @@ rt_err_t rt_sem_release(rt_sem_t sem) } else { - if(sem->value < RT_SEM_VALUE_MAX) + if(sem->value < sem->max_value) { sem->value ++; /* increase value */ } @@ -732,6 +733,38 @@ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg) return RT_EOK; } + else if (cmd == RT_IPC_CMD_SET_VLIMIT) + { + rt_ubase_t max_value; + rt_bool_t need_schedule = RT_FALSE; + + max_value = (rt_uint16_t)((rt_ubase_t)arg); + if (max_value > RT_SEM_VALUE_MAX || max_value < 1) + { + return -RT_EINVAL; + } + + level = rt_spin_lock_irqsave(&(sem->spinlock)); + if (max_value < sem->value) + { + if (!rt_list_isempty(&sem->parent.suspend_thread)) + { + /* resume all waiting thread */ + _ipc_list_resume_all(&sem->parent.suspend_thread); + need_schedule = RT_TRUE; + } + } + /* set new value */ + sem->max_value = max_value; + rt_spin_unlock_irqrestore(&(sem->spinlock), level); + + if (need_schedule) + { + rt_schedule(); + } + + return RT_EOK; + } return -RT_ERROR; } -- cgit v1.3.1