NFS中RPC的异步与同步

rpc_call_async

rpc_run_task

rpc_execute

static void __rpc_execute(struct rpc_task *task)
{
    struct rpc_wait_queue *queue;
    int task_is_async = RPC_IS_ASYNC(task);
    int status = 0;

    dprintk("RPC: %5u __rpc_execute flags=0x%x\n",
            task->tk_pid, task->tk_flags);

    BUG_ON(RPC_IS_QUEUED(task));

    for (;;) {

        /*
         * Execute any pending callback.
         */
        if (task->tk_callback) {
            void (*save_callback)(struct rpc_task *);

            /*
             * We set tk_callback to NULL before calling it,
             * in case it sets the tk_callback field itself:
             */
            save_callback = task->tk_callback;
            task->tk_callback = NULL;
            save_callback(task);
        }

        /*
         * Perform the next FSM step.
         * tk_action may be NULL when the task has been killed
         * by someone else.
         */
        if (!RPC_IS_QUEUED(task)) {
            if (task->tk_action == NULL)
                break;
            task->tk_action(task);
        }

        /*
         * Lockless check for whether task is sleeping or not.
         */
        if (!RPC_IS_QUEUED(task))
            continue;
        /*
         * The queue->lock protects against races with
         * rpc_make_runnable().
         *
         * Note that once we clear RPC_TASK_RUNNING on an asynchronous
         * rpc_task, rpc_make_runnable() can assign it to a
         * different workqueue. We therefore cannot assume that the
         * rpc_task pointer may still be dereferenced.
         */
        queue = task->tk_waitqueue;
        spin_lock_bh(&queue->lock);
        if (!RPC_IS_QUEUED(task)) {
            spin_unlock_bh(&queue->lock);
            continue;
        }
        rpc_clear_running(task);
        spin_unlock_bh(&queue->lock);
        if (task_is_async)
            return;


        /* sync task: sleep here */
        dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
        status = out_of_line_wait_on_bit(&task->tk_runstate,
                RPC_TASK_QUEUED, rpc_wait_bit_killable,
                TASK_KILLABLE);
        if (status == -ERESTARTSYS) {
            /*
             * When a sync task receives a signal, it exits with
             * -ERESTARTSYS. In order to catch any callbacks that
             * clean up after sleeping on some queue, we don't
             * break the loop here, but go around once more.
             */
            dprintk("RPC: %5u got signal\n", task->tk_pid);
            task->tk_flags |= RPC_TASK_KILLED;
            rpc_exit(task, -ERESTARTSYS);
            rpc_wake_up_task(task);
        }
        rpc_set_running(task);
        dprintk("RPC: %5u sync task resuming\n", task->tk_pid);
    }

    dprintk("RPC: %5u return %d, status %d\n", task->tk_pid, status,
            task->tk_status);
    /* Release all resources associated with the task */
    rpc_release_task(task);
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
03-03 1791

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值