2000-06-07  Ulrich Drepper  <drepper@redhat.com>

	* sysdeps/unix/sysv/linux/i386/dl-procinfo.h (x86_cap_flags):
	Update.
This commit is contained in:
Ulrich Drepper 2000-06-07 23:43:59 +00:00
parent 3fc9ca4e38
commit dc3b5786d2
7 changed files with 190 additions and 55 deletions

View File

@ -1,3 +1,8 @@
2000-06-07 Ulrich Drepper <drepper@redhat.com>
* sysdeps/unix/sysv/linux/i386/dl-procinfo.h (x86_cap_flags):
Update.
2000-06-04 Kaz Kylheku <kaz@ashi.footprints.net>
Lock for stdio stream list becomes global, for use in LinuxThreads.

View File

@ -1,3 +1,26 @@
2000-06-04 Kaz Kylheku <kaz@ashi.footprints.net>
Added missing fork time handling of global libio lock.
* lockfile.c (__fresetlockfiles): Now also resets the list lock,
not just the individual stream locks. Rewritten to use new
iterator interface provided by libio rather than accessing
global variable.
* lockfile.c (__flockfilelist, _funlockfilelist): New functions
which lock and unlock the stream list using the new interface
provied by libio.
* internals.h: Likewise.
* ptfork.c (__fork): Now calls __flockfilelist before fork,
and __funlockfilelist in the parent after the fork.
Child still calls __fresetlockfiles as before.
* linuxthreads.texi: Now explains what happens to streams at
fork time. Also whole new section on forking and thread added.
Definition of pthread_atfork moved out of Miscellaneous Functions
to this new section.
2000-06-04 Jakub Jelinek <jakub@redhat.com>
* sysdeps/sparc/sparc32/sparcv9/pspinlock.c (__pthread_spin_lock):

View File

@ -418,6 +418,8 @@ void __pthread_reset_main_thread(void);
void __pthread_once_fork_prepare(void);
void __pthread_once_fork_parent(void);
void __pthread_once_fork_child(void);
void __flockfilelist(void);
void __funlockfilelist(void);
void __fresetlockfiles(void);
void __pthread_manager_adjust_prio(int thread_prio);
void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif);

View File

