Moved brk/sbrk into user-space
authorAndrew Waterman <waterman@ros-dev.(none)>
Mon, 5 Apr 2010 01:49:25 +0000 (18:49 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:39 +0000 (17:35 -0700)
glibc now does it with mmap.  BRK_END is used
to demarcate between the maximum break size
and where non-MAP_FIXED mmap starts allocating,
so the heap and mmap'd memory won't collide.

sys_brk still exists for compatibility with newlib;
someone might want to delete this in the future.

Recompile the cross-compiler, as procinfo changed.

kern/arch/i686/pmap.c
kern/arch/sparc/pmap.c
kern/include/env.h
kern/include/ros/memlayout.h
kern/include/ros/procinfo.h
kern/src/elf.c
kern/src/env.c
kern/src/process.c
kern/src/syscall.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/brk.c
tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/sbrk.c [new file with mode: 0644]

index 495a267..89eaded 100644 (file)
@@ -632,7 +632,7 @@ int get_va_perms(pde_t *pgdir, const void *SNT va)
 
 void *get_free_va_range(pde_t *pgdir, uintptr_t addr, size_t len)
 {
-       addr = ROUNDUP(MAX(addr,UMMAP_START),PGSIZE);
+       addr = ROUNDUP(MAX(addr,BRK_END),PGSIZE);
        len = ROUNDUP(len,PGSIZE);
 
        for(char* a = (char*)addr; a < (char*)USTACKBOT; a += PGSIZE)
index 4121a8d..2e65987 100644 (file)
@@ -123,7 +123,7 @@ int get_va_perms(pde_t *pgdir, const void *SNT va)
 
 void *get_free_va_range(pde_t *pgdir, uintptr_t addr, size_t len)
 {
-       addr = ROUNDUP(MAX(addr,UMMAP_START),PGSIZE);
+       addr = ROUNDUP(MAX(addr,BRK_END),PGSIZE);
        len = ROUNDUP(len,PGSIZE);
 
        for(char* a = (char*)addr; a < (char*)USTACKBOT; a += PGSIZE)
index 68124b2..4099a4b 100644 (file)
@@ -49,7 +49,6 @@ struct Env {
 
        /* Keeps track of this process's current memory allocation 
      * (i.e. its heap pointer) */
-       void* heap_bottom;
        void* heap_top;
 
        // Address space
index d5b4953..9738594 100644 (file)
 // Maximum bottom of normal user stack
 #define USTACKBOT      (USTACKTOP - (USTACK_NUM_PAGES+1)*PGSIZE)
 
-#define UMMAP_NUM_PAGES        131072
-#define UMMAP_START    (USTACKBOT - UMMAP_NUM_PAGES*PGSIZE)
+// Arbitrary boundary between the break and the start of
+// memory returned by calls to mmap with addr = 0
+#define BRK_END 0x20000000
 
 // Where user programs generally begin
 #define UTEXT          (2*PTSIZE)
index 7978f1e..9aaee0b 100644 (file)
@@ -14,6 +14,7 @@ typedef struct procinfo {
        pid_t ppid;
        size_t max_harts;
        uint64_t tsc_freq;
+       void* heap_bottom;
 
        char* argp[PROCINFO_MAX_ARGP];
        char argbuf[PROCINFO_ARGBUF_SIZE];
index 6171a2c..40d4270 100644 (file)
@@ -141,8 +141,8 @@ int load_elf(struct proc* p, struct file* f)
 
        // Set the heap bottom and top to just past where the text 
        // region has been loaded
-       p->heap_bottom = (void*)ei.highest_addr;
-       p->heap_top = p->heap_bottom;
+       p->heap_top = (void*)ei.highest_addr;
+       p->env_procinfo->heap_bottom = p->heap_top;
 
        return 0;
 }
index d674c73..81f0d81 100644 (file)
@@ -253,8 +253,8 @@ void env_load_icode(env_t* e, env_t* binary_env, uint8_t* binary, size_t size)
 {
        /* Load the binary and set the current locations of the elf segments.
         * All end-of-segment pointers are page aligned (invariant) */
-       e->heap_bottom = load_icode(e, binary_env, binary, size);
-       e->heap_top = e->heap_bottom;
+       e->heap_top = load_icode(e, binary_env, binary, size);
+       e->env_procinfo->heap_bottom = e->heap_top;
 }
 
 #define PER_CPU_THING(type,name)\
index c085e2b..c278608 100644 (file)
@@ -251,7 +251,7 @@ static error_t proc_alloc(struct proc *SAFE*SAFE pp, pid_t parent_id)
        p->env_flags = 0;
        p->env_entry = 0; // cheating.  this really gets set in load_icode
        p->num_vcores = 0;
-       p->heap_bottom = (void*)UTEXT;
+       p->env_procinfo->heap_bottom = (void*)UTEXT;
        p->heap_top = (void*)UTEXT;
        memset(&p->vcoremap, -1, sizeof(p->vcoremap));
        memset(&p->resources, 0, sizeof(p->resources));
index 86919a1..aedfb81 100644 (file)
@@ -314,7 +314,6 @@ static ssize_t sys_fork(env_t* e)
        env_t* env = proc_create(NULL,0);
        assert(env != NULL);
 
-       env->heap_bottom = e->heap_bottom;
        env->heap_top = e->heap_top;
        env->ppid = e->pid;
        env->env_tf = *current_tf;
@@ -490,7 +489,7 @@ static void* sys_brk(struct proc *p, void* addr) {
 
        spin_lock_irqsave(&p->proc_lock);
 
-       if((addr < p->heap_bottom) || (addr >= (void*)USTACKBOT))
+       if((addr < p->env_procinfo->heap_bottom) || (addr >= (void*)BRK_END))
                goto out;
 
        uintptr_t real_heap_top = ROUNDUP((uintptr_t)p->heap_top,PGSIZE);
index 0d69ea8..dd99d69 100644 (file)
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <errno.h>
-#include <unistd.h>
-#include <bits/libc-lock.h>
-#include <ros/syscall.h>
+/* definition of __brk lives in sbrk.c */
 
-/* sbrk.c expects this.  */
-void *__curbrk;
-
-/* Set the end of the process's data space to ADDR.
-   Return 0 if successful, -1 if not.   */
-int
-__brk (void* addr)
-{
-  __libc_lock_define(static,sbrk_lock);
-  __libc_lock_lock(sbrk_lock);
-
-  int ret = 0;
-  __curbrk = (void*)ros_syscall(SYS_brk,addr,0,0,0,0);
-  if(addr != 0 && __curbrk != addr)
-    ret = -1;
-
-  __libc_lock_unlock(sbrk_lock);
-
-  return ret;
-}
-weak_alias (__brk, brk)
diff --git a/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/sbrk.c b/tools/compilers/gcc-glibc/glibc-2.11.1-ros/sysdeps/ros/sbrk.c
new file mode 100644 (file)
index 0000000..8eeb40e
--- /dev/null
@@ -0,0 +1,101 @@
+/* Copyright (C) 1991,1995-1997,2000,2002,2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <bits/libc-lock.h>
+#include <ros/memlayout.h>
+#include <ros/procinfo.h>
+#include <sys/mman.h>
+
+__libc_lock_define(static,brk_lock);
+static uintptr_t curbrk = 0;
+
+static uintptr_t
+__internal_getbrk (void)
+{
+  if(curbrk == 0)
+    curbrk = (uintptr_t)__procinfo.heap_bottom;
+  return curbrk;
+}
+
+static int
+__internal_setbrk (uintptr_t addr)
+{
+  uintptr_t real_new_brk = (addr + PGSIZE - 1)/PGSIZE*PGSIZE;
+  uintptr_t real_brk = (__internal_getbrk() + PGSIZE - 1)/PGSIZE*PGSIZE;
+
+  if(real_new_brk > real_brk)
+  {
+    if(real_new_brk > BRK_END)
+      return -1;
+
+    return mmap((void*)real_brk, real_new_brk-real_brk,
+                PROT_READ | PROT_WRITE | PROT_EXEC,
+                MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)real_brk ? 0 : -1;
+  }
+  else if(real_new_brk < real_brk)
+  {
+    if(real_new_brk < (uintptr_t)__procinfo.heap_bottom)
+      return -1;
+
+    return munmap((void*)real_new_brk, real_brk - real_new_brk);
+  }
+
+  curbrk = addr;
+  return 0;
+}
+
+/* Set the end of the process's data space to ADDR.
+   Return 0 if successful, -1 if not.   */
+int
+__brk (void* addr)
+{
+  if(addr == 0)
+    return 0;
+
+  __libc_lock_lock(brk_lock);
+  int ret = __internal_setbrk((uintptr_t)addr);
+  __libc_lock_unlock(brk_lock);
+
+  return ret;
+}
+weak_alias (__brk, brk)
+
+/* Extend the process's data space by INCREMENT.
+   If INCREMENT is negative, shrink data space by - INCREMENT.
+   Return start of new space allocated, or -1 for errors.  */
+void *
+__sbrk (intptr_t increment)
+{
+  __libc_lock_lock(brk_lock);
+
+  uintptr_t oldbrk = __internal_getbrk();
+  if ((increment > 0
+       ? (oldbrk + (uintptr_t) increment < oldbrk)
+       : (oldbrk < (uintptr_t) -increment))
+      || __internal_setbrk (oldbrk + increment) < 0)
+    oldbrk = -1;
+
+  __libc_lock_unlock(brk_lock);
+
+  return (void*)oldbrk;
+}
+libc_hidden_def (__sbrk)
+weak_alias (__sbrk, sbrk)