]> mj.ucw.cz Git - libucw.git/blob - lib/bigalloc.c
Merged main branch to dev-sorter.
[libucw.git] / lib / bigalloc.c
1 /*
2  *      UCW Library -- Allocation of Large Aligned Buffers
3  *
4  *      (c) 2006--2007 Martin Mares <mj@ucw.cz>
5  *      (c) 2007 Pavel Charvat <char@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "lib/lib.h"
12
13 #include <sys/mman.h>
14 #include <string.h>
15
16 void *
17 page_alloc(unsigned int len)
18 {
19   ASSERT(!(len & (CPU_PAGE_SIZE-1)));
20   byte *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
21   if (p == (byte*) MAP_FAILED)
22     die("Cannot mmap %d bytes of memory: %m", len);
23   return p;
24 }
25
26 void
27 page_free(void *start, unsigned int len)
28 {
29   ASSERT(!(len & (CPU_PAGE_SIZE-1)));
30   ASSERT(!((uintptr_t) start & (CPU_PAGE_SIZE-1)));
31   munmap(start, len);
32 }
33
34 void *
35 page_realloc(void *start, unsigned int old_len, unsigned int new_len)
36 {
37   void *p = page_alloc(new_len);
38   memcpy(p, start, MIN(old_len, new_len));
39   page_free(start, old_len);
40   return p;
41 }
42
43 static u64
44 big_round(u64 len)
45 {
46   return ALIGN_TO(len, (u64)CPU_PAGE_SIZE);
47 }
48
49 void *
50 big_alloc(u64 len)
51 {
52   len = big_round(len);
53 #ifndef CPU_64BIT_POINTERS
54   if (len > 0xff000000)
55     die("big_alloc: Size %ju is too large for a 32-bit machine", (uintmax_t) len);
56 #endif
57 #ifdef CONFIG_DEBUG
58   len += 2*CPU_PAGE_SIZE;
59 #endif
60   byte *p = page_alloc(len);
61 #ifdef CONFIG_DEBUG
62   mprotect(p, CPU_PAGE_SIZE, PROT_NONE);
63   mprotect(p+len-CPU_PAGE_SIZE, CPU_PAGE_SIZE, PROT_NONE);
64   p += CPU_PAGE_SIZE;
65 #endif
66   return p;
67 }
68
69 void
70 big_free(void *start, u64 len)
71 {
72   byte *p = start;
73   len = big_round(len);
74 #ifdef CONFIG_DEBUG
75   p -= CPU_PAGE_SIZE;
76   len += 2*CPU_PAGE_SIZE;
77 #endif
78   page_free(p, len);
79 }
80
81 #ifdef TEST
82
83 int main(void)
84 {
85   byte *p = big_alloc(123456);
86   // p[-1] = 1;
87   big_free(p, 123456);
88   return 0;
89 }
90
91 #endif