1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
10 libc_hidden_proto(fflush_unlocked)
14 #ifdef __UCLIBC_MJN3_ONLY__
15 #warning WISHLIST: Add option to test for undefined behavior of fflush.
16 #endif /* __UCLIBC_MJN3_ONLY__ */
18 #ifdef __UCLIBC_HAS_THREADS__
19 /* Even if the stream is set to user-locking, we still need to lock
20 * when all (lbf) writing streams are flushed. */
21 #define MY_STDIO_THREADLOCK(STREAM) \
22 if (_stdio_user_locking != 2) { \
23 __STDIO_ALWAYS_THREADLOCK(STREAM); \
26 #define MY_STDIO_THREADUNLOCK(STREAM) \
27 if (_stdio_user_locking != 2) { \
28 __STDIO_ALWAYS_THREADUNLOCK(STREAM); \
31 #define MY_STDIO_THREADLOCK(STREAM) ((void)0)
32 #define MY_STDIO_THREADUNLOCK(STREAM) ((void)0)
36 int fflush_unlocked(register FILE *stream)
38 #ifdef __STDIO_BUFFERS
41 #ifdef __UCLIBC_MJN3_ONLY__
42 #warning REMINDER: should probably define a modeflags type
44 unsigned short bufmask = __FLAG_LBF;
47 if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
48 __STDIO_STREAM_VALIDATE(stream); /* debugging only */
52 if (stream == (FILE *) &_stdio_openlist) { /* Flush all lbf streams. */
57 if (!stream) { /* Flush all (lbf) writing streams. */
58 __STDIO_THREADLOCK_OPENLIST;
59 for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) {
60 MY_STDIO_THREADLOCK(stream);
61 if (!(((stream->__modeflags | bufmask)
62 ^ (__FLAG_WRITING|__FLAG_LBF)
63 ) & (__FLAG_WRITING|__MASK_BUFMODE))
65 if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
66 __STDIO_STREAM_DISABLE_PUTC(stream);
67 __STDIO_STREAM_CLEAR_WRITING(stream);
72 MY_STDIO_THREADUNLOCK(stream);
74 __STDIO_THREADUNLOCK_OPENLIST;
75 } else if (__STDIO_STREAM_IS_WRITING(stream)) {
76 if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
77 __STDIO_STREAM_DISABLE_PUTC(stream);
78 __STDIO_STREAM_CLEAR_WRITING(stream);
84 else if (stream->__modeflags & (__MASK_READING|__FLAG_READONLY)) {
85 /* ANSI/ISO says behavior in this case is undefined but also says you
86 * shouldn't flush a stream you were reading from. As usual, glibc
87 * caters to broken programs and simply ignores this. */
88 __UNDEFINED_OR_NONPORTABLE;
89 __STDIO_STREAM_SET_ERROR(stream);
96 if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
97 __STDIO_STREAM_VALIDATE(stream); /* debugging only */
103 #else /* __STDIO_BUFFERS --------------------------------------- */
107 #ifdef __STDIO_HAS_OPENLIST
108 && (stream != (FILE *) &_stdio_openlist)
111 __STDIO_STREAM_VALIDATE(stream); /* debugging only */
116 if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) {
117 /* ANSI/ISO says behavior in this case is undefined but also says you
118 * shouldn't flush a stream you were reading from. As usual, glibc
119 * caters to broken programs and simply ignores this. */
120 __UNDEFINED_OR_NONPORTABLE;
121 __STDIO_STREAM_SET_ERROR(stream);
128 #endif /* __STDIO_BUFFERS */
130 libc_hidden_def(fflush_unlocked)
132 #ifndef __UCLIBC_HAS_THREADS__
133 strong_alias(fflush_unlocked,fflush)
134 libc_hidden_proto(fflush)
135 libc_hidden_def(fflush)
138 #elif defined __UCLIBC_HAS_THREADS__
140 int fflush(register FILE *stream)
143 __STDIO_AUTO_THREADLOCK_VAR;
146 #ifdef __STDIO_HAS_OPENLIST
147 && (stream != (FILE *) &_stdio_openlist)
151 __STDIO_AUTO_THREADLOCK(stream);
153 retval = fflush_unlocked(stream);
155 __STDIO_AUTO_THREADUNLOCK(stream);
157 retval = fflush_unlocked(stream);
162 libc_hidden_proto(fflush)
163 libc_hidden_def(fflush)