futex_wait_uninitialized_heap: Detect failure, standardize logging and arguments

Rather than hang, detect the failure and report it. Standardize
arguments and use the logging facilities.

Signed-off-by: Darren Hart <dvhltc@us.ibm.com>
diff --git a/functional/futex_wait_uninitialized_heap.c b/functional/futex_wait_uninitialized_heap.c
index cd7e5f6..24bda66 100644
--- a/functional/futex_wait_uninitialized_heap.c
+++ b/functional/futex_wait_uninitialized_heap.c
@@ -32,6 +32,7 @@
  *
  *****************************************************************************/
 
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mman.h>
@@ -46,40 +47,89 @@
 #include "logging.h"
 #include "futextest.h"
 
+#define WAIT_US 5000000
+
+static int child_blocked = 1;
+static int child_ret;
+void *buf;
+
+void usage(char *prog)
+{
+	printf("Usage: %s\n", prog);
+	printf("  -c	Use color\n");
+	printf("  -h	Display this help message\n");
+	printf("  -v L	Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n",
+	       VQUIET, VCRITICAL, VINFO);
+}
+
+void *wait_thread(void *arg)
+{
+	int res;
+	child_ret = RET_PASS;
+	res = futex_wait(buf, 1, NULL, 0);
+	child_blocked = 0;
+
+	if (res != 0 && errno != EWOULDBLOCK) {
+		error("futex failure\n", errno);
+		child_ret = RET_ERROR;
+	}
+	pthread_exit(NULL);
+}
+
 int main(int argc, char **argv)
 {
+	int c, ret = RET_PASS;
 	long page_size;
-	int res;
-	void *buf;
-	int ret = RET_PASS;
-	int c;
+	pthread_t thr;
 
-	while ((c = getopt(argc, argv, "c")) != -1) {
+	while ((c = getopt(argc, argv, "chv:")) != -1) {
 		switch(c) {
 		case 'c':
 			log_color(1);
 			break;
+		case 'h':
+			usage(basename(argv[0]));
+			exit(0);
+		case 'v':
+			log_verbosity(atoi(optarg));
+			break;
 		default:
+			usage(basename(argv[0]));
 			exit(1);
 		}
 	}
 
 	page_size = sysconf(_SC_PAGESIZE);
 
-	buf = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+	buf = mmap(NULL, page_size, PROT_READ|PROT_WRITE,
+		   MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
 	if (buf == (void *)-1) {
-		perror("mmap error.\n");
+		error("mmap\n", errno);
 		exit(1);
 	}
 
 	printf("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
 	       basename(argv[0]));
 
-	res = futex_wait(buf, 1, NULL, 0);
-	if (res != 0 && errno != EWOULDBLOCK) {
-		ret = RET_FAIL;
-	}
-	print_result(ret);
 
+	ret = pthread_create(&thr, NULL, wait_thread, NULL);
+	if (ret) {
+		error("pthread_create\n", errno);
+		ret = RET_ERROR;
+		goto out;
+	}
+
+	info("waiting %dus for child to return\n", WAIT_US);
+	usleep(WAIT_US);
+
+	if (child_blocked) {
+		fail("child blocked in kernel\n");
+		ret = RET_FAIL;
+	} else {
+		ret = child_ret;
+	}
+
+ out:
+	print_result(ret);
 	return ret;
 }