This is the mail archive of the mailing list for the glibc project.

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

Re: [PATCH] Use malloca instead alloca

On Mon, Jan 07, 2013 at 05:05:34PM -0800, Roland McGrath wrote:
> Paul's points are valid as a generic thing.  But they aren't the key
> points for considering changes to libc.
> The entire discussion about maximum usable size is unnecessary
> fritter.  We already have __libc_use_alloca, alloca_account,
> etc. (include/alloca.h) to govern that decision for libc code.
> If people want to discuss changing that logic, they can do that
> separately.  But we will certainly not have more than one separate
> implementation of such logic in libc.
> Extending that internal API in some fashion to make it less work to
> use would certainly be welcome.  That would have to be done in some
> way that doesn't add overhead when existing uses of __libc_use_alloca
> are converted to the new interface.  The simplest way to do that would
> be a macro interface that stores to a local bool, which is what the
> users of __libc_use_alloca mostly do now.  It would be nice to have an
> interface that is completely trivial to use like malloca is, but for
> code inside libc that ideal is less important than making sure we do
> not degrade the performance (including code size) of any of the
> existing uses.

I wrote a possible new interface below. 
I added __libc_use_alloca that tests if current stack frame will becomes 
larger than __MAX_ALLOCA_CUTOFF. However needs change of nptl __libc_use_alloca.

This makes alloca_account be counted twice so I aliased it with alloca
to be counted only once.

This could be more effective than current state as we do not need to
track counters. (modulo details like that on x64 stackinfo_get_sp 
definition causes %rsp be unnecessary copied into %rax.)

> There are a few existing uses of alloca that use their own ad hoc code
> instead of __libc_use_alloca (misc/err.c, sunrpc/auth_unix.c, maybe
> others).  Those should be converted to use __libc_use_alloca or
> whatever nicer interface is figured out.
> Then there are the existing uses of alloca that don't use
> __libc_use_alloca at all, such as argp/argp-help.c.  Those should
> probably be converted as well, though in some situations like the argp
> ones it's a bit hard to imagine their really being used with sizes
> large enough to matter.

One technical issue is if we want to use STACKINFO_BP_DEF. It would make
getting base pointer more portable but must be added to each function
that uses __libc_use_alloca. 

/* TODO: switch to later case when __builtin_frame_address don't work.  */
#if 1
  #define stackinfo_get_bp() __builtin_frame_address(0)
  #define STACKINFO_BP_DEF void *__stackinfo_bp = &__stackinfo_bp;
  #define stackinfo_get_bp() __stackinfo_bp

  #define __STACKINFO_UB stackinfo_get_bp ()
  #define __STACKINFO_LB stackinfo_get_sp ()
  #define __STACKINFO_UB stackinfo_get_sp ()
  #define __STACKINFO_LB stackinfo_get_bp ()

Then alloca can use following

#define __libc_use_alloca(x) \

#define alloca_account(n, var)  alloca(n)
#define extend_alloca_account(buf, len, newlen, avar) \
        extend_alloca        (buf, len, newlen, avar)

And here is new version of malloca.

/* Safe automatic memory allocation.
   Copyright (C) 2012 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, see <>.  */

#ifndef _MALLOCA_H
#define _MALLOCA_H


#include <alloca.h>
#include <stdlib.h>

#ifdef __cplusplus
extern "C" {

/* malloca(N) is a safe variant of alloca(N).  It allocates N bytes of
   memory allocated on the stack until stack frame has __MAX_ALLOCA_CUTOFF
   bytes and heap otherwise. 
   It must be freed using freea() before the function returns.  */

#define malloca(n) ({                             \
  size_t  __n__ = (n);                            \
  void  * __r__ = NULL;                           \
  if (__libc_use_alloca (__n__))                  \
    {                                             \
      __r__ = alloca (__n__);                     \
    }                                             \
  else                                            \
    {                                             \
      __r__ = malloc (__n__);                     \
    }                                             \
  __r__;                                          \

/* Maybe it is faster to use unsigned comparison such as

#define freea(r) do {                             \
  void *__r = (r);                                \
  if ( __r && !( __STACKINFO_LB <= __r &          \
                 __r <= __STACKINFO_UB ))         \
    free (__r);                                   \
} while (0)

#ifdef __cplusplus

#define malloca(x) malloc (x)
#define freea(x)   free (x)

#endif /* _MALLOCA_H */

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