public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy)
@ 2002-10-07 16:20 Jakub Jelinek
  2002-10-07 18:06 ` Ulrich Drepper
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2002-10-07 16:20 UTC (permalink / raw)
  To: Roland McGrath, Ulrich Drepper; +Cc: Glibc hackers

Hi!

MySQL is using very low RLIMIT_STACK setting (or is it just too low
pthread_attr_setstacksize?) yet does gethostbyname from such threads
and thus crashes when external connections are made to it.
There is a lot of other places in glibc which use various hardcoded
constants to decide whether to use alloca or fall back to malloc.
The following patch deals with this by changing all
such hardcoded constants (I could find) to a variable and changes resolv
to also use malloc as fallback variant.
I haven't changed all setrlimit and getrlimit implementations yet (nor have
a nptl patch) plus did only limited testing so far, but e.g.

#include <netdb.h>
#include <pthread.h>

void *foo (void *arg)
{
  gethostbyname ("sources.redhat.com");
  return 0;
}

int main (void)
{
  pthread_attr_t a;
  pthread_t t;
  pthread_attr_init (&a);
  pthread_attr_setstacksize (&a, 16384);

  pthread_create (&t, &a, foo, 0);
  pthread_join (t, NULL);
}

or

#include <netdb.h>
#include <sys/resource.h>

void *foo (void *arg)
{
  gethostbyname ("sources.redhat.com");
  return 0;
}

int main (void)
{
  struct rlimit r;
  getrlimit (RLIMIT_STACK, &r);
  r.rlim_cur = 3*4096;
  setrlimit (RLIMIT_STACK, &r);
  foo (0);
}

work now and crashed before. Setting rlim_cur to 8192 and doing DNS lookup
still crashes, since res_init.c (but other places in glibc too) use
char buf[BUFSIZ];
on the stack.

2002-10-07  Jakub Jelinek  <jakub@redhat.com>

	* include/alloca.h (__libc_alloca_cutoff): New variable.
	(__libc_set_alloca_cutoff): New prototype.
	(__set_alloca_cutoff): New inline function.
	* malloc/Versions (libc: GLIBC_PRIVATE): Export __libc_alloca_cutoff
	and __libc_set_alloca_cutoff.
	* malloc/Makefile (routines): Add allocalim.
	* malloc/allocalim.c: New file.
	* 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_alloca_cutoff.
	* 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_alloca_cutoff.
	* resolv/res_query.c (res_nquery): Use alloca or malloc to allocate
	buf depending on __libc_alloca_cutoff.
	* resolv/gethnamaddr.c (gethostbyname2, gethostbyaddr): Likewise.
	* stdio-common/vfprintf.c (vfprintf): Use __libc_alloca_cutoff
	instead of hardcoded constants.
	* stdio-common/printf_fp.c (__printf_fp): Likewise.
	* string/strcoll.c (strcoll): Likewise.
	* string/strxfrm.c (strxfrm): Likewise.
	* sysdeps/posix/readv.c (__readv): Likewise.
	* sysdeps/posix/writev.c (__writev): Likewise.
	* sysdeps/unix/sysv/linux/i386/setrlimit.c (__new_setrlimit): Call
	__set_alloca_cutoff.
	* sysdeps/unix/sysv/linux/i386/getrlimit.c (__new_getrlimit):
	Likewise.

	* manager.c (__pthread_allocate_stack): Call __set_alloca_cutoff.

--- 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)
+
+extern void __libc_set_alloca_cutoff (size_t size);
+libc_hidden_proto (__libc_set_alloca_cutoff)
+
+extern inline void __set_alloca_cutoff (size_t size)
+{
+  if (__libc_alloca_cutoff > size / 4)
+    __libc_set_alloca_cutoff (size / 4);
+}
+
 #endif
--- libc/linuxthreads/manager.c.jj	2002-08-28 12:58:03.000000000 +0200
+++ libc/linuxthreads/manager.c	2002-10-07 23:55:45.000000000 +0200
@@ -388,6 +388,7 @@ static int pthread_allocate_stack(const 
       /* Clear the thread data structure.  */
       memset (new_thread, '\0', sizeof (*new_thread));
 #endif
+      stacksize = attr->__stacksize;
     }
   else
     {
@@ -555,6 +556,7 @@ static int pthread_allocate_stack(const 
 # endif  /* !NEED_SEPARATE_REGISTER_STACK */
 #endif   /* !FLOATING_STACKS */
     }
+  __set_alloca_cutoff (stacksize);
   *out_new_thread = (char *) new_thread;
   *out_new_thread_bottom = new_thread_bottom;
   *out_guardaddr = guardaddr;
--- libc/malloc/Versions.jj	2000-04-18 08:13:14.000000000 +0200
+++ libc/malloc/Versions	2002-10-07 23:54:46.000000000 +0200
@@ -55,4 +55,7 @@ libc {
     # p*
     posix_memalign;
   }
+  GLIBC_PRIVATE {
+    __libc_alloca_cutoff; __libc_set_alloca_cutoff;
+  }
 }
--- libc/malloc/Makefile.jj	2002-09-20 08:48:09.000000000 +0200
+++ libc/malloc/Makefile	2002-10-07 14:28:48.000000000 +0200
@@ -36,7 +36,7 @@ distribute = thread-m.h mtrace.pl mcheck
 gmalloc-routines := malloc morecore
 # Things to include in the standalone distribution.
 dist-routines = $(gmalloc-routines) mcheck mtrace
-routines = $(dist-routines) obstack
+routines = $(dist-routines) obstack allocalim
 
 install-lib := libmcheck.a
 non-lib.a := libmcheck.a
--- libc/malloc/allocalim.c.jj	2002-10-07 14:28:54.000000000 +0200
+++ libc/malloc/allocalim.c	2002-10-08 00:12:20.000000000 +0200
@@ -0,0 +1,36 @@
+/* Alloca upper bound handling.
+   Copyright (C) 2002 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
+   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 <stdlib.h>
+#include <bits/libc-lock.h>
+
+/* Default alloca cutoff.  */
+size_t __libc_alloca_cutoff = 65536;
+libc_hidden_data_def (__libc_alloca_cutoff)
+
+__libc_lock_define_initialized (static, lock);
+
+void __libc_set_alloca_cutoff (size_t size)
+{
+  __libc_lock_lock (lock);
+  if (__libc_alloca_cutoff > size)
+    __libc_alloca_cutoff = size;
+  __libc_lock_unlock (lock);
+}
+libc_hidden_def (__libc_set_alloca_cutoff)
--- 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-07 23:29:43.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_alloca_cutoff < 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_alloca_cutoff < 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-07 18:42:42.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_alloca_cutoff < 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_alloca_cutoff < 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-07 18:03:27.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_alloca_cutoff < 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-07 23:23:52.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_alloca_cutoff < 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_alloca_cutoff < 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-07 14:21:46.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 (len <= __libc_alloca_cutoff)				      \
 	      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 (prec <= __libc_alloca_cutoff)			      \
 		  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 (len + 1 < __libc_alloca_cutoff)			      \
 		      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 (width <= (int) (__libc_alloca_cutoff / 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 (width <= (int) (__libc_alloca_cutoff / sizeof (CHAR_T)))
 	    workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
 		       + (width + 32));
 	  else
@@ -1516,7 +1516,7 @@ 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)))
+	  if (prec <= (int) (__libc_alloca_cutoff / sizeof (CHAR_T)))
 	    workend = alloca (prec + 32) + (prec + 32);
 	  else
 	    {
@@ -1832,7 +1832,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 (MAX (prec, width)
+		<= (int) (__libc_alloca_cutoff / 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-07 14:21:46.000000000 +0200
@@ -869,7 +869,8 @@ __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
+      = chars_needed > __libc_alloca_cutoff / 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-07 14:21:46.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 (s1len + s2len > __libc_alloca_cutoff)
     {
       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-07 14:21:46.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 (srclen > __libc_alloca_cutoff)
     {
       idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1));
       rulearr = (unsigned char *) &idxarr[srclen];
--- libc/sysdeps/posix/readv.c.jj	2002-09-30 16:45:08.000000000 +0200
+++ libc/sysdeps/posix/readv.c	2002-10-07 14:21:46.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 (bytes <= __libc_alloca_cutoff)
     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-07 14:21:46.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 (bytes <= __libc_alloca_cutoff)
     buffer = (char *) __alloca (bytes);
   else
     {
--- libc/sysdeps/unix/sysv/linux/i386/setrlimit.c.jj	2001-08-23 18:50:59.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/i386/setrlimit.c	2002-10-08 00:32:58.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2002 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
@@ -24,6 +24,7 @@
 #include <sys/syscall.h>
 #include <shlib-compat.h>
 #include <bp-checks.h>
+#include <alloca.h>
 
 #include "kernel-features.h"
 
@@ -43,6 +44,9 @@ extern int __have_no_new_getrlimit; /* f
 int
 __new_setrlimit (enum __rlimit_resource resource, const struct rlimit *rlimits)
 {
+  if (__builtin_expect (resource == RLIMIT_STACK, 0))
+    __set_alloca_cutoff (rlimits->rlim_cur);
+
 #ifdef __ASSUME_NEW_GETRLIMIT_SYSCALL
   return INLINE_SYSCALL (setrlimit, 2, resource, CHECK_1 (rlimits));
 #else
--- libc/sysdeps/unix/sysv/linux/i386/getrlimit.c.jj	2001-08-23 18:50:54.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/i386/getrlimit.c	2002-10-08 00:32:49.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2002 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
@@ -44,10 +44,15 @@ int __have_no_new_getrlimit;
 int
 __new_getrlimit (enum __rlimit_resource resource, struct rlimit *rlimits)
 {
+  int result;
 #ifdef __ASSUME_NEW_GETRLIMIT_SYSCALL
-  return INLINE_SYSCALL (ugetrlimit, 2, resource, CHECK_1 (rlimits));
+  result = INLINE_SYSCALL (ugetrlimit, 2, resource, CHECK_1 (rlimits));
+
+  if (__builtin_expect (result != -1, 1)
+      && __builtin_expect (resource == RLIMIT_STACK, 0))
+    __set_alloca_cutoff (rlimits->rlim_cur);
+  return result;
 #else
-  int result;
 
 # ifdef __NR_ugetrlimit
   if (__have_no_new_getrlimit <= 0)
@@ -57,6 +62,9 @@ __new_getrlimit (enum __rlimit_resource 
       /* If the system call is available remember this fact and return.  */
       if (result != -1 || errno != ENOSYS)
 	{
+	  if (__builtin_expect (result != -1, 1)
+	      && __builtin_expect (resource == RLIMIT_STACK, 0))
+	    __set_alloca_cutoff (rlimits->rlim_cur);
 	  __have_no_new_getrlimit = -1;
 	  return result;
 	}
@@ -79,6 +87,8 @@ __new_getrlimit (enum __rlimit_resource 
   if (rlimits->rlim_max == RLIM_INFINITY >> 1)
     rlimits->rlim_max = RLIM_INFINITY;
 
+  if (__builtin_expect (resource == RLIMIT_STACK, 0))
+    __set_alloca_cutoff (rlimits->rlim_cur);
   return result;
 #endif
 }

	Jakub

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy)
  2002-10-07 16:20 [PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy) Jakub Jelinek
@ 2002-10-07 18:06 ` Ulrich Drepper
  2002-10-07 21:43   ` Roland McGrath
  0 siblings, 1 reply; 7+ messages in thread
From: Ulrich Drepper @ 2002-10-07 18:06 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Roland McGrath, Glibc hackers

-----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.

- -- 
- --------------.                        ,-.            444 Castro Street
Ulrich Drepper \    ,-----------------'   \ Mountain View, CA 94041 USA
Red Hat         `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE9ohab2ijCOnn/RHQRAnG+AKCOmM3rdHa+1Q2TxeRHC4wOQfR9cQCdHVoy
zx1jQytduWhMy1HB9GC3MCE=
=7Sy3
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy)
  2002-10-07 18:06 ` Ulrich Drepper
@ 2002-10-07 21:43   ` Roland McGrath
  2002-10-08  0:21     ` Ulrich Drepper
  2002-10-09  2:47     ` [PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2) Jakub Jelinek
  0 siblings, 2 replies; 7+ messages in thread
