; doc/emacs/misc.texi (Network Security): Fix typo.
[emacs.git] / src / systhread.c
blobd53b5c207b6cb4c07bfb8106fa28d75660bf322e
1 /* System thread definitions
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 #include <config.h>
20 #include <setjmp.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include "lisp.h"
25 #ifdef HAVE_NS
26 #include "nsterm.h"
27 #endif
29 #ifndef THREADS_ENABLED
31 void
32 sys_mutex_init (sys_mutex_t *m)
34 *m = 0;
37 void
38 sys_mutex_lock (sys_mutex_t *m)
42 void
43 sys_mutex_unlock (sys_mutex_t *m)
47 void
48 sys_cond_init (sys_cond_t *c)
50 *c = 0;
53 void
54 sys_cond_wait (sys_cond_t *c, sys_mutex_t *m)
58 void
59 sys_cond_signal (sys_cond_t *c)
63 void
64 sys_cond_broadcast (sys_cond_t *c)
68 void
69 sys_cond_destroy (sys_cond_t *c)
73 sys_thread_t
74 sys_thread_self (void)
76 return 0;
79 bool
80 sys_thread_equal (sys_thread_t t, sys_thread_t u)
82 return t == u;
85 bool
86 sys_thread_create (sys_thread_t *t, const char *name,
87 thread_creation_function *func, void *datum)
89 return false;
92 void
93 sys_thread_yield (void)
97 #elif defined (HAVE_PTHREAD)
99 #include <sched.h>
101 #ifdef HAVE_SYS_PRCTL_H
102 #include <sys/prctl.h>
103 #endif
105 void
106 sys_mutex_init (sys_mutex_t *mutex)
108 pthread_mutexattr_t *attr_ptr;
109 #ifdef ENABLE_CHECKING
110 pthread_mutexattr_t attr;
112 int error = pthread_mutexattr_init (&attr);
113 eassert (error == 0);
114 error = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK);
115 eassert (error == 0);
117 attr_ptr = &attr;
118 #else
119 attr_ptr = NULL;
120 #endif
121 int error = pthread_mutex_init (mutex, attr_ptr);
122 /* We could get ENOMEM. Can't do anything except aborting. */
123 if (error != 0)
125 fprintf (stderr, "\npthread_mutex_init failed: %s\n", strerror (error));
126 emacs_abort ();
128 #ifdef ENABLE_CHECKING
129 error = pthread_mutexattr_destroy (&attr);
130 eassert (error == 0);
131 #endif
134 void
135 sys_mutex_lock (sys_mutex_t *mutex)
137 int error = pthread_mutex_lock (mutex);
138 eassert (error == 0);
141 void
142 sys_mutex_unlock (sys_mutex_t *mutex)
144 int error = pthread_mutex_unlock (mutex);
145 eassert (error == 0);
148 void
149 sys_cond_init (sys_cond_t *cond)
151 int error = pthread_cond_init (cond, NULL);
152 /* We could get ENOMEM. Can't do anything except aborting. */
153 if (error != 0)
155 fprintf (stderr, "\npthread_cond_init failed: %s\n", strerror (error));
156 emacs_abort ();
160 void
161 sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
163 int error = pthread_cond_wait (cond, mutex);
164 eassert (error == 0);
167 void
168 sys_cond_signal (sys_cond_t *cond)
170 int error = pthread_cond_signal (cond);
171 eassert (error == 0);
174 void
175 sys_cond_broadcast (sys_cond_t *cond)
177 int error = pthread_cond_broadcast (cond);
178 eassert (error == 0);
179 #ifdef HAVE_NS
180 /* Send an app defined event to break out of the NS run loop.
181 It seems that if ns_select is running the NS run loop, this
182 broadcast has no effect until the loop is done, breaking a couple
183 of tests in thread-tests.el. */
184 ns_run_loop_break ();
185 #endif
188 void
189 sys_cond_destroy (sys_cond_t *cond)
191 int error = pthread_cond_destroy (cond);
192 eassert (error == 0);
195 sys_thread_t
196 sys_thread_self (void)
198 return pthread_self ();
201 bool
202 sys_thread_equal (sys_thread_t t, sys_thread_t u)
204 return pthread_equal (t, u);
207 bool
208 sys_thread_create (sys_thread_t *thread_ptr, const char *name,
209 thread_creation_function *func, void *arg)
211 pthread_attr_t attr;
212 bool result = false;
214 if (pthread_attr_init (&attr))
215 return false;
217 /* Avoid crash on macOS with deeply nested GC (Bug#30364). */
218 size_t stack_size;
219 size_t required_stack_size = sizeof (void *) * 1024 * 1024;
220 if (pthread_attr_getstacksize (&attr, &stack_size) == 0
221 && stack_size < required_stack_size)
223 if (pthread_attr_setstacksize (&attr, required_stack_size) != 0)
224 goto out;
227 if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
229 result = pthread_create (thread_ptr, &attr, func, arg) == 0;
230 #if defined (HAVE_SYS_PRCTL_H) && defined (HAVE_PRCTL) && defined (PR_SET_NAME)
231 if (result && name != NULL)
232 prctl (PR_SET_NAME, name);
233 #endif
236 out: ;
237 int error = pthread_attr_destroy (&attr);
238 eassert (error == 0);
240 return result;
243 void
244 sys_thread_yield (void)
246 sched_yield ();
249 #elif defined (WINDOWSNT)
251 #include <w32term.h>
253 /* Cannot include <process.h> because of the local header by the same
254 name, sigh. */
255 uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *);
257 /* Mutexes are implemented as critical sections, because they are
258 faster than Windows mutex objects (implemented in userspace), and
259 satisfy the requirements, since we only need to synchronize within a
260 single process. */
261 void
262 sys_mutex_init (sys_mutex_t *mutex)
264 InitializeCriticalSection ((LPCRITICAL_SECTION)mutex);
267 void
268 sys_mutex_lock (sys_mutex_t *mutex)
270 /* FIXME: What happens if the owning thread exits without releasing
271 the mutex? According to MSDN, the result is undefined behavior. */
272 EnterCriticalSection ((LPCRITICAL_SECTION)mutex);
275 void
276 sys_mutex_unlock (sys_mutex_t *mutex)
278 LeaveCriticalSection ((LPCRITICAL_SECTION)mutex);
281 void
282 sys_cond_init (sys_cond_t *cond)
284 cond->initialized = false;
285 cond->wait_count = 0;
286 /* Auto-reset event for signal. */
287 cond->events[CONDV_SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL);
288 /* Manual-reset event for broadcast. */
289 cond->events[CONDV_BROADCAST] = CreateEvent (NULL, TRUE, FALSE, NULL);
290 if (!cond->events[CONDV_SIGNAL] || !cond->events[CONDV_BROADCAST])
291 return;
292 InitializeCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
293 cond->initialized = true;
296 void
297 sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
299 DWORD wait_result;
300 bool last_thread_waiting;
302 if (!cond->initialized)
303 return;
305 /* Increment the wait count avoiding race conditions. */
306 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
307 cond->wait_count++;
308 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
310 /* Release the mutex and wait for either the signal or the broadcast
311 event. */
312 LeaveCriticalSection ((LPCRITICAL_SECTION)mutex);
313 wait_result = WaitForMultipleObjects (2, cond->events, FALSE, INFINITE);
315 /* Decrement the wait count and see if we are the last thread
316 waiting on the condition variable. */
317 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
318 cond->wait_count--;
319 last_thread_waiting =
320 wait_result == WAIT_OBJECT_0 + CONDV_BROADCAST
321 && cond->wait_count == 0;
322 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
324 /* Broadcast uses a manual-reset event, so when the last thread is
325 released, we must manually reset that event. */
326 if (last_thread_waiting)
327 ResetEvent (cond->events[CONDV_BROADCAST]);
329 /* Per the API, re-acquire the mutex. */
330 EnterCriticalSection ((LPCRITICAL_SECTION)mutex);
333 void
334 sys_cond_signal (sys_cond_t *cond)
336 bool threads_waiting;
338 if (!cond->initialized)
339 return;
341 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
342 threads_waiting = cond->wait_count > 0;
343 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
345 if (threads_waiting)
346 SetEvent (cond->events[CONDV_SIGNAL]);
349 void
350 sys_cond_broadcast (sys_cond_t *cond)
352 bool threads_waiting;
354 if (!cond->initialized)
355 return;
357 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
358 threads_waiting = cond->wait_count > 0;
359 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
361 if (threads_waiting)
362 SetEvent (cond->events[CONDV_BROADCAST]);
365 void
366 sys_cond_destroy (sys_cond_t *cond)
368 if (cond->events[CONDV_SIGNAL])
369 CloseHandle (cond->events[CONDV_SIGNAL]);
370 if (cond->events[CONDV_BROADCAST])
371 CloseHandle (cond->events[CONDV_BROADCAST]);
373 if (!cond->initialized)
374 return;
376 /* FIXME: What if wait_count is non-zero, i.e. there are still
377 threads waiting on this condition variable? */
378 DeleteCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
381 sys_thread_t
382 sys_thread_self (void)
384 return (sys_thread_t) GetCurrentThreadId ();
387 bool
388 sys_thread_equal (sys_thread_t t, sys_thread_t u)
390 return t == u;
393 static thread_creation_function *thread_start_address;
395 /* _beginthread wants a void function, while we are passed a function
396 that returns a pointer. So we use a wrapper. See the command in
397 w32term.h about the need for ALIGN_STACK attribute. */
398 static void ALIGN_STACK
399 w32_beginthread_wrapper (void *arg)
401 (void)thread_start_address (arg);
404 bool
405 sys_thread_create (sys_thread_t *thread_ptr, const char *name,
406 thread_creation_function *func, void *arg)
408 /* FIXME: Do threads that run Lisp require some minimum amount of
409 stack? Zero here means each thread will get the same amount as
410 the main program. On GNU/Linux, it seems like the stack is 2MB
411 by default, overridden by RLIMIT_STACK at program start time.
412 Not sure what to do with this. See also the comment in
413 w32proc.c:new_child. */
414 const unsigned stack_size = 0;
415 uintptr_t thandle;
417 thread_start_address = func;
419 /* We use _beginthread rather than CreateThread because the former
420 arranges for the thread handle to be automatically closed when
421 the thread exits, thus preventing handle leaks and/or the need to
422 track all the threads and close their handles when they exit.
423 Also, MSDN seems to imply that code which uses CRT _must_ call
424 _beginthread, although if that is true, we already violate that
425 rule in many places... */
426 thandle = _beginthread (w32_beginthread_wrapper, stack_size, arg);
427 if (thandle == (uintptr_t)-1L)
428 return false;
430 /* Kludge alert! We use the Windows thread ID, an unsigned 32-bit
431 number, as the sys_thread_t type, because that ID is the only
432 unique identifier of a thread on Windows. But _beginthread
433 returns a handle of the thread, and there's no easy way of
434 getting the thread ID given a handle (GetThreadId is available
435 only since Vista, so we cannot use it portably). Fortunately,
436 the value returned by sys_thread_create is not used by its
437 callers; instead, run_thread, which runs in the context of the
438 new thread, calls sys_thread_self and uses its return value;
439 sys_thread_self in this implementation calls GetCurrentThreadId.
440 Therefore, we return some more or less arbitrary value of the
441 thread ID from this function. */
442 *thread_ptr = thandle & 0xFFFFFFFF;
443 return true;
446 void
447 sys_thread_yield (void)
449 Sleep (0);
452 #else
454 #error port me
456 #endif