[gomp] Add RTEMS configuration
authorSebastian Huber <sebastian.huber@embedded-brains.de>
Thu, 3 Sep 2015 11:26:36 +0000 (11:26 +0000)
committerSebastian Huber <sh@gcc.gnu.org>
Thu, 3 Sep 2015 11:26:36 +0000 (11:26 +0000)
libgomp/ChangeLog

* config/rtems/bar.c: New.
* config/rtems/bar.h: Likewise.
* config/rtems/mutex.c: Likewise.
* config/rtems/mutex.h: Likewise.
* config/rtems/sem.c: Likewise.
* config/rtems/sem.h: Likewise.
* configure.ac (*-*-rtems*): Check that Newlib provides a proper
<sys/lock.h> header file.
* configure.tgt (*-*-rtems*): Enable RTEMS configuration if
supported by Newlib.
* configure: Regenerate.

From-SVN: r227440

libgomp/ChangeLog
libgomp/config/rtems/bar.c [new file with mode: 0644]
libgomp/config/rtems/bar.h [new file with mode: 0644]
libgomp/config/rtems/mutex.c [new file with mode: 0644]
libgomp/config/rtems/mutex.h [new file with mode: 0644]
libgomp/config/rtems/sem.c [new file with mode: 0644]
libgomp/config/rtems/sem.h [new file with mode: 0644]
libgomp/configure
libgomp/configure.ac
libgomp/configure.tgt

index 319795c41ba62bcefabe826f259efc8e0ccdc918..c3e94bfa1bcb23944ad20a8b0e57f36a0222e0af 100644 (file)
@@ -1,3 +1,17 @@
+2015-09-03  Sebastian Huber  <sebastian.huber@embedded-brains.de>
+
+       * config/rtems/bar.c: New.
+       * config/rtems/bar.h: Likewise.
+       * config/rtems/mutex.c: Likewise.
+       * config/rtems/mutex.h: Likewise.
+       * config/rtems/sem.c: Likewise.
+       * config/rtems/sem.h: Likewise.
+       * configure.ac (*-*-rtems*): Check that Newlib provides a proper
+       <sys/lock.h> header file.
+       * configure.tgt (*-*-rtems*): Enable RTEMS configuration if
+       supported by Newlib.
+       * configure: Regenerate.
+
 2015-09-03  Sebastian Huber  <sebastian.huber@embedded-brains.de>
 
        * team.c (gomp_new_thread_pool): Delete and move content to ...
