Print this page
11927 Log, or optionally panic, on zero-length kmem allocations
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Jason King <jason.brian.king@gmail.com>


   7  *
   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 #include <sys/types.h>
  28 #include <sys/systm.h>
  29 #include <sys/cred.h>
  30 #include <sys/modctl.h>
  31 #include <sys/vfs.h>
  32 #include <sys/vfs_opreg.h>
  33 #include <sys/sysmacros.h>
  34 #include <sys/cmn_err.h>
  35 #include <sys/stat.h>
  36 #include <sys/errno.h>
  37 #include <sys/kmem.h>
  38 #include <sys/file.h>
  39 #include <sys/kstat.h>
  40 #include <sys/port_impl.h>
  41 #include <sys/task.h>
  42 #include <sys/project.h>
  43 
  44 /*
  45  * Event Ports can be shared across threads or across processes.
  46  * Every thread/process can use an own event port or a group of them


1362         port_block(portq);      /* block other threads here */
1363         nmax = max < portq->portq_nent ? max : portq->portq_nent;
1364 
1365         if (portq->portq_tnent) {
1366                 /*
1367                  * Move remaining events from previous thread back to the
1368                  * port event queue.
1369                  */
1370                 port_push_eventq(portq);
1371         }
1372         /* move port event queue to a temporary queue */
1373         list_move_tail(&portq->portq_get_list, &portq->portq_list);
1374         glist = &portq->portq_get_list;  /* use temporary event queue */
1375         tnent = portq->portq_nent;   /* get current number of events */
1376         portq->portq_nent = 0;               /* no events in the port event queue */
1377         portq->portq_flags |= PORTQ_WAIT_EVENTS; /* detect incoming events */
1378         mutex_exit(&portq->portq_mutex);    /* event queue can be reused now */
1379 
1380         if (model == DATAMODEL_NATIVE) {
1381                 eventsz = sizeof (port_event_t);




1382                 kevp = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1383                 if (kevp == NULL) {
1384                         if (nmax > pp->port_max_list)
1385                                 nmax = pp->port_max_list;
1386                         kevp = kmem_alloc(eventsz * nmax, KM_SLEEP);
1387                 }


1388                 results = kevp;
1389                 lev = NULL;     /* start with first event in the queue */
1390                 for (nevents = 0; nevents < nmax; ) {
1391                         pev = port_get_kevent(glist, lev);
1392                         if (pev == NULL)        /* no more events available */
1393                                 break;
1394                         if (pev->portkev_flags & PORT_KEV_FREE) {
1395                                 /* Just discard event */
1396                                 list_remove(glist, pev);
1397                                 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1398                                 if (PORT_FREE_EVENT(pev))
1399                                         port_free_event_local(pev, 0);
1400                                 tnent--;
1401                                 continue;
1402                         }
1403 
1404                         /* move event data to copyout list */
1405                         if (port_copy_event(&kevp[nevents], pev, glist)) {
1406                                 /*
1407                                  * Event can not be delivered to the
1408                                  * current process.
1409                                  */
1410                                 if (lev != NULL)
1411                                         list_insert_after(glist, lev, pev);
1412                                 else
1413                                         list_insert_head(glist, pev);
1414                                 lev = pev;  /* last checked event */
1415                         } else {
1416                                 nevents++;      /* # of events ready */
1417                         }
1418                 }
1419 #ifdef  _SYSCALL32_IMPL
1420         } else {
1421                 port_event32_t  *kevp32;
1422 
1423                 eventsz = sizeof (port_event32_t);




1424                 kevp32 = kmem_alloc(eventsz * nmax, KM_NOSLEEP);
1425                 if (kevp32 == NULL) {
1426                         if (nmax > pp->port_max_list)
1427                                 nmax = pp->port_max_list;
1428                         kevp32 = kmem_alloc(eventsz * nmax, KM_SLEEP);
1429                 }


1430                 results = kevp32;
1431                 lev = NULL;     /* start with first event in the queue */
1432                 for (nevents = 0; nevents < nmax; ) {
1433                         pev = port_get_kevent(glist, lev);
1434                         if (pev == NULL)        /* no more events available */
1435                                 break;
1436                         if (pev->portkev_flags & PORT_KEV_FREE) {
1437                                 /* Just discard event */
1438                                 list_remove(glist, pev);
1439                                 pev->portkev_flags &= ~(PORT_CLEANUP_DONE);
1440                                 if (PORT_FREE_EVENT(pev))
1441                                         port_free_event_local(pev, 0);
1442                                 tnent--;
1443                                 continue;
1444                         }
1445 
1446                         /* move event data to copyout list */
1447                         if (port_copy_event32(&kevp32[nevents], pev, glist)) {
1448                                 /*
1449                                  * Event can not be delivered to the




   7  *
   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 /*
  49  * Event Ports can be shared across threads or across processes.
  50  * Every thread/process can use an own event port or a group of them


1366         port_block(portq);      /* block other threads here */
1367         nmax = max < portq->portq_nent ? max : portq->portq_nent;
1368 
1369         if (portq->portq_tnent) {
1370                 /*
1371                  * Move remaining events from previous thread back to the
1372                  * port event queue.
1373                  */
1374                 port_push_eventq(portq);
1375         }
1376         /* move port event queue to a temporary queue */
1377         list_move_tail(&portq->portq_get_list, &portq->portq_list);
1378         glist = &portq->portq_get_list;  /* use temporary event queue */
1379         tnent = portq->portq_nent;   /* get current number of events */
1380         portq->portq_nent = 0;               /* no events in the port event queue */
1381         portq->portq_flags |= PORTQ_WAIT_EVENTS; /* detect incoming events */
1382         mutex_exit(&portq->portq_mutex);    /* event queue can be reused now */
1383 
1384         if (model == DATAMODEL_NATIVE) {
1385                 eventsz = sizeof (port_event_t);
1386 
1387                 if (nmax == 0) {
1388                         kevp = NULL;
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
1430         } else {
1431                 port_event32_t  *kevp32;
1432 
1433                 eventsz = sizeof (port_event32_t);
1434 
1435                 if (nmax == 0) {
1436                         kevp32 = NULL;
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