Chinaunix首页 | 论坛 | 博客
  • 博客访问: 438725
  • 博文数量: 99
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 1012
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-20 16:30
个人简介

linux kernel 工程师

文章分类

全部博文(99)

文章存档

2018年(5)

2017年(12)

2016年(27)

2015年(10)

2014年(43)

2012年(2)

我的朋友

分类: LINUX

2014-02-05 17:58:05


/**
 * worker_thread - the worker thread function
 * @__worker: self
 *
 * The gcwq worker thread function.  There's a single dynamic pool of
 * these per each cpu.  These workers process all works regardless of
 * their specific target workqueue.  The only exception is works which
 * belong to workqueues with a rescuer which will be explained in
 * rescuer_thread().
 */
static int worker_thread(void *__worker)
{
 struct worker *worker = __worker;
 struct global_cwq *gcwq = worker->gcwq;

 /* tell the scheduler that this is a workqueue worker */
 worker->task->flags |= PF_WQ_WORKER;
woke_up:
 spin_lock_irq(&gcwq->lock);

 /* DIE can be set only while we're idle, checking here is enough */
 if (worker->flags & WORKER_DIE) {
  spin_unlock_irq(&gcwq->lock);
  worker->task->flags &= ~PF_WQ_WORKER;
  return 0;
 }

 worker_leave_idle(worker); /* 该worker离开idle状态, 从idle的list上摘下来,idle的worker数减1 */

recheck:
 /* no more worker necessary? */
 if (!need_more_worker(gcwq))   /* need_more_worker 含义: work list 上有work,但nr_running ==0 */
  goto sleep;

 /* do we need to manage? */
 if (unlikely(!may_start_working(gcwq))   /* may_start_working返回idle 的workers,如果idle的worker数等于0, (!may_start_working(gcwq)返回true  */
              && manage_workers(worker)   /* 创建workers 成功 后,idle的worker数就会加1*/ )
  goto recheck;

/* 线程x创建了线程y。
1. 线程y被唤醒后,如果获得在cpu上运行权,判断标号001, 由于work list 上有work,且nr_running ==0 ,所以 need_more_worker
返回true,(!need_more_worker(gcwq) 为false, 所以不会跳转到sleep 。在判断may_start_working(gcwq),idle 的workers==1, (!may_start_working(gcwq) 为false,
所以开始往下走。
2. 假如x继续占据cpu,判断标号001, 由于work list 上有work,切nr_running ==0 ,所以 need_more_worker
返回true,(!need_more_worker(gcwq) 为false, 所以不会跳转到sleep 。在判断may_start_working(gcwq),idle 的workers==1, (!may_start_working(gcwq) 为false,
所以开始往下走。

所以无论原线程x还是新创建的线程y获得cpu的运行权,执行的结果是一致的。
*/


 /*
  * ->scheduled list can only be filled while a worker is
  * preparing to process a work or actually processing it.
  * Make sure nobody diddled with it while I was sleeping.
  */
 BUG_ON(!list_empty(&worker->scheduled));

 /*
  * When control reaches this point, we're guaranteed to have
  * at least one idle worker or that someone else has already
  * assumed the manager role.
  */
 worker_clr_flags(worker, WORKER_PREP);            /* nr_running 加1,如果一个workerA 执行到这一步,另外一个worker B在判断need_more_worker(gcwq)函数时, 就会得到false的结论,workerB sleep*/

/* 遍历global cpu work queue,  work都在gcwq->worklist上 */
 do {
  struct work_struct *work =
   list_first_entry(&gcwq->worklist,
      struct work_struct, entry);

   /* WORK_STRUCT_LINKED表示下一个工作与当前工作有联系,这样做保证这些有联系的工作按顺序执行,我自己的理解  */
  if (likely(!(*work_data_bits(work) & WORK_STRUCT_LINKED))) {
   /* optimization path, not strictly necessary */
   process_one_work(worker, work); /*  一次一个的处理work*/
   if (unlikely(!list_empty(&worker->scheduled)))
    process_scheduled_works(worker);
  } else {
   move_linked_works(work, &worker->scheduled, NULL);
   process_scheduled_works(worker);
  }
 } while (keep_working(gcwq));

 worker_set_flags(worker, WORKER_PREP, false);  /* nr_running 减1 */

sleep:
 if (unlikely(need_to_manage_workers(gcwq)) && manage_workers(worker))
  goto recheck;

 /*
  * gcwq->lock is held and there's no work to process and no
  * need to manage, sleep.  Workers are woken up only while
  * holding gcwq->lock or from local cpu, so setting the
  * current state before releasing gcwq->lock is enough to
  * prevent losing any event.
  */
 worker_enter_idle(worker);  /* 该worker进入idle状态,加入idle的list上,idle的worker数加1  */
 __set_current_state(TASK_INTERRUPTIBLE);
 spin_unlock_irq(&gcwq->lock);
 schedule();
 goto woke_up;
}

-------------------------------------------------------------------------------
/* Do I need to keep working?  Called from currently running workers. */
static bool keep_working(struct global_cwq *gcwq)
{
 atomic_t *nr_running = get_gcwq_nr_running(gcwq->cpu);

 return !list_empty(&gcwq->worklist) &&  /* worklist上还有工作要处理 */
  (atomic_read(nr_running) <= 1 ||  /*  本cpu上的最后一个执行worker */
   gcwq->flags & GCWQ_HIGHPRI_PENDING); /* 有高优先级work待处理 */
}


 

阅读(1022) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~