This source file includes following definitions.
- sys_mutex_init
- sys_mutex_lock
- sys_mutex_unlock
- sys_cond_init
- sys_cond_wait
- sys_cond_signal
- sys_cond_broadcast
- sys_cond_destroy
- sys_thread_self
- sys_thread_equal
- sys_thread_set_name
- sys_thread_create
- sys_thread_yield
- sys_mutex_init
- sys_mutex_lock
- sys_mutex_unlock
- sys_cond_init
- sys_cond_wait
- sys_cond_signal
- sys_cond_broadcast
- sys_cond_destroy
- sys_thread_self
- sys_thread_equal
- sys_thread_set_name
- sys_thread_create
- sys_thread_yield
- sys_mutex_init
- sys_mutex_lock
- sys_mutex_unlock
- sys_cond_init
- sys_cond_wait
- sys_cond_signal
- sys_cond_broadcast
- sys_cond_destroy
- sys_thread_self
- sys_thread_equal
- w32_set_thread_name
- sys_thread_set_name
- w32_beginthread_wrapper
- sys_thread_create
- sys_thread_yield
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20 #include <setjmp.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include "lisp.h"
24
25 #ifdef HAVE_NS
26 #include "nsterm.h"
27 #endif
28
29 #ifdef HAVE_PTHREAD_SET_NAME_NP
30 #include <pthread_np.h>
31 #endif
32
33 #ifndef THREADS_ENABLED
34
35 void
36 sys_mutex_init (sys_mutex_t *m)
37 {
38 *m = 0;
39 }
40
41 void
42 sys_mutex_lock (sys_mutex_t *m)
43 {
44 }
45
46 void
47 sys_mutex_unlock (sys_mutex_t *m)
48 {
49 }
50
51 void
52 sys_cond_init (sys_cond_t *c)
53 {
54 *c = 0;
55 }
56
57 void
58 sys_cond_wait (sys_cond_t *c, sys_mutex_t *m)
59 {
60 }
61
62 void
63 sys_cond_signal (sys_cond_t *c)
64 {
65 }
66
67 void
68 sys_cond_broadcast (sys_cond_t *c)
69 {
70 }
71
72 void
73 sys_cond_destroy (sys_cond_t *c)
74 {
75 }
76
77 sys_thread_t
78 sys_thread_self (void)
79 {
80 return 0;
81 }
82
83 bool
84 sys_thread_equal (sys_thread_t t, sys_thread_t u)
85 {
86 return t == u;
87 }
88 void
89 sys_thread_set_name (const char *name)
90 {
91 }
92
93 bool
94 sys_thread_create (sys_thread_t *t, thread_creation_function *func, void *datum)
95 {
96 return false;
97 }
98
99 void
100 sys_thread_yield (void)
101 {
102 }
103
104 #elif defined (HAVE_PTHREAD)
105
106 #include <sched.h>
107
108 void
109 sys_mutex_init (sys_mutex_t *mutex)
110 {
111 pthread_mutexattr_t *attr_ptr;
112 #ifdef ENABLE_CHECKING
113 pthread_mutexattr_t attr;
114 {
115 int error = pthread_mutexattr_init (&attr);
116 eassert (error == 0);
117 error = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK);
118 eassert (error == 0);
119 }
120 attr_ptr = &attr;
121 #else
122 attr_ptr = NULL;
123 #endif
124 int error = pthread_mutex_init (mutex, attr_ptr);
125
126 if (error != 0)
127 {
128 fprintf (stderr, "\npthread_mutex_init failed: %s\n", strerror (error));
129 emacs_abort ();
130 }
131 #ifdef ENABLE_CHECKING
132 error = pthread_mutexattr_destroy (&attr);
133 eassert (error == 0);
134 #endif
135 }
136
137 void
138 sys_mutex_lock (sys_mutex_t *mutex)
139 {
140 int error = pthread_mutex_lock (mutex);
141 eassert (error == 0);
142 }
143
144 void
145 sys_mutex_unlock (sys_mutex_t *mutex)
146 {
147 int error = pthread_mutex_unlock (mutex);
148 eassert (error == 0);
149 }
150
151 void
152 sys_cond_init (sys_cond_t *cond)
153 {
154 int error = pthread_cond_init (cond, NULL);
155
156 if (error != 0)
157 {
158 fprintf (stderr, "\npthread_cond_init failed: %s\n", strerror (error));
159 emacs_abort ();
160 }
161 }
162
163 void
164 sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
165 {
166 int error = pthread_cond_wait (cond, mutex);
167 eassert (error == 0);
168 }
169
170 void
171 sys_cond_signal (sys_cond_t *cond)
172 {
173 int error = pthread_cond_signal (cond);
174 eassert (error == 0);
175 }
176
177 void
178 sys_cond_broadcast (sys_cond_t *cond)
179 {
180 int error = pthread_cond_broadcast (cond);
181 eassert (error == 0);
182 #ifdef HAVE_NS
183
184
185
186
187 ns_run_loop_break ();
188 #endif
189 }
190
191 void
192 sys_cond_destroy (sys_cond_t *cond)
193 {
194 int error = pthread_cond_destroy (cond);
195 eassert (error == 0);
196 }
197
198 sys_thread_t
199 sys_thread_self (void)
200 {
201 return pthread_self ();
202 }
203
204 bool
205 sys_thread_equal (sys_thread_t t, sys_thread_t u)
206 {
207 return pthread_equal (t, u);
208 }
209
210 void
211 sys_thread_set_name (const char *name)
212 {
213 #ifdef HAVE_PTHREAD_SETNAME_NP
214
215
216
217 #define TASK_COMM_LEN 16
218 char p_name[TASK_COMM_LEN];
219 strncpy (p_name, name, TASK_COMM_LEN - 1);
220 p_name[TASK_COMM_LEN - 1] = '\0';
221 # ifdef HAVE_PTHREAD_SETNAME_NP_1ARG
222 pthread_setname_np (p_name);
223 # elif defined HAVE_PTHREAD_SETNAME_NP_3ARG
224 pthread_setname_np (pthread_self (), "%s", p_name);
225 # else
226 pthread_setname_np (pthread_self (), p_name);
227 # endif
228 #elif HAVE_PTHREAD_SET_NAME_NP
229
230
231 pthread_set_name_np (pthread_self (), name);
232 #endif
233 }
234
235 bool
236 sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
237 void *arg)
238 {
239 pthread_attr_t attr;
240 bool result = false;
241
242 if (pthread_attr_init (&attr))
243 return false;
244
245
246 size_t stack_size;
247 size_t required_stack_size = sizeof (void *) * 1024 * 1024;
248 if (pthread_attr_getstacksize (&attr, &stack_size) == 0
249 && stack_size < required_stack_size)
250 {
251 if (pthread_attr_setstacksize (&attr, required_stack_size) != 0)
252 goto out;
253 }
254
255 if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
256 result = pthread_create (thread_ptr, &attr, func, arg) == 0;
257
258 out: ;
259 int error = pthread_attr_destroy (&attr);
260 eassert (error == 0);
261
262 return result;
263 }
264
265 void
266 sys_thread_yield (void)
267 {
268 sched_yield ();
269 }
270
271 #elif defined (WINDOWSNT)
272
273 #include <mbctype.h>
274 #include "w32term.h"
275
276
277
278 uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *);
279
280
281
282
283
284 void
285 sys_mutex_init (sys_mutex_t *mutex)
286 {
287 InitializeCriticalSection ((LPCRITICAL_SECTION)mutex);
288 }
289
290 void
291 sys_mutex_lock (sys_mutex_t *mutex)
292 {
293
294
295 EnterCriticalSection ((LPCRITICAL_SECTION)mutex);
296 }
297
298 void
299 sys_mutex_unlock (sys_mutex_t *mutex)
300 {
301 LeaveCriticalSection ((LPCRITICAL_SECTION)mutex);
302 }
303
304 void
305 sys_cond_init (sys_cond_t *cond)
306 {
307 cond->initialized = false;
308 cond->wait_count = 0;
309
310 cond->events[CONDV_SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL);
311
312 cond->events[CONDV_BROADCAST] = CreateEvent (NULL, TRUE, FALSE, NULL);
313 if (!cond->events[CONDV_SIGNAL] || !cond->events[CONDV_BROADCAST])
314 return;
315 InitializeCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
316 cond->initialized = true;
317 }
318
319 void
320 sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
321 {
322 DWORD wait_result;
323 bool last_thread_waiting;
324
325 if (!cond->initialized)
326 return;
327
328
329 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
330 cond->wait_count++;
331 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
332
333
334
335 LeaveCriticalSection ((LPCRITICAL_SECTION)mutex);
336 wait_result = WaitForMultipleObjects (2, cond->events, FALSE, INFINITE);
337
338
339
340 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
341 cond->wait_count--;
342 last_thread_waiting =
343 wait_result == WAIT_OBJECT_0 + CONDV_BROADCAST
344 && cond->wait_count == 0;
345 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
346
347
348
349 if (last_thread_waiting)
350 ResetEvent (cond->events[CONDV_BROADCAST]);
351
352
353 EnterCriticalSection ((LPCRITICAL_SECTION)mutex);
354 }
355
356 void
357 sys_cond_signal (sys_cond_t *cond)
358 {
359 bool threads_waiting;
360
361 if (!cond->initialized)
362 return;
363
364 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
365 threads_waiting = cond->wait_count > 0;
366 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
367
368 if (threads_waiting)
369 SetEvent (cond->events[CONDV_SIGNAL]);
370 }
371
372 void
373 sys_cond_broadcast (sys_cond_t *cond)
374 {
375 bool threads_waiting;
376
377 if (!cond->initialized)
378 return;
379
380 EnterCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
381 threads_waiting = cond->wait_count > 0;
382 LeaveCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
383
384 if (threads_waiting)
385 SetEvent (cond->events[CONDV_BROADCAST]);
386 }
387
388 void
389 sys_cond_destroy (sys_cond_t *cond)
390 {
391 if (cond->events[CONDV_SIGNAL])
392 CloseHandle (cond->events[CONDV_SIGNAL]);
393 if (cond->events[CONDV_BROADCAST])
394 CloseHandle (cond->events[CONDV_BROADCAST]);
395
396 if (!cond->initialized)
397 return;
398
399
400
401 DeleteCriticalSection ((LPCRITICAL_SECTION)&cond->wait_count_lock);
402 }
403
404 sys_thread_t
405 sys_thread_self (void)
406 {
407 return (sys_thread_t) GetCurrentThreadId ();
408 }
409
410 bool
411 sys_thread_equal (sys_thread_t t, sys_thread_t u)
412 {
413 return t == u;
414 }
415
416
417
418 #define MS_VC_EXCEPTION 0x406d1388UL
419
420
421 typedef struct _THREADNAME_INFO
422 {
423 DWORD_PTR type;
424 LPCSTR name;
425 DWORD_PTR thread_id;
426 DWORD_PTR reserved;
427 } THREADNAME_INFO;
428
429 typedef BOOL (WINAPI *IsDebuggerPresent_Proc) (void);
430 extern IsDebuggerPresent_Proc is_debugger_present;
431 extern int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
432 typedef HRESULT (WINAPI *SetThreadDescription_Proc)
433 (HANDLE hThread, PCWSTR lpThreadDescription);
434 extern SetThreadDescription_Proc set_thread_description;
435
436
437 static void
438 w32_set_thread_name (DWORD thread_id, const char *name)
439 {
440 if (!name || !*name)
441 return;
442
443
444 if (set_thread_description)
445 {
446
447 wchar_t name_w[1025];
448
449
450 int codepage = _getmbcp ();
451 if (!codepage)
452 codepage = GetACP ();
453 int cnv_result = pMultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS,
454 name, -1,
455 name_w, 1025);
456 if (cnv_result
457 && set_thread_description (GetCurrentThread (), name_w) == S_OK)
458 return;
459 }
460
461
462 if (!(is_debugger_present && is_debugger_present ()))
463 return;
464
465 THREADNAME_INFO tninfo;
466
467 tninfo.type = 0x1000;
468 tninfo.name = name;
469 tninfo.thread_id = thread_id;
470 tninfo.reserved = 0;
471 RaiseException (MS_VC_EXCEPTION, 0, sizeof (tninfo) / sizeof (ULONG_PTR),
472 (ULONG_PTR *) &tninfo);
473 }
474
475 static thread_creation_function *thread_start_address;
476
477 void
478 sys_thread_set_name (const char *name)
479 {
480 w32_set_thread_name (GetCurrentThreadId (), name);
481 }
482
483
484
485
486 static void ALIGN_STACK
487 w32_beginthread_wrapper (void *arg)
488 {
489 (void)thread_start_address (arg);
490 }
491
492 bool
493 sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
494 void *arg)
495 {
496
497
498
499
500
501
502 const unsigned stack_size = 0;
503 uintptr_t thandle;
504
505 thread_start_address = func;
506
507
508
509
510
511
512
513
514 thandle = _beginthread (w32_beginthread_wrapper, stack_size, arg);
515 if (thandle == (uintptr_t)-1L)
516 return false;
517
518
519
520
521
522
523
524
525
526
527
528
529
530 *thread_ptr = thandle & 0xFFFFFFFF;
531 return true;
532 }
533
534 void
535 sys_thread_yield (void)
536 {
537 Sleep (0);
538 }
539
540 #else
541
542 #error port me
543
544 #endif