2 Copyright (C) 2012, 2013 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 <http://www.gnu.org/licenses/>. */
23 #include "character.h"
28 static struct thread_state primary_thread
;
30 struct thread_state
*current_thread
= &primary_thread
;
32 static struct thread_state
*all_threads
= &primary_thread
;
34 static sys_mutex_t global_lock
;
36 Lisp_Object Qthreadp
, Qmutexp
, Qcondition_variablep
;
40 /* m_specpdl is set when the thread is created and cleared when the
42 #define thread_alive_p(STATE) ((STATE)->m_specpdl != NULL)
47 release_global_lock (void)
49 sys_mutex_unlock (&global_lock
);
52 /* You must call this after acquiring the global lock.
53 acquire_global_lock does it for you. */
55 post_acquire_global_lock (struct thread_state
*self
)
59 if (self
!= current_thread
)
61 /* CURRENT_THREAD is NULL if the previously current thread
62 exited. In this case, there is no reason to unbind, and
64 if (current_thread
!= NULL
)
65 unbind_for_thread_switch ();
66 current_thread
= self
;
67 rebind_for_thread_switch ();
70 /* We need special handling to re-set the buffer. */
71 XSETBUFFER (buffer
, self
->m_current_buffer
);
72 self
->m_current_buffer
= 0;
73 set_buffer_internal (XBUFFER (buffer
));
75 if (!NILP (current_thread
->error_symbol
))
77 Lisp_Object sym
= current_thread
->error_symbol
;
78 Lisp_Object data
= current_thread
->error_data
;
80 current_thread
->error_symbol
= Qnil
;
81 current_thread
->error_data
= Qnil
;
87 acquire_global_lock (struct thread_state
*self
)
89 sys_mutex_lock (&global_lock
);
90 post_acquire_global_lock (self
);
96 lisp_mutex_init (lisp_mutex_t
*mutex
)
100 sys_cond_init (&mutex
->condition
);
104 lisp_mutex_lock (lisp_mutex_t
*mutex
, int new_count
)
106 struct thread_state
*self
;
108 if (mutex
->owner
== NULL
)
110 mutex
->owner
= current_thread
;
111 mutex
->count
= new_count
== 0 ? 1 : new_count
;
114 if (mutex
->owner
== current_thread
)
116 eassert (new_count
== 0);
121 self
= current_thread
;
122 self
->wait_condvar
= &mutex
->condition
;
123 while (mutex
->owner
!= NULL
&& (new_count
!= 0
124 || NILP (self
->error_symbol
)))
125 sys_cond_wait (&mutex
->condition
, &global_lock
);
126 self
->wait_condvar
= NULL
;
128 if (new_count
== 0 && !NILP (self
->error_symbol
))
132 mutex
->count
= new_count
== 0 ? 1 : new_count
;
138 lisp_mutex_unlock (lisp_mutex_t
*mutex
)
140 struct thread_state
*self
= current_thread
;
142 if (mutex
->owner
!= current_thread
)
145 if (--mutex
->count
> 0)
149 sys_cond_broadcast (&mutex
->condition
);
155 lisp_mutex_unlock_for_wait (lisp_mutex_t
*mutex
)
157 struct thread_state
*self
= current_thread
;
158 unsigned int result
= mutex
->count
;
160 /* Ensured by condvar code. */
161 eassert (mutex
->owner
== current_thread
);
165 sys_cond_broadcast (&mutex
->condition
);
171 lisp_mutex_destroy (lisp_mutex_t
*mutex
)
173 sys_cond_destroy (&mutex
->condition
);
177 lisp_mutex_owned_p (lisp_mutex_t
*mutex
)
179 return mutex
->owner
== current_thread
;
184 DEFUN ("make-mutex", Fmake_mutex
, Smake_mutex
, 0, 1, 0,
185 doc
: /* Create a mutex.
186 A mutex provides a synchronization point for threads.
187 Only one thread at a time can hold a mutex. Other threads attempting
188 to acquire it will block until the mutex is available.
190 A thread can acquire a mutex any number of times.
192 NAME, if given, is used as the name of the mutex. The name is
193 informational only. */)
196 struct Lisp_Mutex
*mutex
;
202 mutex
= ALLOCATE_PSEUDOVECTOR (struct Lisp_Mutex
, mutex
, PVEC_MUTEX
);
203 memset ((char *) mutex
+ offsetof (struct Lisp_Mutex
, mutex
),
204 0, sizeof (struct Lisp_Mutex
) - offsetof (struct Lisp_Mutex
,
207 lisp_mutex_init (&mutex
->mutex
);
209 XSETMUTEX (result
, mutex
);
214 mutex_lock_callback (void *arg
)
216 struct Lisp_Mutex
*mutex
= arg
;
217 struct thread_state
*self
= current_thread
;
219 if (lisp_mutex_lock (&mutex
->mutex
, 0))
220 post_acquire_global_lock (self
);
224 do_unwind_mutex_lock (void)
226 current_thread
->event_object
= Qnil
;
229 DEFUN ("mutex-lock", Fmutex_lock
, Smutex_lock
, 1, 1, 0,
230 doc
: /* Acquire a mutex.
231 If the current thread already owns MUTEX, increment the count and
233 Otherwise, if no thread owns MUTEX, make the current thread own it.
234 Otherwise, block until MUTEX is available, or until the current thread
235 is signalled using `thread-signal'.
236 Note that calls to `mutex-lock' and `mutex-unlock' must be paired. */)
239 struct Lisp_Mutex
*lmutex
;
240 ptrdiff_t count
= SPECPDL_INDEX ();
243 lmutex
= XMUTEX (mutex
);
245 current_thread
->event_object
= mutex
;
246 record_unwind_protect_void (do_unwind_mutex_lock
);
247 flush_stack_call_func (mutex_lock_callback
, lmutex
);
248 return unbind_to (count
, Qnil
);
252 mutex_unlock_callback (void *arg
)
254 struct Lisp_Mutex
*mutex
= arg
;
255 struct thread_state
*self
= current_thread
;
257 if (lisp_mutex_unlock (&mutex
->mutex
))
258 post_acquire_global_lock (self
);
261 DEFUN ("mutex-unlock", Fmutex_unlock
, Smutex_unlock
, 1, 1, 0,
262 doc
: /* Release the mutex.
263 If this thread does not own MUTEX, signal an error.
264 Otherwise, decrement the mutex's count. If the count is zero,
268 struct Lisp_Mutex
*lmutex
;
271 lmutex
= XMUTEX (mutex
);
273 flush_stack_call_func (mutex_unlock_callback
, lmutex
);
277 DEFUN ("mutex-name", Fmutex_name
, Smutex_name
, 1, 1, 0,
278 doc
: /* Return the name of MUTEX.
279 If no name was given when MUTEX was created, return nil. */)
282 struct Lisp_Mutex
*lmutex
;
285 lmutex
= XMUTEX (mutex
);
291 finalize_one_mutex (struct Lisp_Mutex
*mutex
)
293 lisp_mutex_destroy (&mutex
->mutex
);
298 DEFUN ("make-condition-variable",
299 Fmake_condition_variable
, Smake_condition_variable
,
301 doc
: /* Make a condition variable.
302 A condition variable provides a way for a thread to sleep while
303 waiting for a state change.
305 MUTEX is the mutex associated with this condition variable.
306 NAME, if given, is the name of this condition variable. The name is
307 informational only. */)
308 (Lisp_Object mutex
, Lisp_Object name
)
310 struct Lisp_CondVar
*condvar
;
317 condvar
= ALLOCATE_PSEUDOVECTOR (struct Lisp_CondVar
, cond
, PVEC_CONDVAR
);
318 memset ((char *) condvar
+ offsetof (struct Lisp_CondVar
, cond
),
319 0, sizeof (struct Lisp_CondVar
) - offsetof (struct Lisp_CondVar
,
321 condvar
->mutex
= mutex
;
322 condvar
->name
= name
;
323 sys_cond_init (&condvar
->cond
);
325 XSETCONDVAR (result
, condvar
);
330 condition_wait_callback (void *arg
)
332 struct Lisp_CondVar
*cvar
= arg
;
333 struct Lisp_Mutex
*mutex
= XMUTEX (cvar
->mutex
);
334 struct thread_state
*self
= current_thread
;
335 unsigned int saved_count
;
338 XSETCONDVAR (cond
, cvar
);
339 self
->event_object
= cond
;
340 saved_count
= lisp_mutex_unlock_for_wait (&mutex
->mutex
);
341 /* If we were signalled while unlocking, we skip the wait, but we
342 still must reacquire our lock. */
343 if (NILP (self
->error_symbol
))
345 self
->wait_condvar
= &cvar
->cond
;
346 sys_cond_wait (&cvar
->cond
, &global_lock
);
347 self
->wait_condvar
= NULL
;
349 lisp_mutex_lock (&mutex
->mutex
, saved_count
);
350 self
->event_object
= Qnil
;
351 post_acquire_global_lock (self
);
354 DEFUN ("condition-wait", Fcondition_wait
, Scondition_wait
, 1, 1, 0,
355 doc
: /* Wait for the condition variable to be notified.
356 CONDITION is the condition variable to wait on.
358 The mutex associated with CONDITION must be held when this is called.
359 It is an error if it is not held.
361 This releases the mutex and waits for CONDITION to be notified or for
362 this thread to be signalled with `thread-signal'. When
363 `condition-wait' returns, the mutex will again be locked by this
365 (Lisp_Object condition
)
367 struct Lisp_CondVar
*cvar
;
368 struct Lisp_Mutex
*mutex
;
370 CHECK_CONDVAR (condition
);
371 cvar
= XCONDVAR (condition
);
373 mutex
= XMUTEX (cvar
->mutex
);
374 if (!lisp_mutex_owned_p (&mutex
->mutex
))
377 flush_stack_call_func (condition_wait_callback
, cvar
);
382 /* Used to communicate argumnets to condition_notify_callback. */
385 struct Lisp_CondVar
*cvar
;
390 condition_notify_callback (void *arg
)
392 struct notify_args
*na
= arg
;
393 struct Lisp_Mutex
*mutex
= XMUTEX (na
->cvar
->mutex
);
394 struct thread_state
*self
= current_thread
;
395 unsigned int saved_count
;
398 XSETCONDVAR (cond
, na
->cvar
);
399 saved_count
= lisp_mutex_unlock_for_wait (&mutex
->mutex
);
401 sys_cond_broadcast (&na
->cvar
->cond
);
403 sys_cond_signal (&na
->cvar
->cond
);
404 lisp_mutex_lock (&mutex
->mutex
, saved_count
);
405 post_acquire_global_lock (self
);
408 DEFUN ("condition-notify", Fcondition_notify
, Scondition_notify
, 1, 2, 0,
409 doc
: /* Notify a condition variable.
410 This wakes a thread waiting on CONDITION.
411 If ALL is non-nil, all waiting threads are awoken.
413 The mutex associated with CONDITION must be held when this is called.
414 It is an error if it is not held.
416 This releases the mutex when notifying CONDITION. When
417 `condition-notify' returns, the mutex will again be locked by this
419 (Lisp_Object condition
, Lisp_Object all
)
421 struct Lisp_CondVar
*cvar
;
422 struct Lisp_Mutex
*mutex
;
423 struct notify_args args
;
425 CHECK_CONDVAR (condition
);
426 cvar
= XCONDVAR (condition
);
428 mutex
= XMUTEX (cvar
->mutex
);
429 if (!lisp_mutex_owned_p (&mutex
->mutex
))
433 args
.all
= !NILP (all
);
434 flush_stack_call_func (condition_notify_callback
, &args
);
439 DEFUN ("condition-mutex", Fcondition_mutex
, Scondition_mutex
, 1, 1, 0,
440 doc
: /* Return the mutex associated with CONDITION. */)
441 (Lisp_Object condition
)
443 struct Lisp_CondVar
*cvar
;
445 CHECK_CONDVAR (condition
);
446 cvar
= XCONDVAR (condition
);
451 DEFUN ("condition-name", Fcondition_name
, Scondition_name
, 1, 1, 0,
452 doc
: /* Return the name of CONDITION.
453 If no name was given when CONDITION was created, return nil. */)
454 (Lisp_Object condition
)
456 struct Lisp_CondVar
*cvar
;
458 CHECK_CONDVAR (condition
);
459 cvar
= XCONDVAR (condition
);
465 finalize_one_condvar (struct Lisp_CondVar
*condvar
)
467 sys_cond_destroy (&condvar
->cond
);
485 really_call_select (void *arg
)
487 struct select_args
*sa
= arg
;
488 struct thread_state
*self
= current_thread
;
490 release_global_lock ();
491 sa
->result
= (sa
->func
) (sa
->max_fds
, sa
->rfds
, sa
->wfds
, sa
->efds
,
492 sa
->timeout
, sa
->sigmask
);
493 acquire_global_lock (self
);
497 thread_select (select_func
*func
, int max_fds
, SELECT_TYPE
*rfds
,
498 SELECT_TYPE
*wfds
, SELECT_TYPE
*efds
, EMACS_TIME
*timeout
,
501 struct select_args sa
;
504 sa
.max_fds
= max_fds
;
508 sa
.timeout
= timeout
;
509 sa
.sigmask
= sigmask
;
510 flush_stack_call_func (really_call_select
, &sa
);
517 mark_one_thread (struct thread_state
*thread
)
519 struct handler
*handler
;
522 mark_specpdl (thread
->m_specpdl
, thread
->m_specpdl_ptr
);
524 #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
525 || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
526 mark_stack (thread
->m_stack_bottom
, thread
->stack_top
);
530 for (tail
= thread
->m_gcprolist
; tail
; tail
= tail
->next
)
531 for (i
= 0; i
< tail
->nvars
; i
++)
532 mark_object (tail
->var
[i
]);
536 if (thread
->m_byte_stack_list
)
537 mark_byte_stack (thread
->m_byte_stack_list
);
540 mark_catchlist (thread
->m_catchlist
);
542 for (handler
= thread
->m_handlerlist
; handler
; handler
= handler
->next
)
544 mark_object (handler
->handler
);
545 mark_object (handler
->var
);
549 if (thread
->m_current_buffer
)
551 XSETBUFFER (tem
, thread
->m_current_buffer
);
555 mark_object (thread
->m_last_thing_searched
);
557 if (thread
->m_saved_last_thing_searched
)
558 mark_object (thread
->m_saved_last_thing_searched
);
562 mark_threads_callback (void *ignore
)
564 struct thread_state
*iter
;
566 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
568 Lisp_Object thread_obj
;
570 XSETTHREAD (thread_obj
, iter
);
571 mark_object (thread_obj
);
572 mark_one_thread (iter
);
579 flush_stack_call_func (mark_threads_callback
, NULL
);
583 unmark_threads (void)
585 struct thread_state
*iter
;
587 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
588 if (iter
->m_byte_stack_list
)
589 unmark_byte_stack (iter
->m_byte_stack_list
);
595 yield_callback (void *ignore
)
597 struct thread_state
*self
= current_thread
;
599 release_global_lock ();
601 acquire_global_lock (self
);
604 DEFUN ("thread-yield", Fthread_yield
, Sthread_yield
, 0, 0, 0,
605 doc
: /* Yield the CPU to another thread. */)
608 flush_stack_call_func (yield_callback
, NULL
);
613 invoke_thread_function (void)
616 volatile struct thread_state
*self
= current_thread
;
618 int count
= SPECPDL_INDEX ();
620 Ffuncall (1, ¤t_thread
->function
);
621 return unbind_to (count
, Qnil
);
625 do_nothing (Lisp_Object whatever
)
631 run_thread (void *state
)
634 struct thread_state
*self
= state
;
635 struct thread_state
**iter
;
637 self
->m_stack_bottom
= &stack_pos
;
638 self
->stack_top
= &stack_pos
;
639 self
->thread_id
= sys_thread_self ();
641 acquire_global_lock (self
);
643 /* It might be nice to do something with errors here. */
644 internal_condition_case (invoke_thread_function
, Qt
, do_nothing
);
646 update_processes_for_thread_death (Fcurrent_thread ());
648 xfree (self
->m_specpdl
- 1);
649 self
->m_specpdl
= NULL
;
650 self
->m_specpdl_ptr
= NULL
;
651 self
->m_specpdl_size
= 0;
653 current_thread
= NULL
;
654 sys_cond_broadcast (&self
->thread_condvar
);
656 /* Unlink this thread from the list of all threads. Note that we
657 have to do this very late, after broadcasting our death.
658 Otherwise the GC may decide to reap the thread_state object,
659 leading to crashes. */
660 for (iter
= &all_threads
; *iter
!= self
; iter
= &(*iter
)->next_thread
)
662 *iter
= (*iter
)->next_thread
;
664 release_global_lock ();
670 finalize_one_thread (struct thread_state
*state
)
672 sys_cond_destroy (&state
->thread_condvar
);
675 DEFUN ("make-thread", Fmake_thread
, Smake_thread
, 1, 2, 0,
676 doc
: /* Start a new thread and run FUNCTION in it.
677 When the function exits, the thread dies.
678 If NAME is given, it names the new thread. */)
679 (Lisp_Object function
, Lisp_Object name
)
682 struct thread_state
*new_thread
;
684 const char *c_name
= NULL
;
686 /* Can't start a thread in temacs. */
693 new_thread
= ALLOCATE_PSEUDOVECTOR (struct thread_state
, m_gcprolist
,
695 memset ((char *) new_thread
+ offsetof (struct thread_state
, m_gcprolist
),
696 0, sizeof (struct thread_state
) - offsetof (struct thread_state
,
699 new_thread
->function
= function
;
700 new_thread
->name
= name
;
701 new_thread
->m_last_thing_searched
= Qnil
; /* copy from parent? */
702 new_thread
->m_saved_last_thing_searched
= Qnil
;
703 new_thread
->m_current_buffer
= current_thread
->m_current_buffer
;
704 new_thread
->error_symbol
= Qnil
;
705 new_thread
->error_data
= Qnil
;
706 new_thread
->event_object
= Qnil
;
708 new_thread
->m_specpdl_size
= 50;
709 new_thread
->m_specpdl
= xmalloc ((1 + new_thread
->m_specpdl_size
)
710 * sizeof (union specbinding
));
711 /* Skip the dummy entry. */
712 ++new_thread
->m_specpdl
;
713 new_thread
->m_specpdl_ptr
= new_thread
->m_specpdl
;
715 sys_cond_init (&new_thread
->thread_condvar
);
717 /* We'll need locking here eventually. */
718 new_thread
->next_thread
= all_threads
;
719 all_threads
= new_thread
;
722 c_name
= SSDATA (ENCODE_UTF_8 (name
));
724 if (! sys_thread_create (&thr
, c_name
, run_thread
, new_thread
))
726 /* Restore the previous situation. */
727 all_threads
= all_threads
->next_thread
;
728 error ("Could not start a new thread");
731 /* FIXME: race here where new thread might not be filled in? */
732 XSETTHREAD (result
, new_thread
);
736 DEFUN ("current-thread", Fcurrent_thread
, Scurrent_thread
, 0, 0, 0,
737 doc
: /* Return the current thread. */)
741 XSETTHREAD (result
, current_thread
);
745 DEFUN ("thread-name", Fthread_name
, Sthread_name
, 1, 1, 0,
746 doc
: /* Return the name of the THREAD.
747 The name is the same object that was passed to `make-thread'. */)
750 struct thread_state
*tstate
;
752 CHECK_THREAD (thread
);
753 tstate
= XTHREAD (thread
);
759 thread_signal_callback (void *arg
)
761 struct thread_state
*tstate
= arg
;
762 struct thread_state
*self
= current_thread
;
764 sys_cond_broadcast (tstate
->wait_condvar
);
765 post_acquire_global_lock (self
);
768 DEFUN ("thread-signal", Fthread_signal
, Sthread_signal
, 3, 3, 0,
769 doc
: /* Signal an error in a thread.
770 This acts like `signal', but arranges for the signal to be raised
771 in THREAD. If THREAD is the current thread, acts just like `signal'.
772 This will interrupt a blocked call to `mutex-lock', `condition-wait',
773 or `thread-join' in the target thread. */)
774 (Lisp_Object thread
, Lisp_Object error_symbol
, Lisp_Object data
)
776 struct thread_state
*tstate
;
778 CHECK_THREAD (thread
);
779 tstate
= XTHREAD (thread
);
781 if (tstate
== current_thread
)
782 Fsignal (error_symbol
, data
);
784 /* What to do if thread is already signalled? */
785 /* What if error_symbol is Qnil? */
786 tstate
->error_symbol
= error_symbol
;
787 tstate
->error_data
= data
;
789 if (tstate
->wait_condvar
)
790 flush_stack_call_func (thread_signal_callback
, tstate
);
795 DEFUN ("thread-alive-p", Fthread_alive_p
, Sthread_alive_p
, 1, 1, 0,
796 doc
: /* Return t if THREAD is alive, or nil if it has exited. */)
799 struct thread_state
*tstate
;
801 CHECK_THREAD (thread
);
802 tstate
= XTHREAD (thread
);
804 return thread_alive_p (tstate
) ? Qt
: Qnil
;
807 DEFUN ("thread-blocker", Fthread_blocker
, Sthread_blocker
, 1, 1, 0,
808 doc
: /* Return the object that THREAD is blocking on.
809 If THREAD is blocked in `thread-join' on a second thread, return that
811 If THREAD is blocked in `mutex-lock', return the mutex.
812 If THREAD is blocked in `condition-wait', return the condition variable.
813 Otherwise, if THREAD is not blocked, return nil. */)
816 struct thread_state
*tstate
;
818 CHECK_THREAD (thread
);
819 tstate
= XTHREAD (thread
);
821 return tstate
->event_object
;
825 thread_join_callback (void *arg
)
827 struct thread_state
*tstate
= arg
;
828 struct thread_state
*self
= current_thread
;
831 XSETTHREAD (thread
, tstate
);
832 self
->event_object
= thread
;
833 self
->wait_condvar
= &tstate
->thread_condvar
;
834 while (thread_alive_p (tstate
) && NILP (self
->error_symbol
))
835 sys_cond_wait (self
->wait_condvar
, &global_lock
);
837 self
->wait_condvar
= NULL
;
838 self
->event_object
= Qnil
;
839 post_acquire_global_lock (self
);
842 DEFUN ("thread-join", Fthread_join
, Sthread_join
, 1, 1, 0,
843 doc
: /* Wait for a thread to exit.
844 This blocks the current thread until THREAD exits.
845 It is an error for a thread to try to join itself. */)
848 struct thread_state
*tstate
;
850 CHECK_THREAD (thread
);
851 tstate
= XTHREAD (thread
);
853 if (tstate
== current_thread
)
854 error ("cannot join current thread");
856 if (thread_alive_p (tstate
))
857 flush_stack_call_func (thread_join_callback
, tstate
);
862 DEFUN ("all-threads", Fall_threads
, Sall_threads
, 0, 0, 0,
863 doc
: /* Return a list of all threads. */)
866 Lisp_Object result
= Qnil
;
867 struct thread_state
*iter
;
869 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
871 if (thread_alive_p (iter
))
875 XSETTHREAD (thread
, iter
);
876 result
= Fcons (thread
, result
);
886 thread_check_current_buffer (struct buffer
*buffer
)
888 struct thread_state
*iter
;
890 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
892 if (iter
== current_thread
)
895 if (iter
->m_current_buffer
== buffer
)
905 init_primary_thread (void)
907 primary_thread
.header
.size
908 = PSEUDOVECSIZE (struct thread_state
, m_gcprolist
);
909 XSETPVECTYPE (&primary_thread
, PVEC_THREAD
);
910 primary_thread
.m_last_thing_searched
= Qnil
;
911 primary_thread
.m_saved_last_thing_searched
= Qnil
;
912 primary_thread
.name
= Qnil
;
913 primary_thread
.function
= Qnil
;
914 primary_thread
.error_symbol
= Qnil
;
915 primary_thread
.error_data
= Qnil
;
916 primary_thread
.event_object
= Qnil
;
920 init_threads_once (void)
922 init_primary_thread ();
928 init_primary_thread ();
929 sys_cond_init (&primary_thread
.thread_condvar
);
930 sys_mutex_init (&global_lock
);
931 sys_mutex_lock (&global_lock
);
932 current_thread
= &primary_thread
;
933 primary_thread
.thread_id
= sys_thread_self ();
937 syms_of_threads (void)
939 #ifndef THREADS_ENABLED
943 defsubr (&Sthread_yield
);
944 defsubr (&Smake_thread
);
945 defsubr (&Scurrent_thread
);
946 defsubr (&Sthread_name
);
947 defsubr (&Sthread_signal
);
948 defsubr (&Sthread_alive_p
);
949 defsubr (&Sthread_join
);
950 defsubr (&Sthread_blocker
);
951 defsubr (&Sall_threads
);
952 defsubr (&Smake_mutex
);
953 defsubr (&Smutex_lock
);
954 defsubr (&Smutex_unlock
);
955 defsubr (&Smutex_name
);
956 defsubr (&Smake_condition_variable
);
957 defsubr (&Scondition_wait
);
958 defsubr (&Scondition_notify
);
959 defsubr (&Scondition_mutex
);
960 defsubr (&Scondition_name
);
963 Qthreadp
= intern_c_string ("threadp");
964 staticpro (&Qthreadp
);
965 Qmutexp
= intern_c_string ("mutexp");
966 staticpro (&Qmutexp
);
967 Qcondition_variablep
= intern_c_string ("condition-variablep");
968 staticpro (&Qcondition_variablep
);