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

Commits:

1 changed file:

Changes:

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