summaryrefslogtreecommitdiffstats
path: root/libc/stdio/fclose.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/stdio/fclose.c')
-rw-r--r--libc/stdio/fclose.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c
index 843599c0f..27d3c7e96 100644
--- a/libc/stdio/fclose.c
+++ b/libc/stdio/fclose.c
@@ -16,12 +16,15 @@ int fclose(register FILE *stream)
int rv = 0;
__STDIO_AUTO_THREADLOCK_VAR;
- /* First, remove the file from the open file list. */
#ifdef __STDIO_HAS_OPENLIST
+#if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS)
+ /* First, remove the file from the open file list. */
{
- register FILE *ptr;
+ FILE *ptr;
- __STDIO_THREADLOCK_OPENLIST;
+ __STDIO_THREADLOCK_OPENLIST_DEL;
+ __STDIO_THREADLOCK_OPENLIST_ADD;
+ ptr = _stdio_openlist;
if ((ptr = _stdio_openlist) == stream) {
_stdio_openlist = stream->__nextopen;
} else {
@@ -33,13 +36,11 @@ int fclose(register FILE *stream)
ptr = ptr->__nextopen;
}
}
- __STDIO_THREADUNLOCK_OPENLIST;
-
- if (!ptr) { /* Did not find stream in the open file list! */
- return EOF;
- }
+ __STDIO_THREADUNLOCK_OPENLIST_ADD;
+ __STDIO_THREADUNLOCK_OPENLIST_DEL;
}
#endif
+#endif
__STDIO_AUTO_THREADLOCK(stream);
@@ -62,6 +63,11 @@ int fclose(register FILE *stream)
* Since a file can't be both readonly and writeonly, that makes
* an effective signal. It also has the benefit of disabling
* transitions to either reading or writing. */
+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
+ /* Before we mark the file as closed, make sure we increment the openlist use count
+ * so it isn't freed under us while still cleaning up. */
+ __STDIO_OPENLIST_INC_USE;
+#endif
stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE);
stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY);
@@ -84,7 +90,16 @@ int fclose(register FILE *stream)
__STDIO_AUTO_THREADUNLOCK(stream);
__STDIO_STREAM_FREE_BUFFER(stream);
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: inefficient - locks and unlocks twice and walks whole list
+#endif
+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
+ /* inefficient - locks/unlocks twice and walks whole list */
+ __STDIO_OPENLIST_INC_DEL_CNT;
+ __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */
+#else
__STDIO_STREAM_FREE_FILE(stream);
+#endif
return rv;
}