Ben Gamari pushed to branch wip/T26151 at Glasgow Haskell Compiler / GHC

Commits:

1 changed file:

Changes:

  • rts/posix/OSMem.c
    ... ... @@ -585,6 +585,10 @@ void *osReserveHeapMemory(void *startAddressPtr, W_ *len)
    585 585
         }
    
    586 586
     #endif
    
    587 587
     
    
    588
    +    const int MAX_ATTEMPTS = 8;
    
    589
    +    void *bad_allocs[MAX_ATTEMPTS] = {};
    
    590
    +    size_t bad_alloc_lens[MAX_ATTEMPTS] = {};
    
    591
    +
    
    588 592
         attempt = 0;
    
    589 593
         while (attempt < MAX_ATTEMPTS) {
    
    590 594
             *len &= ~MBLOCK_MASK;
    
    ... ... @@ -611,18 +615,31 @@ void *osReserveHeapMemory(void *startAddressPtr, W_ *len)
    611 615
             } else if ((W_)at >= minimumAddress) {
    
    612 616
                 // Success! We were given a block of memory starting above the 8 GB
    
    613 617
                 // mark, which is what we were looking for.
    
    614
    -
    
    615 618
                 break;
    
    616 619
             } else {
    
    617 620
                 // We got addressing space but it wasn't above the 8GB mark.
    
    618
    -            // Try again.
    
    619
    -            if (munmap(at, *len) < 0) {
    
    620
    -                sysErrorBelch("unable to release reserved heap");
    
    621
    +            // Free any portion *above* 8GB and hang on to the rest to increase
    
    622
    +            // the likelihood that we get a suitable allocation next iteration.
    
    623
    +            uintptr_t end = (W_) at + *len;
    
    624
    +            bad_allocs[attempt] = at;
    
    625
    +            if (end > minimumAddress) {
    
    626
    +                if (munmap((void *) minimumAddress, end - minimumAddress) < 0) {
    
    627
    +                    sysErrorBelch("unable to release high portion of low memory reservation");
    
    628
    +                }
    
    629
    +                bad_alloc_lens[attempt] = minimumAddress - (W_) at;
    
    630
    +            } else {
    
    631
    +                bad_alloc_lens[attempt] = *len;
    
    621 632
                 }
    
    622 633
             }
    
    623 634
             attempt++;
    
    624 635
         }
    
    625 636
     
    
    637
    +    for (int i=0; i < MAX_ATTEMPTS; i++) {
    
    638
    +        if (bad_allocs[i] != NULL && munmap(bad_allocs[i], bad_alloc_lens[i]) < 0) {
    
    639
    +            sysErrorBelch("unable to release reserved heap");
    
    640
    +        }
    
    641
    +    }
    
    642
    +
    
    626 643
         if (at == NULL) {
    
    627 644
             sysErrorBelch("failed to reserve heap memory");
    
    628 645
         }