@ -27,6 +27,10 @@ use @var{errno}.
different threads.
* Threads and Signal Handling:: Why you should avoid mixing the two, and
how to do it if you must.
* Threads and Fork:: Interactions between threads and the
@code{fork} function.
* Streams and Fork:: Interactions between stdio streams and
@code{fork}.
* Miscellaneous Thread Functions:: A grab bag of utility routines.
@end menu
@ -1237,54 +1241,37 @@ threads must not attach their own signal handlers to these signals, or
alternatively they should all block these signals (which is recommended
anyway).
@node Miscellaneous Thread Functions
@section Miscellaneous Thread Functions
@node Threads and Fork
@section Threads and Fork
@comment pthread.h
@comment POSIX
@deftypefun {pthread_t} pthread_self (@var{void})
@code{pthread_self} returns the thread identifier for the calling thread.
@end deftypefun
It's not intuitively obvious what should happen when a multi-threaded POSIX
process calls @code{fork}. Not only are the semantics tricky, but you may
need to write code that does the right thing at fork time even if that code
doesn't use the @code{fork} function. Moreover, you need to be aware of
interaction between @code{fork} and some library features like
@code{pthread_once} and stdio streams.
@comment pthread.h
@comment POSIX
@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2)
@code{pthread_equal} determines if two thread identifiers refer to the same
thread.
When @code{fork} is called by one of the threads of a process, it creates a new
process which is copy of the calling process. Effectively, in addition to
copying certain system objects, the function takes a snapshot of the memory
areas of the parent process, and creates identical areas in the child.
To make matters more complicated, with threads it's possible for two or more
threads to concurrently call fork to create two or more child processes.
A non-zero value is returned if @var{thread1} and @var{thread2} refer to
the same thread. Otherwise, 0 is returned.
@end deftypefun
The child process has a copy of the address space of the parent, but it does
not inherit any of its threads. Execution of the child process is carried out
by a new thread which returns from @code{fork} function with a return value of
zero; it is the only thread in the child process. Because threads are not
inherited across fork, issues arise. At the time of the call to @code{fork},
threads in the parent process other than the one calling @code{fork} may have
been executing critical regions of code. As a result, the child process may
get a copy of objects that are not in a well-defined state. This potential
problem affects all components of the program.
@comment pthread.h
@comment POSIX
@deftypefun int pthread_detach (pthread_t @var{th})
@code{pthread_detach} puts the thread @var{th} in the detached
state. This guarantees that the memory resources consumed by @var{th}
will be freed immediately when @var{th} terminates. However, this
prevents other threads from synchronizing on the termination of @var{th}
using @code{pthread_join}.
A thread can be created initially in the detached state, using the
@code{detachstate} attribute to @code{pthread_create}. In contrast,
@code{pthread_detach} applies to threads created in the joinable state,
and which need to be put in the detached state later.
After @code{pthread_detach} completes, subsequent attempts to perform
@code{pthread_join} on @var{th} will fail. If another thread is already
joining the thread @var{th} at the time @code{pthread_detach} is called,
@code{pthread_detach} does nothing and leaves @var{th} in the joinable
state.
On success, 0 is returned. On error, one of the following codes is
returned:
@table @code
@item ESRCH
No thread could be found corresponding to that specified by @var{th}
@item EINVAL
The thread @var{th} is already in the detached state
@end table
@end deftypefun
Any program component which will continue being used in a child process must
correctly handle its state during @code{fork}. For this purpose, the POSIX
interface provides the special function @code{pthread_atfork} for installing
pointers to handler functions which are called from within @code{fork}.
@comment pthread.h
@comment POSIX
@ -1336,12 +1323,109 @@ their current locking state, but only the calling thread: other threads
are not running in the child process. Thus, if a mutex is locked by a
thread other than the thread calling @code{fork}, that mutex will remain
locked forever in the child process, possibly blocking the execution of
the child process. To avoid this, install handlers with
@code{pthread_atfork} as follows: the @var{prepare} handler locks the
global mutexes (in locking order), and the @var{parent} and @var{child}
handlers unlock them (in reverse order). Alternatively, @var{prepare}
and @var{parent} can be set to @code{NULL} and @var{child} to a function
that calls @code{pthread_mutex_init} on the global mutexes.
the child process. Or if some shared data, such as a linked list, was in the
middle of being updated by a thread in the parent process, the child
will get a copy of the incompletely updated data which it cannot use.
To avoid this, install handlers with @code{pthread_atfork} as follows: have the
@var{prepare} handler lock the mutexes (in locking order), and the
@var{parent} handler unlock the mutexes. The @var{child} handler should reset
the mutexes using @code{pthread_mutex_init}, as well as any other
synchronization objects such as condition variables.
Locking the global mutexes before the fork ensures that all other threads are
locked out of the critical regions of code protected by those mutexes. Thus
when @code{fork} takes a snapshot of the parent's address space, that snapshot
will copy valid, stable data. Resetting the synchronization objects in the
child process will ensure they are properly cleansed of any artifacts from the
threading subsystem of the parent process. For example, a mutex may inherit
a wait queue of threads waiting for the lock; this wait queue makes no sense
in the child process. Initializing the mutex takes care of this.
@node Streams and Fork
@section Streams and Fork
The GNU standard I/O library has an internal mutex which guards the internal
linked list of all standard C FILE objects. This mutex is properly taken care
of during @code{fork} so that the child receives an intact copy of the list.
This allows the @code{fopen} function, and related stream-creating functions,
to work correctly in the child process, since these functions need to insert
into the list.
However, the individual stream locks are not completely taken care of. Thus
unless the multithreaded application takes special precautions in its use of
@code{fork}, the child process might not be able to safely use the streams that
it inherited from the parent. In general, for any given open stream in the
parent that is to be used by the child process, the application must ensure
that that stream is not in use by another thread when @code{fork} is called.
Otherwise an inconsistent copy of the stream object be produced. An easy way to
ensure this is to use @code{flockfile} to lock the stream prior to calling
@code{fork} and then unlock it with @code{funlockfile} inside the parent
process, provided that the parent's threads properly honor these locks.
Nothing special needs to be done in the child process, since the library
internally resets all stream locks.
Note that the stream locks are not shared between the parent and child.
For example, even if you ensure that, say, the stream @code{stdout} is properly
treated and can be safely used in the child, the stream locks do not provide
an exclusion mechanism between the parent and child. If both processes write
to @code{stdout}, strangely interleaved output may result regardless of
the explicit use of @code{flockfile} or implicit locks.
Also note that these provisions are a GNU extension; other systems might not
provide any way for streams to be used in the child of a multithreaded process.
POSIX requires that such a child process confines itself to calling only
asynchronous safe functions, which excludes much of the library, including
standard I/O.
@node Miscellaneous Thread Functions
@section Miscellaneous Thread Functions
@comment pthread.h
@comment POSIX
@deftypefun {pthread_t} pthread_self (@var{void})
@code{pthread_self} returns the thread identifier for the calling thread.
@end deftypefun
@comment pthread.h
@comment POSIX
@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2)
@code{pthread_equal} determines if two thread identifiers refer to the same
thread.
A non-zero value is returned if @var{thread1} and @var{thread2} refer to
the same thread. Otherwise, 0 is returned.
@end deftypefun
@comment pthread.h
@comment POSIX
@deftypefun int pthread_detach (pthread_t @var{th})
@code{pthread_detach} puts the thread @var{th} in the detached
state. This guarantees that the memory resources consumed by @var{th}
will be freed immediately when @var{th} terminates. However, this
prevents other threads from synchronizing on the termination of @var{th}
using @code{pthread_join}.
A thread can be created initially in the detached state, using the
@code{detachstate} attribute to @code{pthread_create}. In contrast,
@code{pthread_detach} applies to threads created in the joinable state,
and which need to be put in the detached state later.
After @code{pthread_detach} completes, subsequent attempts to perform
@code{pthread_join} on @var{th} will fail. If another thread is already
joining the thread @var{th} at the time @code{pthread_detach} is called,
@code{pthread_detach} does nothing and leaves @var{th} in the joinable
state.
On success, 0 is returned. On error, one of the following codes is
returned:
@table @code
@item ESRCH
No thread could be found corresponding to that specified by @var{th}
@item EINVAL
The thread @var{th} is already in the detached state
@end table
@end deftypefun
@comment pthread.h
@comment GNU

