patch-pre2.0.10 linux/mm/kmalloc.c
Next file: linux/net/appletalk/ddp.c
Previous file: linux/mm/filemap.c
Back to the patch index
Back to the overall index
- Lines: 168
- Date:
Fri May 31 16:47:46 1996
- Orig file:
pre2.0.9/linux/mm/kmalloc.c
- Orig date:
Fri May 31 08:02:20 1996
diff -u --recursive --new-file pre2.0.9/linux/mm/kmalloc.c linux/mm/kmalloc.c
@@ -185,12 +185,7 @@
static inline struct page_descriptor * get_kmalloc_pages(unsigned long priority,
unsigned long order, int dma)
{
- struct page_descriptor * tmp;
-
- tmp = (struct page_descriptor *) __get_free_pages(priority, order, dma);
- if (!tmp && !dma && order < MAX_CACHE_ORDER)
- tmp = xchg(kmalloc_cache+order, tmp);
- return tmp;
+ return (struct page_descriptor *) __get_free_pages(priority, order, dma);
}
static inline void free_kmalloc_pages(struct page_descriptor * page,
@@ -227,6 +222,10 @@
}
+/*
+ * Ugh, this is ugly, but we want the default case to run
+ * straight through, which is why we have the ugly goto's
+ */
void *kmalloc(size_t size, int priority)
{
unsigned long flags;
@@ -234,6 +233,7 @@
int order, dma;
struct block_header *p;
struct page_descriptor *page, **pg;
+ struct size_descriptor *bucket = sizes;
/* Get order */
order = 0;
@@ -244,6 +244,7 @@
if (realsize <= ordersize)
break;
order++;
+ bucket++;
if (ordersize)
continue;
printk("kmalloc of too large a block (%d bytes).\n", (int) size);
@@ -253,11 +254,11 @@
dma = 0;
type = MF_USED;
- pg = &sizes[order].firstfree;
+ pg = &bucket->firstfree;
if (priority & GFP_DMA) {
dma = 1;
type = MF_DMA;
- pg = &sizes[order].dmafree;
+ pg = &bucket->dmafree;
}
priority &= GFP_LEVEL_MASK;
@@ -275,15 +276,36 @@
save_flags(flags);
cli();
page = *pg;
- if (page) {
- p = page->firstfree;
- if (p->bh_flags != MF_FREE)
- goto not_free_on_freelist;
- goto found_it;
- }
+ if (!page)
+ goto no_bucket_page;
+
+ p = page->firstfree;
+ if (p->bh_flags != MF_FREE)
+ goto not_free_on_freelist;
- /* We need to get a new free page..... */
- /* This can be done with ints on: This is private to this invocation */
+found_it:
+ page->firstfree = p->bh_next;
+ page->nfree--;
+ if (!page->nfree)
+ *pg = page->next;
+ restore_flags(flags);
+ bucket->nmallocs++;
+ bucket->nbytesmalloced += size;
+ p->bh_flags = type; /* As of now this block is officially in use */
+ p->bh_length = size;
+#ifdef SADISTIC_KMALLOC
+ memset(p+1, 0xf0, size);
+#endif
+ return p + 1; /* Pointer arithmetic: increments past header */
+
+
+no_bucket_page:
+ /*
+ * If we didn't find a page already allocated for this
+ * bucket size, we need to get one..
+ *
+ * This can be done with ints on: it is private to this invocation
+ */
restore_flags(flags);
{
@@ -292,23 +314,27 @@
/* sz is the size of the blocks we're dealing with */
sz = BLOCKSIZE(order);
- page = get_kmalloc_pages(priority, sizes[order].gfporder, dma);
-
+ page = get_kmalloc_pages(priority, bucket->gfporder, dma);
if (!page)
goto no_free_page;
- sizes[order].npages++;
+found_cached_page:
+
+ bucket->npages++;
+ page->order = order;
/* Loop for all but last block: */
- for (i = NBLOCKS(order), p = BH(page + 1); i > 1; i--, p = p->bh_next) {
+ i = (page->nfree = bucket->nblocks) - 1;
+ p = BH(page + 1);
+ while (i > 0) {
+ i--;
p->bh_flags = MF_FREE;
p->bh_next = BH(((long) p) + sz);
+ p = p->bh_next;
}
/* Last block: */
p->bh_flags = MF_FREE;
p->bh_next = NULL;
- page->order = order;
- page->nfree = NBLOCKS(order);
p = BH(page+1);
}
@@ -319,23 +345,19 @@
cli();
page->next = *pg;
*pg = page;
+ goto found_it;
-found_it:
- page->firstfree = p->bh_next;
- page->nfree--;
- if (!page->nfree)
- *pg = page->next;
- restore_flags(flags);
- sizes[order].nmallocs++;
- sizes[order].nbytesmalloced += size;
- p->bh_flags = type; /* As of now this block is officially in use */
- p->bh_length = size;
-#ifdef SADISTIC_KMALLOC
- memset(p+1, 0xf0, size);
-#endif
- return p + 1; /* Pointer arithmetic: increments past header */
no_free_page:
+ /*
+ * No free pages, check the kmalloc cache of
+ * pages to see if maybe we have something available
+ */
+ if (!dma && order < MAX_CACHE_ORDER) {
+ page = xchg(kmalloc_cache+order, page);
+ if (page)
+ goto found_cached_page;
+ }
{
static unsigned long last = 0;
if (priority != GFP_BUFFER && (last + 10 * HZ < jiffies)) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this