aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libcilkrts/runtime/signal_node.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libcilkrts/runtime/signal_node.c')
-rw-r--r--gcc-4.9/libcilkrts/runtime/signal_node.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/gcc-4.9/libcilkrts/runtime/signal_node.c b/gcc-4.9/libcilkrts/runtime/signal_node.c
new file mode 100644
index 000000000..92c404b48
--- /dev/null
+++ b/gcc-4.9/libcilkrts/runtime/signal_node.c
@@ -0,0 +1,241 @@
+/* signal_node.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2011-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+#include "signal_node.h"
+#include <stdlib.h>
+
+/* Define cilk_semaphore_t for all of the respective systems. */
+#if defined __APPLE__
+# include <mach/mach_init.h>
+# include <mach/semaphore.h>
+# include <mach/task.h>
+ typedef semaphore_t cilk_semaphore_t;
+#elif defined _WIN32
+# include "windows-clean.h"
+ typedef HANDLE cilk_semaphore_t;
+#else // Linux/MIC
+# include <errno.h>
+# include <semaphore.h>
+# include <stdio.h>
+ typedef sem_t cilk_semaphore_t;
+#endif // Linux/MIC
+
+#include "bug.h"
+#include "cilk_malloc.h"
+#include "signal_node.h"
+
+/**
+ * Interface within the tree to notify workers to wait without consuming cycles
+ * to expend cycles trying to steal.
+ *
+ * cilk_semaphore_t is implemented as an auto-reset event on Windows, and
+ * as a semaphore_t on Linux and MacOS.
+ */
+struct signal_node_t
+{
+ /** 0 if the worker should wait, 1 if it should be running. */
+ volatile unsigned int run;
+
+ /** OS-specific semaphore on which the worker can wait. */
+ cilk_semaphore_t sem;
+};
+
+/******************************************************************************/
+/* Semaphore-abstraction functions */
+/******************************************************************************/
+
+/*
+ * All of these functions are simple wrappers for the system-specific semaphore
+ * functions. This keeps the rest of the code reasonably clean and readable.
+ */
+
+#if defined __APPLE__
+static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus
+ = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, 0);
+ assert(kstatus == KERN_SUCCESS);
+}
+static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus = semaphore_destroy(mach_task_self(), *sem);
+ assert(kstatus == KERN_SUCCESS);
+}
+static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus = semaphore_wait(*sem);
+ assert(kstatus == KERN_SUCCESS);
+}
+static void signal_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus = semaphore_signal(*sem);
+ assert(kstatus == KERN_SUCCESS);
+}
+#elif defined _WIN32
+// Note: Windows only provides counting semaphores, and we don't really
+// care about the count. So this is implemented using an auto-reset
+// event which will automatically reset after the WaitForSingleObject
+// call
+static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ // Create an auto-reset event
+ *sem = CreateEvent(NULL, // Security attributes
+ FALSE, // Manual reset
+ FALSE, // Initial state (initially reset)
+ NULL); // Name (anonymous)
+ CILK_ASSERT (NULL != *sem);
+}
+
+static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ BOOL result = CloseHandle(*sem);
+ CILK_ASSERT (0 != result);
+}
+
+static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ // WaitForSingleObject will reset the event
+ DWORD result = WaitForSingleObject (*sem, INFINITE);
+ CILK_ASSERT (WAIT_OBJECT_0 == result);
+}
+static void signal_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ BOOL result = SetEvent (*sem);
+ CILK_ASSERT (0 != result);
+}
+#else // Linux/MIC
+static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ int status = sem_init(sem, 0, 0);
+ assert(0 == status);
+}
+static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ int status = sem_destroy(sem);
+ assert(0 == status);
+}
+static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ int status;
+
+ do {
+ status = sem_wait(sem);
+ } while (status != 0 && errno == EINTR);
+
+ if (status != 0) {
+ perror("sem_wait");
+ abort();
+ }
+}
+static void signal_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ sem_post(sem);
+}
+#endif // Linux/MIC
+
+/******************************************************************************/
+/* Runtime interface functions */
+/******************************************************************************/
+
+/*
+ * Return a newly malloc'd and initialized signal_node_t.
+ */
+COMMON_SYSDEP
+signal_node_t *signal_node_create(void)
+{
+ signal_node_t *node;
+
+ node = ( signal_node_t*)
+ __cilkrts_malloc(sizeof( signal_node_t));
+ node->run = 0;
+ initialize_cilk_semaphore(&node->sem);
+
+ return node;
+}
+
+/*
+ * Clean and free a signal_node_t.
+ */
+void signal_node_destroy(signal_node_t *node)
+{
+ CILK_ASSERT(node);
+ deinitialize_cilk_semaphore(&node->sem);
+ __cilkrts_free(node);
+}
+
+/*
+ * Return 1 if the node thinks the worker should go to sleep, 0 otherwise.
+ */
+unsigned int signal_node_should_wait(signal_node_t *node)
+{
+ CILK_ASSERT(node);
+ return !node->run;
+}
+
+/*
+ * Send a message to the node that the worker will eventually read.
+ */
+void signal_node_msg(signal_node_t *node, unsigned int msg)
+{
+ CILK_ASSERT(node);
+ switch (msg) {
+ case 0: // worker should go to sleep.
+ node->run = msg;
+ break;
+ case 1: // worker should be awake.
+ node->run = msg;
+ signal_cilk_semaphore(&node->sem);
+ break;
+ default: // error.
+ CILK_ASSERT(0 == "Bad signal_node_t message.");
+ }
+}
+
+/*
+ * The current worker will wait on the semaphore.
+ */
+void signal_node_wait(signal_node_t *node)
+{
+ CILK_ASSERT(node);
+ while (signal_node_should_wait(node)) {
+ // The loop is here to consume extra semaphore signals that might have
+ // accumulated. No point in passing on the accumulation.
+ wait_on_cilk_semaphore(&node->sem);
+ }
+}