add semaphore max value control. (#8390)
This commit is contained in:
parent
0541b39d61
commit
3dfafcd1d9
|
@ -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;
|
||||
|
|
71
src/ipc.c
71
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue