netinet/in.h: add IPPROTO_MH
[uclibc-ng.git] / libc / stdio / fflush.c
blob7c05ea5feb1274d386004543c98dc4983cd5b374
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.
6 */
8 #include "_stdio.h"
11 #ifdef __DO_UNLOCKED
13 /* Even if the stream is set to user-locking, we still need to lock
14 * when all (lbf) writing streams are flushed. */
16 #define __MY_STDIO_THREADLOCK(__stream) \
17 __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \
18 (_stdio_user_locking != 2))
20 #define __MY_STDIO_THREADUNLOCK(__stream) \
21 __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \
22 (_stdio_user_locking != 2))
24 #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
25 void attribute_hidden _stdio_openlist_dec_use(void)
27 __STDIO_THREADLOCK_OPENLIST_DEL;
28 if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) {
29 FILE *p = NULL;
30 FILE *n;
31 FILE *stream;
33 /* Grab the openlist add lock since we might change the head of the list. */
34 __STDIO_THREADLOCK_OPENLIST_ADD;
35 for (stream = _stdio_openlist; stream; stream = n) {
36 n = stream->__nextopen;
37 if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN))
38 == (__FLAG_READONLY|__FLAG_WRITEONLY)
39 ) { /* The file was closed and should be removed from the list. */
40 if (!p) {
41 _stdio_openlist = n;
42 } else {
43 p->__nextopen = n;
45 __STDIO_STREAM_FREE_FILE(stream);
46 } else {
47 p = stream;
50 __STDIO_THREADUNLOCK_OPENLIST_ADD;
51 _stdio_openlist_del_count = 0; /* Should be clean now. */
53 --_stdio_openlist_use_count;
54 __STDIO_THREADUNLOCK_OPENLIST_DEL;
56 #endif
58 int fflush_unlocked(register FILE *stream)
60 #ifdef __STDIO_BUFFERS
62 int retval = 0;
63 unsigned short bufmask = __FLAG_LBF;
65 #ifndef NDEBUG
66 if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
67 __STDIO_STREAM_VALIDATE(stream); /* debugging only */
69 #endif
71 if (stream == (FILE *) &_stdio_openlist) { /* Flush all lbf streams. */
72 stream = NULL;
73 bufmask = 0;
76 if (!stream) { /* Flush all (lbf) writing streams. */
78 __STDIO_OPENLIST_INC_USE;
80 __STDIO_THREADLOCK_OPENLIST_ADD;
81 stream = _stdio_openlist;
82 __STDIO_THREADUNLOCK_OPENLIST_ADD;
84 while(stream) {
85 /* We only care about currently writing streams and do not want to
86 * block trying to obtain mutexes on non-writing streams. */
87 if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */
88 __MY_STDIO_THREADLOCK(stream);
89 /* Need to check again once we have the lock. */
90 if (!(((stream->__modeflags | bufmask)
91 ^ (__FLAG_WRITING|__FLAG_LBF)
92 ) & (__FLAG_WRITING|__MASK_BUFMODE))
93 ) {
94 if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
95 __STDIO_STREAM_DISABLE_PUTC(stream);
96 __STDIO_STREAM_CLEAR_WRITING(stream);
97 } else {
98 retval = EOF;
101 __MY_STDIO_THREADUNLOCK(stream);
103 stream = stream->__nextopen;
106 __STDIO_OPENLIST_DEC_USE;
108 } else if (__STDIO_STREAM_IS_WRITING(stream)) {
109 if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
110 __STDIO_STREAM_DISABLE_PUTC(stream);
111 __STDIO_STREAM_CLEAR_WRITING(stream);
112 } else {
113 retval = EOF;
116 #if 0
117 else if (stream->__modeflags & (__MASK_READING|__FLAG_READONLY)) {
118 /* ANSI/ISO says behavior in this case is undefined but also says you
119 * shouldn't flush a stream you were reading from. As usual, glibc
120 * caters to broken programs and simply ignores this. */
121 __UNDEFINED_OR_NONPORTABLE;
122 __STDIO_STREAM_SET_ERROR(stream);
123 __set_errno(EBADF);
124 retval = EOF;
126 #endif
128 #ifndef NDEBUG
129 if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
130 __STDIO_STREAM_VALIDATE(stream); /* debugging only */
132 #endif
134 return retval;
136 #else /* __STDIO_BUFFERS --------------------------------------- */
138 #ifndef NDEBUG
139 if ((stream != NULL)
140 #ifdef __STDIO_HAS_OPENLIST
141 && (stream != (FILE *) &_stdio_openlist)
142 #endif
144 __STDIO_STREAM_VALIDATE(stream); /* debugging only */
146 #endif
148 #if 0
149 if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) {
150 /* ANSI/ISO says behavior in this case is undefined but also says you
151 * shouldn't flush a stream you were reading from. As usual, glibc
152 * caters to broken programs and simply ignores this. */
153 __UNDEFINED_OR_NONPORTABLE;
154 __STDIO_STREAM_SET_ERROR(stream);
155 __set_errno(EBADF);
156 return EOF;
158 #endif
160 return 0;
161 #endif /* __STDIO_BUFFERS */
163 libc_hidden_def(fflush_unlocked)
165 #ifndef __UCLIBC_HAS_THREADS__
166 strong_alias(fflush_unlocked,fflush)
167 libc_hidden_def(fflush)
168 #endif
170 #elif defined __UCLIBC_HAS_THREADS__
172 int fflush(register FILE *stream)
174 int retval;
175 __STDIO_AUTO_THREADLOCK_VAR;
177 if (stream
178 #ifdef __STDIO_HAS_OPENLIST
179 && (stream != (FILE *) &_stdio_openlist)
180 #endif
183 __STDIO_AUTO_THREADLOCK(stream);
185 retval = fflush_unlocked(stream);
187 __STDIO_AUTO_THREADUNLOCK(stream);
188 } else {
189 retval = fflush_unlocked(stream);
192 return retval;
194 libc_hidden_def(fflush)
196 #endif