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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright (c) 2015 Joyent, Inc. All rights reserved.
29 */
30
31 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/cred.h>
34 #include <sys/modctl.h>
35 #include <sys/vfs.h>
36 #include <sys/vfs_opreg.h>
37 #include <sys/sysmacros.h>
38 #include <sys/cmn_err.h>
39 #include <sys/stat.h>
40 #include <sys/errno.h>
41 #include <sys/kmem.h>
42 #include <sys/file.h>
43 #include <sys/kstat.h>
44 #include <sys/port_impl.h>
45 #include <sys/task.h>
46 #include <sys/project.h>
47
48 /*
1389 } else {
1390 kevp = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1391 if (kevp == NULL) {
1392 if (nmax > pp->port_max_list)
1393 nmax = pp->port_max_list;
1394 kevp = kmem_alloc(eventsz * nmax, KM_SLEEP);
1395 }
1396 }
1397
1398 results = kevp;
1399 lev = NULL; /* start with first event in the queue */
1400 for (nevents = 0; nevents < nmax; ) {
1401 pev = port_get_kevent(glist, lev);
1402 if (pev == NULL) /* no more events available */
1403 break;
1404 if (pev->portkev_flags & PORT_KEV_FREE) {
1405 /* Just discard event */
1406 list_remove(glist, pev);
1407 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1408 if (PORT_FREE_EVENT(pev))
1409 port_free_event_local(pev, 0);
1410 tnent--;
1411 continue;
1412 }
1413
1414 /* move event data to copyout list */
1415 if (port_copy_event(&kevp[nevents], pev, glist)) {
1416 /*
1417 * Event can not be delivered to the
1418 * current process.
1419 */
1420 if (lev != NULL)
1421 list_insert_after(glist, lev, pev);
1422 else
1423 list_insert_head(glist, pev);
1424 lev = pev; /* last checked event */
1425 } else {
1426 nevents++; /* # of events ready */
1427 }
1428 }
1429 #ifdef _SYSCALL32_IMPL
1437 } else {
1438 kevp32 = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1439 if (kevp32 == NULL) {
1440 if (nmax > pp->port_max_list)
1441 nmax = pp->port_max_list;
1442 kevp32 = kmem_alloc(eventsz * nmax, KM_SLEEP);
1443 }
1444 }
1445
1446 results = kevp32;
1447 lev = NULL; /* start with first event in the queue */
1448 for (nevents = 0; nevents < nmax; ) {
1449 pev = port_get_kevent(glist, lev);
1450 if (pev == NULL) /* no more events available */
1451 break;
1452 if (pev->portkev_flags & PORT_KEV_FREE) {
1453 /* Just discard event */
1454 list_remove(glist, pev);
1455 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1456 if (PORT_FREE_EVENT(pev))
1457 port_free_event_local(pev, 0);
1458 tnent--;
1459 continue;
1460 }
1461
1462 /* move event data to copyout list */
1463 if (port_copy_event32(&kevp32[nevents], pev, glist)) {
1464 /*
1465 * Event can not be delivered to the
1466 * current process.
1467 */
1468 if (lev != NULL)
1469 list_insert_after(glist, lev, pev);
1470 else
1471 list_insert_head(glist, pev);
1472 lev = pev; /* last checked event */
1473 } else {
1474 nevents++; /* # of events ready */
1475 }
1476 }
1477 #endif /* _SYSCALL32_IMPL */
1609 if (pkevp->portkev_flags & PORT_KEV_WIRED)
1610 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1611 else
1612 free_event = 1;
1613
1614 if (pkevp->portkev_callback) {
1615 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1616 &puevp->portev_events, pkevp->portkev_pid,
1617 PORT_CALLBACK_DEFAULT, pkevp);
1618
1619 if (error) {
1620 /*
1621 * Event can not be delivered.
1622 * Caller must reinsert the event into the queue.
1623 */
1624 pkevp->portkev_flags = flags;
1625 return (error);
1626 }
1627 }
1628 if (free_event)
1629 port_free_event_local(pkevp, 0);
1630 return (0);
1631 }
1632
1633 #ifdef _SYSCALL32_IMPL
1634 /*
1635 * 1. copy kernel event structure to user event structure.
1636 * 2. PORT_KEV_WIRED event structures will be reused by the "source"
1637 * 3. Remove PORT_KEV_DONEQ flag (event removed from the event queue)
1638 * 4. Other types of event structures can be delivered back to the port cache
1639 * (port_free_event_local()).
1640 * 5. The event source callback function is the last opportunity for the
1641 * event source to update events, to free local resources associated with
1642 * the event or to deny the delivery of the event.
1643 */
1644 static int
1645 port_copy_event32(port_event32_t *puevp, port_kevent_t *pkevp, list_t *list)
1646 {
1647 int free_event = 0;
1648 int error;
1649 int flags;
1664 flags = pkevp->portkev_flags;
1665 if (pkevp->portkev_flags & PORT_KEV_WIRED)
1666 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1667 else
1668 free_event = 1;
1669
1670 if (pkevp->portkev_callback != NULL) {
1671 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1672 &puevp->portev_events, pkevp->portkev_pid,
1673 PORT_CALLBACK_DEFAULT, pkevp);
1674 if (error) {
1675 /*
1676 * Event can not be delivered.
1677 * Caller must reinsert the event into the queue.
1678 */
1679 pkevp->portkev_flags = flags;
1680 return (error);
1681 }
1682 }
1683 if (free_event)
1684 port_free_event_local(pkevp, 0);
1685 return (0);
1686 }
1687 #endif /* _SYSCALL32_IMPL */
1688
1689 /*
1690 * copyout alert event.
1691 */
1692 static int
1693 port_get_alert(port_alert_t *pa, port_event_t *uevp)
1694 {
1695 model_t model = get_udatamodel();
1696
1697 /* copyout alert event structures to user space */
1698 if (model == DATAMODEL_NATIVE) {
1699 port_event_t uev;
1700 uev.portev_source = PORT_SOURCE_ALERT;
1701 uev.portev_object = pa->portal_object;
1702 uev.portev_events = pa->portal_events;
1703 uev.portev_user = pa->portal_user;
1704 if (copyout(&uev, uevp, sizeof (port_event_t)))
|
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2020 Joyent, Inc.
29 */
30
31 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/cred.h>
34 #include <sys/modctl.h>
35 #include <sys/vfs.h>
36 #include <sys/vfs_opreg.h>
37 #include <sys/sysmacros.h>
38 #include <sys/cmn_err.h>
39 #include <sys/stat.h>
40 #include <sys/errno.h>
41 #include <sys/kmem.h>
42 #include <sys/file.h>
43 #include <sys/kstat.h>
44 #include <sys/port_impl.h>
45 #include <sys/task.h>
46 #include <sys/project.h>
47
48 /*
1389 } else {
1390 kevp = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1391 if (kevp == NULL) {
1392 if (nmax > pp->port_max_list)
1393 nmax = pp->port_max_list;
1394 kevp = kmem_alloc(eventsz * nmax, KM_SLEEP);
1395 }
1396 }
1397
1398 results = kevp;
1399 lev = NULL; /* start with first event in the queue */
1400 for (nevents = 0; nevents < nmax; ) {
1401 pev = port_get_kevent(glist, lev);
1402 if (pev == NULL) /* no more events available */
1403 break;
1404 if (pev->portkev_flags & PORT_KEV_FREE) {
1405 /* Just discard event */
1406 list_remove(glist, pev);
1407 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1408 if (PORT_FREE_EVENT(pev))
1409 port_free_event_local(pev, B_TRUE);
1410 tnent--;
1411 continue;
1412 }
1413
1414 /* move event data to copyout list */
1415 if (port_copy_event(&kevp[nevents], pev, glist)) {
1416 /*
1417 * Event can not be delivered to the
1418 * current process.
1419 */
1420 if (lev != NULL)
1421 list_insert_after(glist, lev, pev);
1422 else
1423 list_insert_head(glist, pev);
1424 lev = pev; /* last checked event */
1425 } else {
1426 nevents++; /* # of events ready */
1427 }
1428 }
1429 #ifdef _SYSCALL32_IMPL
1437 } else {
1438 kevp32 = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1439 if (kevp32 == NULL) {
1440 if (nmax > pp->port_max_list)
1441 nmax = pp->port_max_list;
1442 kevp32 = kmem_alloc(eventsz * nmax, KM_SLEEP);
1443 }
1444 }
1445
1446 results = kevp32;
1447 lev = NULL; /* start with first event in the queue */
1448 for (nevents = 0; nevents < nmax; ) {
1449 pev = port_get_kevent(glist, lev);
1450 if (pev == NULL) /* no more events available */
1451 break;
1452 if (pev->portkev_flags & PORT_KEV_FREE) {
1453 /* Just discard event */
1454 list_remove(glist, pev);
1455 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1456 if (PORT_FREE_EVENT(pev))
1457 port_free_event_local(pev, B_TRUE);
1458 tnent--;
1459 continue;
1460 }
1461
1462 /* move event data to copyout list */
1463 if (port_copy_event32(&kevp32[nevents], pev, glist)) {
1464 /*
1465 * Event can not be delivered to the
1466 * current process.
1467 */
1468 if (lev != NULL)
1469 list_insert_after(glist, lev, pev);
1470 else
1471 list_insert_head(glist, pev);
1472 lev = pev; /* last checked event */
1473 } else {
1474 nevents++; /* # of events ready */
1475 }
1476 }
1477 #endif /* _SYSCALL32_IMPL */
1609 if (pkevp->portkev_flags & PORT_KEV_WIRED)
1610 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1611 else
1612 free_event = 1;
1613
1614 if (pkevp->portkev_callback) {
1615 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1616 &puevp->portev_events, pkevp->portkev_pid,
1617 PORT_CALLBACK_DEFAULT, pkevp);
1618
1619 if (error) {
1620 /*
1621 * Event can not be delivered.
1622 * Caller must reinsert the event into the queue.
1623 */
1624 pkevp->portkev_flags = flags;
1625 return (error);
1626 }
1627 }
1628 if (free_event)
1629 port_free_event_local(pkevp, B_TRUE);
1630 return (0);
1631 }
1632
1633 #ifdef _SYSCALL32_IMPL
1634 /*
1635 * 1. copy kernel event structure to user event structure.
1636 * 2. PORT_KEV_WIRED event structures will be reused by the "source"
1637 * 3. Remove PORT_KEV_DONEQ flag (event removed from the event queue)
1638 * 4. Other types of event structures can be delivered back to the port cache
1639 * (port_free_event_local()).
1640 * 5. The event source callback function is the last opportunity for the
1641 * event source to update events, to free local resources associated with
1642 * the event or to deny the delivery of the event.
1643 */
1644 static int
1645 port_copy_event32(port_event32_t *puevp, port_kevent_t *pkevp, list_t *list)
1646 {
1647 int free_event = 0;
1648 int error;
1649 int flags;
1664 flags = pkevp->portkev_flags;
1665 if (pkevp->portkev_flags & PORT_KEV_WIRED)
1666 pkevp->portkev_flags &= ~PORT_KEV_DONEQ;
1667 else
1668 free_event = 1;
1669
1670 if (pkevp->portkev_callback != NULL) {
1671 error = (*pkevp->portkev_callback)(pkevp->portkev_arg,
1672 &puevp->portev_events, pkevp->portkev_pid,
1673 PORT_CALLBACK_DEFAULT, pkevp);
1674 if (error) {
1675 /*
1676 * Event can not be delivered.
1677 * Caller must reinsert the event into the queue.
1678 */
1679 pkevp->portkev_flags = flags;
1680 return (error);
1681 }
1682 }
1683 if (free_event)
1684 port_free_event_local(pkevp, B_TRUE);
1685 return (0);
1686 }
1687 #endif /* _SYSCALL32_IMPL */
1688
1689 /*
1690 * copyout alert event.
1691 */
1692 static int
1693 port_get_alert(port_alert_t *pa, port_event_t *uevp)
1694 {
1695 model_t model = get_udatamodel();
1696
1697 /* copyout alert event structures to user space */
1698 if (model == DATAMODEL_NATIVE) {
1699 port_event_t uev;
1700 uev.portev_source = PORT_SOURCE_ALERT;
1701 uev.portev_object = pa->portal_object;
1702 uev.portev_events = pa->portal_events;
1703 uev.portev_user = pa->portal_user;
1704 if (copyout(&uev, uevp, sizeof (port_event_t)))
|