]> mj.ucw.cz Git - libucw.git/blob - ucw/bigalloc.c
Tests: xtypes-test sets an explicit timezone
[libucw.git] / ucw / 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 <ucw/lib.h>
12
13 #include <sys/mman.h>
14 #include <string.h>
15 #include <limits.h>
16
17 void *
18 page_alloc(u64 len)
19 {
20   if (!len)
21     return NULL;
22   if (len > SIZE_MAX)
23     die("page_alloc: Size %llu is too large for the current architecture", (long long) len);
24   ASSERT(!(len & (CPU_PAGE_SIZE-1)));
25   byte *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
26   if (p == (byte*) MAP_FAILED)
27     die("Cannot mmap %llu bytes of memory: %m", (long long)len);
28   return p;
29 }
30
31 void *
32 page_alloc_zero(u64 len)
33 {
34   void *p = page_alloc(len);
35   bzero(p, len);
36   return p;
37 }
38
39 void
40 page_free(void *start, u64 len)
41 {
42   ASSERT(!(len & (CPU_PAGE_SIZE-1)));
43   ASSERT(!((uintptr_t) start & (CPU_PAGE_SIZE-1)));
44   munmap(start, len);
45 }
46
47 void *
48 page_realloc(void *start, u64 old_len, u64 new_len)
49 {
50   void *p = page_alloc(new_len);
51   memcpy(p, start, MIN(old_len, new_len));
52   page_free(start, old_len);
53   return p;
54 }
55
56 static u64
57 big_round(u64 len)
58 {
59   return ALIGN_TO(len, (u64)CPU_PAGE_SIZE);
60 }
61
62 void *
63 big_alloc(u64 len)
64 {
65   u64 l = big_round(len);
66   if (l > SIZE_MAX - 2*CPU_PAGE_SIZE)
67     die("big_alloc: Size %llu is too large for the current architecture", (long long) len);
68 #ifdef CONFIG_UCW_DEBUG
69   l += 2*CPU_PAGE_SIZE;
70 #endif
71   byte *p = page_alloc(l);
72 #ifdef CONFIG_UCW_DEBUG
73   *(u64*)p = len;
74   mprotect(p, CPU_PAGE_SIZE, PROT_NONE);
75   mprotect(p+l-CPU_PAGE_SIZE, CPU_PAGE_SIZE, PROT_NONE);
76   p += CPU_PAGE_SIZE;
77 #endif
78   return p;
79 }
80
81 void *
82 big_alloc_zero(u64 len)
83 {
84   void *p = big_alloc(len);
85   bzero(p, big_round(len));
86   return p;
87 }
88
89 void
90 big_free(void *start, u64 len)
91 {
92   byte *p = start;
93   u64 l = big_round(len);
94 #ifdef CONFIG_UCW_DEBUG
95   p -= CPU_PAGE_SIZE;
96   mprotect(p, CPU_PAGE_SIZE, PROT_READ);
97   ASSERT(*(u64*)p == len);
98   l += 2*CPU_PAGE_SIZE;
99 #endif
100   page_free(p, l);
101 }
102
103 #ifdef TEST
104
105 int main(void)
106 {
107   byte *p = big_alloc(123456);
108   // p[-1] = 1;
109   big_free(p, 123456);
110   return 0;
111 }
112
113 #endif