diff --git a/libgomp/config/rtems/bar.c b/libgomp/config/rtems/bar.c
new file mode 100644 (file)
index 0000000..e5b3f76
--- /dev/null
@@ -0,0 +1,255 @@
+/* Copyright (C) 2005-2015 Free Software Foundation, Inc.
+   Contributed by Sebastian Huber <sebastian.huber@embedded-brains.de>.
+
+   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 the RTEMS implementation of a barrier synchronization
+   mechanism for libgomp.  It is identical to the Linux implementation, except
+   that the futex API is slightly different.  This type is private to the
+   library.  */
+
+#include "libgomp.h"
+#include "bar.h"
+#include <limits.h>
+
+static gomp_barrier_t *
+generation_to_barrier (int *addr)
+{
+  return (gomp_barrier_t *)
+        ((char *) addr - __builtin_offsetof (gomp_barrier_t, generation));
+}
+
+static void
+futex_wait (int *addr, int val)
+{
+  gomp_barrier_t *bar = generation_to_barrier (addr);
+  _Futex_Wait (&bar->futex, addr, val);
+}
+
+static void
+futex_wake (int *addr, int count)
+{
+  gomp_barrier_t *bar = generation_to_barrier (addr);
+  _Futex_Wake (&bar->futex, count);
+}
+
+static int
+do_spin (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 (__atomic_load_n (addr, MEMMODEL_RELAXED) != val, 0))
+      return 0;
+  return 1;
+}
+
+static void
+do_wait (int *addr, int val)
+{
+  if (do_spin (addr, val))
+    futex_wait (addr, val);
+}
+
+/* Everything below this point should be identical to the Linux
+   implementation.  */
+
+void
+gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+  if (__builtin_expect (state & BAR_WAS_LAST, 0))
+    {
+      /* Next time we'll be awaiting TOTAL threads again.  */
+      bar->awaited = bar->total;
+      __atomic_store_n (&bar->generation, bar->generation + BAR_INCR,
+                       MEMMODEL_RELEASE);
+      futex_wake ((int *) &bar->generation, INT_MAX);
+    }
+  else
+    {
+      do
+       do_wait ((int *) &bar->generation, state);
+      while (__atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE) == state);
+    }
+}
+
+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 & BAR_WAS_LAST)
+    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, gen;
+
+  if (__builtin_expect (state & BAR_WAS_LAST, 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;
+      team->work_share_cancelled = 0;
+      if (__builtin_expect (team->task_count, 0))
+       {
+         gomp_barrier_handle_tasks (state);
+         state &= ~BAR_WAS_LAST;
+       }
+      else
+       {
+         state &= ~BAR_CANCELLED;
+         state += BAR_INCR - BAR_WAS_LAST;
+         __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE);
+         futex_wake ((int *) &bar->generation, INT_MAX);
+         return;
+       }
+    }
+
+  generation = state;
+  state &= ~BAR_CANCELLED;
+  do
+    {
+      do_wait ((int *) &bar->generation, generation);
+      gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+      if (__builtin_expect (gen & BAR_TASK_PENDING, 0))
+       {
+         gomp_barrier_handle_tasks (state);
+         gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+       }
+      generation |= gen & BAR_WAITING_FOR_TASK;
+    }
+  while (gen != state + BAR_INCR);
+}
+
+void
+gomp_team_barrier_wait (gomp_barrier_t *bar)
+{
+  gomp_team_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
+}
+
+void
+gomp_team_barrier_wait_final (gomp_barrier_t *bar)
+{
+  gomp_barrier_state_t state = gomp_barrier_wait_final_start (bar);
+  if (__builtin_expect (state & BAR_WAS_LAST, 0))
+    bar->awaited_final = bar->total;
+  gomp_team_barrier_wait_end (bar, state);
+}
+
+bool
+gomp_team_barrier_wait_cancel_end (gomp_barrier_t *bar,
+                                  gomp_barrier_state_t state)
+{
+  unsigned int generation, gen;
+
+  if (__builtin_expect (state & BAR_WAS_LAST, 0))
+    {
+      /* Next time we'll be awaiting TOTAL threads again.  */
+      /* BAR_CANCELLED should never be set in state here, because
+        cancellation means that at least one of the threads has been
+        cancelled, thus on a cancellable barrier we should never see
+        all threads to arrive.  */
+      struct gomp_thread *thr = gomp_thread ();
+      struct gomp_team *team = thr->ts.team;
+
+      bar->awaited = bar->total;
+      team->work_share_cancelled = 0;
+      if (__builtin_expect (team->task_count, 0))
+       {
+         gomp_barrier_handle_tasks (state);
+         state &= ~BAR_WAS_LAST;
+       }
+      else
+       {
+         state += BAR_INCR - BAR_WAS_LAST;
+         __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE);
+         futex_wake ((int *) &bar->generation, INT_MAX);
+         return false;
+       }
+    }
+
+  if (__builtin_expect (state & BAR_CANCELLED, 0))
+    return true;
+
+  generation = state;
+  do
+    {
+      do_wait ((int *) &bar->generation, generation);
+      gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+      if (__builtin_expect (gen & BAR_CANCELLED, 0))
+       return true;
+      if (__builtin_expect (gen & BAR_TASK_PENDING, 0))
+       {
+         gomp_barrier_handle_tasks (state);
+         gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+       }
+      generation |= gen & BAR_WAITING_FOR_TASK;
+    }
+  while (gen != state + BAR_INCR);
+
+  return false;
+}
+
+bool
+gomp_team_barrier_wait_cancel (gomp_barrier_t *bar)
+{
+  return gomp_team_barrier_wait_cancel_end (bar, gomp_barrier_wait_start (bar));
+}
+
+void
+gomp_team_barrier_cancel (struct gomp_team *team)
+{
+  gomp_mutex_lock (&team->task_lock);
+  if (team->barrier.generation & BAR_CANCELLED)
+    {
+      gomp_mutex_unlock (&team->task_lock);
+      return;
+    }
+  team->barrier.generation |= BAR_CANCELLED;
+  gomp_mutex_unlock (&team->task_lock);
+  futex_wake ((int *) &team->barrier.generation, INT_MAX);
+}
diff --git a/libgomp/config/rtems/bar.h b/libgomp/config/rtems/bar.h
new file mode 100644 (file)
index 0000000..c85dce3
--- /dev/null
@@ -0,0 +1,170 @@
+/* Copyright (C) 2005-2015 Free Software Foundation, Inc.
+   Contributed by Sebastian Huber <sebastian.huber@embedded-brains.de>.
+
+   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 the RTEMS implementation of a barrier synchronization
+   mechanism for libgomp.  It is identical to the Linux implementation, except
+   that the futex API is slightly different.  This type is private to the
+   library.  */
+
+#ifndef GOMP_BARRIER_H
+#define GOMP_BARRIER_H 1
+
+#include <sys/lock.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;
+  struct _Futex_Control futex;
+  unsigned awaited __attribute__((aligned (64)));
+  unsigned awaited_final;
+} gomp_barrier_t;
+
+typedef unsigned int gomp_barrier_state_t;
+
+/* The generation field contains a counter in the high bits, with a few
+   low bits dedicated to flags.  Note that TASK_PENDING and WAS_LAST can
+   share space because WAS_LAST is never stored back to generation.  */
+#define BAR_TASK_PENDING       1
+#define BAR_WAS_LAST           1
+#define BAR_WAITING_FOR_TASK   2
+#define BAR_CANCELLED          4
+#define BAR_INCR               8
+
+static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
+{
+  bar->total = count;
+  bar->awaited = count;
+  bar->awaited_final = count;
+  bar->generation = 0;
+  _Futex_Initialize (&bar->futex);
+}
+
+static inline void gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
+{
+  __atomic_add_fetch (&bar->awaited, count - bar->total, MEMMODEL_ACQ_REL);
+  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_final (gomp_barrier_t *);
+extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
+                                       gomp_barrier_state_t);
+extern bool gomp_team_barrier_wait_cancel (gomp_barrier_t *);
+extern bool gomp_team_barrier_wait_cancel_end (gomp_barrier_t *,
+                                              gomp_barrier_state_t);
+extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
+struct gomp_team;
+extern void gomp_team_barrier_cancel (struct gomp_team *);
+
+static inline gomp_barrier_state_t
+gomp_barrier_wait_start (gomp_barrier_t *bar)
+{
+  unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+  ret &= -BAR_INCR | BAR_CANCELLED;
+  /* A memory barrier is needed before exiting from the various forms
+     of gomp_barrier_wait, to satisfy OpenMP API version 3.1 section
+     2.8.6 flush Construct, which says there is an implicit flush during
+     a barrier region.  This is a convenient place to add the barrier,
+     so we use MEMMODEL_ACQ_REL here rather than MEMMODEL_ACQUIRE.  */
+  if (__atomic_add_fetch (&bar->awaited, -1, MEMMODEL_ACQ_REL) == 0)
+    ret |= BAR_WAS_LAST;
+  return ret;
+}
+
+static inline gomp_barrier_state_t
+gomp_barrier_wait_cancel_start (gomp_barrier_t *bar)
+{
+  return gomp_barrier_wait_start (bar);
+}
+
+/* This is like gomp_barrier_wait_start, except it decrements
+   bar->awaited_final rather than bar->awaited and should be used
+   for the gomp_team_end barrier only.  */
+static inline gomp_barrier_state_t
+gomp_barrier_wait_final_start (gomp_barrier_t *bar)
+{
+  unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+  ret &= -BAR_INCR | BAR_CANCELLED;
+  /* See above gomp_barrier_wait_start comment.  */
+  if (__atomic_add_fetch (&bar->awaited_final, -1, MEMMODEL_ACQ_REL) == 0)
+    ret |= BAR_WAS_LAST;
+  return ret;
+}
+
+static inline bool
+gomp_barrier_last_thread (gomp_barrier_state_t state)
+{
+  return state & BAR_WAS_LAST;
+}
+
+/* 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 |= BAR_TASK_PENDING;
+}
+
+static inline void
+gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
+{
+  bar->generation &= ~BAR_TASK_PENDING;
+}
+
+static inline void
+gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
+{
+  bar->generation |= BAR_WAITING_FOR_TASK;
+}
+
+static inline bool
+gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
+{
+  return (bar->generation & BAR_WAITING_FOR_TASK) != 0;
+}
+
+static inline bool
+gomp_team_barrier_cancelled (gomp_barrier_t *bar)
+{
+  return __builtin_expect ((bar->generation & BAR_CANCELLED) != 0, 0);
+}
+
+static inline void
+gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
+{
+  bar->generation = (state & -BAR_INCR) + BAR_INCR;
+}
+
+#endif /* GOMP_BARRIER_H */
diff --git a/libgomp/config/rtems/mutex.c b/libgomp/config/rtems/mutex.c
new file mode 100644 (file)
index 0000000..39bb64d
--- /dev/null
@@ -0,0 +1 @@
+/* Everything is in the header.  */
diff --git a/libgomp/config/rtems/mutex.h b/libgomp/config/rtems/mutex.h
new file mode 100644 (file)
index 0000000..39901ee
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+   Contributed by Sebastian Huber <sebastian.huber@embedded-brains.de>.
+
+   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 the RTEMS implementation of a mutex synchronization
+   mechanism for libgomp.  This type is private to the library.  */
+
+#ifndef GOMP_MUTEX_H
+#define GOMP_MUTEX_H 1
+
+#include <sys/lock.h>
+
+typedef struct _Mutex_Control gomp_mutex_t;
+
+#define GOMP_MUTEX_INIT_0 1
+
+static inline void gomp_mutex_init (gomp_mutex_t *mutex)
+{
+  _Mutex_Initialize (mutex);
+}
+
+static inline void gomp_mutex_lock (gomp_mutex_t *mutex)
+{
+  _Mutex_Acquire (mutex);
+}
+
+static inline void gomp_mutex_unlock (gomp_mutex_t *mutex)
+{
+  _Mutex_Release (mutex);
+}
+
+static inline void gomp_mutex_destroy (gomp_mutex_t *mutex)
+{
+  _Mutex_Destroy (mutex);
+}
+
+#endif /* GOMP_MUTEX_H */
diff --git a/libgomp/config/rtems/sem.c b/libgomp/config/rtems/sem.c
new file mode 100644 (file)
index 0000000..39bb64d
--- /dev/null
@@ -0,0 +1 @@
+/* Everything is in the header.  */
diff --git a/libgomp/config/rtems/sem.h b/libgomp/config/rtems/sem.h
new file mode 100644 (file)
index 0000000..0d6765b
--- /dev/null
@@ -0,0 +1,55 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+   Contributed by Sebastian Huber <sebastian.huber@embedded-brains.de>.
+
+   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 the RTEMS implementation of a semaphore synchronization
+   mechanism for libgomp.  This type is private to the library.  */
+
+#ifndef GOMP_SEM_H
+#define GOMP_SEM_H 1
+
+#include <sys/lock.h>
+
+typedef struct _Semaphore_Control gomp_sem_t;
+
+static inline void gomp_sem_init (gomp_sem_t *sem, int value)
+{
+  _Semaphore_Initialize (sem, (unsigned int) value);
+}
+
+static inline void gomp_sem_wait (gomp_sem_t *sem)
+{
+  _Semaphore_Wait (sem);
+}
+
+static inline void gomp_sem_post (gomp_sem_t *sem)
+{
+  _Semaphore_Post (sem);
+}
+
+static inline void gomp_sem_destroy (gomp_sem_t *sem)
+{
+  _Semaphore_Destroy (sem);
+}
+
+#endif /* GOMP_SEM_H  */
index c93e87762417cdfe1bf575a9d2da664c3c507e5b..74d4e822c9e426d77267dc0f5900d80bdf450f0a 100755 (executable)
@@ -15340,6 +15340,23 @@ $as_echo "#define HAVE_BROKEN_POSIX_SEMAPHORES 1" >>confdefs.h
     ;;
 esac
 
