diff options
Diffstat (limited to 'libc/stdio/fclose.c')
| -rw-r--r-- | libc/stdio/fclose.c | 31 | 
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;  }  | 
