uma_core.c (95758) | uma_core.c (95766) |
---|---|
1/* 2 * Copyright (c) 2002, Jeffrey Roberson <jroberson@chesapeake.net> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * | 1/* 2 * Copyright (c) 2002, Jeffrey Roberson <jroberson@chesapeake.net> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/sys/vm/uma_core.c 95758 2002-04-29 23:45:41Z jeff $ | 26 * $FreeBSD: head/sys/vm/uma_core.c 95766 2002-04-30 04:26:34Z jeff $ |
27 * 28 */ 29 30/* 31 * uma_core.c Implementation of the Universal Memory allocator 32 * 33 * This allocator is intended to replace the multitude of similar object caches 34 * in the standard FreeBSD kernel. The intent is to be flexible as well as --- 1250 unchanged lines hidden (view full) --- 1285void 1286uma_zdestroy(uma_zone_t zone) 1287{ 1288 uma_zfree_internal(zones, zone, NULL, 0); 1289} 1290 1291/* See uma.h */ 1292void * | 27 * 28 */ 29 30/* 31 * uma_core.c Implementation of the Universal Memory allocator 32 * 33 * This allocator is intended to replace the multitude of similar object caches 34 * in the standard FreeBSD kernel. The intent is to be flexible as well as --- 1250 unchanged lines hidden (view full) --- 1285void 1286uma_zdestroy(uma_zone_t zone) 1287{ 1288 uma_zfree_internal(zones, zone, NULL, 0); 1289} 1290 1291/* See uma.h */ 1292void * |
1293uma_zalloc_arg(uma_zone_t zone, void *udata, int wait) | 1293uma_zalloc_arg(uma_zone_t zone, void *udata, int flags) |
1294{ 1295 void *item; 1296 uma_cache_t cache; 1297 uma_bucket_t bucket; 1298 int cpu; 1299 1300 /* This is the fast path allocation */ 1301#ifdef UMA_DEBUG_ALLOC_1 --- 16 unchanged lines hidden (view full) --- 1318#endif 1319 bucket->ub_ptr--; 1320 KASSERT(item != NULL, 1321 ("uma_zalloc: Bucket pointer mangled.")); 1322 cache->uc_allocs++; 1323 CPU_UNLOCK(zone, cpu); 1324 if (zone->uz_ctor) 1325 zone->uz_ctor(item, zone->uz_size, udata); | 1294{ 1295 void *item; 1296 uma_cache_t cache; 1297 uma_bucket_t bucket; 1298 int cpu; 1299 1300 /* This is the fast path allocation */ 1301#ifdef UMA_DEBUG_ALLOC_1 --- 16 unchanged lines hidden (view full) --- 1318#endif 1319 bucket->ub_ptr--; 1320 KASSERT(item != NULL, 1321 ("uma_zalloc: Bucket pointer mangled.")); 1322 cache->uc_allocs++; 1323 CPU_UNLOCK(zone, cpu); 1324 if (zone->uz_ctor) 1325 zone->uz_ctor(item, zone->uz_size, udata); |
1326 if (flags & M_ZERO) 1327 bzero(item, zone->uz_size); |
|
1326 return (item); 1327 } else if (cache->uc_freebucket) { 1328 /* 1329 * We have run out of items in our allocbucket. 1330 * See if we can switch with our free bucket. 1331 */ 1332 if (cache->uc_freebucket->ub_ptr > -1) { 1333 uma_bucket_t swap; --- 50 unchanged lines hidden (view full) --- 1384 if ((bucket = LIST_FIRST(&zone->uz_free_bucket)) != NULL) 1385 LIST_REMOVE(bucket, ub_link); 1386 1387 /* Now we no longer need the zone lock. */ 1388 ZONE_UNLOCK(zone); 1389 1390 if (bucket == NULL) 1391 bucket = uma_zalloc_internal(bucketzone, | 1328 return (item); 1329 } else if (cache->uc_freebucket) { 1330 /* 1331 * We have run out of items in our allocbucket. 1332 * See if we can switch with our free bucket. 1333 */ 1334 if (cache->uc_freebucket->ub_ptr > -1) { 1335 uma_bucket_t swap; --- 50 unchanged lines hidden (view full) --- 1386 if ((bucket = LIST_FIRST(&zone->uz_free_bucket)) != NULL) 1387 LIST_REMOVE(bucket, ub_link); 1388 1389 /* Now we no longer need the zone lock. */ 1390 ZONE_UNLOCK(zone); 1391 1392 if (bucket == NULL) 1393 bucket = uma_zalloc_internal(bucketzone, |
1392 NULL, wait, NULL); | 1394 NULL, flags, NULL); |
1393 1394 if (bucket != NULL) { 1395#ifdef INVARIANTS 1396 bzero(bucket, bucketzone->uz_size); 1397#endif 1398 bucket->ub_ptr = -1; 1399 | 1395 1396 if (bucket != NULL) { 1397#ifdef INVARIANTS 1398 bzero(bucket, bucketzone->uz_size); 1399#endif 1400 bucket->ub_ptr = -1; 1401 |
1400 if (uma_zalloc_internal(zone, udata, wait, bucket)) | 1402 if (uma_zalloc_internal(zone, udata, flags, bucket)) |
1401 goto zalloc_restart; 1402 else 1403 uma_zfree_internal(bucketzone, bucket, NULL, 0); 1404 } 1405 /* 1406 * We may not get a bucket if we recurse, so 1407 * return an actual item. 1408 */ 1409#ifdef UMA_DEBUG 1410 printf("uma_zalloc_arg: Bucketzone returned NULL\n"); 1411#endif 1412 | 1403 goto zalloc_restart; 1404 else 1405 uma_zfree_internal(bucketzone, bucket, NULL, 0); 1406 } 1407 /* 1408 * We may not get a bucket if we recurse, so 1409 * return an actual item. 1410 */ 1411#ifdef UMA_DEBUG 1412 printf("uma_zalloc_arg: Bucketzone returned NULL\n"); 1413#endif 1414 |
1413 return (uma_zalloc_internal(zone, udata, wait, NULL)); | 1415 return (uma_zalloc_internal(zone, udata, flags, NULL)); |
1414} 1415 1416/* 1417 * Allocates an item for an internal zone OR fills a bucket 1418 * 1419 * Arguments 1420 * zone The zone to alloc for. 1421 * udata The data to be passed to the constructor. | 1416} 1417 1418/* 1419 * Allocates an item for an internal zone OR fills a bucket 1420 * 1421 * Arguments 1422 * zone The zone to alloc for. 1423 * udata The data to be passed to the constructor. |
1422 * wait M_WAITOK or M_NOWAIT. | 1424 * flags M_WAITOK, M_NOWAIT, M_ZERO. |
1423 * bucket The bucket to fill or NULL 1424 * 1425 * Returns 1426 * NULL if there is no memory and M_NOWAIT is set 1427 * An item if called on an interal zone 1428 * Non NULL if called to fill a bucket and it was successful. 1429 * 1430 * Discussion: 1431 * This was much cleaner before it had to do per cpu caches. It is 1432 * complicated now because it has to handle the simple internal case, and 1433 * the more involved bucket filling and allocation. 1434 */ 1435 1436static void * | 1425 * bucket The bucket to fill or NULL 1426 * 1427 * Returns 1428 * NULL if there is no memory and M_NOWAIT is set 1429 * An item if called on an interal zone 1430 * Non NULL if called to fill a bucket and it was successful. 1431 * 1432 * Discussion: 1433 * This was much cleaner before it had to do per cpu caches. It is 1434 * complicated now because it has to handle the simple internal case, and 1435 * the more involved bucket filling and allocation. 1436 */ 1437 1438static void * |
1437uma_zalloc_internal(uma_zone_t zone, void *udata, int wait, uma_bucket_t bucket) | 1439uma_zalloc_internal(uma_zone_t zone, void *udata, int flags, uma_bucket_t bucket) |
1438{ 1439 uma_slab_t slab; 1440 u_int8_t freei; 1441 void *item; 1442 1443 item = NULL; 1444 1445 /* --- 52 unchanged lines hidden (view full) --- 1498 if (zone == bucketzone && zone->uz_recurse != 0) { 1499 ZONE_UNLOCK(zone); 1500 return (NULL); 1501 } 1502 while (zone->uz_maxpages && 1503 zone->uz_pages >= zone->uz_maxpages) { 1504 zone->uz_flags |= UMA_ZFLAG_FULL; 1505 | 1440{ 1441 uma_slab_t slab; 1442 u_int8_t freei; 1443 void *item; 1444 1445 item = NULL; 1446 1447 /* --- 52 unchanged lines hidden (view full) --- 1500 if (zone == bucketzone && zone->uz_recurse != 0) { 1501 ZONE_UNLOCK(zone); 1502 return (NULL); 1503 } 1504 while (zone->uz_maxpages && 1505 zone->uz_pages >= zone->uz_maxpages) { 1506 zone->uz_flags |= UMA_ZFLAG_FULL; 1507 |
1506 if (wait & M_WAITOK) | 1508 if (flags & M_WAITOK) |
1507 msleep(zone, &zone->uz_lock, PVM, "zonelimit", 0); 1508 else 1509 goto alloc_fail; 1510 1511 goto new_slab; 1512 } 1513 1514 zone->uz_recurse++; | 1509 msleep(zone, &zone->uz_lock, PVM, "zonelimit", 0); 1510 else 1511 goto alloc_fail; 1512 1513 goto new_slab; 1514 } 1515 1516 zone->uz_recurse++; |
1515 slab = slab_zalloc(zone, wait); | 1517 slab = slab_zalloc(zone, flags); |
1516 zone->uz_recurse--; 1517 /* 1518 * We might not have been able to get a slab but another cpu 1519 * could have while we were unlocked. If we did get a slab put 1520 * it on the partially used slab list. If not check the free 1521 * count and restart or fail accordingly. 1522 */ 1523 if (slab) --- 36 unchanged lines hidden (view full) --- 1560 if (slab->us_freecount == 0) { 1561 LIST_REMOVE(slab, us_link); 1562 LIST_INSERT_HEAD(&zone->uz_full_slab, slab, us_link); 1563 } 1564 1565 if (bucket != NULL) { 1566 /* Try to keep the buckets totally full, but don't block */ 1567 if (bucket->ub_ptr < zone->uz_count) { | 1518 zone->uz_recurse--; 1519 /* 1520 * We might not have been able to get a slab but another cpu 1521 * could have while we were unlocked. If we did get a slab put 1522 * it on the partially used slab list. If not check the free 1523 * count and restart or fail accordingly. 1524 */ 1525 if (slab) --- 36 unchanged lines hidden (view full) --- 1562 if (slab->us_freecount == 0) { 1563 LIST_REMOVE(slab, us_link); 1564 LIST_INSERT_HEAD(&zone->uz_full_slab, slab, us_link); 1565 } 1566 1567 if (bucket != NULL) { 1568 /* Try to keep the buckets totally full, but don't block */ 1569 if (bucket->ub_ptr < zone->uz_count) { |
1568 wait = M_NOWAIT; | 1570 flags |= M_NOWAIT; 1571 flags &= ~M_WAITOK; |
1569 goto new_slab; 1570 } else 1571 zone->uz_fills--; 1572 } 1573 1574 ZONE_UNLOCK(zone); 1575 1576 /* Only construct at this time if we're not filling a bucket */ | 1572 goto new_slab; 1573 } else 1574 zone->uz_fills--; 1575 } 1576 1577 ZONE_UNLOCK(zone); 1578 1579 /* Only construct at this time if we're not filling a bucket */ |
1577 if (bucket == NULL && zone->uz_ctor != NULL) | 1580 if (bucket == NULL && zone->uz_ctor != NULL) { |
1578 zone->uz_ctor(item, zone->uz_size, udata); | 1581 zone->uz_ctor(item, zone->uz_size, udata); |
1582 if (flags & M_ZERO) 1583 bzero(item, zone->uz_size); 1584 } |
|
1579 1580 return (item); 1581 1582alloc_fail: 1583 if (bucket != NULL) 1584 zone->uz_fills--; 1585 ZONE_UNLOCK(zone); 1586 --- 455 unchanged lines hidden --- | 1585 1586 return (item); 1587 1588alloc_fail: 1589 if (bucket != NULL) 1590 zone->uz_fills--; 1591 ZONE_UNLOCK(zone); 1592 --- 455 unchanged lines hidden --- |