Upgrade to gcc-4.9.2
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.14.1-ros / sysdeps / akaros / 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/syscall.h>
24 #include <ros/memlayout.h>
25 #include <ros/procinfo.h>
26 #include <sys/mman.h>
27
28 __libc_lock_define(static,brk_lock);
29 static uintptr_t curbrk = 0;
30
31 static uintptr_t
32 __internal_getbrk (void)
33 {
34   if(curbrk == 0)
35     curbrk = (uintptr_t)__procinfo.heap_bottom;
36   return curbrk;
37 }
38
39 static int
40 __internal_setbrk (uintptr_t addr)
41 {
42   uintptr_t real_new_brk = (addr + PGSIZE - 1)/PGSIZE*PGSIZE;
43   uintptr_t real_brk = (__internal_getbrk() + PGSIZE - 1)/PGSIZE*PGSIZE;
44
45   if(real_new_brk > real_brk)
46   {
47     if(real_new_brk > BRK_END)
48       return -1;
49         // calling mmap directly to avoid referencing errno before it is initialized.
50     if ((void*)__ros_syscall_noerrno(SYS_mmap, (void*)real_brk,
51                                          real_new_brk-real_brk,
52                                          PROT_READ | PROT_WRITE | PROT_EXEC,
53                                          MAP_FIXED | MAP_ANONYMOUS,
54                                          -1, 0) != (void*)real_brk)
55       return -1;
56   }
57   else if(real_new_brk < real_brk)
58   {
59     if(real_new_brk < (uintptr_t)__procinfo.heap_bottom)
60       return -1;
61
62     if (munmap((void*)real_new_brk, real_brk - real_new_brk))
63       return -1;
64   }
65
66   curbrk = addr;
67   return 0;
68 }
69
70 /* Set the end of the process's data space to ADDR.
71    Return 0 if successful, -1 if not.   */
72 int
73 __brk (void* addr)
74 {
75   if(addr == 0)
76     return 0;
77
78   __libc_lock_lock(brk_lock);
79   int ret = __internal_setbrk((uintptr_t)addr);
80   __libc_lock_unlock(brk_lock);
81
82   return ret;
83 }
84 weak_alias (__brk, brk)
85
86 /* Extend the process's data space by INCREMENT.
87    If INCREMENT is negative, shrink data space by - INCREMENT.
88    Return start of new space allocated, or -1 for errors.  */
89 void *
90 __sbrk (intptr_t increment)
91 {
92   __libc_lock_lock(brk_lock);
93
94   uintptr_t oldbrk = __internal_getbrk();
95   if ((increment > 0
96        ? (oldbrk + (uintptr_t) increment < oldbrk)
97        : (oldbrk < (uintptr_t) -increment))
98       || __internal_setbrk (oldbrk + increment) < 0)
99     oldbrk = -1;
100
101   __libc_lock_unlock(brk_lock);
102
103   return (void*)oldbrk;
104 }
105 libc_hidden_def (__sbrk)
106 weak_alias (__sbrk, sbrk)