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_variable_p
;
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
)
58 struct thread_state
*prev_thread
= current_thread
;
60 /* Do this early on, so that code below could signal errors (e.g.,
61 unbind_for_thread_switch might) correctly, because we are already
62 running in the context of the thread pointed by SELF. */
63 current_thread
= self
;
65 if (prev_thread
!= current_thread
)
67 /* PREV_THREAD is NULL if the previously current thread
68 exited. In this case, there is no reason to unbind, and
70 if (prev_thread
!= NULL
)
71 unbind_for_thread_switch (prev_thread
);
72 rebind_for_thread_switch ();
75 /* We need special handling to re-set the buffer. */
76 XSETBUFFER (buffer
, self
->m_current_buffer
);
77 self
->m_current_buffer
= 0;
78 set_buffer_internal (XBUFFER (buffer
));
80 if (!NILP (current_thread
->error_symbol
))
82 Lisp_Object sym
= current_thread
->error_symbol
;
83 Lisp_Object data
= current_thread
->error_data
;
85 current_thread
->error_symbol
= Qnil
;
86 current_thread
->error_data
= Qnil
;
92 acquire_global_lock (struct thread_state
*self
)
94 sys_mutex_lock (&global_lock
);
95 post_acquire_global_lock (self
);
101 lisp_mutex_init (lisp_mutex_t
*mutex
)
105 sys_cond_init (&mutex
->condition
);
109 lisp_mutex_lock (lisp_mutex_t
*mutex
, int new_count
)
111 struct thread_state
*self
;
113 if (mutex
->owner
== NULL
)
115 mutex
->owner
= current_thread
;
116 mutex
->count
= new_count
== 0 ? 1 : new_count
;
119 if (mutex
->owner
== current_thread
)
121 eassert (new_count
== 0);
126 self
= current_thread
;
127 self
->wait_condvar
= &mutex
->condition
;
128 while (mutex
->owner
!= NULL
&& (new_count
!= 0
129 || NILP (self
->error_symbol
)))
130 sys_cond_wait (&mutex
->condition
, &global_lock
);
131 self
->wait_condvar
= NULL
;
133 if (new_count
== 0 && !NILP (self
->error_symbol
))
137 mutex
->count
= new_count
== 0 ? 1 : new_count
;
143 lisp_mutex_unlock (lisp_mutex_t
*mutex
)
145 struct thread_state
*self
= current_thread
;
147 if (mutex
->owner
!= current_thread
)
150 if (--mutex
->count
> 0)
154 sys_cond_broadcast (&mutex
->condition
);
160 lisp_mutex_unlock_for_wait (lisp_mutex_t
*mutex
)
162 struct thread_state
*self
= current_thread
;
163 unsigned int result
= mutex
->count
;
165 /* Ensured by condvar code. */
166 eassert (mutex
->owner
== current_thread
);
170 sys_cond_broadcast (&mutex
->condition
);
176 lisp_mutex_destroy (lisp_mutex_t
*mutex
)
178 sys_cond_destroy (&mutex
->condition
);
182 lisp_mutex_owned_p (lisp_mutex_t
*mutex
)
184 return mutex
->owner
== current_thread
;
189 DEFUN ("make-mutex", Fmake_mutex
, Smake_mutex
, 0, 1, 0,
190 doc
: /* Create a mutex.
191 A mutex provides a synchronization point for threads.
192 Only one thread at a time can hold a mutex. Other threads attempting
193 to acquire it will block until the mutex is available.
195 A thread can acquire a mutex any number of times.
197 NAME, if given, is used as the name of the mutex. The name is
198 informational only. */)
201 struct Lisp_Mutex
*mutex
;
207 mutex
= ALLOCATE_PSEUDOVECTOR (struct Lisp_Mutex
, mutex
, PVEC_MUTEX
);
208 memset ((char *) mutex
+ offsetof (struct Lisp_Mutex
, mutex
),
209 0, sizeof (struct Lisp_Mutex
) - offsetof (struct Lisp_Mutex
,
212 lisp_mutex_init (&mutex
->mutex
);
214 XSETMUTEX (result
, mutex
);
219 mutex_lock_callback (void *arg
)
221 struct Lisp_Mutex
*mutex
= arg
;
222 struct thread_state
*self
= current_thread
;
224 if (lisp_mutex_lock (&mutex
->mutex
, 0))
225 post_acquire_global_lock (self
);
229 do_unwind_mutex_lock (void)
231 current_thread
->event_object
= Qnil
;
234 DEFUN ("mutex-lock", Fmutex_lock
, Smutex_lock
, 1, 1, 0,
235 doc
: /* Acquire a mutex.
236 If the current thread already owns MUTEX, increment the count and
238 Otherwise, if no thread owns MUTEX, make the current thread own it.
239 Otherwise, block until MUTEX is available, or until the current thread
240 is signalled using `thread-signal'.
241 Note that calls to `mutex-lock' and `mutex-unlock' must be paired. */)
244 struct Lisp_Mutex
*lmutex
;
245 ptrdiff_t count
= SPECPDL_INDEX ();
248 lmutex
= XMUTEX (mutex
);
250 current_thread
->event_object
= mutex
;
251 record_unwind_protect_void (do_unwind_mutex_lock
);
252 flush_stack_call_func (mutex_lock_callback
, lmutex
);
253 return unbind_to (count
, Qnil
);
257 mutex_unlock_callback (void *arg
)
259 struct Lisp_Mutex
*mutex
= arg
;
260 struct thread_state
*self
= current_thread
;
262 if (lisp_mutex_unlock (&mutex
->mutex
))
263 post_acquire_global_lock (self
);
266 DEFUN ("mutex-unlock", Fmutex_unlock
, Smutex_unlock
, 1, 1, 0,
267 doc
: /* Release the mutex.
268 If this thread does not own MUTEX, signal an error.
269 Otherwise, decrement the mutex's count. If the count is zero,
273 struct Lisp_Mutex
*lmutex
;
276 lmutex
= XMUTEX (mutex
);
278 flush_stack_call_func (mutex_unlock_callback
, lmutex
);
282 DEFUN ("mutex-name", Fmutex_name
, Smutex_name
, 1, 1, 0,
283 doc
: /* Return the name of MUTEX.
284 If no name was given when MUTEX was created, return nil. */)
287 struct Lisp_Mutex
*lmutex
;
290 lmutex
= XMUTEX (mutex
);
296 finalize_one_mutex (struct Lisp_Mutex
*mutex
)
298 lisp_mutex_destroy (&mutex
->mutex
);
303 DEFUN ("make-condition-variable",
304 Fmake_condition_variable
, Smake_condition_variable
,
306 doc
: /* Make a condition variable.
307 A condition variable provides a way for a thread to sleep while
308 waiting for a state change.
310 MUTEX is the mutex associated with this condition variable.
311 NAME, if given, is the name of this condition variable. The name is
312 informational only. */)
313 (Lisp_Object mutex
, Lisp_Object name
)
315 struct Lisp_CondVar
*condvar
;
322 condvar
= ALLOCATE_PSEUDOVECTOR (struct Lisp_CondVar
, cond
, PVEC_CONDVAR
);
323 memset ((char *) condvar
+ offsetof (struct Lisp_CondVar
, cond
),
324 0, sizeof (struct Lisp_CondVar
) - offsetof (struct Lisp_CondVar
,
326 condvar
->mutex
= mutex
;
327 condvar
->name
= name
;
328 sys_cond_init (&condvar
->cond
);
330 XSETCONDVAR (result
, condvar
);
335 condition_wait_callback (void *arg
)
337 struct Lisp_CondVar
*cvar
= arg
;
338 struct Lisp_Mutex
*mutex
= XMUTEX (cvar
->mutex
);
339 struct thread_state
*self
= current_thread
;
340 unsigned int saved_count
;
343 XSETCONDVAR (cond
, cvar
);
344 self
->event_object
= cond
;
345 saved_count
= lisp_mutex_unlock_for_wait (&mutex
->mutex
);
346 /* If we were signalled while unlocking, we skip the wait, but we
347 still must reacquire our lock. */
348 if (NILP (self
->error_symbol
))
350 self
->wait_condvar
= &cvar
->cond
;
351 sys_cond_wait (&cvar
->cond
, &global_lock
);
352 self
->wait_condvar
= NULL
;
354 lisp_mutex_lock (&mutex
->mutex
, saved_count
);
355 self
->event_object
= Qnil
;
356 post_acquire_global_lock (self
);
359 DEFUN ("condition-wait", Fcondition_wait
, Scondition_wait
, 1, 1, 0,
360 doc
: /* Wait for the condition variable to be notified.
361 CONDITION is the condition variable to wait on.
363 The mutex associated with CONDITION must be held when this is called.
364 It is an error if it is not held.
366 This releases the mutex and waits for CONDITION to be notified or for
367 this thread to be signalled with `thread-signal'. When
368 `condition-wait' returns, the mutex will again be locked by this
370 (Lisp_Object condition
)
372 struct Lisp_CondVar
*cvar
;
373 struct Lisp_Mutex
*mutex
;
375 CHECK_CONDVAR (condition
);
376 cvar
= XCONDVAR (condition
);
378 mutex
= XMUTEX (cvar
->mutex
);
379 if (!lisp_mutex_owned_p (&mutex
->mutex
))
382 flush_stack_call_func (condition_wait_callback
, cvar
);
387 /* Used to communicate argumnets to condition_notify_callback. */
390 struct Lisp_CondVar
*cvar
;
395 condition_notify_callback (void *arg
)
397 struct notify_args
*na
= arg
;
398 struct Lisp_Mutex
*mutex
= XMUTEX (na
->cvar
->mutex
);
399 struct thread_state
*self
= current_thread
;
400 unsigned int saved_count
;
403 XSETCONDVAR (cond
, na
->cvar
);
404 saved_count
= lisp_mutex_unlock_for_wait (&mutex
->mutex
);
406 sys_cond_broadcast (&na
->cvar
->cond
);
408 sys_cond_signal (&na
->cvar
->cond
);
409 lisp_mutex_lock (&mutex
->mutex
, saved_count
);
410 post_acquire_global_lock (self
);
413 DEFUN ("condition-notify", Fcondition_notify
, Scondition_notify
, 1, 2, 0,
414 doc
: /* Notify a condition variable.
415 This wakes a thread waiting on CONDITION.
416 If ALL is non-nil, all waiting threads are awoken.
418 The mutex associated with CONDITION must be held when this is called.
419 It is an error if it is not held.
421 This releases the mutex when notifying CONDITION. When
422 `condition-notify' returns, the mutex will again be locked by this
424 (Lisp_Object condition
, Lisp_Object all
)
426 struct Lisp_CondVar
*cvar
;
427 struct Lisp_Mutex
*mutex
;
428 struct notify_args args
;
430 CHECK_CONDVAR (condition
);
431 cvar
= XCONDVAR (condition
);
433 mutex
= XMUTEX (cvar
->mutex
);
434 if (!lisp_mutex_owned_p (&mutex
->mutex
))
438 args
.all
= !NILP (all
);
439 flush_stack_call_func (condition_notify_callback
, &args
);
444 DEFUN ("condition-mutex", Fcondition_mutex
, Scondition_mutex
, 1, 1, 0,
445 doc
: /* Return the mutex associated with CONDITION. */)
446 (Lisp_Object condition
)
448 struct Lisp_CondVar
*cvar
;
450 CHECK_CONDVAR (condition
);
451 cvar
= XCONDVAR (condition
);
456 DEFUN ("condition-name", Fcondition_name
, Scondition_name
, 1, 1, 0,
457 doc
: /* Return the name of CONDITION.
458 If no name was given when CONDITION was created, return nil. */)
459 (Lisp_Object condition
)
461 struct Lisp_CondVar
*cvar
;
463 CHECK_CONDVAR (condition
);
464 cvar
= XCONDVAR (condition
);
470 finalize_one_condvar (struct Lisp_CondVar
*condvar
)
472 sys_cond_destroy (&condvar
->cond
);
490 really_call_select (void *arg
)
492 struct select_args
*sa
= arg
;
493 struct thread_state
*self
= current_thread
;
495 release_global_lock ();
496 sa
->result
= (sa
->func
) (sa
->max_fds
, sa
->rfds
, sa
->wfds
, sa
->efds
,
497 sa
->timeout
, sa
->sigmask
);
498 acquire_global_lock (self
);
502 thread_select (select_func
*func
, int max_fds
, SELECT_TYPE
*rfds
,
503 SELECT_TYPE
*wfds
, SELECT_TYPE
*efds
, EMACS_TIME
*timeout
,
506 struct select_args sa
;
509 sa
.max_fds
= max_fds
;
513 sa
.timeout
= timeout
;
514 sa
.sigmask
= sigmask
;
515 flush_stack_call_func (really_call_select
, &sa
);
522 mark_one_thread (struct thread_state
*thread
)
524 struct handler
*handler
;
527 mark_specpdl (thread
->m_specpdl
, thread
->m_specpdl_ptr
);
529 #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
530 || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
531 mark_stack (thread
->m_stack_bottom
, thread
->stack_top
);
535 for (tail
= thread
->m_gcprolist
; tail
; tail
= tail
->next
)
536 for (i
= 0; i
< tail
->nvars
; i
++)
537 mark_object (tail
->var
[i
]);
541 if (thread
->m_byte_stack_list
)
542 mark_byte_stack (thread
->m_byte_stack_list
);
545 mark_catchlist (thread
->m_catchlist
);
547 for (handler
= thread
->m_handlerlist
; handler
; handler
= handler
->next
)
549 mark_object (handler
->handler
);
550 mark_object (handler
->var
);
554 if (thread
->m_current_buffer
)
556 XSETBUFFER (tem
, thread
->m_current_buffer
);
560 mark_object (thread
->m_last_thing_searched
);
562 if (thread
->m_saved_last_thing_searched
)
563 mark_object (thread
->m_saved_last_thing_searched
);
567 mark_threads_callback (void *ignore
)
569 struct thread_state
*iter
;
571 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
573 Lisp_Object thread_obj
;
575 XSETTHREAD (thread_obj
, iter
);
576 mark_object (thread_obj
);
577 mark_one_thread (iter
);
584 flush_stack_call_func (mark_threads_callback
, NULL
);
588 unmark_threads (void)
590 struct thread_state
*iter
;
592 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
593 if (iter
->m_byte_stack_list
)
594 unmark_byte_stack (iter
->m_byte_stack_list
);
600 yield_callback (void *ignore
)
602 struct thread_state
*self
= current_thread
;
604 release_global_lock ();
606 acquire_global_lock (self
);
609 DEFUN ("thread-yield", Fthread_yield
, Sthread_yield
, 0, 0, 0,
610 doc
: /* Yield the CPU to another thread. */)
613 flush_stack_call_func (yield_callback
, NULL
);
618 invoke_thread_function (void)
621 volatile struct thread_state
*self
= current_thread
;
623 int count
= SPECPDL_INDEX ();
625 Ffuncall (1, ¤t_thread
->function
);
626 return unbind_to (count
, Qnil
);
630 do_nothing (Lisp_Object whatever
)
636 run_thread (void *state
)
639 struct thread_state
*self
= state
;
640 struct thread_state
**iter
;
642 self
->m_stack_bottom
= &stack_pos
;
643 self
->stack_top
= &stack_pos
;
644 self
->thread_id
= sys_thread_self ();
646 acquire_global_lock (self
);
648 /* It might be nice to do something with errors here. */
649 internal_condition_case (invoke_thread_function
, Qt
, do_nothing
);
651 update_processes_for_thread_death (Fcurrent_thread ());
653 xfree (self
->m_specpdl
- 1);
654 self
->m_specpdl
= NULL
;
655 self
->m_specpdl_ptr
= NULL
;
656 self
->m_specpdl_size
= 0;
658 current_thread
= NULL
;
659 sys_cond_broadcast (&self
->thread_condvar
);
661 /* Unlink this thread from the list of all threads. Note that we
662 have to do this very late, after broadcasting our death.
663 Otherwise the GC may decide to reap the thread_state object,
664 leading to crashes. */
665 for (iter
= &all_threads
; *iter
!= self
; iter
= &(*iter
)->next_thread
)
667 *iter
= (*iter
)->next_thread
;
669 release_global_lock ();
675 finalize_one_thread (struct thread_state
*state
)
677 sys_cond_destroy (&state
->thread_condvar
);
680 DEFUN ("make-thread", Fmake_thread
, Smake_thread
, 1, 2, 0,
681 doc
: /* Start a new thread and run FUNCTION in it.
682 When the function exits, the thread dies.
683 If NAME is given, it names the new thread. */)
684 (Lisp_Object function
, Lisp_Object name
)
687 struct thread_state
*new_thread
;
689 const char *c_name
= NULL
;
691 /* Can't start a thread in temacs. */
698 new_thread
= ALLOCATE_PSEUDOVECTOR (struct thread_state
, m_gcprolist
,
700 memset ((char *) new_thread
+ offsetof (struct thread_state
, m_gcprolist
),
701 0, sizeof (struct thread_state
) - offsetof (struct thread_state
,
704 new_thread
->function
= function
;
705 new_thread
->name
= name
;
706 new_thread
->m_last_thing_searched
= Qnil
; /* copy from parent? */
707 new_thread
->m_saved_last_thing_searched
= Qnil
;
708 new_thread
->m_current_buffer
= current_thread
->m_current_buffer
;
709 new_thread
->error_symbol
= Qnil
;
710 new_thread
->error_data
= Qnil
;
711 new_thread
->event_object
= Qnil
;
713 new_thread
->m_specpdl_size
= 50;
714 new_thread
->m_specpdl
= xmalloc ((1 + new_thread
->m_specpdl_size
)
715 * sizeof (union specbinding
));
716 /* Skip the dummy entry. */
717 ++new_thread
->m_specpdl
;
718 new_thread
->m_specpdl_ptr
= new_thread
->m_specpdl
;
720 sys_cond_init (&new_thread
->thread_condvar
);
722 /* We'll need locking here eventually. */
723 new_thread
->next_thread
= all_threads
;
724 all_threads
= new_thread
;
727 c_name
= SSDATA (ENCODE_UTF_8 (name
));
729 if (! sys_thread_create (&thr
, c_name
, run_thread
, new_thread
))
731 /* Restore the previous situation. */
732 all_threads
= all_threads
->next_thread
;
733 error ("Could not start a new thread");
736 /* FIXME: race here where new thread might not be filled in? */
737 XSETTHREAD (result
, new_thread
);
741 DEFUN ("current-thread", Fcurrent_thread
, Scurrent_thread
, 0, 0, 0,
742 doc
: /* Return the current thread. */)
746 XSETTHREAD (result
, current_thread
);
750 DEFUN ("thread-name", Fthread_name
, Sthread_name
, 1, 1, 0,
751 doc
: /* Return the name of the THREAD.
752 The name is the same object that was passed to `make-thread'. */)
755 struct thread_state
*tstate
;
757 CHECK_THREAD (thread
);
758 tstate
= XTHREAD (thread
);
764 thread_signal_callback (void *arg
)
766 struct thread_state
*tstate
= arg
;
767 struct thread_state
*self
= current_thread
;
769 sys_cond_broadcast (tstate
->wait_condvar
);
770 post_acquire_global_lock (self
);
773 DEFUN ("thread-signal", Fthread_signal
, Sthread_signal
, 3, 3, 0,
774 doc
: /* Signal an error in a thread.
775 This acts like `signal', but arranges for the signal to be raised
776 in THREAD. If THREAD is the current thread, acts just like `signal'.
777 This will interrupt a blocked call to `mutex-lock', `condition-wait',
778 or `thread-join' in the target thread. */)
779 (Lisp_Object thread
, Lisp_Object error_symbol
, Lisp_Object data
)
781 struct thread_state
*tstate
;
783 CHECK_THREAD (thread
);
784 tstate
= XTHREAD (thread
);
786 if (tstate
== current_thread
)
787 Fsignal (error_symbol
, data
);
789 /* What to do if thread is already signalled? */
790 /* What if error_symbol is Qnil? */
791 tstate
->error_symbol
= error_symbol
;
792 tstate
->error_data
= data
;
794 if (tstate
->wait_condvar
)
795 flush_stack_call_func (thread_signal_callback
, tstate
);
800 DEFUN ("thread-alive-p", Fthread_alive_p
, Sthread_alive_p
, 1, 1, 0,
801 doc
: /* Return t if THREAD is alive, or nil if it has exited. */)
804 struct thread_state
*tstate
;
806 CHECK_THREAD (thread
);
807 tstate
= XTHREAD (thread
);
809 return thread_alive_p (tstate
) ? Qt
: Qnil
;
812 DEFUN ("thread--blocker", Fthread_blocker
, Sthread_blocker
, 1, 1, 0,
813 doc
: /* Return the object that THREAD is blocking on.
814 If THREAD is blocked in `thread-join' on a second thread, return that
816 If THREAD is blocked in `mutex-lock', return the mutex.
817 If THREAD is blocked in `condition-wait', return the condition variable.
818 Otherwise, if THREAD is not blocked, return nil. */)
821 struct thread_state
*tstate
;
823 CHECK_THREAD (thread
);
824 tstate
= XTHREAD (thread
);
826 return tstate
->event_object
;
830 thread_join_callback (void *arg
)
832 struct thread_state
*tstate
= arg
;
833 struct thread_state
*self
= current_thread
;
836 XSETTHREAD (thread
, tstate
);
837 self
->event_object
= thread
;
838 self
->wait_condvar
= &tstate
->thread_condvar
;
839 while (thread_alive_p (tstate
) && NILP (self
->error_symbol
))
840 sys_cond_wait (self
->wait_condvar
, &global_lock
);
842 self
->wait_condvar
= NULL
;
843 self
->event_object
= Qnil
;
844 post_acquire_global_lock (self
);
847 DEFUN ("thread-join", Fthread_join
, Sthread_join
, 1, 1, 0,
848 doc
: /* Wait for a thread to exit.
849 This blocks the current thread until THREAD exits.
850 It is an error for a thread to try to join itself. */)
853 struct thread_state
*tstate
;
855 CHECK_THREAD (thread
);
856 tstate
= XTHREAD (thread
);
858 if (tstate
== current_thread
)
859 error ("cannot join current thread");
861 if (thread_alive_p (tstate
))
862 flush_stack_call_func (thread_join_callback
, tstate
);
867 DEFUN ("all-threads", Fall_threads
, Sall_threads
, 0, 0, 0,
868 doc
: /* Return a list of all threads. */)
871 Lisp_Object result
= Qnil
;
872 struct thread_state
*iter
;
874 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
876 if (thread_alive_p (iter
))
880 XSETTHREAD (thread
, iter
);
881 result
= Fcons (thread
, result
);
891 thread_check_current_buffer (struct buffer
*buffer
)
893 struct thread_state
*iter
;
895 for (iter
= all_threads
; iter
; iter
= iter
->next_thread
)
897 if (iter
== current_thread
)
900 if (iter
->m_current_buffer
== buffer
)
910 init_primary_thread (void)
912 primary_thread
.header
.size
913 = PSEUDOVECSIZE (struct thread_state
, m_gcprolist
);
914 XSETPVECTYPE (&primary_thread
, PVEC_THREAD
);
915 primary_thread
.m_last_thing_searched
= Qnil
;
916 primary_thread
.m_saved_last_thing_searched
= Qnil
;
917 primary_thread
.name
= Qnil
;
918 primary_thread
.function
= Qnil
;
919 primary_thread
.error_symbol
= Qnil
;
920 primary_thread
.error_data
= Qnil
;
921 primary_thread
.event_object
= Qnil
;
925 init_threads_once (void)
927 init_primary_thread ();
933 init_primary_thread ();
934 sys_cond_init (&primary_thread
.thread_condvar
);
935 sys_mutex_init (&global_lock
);
936 sys_mutex_lock (&global_lock
);
937 current_thread
= &primary_thread
;
938 primary_thread
.thread_id
= sys_thread_self ();
942 syms_of_threads (void)
944 #ifndef THREADS_ENABLED
948 defsubr (&Sthread_yield
);
949 defsubr (&Smake_thread
);
950 defsubr (&Scurrent_thread
);
951 defsubr (&Sthread_name
);
952 defsubr (&Sthread_signal
);
953 defsubr (&Sthread_alive_p
);
954 defsubr (&Sthread_join
);
955 defsubr (&Sthread_blocker
);
956 defsubr (&Sall_threads
);
957 defsubr (&Smake_mutex
);
958 defsubr (&Smutex_lock
);
959 defsubr (&Smutex_unlock
);
960 defsubr (&Smutex_name
);
961 defsubr (&Smake_condition_variable
);
962 defsubr (&Scondition_wait
);
963 defsubr (&Scondition_notify
);
964 defsubr (&Scondition_mutex
);
965 defsubr (&Scondition_name
);
968 Qthreadp
= intern_c_string ("threadp");
969 staticpro (&Qthreadp
);
970 Qmutexp
= intern_c_string ("mutexp");
971 staticpro (&Qmutexp
);
972 Qcondition_variable_p
= intern_c_string ("condition-variable-p");
973 staticpro (&Qcondition_variable_p
);