diff options
author | kib <kib@FreeBSD.org> | 2012-04-24 17:51:36 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-04-24 17:51:36 +0000 |
commit | fa609f4d93f798de2153e04476f9b825aa469491 (patch) | |
tree | 4dea6a5419824f6e6fbe0ef07f6465bd4906fa87 /lib/libc/stdio/fclose.c | |
parent | f0cabca1b818ea8a0563c3640eddf186f272a402 (diff) | |
download | FreeBSD-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.c | 14 |
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); } |