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 Sat, Jan 12, 2013 at 06:22:53PM +0100, OndÅej BÃlka wrote:
> Hello,
> I realized that I can make simpler and faster malloca than my previous
> attempt. 
> 
> 
> You need to write MALLOCA_INIT(); at function header. 
> Allocation is done my malloca(n) which allocates at most __MAX_ALLOCA_CUTOFF 
> bytes per stack frame.

> For deallocation it now suffices to call freeall() which frees all
> elements mallocated in frame.

I realized, that in glibc we do not have to deallocate manualy. It suffices to use
cleanup attribute which is supported since gcc 3.4. I could portably support 
it in c++ with destructors. 

Here is updated version. 


/* 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
   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).  It allocates N bytes of
   memory allocated on the stack until stack frame has __MAX_ALLOCA_CUTOFF
   bytes and heap otherwise. When memory cannot be allocated from heap
   malloca aborts.
   You must write MALLOCA_INIT() at start of each function that uses malloca.
   Memory is freed automaticaly. 
   You need at least gcc-3.4 to use this header. */

/* TODO: switch to later case when -fomit-frame-pointer.*/
#define _MALLOCA_INIT() void *__malloca_gc  __attribute__ ((__cleanup__ (__ifreeall))) = NULL;
#if 1
  #define MALLOCA_INIT() _MALLOCA_INIT ()
  #define __FRAME_ADDRESS __builtin_frame_address (0)
#else
  #define MALLOCA_INIT() _MALLOCA_INIT (); void *__frame_address = &__frame_address;
  #define __FRAME_ADDRESS __frame_address
#endif

#ifdef _STACK_GROWS_DOWN
  #define __MALLOCA_UB __FRAME_ADDRESS
  #define __MALLOCA_LB stackinfo_get_sp ()
#endif
#ifdef _STACK_GROWS_UP
  #define __MALLOCA_UB stackinfo_get_sp ()
  #define __MALLOCA_LB __FRAME_ADDRESS
#endif

#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 __libc_use_alloca(x) ( __MALLOCA_UB - __MALLOCA_LB + (x) < __MAX_ALLOCA_CUTOFF )

/* 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
/* 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 = ((void **)__malloca_gc)[0];
        free (__tmp);
      }
  }

static inline void __ifreeall (void * __malloca_gc)
  {
    if (__malloca_gc)
      __freeall (__malloca_gc);
  }

static void* __malloca_alloc (void *__malloca_gc,size_t __n)
  {
    void *__r         = malloc (__n + _MALLOC_ALIGNMENT);
    if (!__r || __n+_MALLOC_ALIGNMENT < _MALLOC_ALIGNMENT)
      abort ();
    ((void **)__r)[0] = __malloca_gc;
      __malloca_gc      = __r;
    return  __r + _MALLOC_ALIGNMENT;
  }
#endif

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

#undef alloca_account
#define alloca_account(n, var) ({                 \
  void *__r = alloca(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]