Use weak __thread declarations in parlib-compat (XCC)
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.19-akaros / 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/procdata.h>
26 #include <sys/mman.h>
27
28 static uintptr_t curbrk = BRK_START;
29 __libc_lock_define_initialized(static, __brk_lock);
30
31 static bool is_early_scp(void)
32 {
33         struct preempt_data *vcpd = &__procdata.vcore_preempt_data[0];
34
35         return (uintptr_t)vcpd->flags & VC_SCP_NOVCCTX;
36 }
37
38 /* Early SCP context doesn't need the locks, since we're single threaded, and we
39  * can't grab the PDR locks in some cases.  Specifically, we might not have a
40  * TLS for thread 0 yet, so we can't do things like check in_vcore_context(). */
41 static void brk_lock(void)
42 {
43         if (is_early_scp())
44                 return;
45         __libc_lock_lock(__brk_lock);
46 }
47
48 static void brk_unlock(void)
49 {
50         if (is_early_scp())
51                 return;
52         __libc_lock_unlock(__brk_lock);
53 }
54
55 static uintptr_t
56 __internal_getbrk (void)
57 {
58   return curbrk;
59 }
60
61 static int
62 __internal_setbrk (uintptr_t addr)
63 {
64   uintptr_t real_new_brk = (addr + PGSIZE - 1)/PGSIZE*PGSIZE;
65   uintptr_t real_brk = (__internal_getbrk() + PGSIZE - 1)/PGSIZE*PGSIZE;
66
67   if(real_new_brk > real_brk)
68   {
69     if(real_new_brk > BRK_END)
70       return -1;
71         // calling mmap directly to avoid referencing errno before it is initialized.
72     if ((void*)__ros_syscall_noerrno(SYS_mmap, (void*)real_brk,
73                                          real_new_brk-real_brk,
74                                          PROT_READ | PROT_WRITE | PROT_EXEC,
75                                          MAP_FIXED | MAP_ANONYMOUS,
76                                          -1, 0) != (void*)real_brk)
77       return -1;
78   }
79   else if(real_new_brk < real_brk)
80   {
81     if (real_new_brk < BRK_START)
82       return -1;
83
84     if (munmap((void*)real_new_brk, real_brk - real_new_brk))
85       return -1;
86   }
87
88   curbrk = addr;
89   return 0;
90 }
91
92 /* Set the end of the process's data space to ADDR.
93    Return 0 if successful, -1 if not.   */
94 int
95 __brk (void* addr)
96 {
97   if(addr == 0)
98     return 0;
99
100   brk_lock();
101   int ret = __internal_setbrk((uintptr_t)addr);
102   brk_unlock();
103
104   return ret;
105 }
106 weak_alias (__brk, brk)
107
108 /* Extend the process's data space by INCREMENT.
109    If INCREMENT is negative, shrink data space by - INCREMENT.
110    Return start of new space allocated, or -1 for errors.  */
111 void *
112 __sbrk (intptr_t increment)
113 {
114   brk_lock();
115
116   uintptr_t oldbrk = __internal_getbrk();
117   if ((increment > 0
118        ? (oldbrk + (uintptr_t) increment < oldbrk)
119        : (oldbrk < (uintptr_t) -increment))
120       || __internal_setbrk (oldbrk + increment) < 0)
121     oldbrk = -1;
122
123   brk_unlock();
124
125   return (void*)oldbrk;
126 }
127 libc_hidden_def (__sbrk)
128 weak_alias (__sbrk, sbrk)