From: Roland McGrath @ 2002-10-07 21:43 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: Jakub Jelinek, Glibc hackers

> -----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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy)
  2002-10-07 21:43   ` Roland McGrath
@ 2002-10-08  0:21     ` Ulrich Drepper
       [not found]       ` <20021008024727.D5659@devserv.devel.redhat.com>
  2002-10-09  2:47     ` [PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2) Jakub Jelinek
  1 sibling, 1 reply; 7+ messages in thread
From: Ulrich Drepper @ 2002-10-08  0:21 UTC (permalink / raw)
  To: Roland McGrath; +Cc: Jakub Jelinek, Glibc hackers

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Roland McGrath wrote:

> Conversely instead of a variable we could have a function that's given the
> size and returns whether to use alloca or malloc.

The variable should definitely not be exported.  We should always only
use functions.


> The libc version can
> just say to always use alloca, I don't care about supporting tiny
> RLIMIT_STACK values for single-threaded programs.

Sure.  It always worked.



> The libpthread version
> can look at the thread's stack size vs the allocation, and perhaps even
> look at the current stack depth.

Yep.  We have the stack size in the thread descriptor anyway so in fact
we have the thread-local variable.


> Then we don't have to diddle setrlimit
> and all the rest, or add the word of TLS data

setrlimit is out anyway.  I'm not using it in nptl at all.


- -- 
- --------------.                        ,-.            444 Castro Street
Ulrich Drepper \    ,-----------------'   \ Mountain View, CA 94041 USA
Red Hat         `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE9omJM2ijCOnn/RHQRAiidAJwMDY/gohRR4oUMdJmUDg9TzmcWhwCfVtYJ
wJ9vAbZJfyii6TbCBU7uOE8=
=OzH7
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy)
       [not found]       ` <20021008024727.D5659@devserv.devel.redhat.com>
@ 2002-10-08  7:11         ` Ulrich Drepper
  0 siblings, 0 replies; 7+ messages in thread
From: Ulrich Drepper @ 2002-10-08  7:11 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Roland McGrath, Glibc hackers

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jakub Jelinek wrote:

> I diddled setrlimit because people may use it to set the default
> thread stack size instead of always using pthread_attr_setstacksize.

That's completely stupid and unsupported. I wouldn't waste a single
thought about people doing something like that.  The stack limit only
applies to the initial thread.

- -- 
- --------------.                        ,-.            444 Castro Street
Ulrich Drepper \    ,-----------------'   \ Mountain View, CA 94041 USA
Red Hat         `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE9ooeM2ijCOnn/RHQRAmo4AKDJanYc0bWNplShIRlkWvHqE1orrQCggCuF
iOeEUMxihGS3Es0MLpRKTsk=
=X2Fg
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2)
  2002-10-07 21:43   ` Roland McGrath
  2002-10-08  0:21     ` Ulrich Drepper
