概述
lk中还实现thread对全局资源保护的机制:mutex_t。主要用于对全局变量资源保护.而event 主要用于多thread之间
实现这套机制总共就5个函数,我们一个一个看一下
mutex_x的初始化函数和event一样,也是每个mutex_t 需要时wait queue
void mutex_init(mutex_t *m)
{
#if MUTEX_CHECK
//
ASSERT(m->magic != MUTEX_MAGIC);
#endif
m->magic = MUTEX_MAGIC;
m->count = 0;
m->holder = 0;
wait_queue_init(&m->wait);
}
mutex_x的获取函数如下,可见如果只是两个thread之间协调的话m->count ==1,并不会使用wait_queue,而且会记住这个mutex_x 是哪个thread持有
status_t mutex_acquire(mutex_t *m)
{
status_t ret = NO_ERROR;
if (current_thread == m->holder)
panic("mutex_acquire: thread %p (%s) tried to acquire mutex %p it already owns.n",
current_thread, current_thread->name, m);
enter_critical_section();
m->count++;
if (unlikely(m->count > 1)) {
ret = wait_queue_block(&m->wait, INFINITE_TIME);
if (ret < 0)
goto err;
}
m->holder = current_thread;
err:
exit_critical_section();
return ret;
}
如果用在一个thread之内保护资源的话mutex_acquire_timeout 和 mutex_acquire 是一样
status_t mutex_release(mutex_t *m)
{
if (current_thread != m->holder)
panic("mutex_release: thread %p (%s) tried to release mutex %p it doesn't own. owned by %p (%s)n",
current_thread, current_thread->name, m, m->holder, m->holder ? m->holder->name : "none");
enter_critical_section();
m->holder = 0;
m->count--;
if (unlikely(m->count >= 1)) {
/* release a thread */
//
dprintf("releasing threadn");
wait_queue_wake_one(&m->wait, true, NO_ERROR);
}
exit_critical_section();
return NO_ERROR;
}
mutex_release的实现也很简单,将m->count--,一般情况下等于0.也就是if (unlikely(m->count >= 1))
一般不成立。
void mutex_destroy(mutex_t *m)
{
enter_critical_section();
#if MUTEX_CHECK
ASSERT(m->magic == MUTEX_MAGIC);
#endif
//
if (m->holder != 0 && current_thread != m->holder)
//
panic("mutex_destroy: thread %p (%s) tried to release mutex %p it doesn't own. owned by %p (%s)n",
//
current_thread, current_thread->name, m, m->holder, m->holder ? m->holder->name : "none");
m->magic = 0;
m->count = 0;
wait_queue_destroy(&m->wait, true);
exit_critical_section();
}
mutex_destroy用于销毁mutex_x。个人感觉这个函数应该要先判断一下m->count-- 是否为0,如果为0的话,就没必要调用wait_queue_destroy 这个函数了
void wait_queue_destroy(wait_queue_t *wait, bool reschedule)
{
#if THREAD_CHECKS
ASSERT(wait->magic == WAIT_QUEUE_MAGIC);
ASSERT(in_critical_section());
#endif
wait_queue_wake_all(wait, reschedule, ERR_OBJECT_DESTROYED);
wait->magic = 0;
}
继续调用wait_queue_wake_all 来wakeup在等待这个mutex_x的所有thread
int wait_queue_wake_all(wait_queue_t *wait, bool reschedule, status_t wait_queue_error)
{
thread_t *t;
int ret = 0;
if (reschedule && wait->count > 0) {
current_thread->state = THREAD_READY;
insert_in_run_queue_head(current_thread);
}
/* pop all the threads off the wait queue into the run queue */
while ((t = list_remove_head_type(&wait->list, thread_t, queue_node))) {
wait->count--;
t->state = THREAD_READY;
t->wait_queue_block_ret = wait_queue_error;
t->blocking_wait_queue = NULL;
insert_in_run_queue_head(t);
ret++;
}
if (reschedule && ret > 0)
thread_resched();
return ret;
}
如果wait->count > 0的话,由于reschedule ==1.就说明多个thread在使用这个mutex_x.就先将当前thread 放到run_queue中,然后设置current_thread->state = THREAD_READY;,再将其放到run_queue中,饭后将wait list中的每一个thread 都取出来放到run_queue中,单后调用thread_resched来调用
这样run_queue就先运行wait list中的thread.
最后
以上就是明亮菠萝为你收集整理的lk中的mutex_t机制的全部内容,希望文章能够帮你解决lk中的mutex_t机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复