Major libcaps work to support userland threading. Stage 1/2.
[dragonfly.git] / lib / libcaps / slaballoc.c
1 /*
2  * SLABALLOC.C  - Userland SLAB memory allocator
3  *
4  * Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>
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
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $DragonFly: src/lib/libcaps/slaballoc.c,v 1.2 2003/12/04 22:06:19 dillon Exp $
29  *
30  * This module implements a thread-safe slab allocator for userland.
31  *
32  * A slab allocator reserves a ZONE for each chunk size, then lays the
33  * chunks out in an array within the zone.  Allocation and deallocation
34  * is nearly instantanious, and fragmentation/overhead losses are limited
35  * to a fixed worst-case amount.
36  *
37  * The downside of this slab implementation is in the chunk size
38  * multiplied by the number of zones.  ~80 zones * 128K = 10MB of VM per cpu.
39  * To mitigate this we attempt to select a reasonable zone size based on
40  * available system memory.  e.g. 32K instead of 128K.  Also since the
41  * slab allocator is operating out of virtual memory in userland the actual
42  * physical memory use is not as bad as it might otherwise be.
43  *
44  * The upside is that overhead is bounded... waste goes down as use goes up.
45  *
46  * Slab management is done on a per-cpu basis and no locking or mutexes
47  * are required, only a critical section.  When one cpu frees memory
48  * belonging to another cpu's slab manager an asynchronous IPI message
49  * will be queued to execute the operation.   In addition, both the
50  * high level slab allocator and the low level zone allocator optimize
51  * M_ZERO requests, and the slab allocator does not have to pre initialize
52  * the linked list of chunks.
53  *
54  * XXX Balancing is needed between cpus.  Balance will be handled through
55  * asynchronous IPIs primarily by reassigning the z_Cpu ownership of chunks.
56  *
57  *      Alloc Size      Chunking        Number of zones
58  *      0-127           8               16
59  *      128-255         16              8
60  *      256-511         32              8
61  *      512-1023        64              8
62  *      1024-2047       128             8
63  *      2048-4095       256             8
64  *      4096-8191       512             8
65  *      8192-16383      1024            8
66  *      16384-32767     2048            8
67  *      (if PAGE_SIZE is 4K the maximum zone allocation is 16383)
68  *
69  *      Allocations >= ZoneLimit go directly to kmem.
70  *
71  *                      API REQUIREMENTS AND SIDE EFFECTS
72  *
73  *    To operate as a drop-in replacement to the FreeBSD-4.x malloc() we
74  *    have remained compatible with the following API requirements:
75  *
76  *    + small power-of-2 sized allocations are power-of-2 aligned (kern_tty)
77  *    + all power-of-2 sized allocations are power-of-2 aligned (twe)
78  *    + malloc(0) is allowed and returns non-NULL (ahc driver)
79  *    + ability to allocate arbitrarily large chunks of memory
80  */
81
82 #include <string.h>
83 #include <stdlib.h>
84 #include <sys/types.h>
85 #include <sys/mman.h>
86 #include <sys/stdint.h>
87 #include <sys/malloc.h>
88 #include "thread.h"
89 #include <sys/thread.h>
90 #include <sys/msgport.h>
91 #include <sys/errno.h>
92 #include "globaldata.h"
93 #include <sys/sysctl.h>
94 #include <sys/thread2.h>
95 #include <sys/msgport2.h>
96
97 #define arysize(ary)    (sizeof(ary)/sizeof((ary)[0]))
98 #define slab_min(a,b)   (((a)<(b)) ? (a) : (b))
99
100 /*
101  * Fixed globals (not per-cpu)
102  */
103 static int ZoneSize;
104 static int ZoneLimit;
105 static int ZonePageCount;
106 static int ZonePageLimit;
107 static int ZoneMask;
108 static struct malloc_type *kmemstatistics;
109 static int32_t weirdary[16];
110
111 /*
112  * Misc constants.  Note that allocations that are exact multiples of 
113  * PAGE_SIZE, or exceed the zone limit, fall through to the kmem module.
114  * IN_SAME_PAGE_MASK is used to sanity-check the per-page free lists.
115  */
116 #define MIN_CHUNK_SIZE          8               /* in bytes */
117 #define MIN_CHUNK_MASK          (MIN_CHUNK_SIZE - 1)
118 #define ZONE_RELS_THRESH        2               /* threshold number of zones */
119 #define IN_SAME_PAGE_MASK       (~(intptr_t)PAGE_MASK | MIN_CHUNK_MASK)
120
121 #define SLOVERSZ_HSIZE          8192
122 #define SLOVERSZ_HMASK          (SLOVERSZ_HSIZE - 1)
123
124 #define SLOVERSZ_HASH(ptr)      ((((uintptr_t)ptr >> PAGE_SHIFT) ^ \
125                                 ((uintptr_t)ptr >> (PAGE_SHIFT * 2))) & \
126                                 SLOVERSZ_HMASK)
127
128 SLOversized *SLOvHash[SLOVERSZ_HSIZE];
129
130 /*
131  * The WEIRD_ADDR is used as known text to copy into free objects to
132  * try to create deterministic failure cases if the data is accessed after
133  * free.
134  */    
135 #define WEIRD_ADDR      0xdeadc0de
136 #define MAX_COPY        sizeof(weirdary)
137 #define ZERO_LENGTH_PTR ((void *)-8)
138
139 /*
140  * Misc global malloc buckets
141  */
142 MALLOC_DEFINE(M_OVERSIZED, "overszinfo", "Oversized Info Blocks");
143
144 static __inline
145 SLOversized **
146 get_oversized(void *ptr)
147 {
148     SLOversized **slovpp;
149     SLOversized *slov;
150
151     for (slovpp = &SLOvHash[SLOVERSZ_HASH(ptr)];
152         (slov = *slovpp) != NULL;
153         slovpp = &slov->ov_Next
154     ) {
155         if (slov->ov_Ptr == ptr)
156             return(slovpp);
157     }
158     return(NULL);
159 }
160  
161 /*
162  * Initialize the slab memory allocator.  We have to choose a zone size based
163  * on available physical memory.  We choose a zone side which is approximately
164  * 1/1024th of our memory, so if we have 128MB of ram we have a zone size of
165  * 128K.  The zone size is limited to the bounds set in slaballoc.h
166  * (typically 32K min, 128K max). 
167  */
168 void
169 slab_init(void)
170 {
171     int i;
172     int error;
173     int pagecnt;
174     int pagecnt_size = sizeof(pagecnt);
175
176     error = sysctlbyname("vm.stats.vm.v_page_count",
177                         &pagecnt, &pagecnt_size, NULL, 0);
178     if (error == 0) {
179         vm_poff_t limsize;
180         int usesize;
181
182         limsize = pagecnt * (vm_poff_t)PAGE_SIZE;
183         usesize = (int)(limsize / 1024);        /* convert to KB */
184
185         ZoneSize = ZALLOC_MIN_ZONE_SIZE;
186         while (ZoneSize < ZALLOC_MAX_ZONE_SIZE && (ZoneSize << 1) < usesize)
187             ZoneSize <<= 1;
188     } else {
189         ZoneSize = ZALLOC_MIN_ZONE_SIZE;
190     }
191     ZoneLimit = ZoneSize / 4;
192     if (ZoneLimit > ZALLOC_ZONE_LIMIT)
193         ZoneLimit = ZALLOC_ZONE_LIMIT;
194     ZoneMask = ZoneSize - 1;
195     ZonePageLimit = PAGE_SIZE * 4;
196     ZonePageCount = ZoneSize / PAGE_SIZE;
197
198     for (i = 0; i < arysize(weirdary); ++i)
199         weirdary[i] = WEIRD_ADDR;
200     slab_malloc_init(M_OVERSIZED);
201 }
202
203 /*
204  * Initialize a malloc type tracking structure.
205  */
206 void
207 slab_malloc_init(void *data)
208 {
209     struct malloc_type *type = data;
210     vm_poff_t limsize;
211
212     /*
213      * Skip if already initialized
214      */
215     if (type->ks_limit != 0)
216         return;
217
218     type->ks_magic = M_MAGIC;
219     limsize = (vm_poff_t)-1;    /* unlimited */
220     type->ks_limit = limsize / 10;
221     type->ks_next = kmemstatistics;
222     kmemstatistics = type;
223 }
224
225 void
226 slab_malloc_uninit(void *data)
227 {
228     struct malloc_type *type = data;
229     struct malloc_type *t;
230 #ifdef INVARIANTS
231     int i;
232     long ttl;
233 #endif
234
235     if (type->ks_magic != M_MAGIC)
236         panic("malloc type lacks magic");
237
238     if (type->ks_limit == 0)
239         panic("malloc_uninit on uninitialized type");
240
241 #ifdef INVARIANTS
242     /*
243      * memuse is only correct in aggregation.  Due to memory being allocated
244      * on one cpu and freed on another individual array entries may be 
245      * negative or positive (canceling each other out).
246      */
247     for (i = ttl = 0; i < ncpus; ++i)
248         ttl += type->ks_memuse[i];
249     if (ttl) {
250         printf("malloc_uninit: %ld bytes of '%s' still allocated on cpu %d\n",
251             ttl, type->ks_shortdesc, i);
252     }
253 #endif
254     if (type == kmemstatistics) {
255         kmemstatistics = type->ks_next;
256     } else {
257         for (t = kmemstatistics; t->ks_next != NULL; t = t->ks_next) {
258             if (t->ks_next == type) {
259                 t->ks_next = type->ks_next;
260                 break;
261             }
262         }
263     }
264     type->ks_next = NULL;
265     type->ks_limit = 0;
266 }
267
268 /*
269  * Calculate the zone index for the allocation request size and set the
270  * allocation request size to that particular zone's chunk size.
271  */
272 static __inline int
273 zoneindex(unsigned long *bytes)
274 {
275     unsigned int n = (unsigned int)*bytes;      /* unsigned for shift opt */
276     if (n < 128) {
277         *bytes = n = (n + 7) & ~7;
278         return(n / 8 - 1);              /* 8 byte chunks, 16 zones */
279     }
280     if (n < 256) {
281         *bytes = n = (n + 15) & ~15;
282         return(n / 16 + 7);
283     }
284     if (n < 8192) {
285         if (n < 512) {
286             *bytes = n = (n + 31) & ~31;
287             return(n / 32 + 15);
288         }
289         if (n < 1024) {
290             *bytes = n = (n + 63) & ~63;
291             return(n / 64 + 23);
292         } 
293         if (n < 2048) {
294             *bytes = n = (n + 127) & ~127;
295             return(n / 128 + 31);
296         }
297         if (n < 4096) {
298             *bytes = n = (n + 255) & ~255;
299             return(n / 256 + 39);
300         }
301         *bytes = n = (n + 511) & ~511;
302         return(n / 512 + 47);
303     }
304 #if ZALLOC_ZONE_LIMIT > 8192
305     if (n < 16384) {
306         *bytes = n = (n + 1023) & ~1023;
307         return(n / 1024 + 55);
308     }
309 #endif
310 #if ZALLOC_ZONE_LIMIT > 16384
311     if (n < 32768) {
312         *bytes = n = (n + 2047) & ~2047;
313         return(n / 2048 + 63);
314     }
315 #endif
316     panic("Unexpected byte count %d", n);
317     return(0);
318 }
319
320 /*
321  * slab_malloc()
322  *
323  *      Allocate memory via the slab allocator.  If the request is too large,
324  *      or if it page-aligned beyond a certain size, we fall back to the
325  *      KMEM subsystem.  A SLAB tracking descriptor must be specified, use
326  *      &SlabMisc if you don't care.
327  *
328  *      M_NOWAIT        - return NULL instead of blocking.
329  *      M_ZERO          - zero the returned memory.
330  */
331 void *
332 slab_malloc(unsigned long size, struct malloc_type *type, int flags)
333 {
334     SLZone *z;
335     SLChunk *chunk;
336     SLGlobalData *slgd;
337     struct globaldata *gd;
338     int zi;
339
340     gd = mycpu;
341     slgd = &gd->gd_slab;
342
343     /*
344      * XXX silly to have this in the critical path.
345      */
346     if (type->ks_limit == 0) {
347         crit_enter();
348         if (type->ks_limit == 0)
349             slab_malloc_init(type);
350         crit_exit();
351     }
352     ++type->ks_calls;
353
354     /*
355      * Handle the case where the limit is reached.  Panic if can't return
356      * NULL.  XXX the original malloc code looped, but this tended to
357      * simply deadlock the computer.
358      */
359     while (type->ks_loosememuse >= type->ks_limit) {
360         int i;
361         long ttl;
362
363         for (i = ttl = 0; i < ncpus; ++i)
364             ttl += type->ks_memuse[i];
365         type->ks_loosememuse = ttl;
366         if (ttl >= type->ks_limit) {
367             if (flags & (M_NOWAIT|M_NULLOK))
368                 return(NULL);
369             panic("%s: malloc limit exceeded", type->ks_shortdesc);
370         }
371     }
372
373     /*
374      * Handle the degenerate size == 0 case.  Yes, this does happen.
375      * Return a special pointer.  This is to maintain compatibility with
376      * the original malloc implementation.  Certain devices, such as the
377      * adaptec driver, not only allocate 0 bytes, they check for NULL and
378      * also realloc() later on.  Joy.
379      */
380     if (size == 0)
381         return(ZERO_LENGTH_PTR);
382
383     /*
384      * Handle hysteresis from prior frees here in malloc().  We cannot
385      * safely manipulate the kernel_map in free() due to free() possibly
386      * being called via an IPI message or from sensitive interrupt code.
387      */
388     while (slgd->NFreeZones > ZONE_RELS_THRESH && (flags & M_NOWAIT) == 0) {
389         crit_enter();
390         if (slgd->NFreeZones > ZONE_RELS_THRESH) {      /* crit sect race */
391             z = slgd->FreeZones;
392             slgd->FreeZones = z->z_Next;
393             --slgd->NFreeZones;
394             munmap(z, ZoneSize);
395         }
396         crit_exit();
397     }
398     /*
399      * XXX handle oversized frees that were queued from free().
400      */
401     while (slgd->FreeOvZones && (flags & M_NOWAIT) == 0) {
402         crit_enter();
403         if ((z = slgd->FreeOvZones) != NULL) {
404             KKASSERT(z->z_Magic == ZALLOC_OVSZ_MAGIC);
405             slgd->FreeOvZones = z->z_Next;
406             munmap(z, z->z_ChunkSize);
407         }
408         crit_exit();
409     }
410
411     /*
412      * Handle large allocations directly.  There should not be very many of
413      * these so performance is not a big issue.
414      *
415      * Guarentee page alignment for allocations in multiples of PAGE_SIZE
416      */
417     if (size >= ZoneLimit || (size & PAGE_MASK) == 0) {
418         SLOversized **slovpp;
419         SLOversized *slov;
420
421         slov = slab_malloc(sizeof(SLOversized), M_OVERSIZED, M_ZERO);
422         if (slov == NULL)
423             return(NULL);
424
425         size = round_page(size);
426         chunk = mmap(NULL, size, PROT_READ|PROT_WRITE,
427                         MAP_ANON|MAP_PRIVATE, -1, 0);
428         if (chunk == MAP_FAILED) {
429             slab_free(slov, M_OVERSIZED);
430             return(NULL);
431         }
432         flags &= ~M_ZERO;       /* result already zero'd if M_ZERO was set */
433         flags |= M_PASSIVE_ZERO;
434
435         slov->ov_Ptr = chunk;
436         slov->ov_Bytes = size;
437         slovpp = &SLOvHash[SLOVERSZ_HASH(chunk)];
438         slov->ov_Next = *slovpp;
439         *slovpp = slov;
440         crit_enter();
441         goto done;
442     }
443
444     /*
445      * Attempt to allocate out of an existing zone.  First try the free list,
446      * then allocate out of unallocated space.  If we find a good zone move
447      * it to the head of the list so later allocations find it quickly
448      * (we might have thousands of zones in the list).
449      *
450      * Note: zoneindex() will panic of size is too large.
451      */
452     zi = zoneindex(&size);
453     KKASSERT(zi < NZONES);
454     crit_enter();
455     if ((z = slgd->ZoneAry[zi]) != NULL) {
456         KKASSERT(z->z_NFree > 0);
457
458         /*
459          * Remove us from the ZoneAry[] when we become empty
460          */
461         if (--z->z_NFree == 0) {
462             slgd->ZoneAry[zi] = z->z_Next;
463             z->z_Next = NULL;
464         }
465
466         /*
467          * Locate a chunk in a free page.  This attempts to localize
468          * reallocations into earlier pages without us having to sort
469          * the chunk list.  A chunk may still overlap a page boundary.
470          */
471         while (z->z_FirstFreePg < ZonePageCount) {
472             if ((chunk = z->z_PageAry[z->z_FirstFreePg]) != NULL) {
473 #ifdef DIAGNOSTIC
474                 /*
475                  * Diagnostic: c_Next is not total garbage.
476                  */
477                 KKASSERT(chunk->c_Next == NULL ||
478                         ((intptr_t)chunk->c_Next & IN_SAME_PAGE_MASK) ==
479                         ((intptr_t)chunk & IN_SAME_PAGE_MASK));
480 #endif
481 #ifdef INVARIANTS
482                 if ((uintptr_t)chunk < VM_MIN_KERNEL_ADDRESS)
483                         panic("chunk %p FFPG %d/%d", chunk, z->z_FirstFreePg, ZonePageCount);
484                 if (chunk->c_Next && (uintptr_t)chunk->c_Next < VM_MIN_KERNEL_ADDRESS)
485                         panic("chunkNEXT %p %p FFPG %d/%d", chunk, chunk->c_Next, z->z_FirstFreePg, ZonePageCount);
486 #endif
487                 z->z_PageAry[z->z_FirstFreePg] = chunk->c_Next;
488                 goto done;
489             }
490             ++z->z_FirstFreePg;
491         }
492
493         /*
494          * No chunks are available but NFree said we had some memory, so
495          * it must be available in the never-before-used-memory area
496          * governed by UIndex.  The consequences are very serious if our zone
497          * got corrupted so we use an explicit panic rather then a KASSERT.
498          */
499         if (z->z_UIndex + 1 != z->z_NMax)
500             z->z_UIndex = z->z_UIndex + 1;
501         else
502             z->z_UIndex = 0;
503         if (z->z_UIndex == z->z_UEndIndex)
504             panic("slaballoc: corrupted zone");
505         chunk = (SLChunk *)(z->z_BasePtr + z->z_UIndex * size);
506         if ((z->z_Flags & SLZF_UNOTZEROD) == 0) {
507             flags &= ~M_ZERO;
508             flags |= M_PASSIVE_ZERO;
509         }
510         goto done;
511     }
512
513     /*
514      * If all zones are exhausted we need to allocate a new zone for this
515      * index.  Use M_ZERO to take advantage of pre-zerod pages.  Also see
516      * UAlloc use above in regards to M_ZERO.  Note that when we are reusing
517      * a zone from the FreeZones list UAlloc'd data will not be zero'd, and
518      * we do not pre-zero it because we do not want to mess up the L1 cache.
519      *
520      * At least one subsystem, the tty code (see CROUND) expects power-of-2
521      * allocations to be power-of-2 aligned.  We maintain compatibility by
522      * adjusting the base offset below.
523      */
524     {
525         int off;
526
527         if ((z = slgd->FreeZones) != NULL) {
528             slgd->FreeZones = z->z_Next;
529             --slgd->NFreeZones;
530             bzero(z, sizeof(SLZone));
531             z->z_Flags |= SLZF_UNOTZEROD;
532         } else {
533             z = mmap(NULL, ZoneSize, PROT_READ|PROT_WRITE,
534                     MAP_ANON|MAP_PRIVATE, -1, 0);
535             if (z == MAP_FAILED)
536                 goto fail;
537         }
538
539         /*
540          * Guarentee power-of-2 alignment for power-of-2-sized chunks.
541          * Otherwise just 8-byte align the data.
542          */
543         if ((size | (size - 1)) + 1 == (size << 1))
544             off = (sizeof(SLZone) + size - 1) & ~(size - 1);
545         else
546             off = (sizeof(SLZone) + MIN_CHUNK_MASK) & ~MIN_CHUNK_MASK;
547         z->z_Magic = ZALLOC_SLAB_MAGIC;
548         z->z_ZoneIndex = zi;
549         z->z_NMax = (ZoneSize - off) / size;
550         z->z_NFree = z->z_NMax - 1;
551         z->z_BasePtr = (char *)z + off;
552         z->z_UIndex = z->z_UEndIndex = slgd->JunkIndex % z->z_NMax;
553         z->z_ChunkSize = size;
554         z->z_FirstFreePg = ZonePageCount;
555         z->z_Cpu = gd->gd_cpuid;
556         chunk = (SLChunk *)(z->z_BasePtr + z->z_UIndex * size);
557         z->z_Next = slgd->ZoneAry[zi];
558         slgd->ZoneAry[zi] = z;
559         if ((z->z_Flags & SLZF_UNOTZEROD) == 0) {
560             flags &= ~M_ZERO;   /* already zero'd */
561             flags |= M_PASSIVE_ZERO;
562         }
563
564         /*
565          * Slide the base index for initial allocations out of the next
566          * zone we create so we do not over-weight the lower part of the
567          * cpu memory caches.
568          */
569         slgd->JunkIndex = (slgd->JunkIndex + ZALLOC_SLAB_SLIDE)
570                                 & (ZALLOC_MAX_ZONE_SIZE - 1);
571     }
572 done:
573     ++type->ks_inuse[gd->gd_cpuid];
574     type->ks_memuse[gd->gd_cpuid] += size;
575     type->ks_loosememuse += size;
576     crit_exit();
577     if (flags & M_ZERO)
578         bzero(chunk, size);
579 #ifdef INVARIANTS
580     else if ((flags & (M_ZERO|M_PASSIVE_ZERO)) == 0)
581         chunk->c_Next = (void *)-1; /* avoid accidental double-free check */
582 #endif
583     return(chunk);
584 fail:
585     crit_exit();
586     return(NULL);
587 }
588
589 void *
590 slab_realloc(void *ptr, unsigned long size, struct malloc_type *type, int flags)
591 {
592     SLZone *z;
593     SLOversized **slovpp;
594     SLOversized *slov;
595     void *nptr;
596     unsigned long osize;
597
598     if (ptr == NULL || ptr == ZERO_LENGTH_PTR)
599         return(slab_malloc(size, type, flags));
600     if (size == 0) {
601         slab_free(ptr, type);
602         return(NULL);
603     }
604
605     /*
606      * Handle oversized allocations. 
607      */
608     if ((slovpp = get_oversized(ptr)) != NULL) {
609         slov = *slovpp;
610         osize = slov->ov_Bytes;
611         if (osize == round_page(size))
612             return(ptr);
613         if ((nptr = slab_malloc(size, type, flags)) == NULL)
614             return(NULL);
615         bcopy(ptr, nptr, slab_min(size, osize));
616         slab_free(ptr, type);
617         return(nptr);
618     }
619
620     /*
621      * Get the original allocation's zone.  If the new request winds up
622      * using the same chunk size we do not have to do anything.
623      */
624     z = (SLZone *)((uintptr_t)ptr & ~(uintptr_t)ZoneMask);
625     KKASSERT(z->z_Magic == ZALLOC_SLAB_MAGIC);
626
627     zoneindex(&size);
628     if (z->z_ChunkSize == size)
629         return(ptr);
630
631     /*
632      * Allocate memory for the new request size.  Note that zoneindex has
633      * already adjusted the request size to the appropriate chunk size, which
634      * should optimize our bcopy().  Then copy and return the new pointer.
635      */
636     if ((nptr = slab_malloc(size, type, flags)) == NULL)
637         return(NULL);
638     bcopy(ptr, nptr, slab_min(size, z->z_ChunkSize));
639     slab_free(ptr, type);
640     return(nptr);
641 }
642
643 #ifdef SMP
644 /*
645  * slab_free()  (SLAB ALLOCATOR)
646  *
647  *      Free the specified chunk of memory.
648  */
649 static
650 void
651 slab_free_remote(void *ptr)
652 {
653     slab_free(ptr, *(struct malloc_type **)ptr);
654 }
655
656 #endif
657
658 void
659 slab_free(void *ptr, struct malloc_type *type)
660 {
661     SLZone *z;
662     SLOversized **slovpp;
663     SLOversized *slov;
664     SLChunk *chunk;
665     SLGlobalData *slgd;
666     struct globaldata *gd;
667     int pgno;
668
669     gd = mycpu;
670     slgd = &gd->gd_slab;
671
672     /*
673      * Handle special 0-byte allocations
674      */
675     if (ptr == ZERO_LENGTH_PTR)
676         return;
677
678     /*
679      * Handle oversized allocations.  XXX we really should require that a
680      * size be passed to slab_free() instead of this nonsense.
681      *
682      * This code is never called via an ipi.
683      */
684     if ((slovpp = get_oversized(ptr)) != NULL) {
685         slov = *slovpp;
686         *slovpp = slov->ov_Next;
687
688 #ifdef INVARIANTS
689         KKASSERT(sizeof(weirdary) <= slov->ov_Bytes);
690         bcopy(weirdary, ptr, sizeof(weirdary));
691 #endif
692         /*
693          * note: we always adjust our cpu's slot, not the originating
694          * cpu (kup->ku_cpuid).  The statistics are in aggregate.
695          *
696          * note: XXX we have still inherited the interrupts-can't-block
697          * assumption.  An interrupt thread does not bump
698          * gd_intr_nesting_level so check TDF_INTTHREAD.  This is
699          * primarily until we can fix softupdate's assumptions about 
700          * slab_free().
701          */
702         crit_enter();
703         --type->ks_inuse[gd->gd_cpuid];
704         type->ks_memuse[gd->gd_cpuid] -= slov->ov_Bytes;
705         if (mycpu->gd_intr_nesting_level || (gd->gd_curthread->td_flags & TDF_INTTHREAD)) {
706             z = (SLZone *)ptr;
707             z->z_Magic = ZALLOC_OVSZ_MAGIC;
708             z->z_Next = slgd->FreeOvZones;
709             z->z_ChunkSize = slov->ov_Bytes;
710             slgd->FreeOvZones = z;
711             crit_exit();
712         } else {
713             crit_exit();
714             munmap(ptr, slov->ov_Bytes);
715         }
716         slab_free(slov, M_OVERSIZED);
717         return;
718     }
719
720     /*
721      * Zone case.  Figure out the zone based on the fact that it is
722      * ZoneSize aligned. 
723      */
724     z = (SLZone *)((uintptr_t)ptr & ~(uintptr_t)ZoneMask);
725     KKASSERT(z->z_Magic == ZALLOC_SLAB_MAGIC);
726
727     /*
728      * If we do not own the zone then forward the request to the
729      * cpu that does.  The freeing code does not need the byte count
730      * unless DIAGNOSTIC is set.
731      */
732     if (z->z_Cpu != gd->gd_cpuid) {
733         *(struct malloc_type **)ptr = type;
734 #ifdef SMP
735         lwkt_send_ipiq(z->z_Cpu, slab_free_remote, ptr);
736 #else
737         panic("Corrupt SLZone");
738 #endif
739         return;
740     }
741
742     if (type->ks_magic != M_MAGIC)
743         panic("slab_free: malloc type lacks magic");
744
745     crit_enter();
746     pgno = ((char *)ptr - (char *)z) >> PAGE_SHIFT;
747     chunk = ptr;
748
749 #ifdef INVARIANTS
750     /*
751      * Attempt to detect a double-free.  To reduce overhead we only check
752      * if there appears to be link pointer at the base of the data.
753      */
754     if (((intptr_t)chunk->c_Next - (intptr_t)z) >> PAGE_SHIFT == pgno) {
755         SLChunk *scan;
756         for (scan = z->z_PageAry[pgno]; scan; scan = scan->c_Next) {
757             if (scan == chunk)
758                 panic("Double free at %p", chunk);
759         }
760     }
761 #endif
762
763     /*
764      * Put weird data into the memory to detect modifications after freeing,
765      * illegal pointer use after freeing (we should fault on the odd address),
766      * and so forth.  XXX needs more work, see the old malloc code.
767      */
768 #ifdef INVARIANTS
769     if (z->z_ChunkSize < sizeof(weirdary))
770         bcopy(weirdary, chunk, z->z_ChunkSize);
771     else
772         bcopy(weirdary, chunk, sizeof(weirdary));
773 #endif
774
775     /*
776      * Add this free non-zero'd chunk to a linked list for reuse, adjust
777      * z_FirstFreePg.
778      */
779 #ifdef INVARIANTS
780     if ((uintptr_t)chunk < VM_MIN_KERNEL_ADDRESS)
781         panic("BADFREE %p\n", chunk);
782 #endif
783     chunk->c_Next = z->z_PageAry[pgno];
784     z->z_PageAry[pgno] = chunk;
785 #ifdef INVARIANTS
786     if (chunk->c_Next && (uintptr_t)chunk->c_Next < VM_MIN_KERNEL_ADDRESS)
787         panic("BADFREE2");
788 #endif
789     if (z->z_FirstFreePg > pgno)
790         z->z_FirstFreePg = pgno;
791
792     /*
793      * Bump the number of free chunks.  If it becomes non-zero the zone
794      * must be added back onto the appropriate list.
795      */
796     if (z->z_NFree++ == 0) {
797         z->z_Next = slgd->ZoneAry[z->z_ZoneIndex];
798         slgd->ZoneAry[z->z_ZoneIndex] = z;
799     }
800
801     --type->ks_inuse[z->z_Cpu];
802     type->ks_memuse[z->z_Cpu] -= z->z_ChunkSize;
803
804     /*
805      * If the zone becomes totally free, and there are other zones we
806      * can allocate from, move this zone to the FreeZones list.  Since
807      * this code can be called from an IPI callback, do *NOT* try to mess
808      * with kernel_map here.  Hysteresis will be performed at malloc() time.
809      */
810     if (z->z_NFree == z->z_NMax && 
811         (z->z_Next || slgd->ZoneAry[z->z_ZoneIndex] != z)
812     ) {
813         SLZone **pz;
814
815         for (pz = &slgd->ZoneAry[z->z_ZoneIndex]; z != *pz; pz = &(*pz)->z_Next)
816             ;
817         *pz = z->z_Next;
818         z->z_Magic = -1;
819         z->z_Next = slgd->FreeZones;
820         slgd->FreeZones = z;
821         ++slgd->NFreeZones;
822     }
823     crit_exit();
824 }
825