This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

_IO_MTSAFE_IO


I looked at further preprocessor conditionals to remove and came across _IO_MTSAFE_IO.

The odd thing here is that we compile libio and related parts with _IO_MTSAFE_IO, but not the rest of glibc. The public <libio.h> header contains a _IO_MTSAFE_IO conditional, too:

#ifdef _IO_MTSAFE_IO
# define _IO_peekc(_fp) _IO_peekc_locked (_fp)
# define _IO_flockfile(_fp) \
  if (((_fp)->_flags & _IO_USER_LOCK) == 0) _IO_flockfile (_fp)
# define _IO_funlockfile(_fp) \
  if (((_fp)->_flags & _IO_USER_LOCK) == 0) _IO_funlockfile (_fp)
#else
# define _IO_peekc(_fp) _IO_peekc_unlocked (_fp)
# define _IO_flockfile(_fp) /**/
# define _IO_funlockfile(_fp) /**/
# define _IO_ftrylockfile(_fp) /**/
# define _IO_cleanup_region_start(_fct, _fp) /**/
# define _IO_cleanup_region_end(_Doit) /**/
#endif /* !_IO_MTSAFE_IO */

Applications which use these macros get the !_IO_MTSAFE_IO variants, e.g. _IO_flockfile is completely elided.

Whether applications can use these macros is somewhat debatable, but as I said, it happens within glibc as well. There are repeated occurrences of this in posix/getopt.c, for example:

  _IO_flockfile (stderr);

  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
  ((_IO_FILE *) stderr)->_flags2
    |= _IO_FLAGS2_NOTCANCEL;

  __fxprintf (NULL, "%s", buf);

  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
  _IO_funlockfile (stderr);

Both _IO_flockfile and _IO_funlockfile are expanded to nothing, so the flag manipulation constitutes a data race.

__malloc_stats in malloc/malloc.c is similarly afflicted.

A straight removal of _IO_MTSAFE_IO (treating it as always defined) shows that previously, nothing in glibc actually called the _IO_flockfile function. Apparently, the macro expansion provided in <include/libio.h> is always used in those cases where we compile with _IO_MTSAFE_IO defined.

Curiously, _IO_flockfile and _IO_funlockfile are only defined in libpthread.so, not in libc.so. But these implementations are slightly incompatible with the macro definitions in <include/libio.h> because they do not check _IO_USER_LOCK. (libpthread also provides the public names flockfile and funlockfile.)

How should we fix this?  Is the _IO_USER_LOCK check important?

I'm not sure if inlining _IO_flockfile is beneficial. It is a lot of code now: The _IO_USER_LOCK, the recursive mutex wrapper, and the low-level lock implementation (which itself contains a multiple-threads-check).

Florian


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]