Uses kref in the FS, fixes up refcount bugs
[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     if (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)
52       return -1;
53   }
54   else if(real_new_brk < real_brk)
55   {
56     if(real_new_brk < (uintptr_t)__procinfo.heap_bottom)
57       return -1;
58
59     if (munmap((void*)real_new_brk, real_brk - real_new_brk))
60       return -1;
61   }
62
63   curbrk = addr;
64   return 0;
65 }
66
67 /* Set the end of the process's data space to ADDR.
68    Return 0 if successful, -1 if not.   */
69 int
70 __brk (void* addr)
71 {
72   if(addr == 0)
73     return 0;
74
75   __libc_lock_lock(brk_lock);
76   int ret = __internal_setbrk((uintptr_t)addr);
77   __libc_lock_unlock(brk_lock);
78
79   return ret;
80 }
81 weak_alias (__brk, brk)
82
83 /* Extend the process's data space by INCREMENT.
84    If INCREMENT is negative, shrink data space by - INCREMENT.
85    Return start of new space allocated, or -1 for errors.  */
86 void *
87 __sbrk (intptr_t increment)
88 {
89   __libc_lock_lock(brk_lock);
90
91   uintptr_t oldbrk = __internal_getbrk();
92   if ((increment > 0
93        ? (oldbrk + (uintptr_t) increment < oldbrk)
94        : (oldbrk < (uintptr_t) -increment))
95       || __internal_setbrk (oldbrk + increment) < 0)
96     oldbrk = -1;
97
98   __libc_lock_unlock(brk_lock);
99
100   return (void*)oldbrk;
101 }
102 libc_hidden_def (__sbrk)
103 weak_alias (__sbrk, sbrk)