This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] __libc_use_alloca (aka make mysql and others apps with very low RLIMIT_STACK setting happy; take 2)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]