worker線程的建立與使用

1、worker線程的建立node

1. 建立流程spa

//調用這個接口建立內核工做線程,eg: crypto_engine.c中的建立方法:
kthread_create_worker(0, "%s", engine->name); //在CPU0上建立一個work線程
    kthread_create_worker(unsigned int flags, const char namefmt[], ...)
    //或kthread_create_worker_on_cpu(int cpu, unsigned int flags, const char namefmt[], ...)
        __kthread_create_worker(int cpu, unsigned int flags, const char namefmt[], va_list args)
            __kthread_create_on_node(kthread_worker_fn, worker, node, namefmt, args)

 

__kthread_create_worker():線程

/* 如果參數cpu大於等於0就建立特定於某個CPU的工做線程,如果不想建立特定於CPU的工做線程,就將CPU域賦值爲-1 */
static struct kthread_worker * __kthread_create_worker(int cpu, unsigned int flags, const char namefmt[], va_list args)
{
    struct kthread_worker *worker;
    struct task_struct *task;
    int node = -1;

    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
    if (!worker)
        return ERR_PTR(-ENOMEM);

    kthread_init_worker(worker);

    if (cpu >= 0)
        node = cpu_to_node(cpu);

    task = __kthread_create_on_node(kthread_worker_fn, worker,
                        node, namefmt, args);
    if (IS_ERR(task))
        goto fail_task;

    if (cpu >= 0)
        kthread_bind(task, cpu);

    worker->flags = flags;
    worker->task = task;
    wake_up_process(task);
    return worker;

fail_task:
    kfree(worker);
    return ERR_CAST(task);
}

 

kthread_worker_fn 循環監聽是否有工做須要處理: code

int kthread_worker_fn(void *worker_ptr)
{
    struct kthread_worker *worker = worker_ptr;
    struct kthread_work *work;

    /*
     * FIXME: Update the check and remove the assignment when all kthread
     * worker users are created using kthread_create_worker*() functions.
     */
    WARN_ON(worker->task && worker->task != current);
    worker->task = current;

    if (worker->flags & KTW_FREEZABLE)
        set_freezable();

repeat:
    /* 設置進程的狀態,不被調度 */
    set_current_state(TASK_INTERRUPTIBLE);    /* mb paired w/ kthread_stop */

    if (kthread_should_stop()) {
        __set_current_state(TASK_RUNNING);
        spin_lock_irq(&worker->lock);
        worker->task = NULL;
        spin_unlock_irq(&worker->lock);
        return 0;
    }

    work = NULL;
    spin_lock_irq(&worker->lock);
    if (!list_empty(&worker->work_list)) {
        /* 從work_list中取出一個工做 */
        work = list_first_entry(&worker->work_list, struct kthread_work, node);
        list_del_init(&work->node);
    }
    worker->current_work = work;
    spin_unlock_irq(&worker->lock);

    if (work) {
        __set_current_state(TASK_RUNNING);
        /* 執行這個工做上func() */
        work->func(work);
    } else if (!freezing(current))
        schedule();

    try_to_freeze();
    cond_resched();

    /* 又跳到repeat位置,進行循環執行 */
    goto repeat;
}

 

2、worker的使用blog

未完待續。。。。。接口

相關文章
相關標籤/搜索