io_uring/futex.c

Source file repositories/reference/linux-study-clean/io_uring/futex.c

File Facts

System
Linux kernel
Corpus path
io_uring/futex.c
Extension
.c
Size
8701 bytes
Lines
337
Domain
Kernel Services
Bucket
io_uring
Inferred role
Kernel Services: implementation source
Status
source implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

struct io_futex {
	struct file	*file;
	void __user	*uaddr;
	unsigned long	futex_val;
	unsigned long	futex_mask;
	u32		futex_flags;
	unsigned int	futex_nr;
	bool		futexv_unqueued;
};

struct io_futex_data {
	struct futex_q	q;
	struct io_kiocb	*req;
};

struct io_futexv_data {
	unsigned long		owned;
	struct futex_vector	futexv[];
};

#define IO_FUTEX_ALLOC_CACHE_MAX	32

bool io_futex_cache_init(struct io_ring_ctx *ctx)
{
	return io_alloc_cache_init(&ctx->futex_cache, IO_FUTEX_ALLOC_CACHE_MAX,
				sizeof(struct io_futex_data), 0);
}

void io_futex_cache_free(struct io_ring_ctx *ctx)
{
	io_alloc_cache_free(&ctx->futex_cache, kfree);
}

static void __io_futex_complete(struct io_tw_req tw_req, io_tw_token_t tw)
{
	hlist_del_init(&tw_req.req->hash_node);
	io_req_task_complete(tw_req, tw);
}

static void io_futex_complete(struct io_tw_req tw_req, io_tw_token_t tw)
{
	struct io_kiocb *req = tw_req.req;
	struct io_ring_ctx *ctx = req->ctx;

	io_tw_lock(ctx, tw);
	io_cache_free(&ctx->futex_cache, req->async_data);
	io_req_async_data_clear(req, 0);
	__io_futex_complete(tw_req, tw);
}

static void io_futexv_complete(struct io_tw_req tw_req, io_tw_token_t tw)
{
	struct io_kiocb *req = tw_req.req;
	struct io_futex *iof = io_kiocb_to_cmd(req, struct io_futex);
	struct io_futexv_data *ifd = req->async_data;

	io_tw_lock(req->ctx, tw);

	if (!iof->futexv_unqueued) {
		int res;

		res = futex_unqueue_multiple(ifd->futexv, iof->futex_nr);
		if (res != -1)
			io_req_set_res(req, res, 0);
	}

	io_req_async_data_free(req);
	__io_futex_complete(tw_req, tw);
}

static bool io_futexv_claim(struct io_futexv_data *ifd)
{
	if (test_bit(0, &ifd->owned) || test_and_set_bit_lock(0, &ifd->owned))
		return false;
	return true;
}

static bool __io_futex_cancel(struct io_kiocb *req)
{
	/* futex wake already done or in progress */
	if (req->opcode == IORING_OP_FUTEX_WAIT) {
		struct io_futex_data *ifd = req->async_data;

		if (!futex_unqueue(&ifd->q))
			return false;
		req->io_task_work.func = io_futex_complete;
	} else {
		struct io_futexv_data *ifd = req->async_data;

		if (!io_futexv_claim(ifd))

Annotation

Implementation Notes