mirror of git://sourceware.org/git/glibc.git
Update.
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:
parent
3fc9ca4e38
commit
dc3b5786d2
|
|
@ -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>
|
2000-06-04 Kaz Kylheku <kaz@ashi.footprints.net>
|
||||||
|
|
||||||
Lock for stdio stream list becomes global, for use in LinuxThreads.
|
Lock for stdio stream list becomes global, for use in LinuxThreads.
|
||||||
|
|
|
||||||
|
|
@ -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>
|
2000-06-04 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* sysdeps/sparc/sparc32/sparcv9/pspinlock.c (__pthread_spin_lock):
|
* sysdeps/sparc/sparc32/sparcv9/pspinlock.c (__pthread_spin_lock):
|
||||||
|
|
|
||||||
|
|
@ -418,6 +418,8 @@ void __pthread_reset_main_thread(void);
|
||||||
void __pthread_once_fork_prepare(void);
|
void __pthread_once_fork_prepare(void);
|
||||||
void __pthread_once_fork_parent(void);
|
void __pthread_once_fork_parent(void);
|
||||||
void __pthread_once_fork_child(void);
|
void __pthread_once_fork_child(void);
|
||||||
|
void __flockfilelist(void);
|
||||||
|
void __funlockfilelist(void);
|
||||||
void __fresetlockfiles(void);
|
void __fresetlockfiles(void);
|
||||||
void __pthread_manager_adjust_prio(int thread_prio);
|
void __pthread_manager_adjust_prio(int thread_prio);
|
||||||
void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif);
|
void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ use @var{errno}.
|
||||||
different threads.
|
different threads.
|
||||||
* Threads and Signal Handling:: Why you should avoid mixing the two, and
|
* Threads and Signal Handling:: Why you should avoid mixing the two, and
|
||||||
how to do it if you must.
|
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.
|
* Miscellaneous Thread Functions:: A grab bag of utility routines.
|
||||||
@end menu
|
@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
|
alternatively they should all block these signals (which is recommended
|
||||||
anyway).
|
anyway).
|
||||||
|
|
||||||
@node Miscellaneous Thread Functions
|
@node Threads and Fork
|
||||||
@section Miscellaneous Thread Functions
|
@section Threads and Fork
|
||||||
|
|
||||||
@comment pthread.h
|
It's not intuitively obvious what should happen when a multi-threaded POSIX
|
||||||
@comment POSIX
|
process calls @code{fork}. Not only are the semantics tricky, but you may
|
||||||
@deftypefun {pthread_t} pthread_self (@var{void})
|
need to write code that does the right thing at fork time even if that code
|
||||||
@code{pthread_self} returns the thread identifier for the calling thread.
|
doesn't use the @code{fork} function. Moreover, you need to be aware of
|
||||||
@end deftypefun
|
interaction between @code{fork} and some library features like
|
||||||
|
@code{pthread_once} and stdio streams.
|
||||||
|
|
||||||
@comment pthread.h
|
When @code{fork} is called by one of the threads of a process, it creates a new
|
||||||
@comment POSIX
|
process which is copy of the calling process. Effectively, in addition to
|
||||||
@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2)
|
copying certain system objects, the function takes a snapshot of the memory
|
||||||
@code{pthread_equal} determines if two thread identifiers refer to the same
|
areas of the parent process, and creates identical areas in the child.
|
||||||
thread.
|
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 child process has a copy of the address space of the parent, but it does
|
||||||
the same thread. Otherwise, 0 is returned.
|
not inherit any of its threads. Execution of the child process is carried out
|
||||||
@end deftypefun
|
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
|
Any program component which will continue being used in a child process must
|
||||||
@comment POSIX
|
correctly handle its state during @code{fork}. For this purpose, the POSIX
|
||||||
@deftypefun int pthread_detach (pthread_t @var{th})
|
interface provides the special function @code{pthread_atfork} for installing
|
||||||
@code{pthread_detach} puts the thread @var{th} in the detached
|
pointers to handler functions which are called from within @code{fork}.
|
||||||
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 pthread.h
|
||||||
@comment POSIX
|
@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
|
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
|
thread other than the thread calling @code{fork}, that mutex will remain
|
||||||
locked forever in the child process, possibly blocking the execution of
|
locked forever in the child process, possibly blocking the execution of
|
||||||
the child process. To avoid this, install handlers with
|
the child process. Or if some shared data, such as a linked list, was in the
|
||||||
@code{pthread_atfork} as follows: the @var{prepare} handler locks the
|
middle of being updated by a thread in the parent process, the child
|
||||||
global mutexes (in locking order), and the @var{parent} and @var{child}
|
will get a copy of the incompletely updated data which it cannot use.
|
||||||
handlers unlock them (in reverse order). Alternatively, @var{prepare}
|
|
||||||
and @var{parent} can be set to @code{NULL} and @var{child} to a function
|
To avoid this, install handlers with @code{pthread_atfork} as follows: have the
|
||||||
that calls @code{pthread_mutex_init} on the global mutexes.
|
@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 pthread.h
|
||||||
@comment GNU
|
@comment GNU
|
||||||
|
|
|
||||||
|
|
@ -68,20 +68,39 @@ strong_alias (__ftrylockfile, _IO_ftrylockfile)
|
||||||
#endif
|
#endif
|
||||||
weak_alias (__ftrylockfile, ftrylockfile);
|
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
|
void
|
||||||
__fresetlockfiles (void)
|
__fresetlockfiles (void)
|
||||||
{
|
{
|
||||||
#ifdef USE_IN_LIBIO
|
#ifdef USE_IN_LIBIO
|
||||||
|
_IO_ITER i;
|
||||||
|
|
||||||
_IO_FILE *fp;
|
_IO_FILE *fp;
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
|
|
||||||
__pthread_mutexattr_init (&attr);
|
__pthread_mutexattr_init (&attr);
|
||||||
__pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
__pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||||
|
|
||||||
for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
|
for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
|
||||||
__pthread_mutex_init (fp->_lock, &attr);
|
__pthread_mutex_init (_IO_iter_file(i)->_lock, &attr);
|
||||||
|
|
||||||
__pthread_mutexattr_destroy (&attr);
|
__pthread_mutexattr_destroy (&attr);
|
||||||
|
|
||||||
|
_IO_list_resetlock();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ pid_t __fork(void)
|
||||||
|
|
||||||
pthread_call_handlers(pthread_atfork_prepare);
|
pthread_call_handlers(pthread_atfork_prepare);
|
||||||
__pthread_once_fork_prepare();
|
__pthread_once_fork_prepare();
|
||||||
|
__flockfilelist();
|
||||||
|
|
||||||
pid = __libc_fork();
|
pid = __libc_fork();
|
||||||
|
|
||||||
|
|
@ -95,6 +96,7 @@ pid_t __fork(void)
|
||||||
|
|
||||||
pthread_mutex_init(&pthread_atfork_lock, NULL);
|
pthread_mutex_init(&pthread_atfork_lock, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
__funlockfilelist();
|
||||||
__pthread_once_fork_parent();
|
__pthread_once_fork_parent();
|
||||||
pthread_call_handlers(pthread_atfork_parent);
|
pthread_call_handlers(pthread_atfork_parent);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ static const char x86_cap_flags[][7] =
|
||||||
{
|
{
|
||||||
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
|
||||||
"cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov",
|
"cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov",
|
||||||
"pat", "pse36", "18", "19", "20", "21", "22", "mmx",
|
"pat", "pse36", "psn", "19", "20", "21", "22", "mmx",
|
||||||
"osfxsr", "25", "26", "27", "28", "29", "30", "amd3d"
|
"osfxsr", "xmm", "26", "27", "28", "29", "30", "amd3d"
|
||||||
};
|
};
|
||||||
#define _DL_HWCAP_COUNT 32
|
#define _DL_HWCAP_COUNT 32
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@ __attribute__ ((unused))
|
||||||
_dl_string_hwcap (const char *str)
|
_dl_string_hwcap (const char *str)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < _DL_HWCAP_COUNT; i++)
|
for (i = 0; i < _DL_HWCAP_COUNT; i++)
|
||||||
{
|
{
|
||||||
if (strcmp (str, x86_cap_flags[i]) == 0)
|
if (strcmp (str, x86_cap_flags[i]) == 0)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue