]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/mach/hurd/brk.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / mach / hurd / brk.c
CommitLineData
04277e02 1/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
ebbad4cc 2 This file is part of the GNU C Library.
28f540f4 3
ebbad4cc 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
28f540f4 8
ebbad4cc
UD
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
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
28f540f4 17
28f540f4
RM
18#include <errno.h>
19#include <hurd.h>
20#include <hurd/resource.h>
21#include <cthreads.h> /* For `struct mutex'. */
22
23
683158e0
RM
24/* Initial maximum size of the data segment (this is arbitrary). */
25#define DATA_SIZE (128 * 1024 * 1024)
28f540f4 26
28f540f4
RM
27/* Up to the page including this address is allocated from the kernel.
28 This address is the data resource limit. */
29vm_address_t _hurd_data_end;
30
31/* Up to this address is actually available to the user.
32 Pages beyond the one containing this address allow no access. */
51ec5cb2 33vm_address_t _hurd_brk = 0;
28f540f4 34
2cc7dc4d
RM
35/* This name is used by the Linux crtbeginS.o for reasons you don't even
36 want to think about it. It's just easier to provide some definition for
37 it than even to explain the braindamage involved. */
51ec5cb2 38weak_alias (_hurd_brk, ___brk_addr)
2cc7dc4d 39
28f540f4
RM
40struct mutex _hurd_brk_lock;
41
42extern int __data_start, _end;
c6496762
RM
43weak_extern (__data_start)
44static vm_address_t static_data_start;
28f540f4
RM
45
46
47/* Set the end of the process's data space to INADDR.
48 Return 0 if successful, -1 if not. */
49int
ebbad4cc 50__brk (void *inaddr)
28f540f4
RM
51{
52 int ret;
53 HURD_CRITICAL_BEGIN;
54 __mutex_lock (&_hurd_brk_lock);
55 ret = _hurd_set_brk ((vm_address_t) inaddr);
56 __mutex_unlock (&_hurd_brk_lock);
57 HURD_CRITICAL_END;
58 return ret;
59}
60weak_alias (__brk, brk)
61
62
63int
64_hurd_set_brk (vm_address_t addr)
65{
1043890b 66 error_t err = 0;
28f540f4
RM
67 vm_address_t pagend = round_page (addr);
68 vm_address_t pagebrk = round_page (_hurd_brk);
69 long int rlimit;
70
71 if (pagend <= pagebrk)
72 {
73 if (pagend < pagebrk)
55ffcab7
RM
74 {
75 /* XXX wish this were atomic... */
76 /* First deallocate the memory to release its backing space. */
77 __vm_deallocate (__mach_task_self (), pagend, pagebrk - pagend);
78 /* Now reallocate it with no access allowed. */
79 err = __vm_map (__mach_task_self (),
6abc15e9 80 &pagend, pagebrk - pagend,
55ffcab7
RM
81 0, 0, MACH_PORT_NULL, 0, 0,
82 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
83 VM_INHERIT_COPY);
84 /* XXX what if error? */
85 }
28f540f4
RM
86 _hurd_brk = addr;
87 return 0;
88 }
89
90 __mutex_lock (&_hurd_rlimit_lock);
91 rlimit = _hurd_rlimits[RLIMIT_DATA].rlim_cur;
92 __mutex_unlock (&_hurd_rlimit_lock);
93
c6496762 94 if (addr - static_data_start > rlimit)
28f540f4
RM
95 {
96 /* Need to increase the resource limit. */
97 errno = ENOMEM;
98 return -1;
99 }
100
683158e0 101 if (pagend > _hurd_data_end)
28f540f4 102 {
1043890b
ST
103 vm_address_t alloc_start = _hurd_data_end;
104
683158e0 105 /* We didn't allocate enough space! Hopefully we can get some more! */
1043890b
ST
106
107 if (_hurd_data_end > pagebrk)
108 /* First finish allocation. */
109 err = __vm_protect (__mach_task_self (), pagebrk,
110 alloc_start - pagebrk, 0,
111 VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
112 if (! err)
113 _hurd_brk = alloc_start;
114
115 if (! err)
116 err = __vm_allocate (__mach_task_self (), &alloc_start,
117 pagend - alloc_start, 0);
118
683158e0
RM
119 if (! err)
120 _hurd_data_end = pagend;
28f540f4 121 }
683158e0
RM
122 else
123 /* Make the memory accessible. */
124 err = __vm_protect (__mach_task_self (), pagebrk, pagend - pagebrk,
125 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
126
127 if (err)
128 return __hurd_fail (err);
28f540f4
RM
129
130 _hurd_brk = addr;
131 return 0;
132}
133
134static void
135init_brk (void)
136{
137 vm_address_t pagend;
138
139 __mutex_init (&_hurd_brk_lock);
140
c6496762
RM
141 static_data_start = (vm_address_t) (&__data_start ?: &_end);
142
28f540f4
RM
143 /* If _hurd_brk is already set, don't change it. The assumption is that
144 it was set in a previous run before something like Emacs's unexec was
145 called and dumped all the data up to the break at that point. */
146 if (_hurd_brk == 0)
147 _hurd_brk = (vm_address_t) &_end;
148
149 pagend = round_page (_hurd_brk);
150
c6496762 151 _hurd_data_end = round_page (static_data_start + DATA_SIZE);
28f540f4
RM
152
153 if (pagend < _hurd_data_end)
154 {
155 /* We use vm_map to allocate and change permissions atomically. */
156 if (__vm_map (__mach_task_self (), &pagend, _hurd_data_end - pagend,
157 0, 0, MACH_PORT_NULL, 0, 0,
158 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
159 VM_INHERIT_COPY))
160 /* Couldn't allocate the memory. The break will be very short. */
161 _hurd_data_end = pagend;
162 }
163
164 (void) &init_brk; /* Avoid ``defined but not used'' warning. */
165}
166text_set_element (_hurd_preinit_hook, init_brk);