1/*-
2 * Copyright (c) 2002-2005, 2009 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 247360 2013-02-26 23:35:27Z attilio $");
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
--- 14 unchanged lines hidden (view full) ---
74#include <sys/proc.h>
75#include <sys/sbuf.h>
76#include <sys/smp.h>
77#include <sys/vmmeter.h>
78
79#include <vm/vm.h>
80#include <vm/vm_object.h>
81#include <vm/vm_page.h>
82#include <vm/vm_pageout.h>
83#include <vm/vm_param.h>
84#include <vm/vm_map.h>
85#include <vm/vm_kern.h>
86#include <vm/vm_extern.h>
87#include <vm/uma.h>
88#include <vm/uma_int.h>
89#include <vm/uma_dbg.h>
90
--- 118 unchanged lines hidden (view full) ---
209 */
210enum zfreeskip { SKIP_NONE, SKIP_DTOR, SKIP_FINI };
211
212#define ZFREE_STATFAIL 0x00000001 /* Update zone failure statistic. */
213#define ZFREE_STATFREE 0x00000002 /* Update zone free statistic. */
214
215/* Prototypes.. */
216
217static void *noobj_alloc(uma_zone_t, int, u_int8_t *, int);
218static void *page_alloc(uma_zone_t, int, u_int8_t *, int);
219static void *startup_alloc(uma_zone_t, int, u_int8_t *, int);
220static void page_free(void *, int, u_int8_t);
221static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int);
222static void cache_drain(uma_zone_t);
223static void bucket_drain(uma_zone_t, uma_bucket_t);
224static void bucket_cache_drain(uma_zone_t zone);
225static int keg_ctor(void *, int, void *, int);
--- 800 unchanged lines hidden (view full) ---
1026 * bytes The number of bytes requested
1027 * wait Shall we wait?
1028 *
1029 * Returns:
1030 * A pointer to the alloced memory or possibly
1031 * NULL if M_NOWAIT is set.
1032 */
1033static void *
1034noobj_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
1035{
1036 TAILQ_HEAD(, vm_page) alloctail;
1037 u_long npages;
1038 vm_offset_t retkva, zkva;
1039 vm_page_t p, p_next;
1040 uma_keg_t keg;
1041
1042 TAILQ_INIT(&alloctail);
1043 keg = zone_first_keg(zone);
1044
1045 npages = howmany(bytes, PAGE_SIZE);
1046 while (npages > 0) {
1047 p = vm_page_alloc(NULL, 0, VM_ALLOC_INTERRUPT |
1048 VM_ALLOC_WIRED | VM_ALLOC_NOOBJ);
1049 if (p != NULL) {
1050 /*
1051 * Since the page does not belong to an object, its
1052 * listq is unused.
1053 */
1054 TAILQ_INSERT_TAIL(&alloctail, p, listq);
1055 npages--;
1056 continue;
1057 }
1058 if (wait & M_WAITOK) {
1059 VM_WAIT;
1060 continue;
1061 }
1062
1063 /*
1064 * Page allocation failed, free intermediate pages and
1065 * exit.
1066 */
1067 TAILQ_FOREACH_SAFE(p, &alloctail, listq, p_next) {
1068 vm_page_unwire(p, 0);
1069 vm_page_free(p);
1070 }
1071 return (NULL);
1072 }
1073 *flags = UMA_SLAB_PRIV;
1074 zkva = keg->uk_kva +
1075 atomic_fetchadd_long(&keg->uk_offset, round_page(bytes));
1076 retkva = zkva;
1077 TAILQ_FOREACH(p, &alloctail, listq) {
1078 pmap_qenter(zkva, &p, 1);
1079 zkva += PAGE_SIZE;
1080 }
1081
1082 return ((void *)retkva);
1083}
1084
1085/*
1086 * Frees a number of pages to the system
1087 *
1088 * Arguments:
--- 1922 unchanged lines hidden (view full) ---
3011 keg = zone_first_keg(zone);
3012 keg->uk_flags |= UMA_ZFLAG_PRIVALLOC;
3013 keg->uk_allocf = allocf;
3014 ZONE_UNLOCK(zone);
3015}
3016
3017/* See uma.h */
3018int
3019uma_zone_reserve_kva(uma_zone_t zone, int count)
3020{
3021 uma_keg_t keg;
3022 vm_offset_t kva;
3023 int pages;
3024
3025 keg = zone_first_keg(zone);
3026 pages = count / keg->uk_ipers;
3027
3028 if (pages * keg->uk_ipers < count)
3029 pages++;
3030
3031#ifdef UMA_MD_SMALL_ALLOC
3032 if (keg->uk_ppera > 1) {
3033#else
3034 if (1) {
3035#endif
3036 kva = kmem_alloc_nofault(kernel_map, pages * UMA_SLAB_SIZE);
3037 if (kva == 0)
3038 return (0);
3039 } else
3040 kva = 0;
3041 ZONE_LOCK(zone);
3042 keg->uk_kva = kva;
3043 keg->uk_offset = 0;
3044 keg->uk_maxpages = pages;
3045#ifdef UMA_MD_SMALL_ALLOC
3046 keg->uk_allocf = (keg->uk_ppera > 1) ? noobj_alloc : uma_small_alloc;
3047#else
3048 keg->uk_allocf = noobj_alloc;
3049#endif
3050 keg->uk_flags |= UMA_ZONE_NOFREE | UMA_ZFLAG_PRIVALLOC;
3051 ZONE_UNLOCK(zone);
3052 return (1);
3053}
3054
3055/* See uma.h */
3056void
3057uma_prealloc(uma_zone_t zone, int items)
--- 375 unchanged lines hidden ---
2 * Copyright (c) 2002-2005, 2009 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 247360 2013-02-26 23:35:27Z attilio $");
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
--- 14 unchanged lines hidden (view full) ---
74#include <sys/proc.h>
75#include <sys/sbuf.h>
76#include <sys/smp.h>
77#include <sys/vmmeter.h>
78
79#include <vm/vm.h>
80#include <vm/vm_object.h>
81#include <vm/vm_page.h>
82#include <vm/vm_pageout.h>
83#include <vm/vm_param.h>
84#include <vm/vm_map.h>
85#include <vm/vm_kern.h>
86#include <vm/vm_extern.h>
87#include <vm/uma.h>
88#include <vm/uma_int.h>
89#include <vm/uma_dbg.h>
90
--- 118 unchanged lines hidden (view full) ---
209 */
210enum zfreeskip { SKIP_NONE, SKIP_DTOR, SKIP_FINI };
211
212#define ZFREE_STATFAIL 0x00000001 /* Update zone failure statistic. */
213#define ZFREE_STATFREE 0x00000002 /* Update zone free statistic. */
214
215/* Prototypes.. */
216
217static void *noobj_alloc(uma_zone_t, int, u_int8_t *, int);
218static void *page_alloc(uma_zone_t, int, u_int8_t *, int);
219static void *startup_alloc(uma_zone_t, int, u_int8_t *, int);
220static void page_free(void *, int, u_int8_t);
221static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int);
222static void cache_drain(uma_zone_t);
223static void bucket_drain(uma_zone_t, uma_bucket_t);
224static void bucket_cache_drain(uma_zone_t zone);
225static int keg_ctor(void *, int, void *, int);
--- 800 unchanged lines hidden (view full) ---
1026 * bytes The number of bytes requested
1027 * wait Shall we wait?
1028 *
1029 * Returns:
1030 * A pointer to the alloced memory or possibly
1031 * NULL if M_NOWAIT is set.
1032 */
1033static void *
1034noobj_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
1035{
1036 TAILQ_HEAD(, vm_page) alloctail;
1037 u_long npages;
1038 vm_offset_t retkva, zkva;
1039 vm_page_t p, p_next;
1040 uma_keg_t keg;
1041
1042 TAILQ_INIT(&alloctail);
1043 keg = zone_first_keg(zone);
1044
1045 npages = howmany(bytes, PAGE_SIZE);
1046 while (npages > 0) {
1047 p = vm_page_alloc(NULL, 0, VM_ALLOC_INTERRUPT |
1048 VM_ALLOC_WIRED | VM_ALLOC_NOOBJ);
1049 if (p != NULL) {
1050 /*
1051 * Since the page does not belong to an object, its
1052 * listq is unused.
1053 */
1054 TAILQ_INSERT_TAIL(&alloctail, p, listq);
1055 npages--;
1056 continue;
1057 }
1058 if (wait & M_WAITOK) {
1059 VM_WAIT;
1060 continue;
1061 }
1062
1063 /*
1064 * Page allocation failed, free intermediate pages and
1065 * exit.
1066 */
1067 TAILQ_FOREACH_SAFE(p, &alloctail, listq, p_next) {
1068 vm_page_unwire(p, 0);
1069 vm_page_free(p);
1070 }
1071 return (NULL);
1072 }
1073 *flags = UMA_SLAB_PRIV;
1074 zkva = keg->uk_kva +
1075 atomic_fetchadd_long(&keg->uk_offset, round_page(bytes));
1076 retkva = zkva;
1077 TAILQ_FOREACH(p, &alloctail, listq) {
1078 pmap_qenter(zkva, &p, 1);
1079 zkva += PAGE_SIZE;
1080 }
1081
1082 return ((void *)retkva);
1083}
1084
1085/*
1086 * Frees a number of pages to the system
1087 *
1088 * Arguments:
--- 1922 unchanged lines hidden (view full) ---
3011 keg = zone_first_keg(zone);
3012 keg->uk_flags |= UMA_ZFLAG_PRIVALLOC;
3013 keg->uk_allocf = allocf;
3014 ZONE_UNLOCK(zone);
3015}
3016
3017/* See uma.h */
3018int
3019uma_zone_reserve_kva(uma_zone_t zone, int count)
3020{
3021 uma_keg_t keg;
3022 vm_offset_t kva;
3023 int pages;
3024
3025 keg = zone_first_keg(zone);
3026 pages = count / keg->uk_ipers;
3027
3028 if (pages * keg->uk_ipers < count)
3029 pages++;
3030
3031#ifdef UMA_MD_SMALL_ALLOC
3032 if (keg->uk_ppera > 1) {
3033#else
3034 if (1) {
3035#endif
3036 kva = kmem_alloc_nofault(kernel_map, pages * UMA_SLAB_SIZE);
3037 if (kva == 0)
3038 return (0);
3039 } else
3040 kva = 0;
3041 ZONE_LOCK(zone);
3042 keg->uk_kva = kva;
3043 keg->uk_offset = 0;
3044 keg->uk_maxpages = pages;
3045#ifdef UMA_MD_SMALL_ALLOC
3046 keg->uk_allocf = (keg->uk_ppera > 1) ? noobj_alloc : uma_small_alloc;
3047#else
3048 keg->uk_allocf = noobj_alloc;
3049#endif
3050 keg->uk_flags |= UMA_ZONE_NOFREE | UMA_ZFLAG_PRIVALLOC;
3051 ZONE_UNLOCK(zone);
3052 return (1);
3053}
3054
3055/* See uma.h */
3056void
3057uma_prealloc(uma_zone_t zone, int items)
--- 375 unchanged lines hidden ---