+# RTEMS specific checks
+case "$host" in
+  *-*-rtems*)
+    ac_fn_c_check_type "$LINENO" "struct _Mutex_Control" "ac_cv_type_struct__Mutex_Control" "#include <sys/lock.h>
+"
+if test "x$ac_cv_type_struct__Mutex_Control" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT__MUTEX_CONTROL 1
+_ACEOF
+
+
+fi
+
+    ;;
+esac
+
  # Check whether --enable-linux-futex was given.
 if test "${enable_linux_futex+set}" = set; then :
   enableval=$enable_linux_futex;
index b1696d055148fc1b5bd138a8f8e04c5321060c68..2e41ca8aee53aa98c773bea1dbd4a21c8ffabc71 100644 (file)
@@ -216,6 +216,13 @@ case "$host" in
     ;;
 esac
 
+# RTEMS specific checks
+case "$host" in
+  *-*-rtems*)
+    AC_CHECK_TYPES([struct _Mutex_Control],[],[],[#include <sys/lock.h>])
+    ;;
+esac
+
 GCC_LINUX_FUTEX(:)
 
 # Check for pthread_{,attr_}[sg]etaffinity_np.
index 8fad977a2117ae76325e2b36694a706c60d628d9..f2236aec1207ea11ca46e18b498249b41123f498 100644 (file)
@@ -153,6 +153,12 @@ case "${target}" in
 
   nvptx*-*-*)
        config_path="nvptx"
+
+  *-*-rtems*)
+       # Use self-contained synchronization objects if provided by Newlib
+       if test "x$ac_cv_type_struct__Mutex_Control" = xyes ; then
+           config_path="rtems posix"
+       fi
        ;;
 
   *)