21
21
#include "libc/calls/blockcancel.internal.h"
22
22
#include "libc/calls/calls.h"
23
23
#include "libc/calls/internal.h"
24
+ #include "libc/calls/state.internal.h"
24
25
#include "libc/calls/struct/sigset.internal.h"
25
26
#include "libc/calls/syscall-sysv.internal.h"
26
27
#include "libc/dce.h"
@@ -187,10 +188,10 @@ int __munmap(char *addr, size_t size, bool untrack_only) {
187
188
!size || (uintptr_t )addr + size < size )
188
189
return einval ();
189
190
190
- // untrack and delete mapping
191
+ // untrack mappings
191
192
int rc = 0 ;
193
+ struct Dll * delete = 0 ;
192
194
__maps_lock ();
193
- StartOver :;
194
195
struct Map * map = __maps .maps ;
195
196
struct Map * * prev = & __maps .maps ;
196
197
while (map ) {
@@ -202,30 +203,10 @@ StartOver:;
202
203
if (addr <= map_addr && addr + PGUP (size ) >= map_addr + PGUP (map_size )) {
203
204
// remove mapping completely
204
205
dll_remove (& __maps .used , & map -> elem );
206
+ dll_make_first (& delete , & map -> elem );
205
207
* prev = next ;
206
208
__maps .pages -= (map_size + pagesz - 1 ) / pagesz ;
207
209
__maps .count -= 1 ;
208
- if (untrack_only ) {
209
- __maps_free (map );
210
- __maps_check ();
211
- } else {
212
- __maps_unlock ();
213
- if (!IsWindows ()) {
214
- ASSERT (addr <= map_addr );
215
- ASSERT (map_addr + PGUP (map_size ) <= addr + PGUP (size ));
216
- if (sys_munmap (map_addr , map_size ))
217
- rc = -1 ;
218
- } else {
219
- if (!UnmapViewOfFile (map_addr ))
220
- rc = -1 ;
221
- if (!CloseHandle (map -> h ))
222
- rc = -1 ;
223
- }
224
- __maps_lock ();
225
- __maps_free (map );
226
- __maps_check ();
227
- goto StartOver ;
228
- }
229
210
map = next ;
230
211
continue ;
231
212
} else if (IsWindows ()) {
@@ -240,35 +221,34 @@ StartOver:;
240
221
size_t right = map_size - left ;
241
222
ASSERT (right > 0 );
242
223
ASSERT (left > 0 );
243
- map -> addr += left ;
244
- map -> size = right ;
245
- if (!(map -> flags & MAP_ANONYMOUS ))
246
- map -> off += left ;
247
- __maps .pages -= (left + pagesz - 1 ) / pagesz ;
248
- __maps_check ();
249
- if (!untrack_only ) {
250
- __maps_unlock ();
251
- ASSERT (addr <= map_addr );
252
- ASSERT (map_addr + PGUP (left ) <= addr + PGUP (size ));
253
- if (sys_munmap (map_addr , left ) == -1 )
254
- rc = -1 ;
255
- __maps_lock ();
256
- goto StartOver ;
224
+ struct Map * leftmap ;
225
+ if ((leftmap = __maps_alloc ())) {
226
+ map -> addr += left ;
227
+ map -> size = right ;
228
+ if (!(map -> flags & MAP_ANONYMOUS ))
229
+ map -> off += left ;
230
+ __maps .pages -= (left + pagesz - 1 ) / pagesz ;
231
+ __maps_check ();
232
+ leftmap -> addr = map_addr ;
233
+ leftmap -> size = left ;
234
+ dll_make_first (& delete , & leftmap -> elem );
235
+ } else {
236
+ rc = -1 ;
257
237
}
258
238
} else if (addr + PGUP (size ) >= map_addr + PGUP (map_size )) {
259
239
// shave off righthand side of mapping
260
240
size_t left = addr - map_addr ;
261
241
size_t right = map_addr + map_size - addr ;
262
- map -> size = left ;
263
- __maps . pages -= ( right + pagesz - 1 ) / pagesz ;
264
- __maps_check () ;
265
- if (! untrack_only ) {
266
- __maps_unlock ();
267
- ASSERT ( PGUP ( right ) <= PGUP ( size )) ;
268
- if ( sys_munmap ( addr , right ) == -1 )
269
- rc = -1 ;
270
- __maps_lock ();
271
- goto StartOver ;
242
+ struct Map * rightmap ;
243
+ if (( rightmap = __maps_alloc ())) {
244
+ map -> size = left ;
245
+ __maps . pages -= ( right + pagesz - 1 ) / pagesz ;
246
+ __maps_check ();
247
+ rightmap -> addr = addr ;
248
+ rightmap -> size = right ;
249
+ dll_make_first ( & delete , & rightmap -> elem ) ;
250
+ } else {
251
+ rc = -1 ;
272
252
}
273
253
} else {
274
254
// punch hole in mapping
@@ -277,27 +257,28 @@ StartOver:;
277
257
size_t right = map_size - middle - left ;
278
258
struct Map * leftmap ;
279
259
if ((leftmap = __maps_alloc ())) {
280
- leftmap -> next = map ;
281
- leftmap -> addr = map_addr ;
282
- leftmap -> size = left ;
283
- leftmap -> off = map -> off ;
284
- leftmap -> prot = map -> prot ;
285
- leftmap -> flags = map -> flags ;
286
- map -> addr += left + middle ;
287
- map -> size = right ;
288
- if (!(map -> flags & MAP_ANONYMOUS ))
289
- map -> off += left + middle ;
290
- dll_make_first (& __maps .used , & leftmap -> elem );
291
- * prev = leftmap ;
292
- __maps .pages -= (middle + pagesz - 1 ) / pagesz ;
293
- __maps .count += 1 ;
294
- __maps_check ();
295
- if (!untrack_only ) {
296
- __maps_unlock ();
297
- if (sys_munmap (addr , size ) == -1 )
298
- rc = -1 ;
299
- __maps_lock ();
300
- goto StartOver ;
260
+ struct Map * middlemap ;
261
+ if ((middlemap = __maps_alloc ())) {
262
+ leftmap -> next = map ;
263
+ leftmap -> addr = map_addr ;
264
+ leftmap -> size = left ;
265
+ leftmap -> off = map -> off ;
266
+ leftmap -> prot = map -> prot ;
267
+ leftmap -> flags = map -> flags ;
268
+ map -> addr += left + middle ;
269
+ map -> size = right ;
270
+ if (!(map -> flags & MAP_ANONYMOUS ))
271
+ map -> off += left + middle ;
272
+ dll_make_first (& __maps .used , & leftmap -> elem );
273
+ * prev = leftmap ;
274
+ __maps .pages -= (middle + pagesz - 1 ) / pagesz ;
275
+ __maps .count += 1 ;
276
+ __maps_check ();
277
+ middlemap -> addr = addr ;
278
+ middlemap -> size = size ;
279
+ dll_make_first (& delete , & middlemap -> elem );
280
+ } else {
281
+ rc = -1 ;
301
282
}
302
283
} else {
303
284
rc = -1 ;
@@ -309,6 +290,34 @@ StartOver:;
309
290
}
310
291
__maps_unlock ();
311
292
293
+ // delete mappings
294
+ for (struct Dll * e = dll_first (delete ); e ; e = dll_next (delete , e )) {
295
+ map = MAP_CONTAINER (e );
296
+ if (!untrack_only ) {
297
+ if (!IsWindows ()) {
298
+ if (sys_munmap (map -> addr , map -> size ))
299
+ rc = -1 ;
300
+ } else {
301
+ if (!UnmapViewOfFile (map -> addr ))
302
+ rc = -1 ;
303
+ if (!CloseHandle (map -> h ))
304
+ rc = -1 ;
305
+ }
306
+ }
307
+ }
308
+
309
+ // free mappings
310
+ if (!dll_is_empty (delete )) {
311
+ __maps_lock ();
312
+ struct Dll * e ;
313
+ while ((e = dll_first (delete ))) {
314
+ dll_remove (& delete , e );
315
+ __maps_free (MAP_CONTAINER (e ));
316
+ }
317
+ __maps_check ();
318
+ __maps_unlock ();
319
+ }
320
+
312
321
return rc ;
313
322
}
314
323
0 commit comments