mt7530交换芯片的数据接收中断后,把具体接收数据工作任务、委托到workqueue队列中,让内核work_thread()线程任务来处理,这部分内容请参考《workqueue工作原理》中的描述。
workqueue基本工作流程框架如下:
框架业务关系:
1,程序把work单加入到workqueue中,就等于把工作安排好,是工单的生成者、派遣者;
2,work_pool是工厂,提供工作的场地,worker是工人,负责执行工单,是消费者;
3,PWQ(pool work queue)是派遣工单给工厂协调者,负责匹配生产者与消费者之间协调;
workqueue框架启动流程:
1,内核kernel_init_freeable初始化函数(in main.c)调用workqueue_init()初始化程序;
2,workqueue_init()函数为每隔CPU创建一个worker_pool池;
3,kthread_create_on_node()创建一个worker进程,并worker_attach_to_pool(work,pool);添加到池子中;
worker执行工作流程:workqueue.c-->static ini worker_thread(void* __worker)
/** Finish PREP stage. We're guaranteed to have at least one idle* worker or that someone else has already assumed the manager* role. This is where @worker starts participating in concurrency* management if applicable and concurrency management is restored* after being rebound. See rebind_workers() for details.*/worker_clr_flags(worker, WORKER_PREP | WORKER_REBOUND);do {struct work_struct *work =list_first_entry(&pool->worklist,struct work_struct, entry);pool->watchdog_ts = jiffies;if (likely(!(*work_data_bits(work) & WORK_STRUCT_LINKED))) {/* optimization path, not strictly necessary */process_one_work(worker, work); /* worker done work,执行queue中的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(pool));
数据接收任务单的执行者是谁?
硬件中断后程序最终通过insert_work()函数,把待处理的数据任务放到workqueue中,开篇已经描述worker_pool中已经具有worker线程one-by-one执行工作任务,也及时说数据会被process_one_work(worker, work)程序接收、并送往网络协议栈。
/*** process_one_work - process single work* @worker: self* @work: work to process** Process @work. This function contains all the logics necessary to* process a single work including synchronization against and* interaction with other workers on the same cpu, queueing and* flushing. As long as context requirement is met, any worker can* call this function to process a work.** CONTEXT:* spin_lock_irq(pool->lock) which is released and regrabbed.*/
static void process_one_work(struct worker *worker, struct work_struct *work)
__releases(&pool->lock)
__acquires(&pool->lock)
{struct pool_workqueue *pwq = get_work_pwq(work);struct worker_pool *pool = worker->pool;bool cpu_intensive = pwq->wq->flags & WQ_CPU_INTENSIVE;int work_color;struct worker *collision;
#ifdef CONFIG_LOCKDEP/** It is permissible to free the struct work_struct from* inside the function that is called from it, this we need to* take into account for lockdep too. To avoid bogus &#