1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00
This commit is contained in:
Jakub Jelinek
2007-07-12 18:26:36 +00:00
parent 7d58530341
commit 0ecb606cb6
6215 changed files with 494638 additions and 305010 deletions

View File

@@ -1,4 +1,5 @@
/* Copyright (C) 1993,1995,1997-2002, 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 1993,1995,1997-2002, 2003, 2004, 2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -32,6 +33,10 @@
#include <stdlib.h>
#endif
#include <string.h>
#include <stdbool.h>
#ifdef _LIBC
#include <sched.h>
#endif
#ifdef _IO_MTSAFE_IO
static _IO_lock_t list_all_lock = _IO_lock_initializer;
@@ -362,7 +367,7 @@ __uflow (fp)
#endif
if (fp->_mode == 0)
_IO_fwide (fp, -11);
_IO_fwide (fp, -1);
if (_IO_in_put_mode (fp))
if (INTUSE(_IO_switch_to_get_mode) (fp) == EOF)
return EOF;
@@ -657,6 +662,7 @@ _IO_no_init (fp, flags, orientation, wd, jmp)
fp->_wide_data->_wide_vtable = jmp;
}
#endif
fp->_freeres_list = NULL;
}
int
@@ -914,10 +920,27 @@ INTDEF(_IO_flush_all_linebuffered)
weak_alias (_IO_flush_all_linebuffered, _flushlbf)
#endif
/* The following is a bit tricky. In general, we want to unbuffer the
streams so that all output which follows is seen. If we are not
looking for memory leaks it does not make much sense to free the
actual buffer because this will happen anyway once the program
terminated. If we do want to look for memory leaks we have to free
the buffers. Whether something is freed is determined by the
function sin the libc_freeres section. Those are called as part of
the atexit routine, just like _IO_cleanup. The problem is we do
not know whether the freeres code is called first or _IO_cleanup.
if the former is the case, we set the DEALLOC_BUFFER variable to
true and _IO_unbuffer_write will take care of the rest. If
_IO_unbuffer_write is called first we add the streams to a list
which the freeres function later can walk through. */
static void _IO_unbuffer_write (void);
static bool dealloc_buffers;
static _IO_FILE *freeres_list;
static void
_IO_unbuffer_write ()
_IO_unbuffer_write (void)
{
struct _IO_FILE *fp;
for (fp = (_IO_FILE *) INTUSE(_IO_list_all); fp; fp = fp->_chain)
@@ -927,7 +950,32 @@ _IO_unbuffer_write ()
|| (fp->_flags & _IO_IS_APPENDING))
/* Iff stream is un-orientated, it wasn't used. */
&& fp->_mode != 0)
_IO_SETBUF (fp, NULL, 0);
{
int cnt;
#define MAXTRIES 2
for (cnt = 0; cnt < MAXTRIES; ++cnt)
if (_IO_lock_trylock (*fp->_lock) == 0)
break;
else
/* Give the other thread time to finish up its use of the
stream. */
__sched_yield ();
if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
{
fp->_flags |= _IO_USER_BUF;
fp->_freeres_list = freeres_list;
freeres_list = fp;
fp->_freeres_buf = fp->_IO_buf_base;
fp->_freeres_size = _IO_blen (fp);
}
_IO_SETBUF (fp, NULL, 0);
if (cnt < MAXTRIES)
_IO_lock_unlock (*fp->_lock);
}
/* Make sure that never again the wide char functions can be
used. */
@@ -935,11 +983,25 @@ _IO_unbuffer_write ()
}
}
libc_freeres_fn (buffer_free)
{
dealloc_buffers = true;
while (freeres_list != NULL)
{
FREE_BUF (freeres_list->_freeres_buf, freeres_list->_freeres_size);
freeres_list = freeres_list->_freeres_list;
}
}
int
_IO_cleanup ()
{
/* We do *not* want locking. Some threads might use streams but
that is there problem, we flush them underneath them. */
that is their problem, we flush them underneath them. */
int result = _IO_flush_all_lockp (0);
/* We currently don't have a reliable mechanism for making sure that