unix: add Select syscall on AIX

As select is a keyword of Go, C.select cannot be used on gccgo files.
Therefore, select call is transformed into c_select.

Change-Id: Ic68a7ffa03dc5a5d70514876b5f6afb565691a4a
Reviewed-on: https://go-review.googlesource.com/c/sys/+/172739
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/mksyscall_aix_ppc.go b/unix/mksyscall_aix_ppc.go
index f2c58fb..3be3cdf 100644
--- a/unix/mksyscall_aix_ppc.go
+++ b/unix/mksyscall_aix_ppc.go
@@ -214,6 +214,11 @@
 			}
 
 			if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
+				if sysname == "select" {
+					// select is a keyword of Go. Its name is
+					// changed to c_select.
+					cExtern += "#define c_select select\n"
+				}
 				// Imports of system calls from libc
 				cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
 				cIn := strings.Join(cIn, ", ")
@@ -328,7 +333,13 @@
 			} else {
 				call += ""
 			}
-			call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
+			if sysname == "select" {
+				// select is a keyword of Go. Its name is
+				// changed to c_select.
+				call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist)
+			} else {
+				call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
+			}
 
 			// Assign return values.
 			body := ""
diff --git a/unix/mksyscall_aix_ppc64.go b/unix/mksyscall_aix_ppc64.go
index 45b4429..c960099 100644
--- a/unix/mksyscall_aix_ppc64.go
+++ b/unix/mksyscall_aix_ppc64.go
@@ -282,6 +282,11 @@
 			if !onlyCommon {
 				// GCCGO Prototype Generation
 				// Imports of system calls from libc
+				if sysname == "select" {
+					// select is a keyword of Go. Its name is
+					// changed to c_select.
+					cExtern += "#define c_select select\n"
+				}
 				cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
 				cIn := strings.Join(cIn, ", ")
 				cExtern += fmt.Sprintf("(%s);\n", cIn)
@@ -490,7 +495,14 @@
 
 			// GCCGO function generation
 			argsgccgolist := strings.Join(argsgccgo, ", ")
-			callgccgo := fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
+			var callgccgo string
+			if sysname == "select" {
+				// select is a keyword of Go. Its name is
+				// changed to c_select.
+				callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
+			} else {
+				callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
+			}
 			textgccgo += callProto
 			textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
 			textgccgo += "\te1 = syscall.GetErrno()\n"
diff --git a/unix/syscall_aix.go b/unix/syscall_aix.go
index fb7a906..071f4fd 100644
--- a/unix/syscall_aix.go
+++ b/unix/syscall_aix.go
@@ -470,8 +470,7 @@
 //sys	Pause() (err error)
 //sys	Pread(fd int, p []byte, offset int64) (n int, err error) = pread64
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64
-//TODO Select
-// //sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
+//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
 //sys	Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
 //sysnb	Setregid(rgid int, egid int) (err error)
 //sysnb	Setreuid(ruid int, euid int) (err error)
diff --git a/unix/syscall_aix_test.go b/unix/syscall_aix_test.go
index 6f55c07..e9d4a59 100644
--- a/unix/syscall_aix_test.go
+++ b/unix/syscall_aix_test.go
@@ -123,6 +123,26 @@
 	}
 }
 
