Moved brk/sbrk into user-space
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.11.1-ros / sysdeps / ros / sbrk.c
1 /* Copyright (C) 1991,1995-1997,2000,2002,2009 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <errno.h>
20 #include <stdint.h>
21 #include <unistd.h>
22 #include <bits/libc-lock.h>
23 #include <ros/memlayout.h>
24 #include <ros/procinfo.h>
25 #include <sys/mman.h>
26
27 __libc_lock_define(static,brk_lock);
28 static uintptr_t curbrk = 0;
29
30 static uintptr_t
31 __internal_getbrk (void)
32 {
33   if(curbrk == 0)
34     curbrk = (uintptr_t)__procinfo.heap_bottom;
35   return curbrk;
36 }
37
38 static int
39 __internal_setbrk (uintptr_t addr)
40 {
41   uintptr_t real_new_brk = (addr + PGSIZE - 1)/PGSIZE*PGSIZE;
42   uintptr_t real_brk = (__internal_getbrk() + PGSIZE - 1)/PGSIZE*PGSIZE;
43
44   if(real_new_brk > real_brk)
45   {
46     if(real_new_brk > BRK_END)
47       return -1;
48
49     return mmap((void*)real_brk, real_new_brk-real_brk,
50                 PROT_READ | PROT_WRITE | PROT_EXEC,
51                 MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)real_brk ? 0 : -1;
52   }
53   else if(real_new_brk < real_brk)
54   {
55     if(real_new_brk < (uintptr_t)__procinfo.heap_bottom)
56       return -1;
57
58     return munmap((void*)real_new_brk, real_brk - real_new_brk);
59   }
60
61   curbrk = addr;
62   return 0;
63 }
64
65 /* Set the end of the process's data space to ADDR.
66    Return 0 if successful, -1 if not.   */
67 int
68 __brk (void* addr)
69 {
70   if(addr == 0)
71     return 0;
72
73   __libc_lock_lock(brk_lock);
74   int ret = __internal_setbrk((uintptr_t)addr);
75   __libc_lock_unlock(brk_lock);
76
77   return ret;
78 }
79 weak_alias (__brk, brk)
80
81 /* Extend the process's data space by INCREMENT.
82    If INCREMENT is negative, shrink data space by - INCREMENT.
83    Return start of new space allocated, or -1 for errors.  */
84 void *
85 __sbrk (intptr_t increment)
86 {
87   __libc_lock_lock(brk_lock);
88
89   uintptr_t oldbrk = __internal_getbrk();
90   if ((increment > 0
91        ? (oldbrk + (uintptr_t) increment < oldbrk)
92        : (oldbrk < (uintptr_t) -increment))
93       || __internal_setbrk (oldbrk + increment) < 0)
94     oldbrk = -1;
95
96   __libc_lock_unlock(brk_lock);
97
98   return (void*)oldbrk;
99 }
100 libc_hidden_def (__sbrk)
101 weak_alias (__sbrk, sbrk)