On Fri, Oct 16 2020 at 17:13, Jens Axboe wrote: > /** > * task_work_add - ask the @task to execute @work->func() > * @task: the task which should run the callback > * @work: the callback to run > * @notify: how to notify the targeted task > * > * Queue @work for task_work_run() below and notify the @task if @notify > * is @TWA_RESUME or @TWA_SIGNAL. @TWA_SIGNAL work like signals, in that the
s/the// > * it will interrupt the targeted task and run the task_work. @TWA_RESUME > * work is run only when the task exits the kernel and returns to user mode. > * Fails if the @task is exiting/exited and thus it can't process this @work. > * Otherwise @work->func() will be called when the @task returns from kernel > * mode or exits. Yes, that makes a lot more sense. What's still lacking is a description of the return value and how to act upon it. Most of the call sites ignore it, some are acting upon it but I can't make any sense of these actions: fs/io_uring.c- notify = 0; fs/io_uring.c- if (!(ctx->flags & IORING_SETUP_SQPOLL) && twa_signal_ok) fs/io_uring.c- notify = TWA_SIGNAL; fs/io_uring.c- fs/io_uring.c: ret = task_work_add(tsk, &req->task_work, notify); fs/io_uring.c- if (!ret) fs/io_uring.c- wake_up_process(tsk); ??? fs/io_uring.c- if (unlikely(ret)) { fs/io_uring.c- struct task_struct *tsk; fs/io_uring.c- fs/io_uring.c- init_task_work(&req->task_work, io_req_task_cancel); fs/io_uring.c- tsk = io_wq_get_task(req->ctx->io_wq); fs/io_uring.c: task_work_add(tsk, &req->task_work, 0); fs/io_uring.c- wake_up_process(tsk); yet more magic wakeup. fs/io_uring.c- fs/io_uring.c- init_task_work(&req->task_work, io_req_task_submit); fs/io_uring.c- percpu_ref_get(&req->ctx->refs); fs/io_uring.c- fs/io_uring.c- /* submit ref gets dropped, acquire a new one */ fs/io_uring.c- refcount_inc(&req->refs); fs/io_uring.c: ret = io_req_task_work_add(req, true); fs/io_uring.c- if (unlikely(ret)) { fs/io_uring.c- struct task_struct *tsk; fs/io_uring.c- fs/io_uring.c- /* queue just for cancelation */ fs/io_uring.c- init_task_work(&req->task_work, io_req_task_cancel); fs/io_uring.c- tsk = io_wq_get_task(req->ctx->io_wq); fs/io_uring.c: task_work_add(tsk, &req->task_work, 0); fs/io_uring.c- wake_up_process(tsk); Ditto. Why the heck is this wakeup making any sense? The initial task_work_add() within io_req_task_work_add() failed already ... fs/io_uring.c: ret = io_req_task_work_add(req, twa_signal_ok); fs/io_uring.c- if (unlikely(ret)) { fs/io_uring.c- struct task_struct *tsk; fs/io_uring.c- fs/io_uring.c- WRITE_ONCE(poll->canceled, true); fs/io_uring.c- tsk = io_wq_get_task(req->ctx->io_wq); fs/io_uring.c: task_work_add(tsk, &req->task_work, 0); fs/io_uring.c- wake_up_process(tsk); ... Thanks, tglx