Turn SLOW_UNALIGNED_ACCESS into a target hook
[official-gcc.git] / libcilkrts / runtime / signal_node.c
blobbdf820c7a8eb8090a06298f3b329fd6f44c615ad
1 /* signal_node.c -*-C-*-
3 *************************************************************************
5 * Copyright (C) 2011-2016, Intel Corporation
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
32 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * *********************************************************************
37 * PLEASE NOTE: This file is a downstream copy of a file mainitained in
38 * a repository at cilkplus.org. Changes made to this file that are not
39 * submitted through the contribution process detailed at
40 * http://www.cilkplus.org/submit-cilk-contribution will be lost the next
41 * time that a new version is released. Changes only submitted to the
42 * GNU compiler collection or posted to the git repository at
43 * https://bitbucket.org/intelcilkruntime/intel-cilk-runtime.git are
44 * not tracked.
46 * We welcome your contributions to this open source project. Thank you
47 * for your assistance in helping us improve Cilk Plus.
49 **************************************************************************/
51 #include "signal_node.h"
52 #include <stdlib.h>
54 /* Define cilk_semaphore_t for all of the respective systems. */
55 #if defined __APPLE__
56 # include <mach/mach_init.h>
57 # include <mach/semaphore.h>
58 # include <mach/task.h>
59 typedef semaphore_t cilk_semaphore_t;
60 #elif defined _WIN32
61 # include "windows-clean.h"
62 typedef HANDLE cilk_semaphore_t;
63 #else // Linux/MIC
64 # include <errno.h>
65 # include <semaphore.h>
66 # include <stdio.h>
67 typedef sem_t cilk_semaphore_t;
68 #endif // Linux/MIC
70 #include "bug.h"
71 #include "cilk_malloc.h"
72 #include "signal_node.h"
74 /**
75 * Interface within the tree to notify workers to wait without consuming cycles
76 * to expend cycles trying to steal.
78 * cilk_semaphore_t is implemented as an auto-reset event on Windows, and
79 * as a semaphore_t on Linux and MacOS.
81 struct signal_node_t
83 /** 0 if the worker should wait, 1 if it should be running. */
84 volatile unsigned int run;
86 /** OS-specific semaphore on which the worker can wait. */
87 cilk_semaphore_t sem;
90 /******************************************************************************/
91 /* Semaphore-abstraction functions */
92 /******************************************************************************/
95 * All of these functions are simple wrappers for the system-specific semaphore
96 * functions. This keeps the rest of the code reasonably clean and readable.
99 #if defined __APPLE__
100 static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
102 kern_return_t kstatus
103 = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, 0);
104 assert(kstatus == KERN_SUCCESS);
106 static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
108 kern_return_t kstatus = semaphore_destroy(mach_task_self(), *sem);
109 assert(kstatus == KERN_SUCCESS);
111 static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
113 kern_return_t kstatus = semaphore_wait(*sem);
114 assert(kstatus == KERN_SUCCESS);
116 static void signal_cilk_semaphore (cilk_semaphore_t *sem)
118 kern_return_t kstatus = semaphore_signal(*sem);
119 assert(kstatus == KERN_SUCCESS);
121 #elif defined _WIN32
122 // Note: Windows only provides counting semaphores, and we don't really
123 // care about the count. So this is implemented using an auto-reset
124 // event which will automatically reset after the WaitForSingleObject
125 // call
126 static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
128 // Create an auto-reset event
129 *sem = CreateEvent(NULL, // Security attributes
130 FALSE, // Manual reset
131 FALSE, // Initial state (initially reset)
132 NULL); // Name (anonymous)
133 CILK_ASSERT (NULL != *sem);
136 static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
138 BOOL result = CloseHandle(*sem);
139 CILK_ASSERT (0 != result);
142 static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
144 // WaitForSingleObject will reset the event
145 DWORD result = WaitForSingleObject (*sem, INFINITE);
146 CILK_ASSERT (WAIT_OBJECT_0 == result);
148 static void signal_cilk_semaphore (cilk_semaphore_t *sem)
150 BOOL result = SetEvent (*sem);
151 CILK_ASSERT (0 != result);
153 #else // Linux/MIC
154 static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
156 int status = sem_init(sem, 0, 0);
157 assert(0 == status);
159 static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
161 int status = sem_destroy(sem);
162 assert(0 == status);
164 static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
166 int status;
168 do {
169 status = sem_wait(sem);
170 } while (status != 0 && errno == EINTR);
172 if (status != 0) {
173 perror("sem_wait");
174 abort();
177 static void signal_cilk_semaphore (cilk_semaphore_t *sem)
179 sem_post(sem);
181 #endif // Linux/MIC
183 /******************************************************************************/
184 /* Runtime interface functions */
185 /******************************************************************************/
188 * Return a newly malloc'd and initialized signal_node_t.
190 COMMON_SYSDEP
191 signal_node_t *signal_node_create(void)
193 signal_node_t *node;
195 node = ( signal_node_t*)
196 __cilkrts_malloc(sizeof( signal_node_t));
197 node->run = 0;
198 initialize_cilk_semaphore(&node->sem);
200 return node;
204 * Clean and free a signal_node_t.
206 void signal_node_destroy(signal_node_t *node)
208 CILK_ASSERT(node);
209 deinitialize_cilk_semaphore(&node->sem);
210 __cilkrts_free(node);
214 * Return 1 if the node thinks the worker should go to sleep, 0 otherwise.
216 unsigned int signal_node_should_wait(signal_node_t *node)
218 CILK_ASSERT(node);
219 return !node->run;
223 * Send a message to the node that the worker will eventually read.
225 void signal_node_msg(signal_node_t *node, unsigned int msg)
227 CILK_ASSERT(node);
228 switch (msg) {
229 case 0: // worker should go to sleep.
230 node->run = msg;
231 break;
232 case 1: // worker should be awake.
233 node->run = msg;
234 signal_cilk_semaphore(&node->sem);
235 break;
236 default: // error.
237 CILK_ASSERT(0 == "Bad signal_node_t message.");
242 * The current worker will wait on the semaphore.
244 void signal_node_wait(signal_node_t *node)
246 CILK_ASSERT(node);
247 while (signal_node_should_wait(node)) {
248 // The loop is here to consume extra semaphore signals that might have
249 // accumulated. No point in passing on the accumulation.
250 wait_on_cilk_semaphore(&node->sem);