View File

@ -68,20 +68,39 @@ strong_alias (__ftrylockfile, _IO_ftrylockfile)
#endif
weak_alias (__ftrylockfile, ftrylockfile);
void
__flockfilelist(void)
{
#ifdef USE_IN_LIBIO
_IO_list_lock();
#endif
}
void
__funlockfilelist(void)
{
#ifdef USE_IN_LIBIO
_IO_list_unlock();
#endif
}
void
__fresetlockfiles (void)
{
#ifdef USE_IN_LIBIO
_IO_ITER i;
_IO_FILE *fp;
pthread_mutexattr_t attr;
__pthread_mutexattr_init (&attr);
__pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
__pthread_mutex_init (fp->_lock, &attr);
for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
__pthread_mutex_init (_IO_iter_file(i)->_lock, &attr);
__pthread_mutexattr_destroy (&attr);
_IO_list_resetlock();
#endif
}

View File

@ -83,6 +83,7 @@ pid_t __fork(void)
pthread_call_handlers(pthread_atfork_prepare);
__pthread_once_fork_prepare();
__flockfilelist();
pid = __libc_fork();
@ -95,6 +96,7 @@ pid_t __fork(void)
pthread_mutex_init(&pthread_atfork_lock, NULL);
} else {
__funlockfilelist();
__pthread_once_fork_parent();
pthread_call_handlers(pthread_atfork_parent);

View File

@ -27,8 +27,8 @@ static const char x86_cap_flags[][7] =
{
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov",
"pat", "pse36", "18", "19", "20", "21", "22", "mmx",
"osfxsr", "25", "26", "27", "28", "29", "30", "amd3d"
"pat", "pse36", "psn", "19", "20", "21", "22", "mmx",
"osfxsr", "xmm", "26", "27", "28", "29", "30", "amd3d"
};
#define _DL_HWCAP_COUNT 32
@ -89,7 +89,7 @@ __attribute__ ((unused))
_dl_string_hwcap (const char *str)
{
int i;
for (i = 0; i < _DL_HWCAP_COUNT; i++)
{
if (strcmp (str, x86_cap_flags[i]) == 0)