Added futex barriers to libgomp for ros
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 18 Dec 2012 08:39:40 +0000 (00:39 -0800)
committerKevin Klues <klueska@cs.berkeley.edu>
Tue, 18 Dec 2012 09:12:40 +0000 (01:12 -0800)
tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/bar.c [new file with mode: 0644]
tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/bar.h [new file with mode: 0644]
tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/futex.h [new file with mode: 0644]
tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/wait.h [new file with mode: 0644]
tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/configure.tgt [new file with mode: 0644]

diff --git a/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/bar.c b/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/bar.c
new file mode 100644 (file)
index 0000000..3e0379e
--- /dev/null
@@ -0,0 +1,122 @@
+/* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
+   Contributed by Richard Henderson <rth@redhat.com>.
+
+   This file is part of the GNU OpenMP Library (libgomp).
+
+   Libgomp 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 3, or (at your option)
+   any later version.
+
+   Libgomp 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is a Linux specific implementation of a barrier synchronization
+   mechanism for libgomp.  This type is private to the library.  This 
+   implementation uses atomic instructions and the futex syscall.  */
+
+#include <limits.h>
+#include "wait.h"
+
+
+void
+gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+  if (__builtin_expect ((state & 1) != 0, 0))
+    {
+      /* Next time we'll be awaiting TOTAL threads again.  */
+      bar->awaited = bar->total;
+      atomic_write_barrier ();
+      bar->generation += 4;
+      futex_wake ((int *) &bar->generation, INT_MAX);
+    }
+  else
+    {
+      unsigned int generation = state;
+
+      do
+       do_wait ((int *) &bar->generation, generation);
+      while (bar->generation == generation);
+    }
+}
+
+void
+gomp_barrier_wait (gomp_barrier_t *bar)
+{
+  gomp_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
+}
+
+/* Like gomp_barrier_wait, except that if the encountering thread
+   is not the last one to hit the barrier, it returns immediately.
+   The intended usage is that a thread which intends to gomp_barrier_destroy
+   this barrier calls gomp_barrier_wait, while all other threads
+   call gomp_barrier_wait_last.  When gomp_barrier_wait returns,
+   the barrier can be safely destroyed.  */
+
+void
+gomp_barrier_wait_last (gomp_barrier_t *bar)
+{
+  gomp_barrier_state_t state = gomp_barrier_wait_start (bar);
+  if (state & 1)
+    gomp_barrier_wait_end (bar, state);
+}
+
+void
+gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
+{
+  futex_wake ((int *) &bar->generation, count == 0 ? INT_MAX : count);
+}
+
+void
+gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+  unsigned int generation;
+
+  if (__builtin_expect ((state & 1) != 0, 0))
+    {
+      /* Next time we'll be awaiting TOTAL threads again.  */
+      struct gomp_thread *thr = gomp_thread ();
+      struct gomp_team *team = thr->ts.team;
+      bar->awaited = bar->total;
+      atomic_write_barrier ();
+      if (__builtin_expect (team->task_count, 0))
+       {
+         gomp_barrier_handle_tasks (state);
+         state &= ~1;
+       }
+      else
+       {
+         bar->generation = state + 3;
+         futex_wake ((int *) &bar->generation, INT_MAX);
+         return;
+       }
+    }
+
+  generation = state;
+  do
+    {
+      do_wait ((int *) &bar->generation, generation);
+      if (__builtin_expect (bar->generation & 1, 0))
+       gomp_barrier_handle_tasks (state);
+      if ((bar->generation & 2))
+       generation |= 2;
+    }
+  while (bar->generation != state + 4);
+}
+
+void
+gomp_team_barrier_wait (gomp_barrier_t *bar)
+{
+  gomp_team_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
+}
diff --git a/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/bar.h b/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/bar.h
new file mode 100644 (file)
index 0000000..9c1a8a0
--- /dev/null
@@ -0,0 +1,118 @@
+/* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
+   Contributed by Richard Henderson <rth@redhat.com>.
+
+   This file is part of the GNU OpenMP Library (libgomp).
+
+   Libgomp 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 3, or (at your option)
+   any later version.
+
+   Libgomp 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is a Linux specific implementation of a barrier synchronization
+   mechanism for libgomp.  This type is private to the library.  This 
+   implementation uses atomic instructions and the futex syscall.  */
+
+#ifndef GOMP_BARRIER_H
+#define GOMP_BARRIER_H 1
+
+#include "mutex.h"
+
+typedef struct
+{
+  /* Make sure total/generation is in a mostly read cacheline, while
+     awaited in a separate cacheline.  */
+  unsigned total __attribute__((aligned (64)));
+  unsigned generation;
+  unsigned awaited __attribute__((aligned (64)));
+} gomp_barrier_t;
+typedef unsigned int gomp_barrier_state_t;
+
+static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
+{
+  bar->total = count;
+  bar->awaited = count;
+  bar->generation = 0;
+}
+
+static inline void gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
+{
+  __sync_fetch_and_add (&bar->awaited, count - bar->total);
+  bar->total = count;
+}
+
+static inline void gomp_barrier_destroy (gomp_barrier_t *bar)
+{
+}
+
+extern void gomp_barrier_wait (gomp_barrier_t *);
+extern void gomp_barrier_wait_last (gomp_barrier_t *);
+extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t);
+extern void gomp_team_barrier_wait (gomp_barrier_t *);
+extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
+                                       gomp_barrier_state_t);
+extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
+
+static inline gomp_barrier_state_t
+gomp_barrier_wait_start (gomp_barrier_t *bar)
+{
+  unsigned int ret = bar->generation & ~3;
+  /* Do we need any barrier here or is __sync_add_and_fetch acting
+     as the needed LoadLoad barrier already?  */
+  ret += __sync_add_and_fetch (&bar->awaited, -1) == 0;
+  return ret;
+}
+
+static inline bool
+gomp_barrier_last_thread (gomp_barrier_state_t state)
+{
+  return state & 1;
+}
+
+/* All the inlines below must be called with team->task_lock
+   held.  */
+
+static inline void
+gomp_team_barrier_set_task_pending (gomp_barrier_t *bar)
+{
+  bar->generation |= 1;
+}
+
+static inline void
+gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
+{
+  bar->generation &= ~1;
+}
+
+static inline void
+gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
+{
+  bar->generation |= 2;
+}
+
+static inline bool
+gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
+{
+  return (bar->generation & 2) != 0;
+}
+
+static inline void
+gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+  bar->generation = (state & ~3) + 4;
+}
+
+#endif /* GOMP_BARRIER_H */
diff --git a/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/futex.h b/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/futex.h
new file mode 100644 (file)
index 0000000..3a22de0
--- /dev/null
@@ -0,0 +1,53 @@
+/* Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of the GNU OpenMP Library (libgomp).
+
+   Libgomp 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 3, or (at your option)
+   any later version.
+
+   Libgomp 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Provide target-specific access to the futex system call.  */
+
+/* The include file hierachy above us (wait.h) has pushed visibility
+   hidden, this will be applied to prototypes with headers we include
+   with the effect that we cannot link against an external function
+   (syscall). The solution here is to push default visibility, include
+   our required headers then reinstante the original visibility.  */
+
+#include <ros/futex.h>
+
+static inline void
+futex_wait (int *addr, int val)
+{
+  int ret = futex(addr, FUTEX_WAIT, val, NULL, NULL, 0);
+  assert(!ret);
+}
+
+static inline void
+futex_wake (int *addr, int count)
+{
+  int ret = futex(addr, FUTEX_WAKE, count, NULL, NULL, 0);
+  assert(!ret);
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+  __sync_synchronize ();
+}
diff --git a/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/wait.h b/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/config/ros/wait.h
new file mode 100644 (file)
index 0000000..0afce75
--- /dev/null
@@ -0,0 +1,58 @@
+/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+   Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+   This file is part of the GNU OpenMP Library (libgomp).
+
+   Libgomp 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 3, or (at your option)
+   any later version.
+
+   Libgomp 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This is a Linux specific implementation of a mutex synchronization
+   mechanism for libgomp.  This type is private to the library.  This
+   implementation uses atomic instructions and the futex syscall.  */
+
+#ifndef GOMP_WAIT_H
+#define GOMP_WAIT_H 1
+
+#include "libgomp.h"
+#include <errno.h>
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility push(hidden)
+#endif
+#include "futex.h"
+
+static inline void do_wait (int *addr, int val)
+{
+  unsigned long long i, count = gomp_spin_count_var;
+
+  if (__builtin_expect (gomp_managed_threads > gomp_available_cpus, 0))
+    count = gomp_throttled_spin_count_var;
+  for (i = 0; i < count; i++)
+    if (__builtin_expect (*addr != val, 0))
+      return;
+    else
+      cpu_relax ();
+  futex_wait (addr, val);
+}
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
+#endif /* GOMP_WAIT_H */
diff --git a/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/configure.tgt b/tools/compilers/gcc-glibc/gcc-4.6.1-ros/libgomp/configure.tgt
new file mode 100644 (file)
index 0000000..d037711
--- /dev/null
@@ -0,0 +1,143 @@
+# This is the target specific configuration file.  This is invoked by the
+# autoconf generated configure script.  Putting it in a separate shell file
+# lets us skip running autoconf when modifying target specific information.
+
+# This file switches on the shell variable ${target}, and sets the
+# following shell variables:
+#  config_path         An ordered list of directories to search for
+#                      sources and headers.  This is relative to the
+#                      config subdirectory of the source tree.
+#  XCFLAGS             Add extra compile flags to use.
+#  XLDFLAGS            Add extra link flags to use.
+
+# Optimize TLS usage by avoiding the overhead of dynamic allocation.
+if test $gcc_cv_have_tls = yes ; then
+  case "${target}" in
+
+    *-*-linux*)
+       XCFLAGS="${XCFLAGS} -ftls-model=initial-exec"
+       ;;
+  esac
+fi
+
+# Since we require POSIX threads, assume a POSIX system by default.
+config_path="posix"
+
+# Check for futex enabled all at once.
+if test $enable_linux_futex = yes; then
+  case "${target}" in
+
+    alpha*-*-linux*)
+       config_path="linux/alpha linux posix"
+       ;;
+
+    arm*-*-linux*)
+       config_path="linux/arm linux posix"
+       ;;
+
+    ia64*-*-linux*)
+       config_path="linux/ia64 linux posix"
+       ;;
+
+    mips*-*-linux*)
+       config_path="linux/mips linux posix"
+       ;;
+
+    powerpc*-*-linux*)
+       config_path="linux/powerpc linux posix"
+       ;;
+
+    s390*-*-linux*)
+       config_path="linux/s390 linux posix"
+       ;;
+
+    # Note that bare i386 is not included here.  We need cmpxchg.
+    i[456]86-*-linux*)
+       config_path="linux/x86 linux posix"
+       case " ${CC} ${CFLAGS} " in
+         *" -m64 "*)
+           ;;
+         *)
+           if test -z "$with_arch"; then
+             XCFLAGS="${XCFLAGS} -march=i486 -mtune=${target_cpu}"
+           fi
+       esac
+       ;;
+
+    # Similar jiggery-pokery for x86_64 multilibs, except here we
+    # can't rely on the --with-arch configure option, since that
+    # applies to the 64-bit side.
+    x86_64-*-linux*)
+       config_path="linux/x86 linux posix"
+       case " ${CC} ${CFLAGS} " in
+         *" -m32 "*)
+           XCFLAGS="${XCFLAGS} -march=i486 -mtune=i686"
+           ;;
+       esac
+       ;;
+
+    # Note that sparcv7 and sparcv8 is not included here.  We need cas.
+    sparcv9-*-linux* | sparc64-*-linux*)
+       echo "int i;" > conftestx.c
+       if ${CC} ${CFLAGS} -c -o conftestx.o conftestx.c > /dev/null 2>&1; then
+         config_path="linux/sparc linux posix"
+         case "`/usr/bin/file conftestx.o`" in
+           *32-bit*)
+             case " ${CC} ${CFLAGS}" in
+               *" -mcpu=ultrasparc"*)
+                 ;;
+               *)
+                 XCFLAGS="${XCFLAGS} -mcpu=v9"
+                 ;;
+             esac
+             ;;
+         esac
+       fi
+       rm -f conftestx.c conftestx.o
+       ;;
+  esac
+fi
+
+# Other system configury
+case "${target}" in
+
+  *-*-hpux*)
+       case "${target}" in
+         *-*-hpux11*)
+            # HPUX v11.x requires -lrt to resolve sem_init in libgomp.la
+            XLDFLAGS="${XLDFLAGS} -lrt"
+            ;;
+       esac
+       case "${target}" in
+         hppa[12]*-*-hpux*)
+           # PA 32 HP-UX needs -frandom-seed for bootstrap compare.
+           XCFLAGS="${XCFLAGS} -frandom-seed=fixed-seed"
+           ;;
+       esac
+       ;;
+
+  *-*-ros*)
+       config_path="ros posix"
+       ;;
+
+  *-*-mingw32*)
+       config_path="mingw32 posix"
+       ;;
+
+  *-*-darwin*)
+       config_path="bsd posix"
+       ;;
+
+  *-*-freebsd*)
+       # Need to link with -lpthread so libgomp.so is self-contained.
+       XLDFLAGS="${XLDFLAGS} -lpthread"
+       ;;
+
+  mips-sgi-irix6*)
+       # Need to link with -lpthread so libgomp.so is self-contained.
+       XLDFLAGS="${XLDFLAGS} -lpthread"
+       ;;
+  *)
+       ;;
+
+esac