mirror of
git://sourceware.org/git/glibc.git
synced 2025-01-18 12:16:13 +08:00
Update.
1998-03-13 00:46 Ulrich Drepper <drepper@cygnus.com> * attr.c: Implement pthread_attr_[gs]etguardsize, pthread_attr_[gs]setstackaddr, pthread_attr_[gs]etstacksize. Change pthread_attr_init to have two interfaces. * internals.h (struct _pthread_descr_struct): Add new fields for above functions. * libpthread.map: Add names in GLIBC_2.1 section. * manager.c (pthread_handle_create): Implement guardsize and user stack. (pthread_free): Likewise. * pthread.c (pthread_create): Add new interface for changed pthread_attr_t. * sysdeps/pthread/pthread.h: Add prototypes for new functions. * sysdeps/unix/sysv/linux/bits/local_lim.h: Add definition of PTHREAD_STACK_MIN. * manager.c: Enable resetting of the thread scheduling policy to SCHED_OTHER when the parent thread has a different one.
This commit is contained in:
parent
441e41325e
commit
5d409851a3
@ -1,8 +1,24 @@
|
|||||||
|
1998-03-13 00:46 Ulrich Drepper <drepper@cygnus.com>
|
||||||
|
|
||||||
|
* attr.c: Implement pthread_attr_[gs]etguardsize,
|
||||||
|
pthread_attr_[gs]setstackaddr, pthread_attr_[gs]etstacksize.
|
||||||
|
Change pthread_attr_init to have two interfaces.
|
||||||
|
* internals.h (struct _pthread_descr_struct): Add new fields for
|
||||||
|
above functions.
|
||||||
|
* libpthread.map: Add names in GLIBC_2.1 section.
|
||||||
|
* manager.c (pthread_handle_create): Implement guardsize and
|
||||||
|
user stack.
|
||||||
|
(pthread_free): Likewise.
|
||||||
|
* pthread.c (pthread_create): Add new interface for changed
|
||||||
|
pthread_attr_t.
|
||||||
|
* sysdeps/pthread/pthread.h: Add prototypes for new functions.
|
||||||
|
* sysdeps/unix/sysv/linux/bits/local_lim.h: Add definition of
|
||||||
|
PTHREAD_STACK_MIN.
|
||||||
|
|
||||||
1998-03-11 00:42 Wolfram Gloger <wmglo@dent.med.uni-muenchen.de>
|
1998-03-11 00:42 Wolfram Gloger <wmglo@dent.med.uni-muenchen.de>
|
||||||
|
|
||||||
* linuxthreads/manager.c: Enable resetting of the thread
|
* manager.c: Enable resetting of the thread scheduling policy
|
||||||
scheduling policy to SCHED_OTHER when the parent thread
|
to SCHED_OTHER when the parent thread has a different one.
|
||||||
has a different one.
|
|
||||||
|
|
||||||
1998-02-01 13:51 Ulrich Drepper <drepper@cygnus.com>
|
1998-02-01 13:51 Ulrich Drepper <drepper@cygnus.com>
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ STATUS:
|
|||||||
- libc 6 (glibc 2) provides much better thread support than libc 5,
|
- libc 6 (glibc 2) provides much better thread support than libc 5,
|
||||||
and comes with a specially-adapted version of LinuxThreads.
|
and comes with a specially-adapted version of LinuxThreads.
|
||||||
For serious multithreaded programming, you should consider switching
|
For serious multithreaded programming, you should consider switching
|
||||||
to glibc 2. It is available from prep.ai.mit.edu:/pub/gnu and its mirrors.
|
to glibc 2. It is available from ftp.gnu.org:/pub/gnu and its mirrors.
|
||||||
|
|
||||||
|
|
||||||
WARNING:
|
WARNING:
|
||||||
@ -107,6 +107,9 @@ KNOWN BUGS AND LIMITATIONS:
|
|||||||
threads blocked on mutexes or conditions; the other is for thread
|
threads blocked on mutexes or conditions; the other is for thread
|
||||||
cancellation.
|
cancellation.
|
||||||
|
|
||||||
|
*** This is not anymore true when the application runs on a kernel
|
||||||
|
newer than approximately 2.1.60.
|
||||||
|
|
||||||
- The stacks for the threads are allocated high in the memory space,
|
- The stacks for the threads are allocated high in the memory space,
|
||||||
below the stack of the initial process, and spaced 2M apart.
|
below the stack of the initial process, and spaced 2M apart.
|
||||||
Stacks are allocated with the "grow on demand" flag, so they don't
|
Stacks are allocated with the "grow on demand" flag, so they don't
|
||||||
|
@ -15,10 +15,30 @@
|
|||||||
/* Handling of thread attributes */
|
/* Handling of thread attributes */
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include "pthread.h"
|
#include "pthread.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
|
|
||||||
int pthread_attr_init(pthread_attr_t *attr)
|
|
||||||
|
int __pthread_attr_init_2_1(pthread_attr_t *attr)
|
||||||
|
{
|
||||||
|
size_t ps = __getpagesize ();
|
||||||
|
|
||||||
|
attr->detachstate = PTHREAD_CREATE_JOINABLE;
|
||||||
|
attr->schedpolicy = SCHED_OTHER;
|
||||||
|
attr->schedparam.sched_priority = 0;
|
||||||
|
attr->inheritsched = PTHREAD_EXPLICIT_SCHED;
|
||||||
|
attr->scope = PTHREAD_SCOPE_SYSTEM;
|
||||||
|
attr->guardsize = ps;
|
||||||
|
attr->stackaddr = NULL;
|
||||||
|
attr->stackaddr_set = 0;
|
||||||
|
attr->stacksize = STACK_SIZE - ps;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#if defined HAVE_ELF && defined PIC && defined DO_VERSIONING
|
||||||
|
default_symbol_version (__pthread_attr_init_2_1, pthread_attr_init, GLIBC_2.1);
|
||||||
|
|
||||||
|
int __pthread_attr_init_2_0(pthread_attr_t *attr)
|
||||||
{
|
{
|
||||||
attr->detachstate = PTHREAD_CREATE_JOINABLE;
|
attr->detachstate = PTHREAD_CREATE_JOINABLE;
|
||||||
attr->schedpolicy = SCHED_OTHER;
|
attr->schedpolicy = SCHED_OTHER;
|
||||||
@ -27,6 +47,10 @@ int pthread_attr_init(pthread_attr_t *attr)
|
|||||||
attr->scope = PTHREAD_SCOPE_SYSTEM;
|
attr->scope = PTHREAD_SCOPE_SYSTEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
symbol_version (__pthread_attr_init_2_0, pthread_attr_init, GLIBC_2.0);
|
||||||
|
#else
|
||||||
|
strong_alias (__pthread_attr_init_2_1, pthread_attr_init)
|
||||||
|
#endif
|
||||||
|
|
||||||
int pthread_attr_destroy(pthread_attr_t *attr)
|
int pthread_attr_destroy(pthread_attr_t *attr)
|
||||||
{
|
{
|
||||||
@ -115,3 +139,67 @@ int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
|
|||||||
*scope = attr->scope;
|
*scope = attr->scope;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
|
||||||
|
{
|
||||||
|
size_t ps = __getpagesize ();
|
||||||
|
|
||||||
|
/* First round up the guard size. */
|
||||||
|
guardsize = roundup (guardsize, ps);
|
||||||
|
|
||||||
|
/* The current implementation of LinuxThreads allocates 2MB stack space
|
||||||
|
for each thread. So the maximum guardsize is 2MB - pagesize. */
|
||||||
|
if (guardsize >= STACK_SIZE - ps)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
attr->guardsize = guardsize;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
|
||||||
|
|
||||||
|
int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
|
||||||
|
{
|
||||||
|
*guardsize = attr->guardsize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
|
||||||
|
|
||||||
|
int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
|
||||||
|
{
|
||||||
|
attr->stackaddr = stackaddr;
|
||||||
|
attr->stackaddr_set = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
|
||||||
|
|
||||||
|
int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
|
||||||
|
{
|
||||||
|
/* XXX This function has a stupid definition. The standard specifies
|
||||||
|
no error value but what is if no stack address was set? We simply
|
||||||
|
return the value we have in the member. */
|
||||||
|
*stackaddr = attr->stackaddr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_attr_getstackaddr, pthread_attr_etstackaddr)
|
||||||
|
|
||||||
|
int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
|
||||||
|
{
|
||||||
|
size_t ps = __getpagesize ();
|
||||||
|
|
||||||
|
/* We don't accept value smaller than PTHREAD_STACK_MIN or bigger than
|
||||||
|
2MB - pagesize. */
|
||||||
|
if (stacksize < PTHREAD_STACK_MIN || stacksize > STACK_SIZE - ps)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
attr->stacksize = stacksize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
|
||||||
|
|
||||||
|
int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
|
||||||
|
{
|
||||||
|
*stacksize = attr->stacksize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
|
||||||
|
@ -84,6 +84,9 @@ struct _pthread_descr_struct {
|
|||||||
struct pthread_start_args p_start_args; /* arguments for thread creation */
|
struct pthread_start_args p_start_args; /* arguments for thread creation */
|
||||||
void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
|
void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
|
||||||
void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
|
void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */
|
||||||
|
int p_userstack; /* nonzero if the user provided the thread */
|
||||||
|
void *p_guardaddr; /* address of guard area or NULL */
|
||||||
|
size_t p_guardsize; /* size of guard area */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The type of thread handles. */
|
/* The type of thread handles. */
|
||||||
|
@ -53,10 +53,19 @@ GLIBC_2.0 {
|
|||||||
|
|
||||||
GLIBC_2.1 {
|
GLIBC_2.1 {
|
||||||
global:
|
global:
|
||||||
|
# Functions with changed interface.
|
||||||
|
pthread_attr_init; pthread_create;
|
||||||
|
|
||||||
# Unix98 extensions.
|
# Unix98 extensions.
|
||||||
pthread_rwlock_init; pthread_rwlock_destroy; pthread_rwlock_rdlock;
|
pthread_rwlock_init; pthread_rwlock_destroy; pthread_rwlock_rdlock;
|
||||||
pthread_rwlock_tryrdlock; pthread_rwlock_wrlock; pthread_rwlock_trywrlock;
|
pthread_rwlock_tryrdlock; pthread_rwlock_wrlock; pthread_rwlock_trywrlock;
|
||||||
pthread_rwlock_unlock; pthread_rwlockattr_init; pthread_rwlockattr_destroy;
|
pthread_rwlock_unlock; pthread_rwlockattr_init; pthread_rwlockattr_destroy;
|
||||||
pthread_rwlockattr_getpshared; pthread_rwlockattr_setpshared;
|
pthread_rwlockattr_getpshared; pthread_rwlockattr_setpshared;
|
||||||
pthread_rwlockattr_getkind_np; pthread_rwlockattr_setkind_np;
|
pthread_rwlockattr_getkind_np; pthread_rwlockattr_setkind_np;
|
||||||
|
|
||||||
|
pthread_attr_getguardsize; pthread_attr_setguardsize;
|
||||||
|
pthread_attr_getstackaddr; pthread_attr_setstackaddr;
|
||||||
|
pthread_attr_getstacksize; pthread_attr_setstacksize;
|
||||||
|
|
||||||
|
pthread_getconcurrency; pthread_setconcurrency;
|
||||||
} GLIBC_2.0;
|
} GLIBC_2.0;
|
||||||
|
@ -172,27 +172,54 @@ static int pthread_start_thread(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
void * (*start_routine)(void *), void *arg,
|
void * (*start_routine)(void *), void *arg,
|
||||||
sigset_t * mask, int father_pid)
|
sigset_t * mask, int father_pid)
|
||||||
{
|
{
|
||||||
size_t sseg;
|
size_t sseg;
|
||||||
int pid;
|
int pid;
|
||||||
pthread_descr new_thread;
|
pthread_descr new_thread;
|
||||||
pthread_t new_thread_id;
|
pthread_t new_thread_id;
|
||||||
int i;
|
int i;
|
||||||
|
void *guardaddr = NULL;
|
||||||
|
|
||||||
/* Find a free stack segment for the current stack */
|
/* Find a free stack segment for the current stack */
|
||||||
for (sseg = 1; ; sseg++) {
|
for (sseg = 1; ; sseg++)
|
||||||
if (sseg >= PTHREAD_THREADS_MAX) return EAGAIN;
|
{
|
||||||
if (__pthread_handles[sseg].h_descr != NULL) continue;
|
if (sseg >= PTHREAD_THREADS_MAX)
|
||||||
new_thread = thread_segment(sseg);
|
return EAGAIN;
|
||||||
/* Allocate space for stack and thread descriptor. */
|
if (__pthread_handles[sseg].h_descr != NULL)
|
||||||
if (mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
|
continue;
|
||||||
INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
|
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, -1, 0)
|
if (attr == NULL || !attr->stackaddr_set)
|
||||||
!= MAP_FAILED) break;
|
{
|
||||||
/* It seems part of this segment is already mapped. Try the next. */
|
new_thread = thread_segment(sseg);
|
||||||
}
|
/* Allocate space for stack and thread descriptor. */
|
||||||
|
if (mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
|
||||||
|
INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN,
|
||||||
|
-1, 0) != MAP_FAILED)
|
||||||
|
{
|
||||||
|
/* We manage to get a stack. Now see whether we need a guard
|
||||||
|
and allocate it if necessary. */
|
||||||
|
if (attr->guardsize != 0)
|
||||||
|
{
|
||||||
|
guardaddr = mmap ((caddr_t)((char *)(new_thread+1)
|
||||||
|
- 2*1024*1024),
|
||||||
|
attr->guardsize, 0, MAP_FIXED, -1, 0);
|
||||||
|
if (guardaddr == MAP_FAILED)
|
||||||
|
/* We don't make this an error. */
|
||||||
|
guardaddr = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* It seems part of this segment is already mapped. Try the next. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_thread = (pthread_descr) attr->stackaddr - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Allocate new thread identifier */
|
/* Allocate new thread identifier */
|
||||||
pthread_threads_counter += PTHREAD_THREADS_MAX;
|
pthread_threads_counter += PTHREAD_THREADS_MAX;
|
||||||
new_thread_id = sseg + pthread_threads_counter;
|
new_thread_id = sseg + pthread_threads_counter;
|
||||||
@ -217,6 +244,10 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||||||
new_thread->p_errno = 0;
|
new_thread->p_errno = 0;
|
||||||
new_thread->p_h_errnop = &new_thread->p_h_errno;
|
new_thread->p_h_errnop = &new_thread->p_h_errno;
|
||||||
new_thread->p_h_errno = 0;
|
new_thread->p_h_errno = 0;
|
||||||
|
new_thread->p_guardaddr = guardaddr;
|
||||||
|
new_thread->p_guardsize = (attr == NULL || !attr->stackaddr_set
|
||||||
|
? attr->guardsize : 0);
|
||||||
|
new_thread->p_userstack = attr != NULL && attr->stackaddr_set;
|
||||||
for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
|
for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
|
||||||
new_thread->p_specific[i] = NULL;
|
new_thread->p_specific[i] = NULL;
|
||||||
/* Initialize the thread handle */
|
/* Initialize the thread handle */
|
||||||
@ -249,9 +280,14 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||||||
new_thread);
|
new_thread);
|
||||||
/* Check if cloning succeeded */
|
/* Check if cloning succeeded */
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
/* Free the stack */
|
/* Free the stack if we allocated it */
|
||||||
munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
|
if (attr == NULL || !attr->stackaddr_set)
|
||||||
INITIAL_STACK_SIZE);
|
{
|
||||||
|
munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
|
||||||
|
INITIAL_STACK_SIZE);
|
||||||
|
if (attr->guardsize != 0)
|
||||||
|
munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
|
||||||
|
}
|
||||||
__pthread_handles[sseg].h_descr = NULL;
|
__pthread_handles[sseg].h_descr = NULL;
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
@ -268,6 +304,7 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Free the resources of a thread. */
|
/* Free the resources of a thread. */
|
||||||
|
|
||||||
static void pthread_free(pthread_descr th)
|
static void pthread_free(pthread_descr th)
|
||||||
@ -281,8 +318,13 @@ static void pthread_free(pthread_descr th)
|
|||||||
release(&handle->h_spinlock);
|
release(&handle->h_spinlock);
|
||||||
/* If initial thread, nothing to free */
|
/* If initial thread, nothing to free */
|
||||||
if (th == &__pthread_initial_thread) return;
|
if (th == &__pthread_initial_thread) return;
|
||||||
/* Free the stack and thread descriptor area */
|
if (!th->p_userstack)
|
||||||
munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
|
{
|
||||||
|
/* Free the stack and thread descriptor area */
|
||||||
|
munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
|
||||||
|
if (th->p_guardsize != 0)
|
||||||
|
munmap(th->p_guardaddr, th->p_guardsize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle threads that have exited */
|
/* Handle threads that have exited */
|
||||||
|
@ -234,8 +234,8 @@ static int pthread_initialize_manager(void)
|
|||||||
|
|
||||||
/* Thread creation */
|
/* Thread creation */
|
||||||
|
|
||||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
int __pthread_create_2_1(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
void * (*start_routine)(void *), void *arg)
|
void * (*start_routine)(void *), void *arg)
|
||||||
{
|
{
|
||||||
pthread_descr self = thread_self();
|
pthread_descr self = thread_self();
|
||||||
struct pthread_request request;
|
struct pthread_request request;
|
||||||
@ -255,6 +255,35 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
|||||||
return self->p_retcode;
|
return self->p_retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined HAVE_ELF && defined PIC && defined DO_VERSIONING
|
||||||
|
default_symbol_version (__pthread_create_2_1, pthread_create, GLIBC_2.1);
|
||||||
|
|
||||||
|
int __pthread_create_2_0(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
|
void * (*start_routine)(void *), void *arg)
|
||||||
|
{
|
||||||
|
/* The ATTR attribute is not really of type `pthread_attr_t *'. It has
|
||||||
|
the old size and access to the new members might crash the program.
|
||||||
|
We convert the struct now. */
|
||||||
|
pthread_attr_t new_attr;
|
||||||
|
|
||||||
|
if (attr != NULL)
|
||||||
|
{
|
||||||
|
size_t ps = __getpagesize ();
|
||||||
|
|
||||||
|
memcpy (&new_attr, attr, (size_t) &(((pthread_attr_t*)NULL)->guardsize));
|
||||||
|
new_attr.guardsize = ps;
|
||||||
|
new_attr.stackaddr_set = 0;
|
||||||
|
new_attr.stackaddr = NULL;
|
||||||
|
new_attr.stacksize = STACK_SIZE - ps;
|
||||||
|
attr = &new_attr;
|
||||||
|
}
|
||||||
|
return __pthread_create_2_1 (thread, attr, start_routine, arg);
|
||||||
|
}
|
||||||
|
symbol_version (__pthread_create_2_0, pthread_create, GLIBC_2.0);
|
||||||
|
#else
|
||||||
|
strong_alias (__pthread_create_2_1, pthread_create)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Simple operations on thread identifiers */
|
/* Simple operations on thread identifiers */
|
||||||
|
|
||||||
pthread_t pthread_self(void)
|
pthread_t pthread_self(void)
|
||||||
@ -417,6 +446,23 @@ void __pthread_kill_other_threads_np(void)
|
|||||||
}
|
}
|
||||||
weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
|
weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
|
||||||
|
|
||||||
|
/* Concurrency symbol level. */
|
||||||
|
static int current_level;
|
||||||
|
|
||||||
|
int __pthread_setconcurrency(int level)
|
||||||
|
{
|
||||||
|
/* We don't do anything unless we have found a useful interpretation. */
|
||||||
|
current_level = level;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
|
||||||
|
|
||||||
|
int __pthread_getconcurrency(void)
|
||||||
|
{
|
||||||
|
return current_level;
|
||||||
|
}
|
||||||
|
weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
|
||||||
|
|
||||||
/* Debugging aid */
|
/* Debugging aid */
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -119,6 +119,10 @@ typedef struct
|
|||||||
struct sched_param schedparam;
|
struct sched_param schedparam;
|
||||||
int inheritsched;
|
int inheritsched;
|
||||||
int scope;
|
int scope;
|
||||||
|
size_t guardsize;
|
||||||
|
int stackaddr_set;
|
||||||
|
void *stackaddr;
|
||||||
|
size_t stacksize;
|
||||||
} pthread_attr_t;
|
} pthread_attr_t;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -272,6 +276,49 @@ extern int pthread_attr_setscope __P ((pthread_attr_t *__attr, int __scope));
|
|||||||
extern int pthread_attr_getscope __P ((__const pthread_attr_t *__attr,
|
extern int pthread_attr_getscope __P ((__const pthread_attr_t *__attr,
|
||||||
int *__scope));
|
int *__scope));
|
||||||
|
|
||||||
|
#ifdef __USE_UNIX98
|
||||||
|
/* Set the size of the guard area at the bottom of the thread. */
|
||||||
|
extern int __pthread_attr_setguardsize __P ((pthread_attr_t *__attr,
|
||||||
|
size_t __guardsize));
|
||||||
|
extern int pthread_attr_setguardsize __P ((pthread_attr_t *__attr,
|
||||||
|
size_t __guardsize));
|
||||||
|
|
||||||
|
/* Get the size of the guard area at the bottom of the thread. */
|
||||||
|
extern int __pthread_attr_getguardsize __P ((__const pthread_attr_t *__attr,
|
||||||
|
size_t *__guardsize));
|
||||||
|
extern int pthread_attr_getguardsize __P ((__const pthread_attr_t *__attr,
|
||||||
|
size_t *__guardsize));
|
||||||
|
|
||||||
|
/* Set the starting address of the stack of the thread to be created.
|
||||||
|
Depending on whether the stack grows up or doen the value must either
|
||||||
|
be higher or lower than all the address in the memory block. The
|
||||||
|
minimal size of the block must be PTHREAD_STACK_SIZE. */
|
||||||
|
extern int __pthread_attr_setstackaddr __P ((pthread_attr_t *__attr,
|
||||||
|
void *__stackaddr));
|
||||||
|
extern int pthread_attr_setstackaddr __P ((pthread_attr_t *__attr,
|
||||||
|
void *__stackaddr));
|
||||||
|
|
||||||
|
/* Return the previously set address for the stack. */
|
||||||
|
extern int __pthread_attr_getstackaddr __P ((__const pthread_attr_t *__attr,
|
||||||
|
void **__stackaddr));
|
||||||
|
extern int pthread_attr_getstackaddr __P ((__const pthread_attr_t *__attr,
|
||||||
|
void **__stackaddr));
|
||||||
|
|
||||||
|
/* Add information about the minimum stack size needed for the thread
|
||||||
|
to be started. This size must never be less than PTHREAD_STACK_SIZE
|
||||||
|
and must also not exceed the system limits. */
|
||||||
|
extern int __pthread_attr_setstacksize __P ((pthread_attr_t *__attr,
|
||||||
|
size_t __stacksize));
|
||||||
|
extern int pthread_attr_setstacksize __P ((pthread_attr_t *__attr,
|
||||||
|
size_t __stacksize));
|
||||||
|
|
||||||
|
/* Return the currently used minimal stack size. */
|
||||||
|
extern int __pthread_attr_getstacksize __P ((__const pthread_attr_t *__attr,
|
||||||
|
size_t *__stacksize));
|
||||||
|
extern int pthread_attr_getstacksize __P ((__const pthread_attr_t *__attr,
|
||||||
|
size_t *__stacksize));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Functions for scheduling control. */
|
/* Functions for scheduling control. */
|
||||||
|
|
||||||
/* Set the scheduling parameters for TARGET_THREAD according to POLICY
|
/* Set the scheduling parameters for TARGET_THREAD according to POLICY
|
||||||
@ -284,6 +331,15 @@ extern int pthread_getschedparam __P ((pthread_t __target_thread,
|
|||||||
int *__policy,
|
int *__policy,
|
||||||
struct sched_param *__param));
|
struct sched_param *__param));
|
||||||
|
|
||||||
|
#ifdef __USE_UNIX98
|
||||||
|
/* Determine level of concurrency. */
|
||||||
|
extern int __pthread_getconcurrency __P ((void));
|
||||||
|
extern int pthread_getconcurrency __P ((void));
|
||||||
|
|
||||||
|
/* Set new concurrency level to LEVEL. */
|
||||||
|
extern int __pthread_setconcurrency __P ((int __level));
|
||||||
|
extern int pthread_setconcurrency __P ((int __level));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Functions for mutex handling. */
|
/* Functions for mutex handling. */
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Minimum guaranteed maximum values for system limits. Linux version.
|
/* Minimum guaranteed maximum values for system limits. Linux version.
|
||||||
Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -38,3 +38,6 @@
|
|||||||
/* Maximum amount by which a process can descrease its asynchronous I/O
|
/* Maximum amount by which a process can descrease its asynchronous I/O
|
||||||
priority level. */
|
priority level. */
|
||||||
#define AIO_PRIO_DELTA_MAX 20
|
#define AIO_PRIO_DELTA_MAX 20
|
||||||
|
|
||||||
|
/* Minimum size for a thread. We are free to choose a reasonable value. */
|
||||||
|
#define PTHREAD_STACK_MIN 16384
|
||||||
|
Loading…
Reference in New Issue
Block a user