]> mj.ucw.cz Git - libucw.git/blobdiff - lib/bigalloc.c
Added the local copy of the regex library back.
[libucw.git] / lib / bigalloc.c
index 32d546430ea4aaa0c2cd07261601a19f470f90ac..9581188cc046f8171241ef5bfde20e64a44e5a0c 100644 (file)
@@ -2,6 +2,7 @@
  *     UCW Library -- Allocation of Large Aligned Buffers
  *
  *     (c) 2006--2007 Martin Mares <mj@ucw.cz>
+ *     (c) 2007 Pavel Charvat <char@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
 #include "lib/lib.h"
 
 #include <sys/mman.h>
+#include <string.h>
+#include <limits.h>
+
+void *
+page_alloc(u64 len)
+{
+  if (len > SIZE_MAX)
+    die("page_alloc: Size %llu is too large for the current architecture", (long long) len);
+  ASSERT(!(len & (CPU_PAGE_SIZE-1)));
+  byte *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+  if (p == (byte*) MAP_FAILED)
+    die("Cannot mmap %llu bytes of memory: %m", (long long)len);
+  return p;
+}
+
+void *
+page_alloc_zero(u64 len)
+{
+  void *p = page_alloc(len);
+  bzero(p, len);
+  return p;
+}
+
+void
+page_free(void *start, u64 len)
+{
+  ASSERT(!(len & (CPU_PAGE_SIZE-1)));
+  ASSERT(!((uintptr_t) start & (CPU_PAGE_SIZE-1)));
+  munmap(start, len);
+}
+
+void *
+page_realloc(void *start, u64 old_len, u64 new_len)
+{
+  void *p = page_alloc(new_len);
+  memcpy(p, start, MIN(old_len, new_len));
+  page_free(start, old_len);
+  return p;
+}
 
 static u64
 big_round(u64 len)
@@ -20,36 +60,42 @@ big_round(u64 len)
 void *
 big_alloc(u64 len)
 {
-  len = big_round(len);
-#ifndef CPU_64BIT_POINTERS
-  if (len > 0xff000000)
-    die("big_alloc: Size %ju is too large for a 32-bit machine", (uintmax_t) len);
-#endif
+  u64 l = big_round(len);
+  if (l > SIZE_MAX - 2*CPU_PAGE_SIZE)
+    die("big_alloc: Size %llu is too large for the current architecture", (long long) len);
 #ifdef CONFIG_DEBUG
-  len += 2*CPU_PAGE_SIZE;
+  l += 2*CPU_PAGE_SIZE;
 #endif
-  byte *p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-  if (p == (byte*) MAP_FAILED)
-    die("Cannot mmap %ju bytes of memory: %m", (uintmax_t) len);
+  byte *p = page_alloc(l);
 #ifdef CONFIG_DEBUG
+  *(u64*)p = len;
   mprotect(p, CPU_PAGE_SIZE, PROT_NONE);
-  mprotect(p+len-CPU_PAGE_SIZE, CPU_PAGE_SIZE, PROT_NONE);
+  mprotect(p+l-CPU_PAGE_SIZE, CPU_PAGE_SIZE, PROT_NONE);
   p += CPU_PAGE_SIZE;
 #endif
   return p;
 }
 
+void *
+big_alloc_zero(u64 len)
+{
+  void *p = big_alloc(len);
+  bzero(p, big_round(len));
+  return p;
+}
+
 void
 big_free(void *start, u64 len)
 {
   byte *p = start;
-  ASSERT(!((uintptr_t) p & (CPU_PAGE_SIZE-1)));
-  len = big_round(len);
+  u64 l = big_round(len);
 #ifdef CONFIG_DEBUG
   p -= CPU_PAGE_SIZE;
-  len += 2*CPU_PAGE_SIZE;
+  mprotect(p, CPU_PAGE_SIZE, PROT_READ);
+  ASSERT(*(u64*)p == len);
+  l += 2*CPU_PAGE_SIZE;
 #endif
-  munmap(p, len);
+  page_free(p, l);
 }
 
 #ifdef TEST