10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51885Sraf * Common Development and Distribution License (the "License"). 61885Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211885Sraf 220Sstevel@tonic-gate /* 23*4532Ssp92102 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/proc.h> 310Sstevel@tonic-gate #include <sys/file.h> 320Sstevel@tonic-gate #include <sys/errno.h> 330Sstevel@tonic-gate #include <sys/param.h> 340Sstevel@tonic-gate #include <sys/sysmacros.h> 350Sstevel@tonic-gate #include <sys/cmn_err.h> 360Sstevel@tonic-gate #include <sys/systm.h> 370Sstevel@tonic-gate #include <vm/as.h> 380Sstevel@tonic-gate #include <vm/page.h> 390Sstevel@tonic-gate #include <sys/uio.h> 400Sstevel@tonic-gate #include <sys/kmem.h> 410Sstevel@tonic-gate #include <sys/debug.h> 420Sstevel@tonic-gate #include <sys/aio_impl.h> 430Sstevel@tonic-gate #include <sys/epm.h> 440Sstevel@tonic-gate #include <sys/fs/snode.h> 450Sstevel@tonic-gate #include <sys/siginfo.h> 460Sstevel@tonic-gate #include <sys/cpuvar.h> 470Sstevel@tonic-gate #include <sys/tnf_probe.h> 480Sstevel@tonic-gate #include <sys/conf.h> 490Sstevel@tonic-gate #include <sys/sdt.h> 500Sstevel@tonic-gate 510Sstevel@tonic-gate int aphysio(int (*)(), int (*)(), dev_t, int, void (*)(), struct aio_req *); 520Sstevel@tonic-gate void aio_done(struct buf *); 530Sstevel@tonic-gate void aphysio_unlock(aio_req_t *); 540Sstevel@tonic-gate void aio_cleanup(int); 550Sstevel@tonic-gate void aio_cleanup_exit(void); 560Sstevel@tonic-gate 570Sstevel@tonic-gate /* 580Sstevel@tonic-gate * private functions 590Sstevel@tonic-gate */ 600Sstevel@tonic-gate static void aio_sigev_send(proc_t *, sigqueue_t *); 610Sstevel@tonic-gate static void aio_hash_delete(aio_t *, aio_req_t *); 620Sstevel@tonic-gate static void aio_lio_free(aio_t *, aio_lio_t *); 630Sstevel@tonic-gate static void aio_cleanup_cleanupq(aio_t *, aio_req_t *, int); 640Sstevel@tonic-gate static int aio_cleanup_notifyq(aio_t *, aio_req_t *, int); 650Sstevel@tonic-gate static void aio_cleanup_pollq(aio_t *, aio_req_t *, int); 660Sstevel@tonic-gate static void aio_cleanup_portq(aio_t *, aio_req_t *, int); 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * async version of physio() that doesn't wait synchronously 700Sstevel@tonic-gate * for the driver's strategy routine to complete. 710Sstevel@tonic-gate */ 720Sstevel@tonic-gate 730Sstevel@tonic-gate int 740Sstevel@tonic-gate aphysio( 750Sstevel@tonic-gate int (*strategy)(struct buf *), 760Sstevel@tonic-gate int (*cancel)(struct buf *), 770Sstevel@tonic-gate dev_t dev, 780Sstevel@tonic-gate int rw, 790Sstevel@tonic-gate void (*mincnt)(struct buf *), 800Sstevel@tonic-gate struct aio_req *aio) 810Sstevel@tonic-gate { 820Sstevel@tonic-gate struct uio *uio = aio->aio_uio; 830Sstevel@tonic-gate aio_req_t *reqp = (aio_req_t *)aio->aio_private; 840Sstevel@tonic-gate struct buf *bp = &reqp->aio_req_buf; 850Sstevel@tonic-gate struct iovec *iov; 860Sstevel@tonic-gate struct as *as; 870Sstevel@tonic-gate char *a; 880Sstevel@tonic-gate int error; 890Sstevel@tonic-gate size_t c; 900Sstevel@tonic-gate struct page **pplist; 910Sstevel@tonic-gate struct dev_ops *ops = devopsp[getmajor(dev)]; 920Sstevel@tonic-gate 930Sstevel@tonic-gate if (uio->uio_loffset < 0) 940Sstevel@tonic-gate return (EINVAL); 950Sstevel@tonic-gate #ifdef _ILP32 960Sstevel@tonic-gate /* 970Sstevel@tonic-gate * For 32-bit kernels, check against SPEC_MAXOFFSET_T which represents 980Sstevel@tonic-gate * the maximum size that can be supported by the IO subsystem. 990Sstevel@tonic-gate * XXX this code assumes a D_64BIT driver. 1000Sstevel@tonic-gate */ 1010Sstevel@tonic-gate if (uio->uio_loffset > SPEC_MAXOFFSET_T) 1020Sstevel@tonic-gate return (EINVAL); 1030Sstevel@tonic-gate #endif /* _ILP32 */ 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate TNF_PROBE_5(aphysio_start, "kaio", /* CSTYLED */, 1060Sstevel@tonic-gate tnf_opaque, bp, bp, 1070Sstevel@tonic-gate tnf_device, device, dev, 1080Sstevel@tonic-gate tnf_offset, blkno, btodt(uio->uio_loffset), 1090Sstevel@tonic-gate tnf_size, size, uio->uio_iov->iov_len, 1100Sstevel@tonic-gate tnf_bioflags, rw, rw); 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate if (rw == B_READ) { 1130Sstevel@tonic-gate CPU_STATS_ADD_K(sys, phread, 1); 1140Sstevel@tonic-gate } else { 1150Sstevel@tonic-gate CPU_STATS_ADD_K(sys, phwrite, 1); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate iov = uio->uio_iov; 1190Sstevel@tonic-gate sema_init(&bp->b_sem, 0, NULL, SEMA_DEFAULT, NULL); 1200Sstevel@tonic-gate sema_init(&bp->b_io, 0, NULL, SEMA_DEFAULT, NULL); 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate bp->b_error = 0; 1230Sstevel@tonic-gate bp->b_flags = B_BUSY | B_PHYS | B_ASYNC | rw; 1240Sstevel@tonic-gate bp->b_edev = dev; 1250Sstevel@tonic-gate bp->b_dev = cmpdev(dev); 1260Sstevel@tonic-gate bp->b_lblkno = btodt(uio->uio_loffset); 1270Sstevel@tonic-gate bp->b_offset = uio->uio_loffset; 1280Sstevel@tonic-gate (void) ops->devo_getinfo(NULL, DDI_INFO_DEVT2DEVINFO, 1290Sstevel@tonic-gate (void *)bp->b_edev, (void **)&bp->b_dip); 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* 1320Sstevel@tonic-gate * Clustering: Clustering can set the b_iodone, b_forw and 1330Sstevel@tonic-gate * b_proc fields to cluster-specifc values. 1340Sstevel@tonic-gate */ 1350Sstevel@tonic-gate if (bp->b_iodone == NULL) { 1360Sstevel@tonic-gate bp->b_iodone = (int (*)()) aio_done; 1370Sstevel@tonic-gate /* b_forw points at an aio_req_t structure */ 1380Sstevel@tonic-gate bp->b_forw = (struct buf *)reqp; 1390Sstevel@tonic-gate bp->b_proc = curproc; 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate a = bp->b_un.b_addr = iov->iov_base; 1430Sstevel@tonic-gate c = bp->b_bcount = iov->iov_len; 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate (*mincnt)(bp); 1460Sstevel@tonic-gate if (bp->b_bcount != iov->iov_len) 1470Sstevel@tonic-gate return (ENOTSUP); 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate as = bp->b_proc->p_as; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate error = as_pagelock(as, &pplist, a, 1520Sstevel@tonic-gate c, rw == B_READ? S_WRITE : S_READ); 1530Sstevel@tonic-gate if (error != 0) { 1540Sstevel@tonic-gate bp->b_flags |= B_ERROR; 1550Sstevel@tonic-gate bp->b_error = error; 1560Sstevel@tonic-gate bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_SHADOW); 1570Sstevel@tonic-gate return (error); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate reqp->aio_req_flags |= AIO_PAGELOCKDONE; 1600Sstevel@tonic-gate bp->b_shadow = pplist; 1610Sstevel@tonic-gate if (pplist != NULL) { 1620Sstevel@tonic-gate bp->b_flags |= B_SHADOW; 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate if (cancel != anocancel) 1660Sstevel@tonic-gate cmn_err(CE_PANIC, 1670Sstevel@tonic-gate "aphysio: cancellation not supported, use anocancel"); 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate reqp->aio_req_cancel = cancel; 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate DTRACE_IO1(start, struct buf *, bp); 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate return ((*strategy)(bp)); 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate /*ARGSUSED*/ 1770Sstevel@tonic-gate int 1780Sstevel@tonic-gate anocancel(struct buf *bp) 1790Sstevel@tonic-gate { 1800Sstevel@tonic-gate return (ENXIO); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate /* 1840Sstevel@tonic-gate * Called from biodone(). 1850Sstevel@tonic-gate * Notify process that a pending AIO has finished. 1860Sstevel@tonic-gate */ 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * Clustering: This function is made non-static as it is used 1900Sstevel@tonic-gate * by clustering s/w as contract private interface. 1910Sstevel@tonic-gate */ 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate void 1940Sstevel@tonic-gate aio_done(struct buf *bp) 1950Sstevel@tonic-gate { 1960Sstevel@tonic-gate proc_t *p; 1970Sstevel@tonic-gate struct as *as; 1980Sstevel@tonic-gate aio_req_t *reqp; 1991885Sraf aio_lio_t *head = NULL; 2000Sstevel@tonic-gate aio_t *aiop; 2011885Sraf sigqueue_t *sigev = NULL; 2020Sstevel@tonic-gate sigqueue_t *lio_sigev = NULL; 2031885Sraf port_kevent_t *pkevp = NULL; 2041885Sraf port_kevent_t *lio_pkevp = NULL; 2050Sstevel@tonic-gate int fd; 2060Sstevel@tonic-gate int cleanupqflag; 2070Sstevel@tonic-gate int pollqflag; 2080Sstevel@tonic-gate int portevpend; 2090Sstevel@tonic-gate void (*func)(); 2101885Sraf int use_port = 0; 211*4532Ssp92102 int reqp_flags = 0; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate p = bp->b_proc; 214*4532Ssp92102 as = p->p_as; 2150Sstevel@tonic-gate reqp = (aio_req_t *)bp->b_forw; 2160Sstevel@tonic-gate fd = reqp->aio_req_fd; 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate TNF_PROBE_5(aphysio_end, "kaio", /* CSTYLED */, 2190Sstevel@tonic-gate tnf_opaque, bp, bp, 2200Sstevel@tonic-gate tnf_device, device, bp->b_edev, 2210Sstevel@tonic-gate tnf_offset, blkno, btodt(reqp->aio_req_uio.uio_loffset), 2220Sstevel@tonic-gate tnf_size, size, reqp->aio_req_uio.uio_iov->iov_len, 2230Sstevel@tonic-gate tnf_bioflags, rw, (bp->b_flags & (B_READ|B_WRITE))); 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * mapout earlier so that more kmem is available when aio is 2270Sstevel@tonic-gate * heavily used. bug #1262082 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate if (bp->b_flags & B_REMAPPED) 2300Sstevel@tonic-gate bp_mapout(bp); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate /* decrement fd's ref count by one, now that aio request is done. */ 2330Sstevel@tonic-gate areleasef(fd, P_FINFO(p)); 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate aiop = p->p_aio; 2360Sstevel@tonic-gate ASSERT(aiop != NULL); 2370Sstevel@tonic-gate 2381885Sraf mutex_enter(&aiop->aio_portq_mutex); 2391885Sraf mutex_enter(&aiop->aio_mutex); 2401885Sraf ASSERT(aiop->aio_pending > 0); 2411885Sraf ASSERT(reqp->aio_req_flags & AIO_PENDING); 2421885Sraf aiop->aio_pending--; 2431885Sraf reqp->aio_req_flags &= ~AIO_PENDING; 244*4532Ssp92102 reqp_flags = reqp->aio_req_flags; 2451885Sraf if ((pkevp = reqp->aio_req_portkev) != NULL) { 2460Sstevel@tonic-gate /* Event port notification is desired for this transaction */ 2470Sstevel@tonic-gate if (reqp->aio_req_flags & AIO_CLOSE_PORT) { 2480Sstevel@tonic-gate /* 2490Sstevel@tonic-gate * The port is being closed and it is waiting for 2500Sstevel@tonic-gate * pending asynchronous I/O transactions to complete. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate portevpend = --aiop->aio_portpendcnt; 2531885Sraf aio_deq(&aiop->aio_portpending, reqp); 2541885Sraf aio_enq(&aiop->aio_portq, reqp, 0); 2550Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2560Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 2571885Sraf port_send_event(pkevp); 2580Sstevel@tonic-gate if (portevpend == 0) 2590Sstevel@tonic-gate cv_broadcast(&aiop->aio_portcv); 2600Sstevel@tonic-gate return; 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate if (aiop->aio_flags & AIO_CLEANUP) { 2640Sstevel@tonic-gate /* 2650Sstevel@tonic-gate * aio_cleanup_thread() is waiting for completion of 2660Sstevel@tonic-gate * transactions. 2670Sstevel@tonic-gate */ 2680Sstevel@tonic-gate mutex_enter(&as->a_contents); 2691885Sraf aio_deq(&aiop->aio_portpending, reqp); 2701885Sraf aio_enq(&aiop->aio_portcleanupq, reqp, 0); 2710Sstevel@tonic-gate cv_signal(&aiop->aio_cleanupcv); 2720Sstevel@tonic-gate mutex_exit(&as->a_contents); 2730Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 2740Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 2750Sstevel@tonic-gate return; 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2781885Sraf aio_deq(&aiop->aio_portpending, reqp); 2791885Sraf aio_enq(&aiop->aio_portq, reqp, 0); 2800Sstevel@tonic-gate 2811885Sraf use_port = 1; 2821885Sraf } else { 2831885Sraf /* 2841885Sraf * when the AIO_CLEANUP flag is enabled for this 2851885Sraf * process, or when the AIO_POLL bit is set for 2861885Sraf * this request, special handling is required. 2871885Sraf * otherwise the request is put onto the doneq. 2881885Sraf */ 2891885Sraf cleanupqflag = (aiop->aio_flags & AIO_CLEANUP); 2901885Sraf pollqflag = (reqp->aio_req_flags & AIO_POLL); 2911885Sraf if (cleanupqflag | pollqflag) { 2921885Sraf 293*4532Ssp92102 if (cleanupqflag) 2941885Sraf mutex_enter(&as->a_contents); 2950Sstevel@tonic-gate 2961885Sraf /* 2971885Sraf * requests with their AIO_POLL bit set are put 2981885Sraf * on the pollq, requests with sigevent structures 2991885Sraf * or with listio heads are put on the notifyq, and 3001885Sraf * the remaining requests don't require any special 3011885Sraf * cleanup handling, so they're put onto the default 3021885Sraf * cleanupq. 3031885Sraf */ 3041885Sraf if (pollqflag) 3051885Sraf aio_enq(&aiop->aio_pollq, reqp, AIO_POLLQ); 3061885Sraf else if (reqp->aio_req_sigqp || reqp->aio_req_lio) 3071885Sraf aio_enq(&aiop->aio_notifyq, reqp, AIO_NOTIFYQ); 3081885Sraf else 3091885Sraf aio_enq(&aiop->aio_cleanupq, reqp, 3101885Sraf AIO_CLEANUPQ); 3110Sstevel@tonic-gate 3121885Sraf if (cleanupqflag) { 3131885Sraf cv_signal(&aiop->aio_cleanupcv); 3141885Sraf mutex_exit(&as->a_contents); 3151885Sraf mutex_exit(&aiop->aio_mutex); 3161885Sraf mutex_exit(&aiop->aio_portq_mutex); 3171885Sraf } else { 3181885Sraf ASSERT(pollqflag); 3191885Sraf /* block aio_cleanup_exit until we're done */ 3201885Sraf aiop->aio_flags |= AIO_DONE_ACTIVE; 3211885Sraf mutex_exit(&aiop->aio_mutex); 3221885Sraf mutex_exit(&aiop->aio_portq_mutex); 3231885Sraf /* 3241885Sraf * let the cleanup processing happen from an AST 3251885Sraf * set an AST on all threads in this process 3261885Sraf */ 3271885Sraf mutex_enter(&p->p_lock); 3281885Sraf set_proc_ast(p); 3291885Sraf mutex_exit(&p->p_lock); 3301885Sraf mutex_enter(&aiop->aio_mutex); 3311885Sraf /* wakeup anybody waiting in aiowait() */ 3321885Sraf cv_broadcast(&aiop->aio_waitcv); 3331885Sraf 3341885Sraf /* wakeup aio_cleanup_exit if needed */ 3351885Sraf if (aiop->aio_flags & AIO_CLEANUP) 3361885Sraf cv_signal(&aiop->aio_cleanupcv); 3371885Sraf aiop->aio_flags &= ~AIO_DONE_ACTIVE; 3381885Sraf mutex_exit(&aiop->aio_mutex); 3391885Sraf } 3401885Sraf return; 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate /* 3441885Sraf * save req's sigevent pointer, and check its 3451885Sraf * value after releasing aio_mutex lock. 3460Sstevel@tonic-gate */ 3471885Sraf sigev = reqp->aio_req_sigqp; 3481885Sraf reqp->aio_req_sigqp = NULL; 3490Sstevel@tonic-gate 3501885Sraf /* put request on done queue. */ 3511885Sraf aio_enq(&aiop->aio_doneq, reqp, AIO_DONEQ); 3521885Sraf } /* portkevent */ 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate /* 3551885Sraf * when list IO notification is enabled, a notification or 3561885Sraf * signal is sent only when all entries in the list are done. 3570Sstevel@tonic-gate */ 3580Sstevel@tonic-gate if ((head = reqp->aio_req_lio) != NULL) { 3590Sstevel@tonic-gate ASSERT(head->lio_refcnt > 0); 3600Sstevel@tonic-gate if (--head->lio_refcnt == 0) { 3610Sstevel@tonic-gate /* 3620Sstevel@tonic-gate * save lio's sigevent pointer, and check 3631885Sraf * its value after releasing aio_mutex lock. 3640Sstevel@tonic-gate */ 3650Sstevel@tonic-gate lio_sigev = head->lio_sigqp; 3660Sstevel@tonic-gate head->lio_sigqp = NULL; 3671885Sraf cv_signal(&head->lio_notify); 3681885Sraf if (head->lio_port >= 0 && 3691885Sraf (lio_pkevp = head->lio_portkev) != NULL) 3701885Sraf head->lio_port = -1; 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate /* 3750Sstevel@tonic-gate * if AIO_WAITN set then 3760Sstevel@tonic-gate * send signal only when we reached the 3770Sstevel@tonic-gate * required amount of IO's finished 3780Sstevel@tonic-gate * or when all IO's are done 3790Sstevel@tonic-gate */ 3800Sstevel@tonic-gate if (aiop->aio_flags & AIO_WAITN) { 3810Sstevel@tonic-gate if (aiop->aio_waitncnt > 0) 3820Sstevel@tonic-gate aiop->aio_waitncnt--; 3830Sstevel@tonic-gate if (aiop->aio_pending == 0 || 3840Sstevel@tonic-gate aiop->aio_waitncnt == 0) 3850Sstevel@tonic-gate cv_broadcast(&aiop->aio_waitcv); 3860Sstevel@tonic-gate } else { 3870Sstevel@tonic-gate cv_broadcast(&aiop->aio_waitcv); 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 3911885Sraf mutex_exit(&aiop->aio_portq_mutex); 3921885Sraf 393*4532Ssp92102 /* 394*4532Ssp92102 * Could the cleanup thread be waiting for AIO with locked 395*4532Ssp92102 * resources to finish? 396*4532Ssp92102 * Ideally in that case cleanup thread should block on cleanupcv, 397*4532Ssp92102 * but there is a window, where it could miss to see a new aio 398*4532Ssp92102 * request that sneaked in. 399*4532Ssp92102 */ 400*4532Ssp92102 mutex_enter(&as->a_contents); 401*4532Ssp92102 if ((reqp_flags & AIO_PAGELOCKDONE) && AS_ISUNMAPWAIT(as)) 402*4532Ssp92102 cv_broadcast(&as->a_cv); 403*4532Ssp92102 mutex_exit(&as->a_contents); 404*4532Ssp92102 4050Sstevel@tonic-gate if (sigev) 4060Sstevel@tonic-gate aio_sigev_send(p, sigev); 4071885Sraf else if (!use_port && head == NULL) { 4080Sstevel@tonic-gate /* 4091885Sraf * Send a SIGIO signal when the process has a handler enabled. 4100Sstevel@tonic-gate */ 4111885Sraf if ((func = PTOU(p)->u_signal[SIGIO - 1]) != SIG_DFL && 4121885Sraf func != SIG_IGN) 4130Sstevel@tonic-gate psignal(p, SIGIO); 4140Sstevel@tonic-gate } 4151885Sraf if (pkevp) 4161885Sraf port_send_event(pkevp); 4171885Sraf if (lio_sigev) 4181885Sraf aio_sigev_send(p, lio_sigev); 4191885Sraf if (lio_pkevp) 4201885Sraf port_send_event(lio_pkevp); 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate /* 4240Sstevel@tonic-gate * send a queued signal to the specified process when 4250Sstevel@tonic-gate * the event signal is non-NULL. A return value of 1 4260Sstevel@tonic-gate * will indicate that a signal is queued, and 0 means that 4270Sstevel@tonic-gate * no signal was specified, nor sent. 4280Sstevel@tonic-gate */ 4290Sstevel@tonic-gate static void 4300Sstevel@tonic-gate aio_sigev_send(proc_t *p, sigqueue_t *sigev) 4310Sstevel@tonic-gate { 4320Sstevel@tonic-gate ASSERT(sigev != NULL); 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate mutex_enter(&p->p_lock); 4350Sstevel@tonic-gate sigaddqa(p, NULL, sigev); 4360Sstevel@tonic-gate mutex_exit(&p->p_lock); 4370Sstevel@tonic-gate } 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate /* 4400Sstevel@tonic-gate * special case handling for zero length requests. the aio request 4410Sstevel@tonic-gate * short circuits the normal completion path since all that's required 4420Sstevel@tonic-gate * to complete this request is to copyout a zero to the aio request's 4430Sstevel@tonic-gate * return value. 4440Sstevel@tonic-gate */ 4450Sstevel@tonic-gate void 4460Sstevel@tonic-gate aio_zerolen(aio_req_t *reqp) 4470Sstevel@tonic-gate { 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate struct buf *bp = &reqp->aio_req_buf; 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate reqp->aio_req_flags |= AIO_ZEROLEN; 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate bp->b_forw = (struct buf *)reqp; 4540Sstevel@tonic-gate bp->b_proc = curproc; 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate bp->b_resid = 0; 4570Sstevel@tonic-gate bp->b_flags = 0; 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate aio_done(bp); 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* 4630Sstevel@tonic-gate * unlock pages previously locked by as_pagelock 4640Sstevel@tonic-gate */ 4650Sstevel@tonic-gate void 4660Sstevel@tonic-gate aphysio_unlock(aio_req_t *reqp) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate struct buf *bp; 4690Sstevel@tonic-gate struct iovec *iov; 4700Sstevel@tonic-gate int flags; 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate if (reqp->aio_req_flags & AIO_PHYSIODONE) 4730Sstevel@tonic-gate return; 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate reqp->aio_req_flags |= AIO_PHYSIODONE; 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate if (reqp->aio_req_flags & AIO_ZEROLEN) 4780Sstevel@tonic-gate return; 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate bp = &reqp->aio_req_buf; 4810Sstevel@tonic-gate iov = reqp->aio_req_uio.uio_iov; 4820Sstevel@tonic-gate flags = (((bp->b_flags & B_READ) == B_READ) ? S_WRITE : S_READ); 4830Sstevel@tonic-gate if (reqp->aio_req_flags & AIO_PAGELOCKDONE) { 4840Sstevel@tonic-gate as_pageunlock(bp->b_proc->p_as, 4850Sstevel@tonic-gate bp->b_flags & B_SHADOW ? bp->b_shadow : NULL, 4860Sstevel@tonic-gate iov->iov_base, iov->iov_len, flags); 4870Sstevel@tonic-gate reqp->aio_req_flags &= ~AIO_PAGELOCKDONE; 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_SHADOW); 4900Sstevel@tonic-gate bp->b_flags |= B_DONE; 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate /* 4941885Sraf * deletes a requests id from the hash table of outstanding io. 4950Sstevel@tonic-gate */ 4960Sstevel@tonic-gate static void 4971885Sraf aio_hash_delete(aio_t *aiop, struct aio_req_t *reqp) 4980Sstevel@tonic-gate { 4990Sstevel@tonic-gate long index; 5000Sstevel@tonic-gate aio_result_t *resultp = reqp->aio_req_resultp; 5010Sstevel@tonic-gate aio_req_t *current; 5020Sstevel@tonic-gate aio_req_t **nextp; 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate index = AIO_HASH(resultp); 5050Sstevel@tonic-gate nextp = (aiop->aio_hash + index); 5060Sstevel@tonic-gate while ((current = *nextp) != NULL) { 5070Sstevel@tonic-gate if (current->aio_req_resultp == resultp) { 5080Sstevel@tonic-gate *nextp = current->aio_hash_next; 5090Sstevel@tonic-gate return; 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate nextp = ¤t->aio_hash_next; 5120Sstevel@tonic-gate } 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate /* 5160Sstevel@tonic-gate * Put a list head struct onto its free list. 5170Sstevel@tonic-gate */ 5180Sstevel@tonic-gate static void 5190Sstevel@tonic-gate aio_lio_free(aio_t *aiop, aio_lio_t *head) 5200Sstevel@tonic-gate { 5210Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate if (head->lio_sigqp != NULL) 5240Sstevel@tonic-gate kmem_free(head->lio_sigqp, sizeof (sigqueue_t)); 5250Sstevel@tonic-gate head->lio_next = aiop->aio_lio_free; 5260Sstevel@tonic-gate aiop->aio_lio_free = head; 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* 5300Sstevel@tonic-gate * Put a reqp onto the freelist. 5310Sstevel@tonic-gate */ 5320Sstevel@tonic-gate void 5330Sstevel@tonic-gate aio_req_free(aio_t *aiop, aio_req_t *reqp) 5340Sstevel@tonic-gate { 5350Sstevel@tonic-gate aio_lio_t *liop; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate if (reqp->aio_req_portkev) { 5400Sstevel@tonic-gate port_free_event(reqp->aio_req_portkev); 5410Sstevel@tonic-gate reqp->aio_req_portkev = NULL; 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate if ((liop = reqp->aio_req_lio) != NULL) { 5450Sstevel@tonic-gate if (--liop->lio_nent == 0) 5460Sstevel@tonic-gate aio_lio_free(aiop, liop); 5470Sstevel@tonic-gate reqp->aio_req_lio = NULL; 5480Sstevel@tonic-gate } 5491885Sraf if (reqp->aio_req_sigqp != NULL) { 5500Sstevel@tonic-gate kmem_free(reqp->aio_req_sigqp, sizeof (sigqueue_t)); 5511885Sraf reqp->aio_req_sigqp = NULL; 5521885Sraf } 5530Sstevel@tonic-gate reqp->aio_req_next = aiop->aio_free; 5541885Sraf reqp->aio_req_prev = NULL; 5550Sstevel@tonic-gate aiop->aio_free = reqp; 5560Sstevel@tonic-gate aiop->aio_outstanding--; 5570Sstevel@tonic-gate if (aiop->aio_outstanding == 0) 5580Sstevel@tonic-gate cv_broadcast(&aiop->aio_waitcv); 5590Sstevel@tonic-gate aio_hash_delete(aiop, reqp); 5600Sstevel@tonic-gate } 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate /* 5630Sstevel@tonic-gate * Put a reqp onto the freelist. 5640Sstevel@tonic-gate */ 5650Sstevel@tonic-gate void 5660Sstevel@tonic-gate aio_req_free_port(aio_t *aiop, aio_req_t *reqp) 5670Sstevel@tonic-gate { 5680Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_mutex)); 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate reqp->aio_req_next = aiop->aio_free; 5711885Sraf reqp->aio_req_prev = NULL; 5720Sstevel@tonic-gate aiop->aio_free = reqp; 5730Sstevel@tonic-gate aiop->aio_outstanding--; 5740Sstevel@tonic-gate aio_hash_delete(aiop, reqp); 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate /* 5791885Sraf * Verify the integrity of a queue. 5800Sstevel@tonic-gate */ 5811885Sraf #if defined(DEBUG) 5820Sstevel@tonic-gate static void 5831885Sraf aio_verify_queue(aio_req_t *head, 5841885Sraf aio_req_t *entry_present, aio_req_t *entry_missing) 5851885Sraf { 5861885Sraf aio_req_t *reqp; 5871885Sraf int found = 0; 5881885Sraf int present = 0; 5891885Sraf 5901885Sraf if ((reqp = head) != NULL) { 5911885Sraf do { 5921885Sraf ASSERT(reqp->aio_req_prev->aio_req_next == reqp); 5931885Sraf ASSERT(reqp->aio_req_next->aio_req_prev == reqp); 5941885Sraf if (entry_present == reqp) 5951885Sraf found++; 5961885Sraf if (entry_missing == reqp) 5971885Sraf present++; 5981885Sraf } while ((reqp = reqp->aio_req_next) != head); 5991885Sraf } 6001885Sraf ASSERT(entry_present == NULL || found == 1); 6011885Sraf ASSERT(entry_missing == NULL || present == 0); 6021885Sraf } 6031885Sraf #else 6041885Sraf #define aio_verify_queue(x, y, z) 6051885Sraf #endif 6061885Sraf 6071885Sraf /* 6081885Sraf * Put a request onto the tail of a queue. 6091885Sraf */ 6101885Sraf void 6110Sstevel@tonic-gate aio_enq(aio_req_t **qhead, aio_req_t *reqp, int qflg_new) 6120Sstevel@tonic-gate { 6131885Sraf aio_req_t *head; 6141885Sraf aio_req_t *prev; 6151885Sraf 6161885Sraf aio_verify_queue(*qhead, NULL, reqp); 6171885Sraf 6181885Sraf if ((head = *qhead) == NULL) { 6190Sstevel@tonic-gate reqp->aio_req_next = reqp; 6200Sstevel@tonic-gate reqp->aio_req_prev = reqp; 6211885Sraf *qhead = reqp; 6220Sstevel@tonic-gate } else { 6231885Sraf reqp->aio_req_next = head; 6241885Sraf reqp->aio_req_prev = prev = head->aio_req_prev; 6251885Sraf prev->aio_req_next = reqp; 6261885Sraf head->aio_req_prev = reqp; 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate reqp->aio_req_flags |= qflg_new; 6290Sstevel@tonic-gate } 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate /* 6321885Sraf * Remove a request from its queue. 6330Sstevel@tonic-gate */ 6340Sstevel@tonic-gate void 6351885Sraf aio_deq(aio_req_t **qhead, aio_req_t *reqp) 6360Sstevel@tonic-gate { 6371885Sraf aio_verify_queue(*qhead, reqp, NULL); 6380Sstevel@tonic-gate 6391885Sraf if (reqp->aio_req_next == reqp) { 6401885Sraf *qhead = NULL; 6410Sstevel@tonic-gate } else { 6421885Sraf reqp->aio_req_prev->aio_req_next = reqp->aio_req_next; 6431885Sraf reqp->aio_req_next->aio_req_prev = reqp->aio_req_prev; 6441885Sraf if (*qhead == reqp) 6451885Sraf *qhead = reqp->aio_req_next; 6460Sstevel@tonic-gate } 6471885Sraf reqp->aio_req_next = NULL; 6480Sstevel@tonic-gate reqp->aio_req_prev = NULL; 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * concatenate a specified queue with the cleanupq. the specified 6530Sstevel@tonic-gate * queue is put onto the tail of the cleanupq. all elements on the 6540Sstevel@tonic-gate * specified queue should have their aio_req_flags field cleared. 6550Sstevel@tonic-gate */ 6560Sstevel@tonic-gate /*ARGSUSED*/ 6570Sstevel@tonic-gate void 6580Sstevel@tonic-gate aio_cleanupq_concat(aio_t *aiop, aio_req_t *q2, int qflg) 6590Sstevel@tonic-gate { 6600Sstevel@tonic-gate aio_req_t *cleanupqhead, *q2tail; 6610Sstevel@tonic-gate aio_req_t *reqp = q2; 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate do { 6640Sstevel@tonic-gate ASSERT(reqp->aio_req_flags & qflg); 6650Sstevel@tonic-gate reqp->aio_req_flags &= ~qflg; 6660Sstevel@tonic-gate reqp->aio_req_flags |= AIO_CLEANUPQ; 6670Sstevel@tonic-gate } while ((reqp = reqp->aio_req_next) != q2); 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate cleanupqhead = aiop->aio_cleanupq; 6700Sstevel@tonic-gate if (cleanupqhead == NULL) 6710Sstevel@tonic-gate aiop->aio_cleanupq = q2; 6720Sstevel@tonic-gate else { 6730Sstevel@tonic-gate cleanupqhead->aio_req_prev->aio_req_next = q2; 6740Sstevel@tonic-gate q2tail = q2->aio_req_prev; 6750Sstevel@tonic-gate q2tail->aio_req_next = cleanupqhead; 6760Sstevel@tonic-gate q2->aio_req_prev = cleanupqhead->aio_req_prev; 6770Sstevel@tonic-gate cleanupqhead->aio_req_prev = q2tail; 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* 6820Sstevel@tonic-gate * cleanup aio requests that are on the per-process poll queue. 6830Sstevel@tonic-gate */ 6840Sstevel@tonic-gate void 6850Sstevel@tonic-gate aio_cleanup(int flag) 6860Sstevel@tonic-gate { 6870Sstevel@tonic-gate aio_t *aiop = curproc->p_aio; 6880Sstevel@tonic-gate aio_req_t *pollqhead, *cleanupqhead, *notifyqhead; 6890Sstevel@tonic-gate aio_req_t *cleanupport; 6900Sstevel@tonic-gate aio_req_t *portq = NULL; 6910Sstevel@tonic-gate void (*func)(); 6920Sstevel@tonic-gate int signalled = 0; 6930Sstevel@tonic-gate int qflag = 0; 6940Sstevel@tonic-gate int exitflg; 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate ASSERT(aiop != NULL); 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate if (flag == AIO_CLEANUP_EXIT) 6990Sstevel@tonic-gate exitflg = AIO_CLEANUP_EXIT; 7000Sstevel@tonic-gate else 7010Sstevel@tonic-gate exitflg = 0; 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate /* 7040Sstevel@tonic-gate * We need to get the aio_cleanupq_mutex because we are calling 7050Sstevel@tonic-gate * aio_cleanup_cleanupq() 7060Sstevel@tonic-gate */ 7070Sstevel@tonic-gate mutex_enter(&aiop->aio_cleanupq_mutex); 7080Sstevel@tonic-gate /* 7090Sstevel@tonic-gate * take all the requests off the cleanupq, the notifyq, 7100Sstevel@tonic-gate * and the pollq. 7110Sstevel@tonic-gate */ 7120Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 7130Sstevel@tonic-gate if ((cleanupqhead = aiop->aio_cleanupq) != NULL) { 7140Sstevel@tonic-gate aiop->aio_cleanupq = NULL; 7150Sstevel@tonic-gate qflag++; 7160Sstevel@tonic-gate } 7170Sstevel@tonic-gate if ((notifyqhead = aiop->aio_notifyq) != NULL) { 7180Sstevel@tonic-gate aiop->aio_notifyq = NULL; 7190Sstevel@tonic-gate qflag++; 7200Sstevel@tonic-gate } 7210Sstevel@tonic-gate if ((pollqhead = aiop->aio_pollq) != NULL) { 7220Sstevel@tonic-gate aiop->aio_pollq = NULL; 7230Sstevel@tonic-gate qflag++; 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate if (flag) { 7260Sstevel@tonic-gate if ((portq = aiop->aio_portq) != NULL) 7270Sstevel@tonic-gate qflag++; 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate if ((cleanupport = aiop->aio_portcleanupq) != NULL) { 7300Sstevel@tonic-gate aiop->aio_portcleanupq = NULL; 7310Sstevel@tonic-gate qflag++; 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate /* 7370Sstevel@tonic-gate * return immediately if cleanupq, pollq, and 7380Sstevel@tonic-gate * notifyq are all empty. someone else must have 7390Sstevel@tonic-gate * emptied them. 7400Sstevel@tonic-gate */ 7410Sstevel@tonic-gate if (!qflag) { 7420Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex); 7430Sstevel@tonic-gate return; 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate /* 7470Sstevel@tonic-gate * do cleanup for the various queues. 7480Sstevel@tonic-gate */ 7490Sstevel@tonic-gate if (cleanupqhead) 7500Sstevel@tonic-gate aio_cleanup_cleanupq(aiop, cleanupqhead, exitflg); 7510Sstevel@tonic-gate mutex_exit(&aiop->aio_cleanupq_mutex); 7520Sstevel@tonic-gate if (notifyqhead) 7530Sstevel@tonic-gate signalled = aio_cleanup_notifyq(aiop, notifyqhead, exitflg); 7540Sstevel@tonic-gate if (pollqhead) 7550Sstevel@tonic-gate aio_cleanup_pollq(aiop, pollqhead, exitflg); 7560Sstevel@tonic-gate if (flag && (cleanupport || portq)) 7570Sstevel@tonic-gate aio_cleanup_portq(aiop, cleanupport, exitflg); 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate if (exitflg) 7600Sstevel@tonic-gate return; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate /* 7630Sstevel@tonic-gate * If we have an active aio_cleanup_thread it's possible for 7640Sstevel@tonic-gate * this routine to push something on to the done queue after 7650Sstevel@tonic-gate * an aiowait/aiosuspend thread has already decided to block. 7660Sstevel@tonic-gate * This being the case, we need a cv_broadcast here to wake 7670Sstevel@tonic-gate * these threads up. It is simpler and cleaner to do this 7680Sstevel@tonic-gate * broadcast here than in the individual cleanup routines. 7690Sstevel@tonic-gate */ 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 7720Sstevel@tonic-gate cv_broadcast(&aiop->aio_waitcv); 7730Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate /* 7760Sstevel@tonic-gate * Only if the process wasn't already signalled, 7770Sstevel@tonic-gate * determine if a SIGIO signal should be delievered. 7780Sstevel@tonic-gate */ 7790Sstevel@tonic-gate if (!signalled && 7801885Sraf (func = PTOU(curproc)->u_signal[SIGIO - 1]) != SIG_DFL && 7810Sstevel@tonic-gate func != SIG_IGN) 7820Sstevel@tonic-gate psignal(curproc, SIGIO); 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate 7860Sstevel@tonic-gate /* 7870Sstevel@tonic-gate * Do cleanup for every element of the port cleanup queue. 7880Sstevel@tonic-gate */ 7890Sstevel@tonic-gate static void 7900Sstevel@tonic-gate aio_cleanup_portq(aio_t *aiop, aio_req_t *cleanupq, int exitflag) 7910Sstevel@tonic-gate { 7920Sstevel@tonic-gate aio_req_t *reqp; 7930Sstevel@tonic-gate aio_req_t *next; 7940Sstevel@tonic-gate aio_req_t *headp; 7951885Sraf aio_lio_t *liop; 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate /* first check the portq */ 7980Sstevel@tonic-gate if (exitflag || ((aiop->aio_flags & AIO_CLEANUP_PORT) == 0)) { 7990Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 8000Sstevel@tonic-gate if (aiop->aio_flags & AIO_CLEANUP) 8010Sstevel@tonic-gate aiop->aio_flags |= AIO_CLEANUP_PORT; 8020Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 8030Sstevel@tonic-gate 8041885Sraf /* 8051885Sraf * It is not allowed to hold locks during aphysio_unlock(). 8061885Sraf * The aio_done() interrupt function will try to acquire 8071885Sraf * aio_mutex and aio_portq_mutex. Therefore we disconnect 8081885Sraf * the portq list from the aiop for the duration of the 8091885Sraf * aphysio_unlock() loop below. 8101885Sraf */ 8110Sstevel@tonic-gate mutex_enter(&aiop->aio_portq_mutex); 8120Sstevel@tonic-gate headp = aiop->aio_portq; 8130Sstevel@tonic-gate aiop->aio_portq = NULL; 8140Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 8151885Sraf if ((reqp = headp) != NULL) { 8161885Sraf do { 8171885Sraf next = reqp->aio_req_next; 8181885Sraf aphysio_unlock(reqp); 8191885Sraf if (exitflag) { 8201885Sraf mutex_enter(&aiop->aio_mutex); 8211885Sraf aio_req_free(aiop, reqp); 8221885Sraf mutex_exit(&aiop->aio_mutex); 8231885Sraf } 8241885Sraf } while ((reqp = next) != headp); 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate if (headp != NULL && exitflag == 0) { 8281885Sraf /* move unlocked requests back to the port queue */ 8291885Sraf aio_req_t *newq; 8301885Sraf 8310Sstevel@tonic-gate mutex_enter(&aiop->aio_portq_mutex); 8321885Sraf if ((newq = aiop->aio_portq) != NULL) { 8331885Sraf aio_req_t *headprev = headp->aio_req_prev; 8341885Sraf aio_req_t *newqprev = newq->aio_req_prev; 8351885Sraf 8361885Sraf headp->aio_req_prev = newqprev; 8371885Sraf newq->aio_req_prev = headprev; 8381885Sraf headprev->aio_req_next = newq; 8391885Sraf newqprev->aio_req_next = headp; 8400Sstevel@tonic-gate } 8410Sstevel@tonic-gate aiop->aio_portq = headp; 8420Sstevel@tonic-gate cv_broadcast(&aiop->aio_portcv); 8430Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate } 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate /* now check the port cleanup queue */ 8481885Sraf if ((reqp = cleanupq) == NULL) 8491885Sraf return; 8501885Sraf do { 8510Sstevel@tonic-gate next = reqp->aio_req_next; 8520Sstevel@tonic-gate aphysio_unlock(reqp); 8530Sstevel@tonic-gate if (exitflag) { 8540Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 8550Sstevel@tonic-gate aio_req_free(aiop, reqp); 8560Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 8570Sstevel@tonic-gate } else { 8580Sstevel@tonic-gate mutex_enter(&aiop->aio_portq_mutex); 8591885Sraf aio_enq(&aiop->aio_portq, reqp, 0); 8600Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 8611885Sraf port_send_event(reqp->aio_req_portkev); 8621885Sraf if ((liop = reqp->aio_req_lio) != NULL) { 8631885Sraf int send_event = 0; 8641885Sraf 8651885Sraf mutex_enter(&aiop->aio_mutex); 8661885Sraf ASSERT(liop->lio_refcnt > 0); 8671885Sraf if (--liop->lio_refcnt == 0) { 8681885Sraf if (liop->lio_port >= 0 && 8691885Sraf liop->lio_portkev) { 8701885Sraf liop->lio_port = -1; 8711885Sraf send_event = 1; 8721885Sraf } 8731885Sraf } 8741885Sraf mutex_exit(&aiop->aio_mutex); 8751885Sraf if (send_event) 8761885Sraf port_send_event(liop->lio_portkev); 8771885Sraf } 8780Sstevel@tonic-gate } 8791885Sraf } while ((reqp = next) != cleanupq); 8800Sstevel@tonic-gate } 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate /* 8830Sstevel@tonic-gate * Do cleanup for every element of the cleanupq. 8840Sstevel@tonic-gate */ 8850Sstevel@tonic-gate static void 8860Sstevel@tonic-gate aio_cleanup_cleanupq(aio_t *aiop, aio_req_t *qhead, int exitflg) 8870Sstevel@tonic-gate { 8880Sstevel@tonic-gate aio_req_t *reqp, *next; 8891885Sraf 8900Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_cleanupq_mutex)); 8910Sstevel@tonic-gate 8920Sstevel@tonic-gate /* 8930Sstevel@tonic-gate * Since aio_req_done() or aio_req_find() use the HASH list to find 8940Sstevel@tonic-gate * the required requests, they could potentially take away elements 8950Sstevel@tonic-gate * if they are already done (AIO_DONEQ is set). 8960Sstevel@tonic-gate * The aio_cleanupq_mutex protects the queue for the duration of the 8970Sstevel@tonic-gate * loop from aio_req_done() and aio_req_find(). 8980Sstevel@tonic-gate */ 8991885Sraf if ((reqp = qhead) == NULL) 9001885Sraf return; 9011885Sraf do { 9020Sstevel@tonic-gate ASSERT(reqp->aio_req_flags & AIO_CLEANUPQ); 9031885Sraf ASSERT(reqp->aio_req_portkev == NULL); 9040Sstevel@tonic-gate next = reqp->aio_req_next; 9050Sstevel@tonic-gate aphysio_unlock(reqp); 9060Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 9071885Sraf if (exitflg) 9080Sstevel@tonic-gate aio_req_free(aiop, reqp); 9091885Sraf else 9101885Sraf aio_enq(&aiop->aio_doneq, reqp, AIO_DONEQ); 9110Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 9121885Sraf } while ((reqp = next) != qhead); 9130Sstevel@tonic-gate } 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate /* 9160Sstevel@tonic-gate * do cleanup for every element of the notify queue. 9170Sstevel@tonic-gate */ 9180Sstevel@tonic-gate static int 9190Sstevel@tonic-gate aio_cleanup_notifyq(aio_t *aiop, aio_req_t *qhead, int exitflg) 9200Sstevel@tonic-gate { 9210Sstevel@tonic-gate aio_req_t *reqp, *next; 9220Sstevel@tonic-gate aio_lio_t *liohead; 9230Sstevel@tonic-gate sigqueue_t *sigev, *lio_sigev = NULL; 9240Sstevel@tonic-gate int signalled = 0; 9250Sstevel@tonic-gate 9261885Sraf if ((reqp = qhead) == NULL) 9271885Sraf return (0); 9281885Sraf do { 9290Sstevel@tonic-gate ASSERT(reqp->aio_req_flags & AIO_NOTIFYQ); 9300Sstevel@tonic-gate next = reqp->aio_req_next; 9310Sstevel@tonic-gate aphysio_unlock(reqp); 9320Sstevel@tonic-gate if (exitflg) { 9330Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 9340Sstevel@tonic-gate aio_req_free(aiop, reqp); 9350Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 9361885Sraf } else { 9371885Sraf mutex_enter(&aiop->aio_mutex); 9381885Sraf aio_enq(&aiop->aio_doneq, reqp, AIO_DONEQ); 9391885Sraf sigev = reqp->aio_req_sigqp; 9401885Sraf reqp->aio_req_sigqp = NULL; 9411885Sraf if ((liohead = reqp->aio_req_lio) != NULL) { 9421885Sraf ASSERT(liohead->lio_refcnt > 0); 9431885Sraf if (--liohead->lio_refcnt == 0) { 9441885Sraf cv_signal(&liohead->lio_notify); 9451885Sraf lio_sigev = liohead->lio_sigqp; 9461885Sraf liohead->lio_sigqp = NULL; 9471885Sraf } 9481885Sraf } 9491885Sraf mutex_exit(&aiop->aio_mutex); 9501885Sraf if (sigev) { 9511885Sraf signalled++; 9521885Sraf aio_sigev_send(reqp->aio_req_buf.b_proc, 9531885Sraf sigev); 9541885Sraf } 9551885Sraf if (lio_sigev) { 9561885Sraf signalled++; 9571885Sraf aio_sigev_send(reqp->aio_req_buf.b_proc, 9581885Sraf lio_sigev); 9590Sstevel@tonic-gate } 9600Sstevel@tonic-gate } 9611885Sraf } while ((reqp = next) != qhead); 9621885Sraf 9630Sstevel@tonic-gate return (signalled); 9640Sstevel@tonic-gate } 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate /* 9670Sstevel@tonic-gate * Do cleanup for every element of the poll queue. 9680Sstevel@tonic-gate */ 9690Sstevel@tonic-gate static void 9700Sstevel@tonic-gate aio_cleanup_pollq(aio_t *aiop, aio_req_t *qhead, int exitflg) 9710Sstevel@tonic-gate { 9720Sstevel@tonic-gate aio_req_t *reqp, *next; 9730Sstevel@tonic-gate 9740Sstevel@tonic-gate /* 9750Sstevel@tonic-gate * As no other threads should be accessing the queue at this point, 9760Sstevel@tonic-gate * it isn't necessary to hold aio_mutex while we traverse its elements. 9770Sstevel@tonic-gate */ 9781885Sraf if ((reqp = qhead) == NULL) 9791885Sraf return; 9801885Sraf do { 9810Sstevel@tonic-gate ASSERT(reqp->aio_req_flags & AIO_POLLQ); 9820Sstevel@tonic-gate next = reqp->aio_req_next; 9830Sstevel@tonic-gate aphysio_unlock(reqp); 9840Sstevel@tonic-gate if (exitflg) { 9850Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 9860Sstevel@tonic-gate aio_req_free(aiop, reqp); 9870Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 9881885Sraf } else { 9891885Sraf aio_copyout_result(reqp); 9901885Sraf mutex_enter(&aiop->aio_mutex); 9911885Sraf aio_enq(&aiop->aio_doneq, reqp, AIO_DONEQ); 9921885Sraf mutex_exit(&aiop->aio_mutex); 9930Sstevel@tonic-gate } 9941885Sraf } while ((reqp = next) != qhead); 9950Sstevel@tonic-gate } 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate /* 9980Sstevel@tonic-gate * called by exit(). waits for all outstanding kaio to finish 9990Sstevel@tonic-gate * before the kaio resources are freed. 10000Sstevel@tonic-gate */ 10010Sstevel@tonic-gate void 10020Sstevel@tonic-gate aio_cleanup_exit(void) 10030Sstevel@tonic-gate { 10040Sstevel@tonic-gate proc_t *p = curproc; 10050Sstevel@tonic-gate aio_t *aiop = p->p_aio; 10060Sstevel@tonic-gate aio_req_t *reqp, *next, *head; 10070Sstevel@tonic-gate aio_lio_t *nxtlio, *liop; 10080Sstevel@tonic-gate 10090Sstevel@tonic-gate /* 10100Sstevel@tonic-gate * wait for all outstanding kaio to complete. process 10110Sstevel@tonic-gate * is now single-threaded; no other kaio requests can 10120Sstevel@tonic-gate * happen once aio_pending is zero. 10130Sstevel@tonic-gate */ 10140Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 10150Sstevel@tonic-gate aiop->aio_flags |= AIO_CLEANUP; 10160Sstevel@tonic-gate while ((aiop->aio_pending != 0) || (aiop->aio_flags & AIO_DONE_ACTIVE)) 10170Sstevel@tonic-gate cv_wait(&aiop->aio_cleanupcv, &aiop->aio_mutex); 10180Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate /* cleanup the cleanup-thread queues. */ 10210Sstevel@tonic-gate aio_cleanup(AIO_CLEANUP_EXIT); 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate /* 10240Sstevel@tonic-gate * Although this process is now single-threaded, we 10250Sstevel@tonic-gate * still need to protect ourselves against a race with 10260Sstevel@tonic-gate * aio_cleanup_dr_delete_memory(). 10270Sstevel@tonic-gate */ 10280Sstevel@tonic-gate mutex_enter(&p->p_lock); 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate /* 10310Sstevel@tonic-gate * free up the done queue's resources. 10320Sstevel@tonic-gate */ 10330Sstevel@tonic-gate if ((head = aiop->aio_doneq) != NULL) { 10341885Sraf aiop->aio_doneq = NULL; 10351885Sraf reqp = head; 10361885Sraf do { 10370Sstevel@tonic-gate next = reqp->aio_req_next; 10380Sstevel@tonic-gate aphysio_unlock(reqp); 10390Sstevel@tonic-gate kmem_free(reqp, sizeof (struct aio_req_t)); 10401885Sraf } while ((reqp = next) != head); 10410Sstevel@tonic-gate } 10420Sstevel@tonic-gate /* 10430Sstevel@tonic-gate * release aio request freelist. 10440Sstevel@tonic-gate */ 10450Sstevel@tonic-gate for (reqp = aiop->aio_free; reqp != NULL; reqp = next) { 10460Sstevel@tonic-gate next = reqp->aio_req_next; 10470Sstevel@tonic-gate kmem_free(reqp, sizeof (struct aio_req_t)); 10480Sstevel@tonic-gate } 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate /* 10510Sstevel@tonic-gate * release io list head freelist. 10520Sstevel@tonic-gate */ 10530Sstevel@tonic-gate for (liop = aiop->aio_lio_free; liop != NULL; liop = nxtlio) { 10540Sstevel@tonic-gate nxtlio = liop->lio_next; 10550Sstevel@tonic-gate kmem_free(liop, sizeof (aio_lio_t)); 10560Sstevel@tonic-gate } 10570Sstevel@tonic-gate 10580Sstevel@tonic-gate if (aiop->aio_iocb) 10590Sstevel@tonic-gate kmem_free(aiop->aio_iocb, aiop->aio_iocbsz); 10600Sstevel@tonic-gate 10610Sstevel@tonic-gate mutex_destroy(&aiop->aio_mutex); 10620Sstevel@tonic-gate mutex_destroy(&aiop->aio_portq_mutex); 10630Sstevel@tonic-gate mutex_destroy(&aiop->aio_cleanupq_mutex); 10640Sstevel@tonic-gate p->p_aio = NULL; 10650Sstevel@tonic-gate mutex_exit(&p->p_lock); 10660Sstevel@tonic-gate kmem_free(aiop, sizeof (struct aio)); 10670Sstevel@tonic-gate } 10680Sstevel@tonic-gate 10690Sstevel@tonic-gate /* 10700Sstevel@tonic-gate * copy out aio request's result to a user-level result_t buffer. 10710Sstevel@tonic-gate */ 10720Sstevel@tonic-gate void 10730Sstevel@tonic-gate aio_copyout_result(aio_req_t *reqp) 10740Sstevel@tonic-gate { 10750Sstevel@tonic-gate struct buf *bp; 10760Sstevel@tonic-gate struct iovec *iov; 10770Sstevel@tonic-gate void *resultp; 10780Sstevel@tonic-gate int error; 10790Sstevel@tonic-gate size_t retval; 10800Sstevel@tonic-gate 10810Sstevel@tonic-gate if (reqp->aio_req_flags & AIO_COPYOUTDONE) 10820Sstevel@tonic-gate return; 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate reqp->aio_req_flags |= AIO_COPYOUTDONE; 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate iov = reqp->aio_req_uio.uio_iov; 10870Sstevel@tonic-gate bp = &reqp->aio_req_buf; 10880Sstevel@tonic-gate /* "resultp" points to user-level result_t buffer */ 10890Sstevel@tonic-gate resultp = (void *)reqp->aio_req_resultp; 10900Sstevel@tonic-gate if (bp->b_flags & B_ERROR) { 10910Sstevel@tonic-gate if (bp->b_error) 10920Sstevel@tonic-gate error = bp->b_error; 10930Sstevel@tonic-gate else 10940Sstevel@tonic-gate error = EIO; 10950Sstevel@tonic-gate retval = (size_t)-1; 10960Sstevel@tonic-gate } else { 10970Sstevel@tonic-gate error = 0; 10980Sstevel@tonic-gate retval = iov->iov_len - bp->b_resid; 10990Sstevel@tonic-gate } 11000Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 11010Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 11020Sstevel@tonic-gate (void) sulword(&((aio_result_t *)resultp)->aio_return, retval); 11030Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_errno, error); 11040Sstevel@tonic-gate } else { 11050Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_return, 11060Sstevel@tonic-gate (int)retval); 11070Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_errno, error); 11080Sstevel@tonic-gate } 11090Sstevel@tonic-gate #else 11100Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_return, retval); 11110Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_errno, error); 11120Sstevel@tonic-gate #endif 11130Sstevel@tonic-gate } 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate 11160Sstevel@tonic-gate void 11170Sstevel@tonic-gate aio_copyout_result_port(struct iovec *iov, struct buf *bp, void *resultp) 11180Sstevel@tonic-gate { 11190Sstevel@tonic-gate int errno; 11200Sstevel@tonic-gate size_t retval; 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate if (bp->b_flags & B_ERROR) { 11230Sstevel@tonic-gate if (bp->b_error) 11240Sstevel@tonic-gate errno = bp->b_error; 11250Sstevel@tonic-gate else 11260Sstevel@tonic-gate errno = EIO; 11270Sstevel@tonic-gate retval = (size_t)-1; 11280Sstevel@tonic-gate } else { 11290Sstevel@tonic-gate errno = 0; 11300Sstevel@tonic-gate retval = iov->iov_len - bp->b_resid; 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 11330Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_NATIVE) { 11340Sstevel@tonic-gate (void) sulword(&((aio_result_t *)resultp)->aio_return, retval); 11350Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_errno, errno); 11360Sstevel@tonic-gate } else { 11370Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_return, 11380Sstevel@tonic-gate (int)retval); 11390Sstevel@tonic-gate (void) suword32(&((aio_result32_t *)resultp)->aio_errno, errno); 11400Sstevel@tonic-gate } 11410Sstevel@tonic-gate #else 11420Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_return, retval); 11430Sstevel@tonic-gate (void) suword32(&((aio_result_t *)resultp)->aio_errno, errno); 11440Sstevel@tonic-gate #endif 11450Sstevel@tonic-gate } 11460Sstevel@tonic-gate 11470Sstevel@tonic-gate /* 11480Sstevel@tonic-gate * This function is used to remove a request from the done queue. 11490Sstevel@tonic-gate */ 11500Sstevel@tonic-gate 11510Sstevel@tonic-gate void 11520Sstevel@tonic-gate aio_req_remove_portq(aio_t *aiop, aio_req_t *reqp) 11530Sstevel@tonic-gate { 11540Sstevel@tonic-gate ASSERT(MUTEX_HELD(&aiop->aio_portq_mutex)); 11550Sstevel@tonic-gate while (aiop->aio_portq == NULL) { 11560Sstevel@tonic-gate /* 11570Sstevel@tonic-gate * aio_portq is set to NULL when aio_cleanup_portq() 11580Sstevel@tonic-gate * is working with the event queue. 11590Sstevel@tonic-gate * The aio_cleanup_thread() uses aio_cleanup_portq() 11600Sstevel@tonic-gate * to unlock all AIO buffers with completed transactions. 11610Sstevel@tonic-gate * Wait here until aio_cleanup_portq() restores the 11620Sstevel@tonic-gate * list of completed transactions in aio_portq. 11630Sstevel@tonic-gate */ 11640Sstevel@tonic-gate cv_wait(&aiop->aio_portcv, &aiop->aio_portq_mutex); 11650Sstevel@tonic-gate } 11661885Sraf aio_deq(&aiop->aio_portq, reqp); 11670Sstevel@tonic-gate } 11680Sstevel@tonic-gate 11690Sstevel@tonic-gate /* ARGSUSED */ 11700Sstevel@tonic-gate void 11710Sstevel@tonic-gate aio_close_port(void *arg, int port, pid_t pid, int lastclose) 11720Sstevel@tonic-gate { 11730Sstevel@tonic-gate aio_t *aiop; 11740Sstevel@tonic-gate aio_req_t *reqp; 11750Sstevel@tonic-gate aio_req_t *next; 11760Sstevel@tonic-gate aio_req_t *headp; 11770Sstevel@tonic-gate int counter; 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate if (arg == NULL) 11800Sstevel@tonic-gate aiop = curproc->p_aio; 11810Sstevel@tonic-gate else 11820Sstevel@tonic-gate aiop = (aio_t *)arg; 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate /* 11850Sstevel@tonic-gate * The PORT_SOURCE_AIO source is always associated with every new 11860Sstevel@tonic-gate * created port by default. 11870Sstevel@tonic-gate * If no asynchronous I/O transactions were associated with the port 11880Sstevel@tonic-gate * then the aiop pointer will still be set to NULL. 11890Sstevel@tonic-gate */ 11900Sstevel@tonic-gate if (aiop == NULL) 11910Sstevel@tonic-gate return; 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate /* 11940Sstevel@tonic-gate * Within a process event ports can be used to collect events other 11950Sstevel@tonic-gate * than PORT_SOURCE_AIO events. At the same time the process can submit 11960Sstevel@tonic-gate * asynchronous I/Os transactions which are not associated with the 11970Sstevel@tonic-gate * current port. 11980Sstevel@tonic-gate * The current process oriented model of AIO uses a sigle queue for 11990Sstevel@tonic-gate * pending events. On close the pending queue (queue of asynchronous 12000Sstevel@tonic-gate * I/O transactions using event port notification) must be scanned 12010Sstevel@tonic-gate * to detect and handle pending I/Os using the current port. 12020Sstevel@tonic-gate */ 12030Sstevel@tonic-gate mutex_enter(&aiop->aio_portq_mutex); 12040Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 12051885Sraf counter = 0; 12061885Sraf if ((headp = aiop->aio_portpending) != NULL) { 12071885Sraf reqp = headp; 12081885Sraf do { 12091885Sraf if (reqp->aio_req_portkev && 12101885Sraf reqp->aio_req_port == port) { 12111885Sraf reqp->aio_req_flags |= AIO_CLOSE_PORT; 12121885Sraf counter++; 12131885Sraf } 12141885Sraf } while ((reqp = reqp->aio_req_next) != headp); 12150Sstevel@tonic-gate } 12160Sstevel@tonic-gate if (counter == 0) { 12170Sstevel@tonic-gate /* no AIOs pending */ 12180Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 12190Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 12200Sstevel@tonic-gate return; 12210Sstevel@tonic-gate } 12220Sstevel@tonic-gate aiop->aio_portpendcnt += counter; 122341Spraks mutex_exit(&aiop->aio_mutex); 12240Sstevel@tonic-gate while (aiop->aio_portpendcnt) 122541Spraks cv_wait(&aiop->aio_portcv, &aiop->aio_portq_mutex); 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate /* 12280Sstevel@tonic-gate * all pending AIOs are completed. 12290Sstevel@tonic-gate * check port doneq 12300Sstevel@tonic-gate */ 12310Sstevel@tonic-gate headp = NULL; 12321885Sraf if ((reqp = aiop->aio_portq) != NULL) { 12331885Sraf do { 12341885Sraf next = reqp->aio_req_next; 12351885Sraf if (reqp->aio_req_port == port) { 12361885Sraf /* dequeue request and discard event */ 12371885Sraf aio_req_remove_portq(aiop, reqp); 12381885Sraf port_free_event(reqp->aio_req_portkev); 12391885Sraf /* put request in temporary queue */ 12401885Sraf reqp->aio_req_next = headp; 12411885Sraf headp = reqp; 12421885Sraf } 12431885Sraf } while ((reqp = next) != aiop->aio_portq); 12440Sstevel@tonic-gate } 12450Sstevel@tonic-gate mutex_exit(&aiop->aio_portq_mutex); 12460Sstevel@tonic-gate 12470Sstevel@tonic-gate /* headp points to the list of requests to be discarded */ 12480Sstevel@tonic-gate for (reqp = headp; reqp != NULL; reqp = next) { 12490Sstevel@tonic-gate next = reqp->aio_req_next; 12500Sstevel@tonic-gate aphysio_unlock(reqp); 12510Sstevel@tonic-gate mutex_enter(&aiop->aio_mutex); 12520Sstevel@tonic-gate aio_req_free_port(aiop, reqp); 12530Sstevel@tonic-gate mutex_exit(&aiop->aio_mutex); 12540Sstevel@tonic-gate } 12550Sstevel@tonic-gate 12560Sstevel@tonic-gate if (aiop->aio_flags & AIO_CLEANUP) 12570Sstevel@tonic-gate cv_broadcast(&aiop->aio_waitcv); 12580Sstevel@tonic-gate } 12590Sstevel@tonic-gate 12600Sstevel@tonic-gate /* 12610Sstevel@tonic-gate * aio_cleanup_dr_delete_memory is used by dr's delete_memory_thread 1262304Spraks * to kick start the aio_cleanup_thread for the give process to do the 1263304Spraks * necessary cleanup. 1264304Spraks * This is needed so that delete_memory_thread can obtain writer locks 1265304Spraks * on pages that need to be relocated during a dr memory delete operation, 1266304Spraks * otherwise a deadly embrace may occur. 12670Sstevel@tonic-gate */ 12680Sstevel@tonic-gate int 12690Sstevel@tonic-gate aio_cleanup_dr_delete_memory(proc_t *procp) 12700Sstevel@tonic-gate { 12710Sstevel@tonic-gate struct aio *aiop = procp->p_aio; 1272304Spraks struct as *as = procp->p_as; 1273304Spraks int ret = 0; 12740Sstevel@tonic-gate 12750Sstevel@tonic-gate ASSERT(MUTEX_HELD(&procp->p_lock)); 1276304Spraks 1277304Spraks mutex_enter(&as->a_contents); 1278304Spraks 1279304Spraks if (aiop != NULL) { 1280304Spraks aiop->aio_rqclnup = 1; 1281304Spraks cv_broadcast(&as->a_cv); 1282304Spraks ret = 1; 12830Sstevel@tonic-gate } 1284304Spraks mutex_exit(&as->a_contents); 1285304Spraks return (ret); 12860Sstevel@tonic-gate } 1287