Fix the handle locking in stdio

Fix the handle locking in stdio to use flockfile/funlockfile
internally when and where required.  Macros in <stdio.h> are updated
to automatically call the underlying functions when the process is
threaded to obtain the necessary locking.  A private mutex is added
to protect __sglue, the internal list of FILE handles, and another
to protect the one-time initialization.  Some routines in libc that
use getc() change to use getc_unlocked() as they're either protected
by their own lock or aren't thread-safe routines anyway.

Based on OpenBSD change by guenther@openbsd.org
http://www.mail-archive.com/source-changes@cvs.openbsd.org/msg01015.html

Bug: 3446659
Change-Id: Ie82116e358c541718d6709ec45ca6796be5a007b
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index c38ed5a..4006882 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -170,6 +170,7 @@
 #define	__SOFF	0x1000		/* set iff _offset is in fact correct */
 #define	__SMOD	0x2000		/* true => fgetln modified _p text */
 #define	__SALC	0x4000		/* allocate string space dynamically */
+#define	__SIGN	0x8000		/* ignore this file in _fwalk */
 
 /*
  * The following three definitions are for ANSI C, which took them
@@ -406,38 +407,43 @@
 #define	__sclearerr(p)	((void)((p)->_flags &= ~(__SERR|__SEOF)))
 #define	__sfileno(p)	((p)->_file)
 
-#define	feof(p)		__sfeof(p)
-#define	ferror(p)	__sferror(p)
+extern	int __isthreaded;
 
-#ifndef _POSIX_THREADS
-#define	clearerr(p)	__sclearerr(p)
-#endif
+#define	feof(p)		(!__isthreaded ? __sfeof(p) : (feof)(p))
+#define	ferror(p)	(!__isthreaded ? __sferror(p) : (ferror)(p))
+#define	clearerr(p)	(!__isthreaded ? __sclearerr(p) : (clearerr)(p))
 
 #if __POSIX_VISIBLE
-#define	fileno(p)	__sfileno(p)
+#define	fileno(p)	(!__isthreaded ? __sfileno(p) : (fileno)(p))
 #endif
 
+#define	getc(fp)	(!__isthreaded ? __sgetc(fp) : (getc)(fp))
+
+#if __BSD_VISIBLE
+/*
+ * The macro implementations of putc and putc_unlocked are not
+ * fully POSIX compliant; they do not set errno on failure
+ */
+#define putc(x, fp)	(!__isthreaded ? __sputc(x, fp) : (putc)(x, fp))
+#endif /* __BSD_VISIBLE */
+
 #ifndef lint
-#ifndef _POSIX_THREADS
-#define	getc(fp)	__sgetc(fp)
-#endif /* _POSIX_THREADS */
+#if __POSIX_VISIBLE >= 199506
 #define	getc_unlocked(fp)	__sgetc(fp)
 /*
  * The macro implementations of putc and putc_unlocked are not
  * fully POSIX compliant; they do not set errno on failure
  */
 #if __BSD_VISIBLE
-#ifndef _POSIX_THREADS
-#define putc(x, fp)	__sputc(x, fp)
-#endif /* _POSIX_THREADS */
 #define putc_unlocked(x, fp)	__sputc(x, fp)
 #endif /* __BSD_VISIBLE */
+#endif /* __POSIX_VISIBLE >= 199506 */
 #endif /* lint */
 
 #define	getchar()	getc(stdin)
 #define	putchar(x)	putc(x, stdout)
-#define getchar_unlocked()	getc_unlocked(stdin)
-#define putchar_unlocked(c)	putc_unlocked(c, stdout)
+#define	getchar_unlocked()	getc_unlocked(stdin)
+#define	putchar_unlocked(c)	putc_unlocked(c, stdout)
 
 #ifdef _GNU_SOURCE
 /*