lk中的mutex_t机制

来源:互联网 发布:mac如何退出dashboard 编辑:程序博客网 时间:2024/06/10 15:54
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 thread\n");
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.
0 0
原创粉丝点击