summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/fclose.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-04-24 17:51:36 +0000
committerkib <kib@FreeBSD.org>2012-04-24 17:51:36 +0000
commitfa609f4d93f798de2153e04476f9b825aa469491 (patch)
tree4dea6a5419824f6e6fbe0ef07f6465bd4906fa87 /lib/libc/stdio/fclose.c
parentf0cabca1b818ea8a0563c3640eddf186f272a402 (diff)
downloadFreeBSD-src-fa609f4d93f798de2153e04476f9b825aa469491.zip
FreeBSD-src-fa609f4d93f798de2153e04476f9b825aa469491.tar.gz
Take the spinlock around clearing of the fp->_flags in fclose(3), which
indicates the avaliability of FILE, to prevent possible reordering of the writes as seen by other CPUs. Reported by: Fengwei yin <yfw.bsd gmail com> Reviewed by: jhb MFC after: 1 week
Diffstat (limited to 'lib/libc/stdio/fclose.c')
-rw-r--r--lib/libc/stdio/fclose.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c
index f0629e8..3957b6a 100644
--- a/lib/libc/stdio/fclose.c
+++ b/lib/libc/stdio/fclose.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include "un-namespace.h"
+#include <spinlock.h>
#include "libc_private.h"
#include "local.h"
@@ -65,7 +66,20 @@ fclose(FILE *fp)
FREELB(fp);
fp->_file = -1;
fp->_r = fp->_w = 0; /* Mess up if reaccessed. */
+
+ /*
+ * Lock the spinlock used to protect __sglue list walk in
+ * __sfp(). The __sfp() uses fp->_flags == 0 test as an
+ * indication of the unused FILE.
+ *
+ * Taking the lock prevents possible compiler or processor
+ * reordering of the writes performed before the final _flags
+ * cleanup, making sure that we are done with the FILE before
+ * it is considered available.
+ */
+ STDIO_THREAD_LOCK();
fp->_flags = 0; /* Release this FILE for reuse. */
+ STDIO_THREAD_UNLOCK();
FUNLOCKFILE(fp);
return (r);
}
OpenPOWER on IntegriCloud