| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 | /* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org> * * GNU Library General Public License (LGPL) version 2 or later. * * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details. */#include "_stdio.h"extern int __fflush_unlocked(register FILE *stream);#ifdef __DO_UNLOCKED#ifdef __UCLIBC_MJN3_ONLY__#warning WISHLIST: Add option to test for undefined behavior of fflush.#endif /* __UCLIBC_MJN3_ONLY__ */weak_alias(__fflush_unlocked,fflush_unlocked);#ifndef __UCLIBC_HAS_THREADS__weak_alias(__fflush_unlocked,fflush);#endif#ifdef __UCLIBC_HAS_THREADS__/* Even if the stream is set to user-locking, we still need to lock * when all (lbf) writing streams are flushed. */#define MY_STDIO_THREADLOCK(STREAM) \	if (_stdio_user_locking != 2) { \		__STDIO_ALWAYS_THREADLOCK(STREAM); \	}#define MY_STDIO_THREADUNLOCK(STREAM) \	if (_stdio_user_locking != 2) { \		__STDIO_ALWAYS_THREADUNLOCK(STREAM); \	}#else#define MY_STDIO_THREADLOCK(STREAM)		((void)0)#define MY_STDIO_THREADUNLOCK(STREAM)	((void)0)#endifint __fflush_unlocked(register FILE *stream){#ifdef __STDIO_BUFFERS	int retval = 0;#ifdef __UCLIBC_MJN3_ONLY__#warning REMINDER: should probably define a modeflags type#endif	unsigned short bufmask = __FLAG_LBF;#ifndef NDEBUG	if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {		__STDIO_STREAM_VALIDATE(stream); /* debugging only */	}#endif	if (stream == (FILE *) &_stdio_openlist) { /* Flush all lbf streams. */		stream = NULL;		bufmask = 0;	}	if (!stream) {				/* Flush all (lbf) writing streams. */		__STDIO_THREADLOCK_OPENLIST;		for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) {			MY_STDIO_THREADLOCK(stream);			if (!(((stream->__modeflags | bufmask)				   ^ (__FLAG_WRITING|__FLAG_LBF)				   ) & (__FLAG_WRITING|__MASK_BUFMODE))				) {				if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {					__STDIO_STREAM_DISABLE_PUTC(stream);					__STDIO_STREAM_CLEAR_WRITING(stream);				} else {					retval = EOF;				}			}			MY_STDIO_THREADUNLOCK(stream);		}		__STDIO_THREADUNLOCK_OPENLIST;	} else if (__STDIO_STREAM_IS_WRITING(stream)) {		if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {			__STDIO_STREAM_DISABLE_PUTC(stream);			__STDIO_STREAM_CLEAR_WRITING(stream);		} else {			retval = EOF;		}	}#if 0	else if (stream->__modeflags & (__MASK_READING|__FLAG_READONLY)) {		/* ANSI/ISO says behavior in this case is undefined but also says you		 * shouldn't flush a stream you were reading from.  As usual, glibc		 * caters to broken programs and simply ignores this. */		__UNDEFINED_OR_NONPORTABLE;		__STDIO_STREAM_SET_ERROR(stream);		__set_errno(EBADF);		retval = EOF;	}#endif#ifndef NDEBUG	if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {		__STDIO_STREAM_VALIDATE(stream); /* debugging only */	}#endif	return retval;#else  /* __STDIO_BUFFERS --------------------------------------- */#ifndef NDEBUG	if ((stream != NULL)#ifdef __STDIO_HAS_OPENLIST		&& (stream != (FILE *) &_stdio_openlist)#endif		) {		__STDIO_STREAM_VALIDATE(stream); /* debugging only */	}#endif#if 0	if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) {		/* ANSI/ISO says behavior in this case is undefined but also says you		 * shouldn't flush a stream you were reading from.  As usual, glibc		 * caters to broken programs and simply ignores this. */		__UNDEFINED_OR_NONPORTABLE;		__STDIO_STREAM_SET_ERROR(stream);		__set_errno(EBADF);		return EOF;	}#endif	return 0;#endif /* __STDIO_BUFFERS */}#elif defined __UCLIBC_HAS_THREADS__int fflush(register FILE *stream){	int retval;	__STDIO_AUTO_THREADLOCK_VAR;	if (stream#ifdef __STDIO_HAS_OPENLIST		&& (stream != (FILE *) &_stdio_openlist)#endif		) {		__STDIO_AUTO_THREADLOCK(stream);		retval = __fflush_unlocked(stream);		__STDIO_AUTO_THREADUNLOCK(stream);	} else {		retval = __fflush_unlocked(stream);	}	return retval;}#endif
 |