aboutsummaryrefslogtreecommitdiffstats
path: root/src/thread.c
diff options
context:
space:
mode:
authorTom Tromey2012-08-15 13:01:36 -0600
committerTom Tromey2012-08-15 13:01:36 -0600
commit2d525b793f1b0fd2b6f66881310bec8684bceffe (patch)
tree932fb8b75974ac4c16ecfc5bc216fe362b0a4d27 /src/thread.c
parent68b32482437e05f0994c4dd0ab5b0c27d39f0f6d (diff)
downloademacs-2d525b793f1b0fd2b6f66881310bec8684bceffe.tar.gz
emacs-2d525b793f1b0fd2b6f66881310bec8684bceffe.zip
This parameterizes the GC a bit to make it thread-ready.
The basic idea is that whenever a thread "exits lisp" -- that is, releases the global lock in favor of another thread -- it must save its stack boundaries in the thread object. This way the boundaries are always available for marking. This is the purpose of flush_stack_call_func. I haven't tested this under all the possible GC configurations. There is a new FIXME in a spot that i didn't convert. Arguably all_threads should go in the previous patch.
Diffstat (limited to 'src/thread.c')
-rw-r--r--src/thread.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/thread.c b/src/thread.c
index 0bd97b4fd8e..ba2d66320fa 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -24,3 +24,82 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24struct thread_state the_only_thread; 24struct thread_state the_only_thread;
25 25
26struct thread_state *current_thread = &the_only_thread; 26struct thread_state *current_thread = &the_only_thread;
27
28struct thread_state *all_threads = &the_only_thread;
29
30static void
31mark_one_thread (struct thread_state *thread)
32{
33 register struct specbinding *bind;
34 struct handler *handler;
35 Lisp_Object tem;
36
37 for (bind = thread->m_specpdl; bind != thread->m_specpdl_ptr; bind++)
38 {
39 mark_object (bind->symbol);
40 mark_object (bind->old_value);
41 }
42
43#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
44 || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
45 mark_stack (thread->m_stack_bottom, thread->stack_top);
46#else
47 {
48 register struct gcpro *tail;
49 for (tail = thread->m_gcprolist; tail; tail = tail->next)
50 for (i = 0; i < tail->nvars; i++)
51 mark_object (tail->var[i]);
52 }
53
54#if BYTE_MARK_STACK
55 if (thread->m_byte_stack_list)
56 mark_byte_stack (thread->m_byte_stack_list);
57#endif
58
59 mark_catchlist (thread->m_catchlist);
60
61 for (handler = thread->m_handlerlist; handler; handler = handler->next)
62 {
63 mark_object (handler->handler);
64 mark_object (handler->var);
65 }
66
67 mark_backtrace (thread->m_backtrace_list);
68#endif
69
70 if (thread->m_current_buffer)
71 {
72 XSETBUFFER (tem, thread->m_current_buffer);
73 mark_object (tem);
74 }
75
76 mark_object (thread->m_last_thing_searched);
77
78 if (thread->m_saved_last_thing_searched)
79 mark_object (thread->m_saved_last_thing_searched);
80}
81
82static void
83mark_threads_callback (void *ignore)
84{
85 struct thread_state *iter;
86
87 for (iter = all_threads; iter; iter = iter->next_thread)
88 mark_one_thread (iter);
89}
90
91void
92mark_threads (void)
93{
94 flush_stack_call_func (mark_threads_callback, NULL);
95}
96
97void
98unmark_threads (void)
99{
100 struct thread_state *iter;
101
102 for (iter = all_threads; iter; iter = iter->next_thread)
103 if (iter->m_byte_stack_list)
104 unmark_byte_stack (iter->m_byte_stack_list);
105}