summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgeniusgogo <[email protected]>2023-12-21 10:31:27 +0800
committerGitHub <[email protected]>2023-12-21 10:31:27 +0800
commit3dfafcd1d982c09b1718f36c956263fd1ef507db (patch)
tree276b33e3376cc061f13190bac1d5de6a178df88a /src
parent0541b39d61d4db7577037d51be70eb09d0a609e2 (diff)
add semaphore max value control. (#8390)
Diffstat (limited to 'src')
-rw-r--r--src/ipc.c71
1 files changed, 52 insertions, 19 deletions
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;
}