@ 2002-10-09  2:47     ` Jakub Jelinek
  2002-10-09  6:07       ` Ulrich Drepper
  1 sibling, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2002-10-09  2:47 UTC (permalink / raw)
  To: Roland McGrath; +Cc: Ulrich Drepper, Glibc hackers

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  <jakub@redhat.com>

	* 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 <allocalim.h>
+
 #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 <limits.h>
+
+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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2)
  2002-10-09  2:47     ` [PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2) Jakub Jelinek
@ 2002-10-09  6:07       ` Ulrich Drepper
  0 siblings, 0 replies; 7+ messages in thread
From: Ulrich Drepper @ 2002-10-09  6:07 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Roland McGrath, Glibc hackers

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I've applied Jakub's patch now and a few more non-code changes which are
necessary for a correct thread library (npt in this case).  This should
be about it for 2.3.1.  Please test it.  I just want to get the losers
with tiny stacks off my back so that we can get on with the development.

- -- 
- --------------.                        ,-.            444 Castro Street
Ulrich Drepper \    ,-----------------'   \ Mountain View, CA 94041 USA
Red Hat         `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE9o/sv2ijCOnn/RHQRApJ3AKCGZAA2aR8lApHDK5mxviEeSukxtACfb+xQ
EymApcl797bSPiEJSpzTHsE=
=c9pL
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-10-09  9:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-07 16:20 [PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy) Jakub Jelinek
2002-10-07 18:06 ` Ulrich Drepper
2002-10-07 21:43   ` Roland McGrath
2002-10-08  0:21     ` Ulrich Drepper
     [not found]       ` <20021008024727.D5659@devserv.devel.redhat.com>
2002-10-08  7:11         ` Ulrich Drepper
2002-10-09  2:47     ` [PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2) Jakub Jelinek
2002-10-09  6:07       ` Ulrich Drepper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).