mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 17:53:37 +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>
|
||||
|
||||
* linuxthreads/manager.c: Enable resetting of the thread
|
||||
scheduling policy to SCHED_OTHER when the parent thread
|
||||
has a different one.
|
||||
* manager.c: Enable resetting of the thread scheduling policy
|
||||
to SCHED_OTHER when the parent thread has a different one.
|
||||
|
||||
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,
|
||||
and comes with a specially-adapted version of LinuxThreads.
|
||||
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:
|
||||
@ -107,6 +107,9 @@ KNOWN BUGS AND LIMITATIONS:
|
||||
threads blocked on mutexes or conditions; the other is for thread
|
||||
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,
|
||||
below the stack of the initial process, and spaced 2M apart.
|
||||
Stacks are allocated with the "grow on demand" flag, so they don't
|
||||
|
@ -15,10 +15,30 @@
|
||||
/* Handling of thread attributes */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include "pthread.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->schedpolicy = SCHED_OTHER;
|
||||
@ -27,6 +47,10 @@ int pthread_attr_init(pthread_attr_t *attr)
|
||||
attr->scope = PTHREAD_SCOPE_SYSTEM;
|
||||
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)
|
||||
{
|
||||
@ -115,3 +139,67 @@ int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
|
||||
*scope = attr->scope;
|
||||
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 */
|
||||
void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */
|
||||
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. */
|
||||
|
@ -53,10 +53,19 @@ GLIBC_2.0 {
|
||||
|
||||
GLIBC_2.1 {
|
||||
global:
|
||||
# Functions with changed interface.
|
||||
pthread_attr_init; pthread_create;
|
||||
|
||||
# Unix98 extensions.
|
||||
pthread_rwlock_init; pthread_rwlock_destroy; pthread_rwlock_rdlock;
|
||||
pthread_rwlock_tryrdlock; pthread_rwlock_wrlock; pthread_rwlock_trywrlock;
|
||||
pthread_rwlock_unlock; pthread_rwlockattr_init; pthread_rwlockattr_destroy;
|
||||
pthread_rwlockattr_getpshared; pthread_rwlockattr_setpshared;
|
||||
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;
|
||||
|
@ -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 */
|
||||
|
@ -234,8 +234,8 @@ static int pthread_initialize_manager(void)
|
||||
|
||||
/* Thread creation */
|
||||
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void * (*start_routine)(void *), void *arg)
|
||||
int __pthread_create_2_1(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void * (*start_routine)(void *), void *arg)
|
||||
{
|
||||
pthread_descr self = thread_self();
|
||||
struct pthread_request request;
|
||||
@ -255,6 +255,35 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
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 */
|
||||
|
||||
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)
|
||||
|
||||
/* 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 */
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -119,6 +119,10 @@ typedef struct
|
||||
struct sched_param schedparam;
|
||||
int inheritsched;
|
||||
int scope;
|
||||
size_t guardsize;
|
||||
int stackaddr_set;
|
||||
void *stackaddr;
|
||||
size_t stacksize;
|
||||
} pthread_attr_t;
|
||||
|
||||
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,
|
||||
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. */
|
||||
|
||||
/* 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,
|
||||
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. */
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* 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.
|
||||
|
||||
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
|
||||
priority level. */
|
||||
#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