+func TestSelect(t *testing.T) {
+	_, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
+	if err != nil {
+		t.Fatalf("Select: %v", err)
+	}
+
+	dur := 150 * time.Millisecond
+	tv := unix.NsecToTimeval(int64(dur))
+	start := time.Now()
+	_, err = unix.Select(0, nil, nil, nil, &tv)
+	took := time.Since(start)
+	if err != nil {
+		t.Fatalf("Select: %v", err)
+	}
+
+	if took < dur {
+		t.Errorf("Select: timeout should have been at least %v, got %v", dur, took)
+	}
+}
+
 func TestPselect(t *testing.T) {
 	if runtime.GOARCH == "ppc64" {
 		t.Skip("pselect issue with structure timespec on AIX 7.2 tl0, skipping test")
diff --git a/unix/zsyscall_aix_ppc.go b/unix/zsyscall_aix_ppc.go
index 8b75335..d102107 100644
--- a/unix/zsyscall_aix_ppc.go
+++ b/unix/zsyscall_aix_ppc.go
@@ -83,6 +83,8 @@
 int pause();
 int pread64(int, uintptr_t, size_t, long long);
 int pwrite64(int, uintptr_t, size_t, long long);
+#define c_select select
+int select(int, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
 int pselect(int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
 int setregid(int, int);
 int setreuid(int, int);
@@ -1005,6 +1007,17 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+	r0, er := C.c_select(C.int(nfd), C.uintptr_t(uintptr(unsafe.Pointer(r))), C.uintptr_t(uintptr(unsafe.Pointer(w))), C.uintptr_t(uintptr(unsafe.Pointer(e))), C.uintptr_t(uintptr(unsafe.Pointer(timeout))))
+	n = int(r0)
+	if r0 == -1 && er != nil {
+		err = er
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
 	r0, er := C.pselect(C.int(nfd), C.uintptr_t(uintptr(unsafe.Pointer(r))), C.uintptr_t(uintptr(unsafe.Pointer(w))), C.uintptr_t(uintptr(unsafe.Pointer(e))), C.uintptr_t(uintptr(unsafe.Pointer(timeout))), C.uintptr_t(uintptr(unsafe.Pointer(sigmask))))
 	n = int(r0)
diff --git a/unix/zsyscall_aix_ppc64.go b/unix/zsyscall_aix_ppc64.go
index e954533..0b8e0fc 100644
--- a/unix/zsyscall_aix_ppc64.go
+++ b/unix/zsyscall_aix_ppc64.go
@@ -960,6 +960,17 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+	r0, e1 := callselect(nfd, uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
 	r0, e1 := callpselect(nfd, uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)))
 	n = int(r0)
diff --git a/unix/zsyscall_aix_ppc64_gc.go b/unix/zsyscall_aix_ppc64_gc.go
index 926ab78..a1801d8 100644
--- a/unix/zsyscall_aix_ppc64_gc.go
+++ b/unix/zsyscall_aix_ppc64_gc.go
@@ -85,6 +85,7 @@
 //go:cgo_import_dynamic libc_pause pause "libc.a/shr_64.o"
 //go:cgo_import_dynamic libc_pread64 pread64 "libc.a/shr_64.o"
 //go:cgo_import_dynamic libc_pwrite64 pwrite64 "libc.a/shr_64.o"
+//go:cgo_import_dynamic libc_select select "libc.a/shr_64.o"
 //go:cgo_import_dynamic libc_pselect pselect "libc.a/shr_64.o"
 //go:cgo_import_dynamic libc_setregid setregid "libc.a/shr_64.o"
 //go:cgo_import_dynamic libc_setreuid setreuid "libc.a/shr_64.o"
@@ -201,6 +202,7 @@
 //go:linkname libc_pause libc_pause
 //go:linkname libc_pread64 libc_pread64
 //go:linkname libc_pwrite64 libc_pwrite64
+//go:linkname libc_select libc_select
 //go:linkname libc_pselect libc_pselect
 //go:linkname libc_setregid libc_setregid
 //go:linkname libc_setreuid libc_setreuid
@@ -320,6 +322,7 @@
 	libc_pause,
 	libc_pread64,
 	libc_pwrite64,
+	libc_select,
 	libc_pselect,
 	libc_setregid,
 	libc_setreuid,
@@ -893,6 +896,13 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func callselect(nfd int, r uintptr, w uintptr, e uintptr, timeout uintptr) (r1 uintptr, e1 Errno) {
+	r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_select)), 5, uintptr(nfd), r, w, e, timeout, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func callpselect(nfd int, r uintptr, w uintptr, e uintptr, timeout uintptr, sigmask uintptr) (r1 uintptr, e1 Errno) {
 	r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_pselect)), 6, uintptr(nfd), r, w, e, timeout, sigmask)
 	return
diff --git a/unix/zsyscall_aix_ppc64_gccgo.go b/unix/zsyscall_aix_ppc64_gccgo.go
index c1796cb..1b5d567 100644
--- a/unix/zsyscall_aix_ppc64_gccgo.go
+++ b/unix/zsyscall_aix_ppc64_gccgo.go
@@ -83,6 +83,8 @@
 int pause();
 int pread64(int, uintptr_t, size_t, long long);
 int pwrite64(int, uintptr_t, size_t, long long);
+#define c_select select
+int select(int, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
 int pselect(int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
 int setregid(int, int);
 int setreuid(int, int);
@@ -732,6 +734,14 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func callselect(nfd int, r uintptr, w uintptr, e uintptr, timeout uintptr) (r1 uintptr, e1 Errno) {
+	r1 = uintptr(C.c_select(C.int(nfd), C.uintptr_t(r), C.uintptr_t(w), C.uintptr_t(e), C.uintptr_t(timeout)))
+	e1 = syscall.GetErrno()
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func callpselect(nfd int, r uintptr, w uintptr, e uintptr, timeout uintptr, sigmask uintptr) (r1 uintptr, e1 Errno) {
 	r1 = uintptr(C.pselect(C.int(nfd), C.uintptr_t(r), C.uintptr_t(w), C.uintptr_t(e), C.uintptr_t(timeout), C.uintptr_t(sigmask)))
 	e1 = syscall.GetErrno()