runtime: adapt memory management to AIX mmap

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 is adapted from change 37845.

Issue golang/go#19200

Change-Id: I0e30cb938968cadd21968c3598ddce59f5f0ca0f
Reviewed-on: https://go-review.googlesource.com/46772
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go
index 05a69c9..3912fc2 100644
--- a/libgo/go/runtime/malloc.go
+++ b/libgo/go/runtime/malloc.go
@@ -291,6 +291,8 @@
 		// 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 @@
 				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
 			}
 		}
diff --git a/libgo/go/runtime/mem_gccgo.go b/libgo/go/runtime/mem_gccgo.go
index 161ff26..ea3e5eb 100644
--- a/libgo/go/runtime/mem_gccgo.go
+++ b/libgo/go/runtime/mem_gccgo.go
@@ -270,6 +270,11 @@
 		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")
diff --git a/libgo/runtime/runtime_c.c b/libgo/runtime/runtime_c.c
index 336b261..6da3521 100644
--- a/libgo/runtime/runtime_c.c
+++ b/libgo/runtime/runtime_c.c
@@ -139,6 +139,10 @@
 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 @@
   if (pend != nil) {
     end = *pend;
   }
+#endif
+
   return end;
 }