mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-05 21:00:05 +00:00
Update.
2000-05-07 H.J. Lu <hjl@gnu.org> * csu/initfini.c: Moved to .... * sysdeps/generic/initfini.c: ...here. * csu/Makefile (initfini.c): Set vpath to $(full_config_sysdirs).
This commit is contained in:
parent
639c6286de
commit
93414bb97c
@ -1,3 +1,10 @@
|
||||
2000-05-07 H.J. Lu <hjl@gnu.org>
|
||||
|
||||
* csu/initfini.c: Moved to ....
|
||||
* sysdeps/generic/initfini.c: ...here.
|
||||
|
||||
* csu/Makefile (initfini.c): Set vpath to $(full_config_sysdirs).
|
||||
|
||||
2000-05-07 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* manual/resource.texi: Document POSIX scheduling functions.
|
||||
|
@ -85,6 +85,8 @@ $(objpfx)crt%.o: $(objpfx)crt%.S $(objpfx)defs.h
|
||||
|
||||
CFLAGS-initfini.s = -g0 -fPIC -fno-inline-functions
|
||||
|
||||
vpath initfini.c $(full_config_sysdirs)
|
||||
|
||||
$(objpfx)initfini.s: initfini.c
|
||||
$(compile.c) -S $(CFLAGS-initfini.s) -finhibit-size-directive \
|
||||
$(patsubst -f%,-fno-%,$(exceptions)) -o $@
|
||||
|
@ -1,3 +1,21 @@
|
||||
2000-05-06 Kaz Kylheku <kaz@ashi.footprints.net>
|
||||
|
||||
* mutex.c (pthread_once): IN_PROGRESS state of pthread_once_t
|
||||
object state is represented with additional bits which distinguish
|
||||
whether that state was set up in the current process, or
|
||||
in an ancestor process. If that state was set in an ancestor,
|
||||
it means that a fork happened while thread was executing the init
|
||||
function. In that case, the state is reset to NEVER.
|
||||
* mutex.c (__pthread_once_fork_prepare): New function.
|
||||
(__pthread_once_fork_child): Likewise
|
||||
(__pthread_once_fork_parent): Likewise
|
||||
(__pthread_reset_pthread_once): Removed.
|
||||
* ptfork.c (__fork): Call new handlers in mutex.c.
|
||||
* internals.h: Declarations of new mutex.c functions added.
|
||||
Declaration of removed function deleted.
|
||||
* linuxthreads.texi: Updated documentation about pthread_once
|
||||
to clarify what happens under cancellation and forking.
|
||||
|
||||
2000-05-06 Kaz Kylheku <kaz@ashi.footprints.net>
|
||||
|
||||
* internals.h: New thread manager request type, REQ_KICK.
|
||||
|
@ -414,7 +414,9 @@ int __pthread_manager(void *reqfd);
|
||||
int __pthread_manager_event(void *reqfd);
|
||||
void __pthread_manager_sighandler(int sig);
|
||||
void __pthread_reset_main_thread(void);
|
||||
void __pthread_reset_pthread_once(void);
|
||||
void __pthread_once_fork_prepare(void);
|
||||
void __pthread_once_fork_parent(void);
|
||||
void __pthread_once_fork_child(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);
|
||||
|
@ -1368,6 +1368,15 @@ record that initialization has been performed. Subsequent calls to
|
||||
@code{pthread_once} with the same @code{once_control} argument do
|
||||
nothing.
|
||||
|
||||
If a thread is cancelled while executing @var{init_routine}
|
||||
the state of the @var{once_control} variable is reset so that
|
||||
a future call to @code{pthread_once} will call the routine again.
|
||||
|
||||
If the process forks while one or more threads are executing
|
||||
@code{pthread_once} initialization routines, the states of their respective
|
||||
@var{once_control} variables will appear to be reset in the child process so
|
||||
that if the child calls @code{pthread_once}, the routines will be executed.
|
||||
|
||||
@code{pthread_once} always returns 0.
|
||||
@end deftypefun
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include "pthread.h"
|
||||
#include "internals.h"
|
||||
#include "spinlock.h"
|
||||
@ -170,6 +171,7 @@ weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np)
|
||||
|
||||
static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER;
|
||||
static int fork_generation = 0; /* Child process increments this after fork. */
|
||||
|
||||
enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 };
|
||||
|
||||
@ -199,14 +201,20 @@ int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
|
||||
state_changed = 0;
|
||||
|
||||
pthread_mutex_lock(&once_masterlock);
|
||||
|
||||
/* If this object was left in an IN_PROGRESS state in a parent
|
||||
process (indicated by stale generation field), reset it to NEVER. */
|
||||
if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation)
|
||||
*once_control = NEVER;
|
||||
|
||||
/* If init_routine is being called from another routine, wait until
|
||||
it completes. */
|
||||
while (*once_control == IN_PROGRESS) {
|
||||
while ((*once_control & 3) == IN_PROGRESS) {
|
||||
pthread_cond_wait(&once_finished, &once_masterlock);
|
||||
}
|
||||
/* Here *once_control is stable and either NEVER or DONE. */
|
||||
if (*once_control == NEVER) {
|
||||
*once_control = IN_PROGRESS;
|
||||
*once_control = IN_PROGRESS | fork_generation;
|
||||
pthread_mutex_unlock(&once_masterlock);
|
||||
pthread_cleanup_push(pthread_once_cancelhandler, once_control);
|
||||
init_routine();
|
||||
@ -225,13 +233,31 @@ int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
|
||||
strong_alias (__pthread_once, pthread_once)
|
||||
|
||||
/*
|
||||
* This is called in the child process after a fork to make
|
||||
* sure that the global mutex pthread_once is not held,
|
||||
* and that the condition variable is reset to an initial state.
|
||||
* Handle the state of the pthread_once mechanism across forks. The
|
||||
* once_masterlock is acquired in the parent process prior to a fork to ensure
|
||||
* that no thread is in the critical region protected by the lock. After the
|
||||
* fork, the lock is released. In the child, the lock and the condition
|
||||
* variable are simply reset. The child also increments its generation
|
||||
* counter which lets pthread_once calls detect stale IN_PROGRESS states
|
||||
* and reset them back to NEVER.
|
||||
*/
|
||||
|
||||
void __pthread_reset_pthread_once(void)
|
||||
void __pthread_once_fork_prepare(void)
|
||||
{
|
||||
pthread_mutex_lock(&once_masterlock);
|
||||
}
|
||||
|
||||
void __pthread_once_fork_parent(void)
|
||||
{
|
||||
pthread_mutex_unlock(&once_masterlock);
|
||||
}
|
||||
|
||||
void __pthread_once_fork_child(void)
|
||||
{
|
||||
pthread_mutex_init(&once_masterlock, NULL);
|
||||
pthread_cond_init(&once_finished, NULL);
|
||||
if (fork_generation <= INT_MAX - 4)
|
||||
fork_generation += 4; /* leave least significant two bits zero */
|
||||
else
|
||||
fork_generation = 0;
|
||||
}
|
||||
|
@ -86,14 +86,16 @@ pid_t __fork(void)
|
||||
parent = pthread_atfork_parent;
|
||||
pthread_mutex_unlock(&pthread_atfork_lock);
|
||||
pthread_call_handlers(prepare);
|
||||
__pthread_once_fork_prepare();
|
||||
pid = __libc_fork();
|
||||
if (pid == 0) {
|
||||
__pthread_reset_main_thread();
|
||||
__pthread_reset_pthread_once();
|
||||
__fresetlockfiles();
|
||||
pthread_call_handlers(child);
|
||||
__pthread_once_fork_child();
|
||||
} else {
|
||||
pthread_call_handlers(parent);
|
||||
__pthread_once_fork_parent();
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user