4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
30 #pragma ident "%Z%%M% %I% %E% SMI"
41 #include <sys/types.h>
51 #include <sys/asynch.h>
55 #define AIOSTKSIZE (64 * 1024)
57 #define AIOSTKSIZE (128 * 1024)
60 #define SIGAIOCANCEL SIGLWP /* special aio cancelation signal */
62 #define AIO_WAITN_MAXIOCBS 32768 /* max. iocbs per system call */
65 * Declare structure types. The structures themselves are defined below.
67 typedef struct aio_args aio_args_t
;
68 typedef struct aio_lio aio_lio_t
;
69 typedef struct notif_param notif_param_t
;
70 typedef struct aio_req aio_req_t
;
71 typedef struct aio_worker aio_worker_t
;
72 typedef struct aio_hash aio_hash_t
;
82 * list head for UFS list I/O
85 mutex_t lio_mutex
; /* list mutex */
86 cond_t lio_cond_cv
; /* list notification for I/O done */
87 aio_lio_t
*lio_next
; /* pointer to next on freelist */
88 char lio_mode
; /* LIO_WAIT/LIO_NOWAIT */
89 char lio_canned
; /* lio was canceled */
90 char lio_largefile
; /* largefile operation */
91 char lio_waiting
; /* waiting in __lio_listio() */
92 int lio_nent
; /* Number of list I/O's */
93 int lio_refcnt
; /* outstanding I/O's */
94 int lio_event
; /* Event number for notification */
95 int lio_port
; /* Port number for notification */
96 int lio_signo
; /* Signal number for notification */
97 union sigval lio_sigval
; /* Signal parameter */
98 uintptr_t lio_object
; /* for SIGEV_THREAD or SIGEV_PORT */
99 struct sigevent
*lio_sigevent
; /* Notification function and attr. */
103 * Notification parameters
106 int np_signo
; /* SIGEV_SIGNAL */
107 int np_port
; /* SIGEV_THREAD or SIGEV_PORT */
111 int np_lio_signo
; /* listio: SIGEV_SIGNAL */
112 int np_lio_port
; /* listio: SIGEV_THREAD or SIGEV_PORT */
115 uintptr_t np_lio_object
;
120 * fields protected by _aio_mutex lock.
122 aio_req_t
*req_link
; /* hash/freelist chain link */
124 * when req is on the doneq, then req_next is protected by
125 * the _aio_mutex lock. when the req is on a work q, then
126 * req_next is protected by a worker's work_qlock1 lock.
128 aio_req_t
*req_next
; /* request/done queue link */
129 aio_req_t
*req_prev
; /* double linked list */
131 * fields protected by a worker's work_qlock1 lock.
133 char req_state
; /* AIO_REQ_QUEUED, ... */
135 * fields require no locking.
137 char req_type
; /* AIO_POSIX_REQ or not */
138 char req_largefile
; /* largefile operation */
139 char req_op
; /* AIOREAD, etc. */
140 aio_worker_t
*req_worker
; /* associate request with worker */
141 aio_result_t
*req_resultp
; /* address of result buffer */
142 aio_args_t req_args
; /* arglist */
143 aio_lio_t
*req_head
; /* list head for LIO */
144 struct sigevent req_sigevent
;
145 void *req_aiocbp
; /* ptr to aiocb or aiocb64 */
146 notif_param_t req_notify
; /* notification parameters */
149 /* special lio type that destroys itself when lio refcnt becomes zero */
150 #define LIO_FSYNC LIO_WAIT+1
151 #define LIO_DESTROY LIO_FSYNC+1
154 #define LIO_FSYNC_CANCELED 0x1
156 /* values for aio_state */
158 #define AIO_REQ_QUEUED 1
159 #define AIO_REQ_INPROGRESS 2
160 #define AIO_REQ_CANCELED 3
161 #define AIO_REQ_DONE 4
162 #define AIO_REQ_FREE 5
163 #define AIO_REQ_DONEQ 6
165 /* use KAIO in _aio_rw() */
166 #define AIO_NO_KAIO 0x0
168 #define AIO_NO_DUPS 0x2
170 #define AIO_POSIX_REQ 0x1
176 #define USERAIO_DONE 5
178 /* values for _aio_flags */
180 /* if set, _aiodone() notifies aio_waitn about done requests */
181 #define AIO_WAIT_INPROGRESS 0x1
182 /* if set, _aiodone() wakes up functions waiting for completed I/Os */
183 #define AIO_IO_WAITING 0x2
184 #define AIO_LIB_WAITN 0x4 /* aio_waitn in progress */
185 #define AIO_LIB_WAITN_PENDING 0x8 /* aio_waitn requests pending */
188 * Before a kaio() system call, the fd will be checked
189 * to ensure that kernel async. I/O is supported for this file.
190 * The only way to find out is if a kaio() call returns ENOTSUP,
191 * so the default will always be to try the kaio() call. Only in
192 * the specific instance of a kaio() call returning ENOTSUP
193 * will we stop submitting kaio() calls for that fd.
194 * If the fd is outside the array bounds, we will allow the kaio()
197 * The only way that an fd entry can go from ENOTSUP to supported
198 * is if that fd is freed up by a close(), and close will clear
199 * the entry for that fd.
201 * Each fd gets a bit in the array _kaio_supported[].
203 * uint32_t _kaio_supported[MAX_KAIO_FDARRAY_SIZE];
205 * Array is MAX_KAIO_ARRAY_SIZE of 32-bit elements, for 8kb.
206 * If more than (MAX_KAIO_FDARRAY_SIZE * KAIO_FDARRAY_ELEM_SIZE)
207 * files are open, this can be expanded.
210 #define MAX_KAIO_FDARRAY_SIZE 2048
211 #define KAIO_FDARRAY_ELEM_SIZE WORD_BIT /* uint32_t */
213 #define MAX_KAIO_FDS (MAX_KAIO_FDARRAY_SIZE * KAIO_FDARRAY_ELEM_SIZE)
215 #define VALID_FD(fdes) ((fdes) >= 0 && (fdes) < MAX_KAIO_FDS)
217 #define KAIO_SUPPORTED(fdes) \
218 (!VALID_FD(fdes) || \
219 ((_kaio_supported[(fdes) / KAIO_FDARRAY_ELEM_SIZE] & \
220 (uint32_t)(1 << ((fdes) % KAIO_FDARRAY_ELEM_SIZE))) == 0))
222 #define SET_KAIO_NOT_SUPPORTED(fdes) \
223 if (VALID_FD(fdes)) \
224 _kaio_supported[(fdes) / KAIO_FDARRAY_ELEM_SIZE] |= \
225 (uint32_t)(1 << ((fdes) % KAIO_FDARRAY_ELEM_SIZE))
227 #define CLEAR_KAIO_SUPPORTED(fdes) \
228 if (VALID_FD(fdes)) \
229 _kaio_supported[(fdes) / KAIO_FDARRAY_ELEM_SIZE] &= \
230 ~(uint32_t)(1 << ((fdes) % KAIO_FDARRAY_ELEM_SIZE))
233 aio_worker_t
*work_forw
; /* forward link in list of workers */
234 aio_worker_t
*work_backw
; /* backwards link in list of workers */
235 mutex_t work_qlock1
; /* lock for work queue 1 */
236 cond_t work_idle_cv
; /* place to sleep when idle */
237 aio_req_t
*work_head1
; /* head of work request queue 1 */
238 aio_req_t
*work_tail1
; /* tail of work request queue 1 */
239 aio_req_t
*work_next1
; /* work queue one's next pointer */
240 aio_req_t
*work_prev1
; /* last request done from queue 1 */
241 aio_req_t
*work_req
; /* active work request */
242 thread_t work_tid
; /* worker's thread-id */
243 int work_count1
; /* length of work queue one */
244 int work_done1
; /* number of requests done */
245 int work_minload1
; /* min length of queue */
246 int work_idleflg
; /* when set, worker is idle */
247 sigjmp_buf work_jmp_buf
; /* cancellation point */
250 struct aio_hash
{ /* resultp hash table */
254 void *hash_pad
; /* ensure sizeof (aio_hash_t) == 32 */
258 extern aio_hash_t
*_aio_hash
;
260 #define HASHSZ 2048 /* power of 2 */
261 #define AIOHASH(resultp) ((((uintptr_t)(resultp) >> 17) ^ \
262 ((uintptr_t)(resultp) >> 2)) & (HASHSZ - 1))
263 #define POSIX_AIO(x) ((x)->req_type == AIO_POSIX_REQ)
265 extern int __uaio_init(void);
266 extern void _kaio_init(void);
267 extern intptr_t _kaio(int, ...);
268 extern int _aiorw(int, caddr_t
, int, offset_t
, int, aio_result_t
*, int);
269 extern int _aio_rw(aiocb_t
*, aio_lio_t
*, aio_worker_t
**, int, int);
271 extern int _aio_rw64(aiocb64_t
*, aio_lio_t
*, aio_worker_t
**, int, int);
273 extern int _aio_create_worker(aio_req_t
*, int);
274 extern int _aio_cancel_req(aio_worker_t
*, aio_req_t
*, int *, int *);
275 extern int aiocancel_all(int);
276 extern void aio_panic(const char *);
277 extern aio_req_t
*_aio_hash_find(aio_result_t
*);
278 extern aio_req_t
*_aio_hash_del(aio_result_t
*);
279 extern void _aio_req_mark_done(aio_req_t
*);
280 extern void _aio_waitn_wakeup(void);
281 extern aio_worker_t
*_aio_worker_alloc(void);
282 extern void _aio_worker_free(void *);
283 extern aio_req_t
*_aio_req_alloc(void);
284 extern void _aio_req_free(aio_req_t
*);
285 extern aio_lio_t
*_aio_lio_alloc(void);
286 extern void _aio_lio_free(aio_lio_t
*);
287 extern int _aio_idle(aio_worker_t
*);
288 extern void *_aio_do_request(void *);
289 extern void *_aio_do_notify(void *);
290 extern void _lio_remove(aio_req_t
*);
291 extern aio_req_t
*_aio_req_remove(aio_req_t
*);
292 extern int _aio_get_timedelta(timespec_t
*, timespec_t
*);
293 extern aio_result_t
*_aio_req_done(void);
294 extern void _aio_set_result(aio_req_t
*, ssize_t
, int);
295 extern int _aio_sigev_thread_init(struct sigevent
*);
296 extern int _aio_sigev_thread(aiocb_t
*);
298 extern int _aio_sigev_thread64(aiocb64_t
*);
301 extern aio_worker_t
*_kaiowp
; /* points to kaio cleanup thread */
302 extern aio_worker_t
*__workers_rw
; /* list of all rw workers */
303 extern aio_worker_t
*__nextworker_rw
; /* worker chosen for next rw request */
304 extern int __rw_workerscnt
; /* number of rw workers */
305 extern aio_worker_t
*__workers_no
; /* list of all notification workers */
306 extern aio_worker_t
*__nextworker_no
; /* worker chosen, next notification */
307 extern int __no_workerscnt
; /* number of notification workers */
308 extern mutex_t __aio_initlock
; /* makes aio initialization atomic */
309 extern cond_t __aio_initcv
;
310 extern int __aio_initbusy
;
311 extern mutex_t __aio_mutex
; /* global aio lock */
312 extern cond_t _aio_iowait_cv
; /* wait for userland I/Os */
313 extern cond_t _aio_waitn_cv
; /* wait for end of aio_waitn */
314 extern int _max_workers
; /* max number of workers permitted */
315 extern int _min_workers
; /* min number of workers */
316 extern sigset_t _worker_set
; /* worker's signal mask */
317 extern int _aio_worker_cnt
; /* number of AIO workers */
318 extern int _sigio_enabled
; /* when set, send SIGIO signal */
319 extern pid_t __pid
; /* process's PID */
320 extern int __uaio_ok
; /* indicates if aio is initialized */
321 extern int _kaio_ok
; /* indicates if kaio is initialized */
322 extern pthread_key_t _aio_key
; /* for thread-specific data */
323 extern aio_req_t
*_aio_done_tail
; /* list of done requests */
324 extern aio_req_t
*_aio_done_head
;
325 extern aio_req_t
*_aio_doneq
;
326 extern int _aio_freelist_cnt
;
327 extern int _aio_allocated_cnt
;
328 extern int _aio_donecnt
;
329 extern int _aio_doneq_cnt
;
330 extern int _aio_waitncnt
; /* # of requests for aio_waitn */
331 extern int _aio_outstand_cnt
; /* # of outstanding requests */
332 extern int _kaio_outstand_cnt
; /* # of outstanding kaio requests */
333 extern int _aio_req_done_cnt
; /* req. done but not in "done queue" */
334 extern int _aio_kernel_suspend
; /* active kernel kaio calls */
335 extern int _aio_suscv_cnt
; /* aio_suspend calls waiting on cv's */
336 extern int _aiowait_flag
; /* when set, aiowait() is inprogress */
337 extern int _aio_flags
; /* see defines, above */
338 extern uint32_t *_kaio_supported
;
340 extern const sigset_t maskset
; /* all maskable signals */
346 #endif /* _ASYNCIO_H */