互斥量
互斥量是特殊的信号量,资源个数只能是0、1,实现了优先级继承。
互斥量优点:谁拥有谁释放,优先级继承。
信号量的缺点:谁都可以释放信号量、优先级反转。
HP被MP抢占,优先级反转。
互斥量实现了优先级继承。
提升了拥有者的优先级,使其尽快释放资源。
互斥量结构体
struct rt_mutex
{
struct rt_ipc_object parent; /**< inherit from ipc_object */
rt_uint16_t value; /**< value of mutex */
rt_uint8_t original_priority; /**< priority of last thread hold the mutex */
rt_uint8_t hold; /**< numbers of thread hold the mutex */
struct rt_thread *owner; //信号量拥有者
};
struct rt_ipc_object
{
struct rt_object parent; /**< inherit from rt_object */
rt_list_t suspend_thread; /**< threads pended on this resource */
};
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
{
struct rt_mutex *mutex;
RT_DEBUG_NOT_IN_INTERRUPT;
/* allocate object */
mutex = (rt_mutex_t)rt_object_allocate(RT_Object_Class_Mutex, name); //分配互斥量结构体
if (mutex == RT_NULL)
return mutex;
/* initialize ipc object */
rt_ipc_object_init(&(mutex->parent));
mutex->value = 1;// 初始值设为1,表示资源可用
mutex->owner = RT_NULL;
mutex->original_priority = 0xFF;
mutex->hold = 0;
/* set flag */
mutex->parent.parent.flag = flag;
return mutex;
}
RTM_EXPORT(rt_mutex_create);
线程第一次获取互斥量
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
{
temp = rt_hw_interrupt_disable();//关中断
if (mutex->value > 0)
{
/* mutex is available */
mutex->value --;
/* set mutex owner and original priority */
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
mutex->hold ++;
}
rt_hw_interrupt_enable(temp);
return RT_EOK;
}
线程第二次获取互斥量,同一个线程可以多次获取
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
{
temp = rt_hw_interrupt_disable();//关中断
if (mutex->owner == thread)
{
/* it's the same thread */
mutex->hold ++;
}
rt_hw_interrupt_enable(temp);
return RT_EOK;
}
不同线程获取互斥量
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
{
temp = rt_hw_interrupt_disable();//关中断
if (thread->current_priority < mutex->owner->current_priority)//如果当前因申请互斥量而被阻塞的线程的优先级高于拥有互斥量的优先级
{
/* change the owner thread priority */
rt_thread_control(mutex->owner,
RT_THREAD_CTRL_CHANGE_PRIORITY,
&thread->current_priority);//占有线程的优先级继承线程的优先级
}
}
释放互斥量
/**
* This function will release a mutex, if there are threads suspended on mutex,
* it will be waked up.
*
* @param mutex the mutex object
*
* @return the error code
*/
rt_err_t rt_mutex_release(rt_mutex_t mutex)
{
if (thread != mutex->owner)
{
thread->error = -RT_ERROR;
/* enable interrupt */
rt_hw_interrupt_enable(temp);
return -RT_ERROR;
}
mutex->hold --;//释放一次
if (mutex->hold == 0)
{
/* change the owner thread to original priority */
if (mutex->original_priority != mutex->owner->current_priority)//如果线程原始优先级和当前优先级不一样,一定发生了优先级继承,所以需要恢复优先级
{
rt_thread_control(mutex->owner,
RT_THREAD_CTRL_CHANGE_PRIORITY,
&(mutex->original_priority));
}
/* wakeup suspended thread */
if (!rt_list_isempty(&mutex->parent.suspend_thread))
{
/* get suspended thread */
thread = rt_list_entry(mutex->parent.suspend_thread.next,
struct rt_thread,
tlist);
RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_release: resume thread: %s\n",
thread->name));
/* set new owner and priority */
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
mutex->hold ++;
/* resume thread */
rt_ipc_list_resume(&(mutex->parent.suspend_thread));
need_schedule = RT_TRUE;
}
else
{
/* increase value */
mutex->value ++;
/* clear owner */
mutex->owner = RT_NULL;
mutex->original_priority = 0xff;
}
}
}