1、网上的一个deadlock
idle_worker_rebind() path HOTPLUG path
online
rebind_workers()
wait_event(gcwq->rebind_hold)
woken up but no scheduled rebind_workers() returns (*)
the same cpu offline
the same cpu online again
rebind_workers()
set WORKER_REBIND
scheduled,see the WORKER_REBIND
wait rebind_workers() clear it <--bug--> wait idle_worker_rebind()
rebound.
The two thread wait each other. It is bug
这个bug在我下载的内核中应该已经修掉了,因为在rebind_workers函数中,wake_up_all(&gcwq->rebind_hold);之后,加入了如下代码:
____if (--idle_rebind.cnt) {
________spin_unlock_irq(&gcwq->lock);
________wait_for_completion(&idle_rebind.done);
________spin_lock_irq(&gcwq->lock);
____}
保证了在idle_worker_rebind()运行完成之前,rebind_workers()会一直等待不会退出。
2、引入线程池
使用worker_pool来管理,每个cpu有两个线程池,另外还有两个unbound线程池,每个线程池里至少有一个线程。
线程池的管理,大家都知道线程状态粗略的分为运行态(所谓运行态表示可以运行,在运行队列中,并不表示其正在运行)和等待态,
我们使用pool_nr_running来统计该线程池中有多少个处于运行态。当线程池中处于可运行状态的线程很多时,新创建的线程,就会处于TASK_INTERRUPTIBLE的睡眠状态。
那么处于TASK_INTERRUPTIBLE状态的线程什么时候变成可运行态呢?有以下几个触发点:
1)、insert_work
____if (__need_more_worker(pool))
________wake_up_worker(pool);
2)、idle_worker_timeout(这个函数主要是用来管理线程池中的线程的个数,当线程池中线程的个数很多时,就删除掉一些线程)
____if (too_many_workers(pool)) {
________struct worker *worker;
________unsigned long expires;
________/* idle_list is kept in LIFO order, check the last one */
________worker = list_entry(pool->idle_list.prev, struct worker, entry);
________expires = worker->last_active + IDLE_WORKER_TIMEOUT;
________if (time_before(jiffies, expires))
____________mod_timer(&pool->idle_timer, expires);
________else {
____________/* it's been idle for too long, wake up manager */
____________pool->flags |= POOL_MANAGE_WORKERS;
____________wake_up_worker(pool);
________}
____}
3、关键是rebind_workers()是干什么用的?
阅读(2422) | 评论(0) | 转发(0) |