util: Use posix_memalign for xmalloc_cacheline if available
authorYAMAMOTO Takashi <yamamoto@valinux.co.jp>
Fri, 2 May 2014 08:07:29 +0000 (17:07 +0900)
committerYAMAMOTO Takashi <yamamoto@valinux.co.jp>
Tue, 6 May 2014 22:31:50 +0000 (07:31 +0900)
A malloc library is expected to provide a better implementation
using the knowledge of its internal details.

ax_func_posix_memalign.m4 was obtained from:
http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_func_posix_memalign.m4

Acked-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
configure.ac
lib/util.c
m4/ax_func_posix_memalign.m4 [new file with mode: 0644]

index 9672cb0..16bc6a6 100644 (file)
@@ -91,6 +91,7 @@ OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(8)
 OVS_CHECK_POSIX_AIO
 OVS_CHECK_PTHREAD_SET_NAME
 OVS_CHECK_LINUX_HOST
+AX_FUNC_POSIX_MEMALIGN
 
 OVS_CHECK_INCLUDE_NEXT([stdio.h string.h])
 AC_CONFIG_FILES([lib/stdio.h lib/string.h])
index 1ebe22a..3dba335 100644 (file)
@@ -189,6 +189,17 @@ BUILD_ASSERT_DECL(CACHE_LINE_SIZE >= MEM_ALIGN);
 void *
 xmalloc_cacheline(size_t size)
 {
+#ifdef HAVE_POSIX_MEMALIGN
+    void *p;
+    int error;
+
+    COVERAGE_INC(util_xalloc);
+    error = posix_memalign(&p, CACHE_LINE_SIZE, size ? size : 1);
+    if (error != 0) {
+        out_of_memory();
+    }
+    return p;
+#else
     void **payload;
     void *base;
 
@@ -211,6 +222,7 @@ xmalloc_cacheline(size_t size)
     *payload = base;
 
     return (char *) payload + MEM_ALIGN;
+#endif
 }
 
 /* Like xmalloc_cacheline() but clears the allocated memory to all zero
@@ -228,9 +240,13 @@ xzalloc_cacheline(size_t size)
 void
 free_cacheline(void *p)
 {
+#ifdef HAVE_POSIX_MEMALIGN
+    free(p);
+#else
     if (p) {
         free(*(void **) ((uintptr_t) p - MEM_ALIGN));
     }
+#endif
 }
 
 char *
diff --git a/m4/ax_func_posix_memalign.m4 b/m4/ax_func_posix_memalign.m4
new file mode 100644 (file)
index 0000000..bd60adc
--- /dev/null
@@ -0,0 +1,50 @@
+# ===========================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_func_posix_memalign.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_FUNC_POSIX_MEMALIGN
+#
+# DESCRIPTION
+#
+#   Some versions of posix_memalign (notably glibc 2.2.5) incorrectly apply
+#   their power-of-two check to the size argument, not the alignment
+#   argument. AX_FUNC_POSIX_MEMALIGN defines HAVE_POSIX_MEMALIGN if the
+#   power-of-two check is correctly applied to the alignment argument.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Scott Pakin <pakin@uiuc.edu>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 7
+
+AC_DEFUN([AX_FUNC_POSIX_MEMALIGN],
+[AC_CACHE_CHECK([for working posix_memalign],
+  [ax_cv_func_posix_memalign_works],
+  [AC_TRY_RUN([
+#include <stdlib.h>
+
+int
+main ()
+{
+  void *buffer;
+
+  /* Some versions of glibc incorrectly perform the alignment check on
+   * the size word. */
+  exit (posix_memalign (&buffer, sizeof(void *), 123) != 0);
+}
+    ],
+    [ax_cv_func_posix_memalign_works=yes],
+    [ax_cv_func_posix_memalign_works=no],
+    [ax_cv_func_posix_memalign_works=no])])
+if test "$ax_cv_func_posix_memalign_works" = "yes" ; then
+  AC_DEFINE([HAVE_POSIX_MEMALIGN], [1],
+    [Define to 1 if `posix_memalign' works.])
+fi
+])