uma_core.c (251709) | uma_core.c (251826) |
---|---|
1/*- 2 * Copyright (c) 2002-2005, 2009, 2013 Jeffrey Roberson <jeff@FreeBSD.org> 3 * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@FreeBSD.org> 4 * Copyright (c) 2004-2006 Robert N. M. Watson 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 34 unchanged lines hidden (view full) --- 43 44/* 45 * TODO: 46 * - Improve memory usage for large allocations 47 * - Investigate cache size adjustments 48 */ 49 50#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2002-2005, 2009, 2013 Jeffrey Roberson <jeff@FreeBSD.org> 3 * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@FreeBSD.org> 4 * Copyright (c) 2004-2006 Robert N. M. Watson 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 34 unchanged lines hidden (view full) --- 43 44/* 45 * TODO: 46 * - Improve memory usage for large allocations 47 * - Investigate cache size adjustments 48 */ 49 50#include <sys/cdefs.h> |
51__FBSDID("$FreeBSD: head/sys/vm/uma_core.c 251709 2013-06-13 21:05:38Z jeff $"); | 51__FBSDID("$FreeBSD: head/sys/vm/uma_core.c 251826 2013-06-17 03:43:47Z jeff $"); |
52 53/* I should really use ktr.. */ 54/* 55#define UMA_DEBUG 1 56#define UMA_DEBUG_ALLOC 1 57#define UMA_DEBUG_ALLOC_1 1 58*/ 59 --- 66 unchanged lines hidden (view full) --- 126 * Are we allowed to allocate buckets? 127 */ 128static int bucketdisable = 1; 129 130/* Linked list of all kegs in the system */ 131static LIST_HEAD(,uma_keg) uma_kegs = LIST_HEAD_INITIALIZER(uma_kegs); 132 133/* This mutex protects the keg list */ | 52 53/* I should really use ktr.. */ 54/* 55#define UMA_DEBUG 1 56#define UMA_DEBUG_ALLOC 1 57#define UMA_DEBUG_ALLOC_1 1 58*/ 59 --- 66 unchanged lines hidden (view full) --- 126 * Are we allowed to allocate buckets? 127 */ 128static int bucketdisable = 1; 129 130/* Linked list of all kegs in the system */ 131static LIST_HEAD(,uma_keg) uma_kegs = LIST_HEAD_INITIALIZER(uma_kegs); 132 133/* This mutex protects the keg list */ |
134static struct mtx uma_mtx; | 134static struct mtx_padalign uma_mtx; |
135 136/* Linked list of boot time pages */ 137static LIST_HEAD(,uma_slab) uma_boot_pages = 138 LIST_HEAD_INITIALIZER(uma_boot_pages); 139 140/* This mutex protects the boot time pages list */ | 135 136/* Linked list of boot time pages */ 137static LIST_HEAD(,uma_slab) uma_boot_pages = 138 LIST_HEAD_INITIALIZER(uma_boot_pages); 139 140/* This mutex protects the boot time pages list */ |
141static struct mtx uma_boot_pages_mtx; | 141static struct mtx_padalign uma_boot_pages_mtx; |
142 143/* Is the VM done starting up? */ 144static int booted = 0; 145#define UMA_STARTUP 1 146#define UMA_STARTUP2 2 147 148/* Maximum number of allowed items-per-slab if the slab header is OFFPAGE */ 149static const u_int uma_max_ipers = SLAB_SETSIZE; --- 17 unchanged lines hidden (view full) --- 167 */ 168struct uma_zctor_args { 169 const char *name; 170 size_t size; 171 uma_ctor ctor; 172 uma_dtor dtor; 173 uma_init uminit; 174 uma_fini fini; | 142 143/* Is the VM done starting up? */ 144static int booted = 0; 145#define UMA_STARTUP 1 146#define UMA_STARTUP2 2 147 148/* Maximum number of allowed items-per-slab if the slab header is OFFPAGE */ 149static const u_int uma_max_ipers = SLAB_SETSIZE; --- 17 unchanged lines hidden (view full) --- 167 */ 168struct uma_zctor_args { 169 const char *name; 170 size_t size; 171 uma_ctor ctor; 172 uma_dtor dtor; 173 uma_init uminit; 174 uma_fini fini; |
175 uma_import import; 176 uma_release release; 177 void *arg; |
|
175 uma_keg_t keg; 176 int align; 177 uint32_t flags; 178}; 179 180struct uma_kctor_args { 181 uma_zone_t zone; 182 size_t size; --- 28 unchanged lines hidden (view full) --- 211 */ 212static uint8_t bucket_size[BUCKET_ZONES]; 213 214/* 215 * Flags and enumerations to be passed to internal functions. 216 */ 217enum zfreeskip { SKIP_NONE = 0, SKIP_DTOR, SKIP_FINI }; 218 | 178 uma_keg_t keg; 179 int align; 180 uint32_t flags; 181}; 182 183struct uma_kctor_args { 184 uma_zone_t zone; 185 size_t size; --- 28 unchanged lines hidden (view full) --- 214 */ 215static uint8_t bucket_size[BUCKET_ZONES]; 216 217/* 218 * Flags and enumerations to be passed to internal functions. 219 */ 220enum zfreeskip { SKIP_NONE = 0, SKIP_DTOR, SKIP_FINI }; 221 |
219#define ZFREE_STATFAIL 0x00000001 /* Update zone failure statistic. */ 220#define ZFREE_STATFREE 0x00000002 /* Update zone free statistic. */ 221 | |
222/* Prototypes.. */ 223 224static void *noobj_alloc(uma_zone_t, int, uint8_t *, int); 225static void *page_alloc(uma_zone_t, int, uint8_t *, int); 226static void *startup_alloc(uma_zone_t, int, uint8_t *, int); 227static void page_free(void *, int, uint8_t); 228static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int); 229static void cache_drain(uma_zone_t); --- 9 unchanged lines hidden (view full) --- 239static void zone_foreach(void (*zfunc)(uma_zone_t)); 240static void zone_timeout(uma_zone_t zone); 241static int hash_alloc(struct uma_hash *); 242static int hash_expand(struct uma_hash *, struct uma_hash *); 243static void hash_free(struct uma_hash *hash); 244static void uma_timeout(void *); 245static void uma_startup3(void); 246static void *zone_alloc_item(uma_zone_t, void *, int); | 222/* Prototypes.. */ 223 224static void *noobj_alloc(uma_zone_t, int, uint8_t *, int); 225static void *page_alloc(uma_zone_t, int, uint8_t *, int); 226static void *startup_alloc(uma_zone_t, int, uint8_t *, int); 227static void page_free(void *, int, uint8_t); 228static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int); 229static void cache_drain(uma_zone_t); --- 9 unchanged lines hidden (view full) --- 239static void zone_foreach(void (*zfunc)(uma_zone_t)); 240static void zone_timeout(uma_zone_t zone); 241static int hash_alloc(struct uma_hash *); 242static int hash_expand(struct uma_hash *, struct uma_hash *); 243static void hash_free(struct uma_hash *hash); 244static void uma_timeout(void *); 245static void uma_startup3(void); 246static void *zone_alloc_item(uma_zone_t, void *, int); |
247static void zone_free_item(uma_zone_t, void *, void *, enum zfreeskip, 248 int); | 247static void zone_free_item(uma_zone_t, void *, void *, enum zfreeskip); |
249static void bucket_enable(void); 250static void bucket_init(void); 251static uma_bucket_t bucket_alloc(int, int); 252static void bucket_free(uma_bucket_t); 253static void bucket_zone_drain(void); 254static int zone_alloc_bucket(uma_zone_t zone, int flags); 255static uma_slab_t zone_fetch_slab(uma_zone_t zone, uma_keg_t last, int flags); 256static uma_slab_t zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int flags); | 248static void bucket_enable(void); 249static void bucket_init(void); 250static uma_bucket_t bucket_alloc(int, int); 251static void bucket_free(uma_bucket_t); 252static void bucket_zone_drain(void); 253static int zone_alloc_bucket(uma_zone_t zone, int flags); 254static uma_slab_t zone_fetch_slab(uma_zone_t zone, uma_keg_t last, int flags); 255static uma_slab_t zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int flags); |
257static void *slab_alloc_item(uma_zone_t zone, uma_slab_t slab); | 256static void *slab_alloc_item(uma_keg_t keg, uma_slab_t slab); 257static void slab_free_item(uma_keg_t keg, uma_slab_t slab, void *item); |
258static uma_keg_t uma_kcreate(uma_zone_t zone, size_t size, uma_init uminit, 259 uma_fini fini, int align, uint32_t flags); 260static inline void zone_relock(uma_zone_t zone, uma_keg_t keg); 261static inline void keg_relock(uma_keg_t keg, uma_zone_t zone); | 258static uma_keg_t uma_kcreate(uma_zone_t zone, size_t size, uma_init uminit, 259 uma_fini fini, int align, uint32_t flags); 260static inline void zone_relock(uma_zone_t zone, uma_keg_t keg); 261static inline void keg_relock(uma_keg_t keg, uma_zone_t zone); |
262static int zone_import(uma_zone_t zone, void **bucket, int max, int flags); 263static void zone_release(uma_zone_t zone, void **bucket, int cnt); |
|
262 263void uma_print_zone(uma_zone_t); 264void uma_print_stats(void); 265static int sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS); 266static int sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS); 267 268SYSINIT(uma_startup3, SI_SUB_VM_CONF, SI_ORDER_SECOND, uma_startup3, NULL); 269 --- 88 unchanged lines hidden (view full) --- 358} 359 360static void 361bucket_free(uma_bucket_t bucket) 362{ 363 struct uma_bucket_zone *ubz; 364 365 ubz = bucket_zone_lookup(bucket->ub_entries); | 264 265void uma_print_zone(uma_zone_t); 266void uma_print_stats(void); 267static int sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS); 268static int sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS); 269 270SYSINIT(uma_startup3, SI_SUB_VM_CONF, SI_ORDER_SECOND, uma_startup3, NULL); 271 --- 88 unchanged lines hidden (view full) --- 360} 361 362static void 363bucket_free(uma_bucket_t bucket) 364{ 365 struct uma_bucket_zone *ubz; 366 367 ubz = bucket_zone_lookup(bucket->ub_entries); |
366 zone_free_item(ubz->ubz_zone, bucket, NULL, SKIP_NONE, 367 ZFREE_STATFREE); | 368 zone_free_item(ubz->ubz_zone, bucket, NULL, SKIP_NONE); |
368} 369 370static void 371bucket_zone_drain(void) 372{ 373 struct uma_bucket_zone *ubz; 374 375 for (ubz = &bucket_zones[0]; ubz->ubz_entries != 0; ubz++) --- 7 unchanged lines hidden (view full) --- 383 384 if (!zone_warnings || zone->uz_warning == NULL) 385 return; 386 387 if (ratecheck(&zone->uz_ratecheck, &warninterval)) 388 printf("[zone: %s] %s\n", zone->uz_name, zone->uz_warning); 389} 390 | 369} 370 371static void 372bucket_zone_drain(void) 373{ 374 struct uma_bucket_zone *ubz; 375 376 for (ubz = &bucket_zones[0]; ubz->ubz_entries != 0; ubz++) --- 7 unchanged lines hidden (view full) --- 384 385 if (!zone_warnings || zone->uz_warning == NULL) 386 return; 387 388 if (ratecheck(&zone->uz_ratecheck, &warninterval)) 389 printf("[zone: %s] %s\n", zone->uz_name, zone->uz_warning); 390} 391 |
391static inline uma_keg_t 392zone_first_keg(uma_zone_t zone) 393{ 394 395 return (LIST_FIRST(&zone->uz_kegs)->kl_keg); 396} 397 | |
398static void 399zone_foreach_keg(uma_zone_t zone, void (*kegfn)(uma_keg_t)) 400{ 401 uma_klink_t klink; 402 403 LIST_FOREACH(klink, &zone->uz_kegs, kl_link) 404 kegfn(klink->kl_keg); 405} --- 168 unchanged lines hidden (view full) --- 574 * Nothing 575 */ 576static void 577hash_free(struct uma_hash *hash) 578{ 579 if (hash->uh_slab_hash == NULL) 580 return; 581 if (hash->uh_hashsize == UMA_HASH_SIZE_INIT) | 392static void 393zone_foreach_keg(uma_zone_t zone, void (*kegfn)(uma_keg_t)) 394{ 395 uma_klink_t klink; 396 397 LIST_FOREACH(klink, &zone->uz_kegs, kl_link) 398 kegfn(klink->kl_keg); 399} --- 168 unchanged lines hidden (view full) --- 568 * Nothing 569 */ 570static void 571hash_free(struct uma_hash *hash) 572{ 573 if (hash->uh_slab_hash == NULL) 574 return; 575 if (hash->uh_hashsize == UMA_HASH_SIZE_INIT) |
582 zone_free_item(hashzone, 583 hash->uh_slab_hash, NULL, SKIP_NONE, ZFREE_STATFREE); | 576 zone_free_item(hashzone, hash->uh_slab_hash, NULL, SKIP_NONE); |
584 else 585 free(hash->uh_slab_hash, M_UMAHASH); 586} 587 588/* 589 * Frees all outstanding items in a bucket 590 * 591 * Arguments: 592 * zone The zone to free to, must be unlocked. 593 * bucket The free/alloc bucket with items, cpu queue must be locked. 594 * 595 * Returns: 596 * Nothing 597 */ 598 599static void 600bucket_drain(uma_zone_t zone, uma_bucket_t bucket) 601{ | 577 else 578 free(hash->uh_slab_hash, M_UMAHASH); 579} 580 581/* 582 * Frees all outstanding items in a bucket 583 * 584 * Arguments: 585 * zone The zone to free to, must be unlocked. 586 * bucket The free/alloc bucket with items, cpu queue must be locked. 587 * 588 * Returns: 589 * Nothing 590 */ 591 592static void 593bucket_drain(uma_zone_t zone, uma_bucket_t bucket) 594{ |
602 void *item; | 595 int i; |
603 604 if (bucket == NULL) 605 return; 606 | 596 597 if (bucket == NULL) 598 return; 599 |
607 while (bucket->ub_cnt > 0) { 608 bucket->ub_cnt--; 609 item = bucket->ub_bucket[bucket->ub_cnt]; 610#ifdef INVARIANTS 611 bucket->ub_bucket[bucket->ub_cnt] = NULL; 612 KASSERT(item != NULL, 613 ("bucket_drain: botched ptr, item is NULL")); 614#endif 615 zone_free_item(zone, item, NULL, SKIP_DTOR, 0); 616 } | 600 if (zone->uz_fini) 601 for (i = 0; i < bucket->ub_cnt; i++) 602 zone->uz_fini(bucket->ub_bucket[i], zone->uz_size); 603 zone->uz_release(zone->uz_arg, bucket->ub_bucket, bucket->ub_cnt); 604 bucket->ub_cnt = 0; |
617} 618 619/* 620 * Drains the per cpu caches for a zone. 621 * 622 * NOTE: This may only be called while the zone is being turn down, and not 623 * during normal operation. This is necessary in order that we do not have 624 * to migrate CPUs to drain the per-CPU caches. --- 137 unchanged lines hidden (view full) --- 762 obj = kernel_object; 763 else 764 obj = NULL; 765 for (i = 0; i < keg->uk_ppera; i++) 766 vsetobj((vm_offset_t)mem + (i * PAGE_SIZE), 767 obj); 768 } 769 if (keg->uk_flags & UMA_ZONE_OFFPAGE) | 605} 606 607/* 608 * Drains the per cpu caches for a zone. 609 * 610 * NOTE: This may only be called while the zone is being turn down, and not 611 * during normal operation. This is necessary in order that we do not have 612 * to migrate CPUs to drain the per-CPU caches. --- 137 unchanged lines hidden (view full) --- 750 obj = kernel_object; 751 else 752 obj = NULL; 753 for (i = 0; i < keg->uk_ppera; i++) 754 vsetobj((vm_offset_t)mem + (i * PAGE_SIZE), 755 obj); 756 } 757 if (keg->uk_flags & UMA_ZONE_OFFPAGE) |
770 zone_free_item(keg->uk_slabzone, slab, NULL, 771 SKIP_NONE, ZFREE_STATFREE); | 758 zone_free_item(keg->uk_slabzone, slab, NULL, SKIP_NONE); |
772#ifdef UMA_DEBUG 773 printf("%s: Returning %d bytes.\n", 774 keg->uk_name, PAGE_SIZE * keg->uk_ppera); 775#endif 776 keg->uk_freef(mem, PAGE_SIZE * keg->uk_ppera, flags); 777 } 778} 779 --- 57 unchanged lines hidden (view full) --- 837 uint8_t *mem; 838 uint8_t flags; 839 int i; 840 841 mtx_assert(&keg->uk_lock, MA_OWNED); 842 slab = NULL; 843 844#ifdef UMA_DEBUG | 759#ifdef UMA_DEBUG 760 printf("%s: Returning %d bytes.\n", 761 keg->uk_name, PAGE_SIZE * keg->uk_ppera); 762#endif 763 keg->uk_freef(mem, PAGE_SIZE * keg->uk_ppera, flags); 764 } 765} 766 --- 57 unchanged lines hidden (view full) --- 824 uint8_t *mem; 825 uint8_t flags; 826 int i; 827 828 mtx_assert(&keg->uk_lock, MA_OWNED); 829 slab = NULL; 830 831#ifdef UMA_DEBUG |
845 printf("slab_zalloc: Allocating a new slab for %s\n", keg->uk_name); | 832 printf("alloc_slab: Allocating a new slab for %s\n", keg->uk_name); |
846#endif 847 allocf = keg->uk_allocf; 848 KEG_UNLOCK(keg); 849 850 if (keg->uk_flags & UMA_ZONE_OFFPAGE) { 851 slab = zone_alloc_item(keg->uk_slabzone, NULL, wait); 852 if (slab == NULL) { 853 KEG_LOCK(keg); --- 15 unchanged lines hidden (view full) --- 869 870 if (keg->uk_flags & UMA_ZONE_NODUMP) 871 wait |= M_NODUMP; 872 873 /* zone is passed for legacy reasons. */ 874 mem = allocf(zone, keg->uk_ppera * PAGE_SIZE, &flags, wait); 875 if (mem == NULL) { 876 if (keg->uk_flags & UMA_ZONE_OFFPAGE) | 833#endif 834 allocf = keg->uk_allocf; 835 KEG_UNLOCK(keg); 836 837 if (keg->uk_flags & UMA_ZONE_OFFPAGE) { 838 slab = zone_alloc_item(keg->uk_slabzone, NULL, wait); 839 if (slab == NULL) { 840 KEG_LOCK(keg); --- 15 unchanged lines hidden (view full) --- 856 857 if (keg->uk_flags & UMA_ZONE_NODUMP) 858 wait |= M_NODUMP; 859 860 /* zone is passed for legacy reasons. */ 861 mem = allocf(zone, keg->uk_ppera * PAGE_SIZE, &flags, wait); 862 if (mem == NULL) { 863 if (keg->uk_flags & UMA_ZONE_OFFPAGE) |
877 zone_free_item(keg->uk_slabzone, slab, NULL, 878 SKIP_NONE, ZFREE_STATFREE); | 864 zone_free_item(keg->uk_slabzone, slab, NULL, SKIP_NONE); |
879 KEG_LOCK(keg); 880 return (NULL); 881 } 882 883 /* Point the slab into the allocated memory */ 884 if (!(keg->uk_flags & UMA_ZONE_OFFPAGE)) 885 slab = (uma_slab_t )(mem + keg->uk_pgoff); 886 --- 37 unchanged lines hidden (view full) --- 924 else 925 obj = NULL; 926 for (i = 0; i < keg->uk_ppera; i++) 927 vsetobj((vm_offset_t)mem + 928 (i * PAGE_SIZE), obj); 929 } 930 if (keg->uk_flags & UMA_ZONE_OFFPAGE) 931 zone_free_item(keg->uk_slabzone, slab, | 865 KEG_LOCK(keg); 866 return (NULL); 867 } 868 869 /* Point the slab into the allocated memory */ 870 if (!(keg->uk_flags & UMA_ZONE_OFFPAGE)) 871 slab = (uma_slab_t )(mem + keg->uk_pgoff); 872 --- 37 unchanged lines hidden (view full) --- 910 else 911 obj = NULL; 912 for (i = 0; i < keg->uk_ppera; i++) 913 vsetobj((vm_offset_t)mem + 914 (i * PAGE_SIZE), obj); 915 } 916 if (keg->uk_flags & UMA_ZONE_OFFPAGE) 917 zone_free_item(keg->uk_slabzone, slab, |
932 NULL, SKIP_NONE, ZFREE_STATFREE); | 918 NULL, SKIP_NONE); |
933 keg->uk_freef(mem, PAGE_SIZE * keg->uk_ppera, 934 flags); 935 KEG_LOCK(keg); 936 return (NULL); 937 } 938 } 939 KEG_LOCK(keg); 940 --- 537 unchanged lines hidden (view full) --- 1478 zone->uz_fails = 0; 1479 zone->uz_sleeps = 0; 1480 zone->uz_fills = zone->uz_count = 0; 1481 zone->uz_flags = 0; 1482 zone->uz_warning = NULL; 1483 timevalclear(&zone->uz_ratecheck); 1484 keg = arg->keg; 1485 | 919 keg->uk_freef(mem, PAGE_SIZE * keg->uk_ppera, 920 flags); 921 KEG_LOCK(keg); 922 return (NULL); 923 } 924 } 925 KEG_LOCK(keg); 926 --- 537 unchanged lines hidden (view full) --- 1464 zone->uz_fails = 0; 1465 zone->uz_sleeps = 0; 1466 zone->uz_fills = zone->uz_count = 0; 1467 zone->uz_flags = 0; 1468 zone->uz_warning = NULL; 1469 timevalclear(&zone->uz_ratecheck); 1470 keg = arg->keg; 1471 |
1472 /* 1473 * This is a pure cache zone, no kegs. 1474 */ 1475 if (arg->import) { 1476 zone->uz_import = arg->import; 1477 zone->uz_release = arg->release; 1478 zone->uz_arg = arg->arg; 1479 zone->uz_count = BUCKET_MAX; 1480 return (0); 1481 } 1482 1483 /* 1484 * Use the regular zone/keg/slab allocator. 1485 */ 1486 zone->uz_import = (uma_import)zone_import; 1487 zone->uz_release = (uma_release)zone_release; 1488 zone->uz_arg = zone; 1489 |
|
1486 if (arg->flags & UMA_ZONE_SECONDARY) { 1487 KASSERT(arg->keg != NULL, ("Secondary zone on zero'd keg")); 1488 zone->uz_init = arg->uminit; 1489 zone->uz_fini = arg->fini; 1490 zone->uz_lock = &keg->uk_lock; 1491 zone->uz_flags |= UMA_ZONE_SECONDARY; 1492 mtx_lock(&uma_mtx); 1493 ZONE_LOCK(zone); --- 20 unchanged lines hidden (view full) --- 1514 karg.align = arg->align; 1515 karg.flags = arg->flags; 1516 karg.zone = zone; 1517 error = keg_ctor(arg->keg, sizeof(struct uma_keg), &karg, 1518 flags); 1519 if (error) 1520 return (error); 1521 } | 1490 if (arg->flags & UMA_ZONE_SECONDARY) { 1491 KASSERT(arg->keg != NULL, ("Secondary zone on zero'd keg")); 1492 zone->uz_init = arg->uminit; 1493 zone->uz_fini = arg->fini; 1494 zone->uz_lock = &keg->uk_lock; 1495 zone->uz_flags |= UMA_ZONE_SECONDARY; 1496 mtx_lock(&uma_mtx); 1497 ZONE_LOCK(zone); --- 20 unchanged lines hidden (view full) --- 1518 karg.align = arg->align; 1519 karg.flags = arg->flags; 1520 karg.zone = zone; 1521 error = keg_ctor(arg->keg, sizeof(struct uma_keg), &karg, 1522 flags); 1523 if (error) 1524 return (error); 1525 } |
1526 |
|
1522 /* 1523 * Link in the first keg. 1524 */ 1525 zone->uz_klink.kl_keg = keg; 1526 LIST_INSERT_HEAD(&zone->uz_kegs, &zone->uz_klink, kl_link); 1527 zone->uz_lock = &keg->uk_lock; 1528 zone->uz_size = keg->uk_size; 1529 zone->uz_flags |= (keg->uk_flags & --- 81 unchanged lines hidden (view full) --- 1611 LIST_REMOVE(klink, kl_link); 1612 if (klink == &zone->uz_klink) 1613 continue; 1614 free(klink, M_TEMP); 1615 } 1616 /* 1617 * We only destroy kegs from non secondary zones. 1618 */ | 1527 /* 1528 * Link in the first keg. 1529 */ 1530 zone->uz_klink.kl_keg = keg; 1531 LIST_INSERT_HEAD(&zone->uz_kegs, &zone->uz_klink, kl_link); 1532 zone->uz_lock = &keg->uk_lock; 1533 zone->uz_size = keg->uk_size; 1534 zone->uz_flags |= (keg->uk_flags & --- 81 unchanged lines hidden (view full) --- 1616 LIST_REMOVE(klink, kl_link); 1617 if (klink == &zone->uz_klink) 1618 continue; 1619 free(klink, M_TEMP); 1620 } 1621 /* 1622 * We only destroy kegs from non secondary zones. 1623 */ |
1619 if ((zone->uz_flags & UMA_ZONE_SECONDARY) == 0) { | 1624 if (keg != NULL && (zone->uz_flags & UMA_ZONE_SECONDARY) == 0) { |
1620 mtx_lock(&uma_mtx); 1621 LIST_REMOVE(keg, uk_link); 1622 mtx_unlock(&uma_mtx); | 1625 mtx_lock(&uma_mtx); 1626 LIST_REMOVE(keg, uk_link); 1627 mtx_unlock(&uma_mtx); |
1623 zone_free_item(kegs, keg, NULL, SKIP_NONE, 1624 ZFREE_STATFREE); | 1628 zone_free_item(kegs, keg, NULL, SKIP_NONE); |
1625 } 1626} 1627 1628/* 1629 * Traverses every zone in the system and calls a callback 1630 * 1631 * Arguments: 1632 * zfunc A pointer to a function which accepts a zone --- 27 unchanged lines hidden (view full) --- 1660 int i; 1661 1662#ifdef UMA_DEBUG 1663 printf("Creating uma keg headers zone and keg.\n"); 1664#endif 1665 mtx_init(&uma_mtx, "UMA lock", NULL, MTX_DEF); 1666 1667 /* "manually" create the initial zone */ | 1629 } 1630} 1631 1632/* 1633 * Traverses every zone in the system and calls a callback 1634 * 1635 * Arguments: 1636 * zfunc A pointer to a function which accepts a zone --- 27 unchanged lines hidden (view full) --- 1664 int i; 1665 1666#ifdef UMA_DEBUG 1667 printf("Creating uma keg headers zone and keg.\n"); 1668#endif 1669 mtx_init(&uma_mtx, "UMA lock", NULL, MTX_DEF); 1670 1671 /* "manually" create the initial zone */ |
1672 memset(&args, 0, sizeof(args)); |
|
1668 args.name = "UMA Kegs"; 1669 args.size = sizeof(struct uma_keg); 1670 args.ctor = keg_ctor; 1671 args.dtor = keg_dtor; 1672 args.uminit = zero_init; 1673 args.fini = NULL; 1674 args.keg = &masterkeg; 1675 args.align = 32 - 1; --- 124 unchanged lines hidden (view full) --- 1800uma_zone_t 1801uma_zcreate(const char *name, size_t size, uma_ctor ctor, uma_dtor dtor, 1802 uma_init uminit, uma_fini fini, int align, uint32_t flags) 1803 1804{ 1805 struct uma_zctor_args args; 1806 1807 /* This stuff is essential for the zone ctor */ | 1673 args.name = "UMA Kegs"; 1674 args.size = sizeof(struct uma_keg); 1675 args.ctor = keg_ctor; 1676 args.dtor = keg_dtor; 1677 args.uminit = zero_init; 1678 args.fini = NULL; 1679 args.keg = &masterkeg; 1680 args.align = 32 - 1; --- 124 unchanged lines hidden (view full) --- 1805uma_zone_t 1806uma_zcreate(const char *name, size_t size, uma_ctor ctor, uma_dtor dtor, 1807 uma_init uminit, uma_fini fini, int align, uint32_t flags) 1808 1809{ 1810 struct uma_zctor_args args; 1811 1812 /* This stuff is essential for the zone ctor */ |
1813 memset(&args, 0, sizeof(args)); |
|
1808 args.name = name; 1809 args.size = size; 1810 args.ctor = ctor; 1811 args.dtor = dtor; 1812 args.uminit = uminit; 1813 args.fini = fini; 1814 args.align = align; 1815 args.flags = flags; --- 6 unchanged lines hidden (view full) --- 1822uma_zone_t 1823uma_zsecond_create(char *name, uma_ctor ctor, uma_dtor dtor, 1824 uma_init zinit, uma_fini zfini, uma_zone_t master) 1825{ 1826 struct uma_zctor_args args; 1827 uma_keg_t keg; 1828 1829 keg = zone_first_keg(master); | 1814 args.name = name; 1815 args.size = size; 1816 args.ctor = ctor; 1817 args.dtor = dtor; 1818 args.uminit = uminit; 1819 args.fini = fini; 1820 args.align = align; 1821 args.flags = flags; --- 6 unchanged lines hidden (view full) --- 1828uma_zone_t 1829uma_zsecond_create(char *name, uma_ctor ctor, uma_dtor dtor, 1830 uma_init zinit, uma_fini zfini, uma_zone_t master) 1831{ 1832 struct uma_zctor_args args; 1833 uma_keg_t keg; 1834 1835 keg = zone_first_keg(master); |
1836 memset(&args, 0, sizeof(args)); |
|
1830 args.name = name; 1831 args.size = keg->uk_size; 1832 args.ctor = ctor; 1833 args.dtor = dtor; 1834 args.uminit = zinit; 1835 args.fini = zfini; 1836 args.align = keg->uk_align; 1837 args.flags = keg->uk_flags | UMA_ZONE_SECONDARY; 1838 args.keg = keg; 1839 1840 /* XXX Attaches only one keg of potentially many. */ 1841 return (zone_alloc_item(zones, &args, M_WAITOK)); 1842} 1843 | 1837 args.name = name; 1838 args.size = keg->uk_size; 1839 args.ctor = ctor; 1840 args.dtor = dtor; 1841 args.uminit = zinit; 1842 args.fini = zfini; 1843 args.align = keg->uk_align; 1844 args.flags = keg->uk_flags | UMA_ZONE_SECONDARY; 1845 args.keg = keg; 1846 1847 /* XXX Attaches only one keg of potentially many. */ 1848 return (zone_alloc_item(zones, &args, M_WAITOK)); 1849} 1850 |
1851/* See uma.h */ 1852uma_zone_t 1853uma_zcache_create(char *name, uma_ctor ctor, uma_dtor dtor, uma_init zinit, 1854 uma_fini zfini, uma_import zimport, uma_release zrelease, 1855 void *arg, int flags) 1856{ 1857 struct uma_zctor_args args; 1858 1859 memset(&args, 0, sizeof(args)); 1860 args.name = name; 1861 args.size = 0; 1862 args.ctor = ctor; 1863 args.dtor = dtor; 1864 args.uminit = zinit; 1865 args.fini = zfini; 1866 args.import = zimport; 1867 args.release = zrelease; 1868 args.arg = arg; 1869 args.align = 0; 1870 args.flags = flags; 1871 1872 return (zone_alloc_item(zones, &args, M_WAITOK)); 1873} 1874 |
|
1844static void 1845zone_lock_pair(uma_zone_t a, uma_zone_t b) 1846{ 1847 if (a < b) { 1848 ZONE_LOCK(a); 1849 mtx_lock_flags(b->uz_lock, MTX_DUPOK); 1850 } else { 1851 ZONE_LOCK(b); --- 75 unchanged lines hidden (view full) --- 1927} 1928 1929 1930/* See uma.h */ 1931void 1932uma_zdestroy(uma_zone_t zone) 1933{ 1934 | 1875static void 1876zone_lock_pair(uma_zone_t a, uma_zone_t b) 1877{ 1878 if (a < b) { 1879 ZONE_LOCK(a); 1880 mtx_lock_flags(b->uz_lock, MTX_DUPOK); 1881 } else { 1882 ZONE_LOCK(b); --- 75 unchanged lines hidden (view full) --- 1958} 1959 1960 1961/* See uma.h */ 1962void 1963uma_zdestroy(uma_zone_t zone) 1964{ 1965 |
1935 zone_free_item(zones, zone, NULL, SKIP_NONE, ZFREE_STATFREE); | 1966 zone_free_item(zones, zone, NULL, SKIP_NONE); |
1936} 1937 1938/* See uma.h */ 1939void * 1940uma_zalloc_arg(uma_zone_t zone, void *udata, int flags) 1941{ 1942 void *item; 1943 uma_cache_t cache; --- 62 unchanged lines hidden (view full) --- 2006#endif 2007 KASSERT(item != NULL, 2008 ("uma_zalloc: Bucket pointer mangled.")); 2009 cache->uc_allocs++; 2010 critical_exit(); 2011 if (zone->uz_ctor != NULL) { 2012 if (zone->uz_ctor(item, zone->uz_size, 2013 udata, flags) != 0) { | 1967} 1968 1969/* See uma.h */ 1970void * 1971uma_zalloc_arg(uma_zone_t zone, void *udata, int flags) 1972{ 1973 void *item; 1974 uma_cache_t cache; --- 62 unchanged lines hidden (view full) --- 2037#endif 2038 KASSERT(item != NULL, 2039 ("uma_zalloc: Bucket pointer mangled.")); 2040 cache->uc_allocs++; 2041 critical_exit(); 2042 if (zone->uz_ctor != NULL) { 2043 if (zone->uz_ctor(item, zone->uz_size, 2044 udata, flags) != 0) { |
2045 atomic_add_long(&zone->uz_fails, 1); |
|
2014 zone_free_item(zone, item, udata, | 2046 zone_free_item(zone, item, udata, |
2015 SKIP_DTOR, ZFREE_STATFAIL | 2016 ZFREE_STATFREE); | 2047 SKIP_DTOR); |
2017 return (NULL); 2018 } 2019 } 2020#ifdef INVARIANTS 2021 uma_dbg_alloc(zone, NULL, item); 2022#endif 2023 if (flags & M_ZERO) 2024 bzero(item, zone->uz_size); --- 39 unchanged lines hidden (view full) --- 2064 bucket = cache->uc_freebucket; 2065 if (bucket != NULL && bucket->ub_cnt > 0) { 2066 ZONE_UNLOCK(zone); 2067 goto zalloc_start; 2068 } 2069 } 2070 2071 /* Since we have locked the zone we may as well send back our stats */ | 2048 return (NULL); 2049 } 2050 } 2051#ifdef INVARIANTS 2052 uma_dbg_alloc(zone, NULL, item); 2053#endif 2054 if (flags & M_ZERO) 2055 bzero(item, zone->uz_size); --- 39 unchanged lines hidden (view full) --- 2095 bucket = cache->uc_freebucket; 2096 if (bucket != NULL && bucket->ub_cnt > 0) { 2097 ZONE_UNLOCK(zone); 2098 goto zalloc_start; 2099 } 2100 } 2101 2102 /* Since we have locked the zone we may as well send back our stats */ |
2072 zone->uz_allocs += cache->uc_allocs; | 2103 atomic_add_long(&zone->uz_allocs, cache->uc_allocs); 2104 atomic_add_long(&zone->uz_frees, cache->uc_frees); |
2073 cache->uc_allocs = 0; | 2105 cache->uc_allocs = 0; |
2074 zone->uz_frees += cache->uc_frees; | |
2075 cache->uc_frees = 0; 2076 2077 /* Our old one is now a free bucket */ 2078 if (cache->uc_allocbucket) { 2079 KASSERT(cache->uc_allocbucket->ub_cnt == 0, 2080 ("uma_zalloc_arg: Freeing a non free bucket.")); 2081 LIST_INSERT_HEAD(&zone->uz_free_bucket, 2082 cache->uc_allocbucket, ub_link); --- 231 unchanged lines hidden (view full) --- 2314 zone->uz_flags &= ~UMA_ZFLAG_FULL; 2315 continue; 2316 } 2317 } 2318 return (NULL); 2319} 2320 2321static void * | 2106 cache->uc_frees = 0; 2107 2108 /* Our old one is now a free bucket */ 2109 if (cache->uc_allocbucket) { 2110 KASSERT(cache->uc_allocbucket->ub_cnt == 0, 2111 ("uma_zalloc_arg: Freeing a non free bucket.")); 2112 LIST_INSERT_HEAD(&zone->uz_free_bucket, 2113 cache->uc_allocbucket, ub_link); --- 231 unchanged lines hidden (view full) --- 2345 zone->uz_flags &= ~UMA_ZFLAG_FULL; 2346 continue; 2347 } 2348 } 2349 return (NULL); 2350} 2351 2352static void * |
2322slab_alloc_item(uma_zone_t zone, uma_slab_t slab) | 2353slab_alloc_item(uma_keg_t keg, uma_slab_t slab) |
2323{ | 2354{ |
2324 uma_keg_t keg; | |
2325 void *item; 2326 uint8_t freei; 2327 | 2355 void *item; 2356 uint8_t freei; 2357 |
2328 keg = slab->us_keg; | 2358 MPASS(keg == slab->us_keg); |
2329 mtx_assert(&keg->uk_lock, MA_OWNED); 2330 2331 freei = BIT_FFS(SLAB_SETSIZE, &slab->us_free) - 1; 2332 BIT_CLR(SLAB_SETSIZE, freei, &slab->us_free); 2333 item = slab->us_data + (keg->uk_rsize * freei); 2334 slab->us_freecount--; 2335 keg->uk_free--; 2336 2337 /* Move this slab to the full list */ 2338 if (slab->us_freecount == 0) { 2339 LIST_REMOVE(slab, us_link); 2340 LIST_INSERT_HEAD(&keg->uk_full_slab, slab, us_link); 2341 } 2342 2343 return (item); 2344} 2345 2346static int | 2359 mtx_assert(&keg->uk_lock, MA_OWNED); 2360 2361 freei = BIT_FFS(SLAB_SETSIZE, &slab->us_free) - 1; 2362 BIT_CLR(SLAB_SETSIZE, freei, &slab->us_free); 2363 item = slab->us_data + (keg->uk_rsize * freei); 2364 slab->us_freecount--; 2365 keg->uk_free--; 2366 2367 /* Move this slab to the full list */ 2368 if (slab->us_freecount == 0) { 2369 LIST_REMOVE(slab, us_link); 2370 LIST_INSERT_HEAD(&keg->uk_full_slab, slab, us_link); 2371 } 2372 2373 return (item); 2374} 2375 2376static int |
2347zone_alloc_bucket(uma_zone_t zone, int flags) | 2377zone_import(uma_zone_t zone, void **bucket, int max, int flags) |
2348{ | 2378{ |
2349 uma_bucket_t bucket; | |
2350 uma_slab_t slab; 2351 uma_keg_t keg; | 2379 uma_slab_t slab; 2380 uma_keg_t keg; |
2352 int16_t saved; 2353 int max, origflags = flags; | 2381 int i; |
2354 | 2382 |
2355 /* 2356 * Try this zone's free list first so we don't allocate extra buckets. 2357 */ 2358 if ((bucket = LIST_FIRST(&zone->uz_free_bucket)) != NULL) { 2359 KASSERT(bucket->ub_cnt == 0, 2360 ("zone_alloc_bucket: Bucket on free list is not empty.")); 2361 LIST_REMOVE(bucket, ub_link); 2362 } else { 2363 int bflags; | 2383 ZONE_LOCK(zone); 2384 /* Try to keep the buckets totally full */ 2385 slab = NULL; 2386 keg = NULL; 2387 for (i = 0; i < max; ) { 2388 if ((slab = zone->uz_slab(zone, keg, flags)) == NULL) 2389 break; 2390 keg = slab->us_keg; 2391 while (slab->us_freecount && i < max) 2392 bucket[i++] = slab_alloc_item(keg, slab); |
2364 | 2393 |
2365 bflags = (flags & ~M_ZERO); 2366 if (zone->uz_flags & UMA_ZFLAG_CACHEONLY) 2367 bflags |= M_NOVM; 2368 2369 ZONE_UNLOCK(zone); 2370 bucket = bucket_alloc(zone->uz_count, bflags); 2371 ZONE_LOCK(zone); | 2394 /* Don't block on the next fill */ 2395 flags &= ~M_WAITOK; 2396 flags |= M_NOWAIT; |
2372 } | 2397 } |
2398 if (slab != NULL) 2399 KEG_UNLOCK(keg); 2400 else 2401 ZONE_UNLOCK(zone); |
|
2373 | 2402 |
2374 if (bucket == NULL) { 2375 return (0); 2376 } | 2403 return i; 2404} |
2377 | 2405 |
2406static int 2407zone_alloc_bucket(uma_zone_t zone, int flags) 2408{ 2409 uma_bucket_t bucket; 2410 int bflags; 2411 int max; 2412 |
|
2378#ifdef SMP 2379 /* 2380 * This code is here to limit the number of simultaneous bucket fills 2381 * for any given zone to the number of per cpu caches in this zone. This 2382 * is done so that we don't allocate more memory than we really need. 2383 */ 2384 if (zone->uz_fills >= mp_ncpus) | 2413#ifdef SMP 2414 /* 2415 * This code is here to limit the number of simultaneous bucket fills 2416 * for any given zone to the number of per cpu caches in this zone. This 2417 * is done so that we don't allocate more memory than we really need. 2418 */ 2419 if (zone->uz_fills >= mp_ncpus) |
2385 goto done; | 2420 return (0); |
2386 2387#endif 2388 zone->uz_fills++; | 2421 2422#endif 2423 zone->uz_fills++; |
2424 max = zone->uz_count; |
|
2389 | 2425 |
2390 max = MIN(bucket->ub_entries, zone->uz_count); 2391 /* Try to keep the buckets totally full */ 2392 saved = bucket->ub_cnt; 2393 slab = NULL; 2394 keg = NULL; 2395 while (bucket->ub_cnt < max && 2396 (slab = zone->uz_slab(zone, keg, flags)) != NULL) { 2397 keg = slab->us_keg; 2398 while (slab->us_freecount && bucket->ub_cnt < max) { 2399 bucket->ub_bucket[bucket->ub_cnt++] = 2400 slab_alloc_item(zone, slab); 2401 } 2402 2403 /* Don't block on the next fill */ 2404 flags |= M_NOWAIT; | 2426 /* 2427 * Try this zone's free list first so we don't allocate extra buckets. 2428 */ 2429 if ((bucket = LIST_FIRST(&zone->uz_free_bucket)) != NULL) { 2430 KASSERT(bucket->ub_cnt == 0, 2431 ("zone_alloc_bucket: Bucket on free list is not empty.")); 2432 LIST_REMOVE(bucket, ub_link); 2433 ZONE_UNLOCK(zone); 2434 } else { 2435 bflags = (flags & ~M_ZERO); 2436 if (zone->uz_flags & UMA_ZFLAG_CACHEONLY) 2437 bflags |= M_NOVM; 2438 ZONE_UNLOCK(zone); 2439 bucket = bucket_alloc(zone->uz_count, bflags); 2440 if (bucket == NULL) 2441 goto out; |
2405 } | 2442 } |
2406 if (slab) 2407 zone_relock(zone, keg); | |
2408 | 2443 |
2444 max = MIN(bucket->ub_entries, max); 2445 bucket->ub_cnt = zone->uz_import(zone->uz_arg, bucket->ub_bucket, 2446 max, flags); 2447 |
|
2409 /* | 2448 /* |
2410 * We unlock here because we need to call the zone's init. 2411 * It should be safe to unlock because the slab dealt with 2412 * above is already on the appropriate list within the keg 2413 * and the bucket we filled is not yet on any list, so we 2414 * own it. | 2449 * Initialize the memory if necessary. |
2415 */ | 2450 */ |
2416 if (zone->uz_init != NULL) { | 2451 if (bucket->ub_cnt != 0 && zone->uz_init != NULL) { |
2417 int i; 2418 | 2452 int i; 2453 |
2419 ZONE_UNLOCK(zone); 2420 for (i = saved; i < bucket->ub_cnt; i++) | 2454 for (i = 0; i < bucket->ub_cnt; i++) |
2421 if (zone->uz_init(bucket->ub_bucket[i], zone->uz_size, | 2455 if (zone->uz_init(bucket->ub_bucket[i], zone->uz_size, |
2422 origflags) != 0) | 2456 flags) != 0) |
2423 break; 2424 /* 2425 * If we couldn't initialize the whole bucket, put the 2426 * rest back onto the freelist. 2427 */ 2428 if (i != bucket->ub_cnt) { | 2457 break; 2458 /* 2459 * If we couldn't initialize the whole bucket, put the 2460 * rest back onto the freelist. 2461 */ 2462 if (i != bucket->ub_cnt) { |
2429 int j; 2430 2431 for (j = i; j < bucket->ub_cnt; j++) { 2432 zone_free_item(zone, bucket->ub_bucket[j], 2433 NULL, SKIP_FINI, 0); | 2463 zone->uz_release(zone->uz_arg, bucket->ub_bucket[i], 2464 bucket->ub_cnt - i); |
2434#ifdef INVARIANTS | 2465#ifdef INVARIANTS |
2435 bucket->ub_bucket[j] = NULL; | 2466 bzero(&bucket->ub_bucket[i], 2467 sizeof(void *) * (bucket->ub_cnt - i)); |
2436#endif | 2468#endif |
2437 } | |
2438 bucket->ub_cnt = i; 2439 } | 2469 bucket->ub_cnt = i; 2470 } |
2440 ZONE_LOCK(zone); | |
2441 } 2442 | 2471 } 2472 |
2473out: 2474 ZONE_LOCK(zone); |
|
2443 zone->uz_fills--; | 2475 zone->uz_fills--; |
2444 if (bucket->ub_cnt != 0) { | 2476 if (bucket != NULL && bucket->ub_cnt != 0) { |
2445 LIST_INSERT_HEAD(&zone->uz_full_bucket, 2446 bucket, ub_link); 2447 return (1); 2448 } | 2477 LIST_INSERT_HEAD(&zone->uz_full_bucket, 2478 bucket, ub_link); 2479 return (1); 2480 } |
2449#ifdef SMP 2450done: 2451#endif 2452 bucket_free(bucket); | 2481 atomic_add_long(&zone->uz_fails, 1); 2482 if (bucket != NULL) 2483 bucket_free(bucket); |
2453 2454 return (0); 2455} 2456/* | 2484 2485 return (0); 2486} 2487/* |
2457 * Allocates an item for an internal zone | 2488 * Allocates a single item from a zone. |
2458 * 2459 * Arguments 2460 * zone The zone to alloc for. 2461 * udata The data to be passed to the constructor. 2462 * flags M_WAITOK, M_NOWAIT, M_ZERO. 2463 * 2464 * Returns 2465 * NULL if there is no memory and M_NOWAIT is set 2466 * An item if successful 2467 */ 2468 2469static void * 2470zone_alloc_item(uma_zone_t zone, void *udata, int flags) 2471{ | 2489 * 2490 * Arguments 2491 * zone The zone to alloc for. 2492 * udata The data to be passed to the constructor. 2493 * flags M_WAITOK, M_NOWAIT, M_ZERO. 2494 * 2495 * Returns 2496 * NULL if there is no memory and M_NOWAIT is set 2497 * An item if successful 2498 */ 2499 2500static void * 2501zone_alloc_item(uma_zone_t zone, void *udata, int flags) 2502{ |
2472 uma_slab_t slab; | |
2473 void *item; 2474 2475 item = NULL; 2476 2477#ifdef UMA_DEBUG_ALLOC 2478 printf("INTERNAL: Allocating one item from %s(%p)\n", zone->uz_name, zone); 2479#endif | 2503 void *item; 2504 2505 item = NULL; 2506 2507#ifdef UMA_DEBUG_ALLOC 2508 printf("INTERNAL: Allocating one item from %s(%p)\n", zone->uz_name, zone); 2509#endif |
2480 ZONE_LOCK(zone); | 2510 if (zone->uz_import(zone->uz_arg, &item, 1, flags) != 1) 2511 goto fail; 2512 atomic_add_long(&zone->uz_allocs, 1); |
2481 | 2513 |
2482 slab = zone->uz_slab(zone, NULL, flags); 2483 if (slab == NULL) { 2484 zone->uz_fails++; 2485 ZONE_UNLOCK(zone); 2486 return (NULL); 2487 } 2488 2489 item = slab_alloc_item(zone, slab); 2490 2491 zone_relock(zone, slab->us_keg); 2492 zone->uz_allocs++; 2493 ZONE_UNLOCK(zone); 2494 | |
2495 /* 2496 * We have to call both the zone's init (not the keg's init) 2497 * and the zone's ctor. This is because the item is going from 2498 * a keg slab directly to the user, and the user is expecting it 2499 * to be both zone-init'd as well as zone-ctor'd. 2500 */ 2501 if (zone->uz_init != NULL) { 2502 if (zone->uz_init(item, zone->uz_size, flags) != 0) { | 2514 /* 2515 * We have to call both the zone's init (not the keg's init) 2516 * and the zone's ctor. This is because the item is going from 2517 * a keg slab directly to the user, and the user is expecting it 2518 * to be both zone-init'd as well as zone-ctor'd. 2519 */ 2520 if (zone->uz_init != NULL) { 2521 if (zone->uz_init(item, zone->uz_size, flags) != 0) { |
2503 zone_free_item(zone, item, udata, SKIP_FINI, 2504 ZFREE_STATFAIL | ZFREE_STATFREE); 2505 return (NULL); | 2522 zone_free_item(zone, item, udata, SKIP_FINI); 2523 goto fail; |
2506 } 2507 } 2508 if (zone->uz_ctor != NULL) { 2509 if (zone->uz_ctor(item, zone->uz_size, udata, flags) != 0) { | 2524 } 2525 } 2526 if (zone->uz_ctor != NULL) { 2527 if (zone->uz_ctor(item, zone->uz_size, udata, flags) != 0) { |
2510 zone_free_item(zone, item, udata, SKIP_DTOR, 2511 ZFREE_STATFAIL | ZFREE_STATFREE); 2512 return (NULL); | 2528 zone_free_item(zone, item, udata, SKIP_DTOR); 2529 goto fail; |
2513 } 2514 } 2515#ifdef INVARIANTS | 2530 } 2531 } 2532#ifdef INVARIANTS |
2516 uma_dbg_alloc(zone, slab, item); | 2533 uma_dbg_alloc(zone, NULL, item); |
2517#endif 2518 if (flags & M_ZERO) 2519 bzero(item, zone->uz_size); 2520 2521 return (item); | 2534#endif 2535 if (flags & M_ZERO) 2536 bzero(item, zone->uz_size); 2537 2538 return (item); |
2539 2540fail: 2541 atomic_add_long(&zone->uz_fails, 1); 2542 return (NULL); |
|
2522} 2523 2524/* See uma.h */ 2525void 2526uma_zfree_arg(uma_zone_t zone, void *item, void *udata) 2527{ 2528 uma_cache_t cache; 2529 uma_bucket_t bucket; --- 113 unchanged lines hidden (view full) --- 2643 (cache->uc_allocbucket->ub_cnt < 2644 cache->uc_freebucket->ub_cnt)) { 2645 ZONE_UNLOCK(zone); 2646 goto zfree_start; 2647 } 2648 } 2649 2650 /* Since we have locked the zone we may as well send back our stats */ | 2543} 2544 2545/* See uma.h */ 2546void 2547uma_zfree_arg(uma_zone_t zone, void *item, void *udata) 2548{ 2549 uma_cache_t cache; 2550 uma_bucket_t bucket; --- 113 unchanged lines hidden (view full) --- 2664 (cache->uc_allocbucket->ub_cnt < 2665 cache->uc_freebucket->ub_cnt)) { 2666 ZONE_UNLOCK(zone); 2667 goto zfree_start; 2668 } 2669 } 2670 2671 /* Since we have locked the zone we may as well send back our stats */ |
2651 zone->uz_allocs += cache->uc_allocs; | 2672 atomic_add_long(&zone->uz_allocs, cache->uc_allocs); 2673 atomic_add_long(&zone->uz_frees, cache->uc_frees); |
2652 cache->uc_allocs = 0; | 2674 cache->uc_allocs = 0; |
2653 zone->uz_frees += cache->uc_frees; | |
2654 cache->uc_frees = 0; 2655 2656 bucket = cache->uc_freebucket; 2657 cache->uc_freebucket = NULL; 2658 2659 /* Can we throw this on the zone full list? */ 2660 if (bucket != NULL) { 2661#ifdef UMA_DEBUG_ALLOC --- 32 unchanged lines hidden (view full) --- 2694 ZONE_UNLOCK(zone); 2695 goto zfree_restart; 2696 } 2697 2698 /* 2699 * If nothing else caught this, we'll just do an internal free. 2700 */ 2701zfree_internal: | 2675 cache->uc_frees = 0; 2676 2677 bucket = cache->uc_freebucket; 2678 cache->uc_freebucket = NULL; 2679 2680 /* Can we throw this on the zone full list? */ 2681 if (bucket != NULL) { 2682#ifdef UMA_DEBUG_ALLOC --- 32 unchanged lines hidden (view full) --- 2715 ZONE_UNLOCK(zone); 2716 goto zfree_restart; 2717 } 2718 2719 /* 2720 * If nothing else caught this, we'll just do an internal free. 2721 */ 2722zfree_internal: |
2702 zone_free_item(zone, item, udata, SKIP_DTOR, ZFREE_STATFREE); | 2723 zone_free_item(zone, item, udata, SKIP_DTOR); |
2703 2704 return; 2705} 2706 | 2724 2725 return; 2726} 2727 |
2707/* 2708 * Frees an item to an INTERNAL zone or allocates a free bucket 2709 * 2710 * Arguments: 2711 * zone The zone to free to 2712 * item The item we're freeing 2713 * udata User supplied data for the dtor 2714 * skip Skip dtors and finis 2715 */ | |
2716static void | 2728static void |
2717zone_free_item(uma_zone_t zone, void *item, void *udata, 2718 enum zfreeskip skip, int flags) | 2729slab_free_item(uma_keg_t keg, uma_slab_t slab, void *item) |
2719{ | 2730{ |
2720 uma_slab_t slab; 2721 uma_keg_t keg; 2722 uint8_t *mem; | |
2723 uint8_t freei; | 2731 uint8_t freei; |
2724 int clearfull; | |
2725 | 2732 |
2726#ifdef INVARIANTS 2727 if (skip == SKIP_NONE) { 2728 if (zone->uz_flags & UMA_ZONE_MALLOC) 2729 uma_dbg_free(zone, udata, item); 2730 else 2731 uma_dbg_free(zone, NULL, item); 2732 } 2733#endif 2734 if (skip < SKIP_DTOR && zone->uz_dtor) 2735 zone->uz_dtor(item, zone->uz_size, udata); 2736 2737 if (skip < SKIP_FINI && zone->uz_fini) 2738 zone->uz_fini(item, zone->uz_size); 2739 2740 ZONE_LOCK(zone); 2741 2742 if (flags & ZFREE_STATFAIL) 2743 zone->uz_fails++; 2744 if (flags & ZFREE_STATFREE) 2745 zone->uz_frees++; 2746 2747 if (!(zone->uz_flags & UMA_ZONE_VTOSLAB)) { 2748 mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK)); 2749 keg = zone_first_keg(zone); /* Must only be one. */ 2750 if (zone->uz_flags & UMA_ZONE_HASH) { 2751 slab = hash_sfind(&keg->uk_hash, mem); 2752 } else { 2753 mem += keg->uk_pgoff; 2754 slab = (uma_slab_t)mem; 2755 } 2756 } else { 2757 /* This prevents redundant lookups via free(). */ 2758 if ((zone->uz_flags & UMA_ZONE_MALLOC) && udata != NULL) 2759 slab = (uma_slab_t)udata; 2760 else 2761 slab = vtoslab((vm_offset_t)item); 2762 keg = slab->us_keg; 2763 keg_relock(keg, zone); 2764 } | 2733 mtx_assert(&keg->uk_lock, MA_OWNED); |
2765 MPASS(keg == slab->us_keg); 2766 2767 /* Do we need to remove from any lists? */ 2768 if (slab->us_freecount+1 == keg->uk_ipers) { 2769 LIST_REMOVE(slab, us_link); 2770 LIST_INSERT_HEAD(&keg->uk_free_slab, slab, us_link); 2771 } else if (slab->us_freecount == 0) { 2772 LIST_REMOVE(slab, us_link); 2773 LIST_INSERT_HEAD(&keg->uk_part_slab, slab, us_link); 2774 } 2775 2776 /* Slab management. */ 2777 freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; 2778 BIT_SET(SLAB_SETSIZE, freei, &slab->us_free); 2779 slab->us_freecount++; 2780 2781 /* Keg statistics. */ 2782 keg->uk_free++; | 2734 MPASS(keg == slab->us_keg); 2735 2736 /* Do we need to remove from any lists? */ 2737 if (slab->us_freecount+1 == keg->uk_ipers) { 2738 LIST_REMOVE(slab, us_link); 2739 LIST_INSERT_HEAD(&keg->uk_free_slab, slab, us_link); 2740 } else if (slab->us_freecount == 0) { 2741 LIST_REMOVE(slab, us_link); 2742 LIST_INSERT_HEAD(&keg->uk_part_slab, slab, us_link); 2743 } 2744 2745 /* Slab management. */ 2746 freei = ((uintptr_t)item - (uintptr_t)slab->us_data) / keg->uk_rsize; 2747 BIT_SET(SLAB_SETSIZE, freei, &slab->us_free); 2748 slab->us_freecount++; 2749 2750 /* Keg statistics. */ 2751 keg->uk_free++; |
2752} |
|
2783 | 2753 |
2754static void 2755zone_release(uma_zone_t zone, void **bucket, int cnt) 2756{ 2757 void *item; 2758 uma_slab_t slab; 2759 uma_keg_t keg; 2760 uint8_t *mem; 2761 int clearfull; 2762 int i; 2763 |
|
2784 clearfull = 0; | 2764 clearfull = 0; |
2785 if (keg->uk_flags & UMA_ZFLAG_FULL) { 2786 if (keg->uk_pages < keg->uk_maxpages) { 2787 keg->uk_flags &= ~UMA_ZFLAG_FULL; 2788 clearfull = 1; | 2765 ZONE_LOCK(zone); 2766 keg = zone_first_keg(zone); 2767 for (i = 0; i < cnt; i++) { 2768 item = bucket[i]; 2769 if (!(zone->uz_flags & UMA_ZONE_VTOSLAB)) { 2770 mem = (uint8_t *)((uintptr_t)item & (~UMA_SLAB_MASK)); 2771 if (zone->uz_flags & UMA_ZONE_HASH) { 2772 slab = hash_sfind(&keg->uk_hash, mem); 2773 } else { 2774 mem += keg->uk_pgoff; 2775 slab = (uma_slab_t)mem; 2776 } 2777 } else { 2778 slab = vtoslab((vm_offset_t)item); 2779 if (slab->us_keg != keg) { 2780 KEG_UNLOCK(keg); 2781 keg = slab->us_keg; 2782 KEG_LOCK(keg); 2783 } |
2789 } | 2784 } |
2785 slab_free_item(keg, slab, item); 2786 if (keg->uk_flags & UMA_ZFLAG_FULL) { 2787 if (keg->uk_pages < keg->uk_maxpages) { 2788 keg->uk_flags &= ~UMA_ZFLAG_FULL; 2789 clearfull = 1; 2790 } |
|
2790 | 2791 |
2791 /* 2792 * We can handle one more allocation. Since we're 2793 * clearing ZFLAG_FULL, wake up all procs blocked 2794 * on pages. This should be uncommon, so keeping this 2795 * simple for now (rather than adding count of blocked 2796 * threads etc). 2797 */ 2798 wakeup(keg); | 2792 /* 2793 * We can handle one more allocation. Since we're 2794 * clearing ZFLAG_FULL, wake up all procs blocked 2795 * on pages. This should be uncommon, so keeping this 2796 * simple for now (rather than adding count of blocked 2797 * threads etc). 2798 */ 2799 wakeup(keg); 2800 } |
2799 } | 2801 } |
2802 zone_relock(zone, keg); |
|
2800 if (clearfull) { | 2803 if (clearfull) { |
2801 zone_relock(zone, keg); | |
2802 zone->uz_flags &= ~UMA_ZFLAG_FULL; 2803 wakeup(zone); | 2804 zone->uz_flags &= ~UMA_ZFLAG_FULL; 2805 wakeup(zone); |
2804 ZONE_UNLOCK(zone); 2805 } else 2806 KEG_UNLOCK(keg); | 2806 } 2807 ZONE_UNLOCK(zone); |
2807 2808} 2809 | 2808 2809} 2810 |
2811/* 2812 * Frees a single item to any zone. 2813 * 2814 * Arguments: 2815 * zone The zone to free to 2816 * item The item we're freeing 2817 * udata User supplied data for the dtor 2818 * skip Skip dtors and finis 2819 */ 2820static void 2821zone_free_item(uma_zone_t zone, void *item, void *udata, enum zfreeskip skip) 2822{ 2823 2824#ifdef INVARIANTS 2825 if (skip == SKIP_NONE) { 2826 if (zone->uz_flags & UMA_ZONE_MALLOC) 2827 uma_dbg_free(zone, udata, item); 2828 else 2829 uma_dbg_free(zone, NULL, item); 2830 } 2831#endif 2832 if (skip < SKIP_DTOR && zone->uz_dtor) 2833 zone->uz_dtor(item, zone->uz_size, udata); 2834 2835 if (skip < SKIP_FINI && zone->uz_fini) 2836 zone->uz_fini(item, zone->uz_size); 2837 2838 atomic_add_long(&zone->uz_frees, 1); 2839 zone->uz_release(zone->uz_arg, &item, 1); 2840} 2841 |
|
2810/* See uma.h */ 2811int 2812uma_zone_set_max(uma_zone_t zone, int nitems) 2813{ 2814 uma_keg_t keg; 2815 | 2842/* See uma.h */ 2843int 2844uma_zone_set_max(uma_zone_t zone, int nitems) 2845{ 2846 uma_keg_t keg; 2847 |
2816 ZONE_LOCK(zone); | |
2817 keg = zone_first_keg(zone); | 2848 keg = zone_first_keg(zone); |
2849 if (keg == NULL) 2850 return (0); 2851 ZONE_LOCK(zone); |
|
2818 keg->uk_maxpages = (nitems / keg->uk_ipers) * keg->uk_ppera; 2819 if (keg->uk_maxpages * keg->uk_ipers < nitems) 2820 keg->uk_maxpages += keg->uk_ppera; 2821 nitems = keg->uk_maxpages * keg->uk_ipers; 2822 ZONE_UNLOCK(zone); 2823 2824 return (nitems); 2825} 2826 2827/* See uma.h */ 2828int 2829uma_zone_get_max(uma_zone_t zone) 2830{ 2831 int nitems; 2832 uma_keg_t keg; 2833 | 2852 keg->uk_maxpages = (nitems / keg->uk_ipers) * keg->uk_ppera; 2853 if (keg->uk_maxpages * keg->uk_ipers < nitems) 2854 keg->uk_maxpages += keg->uk_ppera; 2855 nitems = keg->uk_maxpages * keg->uk_ipers; 2856 ZONE_UNLOCK(zone); 2857 2858 return (nitems); 2859} 2860 2861/* See uma.h */ 2862int 2863uma_zone_get_max(uma_zone_t zone) 2864{ 2865 int nitems; 2866 uma_keg_t keg; 2867 |
2834 ZONE_LOCK(zone); | |
2835 keg = zone_first_keg(zone); | 2868 keg = zone_first_keg(zone); |
2869 if (keg == NULL) 2870 return (0); 2871 ZONE_LOCK(zone); |
|
2836 nitems = keg->uk_maxpages * keg->uk_ipers; 2837 ZONE_UNLOCK(zone); 2838 2839 return (nitems); 2840} 2841 2842/* See uma.h */ 2843void --- 31 unchanged lines hidden (view full) --- 2875/* See uma.h */ 2876void 2877uma_zone_set_init(uma_zone_t zone, uma_init uminit) 2878{ 2879 uma_keg_t keg; 2880 2881 ZONE_LOCK(zone); 2882 keg = zone_first_keg(zone); | 2872 nitems = keg->uk_maxpages * keg->uk_ipers; 2873 ZONE_UNLOCK(zone); 2874 2875 return (nitems); 2876} 2877 2878/* See uma.h */ 2879void --- 31 unchanged lines hidden (view full) --- 2911/* See uma.h */ 2912void 2913uma_zone_set_init(uma_zone_t zone, uma_init uminit) 2914{ 2915 uma_keg_t keg; 2916 2917 ZONE_LOCK(zone); 2918 keg = zone_first_keg(zone); |
2919 KASSERT(keg != NULL, ("uma_zone_set_init: Invalid zone type")); |
|
2883 KASSERT(keg->uk_pages == 0, 2884 ("uma_zone_set_init on non-empty keg")); 2885 keg->uk_init = uminit; 2886 ZONE_UNLOCK(zone); 2887} 2888 2889/* See uma.h */ 2890void 2891uma_zone_set_fini(uma_zone_t zone, uma_fini fini) 2892{ 2893 uma_keg_t keg; 2894 2895 ZONE_LOCK(zone); 2896 keg = zone_first_keg(zone); | 2920 KASSERT(keg->uk_pages == 0, 2921 ("uma_zone_set_init on non-empty keg")); 2922 keg->uk_init = uminit; 2923 ZONE_UNLOCK(zone); 2924} 2925 2926/* See uma.h */ 2927void 2928uma_zone_set_fini(uma_zone_t zone, uma_fini fini) 2929{ 2930 uma_keg_t keg; 2931 2932 ZONE_LOCK(zone); 2933 keg = zone_first_keg(zone); |
2934 KASSERT(keg != NULL, ("uma_zone_set_init: Invalid zone type")); |
|
2897 KASSERT(keg->uk_pages == 0, 2898 ("uma_zone_set_fini on non-empty keg")); 2899 keg->uk_fini = fini; 2900 ZONE_UNLOCK(zone); 2901} 2902 2903/* See uma.h */ 2904void --- 17 unchanged lines hidden (view full) --- 2922 ZONE_UNLOCK(zone); 2923} 2924 2925/* See uma.h */ 2926/* XXX uk_freef is not actually used with the zone locked */ 2927void 2928uma_zone_set_freef(uma_zone_t zone, uma_free freef) 2929{ | 2935 KASSERT(keg->uk_pages == 0, 2936 ("uma_zone_set_fini on non-empty keg")); 2937 keg->uk_fini = fini; 2938 ZONE_UNLOCK(zone); 2939} 2940 2941/* See uma.h */ 2942void --- 17 unchanged lines hidden (view full) --- 2960 ZONE_UNLOCK(zone); 2961} 2962 2963/* See uma.h */ 2964/* XXX uk_freef is not actually used with the zone locked */ 2965void 2966uma_zone_set_freef(uma_zone_t zone, uma_free freef) 2967{ |
2968 uma_keg_t keg; |
|
2930 2931 ZONE_LOCK(zone); | 2969 2970 ZONE_LOCK(zone); |
2932 zone_first_keg(zone)->uk_freef = freef; | 2971 keg = zone_first_keg(zone); 2972 KASSERT(keg != NULL, ("uma_zone_set_init: Invalid zone type")); 2973 keg->uk_freef = freef; |
2933 ZONE_UNLOCK(zone); 2934} 2935 2936/* See uma.h */ 2937/* XXX uk_allocf is not actually used with the zone locked */ 2938void 2939uma_zone_set_allocf(uma_zone_t zone, uma_alloc allocf) 2940{ --- 10 unchanged lines hidden (view full) --- 2951int 2952uma_zone_reserve_kva(uma_zone_t zone, int count) 2953{ 2954 uma_keg_t keg; 2955 vm_offset_t kva; 2956 int pages; 2957 2958 keg = zone_first_keg(zone); | 2974 ZONE_UNLOCK(zone); 2975} 2976 2977/* See uma.h */ 2978/* XXX uk_allocf is not actually used with the zone locked */ 2979void 2980uma_zone_set_allocf(uma_zone_t zone, uma_alloc allocf) 2981{ --- 10 unchanged lines hidden (view full) --- 2992int 2993uma_zone_reserve_kva(uma_zone_t zone, int count) 2994{ 2995 uma_keg_t keg; 2996 vm_offset_t kva; 2997 int pages; 2998 2999 keg = zone_first_keg(zone); |
3000 if (keg == NULL) 3001 return (0); |
|
2959 pages = count / keg->uk_ipers; 2960 2961 if (pages * keg->uk_ipers < count) 2962 pages++; 2963 2964#ifdef UMA_MD_SMALL_ALLOC 2965 if (keg->uk_ppera > 1) { 2966#else --- 22 unchanged lines hidden (view full) --- 2989void 2990uma_prealloc(uma_zone_t zone, int items) 2991{ 2992 int slabs; 2993 uma_slab_t slab; 2994 uma_keg_t keg; 2995 2996 keg = zone_first_keg(zone); | 3002 pages = count / keg->uk_ipers; 3003 3004 if (pages * keg->uk_ipers < count) 3005 pages++; 3006 3007#ifdef UMA_MD_SMALL_ALLOC 3008 if (keg->uk_ppera > 1) { 3009#else --- 22 unchanged lines hidden (view full) --- 3032void 3033uma_prealloc(uma_zone_t zone, int items) 3034{ 3035 int slabs; 3036 uma_slab_t slab; 3037 uma_keg_t keg; 3038 3039 keg = zone_first_keg(zone); |
3040 if (keg == NULL) 3041 return; |
|
2997 ZONE_LOCK(zone); 2998 slabs = items / keg->uk_ipers; 2999 if (slabs * keg->uk_ipers < items) 3000 slabs++; 3001 while (slabs > 0) { 3002 slab = keg_alloc_slab(keg, zone, M_WAITOK); 3003 if (slab == NULL) 3004 break; --- 73 unchanged lines hidden (view full) --- 3078 return (NULL); 3079 mem = page_alloc(NULL, size, &flags, wait); 3080 if (mem) { 3081 vsetslab((vm_offset_t)mem, slab); 3082 slab->us_data = mem; 3083 slab->us_flags = flags | UMA_SLAB_MALLOC; 3084 slab->us_size = size; 3085 } else { | 3042 ZONE_LOCK(zone); 3043 slabs = items / keg->uk_ipers; 3044 if (slabs * keg->uk_ipers < items) 3045 slabs++; 3046 while (slabs > 0) { 3047 slab = keg_alloc_slab(keg, zone, M_WAITOK); 3048 if (slab == NULL) 3049 break; --- 73 unchanged lines hidden (view full) --- 3123 return (NULL); 3124 mem = page_alloc(NULL, size, &flags, wait); 3125 if (mem) { 3126 vsetslab((vm_offset_t)mem, slab); 3127 slab->us_data = mem; 3128 slab->us_flags = flags | UMA_SLAB_MALLOC; 3129 slab->us_size = size; 3130 } else { |
3086 zone_free_item(slabzone, slab, NULL, SKIP_NONE, 3087 ZFREE_STATFAIL | ZFREE_STATFREE); | 3131 zone_free_item(slabzone, slab, NULL, SKIP_NONE); |
3088 } 3089 3090 return (mem); 3091} 3092 3093void 3094uma_large_free(uma_slab_t slab) 3095{ 3096 vsetobj((vm_offset_t)slab->us_data, kmem_object); 3097 page_free(slab->us_data, slab->us_size, slab->us_flags); | 3132 } 3133 3134 return (mem); 3135} 3136 3137void 3138uma_large_free(uma_slab_t slab) 3139{ 3140 vsetobj((vm_offset_t)slab->us_data, kmem_object); 3141 page_free(slab->us_data, slab->us_size, slab->us_flags); |
3098 zone_free_item(slabzone, slab, NULL, SKIP_NONE, ZFREE_STATFREE); | 3142 zone_free_item(slabzone, slab, NULL, SKIP_NONE); |
3099} 3100 3101void 3102uma_print_stats(void) 3103{ 3104 zone_foreach(uma_print_zone); 3105} 3106 --- 258 unchanged lines hidden --- | 3143} 3144 3145void 3146uma_print_stats(void) 3147{ 3148 zone_foreach(uma_print_zone); 3149} 3150 --- 258 unchanged lines hidden --- |