static int
mydrv_worker(void *unused)
{
    DECLARE_WAITQUEUE(wait, current);
    void (*worker_func)(void *);
    void *worker_data;
    struct _mydrv_work *mydrv_work;

    set_current_state(TASK_INTERRUPTIBLE);

    /* Spin until asked to die */
    while (!asked_to_die()) {
        add_wait_queue(&mydrv_wq.todo, &wait);

        if (list_empty(&mydrv_wq.mydrv_worklist)) {
            schedule();
            /* Woken up by the submitter */
        } else {
            set_current_state(TASK_RUNNING);
        }

        remove_wait_queue(&mydrv_wq.todo, &wait);

        /* Protect concurrent access to the list */
        spin_lock(&mydrv_wq.lock);

        /* Traverse the list and plough through the work functions
           present in each node */

        while (!list_empty(&mydrv_wq.mydrv_worklist)) {
            /* Get the first entry in the list */
            mydrv_work = list_entry(mydrv_wq.mydrv_worklist.next,
                                    struct _mydrv_work, mydrv_workitem);
            worker_func = mydrv_work->worker_func;
            worker_data = mydrv_work->worker_data;
            /* This node has been processed. Throw it
               out of the list */
            list_del(mydrv_wq.mydrv_worklist.next);
            kfree(mydrv_work); /* Free the node */
            /* Execute the work function in this node */
            spin_unlock(&mydrv_wq.lock); /* Release lock */
            worker_func(worker_data);
            spin_lock(&mydrv_wq.lock); /* Re-acquire lock */
        }

        spin_unlock(&mydrv_wq.lock);
        set_current_state(TASK_INTERRUPTIBLE);
    }

    set_current_state(TASK_RUNNING);
    return 0;
} 


syntax highlighted by Code2HTML, v. 0.9.1