From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31482 invoked by alias); 8 Oct 2002 14:11:29 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 31466 invoked from network); 8 Oct 2002 14:11:27 -0000 Received: from unknown (HELO sunsite.mff.cuni.cz) (195.113.19.66) by sources.redhat.com with SMTP; 8 Oct 2002 14:11:27 -0000 Received: (from jakub@localhost) by sunsite.mff.cuni.cz (8.11.6/8.11.6) id g98EBMY24879; Tue, 8 Oct 2002 16:11:22 +0200 Date: Wed, 09 Oct 2002 02:47:00 -0000 From: Jakub Jelinek To: Roland McGrath Cc: Ulrich Drepper , Glibc hackers Subject: [PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2) Message-ID: <20021008161121.M3451@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek References: <3DA2169B.2070004@redhat.com> <200210080106.g9816rJ27102@magilla.sf.frob.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5.1i In-Reply-To: <200210080106.g9816rJ27102@magilla.sf.frob.com>; from roland@redhat.com on Mon, Oct 07, 2002 at 06:06:53PM -0700 X-SW-Source: 2002-10/txt/msg00039.txt.bz2 On Mon, Oct 07, 2002 at 06:06:53PM -0700, Roland McGrath wrote: > > -----BEGIN PGP SIGNED MESSAGE----- > > Hash: SHA1 > > > > Jakub Jelinek wrote: > > > > > --- libc/include/alloca.h.jj 2002-09-30 16:45:04.000000000 +0200 > > > +++ libc/include/alloca.h 2002-10-08 00:12:01.000000000 +0200 > > > @@ -11,4 +11,16 @@ extern void *__alloca (size_t __size); > > > # define __alloca(size) __builtin_alloca (size) > > > #endif /* GCC. */ > > > > > > +extern size_t __libc_alloca_cutoff; > > > +libc_hidden_proto (__libc_alloca_cutoff) > > > > We should have this variable per-thread (use __thread). Tis way a few > > worker threads using very small stack do not affect to whole process. > > Conversely instead of a variable we could have a function that's given the > size and returns whether to use alloca or malloc. The libc version can > just say to always use alloca, I don't care about supporting tiny > RLIMIT_STACK values for single-threaded programs. The libpthread version > can look at the thread's stack size vs the allocation, and perhaps even > look at the current stack depth. Then we don't have to diddle setrlimit > and all the rest, or add the word of TLS data Ok, here is the next version. NPTL could use TLS variable in the inline or whatever else it wants to do. BTW: I found a bug in vfprintf.c, where it did: if (prec < (int) (32768 / sizeof (CHAR_T))) workend = alloca (prec + 32) + (prec + 32); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ else { workstart = (CHAR_T *) malloc ((prec + 32) * sizeof (CHAR_T)); if (workstart == NULL) { done = -1; goto all_done; } workend = workstart + (prec + 32); } The alloca line is wrong in wide version, it would result in clobbering area below stack. 2002-10-07 Jakub Jelinek * include/alloca.h (__libc_use_alloca, __libc_alloca_cutoff): New prototypes. (__MAX_ALLOCA_CUTOFF): Define. Include allocalim.h. * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r, _nss_dns_gethostbyaddr_r): Use alloca or malloc to allocate host_buffer depending on __libc_use_alloca. * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r, _nss_dns_getnetbyaddr_r): Use alloca or malloc to allocate net_buffer depending on __libc_use_alloca. * resolv/res_query.c (res_nquery): Use alloca or malloc to allocate buf depending on __libc_use_alloca. * resolv/gethnamaddr.c (gethostbyname2, gethostbyaddr): Likewise. * stdio-common/vfprintf.c (vfprintf): Use __libc_use_alloca instead of hardcoded constants. Pass proper size argument to alloca and compute end for wide char version. * stdio-common/printf_fp.c (__printf_fp): Use __libc_use_alloca instead of hardcoded constants. * string/strcoll.c (strcoll): Likewise. * string/strxfrm.c (strxfrm): Likewise. * sysdeps/posix/readv.c (__readv): Likewise. * sysdeps/posix/writev.c (__writev): Likewise. * sysdeps/generic/allocalim.h: New file. * sysdeps/unix/sysv/linux/allocalim.h: New file. * descr.h (struct _pthread_descr_struct): Add p_alloca_cutoff field. * manager.c (__pthread_allocate_stack): Add out_stacksize argument. Pass stack size to caller. (pthread_handle_create): Set p_alloca_cutoff. * pthread.c (__pthread_initial_thread): Use C99 designated initializers. Set p_alloca_cutoff. (__pthread_manager_thread): Likewise. (__pthread_initialize_minimal) [USE_TLS]: Set p_alloca_cutoff for initial thread. (__pthread_init_max_stacksize): Possibly decrease p_alloca_cutoff for initial thread. (__pthread_initialize_manager) [USE_TLS]: Set p_alloca_cutoff for manager thread. * specific.c (__libc_alloca_cutoff): New function. * no-tsd.c (__libc_alloca_cutoff): New function. * Versions: Export __libc_alloca_cutoff@@GLIBC_PRIVATE from libc and libpthread. --- libc/include/alloca.h.jj 2002-09-30 16:45:04.000000000 +0200 +++ libc/include/alloca.h 2002-10-08 14:59:39.000000000 +0200 @@ -11,4 +11,11 @@ extern void *__alloca (size_t __size); # define __alloca(size) __builtin_alloca (size) #endif /* GCC. */ +extern int __libc_use_alloca (size_t size) __attribute__ ((const)); +extern int __libc_alloca_cutoff (size_t size) __attribute__ ((const)); + +#define __MAX_ALLOCA_CUTOFF 65536 + +#include + #endif --- libc/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h.jj 2002-10-08 14:59:39.000000000 +0200 +++ libc/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h 2002-10-08 14:59:39.000000000 +0200 @@ -0,0 +1,7 @@ +#include + +extern inline int __libc_use_alloca (size_t size) +{ + return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) + || __libc_alloca_cutoff (size)); +} --- libc/linuxthreads/manager.c.jj 2002-08-28 12:58:03.000000000 +0200 +++ libc/linuxthreads/manager.c 2002-10-08 14:59:39.000000000 +0200 @@ -334,7 +334,8 @@ static int pthread_allocate_stack(const char ** out_new_thread, char ** out_new_thread_bottom, char ** out_guardaddr, - size_t * out_guardsize) + size_t * out_guardsize, + size_t * out_stacksize) { pthread_descr new_thread; char * new_thread_bottom; @@ -388,6 +389,7 @@ static int pthread_allocate_stack(const /* Clear the thread data structure. */ memset (new_thread, '\0', sizeof (*new_thread)); #endif + stacksize = attr->__stacksize; } else { @@ -559,6 +561,11 @@ static int pthread_allocate_stack(const *out_new_thread_bottom = new_thread_bottom; *out_guardaddr = guardaddr; *out_guardsize = guardsize; +#ifdef NEED_SEPARATE_REGISTER_STACK + *out_stacksize = stacksize / 2; +#else + *out_stacksize = stacksize; +#endif return 0; } @@ -575,7 +582,7 @@ static int pthread_handle_create(pthread char * new_thread_bottom; pthread_t new_thread_id; char *guardaddr = NULL; - size_t guardsize = 0; + size_t guardsize = 0, stksize = 0; int pagesize = __getpagesize(); int saved_errno = 0; @@ -608,7 +615,7 @@ static int pthread_handle_create(pthread continue; if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize, &stack_addr, &new_thread_bottom, - &guardaddr, &guardsize) == 0) + &guardaddr, &guardsize, &stksize) == 0) { #ifdef USE_TLS new_thread->p_stackaddr = stack_addr; @@ -639,6 +646,8 @@ static int pthread_handle_create(pthread new_thread->p_guardsize = guardsize; new_thread->p_nr = sseg; new_thread->p_inheritsched = attr ? attr->__inheritsched : 0; + new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF + ? __MAX_ALLOCA_CUTOFF : stksize / 4; /* Initialize the thread handle */ __pthread_init_lock(&__pthread_handles[sseg].h_lock); __pthread_handles[sseg].h_descr = new_thread; --- libc/linuxthreads/specific.c.jj 2002-09-28 17:06:08.000000000 +0200 +++ libc/linuxthreads/specific.c 2002-10-08 14:59:39.000000000 +0200 @@ -239,3 +239,9 @@ void **(*const __libc_internal_tsd_addre __THROW __attribute__ ((__const__)) = libc_internal_tsd_address; #endif + +int __libc_alloca_cutoff (size_t size) +{ + pthread_descr self = thread_self(); + return size <= THREAD_GETMEM_NC(self, p_alloca_cutoff); +} --- libc/linuxthreads/no-tsd.c.jj 2002-09-03 15:34:45.000000000 +0200 +++ libc/linuxthreads/no-tsd.c 2002-10-08 14:59:39.000000000 +0200 @@ -38,3 +38,8 @@ void **(*__libc_internal_tsd_address) (e __THROW __attribute__ ((__const__)); #endif /* !(USE_TLS && HAVE___THREAD) */ + +int __libc_alloca_cutoff (size_t size) +{ + return size <= __MAX_ALLOCA_CUTOFF; +} --- libc/linuxthreads/Versions.jj 2002-09-02 09:58:47.000000000 +0200 +++ libc/linuxthreads/Versions 2002-10-08 14:59:39.000000000 +0200 @@ -20,8 +20,7 @@ libc { GLIBC_PRIVATE { # Internal libc interface to libpthread __libc_internal_tsd_get; __libc_internal_tsd_set; - __libc_internal_tsd_address; - + __libc_internal_tsd_address; __libc_alloca_cutoff; } } @@ -163,7 +162,7 @@ libpthread { GLIBC_PRIVATE { # Internal libc interface to libpthread __libc_internal_tsd_get; __libc_internal_tsd_set; - __libc_internal_tsd_address; + __libc_internal_tsd_address; __libc_alloca_cutoff; __pthread_kill_other_threads_np; } } --- libc/linuxthreads/descr.h.jj 2002-08-02 11:47:38.000000000 +0200 +++ libc/linuxthreads/descr.h 2002-10-08 14:59:39.000000000 +0200 @@ -165,6 +165,8 @@ struct _pthread_descr_struct { #ifdef USE_TLS char *p_stackaddr; /* Stack address. */ #endif + size_t p_alloca_cutoff; /* Maximum size which should be allocated + using alloca() instead of malloc(). */ /* New elements must be added at the end. */ } __attribute__ ((aligned(32))); /* We need to align the structure so that doubles are aligned properly. This is 8 --- libc/linuxthreads/pthread.c.jj 2002-09-30 11:23:43.000000000 +0200 +++ libc/linuxthreads/pthread.c 2002-10-08 14:59:39.000000000 +0200 @@ -63,58 +63,20 @@ static pthread_descr manager_thread; /* Descriptor of the initial thread */ struct _pthread_descr_struct __pthread_initial_thread = { - { - { - .self = &__pthread_initial_thread /* pthread_descr self */ - } - }, - &__pthread_initial_thread, /* pthread_descr p_nextlive */ - &__pthread_initial_thread, /* pthread_descr p_prevlive */ - NULL, /* pthread_descr p_nextwaiting */ - NULL, /* pthread_descr p_nextlock */ - PTHREAD_THREADS_MAX, /* pthread_t p_tid */ - 0, /* int p_pid */ - 0, /* int p_priority */ - &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */ - 0, /* int p_signal */ - NULL, /* sigjmp_buf * p_signal_buf */ - NULL, /* sigjmp_buf * p_cancel_buf */ - 0, /* char p_terminated */ - 0, /* char p_detached */ - 0, /* char p_exited */ - NULL, /* void * p_retval */ - 0, /* int p_retval */ - NULL, /* pthread_descr p_joining */ - NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ - 0, /* char p_cancelstate */ - 0, /* char p_canceltype */ - 0, /* char p_canceled */ - NULL, /* char * p_in_sighandler */ - 0, /* char p_sigwaiting */ - PTHREAD_START_ARGS_INITIALIZER(NULL), - /* struct pthread_start_args p_start_args */ - {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ - {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ - &_errno, /* int *p_errnop */ - 0, /* int p_errno */ - &_h_errno, /* int *p_h_errnop */ - 0, /* int p_h_errno */ - &_res, /* struct __res_state *p_resp */ - {}, /* struct __res_state p_res */ - 1, /* int p_userstack */ - NULL, /* void * p_guardaddr */ - 0, /* size_t p_guardsize */ - 0, /* Always index 0 */ - 0, /* int p_report_events */ - {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ - __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ - 0, /* char p_woken_by_cancel */ - 0, /* char p_condvar_avail */ - 0, /* char p_sem_avail */ - NULL, /* struct pthread_extricate_if *p_extricate */ - NULL, /* pthread_readlock_info *p_readlock_list; */ - NULL, /* pthread_readlock_info *p_readlock_free; */ - 0 /* int p_untracked_readlock_count; */ + .p_header.data.self = &__pthread_initial_thread, + .p_nextlive = &__pthread_initial_thread, + .p_prevlive = &__pthread_initial_thread, + .p_tid = PTHREAD_THREADS_MAX, + .p_lock = &__pthread_handles[0].h_lock, + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(NULL), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &_errno, + .p_h_errnop = &_h_errno, + .p_resp = &_res, +#endif + .p_userstack = 1, + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = __MAX_ALLOCA_CUTOFF }; /* Descriptor of the manager thread; none of this is used but the error @@ -123,58 +85,15 @@ struct _pthread_descr_struct __pthread_i #define manager_thread (&__pthread_manager_thread) struct _pthread_descr_struct __pthread_manager_thread = { - { - { - .self = &__pthread_manager_thread /* pthread_descr self */ - } - }, - NULL, /* pthread_descr p_nextlive */ - NULL, /* pthread_descr p_prevlive */ - NULL, /* pthread_descr p_nextwaiting */ - NULL, /* pthread_descr p_nextlock */ - 0, /* int p_tid */ - 0, /* int p_pid */ - 0, /* int p_priority */ - &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */ - 0, /* int p_signal */ - NULL, /* sigjmp_buf * p_signal_buf */ - NULL, /* sigjmp_buf * p_cancel_buf */ - 0, /* char p_terminated */ - 0, /* char p_detached */ - 0, /* char p_exited */ - NULL, /* void * p_retval */ - 0, /* int p_retval */ - NULL, /* pthread_descr p_joining */ - NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ - 0, /* char p_cancelstate */ - 0, /* char p_canceltype */ - 0, /* char p_canceled */ - NULL, /* char * p_in_sighandler */ - 0, /* char p_sigwaiting */ - PTHREAD_START_ARGS_INITIALIZER(__pthread_manager), - /* struct pthread_start_args p_start_args */ - {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ - {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ - &__pthread_manager_thread.p_errno, /* int *p_errnop */ - 0, /* int p_errno */ - NULL, /* int *p_h_errnop */ - 0, /* int p_h_errno */ - NULL, /* struct __res_state *p_resp */ - {}, /* struct __res_state p_res */ - 0, /* int p_userstack */ - NULL, /* void * p_guardaddr */ - 0, /* size_t p_guardsize */ - 1, /* Always index 1 */ - 0, /* int p_report_events */ - {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ - __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ - 0, /* char p_woken_by_cancel */ - 0, /* char p_condvar_avail */ - 0, /* char p_sem_avail */ - NULL, /* struct pthread_extricate_if *p_extricate */ - NULL, /* pthread_readlock_info *p_readlock_list; */ - NULL, /* pthread_readlock_info *p_readlock_free; */ - 0 /* int p_untracked_readlock_count; */ + .p_header.data.self = &__pthread_manager_thread, + .p_lock = &__pthread_handles[1].h_lock, + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(__pthread_manager), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &__pthread_manager_thread.p_errno, +#endif + .p_nr = 1, + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = PTHREAD_STACK_MIN / 4 }; #endif @@ -418,6 +337,7 @@ __pthread_initialize_minimal(void) # if __LT_SPINLOCK_INIT != 0 self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; # endif + self->p_alloca_cutoff = __MAX_ALLOCA_CUTOFF; /* Another variable which points to the thread descriptor. */ __pthread_main_thread = self; @@ -487,6 +407,15 @@ __pthread_init_max_stacksize(void) } #endif __pthread_max_stacksize = max_stack; + if (max_stack / 4 < __MAX_ALLOCA_CUTOFF) + { +#ifdef USE_TLS + pthread_descr self = THREAD_SELF; + self->p_alloca_cutoff = max_stack / 4; +#else + __pthread_initial_thread.p_alloca_cutoff = max_stack / 4; +#endif + } } @@ -629,6 +558,7 @@ int __pthread_initialize_manager(void) # if __LT_SPINLOCK_INIT != 0 self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; # endif + tcb->p_alloca_cutoff = PTHREAD_STACK_MIN / 4; #else tcb = &__pthread_manager_thread; #endif --- libc/resolv/nss_dns/dns-host.c.jj 2002-08-27 23:19:49.000000000 +0200 +++ libc/resolv/nss_dns/dns-host.c 2002-10-08 14:59:39.000000000 +0200 @@ -132,12 +132,13 @@ _nss_dns_gethostbyname2_r (const char *n char *buffer, size_t buflen, int *errnop, int *h_errnop) { - querybuf host_buffer; + querybuf *host_buffer; char tmp[NS_MAXDNAME]; int size, type, n; const char *cp; - int map = 0; + int map = 0, use_malloc = 0; int olderr = errno; + enum nss_status status; if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) return NSS_STATUS_UNAVAIL; @@ -169,8 +170,21 @@ _nss_dns_gethostbyname2_r (const char *n && (cp = res_hostalias (&_res, name, tmp, sizeof (tmp))) != NULL) name = cp; - n = res_nsearch (&_res, name, C_IN, type, host_buffer.buf, - sizeof (host_buffer.buf)); + if (!__libc_use_alloca (MAXPACKET)) + { + host_buffer = (querybuf *) malloc (sizeof (querybuf)); + if (host_buffer == NULL) + { + *errnop = ENOMEM; + return NSS_STATUS_UNAVAIL; + } + use_malloc = 1; + } + else + host_buffer = (querybuf *) alloca (sizeof (querybuf)); + + n = res_nsearch (&_res, name, C_IN, type, host_buffer->buf, + sizeof (host_buffer->buf)); if (n < 0) { enum nss_status status = (errno == ECONNREFUSED @@ -185,11 +199,15 @@ _nss_dns_gethostbyname2_r (const char *n by having the RES_USE_INET6 bit in _res.options set, we try another lookup. */ if (af == AF_INET6 && (_res.options & RES_USE_INET6)) - n = res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf, - sizeof (host_buffer.buf)); + n = res_nsearch (&_res, name, C_IN, T_A, host_buffer->buf, + sizeof (host_buffer->buf)); if (n < 0) - return status; + { + if (use_malloc) + free (host_buffer); + return status; + } map = 1; @@ -197,8 +215,11 @@ _nss_dns_gethostbyname2_r (const char *n result->h_length = INADDRSZ;; } - return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen, - errnop, h_errnop, map); + status = getanswer_r (host_buffer, n, name, type, result, buffer, buflen, + errnop, h_errnop, map); + if (use_malloc) + free (host_buffer); + return status; } @@ -236,10 +257,10 @@ _nss_dns_gethostbyaddr_r (const void *ad char *h_addr_ptrs[MAX_NR_ADDRS + 1]; char linebuffer[0]; } *host_data = (struct host_data *) buffer; - querybuf host_buffer; + querybuf *host_buffer; char qbuf[MAXDNAME+1], *qp = NULL; size_t size; - int n, status; + int n, status, use_malloc = 0; int olderr = errno; if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) @@ -294,23 +315,40 @@ _nss_dns_gethostbyaddr_r (const void *ad break; } - n = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf, - sizeof host_buffer); + if (!__libc_use_alloca (MAXPACKET)) + { + host_buffer = (querybuf *) malloc (sizeof (querybuf)); + if (host_buffer == NULL) + { + *errnop = ENOMEM; + return NSS_STATUS_UNAVAIL; + } + use_malloc = 1; + } + else + host_buffer = (querybuf *) alloca (sizeof (querybuf)); + + n = res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer->buf, + sizeof (host_buffer->buf)); if (n < 0 && af == AF_INET6) { strcpy (qp, "ip6.int"); - n = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf, - sizeof host_buffer); + n = res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer->buf, + sizeof (host_buffer->buf)); } if (n < 0) { *h_errnop = h_errno; __set_errno (olderr); + if (use_malloc) + free (host_buffer); return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; } - status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen, + status = getanswer_r (host_buffer, n, qbuf, T_PTR, result, buffer, buflen, errnop, h_errnop, 0 /* XXX */); + if (use_malloc) + free (host_buffer); if (status != NSS_STATUS_SUCCESS) { *h_errnop = h_errno; --- libc/resolv/nss_dns/dns-network.c.jj 2002-09-05 11:57:18.000000000 +0200 +++ libc/resolv/nss_dns/dns-network.c 2002-10-08 14:59:39.000000000 +0200 @@ -110,27 +110,47 @@ _nss_dns_getnetbyname_r (const char *nam int *herrnop) { /* Return entry for network with NAME. */ - querybuf net_buffer; - int anslen; + querybuf *net_buffer; + int anslen, use_malloc = 0; char *qbuf; + enum nss_status status; if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) return NSS_STATUS_UNAVAIL; qbuf = strdupa (name); - anslen = res_nsearch (&_res, qbuf, C_IN, T_PTR, (u_char *) &net_buffer, - sizeof (querybuf)); + + if (!__libc_use_alloca (MAXPACKET)) + { + net_buffer = (querybuf *) malloc (sizeof (querybuf)); + if (net_buffer == NULL) + { + *errnop = ENOMEM; + return NSS_STATUS_UNAVAIL; + } + use_malloc = 1; + } + else + net_buffer = (querybuf *) alloca (sizeof (querybuf)); + + anslen = res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer->buf, + sizeof (net_buffer->buf)); if (anslen < 0) { /* Nothing found. */ *errnop = errno; + if (use_malloc) + free (net_buffer); return (errno == ECONNREFUSED || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT) ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; } - return getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYNAME); + status = getanswer_r (net_buffer, anslen, result, buffer, buflen, BYNAME); + if (use_malloc) + free (net_buffer); + return status; } @@ -141,10 +161,10 @@ _nss_dns_getnetbyaddr_r (uint32_t net, i { /* Return entry for network with NAME. */ enum nss_status status; - querybuf net_buffer; + querybuf *net_buffer; unsigned int net_bytes[4]; char qbuf[MAXDNAME]; - int cnt, anslen; + int cnt, anslen, use_malloc = 0; u_int32_t net2; int olderr = errno; @@ -181,20 +201,37 @@ _nss_dns_getnetbyaddr_r (uint32_t net, i break; } - anslen = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *) &net_buffer, - sizeof (querybuf)); + if (!__libc_use_alloca (MAXPACKET)) + { + net_buffer = (querybuf *) malloc (sizeof (querybuf)); + if (net_buffer == NULL) + { + *errnop = ENOMEM; + return NSS_STATUS_UNAVAIL; + } + use_malloc = 1; + } + else + net_buffer = (querybuf *) alloca (sizeof (querybuf)); + + anslen = res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer->buf, + sizeof (net_buffer->buf)); if (anslen < 0) { /* Nothing found. */ int err = errno; __set_errno (olderr); + if (use_malloc) + free (net_buffer); return (err == ECONNREFUSED || err == EPFNOSUPPORT || err == EAFNOSUPPORT) ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; } - status = getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYADDR); + status = getanswer_r (net_buffer, anslen, result, buffer, buflen, BYADDR); + if (use_malloc) + free (net_buffer); if (status == NSS_STATUS_SUCCESS) { /* Strip trailing zeros. */ --- libc/resolv/res_query.c.jj 2002-08-27 23:19:49.000000000 +0200 +++ libc/resolv/res_query.c 2002-10-08 14:59:39.000000000 +0200 @@ -108,28 +108,42 @@ res_nquery(res_state statp, u_char *answer, /* buffer to put answer */ int anslen) /* size of answer buffer */ { - u_char buf[MAXPACKET]; + u_char *buf; HEADER *hp = (HEADER *) answer; - int n; + int n, use_malloc = 0; hp->rcode = NOERROR; /* default */ + if (!__libc_use_alloca (MAXPACKET)) { + buf = malloc (MAXPACKET); + if (buf == NULL) { + __set_h_errno (NETDB_INTERNAL); + return -1; + } + use_malloc = 1; + } else + buf = alloca (MAXPACKET); + #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";; res_query(%s, %d, %d)\n", name, class, type); #endif n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, - buf, sizeof(buf)); + buf, MAXPACKET); if (n <= 0) { #ifdef DEBUG if (statp->options & RES_DEBUG) printf(";; res_query: mkquery failed\n"); #endif RES_SET_H_ERRNO(statp, NO_RECOVERY); + if (use_malloc) + free (buf); return (n); } n = res_nsend(statp, buf, n, answer, anslen); + if (use_malloc) + free (buf); if (n < 0) { #ifdef DEBUG if (statp->options & RES_DEBUG) --- libc/resolv/gethnamaddr.c.jj 2002-09-25 11:11:53.000000000 +0200 +++ libc/resolv/gethnamaddr.c 2002-10-08 14:59:39.000000000 +0200 @@ -510,10 +510,11 @@ gethostbyname2(name, af) const char *name; int af; { - querybuf buf; + querybuf *buf; register const char *cp; char *bp; - int n, size, type, len; + int n, size, type, len, use_malloc = 0; + struct hostent *ret; extern struct hostent *_gethtbyname2(); if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) { @@ -615,13 +616,26 @@ gethostbyname2(name, af) break; } - if ((n = res_nsearch(&_res, name, C_IN, type, buf.buf, sizeof(buf.buf))) < 0) { + if (!__libc_use_alloca (MAXPACKET)) { + buf = (querybuf *) malloc (sizeof (*buf)); + if (buf == NULL) { + __set_h_errno (NETDB_INTERNAL); + return NULL; + } + use_malloc = 1; + } else + buf = (querybuf *) alloca (sizeof (*buf)); + + if ((n = res_nsearch(&_res, name, C_IN, type, buf->buf, sizeof(buf->buf))) < 0) { dprintf("res_nsearch failed (%d)\n", n); if (errno == ECONNREFUSED) return (_gethtbyname2(name, af)); return (NULL); } - return (getanswer(&buf, n, name, type)); + ret = getanswer(buf, n, name, type); + if (use_malloc) + free (buf); + return ret; } struct hostent * @@ -633,9 +647,9 @@ gethostbyaddr(addr, len, af) const u_char *uaddr = (const u_char *)addr; static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; - int n; + int n, use_malloc = 0; socklen_t size; - querybuf buf; + querybuf *buf; register struct hostent *hp; char qbuf[MAXDNAME+1], *qp = NULL; #ifdef SUNSECURITY @@ -696,18 +710,34 @@ gethostbyaddr(addr, len, af) default: abort(); } - n = res_nquery(&_res, qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); + + if (!__libc_use_alloca (MAXPACKET)) { + buf = (querybuf *) malloc (sizeof (*buf)); + if (buf == NULL) { + __set_h_errno (NETDB_INTERNAL); + return NULL; + } + use_malloc = 1; + } else + buf = (querybuf *) alloca (sizeof (*buf)); + + n = res_nquery(&_res, qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf); if (n < 0 && af == AF_INET6) { strcpy(qp, "ip6.int"); - n = res_nquery(&_res, qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); + n = res_nquery(&_res, qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf); } if (n < 0) { + if (use_malloc) + free (buf); dprintf("res_nquery failed (%d)\n", n); if (errno == ECONNREFUSED) return (_gethtbyaddr(addr, len, af)); return (NULL); } - if (!(hp = getanswer(&buf, n, qbuf, T_PTR))) + hp = getanswer(buf, n, qbuf, T_PTR); + if (use_malloc) + free (buf); + if (!hp) return (NULL); /* h_errno was set by getanswer() */ #ifdef SUNSECURITY if (af == AF_INET) { --- libc/stdio-common/vfprintf.c.jj 2002-09-30 16:45:06.000000000 +0200 +++ libc/stdio-common/vfprintf.c 2002-10-08 14:59:39.000000000 +0200 @@ -1039,7 +1039,7 @@ vfprintf (FILE *s, const CHAR_T *format, \ /* Allocate dynamically an array which definitely is long \ enough for the wide character version. */ \ - if (len < 8192) \ + if (__libc_use_alloca (len * sizeof (wchar_t))) \ string = (CHAR_T *) alloca (len * sizeof (wchar_t)); \ else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t))) \ == NULL) \ @@ -1201,7 +1201,7 @@ vfprintf (FILE *s, const CHAR_T *format, if (prec >= 0) \ { \ /* The string `s2' might not be NUL terminated. */ \ - if (prec < 32768) \ + if (__libc_use_alloca (prec)) \ string = (char *) alloca (prec); \ else if ((string = (char *) malloc (prec)) == NULL) \ { \ @@ -1219,7 +1219,7 @@ vfprintf (FILE *s, const CHAR_T *format, { \ assert (__mbsinit (&mbstate)); \ s2 = (const wchar_t *) string; \ - if (len + 1 < 32768) \ + if (__libc_use_alloca (len + 1)) \ string = (char *) alloca (len + 1); \ else if ((string = (char *) malloc (len + 1)) == NULL) \ { \ @@ -1448,7 +1448,7 @@ vfprintf (FILE *s, const CHAR_T *format, { /* We have to use a special buffer. The "32" is just a safe bet for all the output which is not counted in the width. */ - if (width < (int) (32768 / sizeof (CHAR_T))) + if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T))) workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T)) + (width + 32)); else @@ -1473,7 +1473,7 @@ vfprintf (FILE *s, const CHAR_T *format, { /* We have to use a special buffer. The "32" is just a safe bet for all the output which is not counted in the width. */ - if (width < (int) (32768 / sizeof (CHAR_T))) + if (__libc_use_alloca ((width + 32) * sizeof (CHAR_T))) workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T)) + (width + 32)); else @@ -1516,8 +1516,9 @@ vfprintf (FILE *s, const CHAR_T *format, if (prec > width && prec + 32 > (int)(sizeof (work_buffer) / sizeof (work_buffer[0]))) { - if (prec < (int) (32768 / sizeof (CHAR_T))) - workend = alloca (prec + 32) + (prec + 32); + if (__libc_use_alloca ((prec + 32) * sizeof (CHAR_T))) + workend = ((CHAR_T *) alloca ((prec + 32) * sizeof (CHAR_T))) + + (prec + 32); else { workstart = (CHAR_T *) malloc ((prec + 32) * sizeof (CHAR_T)); @@ -1832,7 +1833,8 @@ do_positional: if (MAX (prec, width) + 32 > (int) (sizeof (work_buffer) / sizeof (CHAR_T))) { - if (MAX (prec, width) < (int) (32768 / sizeof (CHAR_T))) + if (__libc_use_alloca ((MAX (prec, width) + 32) + * sizeof (CHAR_T))) workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32) * sizeof (CHAR_T)) + (MAX (prec, width) + 32)); --- libc/stdio-common/printf_fp.c.jj 2002-10-02 10:26:33.000000000 +0200 +++ libc/stdio-common/printf_fp.c 2002-10-08 14:59:39.000000000 +0200 @@ -869,7 +869,7 @@ __printf_fp (FILE *fp, it is possible that we need two more characters in front of all the other output. If the amount of memory we have to allocate is too large use `malloc' instead of `alloca'. */ - buffer_malloced = chars_needed > 5000; + buffer_malloced = ! __libc_use_alloca (chars_needed * 2 * sizeof (wchar_t)); if (buffer_malloced) { wbuffer = (wchar_t *) malloc ((2 + chars_needed) * sizeof (wchar_t)); --- libc/string/strcoll.c.jj 2002-09-30 16:45:06.000000000 +0200 +++ libc/string/strcoll.c 2002-10-08 14:59:39.000000000 +0200 @@ -155,7 +155,7 @@ STRCOLL (s1, s2, l) Please note that the localedef programs makes sure that `position' is not used at the first level. */ - if (s1len + s2len >= 16384) + if (! __libc_use_alloca (s1len + s2len)) { idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1)); idx2arr = &idx1arr[s1len]; --- libc/string/strxfrm.c.jj 2002-09-30 16:45:06.000000000 +0200 +++ libc/string/strxfrm.c 2002-10-08 14:59:39.000000000 +0200 @@ -175,7 +175,7 @@ STRXFRM (STRING_TYPE *dest, const STRING values. But since there is no limit on the length of the string we have to use `malloc' if the string is too long. We should be very conservative here. */ - if (srclen >= 16384) + if (! __libc_use_alloca (srclen)) { idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1)); rulearr = (unsigned char *) &idxarr[srclen]; --- libc/sysdeps/generic/allocalim.h.jj 2002-10-08 14:59:39.000000000 +0200 +++ libc/sysdeps/generic/allocalim.h 2002-10-08 14:59:39.000000000 +0200 @@ -0,0 +1,4 @@ +extern inline int __libc_use_alloca (size_t size) +{ + return size <= __MAX_ALLOCA_CUTOFF; +} --- libc/sysdeps/posix/readv.c.jj 2002-09-30 16:45:08.000000000 +0200 +++ libc/sysdeps/posix/readv.c 2002-10-08 14:59:39.000000000 +0200 @@ -55,8 +55,8 @@ __readv (int fd, const struct iovec *vec /* Allocate a temporary buffer to hold the data. We should normally use alloca since it's faster and does not require synchronization with other threads. But we cannot if the amount of memory - required is too large. Use 512k as the limit. */ - if (bytes < 512 * 1024) + required is too large. */ + if (__libc_use_alloca (bytes)) buffer = (char *) __alloca (bytes); else { --- libc/sysdeps/posix/writev.c.jj 2002-09-30 16:45:08.000000000 +0200 +++ libc/sysdeps/posix/writev.c 2002-10-08 14:59:39.000000000 +0200 @@ -55,8 +55,8 @@ __writev (int fd, const struct iovec *ve /* Allocate a temporary buffer to hold the data. We should normally use alloca since it's faster and does not require synchronization with other threads. But we cannot if the amount of memory - required is too large. Use 512k as the limit. */ - if (bytes < 512 * 1024) + required is too large. */ + if (__libc_use_alloca (bytes)) buffer = (char *) __alloca (bytes); else { Jakub