123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- #include "_stdio.h"
- #ifdef __DO_UNLOCKED
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning WISHLIST: Add option to test for undefined behavior of fflush.
- #endif
- #define __MY_STDIO_THREADLOCK(__stream) \
- __UCLIBC_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \
- (_stdio_user_locking != 2))
- #define __MY_STDIO_THREADUNLOCK(__stream) \
- __UCLIBC_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \
- (_stdio_user_locking != 2))
- #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
- void attribute_hidden _stdio_openlist_dec_use(void)
- {
- __STDIO_THREADLOCK_OPENLIST_DEL;
- if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) {
- FILE *p = NULL;
- FILE *n;
- FILE *stream;
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning REMINDER: As an optimization, we could unlock after we move past the head.
- #endif
-
- __STDIO_THREADLOCK_OPENLIST_ADD;
- for (stream = _stdio_openlist; stream; stream = n) {
- n = stream->__nextopen;
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning REMINDER: fix for nonatomic
- #endif
- if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN))
- == (__FLAG_READONLY|__FLAG_WRITEONLY)
- ) {
- if (!p) {
- _stdio_openlist = n;
- } else {
- p->__nextopen = n;
- }
- __STDIO_STREAM_FREE_FILE(stream);
- } else {
- p = stream;
- }
- }
- __STDIO_THREADUNLOCK_OPENLIST_ADD;
- _stdio_openlist_del_count = 0;
- }
- --_stdio_openlist_use_count;
- __STDIO_THREADUNLOCK_OPENLIST_DEL;
- }
- #endif
- int 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);
- }
- #endif
- if (stream == (FILE *) &_stdio_openlist) {
- stream = NULL;
- bufmask = 0;
- }
- if (!stream) {
- __STDIO_OPENLIST_INC_USE;
- __STDIO_THREADLOCK_OPENLIST_ADD;
- stream = _stdio_openlist;
- __STDIO_THREADUNLOCK_OPENLIST_ADD;
- while(stream) {
-
- #warning fix for nonatomic
- #warning unnecessary check if no threads
- if (__STDIO_STREAM_IS_WRITING(stream)) {
- __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);
- }
- stream = stream->__nextopen;
- }
- __STDIO_OPENLIST_DEC_USE;
- } 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)) {
-
- __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);
- }
- #endif
- return retval;
- #else
- #ifndef NDEBUG
- if ((stream != NULL)
- #ifdef __STDIO_HAS_OPENLIST
- && (stream != (FILE *) &_stdio_openlist)
- #endif
- ) {
- __STDIO_STREAM_VALIDATE(stream);
- }
- #endif
- #if 0
- if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) {
-
- __UNDEFINED_OR_NONPORTABLE;
- __STDIO_STREAM_SET_ERROR(stream);
- __set_errno(EBADF);
- return EOF;
- }
- #endif
- return 0;
- #endif
- }
- libc_hidden_def(fflush_unlocked)
- #ifndef __UCLIBC_HAS_THREADS__
- strong_alias(fflush_unlocked,fflush)
- libc_hidden_def(fflush)
- #endif
- #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;
- }
- libc_hidden_def(fflush)
- #endif
|