Home | History | Annotate | Line # | Download | only in sys
      1 /*	$NetBSD: aio.h,v 1.14 2025/10/10 15:53:55 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2025 The NetBSD Foundation, Inc.
      5  * Copyright (c) 2007, Mindaugas Rasiukevicius <rmind at NetBSD org>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #ifndef _SYS_AIO_H_
     31 #define _SYS_AIO_H_
     32 
     33 #include <sys/types.h>
     34 #include <sys/signal.h>
     35 #include <sys/tree.h>
     36 
     37 /* Returned by aio_cancel() */
     38 #define AIO_CANCELED		0x1
     39 #define AIO_NOTCANCELED		0x2
     40 #define AIO_ALLDONE		0x3
     41 
     42 /* LIO opcodes */
     43 #define LIO_NOP			0x0
     44 #define LIO_WRITE		0x1
     45 #define LIO_READ		0x2
     46 
     47 /* LIO modes */
     48 #define LIO_NOWAIT		0x0
     49 #define LIO_WAIT		0x1
     50 
     51 /*
     52  * Asynchronous I/O structure.
     53  * Defined in the Base Definitions volume of IEEE Std 1003.1-2001 .
     54  */
     55 struct aiocb {
     56 	off_t aio_offset;		/* File offset */
     57 	void *aio_buf;			/* I/O buffer in process space */
     58 	size_t aio_nbytes;		/* Length of transfer */
     59 	int aio_fildes;			/* File descriptor */
     60 	int aio_lio_opcode;		/* LIO opcode */
     61 	int aio_reqprio;		/* Request priority offset */
     62 	struct sigevent aio_sigevent;	/* Signal to deliver */
     63 
     64 	/* Internal kernel variables */
     65 	int _state;			/* State of the job */
     66 	int _errno;			/* Error value */
     67 	ssize_t _retval;		/* Return value */
     68 };
     69 
     70 /* Internal kernel data */
     71 #ifdef _KERNEL
     72 
     73 /* Default limits of allowed AIO operations */
     74 #define AIO_LISTIO_MAX		512
     75 #define AIO_MAX			(AIO_LISTIO_MAX * 16)
     76 
     77 #include <sys/condvar.h>
     78 #include <sys/lwp.h>
     79 #include <sys/mutex.h>
     80 #include <sys/pool.h>
     81 #include <sys/queue.h>
     82 
     83 /* Operations (as flags) */
     84 #define AIO_LIO			0x00
     85 #define AIO_READ		0x01
     86 #define AIO_WRITE		0x02
     87 #define AIO_SYNC		0x04
     88 #define AIO_DSYNC		0x08
     89 
     90 /* Job states */
     91 #define JOB_NONE		0x0
     92 #define JOB_WIP			0x1
     93 #define JOB_DONE		0x2
     94 
     95 /* Structure for tracking the status of a collection of OPS */
     96 struct aiowaitgroup {
     97 	kmutex_t mtx;		/* Protects entire structure */
     98 	kcondvar_t done_cv;	/* Signaled when job completes */
     99 	size_t completed;	/* Number of completed jobs in this wait group */
    100 	size_t total;		/* Total jobs being waited on */
    101 	bool active;		/* False after suspend returns/times out */
    102 	int refcnt;		/* Reference count */
    103 };
    104 
    105 /* */
    106 struct aiowaitgrouplk {
    107 	kmutex_t mtx;	/* Protects wgs array modifications */
    108 	void **wgs;	/* Dynamic array of waiting aiowaitgroups */
    109 	size_t s;	/* Allocated size of wgs array */
    110 	size_t n;	/* Current number of waitgroups */
    111 };
    112 
    113 /* Structure of AIO job */
    114 struct aiost;
    115 struct buf;
    116 struct aio_job {
    117 	kmutex_t mtx;		/* Protects completed flag */
    118 	int aio_op;		/* Operation type (AIO_READ/WRITE/SYNC) */
    119 	struct aiocb aiocbp;	/* User-visible AIO control block */
    120 	void *aiocb_uptr;	/* User pointer for job identification */
    121 	struct proc *p;		/* Originating process */
    122 	bool completed;		/* Job completion status */
    123 	bool on_queue;		/* Whether or not this job is on sp->jobs */
    124 	struct file *fp;	/* File pointer associated with the job */
    125 	struct aiowaitgrouplk lk; /* List of waitgroups waiting on this job */
    126 	TAILQ_ENTRY(aio_job) list;
    127 	struct lio_req *lio;	/* List I/O request (if part of lio_listio) */
    128 };
    129 
    130 #define AIOST_STATE_NONE	0x1
    131 #define AIOST_STATE_OPERATION	0x2
    132 #define AIOST_STATE_TERMINATE	0x4
    133 
    134 #define AIOSP_SUSPEND_ANY	0x1
    135 #define AIOSP_SUSPEND_ALL	0x2
    136 
    137 struct aiost;
    138 struct aiost_file_group {
    139 	RB_ENTRY(aiost_file_group) tree;
    140 	struct file *fp;
    141 	struct aiost *aiost;
    142 	kmutex_t mtx;
    143 	TAILQ_HEAD(, aio_job) queue;
    144 	size_t queue_size;
    145 };
    146 
    147 /* Structure for AIO servicing thread */
    148 struct aiosp;
    149 struct aiost {
    150 	TAILQ_ENTRY(aiost) list;
    151 	struct aiosp *aiosp;		/* Servicing pool of this thread */
    152 	kmutex_t mtx;			/* Protects this structure */
    153 	kcondvar_t service_cv;		/* Signal to activate thread */
    154 	struct lwp *lwp;		/* Servicing thread LWP */
    155 	int state;			/* The state of the thread */
    156 	bool freelist;			/* Whether or not aiost is on freelist */
    157 	struct aiost_file_group *fg;	/* File group associated with the thread */
    158 	struct aio_job *job;		/* Singleton job */
    159 };
    160 
    161 struct aiocbp {
    162 	TAILQ_ENTRY(aiocbp) list;
    163 	const void *uptr;
    164 	struct aio_job *job;
    165 };
    166 
    167 /* Structure for AIO servicing pool */
    168 TAILQ_HEAD(aiost_list, aiost);
    169 TAILQ_HEAD(aiocbp_list, aiocbp);
    170 struct aiost_file_tree;
    171 struct aiosp {
    172 	struct aiost_list freelist;	/* Available service threads */
    173 	size_t nthreads_free;		/* Length of freelist */
    174 	struct aiost_list active;	/* Active servicing threads */
    175 	size_t nthreads_active;		/* length of active list */
    176 	TAILQ_HEAD(, aio_job) jobs;	/* Queue of pending jobs */
    177 	size_t jobs_pending;		/* Number of pending jobs */
    178 	kmutex_t mtx;			/* Protects structure */
    179 	size_t nthreads_total;		/* Number of total servicing threads */
    180 	volatile u_long njobs_processing;/* Number of total jobs currently being processed*/
    181 	struct aiocbp_list *aio_hash;	/* Aiocbp hash root */
    182 	kmutex_t aio_hash_mtx;		/* Protects the hash table */
    183 	size_t aio_hash_size;		/* Total number of buckets */
    184 	u_int aio_hash_mask;		/* Hash mask */
    185 	struct aiost_file_tree *fg_root;/* RB tree of file groups */
    186 };
    187 
    188 /* LIO structure */
    189 struct lio_req {
    190 	u_int refcnt;		/* Reference counter */
    191 	struct sigevent sig;	/* Signal of lio_listio() calls */
    192 };
    193 
    194 /* Structure of AIO data for process */
    195 struct aioproc {
    196 	kmutex_t aio_mtx;		/* Protects the entire structure */
    197 	unsigned int jobs_count;	/* Count of the jobs */
    198 	struct aiosp aiosp;		/* Per-process service pool */
    199 };
    200 
    201 extern u_int aio_listio_max;
    202 
    203 /*
    204  * Prototypes
    205  */
    206 
    207 void	aio_print_jobs(void (*)(const char *, ...) __printflike(1, 2));
    208 int	aio_suspend1(struct lwp *, struct aiocb **, int, struct timespec *);
    209 
    210 int	aiosp_initialize(struct aiosp *);
    211 int	aiosp_destroy(struct aiosp *, int *);
    212 int	aiosp_distribute_jobs(struct aiosp *);
    213 int	aiosp_enqueue_job(struct aiosp *, struct aio_job *);
    214 int	aiosp_suspend(struct aiosp *, struct aiocb **, int, struct timespec *,
    215 		int);
    216 int	aiosp_flush(struct aiosp *);
    217 int	aiosp_validate_conflicts(struct aiosp *, const void *);
    218 int	aiosp_error(struct aiosp *, const void *, register_t *);
    219 int	aiosp_return(struct aiosp *, const void *, register_t *);
    220 
    221 void	aiowaitgroup_init(struct aiowaitgroup *);
    222 void	aiowaitgroup_fini(struct aiowaitgroup *);
    223 int	aiowaitgroup_wait(struct aiowaitgroup *, int);
    224 void	aiowaitgroup_done(struct aiowaitgroup *);
    225 void	aiowaitgroup_join(struct aiowaitgroup *, struct aiowaitgrouplk *);
    226 void	aiowaitgrouplk_init(struct aiowaitgrouplk *);
    227 void	aiowaitgrouplk_fini(struct aiowaitgrouplk *);
    228 void	aiowaitgrouplk_flush(struct aiowaitgrouplk *);
    229 
    230 
    231 #endif /* _KERNEL */
    232 
    233 #endif /* _SYS_AIO_H_ */
    234