add semaphore max value control. (#8390)

This commit is contained in:
geniusgogo 2023-12-21 10:31:27 +08:00 committed by GitHub
parent 0541b39d61
commit 3dfafcd1d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 20 deletions

View File

@ -1038,6 +1038,7 @@ typedef struct rt_thread *rt_thread_t;
#define RT_IPC_CMD_UNKNOWN 0x00 /**< unknown IPC command */
#define RT_IPC_CMD_RESET 0x01 /**< reset IPC object */
#define RT_IPC_CMD_GET_STATE 0x02 /**< get the state of IPC object */
#define RT_IPC_CMD_SET_VLIMIT 0x03 /**< set max limit value of IPC value */
#define RT_WAITING_FOREVER -1 /**< Block forever until get resource. */
#define RT_WAITING_NO 0 /**< Non-block. */
@ -1061,7 +1062,7 @@ struct rt_semaphore
struct rt_ipc_object parent; /**< inherit from ipc_object */
rt_uint16_t value; /**< value of semaphore. */
rt_uint16_t reserved; /**< reserved field */
rt_uint16_t max_value;
struct rt_spinlock spinlock;
};
typedef struct rt_semaphore *rt_sem_t;

View File

@ -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;
}