1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 3.0
6 // Copyright (2020) National Technology & Engineering
7 // Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44
45 #include <Kokkos_Macros.hpp>
46 #if defined(KOKKOS_ENABLE_THREADS)
47
48 #include <Kokkos_Core_fwd.hpp>
49 /* Standard 'C' Linux libraries */
50
51 #include <pthread.h>
52 #include <sched.h>
53 #include <errno.h>
54
55 /* Standard C++ libraries */
56
57 #include <cstdlib>
58 #include <string>
59 #include <iostream>
60 #include <stdexcept>
61
62 #include <Kokkos_Threads.hpp>
63
64 //----------------------------------------------------------------------------
65
66 namespace Kokkos {
67 namespace Impl {
68 namespace {
69
70 pthread_mutex_t host_internal_pthread_mutex = PTHREAD_MUTEX_INITIALIZER;
71
72 // Pthreads compatible driver.
73 // Recovery from an exception would require constant intra-thread health
74 // verification; which would negatively impact runtime. As such simply
75 // abort the process.
76
internal_pthread_driver(void *)77 void* internal_pthread_driver(void*) {
78 try {
79 ThreadsExec::driver();
80 } catch (const std::exception& x) {
81 std::cerr << "Exception thrown from worker thread: " << x.what()
82 << std::endl;
83 std::cerr.flush();
84 std::abort();
85 } catch (...) {
86 std::cerr << "Exception thrown from worker thread" << std::endl;
87 std::cerr.flush();
88 std::abort();
89 }
90 return nullptr;
91 }
92
93 } // namespace
94
95 //----------------------------------------------------------------------------
96 // Spawn a thread
97
spawn()98 bool ThreadsExec::spawn() {
99 bool result = false;
100
101 pthread_attr_t attr;
102
103 if (0 == pthread_attr_init(&attr) ||
104 0 == pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) ||
105 0 == pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
106 pthread_t pt;
107
108 result = 0 == pthread_create(&pt, &attr, internal_pthread_driver, nullptr);
109 }
110
111 pthread_attr_destroy(&attr);
112
113 return result;
114 }
115
116 //----------------------------------------------------------------------------
117
is_process()118 bool ThreadsExec::is_process() {
119 static const pthread_t master_pid = pthread_self();
120
121 return pthread_equal(master_pid, pthread_self());
122 }
123
global_lock()124 void ThreadsExec::global_lock() {
125 pthread_mutex_lock(&host_internal_pthread_mutex);
126 }
127
global_unlock()128 void ThreadsExec::global_unlock() {
129 pthread_mutex_unlock(&host_internal_pthread_mutex);
130 }
131
132 //----------------------------------------------------------------------------
133
wait_yield(volatile int & flag,const int value)134 void ThreadsExec::wait_yield(volatile int& flag, const int value) {
135 while (value == flag) {
136 sched_yield();
137 }
138 }
139
140 } // namespace Impl
141 } // namespace Kokkos
142
143 /* end #if defined( KOKKOS_ENABLE_THREADS ) */
144 //----------------------------------------------------------------------------
145 //----------------------------------------------------------------------------
146
147 #elif defined(KOKKOS_ENABLE_WINTHREAD)
148
149 #include <Kokkos_Core_fwd.hpp>
150
151 /* Windows libraries */
152 #include <winsock2.h>
153 #include <windows.h>
154 #include <process.h>
155
156 /* Standard C++ libraries */
157
158 #include <cstdlib>
159 #include <string>
160 #include <iostream>
161 #include <stdexcept>
162
163 #include <Kokkos_Threads.hpp>
164
165 //----------------------------------------------------------------------------
166 // Driver for each created pthread
167
168 namespace Kokkos {
169 namespace Impl {
170 namespace {
171
internal_winthread_driver(void * arg)172 unsigned WINAPI internal_winthread_driver(void* arg) {
173 ThreadsExec::driver();
174
175 return 0;
176 }
177
178 class ThreadLockWindows {
179 private:
180 CRITICAL_SECTION m_handle;
181
~ThreadLockWindows()182 ~ThreadLockWindows() { DeleteCriticalSection(&m_handle); }
183
184 ThreadLockWindows();
185 { InitializeCriticalSection(&m_handle); }
186
187 ThreadLockWindows(const ThreadLockWindows&);
188 ThreadLockWindows& operator=(const ThreadLockWindows&);
189
190 public:
191 static ThreadLockWindows& singleton();
192
lock()193 void lock() { EnterCriticalSection(&m_handle); }
194
unlock()195 void unlock() { LeaveCriticalSection(&m_handle); }
196 };
197
singleton()198 ThreadLockWindows& ThreadLockWindows::singleton() {
199 static ThreadLockWindows self;
200 return self;
201 }
202
203 } // namespace
204 } // namespace Impl
205 } // namespace Kokkos
206
207 //----------------------------------------------------------------------------
208 //----------------------------------------------------------------------------
209
210 namespace Kokkos {
211 namespace Impl {
212
213 // Spawn this thread
214
spawn()215 bool ThreadsExec::spawn() {
216 unsigned Win32ThreadID = 0;
217
218 HANDLE handle =
219 _beginthreadex(0, 0, internal_winthread_driver, 0, 0, &Win32ThreadID);
220
221 return !handle;
222 }
223
is_process()224 bool ThreadsExec::is_process() { return true; }
225
global_lock()226 void ThreadsExec::global_lock() { ThreadLockWindows::singleton().lock(); }
227
global_unlock()228 void ThreadsExec::global_unlock() { ThreadLockWindows::singleton().unlock(); }
229
wait_yield(volatile int & flag,const int value)230 void ThreadsExec::wait_yield(volatile int& flag, const int value){} {
231 while (value == flag) {
232 Sleep(0);
233 }
234 }
235
236 } // namespace Impl
237 } // namespace Kokkos
238
239 #else
KOKKOS_CORE_SRC_THREADS_EXEC_BASE_PREVENT_LINK_ERROR()240 void KOKKOS_CORE_SRC_THREADS_EXEC_BASE_PREVENT_LINK_ERROR() {}
241 #endif /* end #elif defined( KOKKOS_ENABLE_WINTHREAD ) */
242