This is the mail archive of the libc-alpha@sourceware.org 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] malloca v2


On Sun, Jan 13, 2013 at 12:34:23PM -0800, Paul Eggert wrote:
> Some comments:
> 
Thanks, they were helpful. 

I decided to write portable implementation for now and add platform
specific optimizations later.

I wanted to be also eventualy used outside libc, one of possible
applications. 

Now it only requires a cleanup attribute which most compilers supported 
for ages. 

Roland, what is your opinion? If this would be accepted as new interface
 I could replace libc_use_alloca/alloca_account logic by malloca which would 
simplify implementation and had faster allocation and free paths.


/* Safe automatic memory allocation.
   Copyright (C) 2012-2013 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
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   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 <http://www.gnu.org/licenses/>.  */

#ifndef _MALLOCA_H
#define _MALLOCA_H

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

#ifdef __cplusplus
extern "C" {
#endif

/* malloca(N) is a safe variant of alloca(N). Malloca allocates N bytes of
   memory from stack until limit specified below in MALLOCA_INIT_CUTOFF
   is reached. Then it returns memory allocated on heap.
   When no memory is available malloca returns NULL.
   
   At start of function you have to write MALLOCA_INIT_CUTOFF(S) to specify
   that all malloca calls use together at most S bytes of stack memory.
   You can instead write MALLOCA_INIT which supplies a reasonable default.


   Memory is freed automatically when function returns.

   This header can be used with c compilers that supports cleanup attribute.  */


#ifndef __MAX_ALLOCA_CUTOFF 
  #define __MAX_ALLOCA_CUTOFF (1<<16)
#endif
#ifdef MALLOC_ALIGNMENT
  #define _MALLOC_ALIGNMENT MALLOC_ALIGNMENT
#else
  #define _MALLOC_ALIGNMENT 16
#endif

#define MALLOCA_INIT MALLOCA_INIT_CUTOFF(__MAX_ALLOCA_CUTOFF)

#define MALLOCA_INIT_CUTOFF(__siz)                                       \
  void  *__malloca_gc  __attribute__ ((__cleanup__ (__ifreeall))) = NULL;\
  size_t __frame_estimate = (__siz);                                     


/* These functions are used to save space factoring out paths that rarely happen.  */
#ifdef SHARED_MALLOCA
void  __freeall       (void *__malloca_gc);
void *__malloca_alloc (void *__malloca_gc,size_t __n);
#else
static void *
__malloca_alloc (void *__malloca_gc,size_t __n)
{
  size_t __al = __n + _MALLOC_ALIGNMENT;
  void *__r   = malloc (__al);
  void **__pr  = __r;
  if (!__r || __al < _MALLOC_ALIGNMENT)
    return NULL;
  *__pr = __malloca_gc;
  __malloca_gc      = __pr;
  return  __r + _MALLOC_ALIGNMENT;
}

/* Noinline because gcc inlines this to __ifreeall which defeats the point.  */
__attribute ((noinline)) static void 
__freeall (void *__malloca_gc) 
{
  while (__malloca_gc)
    {
      void **__tmp = __malloca_gc;
      __malloca_gc = *__tmp;
      free (__tmp);
    }
}
#endif
static inline void 
__ifreeall (void *__malloca_gc)
{
  if (__malloca_gc)
    __freeall (__malloca_gc);
}

/* Possibly faster test is __frame_estimate - __n <= __frame_estimate
which uses unsigned wraparound.  */

#define malloca(n) ({                             \
  size_t  __n = (n);                              \
  void  *__r;                                     \
  if (__frame_estimate >= (__n))                  \
    {                                             \
      __frame_estimate -= (__n);                  \
      __r = alloca (__n);                         \
    }                                             \
  else                                            \
    {                                             \
      __r = __malloca_alloc (__malloca_gc, __n);  \
    }                                             \
  __r;                                            \
})


#ifdef __cplusplus
}
#endif

#endif /* _MALLOCA_H */


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