mirror of
https://sourceware.org/git/glibc.git
synced 2026-01-06 11:51:29 +03: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:
@@ -172,27 +172,54 @@ static int pthread_start_thread(void *arg)
|
||||
}
|
||||
|
||||
static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void * (*start_routine)(void *), void *arg,
|
||||
sigset_t * mask, int father_pid)
|
||||
void * (*start_routine)(void *), void *arg,
|
||||
sigset_t * mask, int father_pid)
|
||||
{
|
||||
size_t sseg;
|
||||
int pid;
|
||||
pthread_descr new_thread;
|
||||
pthread_t new_thread_id;
|
||||
int i;
|
||||
void *guardaddr = NULL;
|
||||
|
||||
/* Find a free stack segment for the current stack */
|
||||
for (sseg = 1; ; sseg++) {
|
||||
if (sseg >= PTHREAD_THREADS_MAX) return EAGAIN;
|
||||
if (__pthread_handles[sseg].h_descr != NULL) continue;
|
||||
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) break;
|
||||
/* It seems part of this segment is already mapped. Try the next. */
|
||||
}
|
||||
for (sseg = 1; ; sseg++)
|
||||
{
|
||||
if (sseg >= PTHREAD_THREADS_MAX)
|
||||
return EAGAIN;
|
||||
if (__pthread_handles[sseg].h_descr != NULL)
|
||||
continue;
|
||||
|
||||
if (attr == NULL || !attr->stackaddr_set)
|
||||
{
|
||||
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 */
|
||||
pthread_threads_counter += PTHREAD_THREADS_MAX;
|
||||
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_h_errnop = &new_thread->p_h_errno;
|
||||
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++)
|
||||
new_thread->p_specific[i] = NULL;
|
||||
/* Initialize the thread handle */
|
||||
@@ -249,9 +280,14 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
new_thread);
|
||||
/* Check if cloning succeeded */
|
||||
if (pid == -1) {
|
||||
/* Free the stack */
|
||||
munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
|
||||
INITIAL_STACK_SIZE);
|
||||
/* Free the stack if we allocated it */
|
||||
if (attr == NULL || !attr->stackaddr_set)
|
||||
{
|
||||
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;
|
||||
return errno;
|
||||
}
|
||||
@@ -268,6 +304,7 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Free the resources of a thread. */
|
||||
|
||||
static void pthread_free(pthread_descr th)
|
||||
@@ -281,8 +318,13 @@ static void pthread_free(pthread_descr th)
|
||||
release(&handle->h_spinlock);
|
||||
/* If initial thread, nothing to free */
|
||||
if (th == &__pthread_initial_thread) return;
|
||||
/* Free the stack and thread descriptor area */
|
||||
munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
|
||||
if (!th->p_userstack)
|
||||
{
|
||||
/* 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 */
|
||||
|
||||
Reference in New Issue
Block a user