mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +00:00
Update.
* sysdeps/pthread/createthread.c (do_clone): If __ASSUME_CLONE_STOPPED is not defined, do explicit synchronization. (create_thread): Do not lock pd->lock here. If __ASSUME_CLONE_STOPPED is not defined also unlock pd->lock for non-debugging case in case it is necessary. * pthread_create.c (start_thread): Always get and release pd->lock if __ASSUME_CLONE_STOPPED is not defined. (start_thread_debug): Removed. Adjust users. * allocatestack.c (allocate_stack): Always initialize lock if __ASSUME_CLONE_STOPPED is not defined. * Makefile (tests): Add tst-sched1. * tst-sched1.c: New file.
This commit is contained in:
parent
0cbc6c4eba
commit
f1205aa71f
@ -1,5 +1,18 @@
|
||||
2003-08-02 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/pthread/createthread.c (do_clone): If __ASSUME_CLONE_STOPPED
|
||||
is not defined, do explicit synchronization.
|
||||
(create_thread): Do not lock pd->lock here. If __ASSUME_CLONE_STOPPED
|
||||
is not defined also unlock pd->lock for non-debugging case in case
|
||||
it is necessary.
|
||||
* pthread_create.c (start_thread): Always get and release pd->lock
|
||||
if __ASSUME_CLONE_STOPPED is not defined.
|
||||
(start_thread_debug): Removed. Adjust users.
|
||||
* allocatestack.c (allocate_stack): Always initialize lock if
|
||||
__ASSUME_CLONE_STOPPED is not defined.
|
||||
* Makefile (tests): Add tst-sched1.
|
||||
* tst-sched1.c: New file.
|
||||
|
||||
* sysdeps/pthread/createthread.c (do_clone): Only use
|
||||
sched_setschduler and pass correct parameters.
|
||||
|
||||
|
@ -231,7 +231,8 @@ tests = tst-attr1 tst-attr2 \
|
||||
tst-umask1 \
|
||||
tst-popen1 \
|
||||
tst-clock1 tst-clock2 \
|
||||
tst-context1
|
||||
tst-context1 \
|
||||
tst-sched1
|
||||
|
||||
distribute = eintr.c
|
||||
|
||||
|
@ -308,7 +308,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
/* The first TSD block is included in the TCB. */
|
||||
pd->specific[0] = pd->specific_1stblock;
|
||||
|
||||
#if LLL_LOCK_INITIALIZER != 0
|
||||
#if defined __ASSUME_CLONE_STOPPED && LLL_LOCK_INITIALIZER != 0
|
||||
/* Initialize the lock. */
|
||||
pd->lock = LLL_LOCK_INITIALIZER;
|
||||
#endif
|
||||
@ -451,7 +451,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
descriptor. */
|
||||
pd->specific[0] = pd->specific_1stblock;
|
||||
|
||||
#if LLL_LOCK_INITIALIZER != 0
|
||||
#if defined __ASSUME_CLONE_STOPPED && LLL_LOCK_INITIALIZER != 0
|
||||
/* Initialize the lock. */
|
||||
pd->lock = LLL_LOCK_INITIALIZER;
|
||||
#endif
|
||||
@ -564,6 +564,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __ASSUME_CLONE_STOPPED
|
||||
/* Initialize the lock. We have to do this unconditionally if the
|
||||
CLONE_STOPPED flag is not available since then the stillborn
|
||||
thread could be canceled while the lock is taken. */
|
||||
pd->lock = LLL_LOCK_INITIALIZER;
|
||||
#endif
|
||||
|
||||
/* We place the thread descriptor at the end of the stack. */
|
||||
*pdp = pd;
|
||||
|
||||
|
@ -33,8 +33,6 @@
|
||||
|
||||
/* Local function to start thread and handle cleanup. */
|
||||
static int start_thread (void *arg);
|
||||
/* Similar version used when debugging. */
|
||||
static int start_thread_debug (void *arg);
|
||||
|
||||
|
||||
/* Nozero if debugging mode is enabled. */
|
||||
@ -232,6 +230,13 @@ start_thread (void *arg)
|
||||
|
||||
struct pthread *pd = (struct pthread *) arg;
|
||||
|
||||
#ifndef __ASSUME_CLONE_STOPPED
|
||||
/* Get the lock the parent locked to force synchronization. */
|
||||
lll_lock (pd->lock);
|
||||
/* And give it up right away. */
|
||||
lll_unlock (pd->lock);
|
||||
#endif
|
||||
|
||||
#if HP_TIMING_AVAIL
|
||||
/* Remember the time when the thread was started. */
|
||||
hp_timing_t now;
|
||||
@ -331,23 +336,6 @@ start_thread (void *arg)
|
||||
}
|
||||
|
||||
|
||||
/* Just list start_thread but we do some more things needed for a run
|
||||
with a debugger attached. */
|
||||
static int
|
||||
start_thread_debug (void *arg)
|
||||
{
|
||||
struct pthread *pd = (struct pthread *) arg;
|
||||
|
||||
/* Get the lock the parent locked to force synchronization. */
|
||||
lll_lock (pd->lock);
|
||||
/* And give it up right away. */
|
||||
lll_unlock (pd->lock);
|
||||
|
||||
/* Now do the actual startup. */
|
||||
return start_thread (arg);
|
||||
}
|
||||
|
||||
|
||||
/* Default thread attributes for the case when the user does not
|
||||
provide any. */
|
||||
static const struct pthread_attr default_attr =
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <ldsodefs.h>
|
||||
#include <tls.h>
|
||||
|
||||
#include "kernel-features.h"
|
||||
|
||||
|
||||
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
|
||||
|
||||
@ -55,7 +57,20 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
|
||||
PREPARE_CREATE;
|
||||
#endif
|
||||
|
||||
if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
|
||||
/* Lame old kernels do not have CLONE_STOPPED support. For those do
|
||||
not pass the flag, not instead use the futex method. */
|
||||
#ifndef __ASSUME_CLONE_STOPPED
|
||||
# define final_clone_flags clone_flags & ~CLONE_STOPPED
|
||||
if (clone_flags & CLONE_STOPPED)
|
||||
/* We Make sure the thread does not run far by forcing it to get a
|
||||
lock. We lock it here too so that the new thread cannot continue
|
||||
until we tell it to. */
|
||||
lll_lock (pd->lock);
|
||||
#else
|
||||
# define final_clone_flags clone_flags
|
||||
#endif
|
||||
|
||||
if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, final_clone_flags,
|
||||
pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
|
||||
/* Failed. */
|
||||
return errno;
|
||||
@ -86,8 +101,10 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
#ifdef __ASSUME_CLONE_STOPPED
|
||||
/* Now start the thread for real. */
|
||||
res = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCONT);
|
||||
#endif
|
||||
|
||||
/* If something went wrong, kill the thread. */
|
||||
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
|
||||
@ -98,8 +115,10 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
|
||||
err_out:
|
||||
(void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL);
|
||||
|
||||
#ifdef __ASSUME_CLONE_STOPPED
|
||||
/* Then wake it up so that the signal can be processed. */
|
||||
(void) INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCONT);
|
||||
(void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCONT);
|
||||
#endif
|
||||
|
||||
return INTERNAL_SYSCALL_ERRNO (res, err);
|
||||
}
|
||||
@ -175,15 +194,10 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
|
||||
if ((_mask & (__nptl_threads_events.event_bits[_idx]
|
||||
| pd->eventbuf.eventmask.event_bits[_idx])) != 0)
|
||||
{
|
||||
/* We have to report the new thread. Make sure the thread
|
||||
does not run far by forcing it to get a lock. We lock it
|
||||
here too so that the new thread cannot continue until we
|
||||
tell it to. */
|
||||
lll_lock (pd->lock);
|
||||
|
||||
/* Create the thread. */
|
||||
int res = do_clone (pd, attr, clone_flags, start_thread_debug,
|
||||
STACK_VARIABLES_ARGS);
|
||||
/* Create the thread. We always create the thread stopped
|
||||
so that it does not get far before we tell the debugger. */
|
||||
int res = do_clone (pd, attr, clone_flags | CLONE_STOPPED,
|
||||
start_thread, STACK_VARIABLES_ARGS);
|
||||
if (res == 0)
|
||||
{
|
||||
/* Now fill in the information about the new thread in
|
||||
@ -216,5 +230,16 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
|
||||
#endif
|
||||
|
||||
/* Actually create the thread. */
|
||||
return do_clone (pd, attr, clone_flags, start_thread, STACK_VARIABLES_ARGS);
|
||||
int res = do_clone (pd, attr, clone_flags, start_thread,
|
||||
STACK_VARIABLES_ARGS);
|
||||
|
||||
#ifndef __ASSUME_CLONE_STOPPED
|
||||
if (res == 0 && (clone_flags & CLONE_STOPPED))
|
||||
{
|
||||
/* And finally restart the new thread. */
|
||||
lll_unlock (pd->lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
98
nptl/tst-sched1.c
Normal file
98
nptl/tst-sched1.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
static int global;
|
||||
|
||||
static void *
|
||||
tf (void *a)
|
||||
{
|
||||
global = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t th;
|
||||
pthread_attr_t at;
|
||||
|
||||
if (pthread_attr_init (&at) != 0)
|
||||
{
|
||||
puts ("attr_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_attr_setschedpolicy (&at, SCHED_OTHER) != 0)
|
||||
{
|
||||
puts ("attr_setschedpolicy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct sched_param pa;
|
||||
if (sched_getparam (getpid (), &pa) != 0)
|
||||
{
|
||||
puts ("sched_getschedparam failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_attr_setschedparam (&at, &pa) != 0)
|
||||
{
|
||||
puts ("attr_setschedparam failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_attr_setinheritsched (&at, PTHREAD_EXPLICIT_SCHED) != 0)
|
||||
{
|
||||
puts ("attr_setinheritsched failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_create (&th, &at, tf, NULL) != 0)
|
||||
{
|
||||
puts ("create failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int e = pthread_join (th, NULL);
|
||||
if (e != 0)
|
||||
{
|
||||
printf ("join failed: %d\n", e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (global == 0)
|
||||
{
|
||||
puts ("thread didn't run");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
Loading…
Reference in New Issue
Block a user