6 void mark_byte_stack
P_ ((struct byte_stack
*));
7 void mark_backtrace
P_ ((struct backtrace
*));
8 void mark_catchlist
P_ ((struct catchtag
*));
9 void mark_stack
P_ ((char *, char *));
10 void flush_stack_call_func
P_ ((void (*) (char *)));
13 static struct thread_state primary_thread
;
15 static struct thread_state
*all_threads
= &primary_thread
;
17 __thread
struct thread_state
*current_thread
= &primary_thread
;
19 static pthread_mutex_t global_lock
;
22 mark_one_thread (struct thread_state
*thread
)
24 register struct specbinding
*bind
;
25 struct handler
*handler
;
27 for (bind
= thread
->m_specpdl
; bind
!= thread
->m_specpdl_ptr
; bind
++)
29 mark_object (bind
->symbol
);
30 mark_object (bind
->old_value
);
33 #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
34 || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
35 mark_stack (thread
->stack_bottom
, thread
->stack_top
);
38 register struct gcpro
*tail
;
39 for (tail
= thread
->m_gcprolist
; tail
; tail
= tail
->next
)
40 for (i
= 0; i
< tail
->nvars
; i
++)
41 mark_object (tail
->var
[i
]);
45 mark_byte_stack (thread
->m_byte_stack_list
);
47 mark_catchlist (thread
->m_catchlist
);
49 for (handler
= thread
->m_handlerlist
; handler
; handler
= handler
->next
)
51 mark_object (handler
->handler
);
52 mark_object (handler
->var
);
55 mark_backtrace (thread
->m_backtrace_list
);
58 mark_object (thread
->func
);
62 mark_threads_continuation (char *end
)
64 struct thread_state
*iter
;
66 current_thread
->stack_top
= end
;
67 for (iter
= all_threads
; iter
; iter
= iter
->next
)
68 mark_one_thread (iter
);
74 flush_stack_call_func (mark_threads_continuation
);
80 struct thread_state
*iter
;
82 for (iter
= all_threads
; iter
; iter
= iter
->next
)
83 unmark_byte_stack (iter
->m_byte_stack_list
);
87 thread_yield_continuation (char *end
)
89 current_thread
->stack_top
= end
;
90 pthread_mutex_unlock (&global_lock
);
92 pthread_mutex_lock (&global_lock
);
98 /* Note: currently it is safe to check this here, but eventually it
99 will require a lock to ensure non-racy operation. */
100 /* Only yield if there is another thread to yield to. */
101 if (all_threads
->next
)
102 flush_stack_call_func (thread_yield_continuation
);
105 DEFUN ("yield", Fyield
, Syield
, 0, 0, 0,
106 doc
: /* Yield to the next thread. */)
113 run_thread (void *state
)
115 char stack_bottom_variable
;
116 struct thread_state
*self
= state
;
117 struct thread_state
**iter
;
119 self
->stack_bottom
= &stack_bottom_variable
;
121 self
->m_specpdl_size
= 50;
122 self
->m_specpdl
= xmalloc (self
->m_specpdl_size
123 * sizeof (struct specbinding
));
124 self
->m_specpdl_ptr
= self
->m_specpdl
;
126 /* Thread-local assignment. */
127 current_thread
= self
;
129 pthread_mutex_lock (&global_lock
);
131 /* FIXME: unwind protect here. */
132 Ffuncall (1, &self
->func
);
134 /* Unlink this thread from the list of all threads. */
135 for (iter
= &all_threads
; *iter
!= self
; iter
= &(*iter
)->next
)
137 *iter
= (*iter
)->next
;
139 xfree (self
->m_specpdl
);
140 /* FIXME: other cleanups here. */
143 pthread_mutex_unlock (&global_lock
);
148 DEFUN ("run-in-thread", Frun_in_thread
, Srun_in_thread
, 1, 1, 0,
149 doc
: /* Start a new thread and run FUNCTION in it.
150 When the function exits, the thread dies. */)
152 Lisp_Object function
;
155 struct thread_state
*new_thread
;
157 /* Can't start a thread in temacs. */
161 new_thread
= xmalloc (sizeof (struct thread_state
));
162 memset (new_thread
, 0, sizeof (struct thread_state
));
164 new_thread
->func
= function
;
166 /* We'll need locking here. */
167 new_thread
->next
= all_threads
;
168 all_threads
= new_thread
;
170 /* FIXME check result */
171 pthread_create (&thr
, NULL
, run_thread
, new_thread
);
177 pthread_mutex_init (&global_lock
, NULL
);
178 pthread_mutex_lock (&global_lock
);
182 syms_of_threads (void)
184 defsubr (&Srun_in_thread
);