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]

[PATCH] Use malloca instead alloca


As I described in http://sourceware.org/ml/libc-alpha/2012-12/msg00459.html 
I looked into using malloca.

It has two advantages, first is to avoid allocation large arrays into
stack, second is simplifying code by reducing number of #ifdef's

Initialy I examined gnulib one but it uses hash tables and is hard to
inline so I wrote faster variant.

As example I added used it in argp/argp-help.c .
I did not do more general alloca detection that glibc uses. 

Also it could be possible GNU extension for 2.18?

---
 argp/argp-help.c |   23 ++++--------
 malloc/malloca.h |  102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+), 16 deletions(-)
 create mode 100644 malloc/malloca.h

diff --git a/argp/argp-help.c b/argp/argp-help.c
index 80c2b7d..f0f74b4 100644
--- a/argp/argp-help.c
+++ b/argp/argp-help.c
@@ -25,20 +25,7 @@
 #include <config.h>
 #endif
 
-/* AIX requires this to be the first thing in the file.  */
-#ifndef __GNUC__
-# if HAVE_ALLOCA_H || defined _LIBC
-#  include <alloca.h>
-# else
-#  ifdef _AIX
-#pragma alloca
-#  else
-#   ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-#   endif
-#  endif
-# endif
-#endif
+#include <malloc/malloca.h>
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -1310,11 +1297,12 @@ usage_long_opt (const struct argp_option *opt,
 static void
 hol_usage (struct hol *hol, argp_fmtstream_t stream)
 {
+  char *short_no_arg_opts = NULL;
   if (hol->num_entries > 0)
     {
       unsigned nentries;
       struct hol_entry *entry;
-      char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
+      short_no_arg_opts = malloca (strlen (hol->short_options) + 1);
       char *snao_end = short_no_arg_opts;
 
       /* First we put a list of short options without arguments.  */
@@ -1343,6 +1331,7 @@ hol_usage (struct hol *hol, argp_fmtstream_t stream)
 	hol_entry_long_iterate (entry, usage_long_opt,
 				entry->argp->argp_domain, stream);
     }
+  freea(short_no_arg_opts);
 }
 
 /* Make a HOL containing all levels of options in ARGP.  CLUSTER is the
@@ -1547,6 +1536,7 @@ static void
 _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
        unsigned flags, char *name)
 {
+  char *pattern_levels = NULL;
   int anything = 0;		/* Whether we've output anything.  */
   struct hol *hol = 0;
   argp_fmtstream_t fs;
@@ -1585,7 +1575,7 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
     {
       int first_pattern = 1, more_patterns;
       size_t num_pattern_levels = argp_args_levels (argp);
-      char *pattern_levels = alloca (num_pattern_levels);
+      pattern_levels = malloca (num_pattern_levels);
 
       memset (pattern_levels, 0, num_pattern_levels);
 
@@ -1680,6 +1670,7 @@ Try `%s --help' or `%s --usage' for more information.\n"),
   if (hol)
     hol_free (hol);
 
+  freea (pattern_levels);
   __argp_fmtstream_free (fs);
 }
 
diff --git a/malloc/malloca.h b/malloc/malloca.h
new file mode 100644
index 0000000..fbae6e8
--- /dev/null
+++ b/malloc/malloca.h
@@ -0,0 +1,102 @@
+/* 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 <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ALLOCA_MC 0x2439a2431bca4812L
+#define MALLOC_MC 0x1bca48122439a243L
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H || defined _LIBC
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+#pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+
+  /* malloca(N) is a safe variant of alloca(N).  It allocates N bytes of
+     memory allocated on the stack or heap for large requests.
+     It must be freed using freea() before
+     the function returns.  Upon failure, it returns NULL.  */
+#if 1
+#define malloca(n) ({\
+  void *__r__ = NULL;\
+  if (n < 4096 - 8)\
+    {\
+      __r__ = alloca (n + sizeof (uint64_t));\
+      if (__r__)\
+        {\
+          *((uint64_t *)__r__)=ALLOCA_MC;\
+          __r__ += sizeof (uint64_t);\
+        }\
+    }\
+  if (!__r__)\
+    {\
+      __r__ = malloc (n + sizeof (uint64_t));\
+      if (__r__)\
+        {\
+          *((uint64_t *)__r__)=MALLOC_MC;\
+          __r__ += sizeof (uint64_t);\
+        }\
+    }\
+  __r__;\
+})
+
+#define freea(r) {\
+void *__r__ = r;\
+if (__r__)\
+  {\
+    __r__ -= sizeof (uint64_t);\
+    if  (*((uint64_t *)__r__) == MALLOC_MC)\
+      free (__r__);\
+    else if (*((uint64_t *)__r__) != ALLOCA_MC) abort_freea();\
+  }\
+}
+
+static void abort_freea()
+{
+  fprintf(stderr, "double freea or corruption\n");
+  abort();
+}
+#else
+#define malloca malloc
+#define freea   free
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MALLOCA_H */
-- 
1.7.4.4


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