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