105 return (old_brk);
106 }
107
108 /*
109 * _sbrk_grow_aligned() aligns the old break to a low_align boundry,
110 * adds min_size, aligns to a high_align boundry, and calls _brk_unlocked()
111 * to set the new break. The low_aligned-aligned value is returned, and
112 * the actual space allocated is returned through actual_size.
113 *
114 * Unlike sbrk(2), _sbrk_grow_aligned takes an unsigned size, and does
115 * not allow shrinking the heap.
116 */
117 void *
118 _sbrk_grow_aligned(size_t min_size, size_t low_align, size_t high_align,
119 size_t *actual_size)
120 {
121 uintptr_t old_brk;
122 uintptr_t ret_brk;
123 uintptr_t high_brk;
124 uintptr_t new_brk;
125 int brk_result;
126
127 if (!primary_link_map) {
128 errno = ENOTSUP;
129 return ((void *)-1);
130 }
131 if ((low_align & (low_align - 1)) != 0 ||
132 (high_align & (high_align - 1)) != 0) {
133 errno = EINVAL;
134 return ((void *)-1);
135 }
136 low_align = MAX(low_align, ALIGNSZ);
137 high_align = MAX(high_align, ALIGNSZ);
138
139 lmutex_lock(&__sbrk_lock);
140
141 if (_nd == NULL) {
142 _nd = (void *)_brk_unlocked(0);
143 }
144
145 old_brk = (uintptr_t)BRKALIGN(_nd);
146 ret_brk = P2ROUNDUP(old_brk, low_align);
147 high_brk = ret_brk + min_size;
148 new_brk = P2ROUNDUP(high_brk, high_align);
149
150 /*
151 * Check for overflow
152 */
153 if (ret_brk < old_brk || high_brk < ret_brk || new_brk < high_brk) {
154 lmutex_unlock(&__sbrk_lock);
155 errno = ENOMEM;
156 return ((void *)-1);
157 }
158
159 if ((brk_result = (int)_brk_unlocked((void *)new_brk)) == 0)
160 _nd = (void *)new_brk;
161 lmutex_unlock(&__sbrk_lock);
162
163 if (brk_result != 0)
164 return ((void *)-1);
165
166 if (actual_size != NULL)
167 *actual_size = (new_brk - ret_brk);
168 return ((void *)ret_brk);
169 }
170
171 int
172 brk(void *new_brk)
173 {
174 int result;
175
176 /*
177 * brk(2) will return the current brk if given an argument of 0, so we
178 * need to fail it here
179 */
180 if (new_brk == 0) {
181 errno = ENOMEM;
182 return (-1);
183 }
184
185 if (!primary_link_map) {
186 errno = ENOTSUP;
187 return (-1);
188 }
189 /*
190 * Need to align this here; _brk_unlocked won't do it for us.
191 */
192 new_brk = BRKALIGN(new_brk);
193
194 lmutex_lock(&__sbrk_lock);
195 if ((result = (int)_brk_unlocked(new_brk)) == 0)
196 _nd = new_brk;
197 lmutex_unlock(&__sbrk_lock);
198
199 return (result);
200 }
|
105 return (old_brk);
106 }
107
108 /*
109 * _sbrk_grow_aligned() aligns the old break to a low_align boundry,
110 * adds min_size, aligns to a high_align boundry, and calls _brk_unlocked()
111 * to set the new break. The low_aligned-aligned value is returned, and
112 * the actual space allocated is returned through actual_size.
113 *
114 * Unlike sbrk(2), _sbrk_grow_aligned takes an unsigned size, and does
115 * not allow shrinking the heap.
116 */
117 void *
118 _sbrk_grow_aligned(size_t min_size, size_t low_align, size_t high_align,
119 size_t *actual_size)
120 {
121 uintptr_t old_brk;
122 uintptr_t ret_brk;
123 uintptr_t high_brk;
124 uintptr_t new_brk;
125 intptr_t brk_result;
126
127 if (!primary_link_map) {
128 errno = ENOTSUP;
129 return ((void *)-1);
130 }
131 if ((low_align & (low_align - 1)) != 0 ||
132 (high_align & (high_align - 1)) != 0) {
133 errno = EINVAL;
134 return ((void *)-1);
135 }
136 low_align = MAX(low_align, ALIGNSZ);
137 high_align = MAX(high_align, ALIGNSZ);
138
139 lmutex_lock(&__sbrk_lock);
140
141 if (_nd == NULL)
142 _nd = (void *)_brk_unlocked(0);
143
144 old_brk = (uintptr_t)BRKALIGN(_nd);
145 ret_brk = P2ROUNDUP(old_brk, low_align);
146 high_brk = ret_brk + min_size;
147 new_brk = P2ROUNDUP(high_brk, high_align);
148
149 /*
150 * Check for overflow
151 */
152 if (ret_brk < old_brk || high_brk < ret_brk || new_brk < high_brk) {
153 lmutex_unlock(&__sbrk_lock);
154 errno = ENOMEM;
155 return ((void *)-1);
156 }
157
158 if ((brk_result = _brk_unlocked((void *)new_brk)) == 0)
159 _nd = (void *)new_brk;
160 lmutex_unlock(&__sbrk_lock);
161
162 if (brk_result != 0)
163 return ((void *)-1);
164
165 if (actual_size != NULL)
166 *actual_size = (new_brk - ret_brk);
167 return ((void *)ret_brk);
168 }
169
170 int
171 brk(void *new_brk)
172 {
173 intptr_t result;
174
175 /*
176 * brk(2) will return the current brk if given an argument of 0, so we
177 * need to fail it here
178 */
179 if (new_brk == 0) {
180 errno = ENOMEM;
181 return (-1);
182 }
183
184 if (!primary_link_map) {
185 errno = ENOTSUP;
186 return (-1);
187 }
188 /*
189 * Need to align this here; _brk_unlocked won't do it for us.
190 */
191 new_brk = BRKALIGN(new_brk);
192
193 lmutex_lock(&__sbrk_lock);
194 if ((result = _brk_unlocked(new_brk)) == 0)
195 _nd = new_brk;
196 lmutex_unlock(&__sbrk_lock);
197
198 return (result);
199 }
|