On AIX: * mmap does not allow to map an already mapped range, * mmap range start at 0x30000000 for 32 bits processes, * mmap range start at 0x70000000_00000000 for 64 bits processes
This libgo patch by Matthieu Sarter addresses these issues. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline. Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 249712) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -63b766d67098877496a4b79d7f41e731fbe8abc8 +66d14d95a5a453682fe387319c80bc4fc40d96ad The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: libgo/go/runtime/malloc.go =================================================================== --- libgo/go/runtime/malloc.go (revision 249205) +++ libgo/go/runtime/malloc.go (working copy) @@ -291,6 +291,8 @@ func mallocinit() { // allocation at 0x40 << 32 because when using 4k pages with 3-level // translation buffers, the user address space is limited to 39 bits // On darwin/arm64, the address space is even smaller. + // On AIX, mmap adresses range start at 0x07000000_00000000 for 64 bits + // processes. arenaSize := round(_MaxMem, _PageSize) bitmapSize = arenaSize / (sys.PtrSize * 8 / 2) spansSize = arenaSize / _PageSize * sys.PtrSize @@ -301,12 +303,15 @@ func mallocinit() { p = uintptr(i)<<40 | uintptrMask&(0x0013<<28) case GOARCH == "arm64": p = uintptr(i)<<40 | uintptrMask&(0x0040<<32) + case GOOS == "aix": + i = 1 + p = uintptr(i)<<32 | uintptrMask&(0x70<<52) default: p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32) } pSize = bitmapSize + spansSize + arenaSize + _PageSize p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved)) - if p != 0 { + if p != 0 || GOOS == "aix" { // Useless to loop on AIX, as i is forced to 1 break } } Index: libgo/go/runtime/mem_gccgo.go =================================================================== --- libgo/go/runtime/mem_gccgo.go (revision 249205) +++ libgo/go/runtime/mem_gccgo.go (working copy) @@ -270,6 +270,11 @@ func sysMap(v unsafe.Pointer, n uintptr, return } + if GOOS == "aix" { + // AIX does not allow mapping a range that is already mapped. + // So always unmap first even if it is already unmapped. + munmap(v, n) + } p := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, mmapFD, 0) if uintptr(p) == _MAP_FAILED && errno() == _ENOMEM { throw("runtime: out of memory") Index: libgo/runtime/runtime_c.c =================================================================== --- libgo/runtime/runtime_c.c (revision 249205) +++ libgo/runtime/runtime_c.c (working copy) @@ -139,6 +139,10 @@ uintptr getEnd(void) uintptr getEnd() { +#ifdef _AIX + // mmap adresses range start at 0x30000000 on AIX for 32 bits processes + uintptr end = 0x30000000U; +#else uintptr end = 0; uintptr *pend; @@ -146,6 +150,8 @@ getEnd() if (pend != nil) { end = *pend; } +#endif + return end; }