aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/alloc.c78
-rw-r--r--src/bytecode.c11
-rw-r--r--src/eval.c13
-rw-r--r--src/lisp.h18
-rw-r--r--src/thread.c79
-rw-r--r--src/thread.h5
6 files changed, 140 insertions, 64 deletions
diff --git a/src/alloc.c b/src/alloc.c
index bdf7b24af04..dfae2d1ef67 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -387,7 +387,6 @@ static struct mem_node mem_z;
387 387
388static struct Lisp_Vector *allocate_vectorlike (ptrdiff_t); 388static struct Lisp_Vector *allocate_vectorlike (ptrdiff_t);
389static void lisp_free (void *); 389static void lisp_free (void *);
390static void mark_stack (void);
391static int live_vector_p (struct mem_node *, void *); 390static int live_vector_p (struct mem_node *, void *);
392static int live_buffer_p (struct mem_node *, void *); 391static int live_buffer_p (struct mem_node *, void *);
393static int live_string_p (struct mem_node *, void *); 392static int live_string_p (struct mem_node *, void *);
@@ -4865,8 +4864,27 @@ dump_zombies (void)
4865 would be necessary, each one starting with one byte more offset 4864 would be necessary, each one starting with one byte more offset
4866 from the stack start. */ 4865 from the stack start. */
4867 4866
4868static void 4867void
4869mark_stack (void) 4868mark_stack (char *bottom, char *end)
4869{
4870 /* This assumes that the stack is a contiguous region in memory. If
4871 that's not the case, something has to be done here to iterate
4872 over the stack segments. */
4873 mark_memory (bottom, end);
4874
4875 /* Allow for marking a secondary stack, like the register stack on the
4876 ia64. */
4877#ifdef GC_MARK_SECONDARY_STACK
4878 GC_MARK_SECONDARY_STACK ();
4879#endif
4880
4881#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
4882 check_gcpros ();
4883#endif
4884}
4885
4886void
4887flush_stack_call_func (void (*func) (void *arg), void *arg)
4870{ 4888{
4871 void *end; 4889 void *end;
4872 4890
@@ -4922,20 +4940,8 @@ mark_stack (void)
4922#endif /* not GC_SAVE_REGISTERS_ON_STACK */ 4940#endif /* not GC_SAVE_REGISTERS_ON_STACK */
4923#endif /* not HAVE___BUILTIN_UNWIND_INIT */ 4941#endif /* not HAVE___BUILTIN_UNWIND_INIT */
4924 4942
4925 /* This assumes that the stack is a contiguous region in memory. If 4943 current_thread->stack_top = end;
4926 that's not the case, something has to be done here to iterate 4944 (*func) (arg);
4927 over the stack segments. */
4928 mark_memory (stack_bottom, end);
4929
4930 /* Allow for marking a secondary stack, like the register stack on the
4931 ia64. */
4932#ifdef GC_MARK_SECONDARY_STACK
4933 GC_MARK_SECONDARY_STACK ();
4934#endif
4935
4936#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
4937 check_gcpros ();
4938#endif
4939} 4945}
4940 4946
4941#endif /* GC_MARK_STACK != 0 */ 4947#endif /* GC_MARK_STACK != 0 */
@@ -5457,11 +5463,7 @@ See Info node `(elisp)Garbage Collection'. */)
5457 for (i = 0; i < staticidx; i++) 5463 for (i = 0; i < staticidx; i++)
5458 mark_object (*staticvec[i]); 5464 mark_object (*staticvec[i]);
5459 5465
5460 for (bind = specpdl; bind != specpdl_ptr; bind++) 5466 mark_threads ();
5461 {
5462 mark_object (bind->symbol);
5463 mark_object (bind->old_value);
5464 }
5465 mark_terminals (); 5467 mark_terminals ();
5466 mark_kboards (); 5468 mark_kboards ();
5467 mark_ttys (); 5469 mark_ttys ();
@@ -5473,40 +5475,12 @@ See Info node `(elisp)Garbage Collection'. */)
5473 } 5475 }
5474#endif 5476#endif
5475 5477
5476#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
5477 || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
5478 mark_stack ();
5479#else
5480 {
5481 register struct gcpro *tail;
5482 for (tail = gcprolist; tail; tail = tail->next)
5483 for (i = 0; i < tail->nvars; i++)
5484 mark_object (tail->var[i]);
5485 }
5486 mark_byte_stack ();
5487 {
5488 struct catchtag *catch;
5489 struct handler *handler;
5490
5491 for (catch = catchlist; catch; catch = catch->next)
5492 {
5493 mark_object (catch->tag);
5494 mark_object (catch->val);
5495 }
5496 for (handler = handlerlist; handler; handler = handler->next)
5497 {
5498 mark_object (handler->handler);
5499 mark_object (handler->var);
5500 }
5501 }
5502 mark_backtrace ();
5503#endif
5504
5505#ifdef HAVE_WINDOW_SYSTEM 5478#ifdef HAVE_WINDOW_SYSTEM
5506 mark_fringe_data (); 5479 mark_fringe_data ();
5507#endif 5480#endif
5508 5481
5509#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES 5482#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
5483 FIXME;
5510 mark_stack (); 5484 mark_stack ();
5511#endif 5485#endif
5512 5486
@@ -5556,7 +5530,7 @@ See Info node `(elisp)Garbage Collection'. */)
5556 5530
5557 /* Clear the mark bits that we set in certain root slots. */ 5531 /* Clear the mark bits that we set in certain root slots. */
5558 5532
5559 unmark_byte_stack (); 5533 unmark_threads ();
5560 VECTOR_UNMARK (&buffer_defaults); 5534 VECTOR_UNMARK (&buffer_defaults);
5561 VECTOR_UNMARK (&buffer_local_symbols); 5535 VECTOR_UNMARK (&buffer_local_symbols);
5562 5536
diff --git a/src/bytecode.c b/src/bytecode.c
index 019459491e9..d61e37d7886 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -335,12 +335,11 @@ struct byte_stack
335 335
336#if BYTE_MARK_STACK 336#if BYTE_MARK_STACK
337void 337void
338mark_byte_stack (void) 338mark_byte_stack (struct byte_stack *stack)
339{ 339{
340 struct byte_stack *stack;
341 Lisp_Object *obj; 340 Lisp_Object *obj;
342 341
343 for (stack = byte_stack_list; stack; stack = stack->next) 342 for (; stack; stack = stack->next)
344 { 343 {
345 /* If STACK->top is null here, this means there's an opcode in 344 /* If STACK->top is null here, this means there's an opcode in
346 Fbyte_code that wasn't expected to GC, but did. To find out 345 Fbyte_code that wasn't expected to GC, but did. To find out
@@ -364,11 +363,9 @@ mark_byte_stack (void)
364 counters. Called when GC has completed. */ 363 counters. Called when GC has completed. */
365 364
366void 365void
367unmark_byte_stack (void) 366unmark_byte_stack (struct byte_stack *stack)
368{ 367{
369 struct byte_stack *stack; 368 for (; stack; stack = stack->next)
370
371 for (stack = byte_stack_list; stack; stack = stack->next)
372 { 369 {
373 if (stack->byte_string_start != SDATA (stack->byte_string)) 370 if (stack->byte_string_start != SDATA (stack->byte_string))
374 { 371 {
diff --git a/src/eval.c b/src/eval.c
index 768cdc1a8f8..49ead499044 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -165,6 +165,19 @@ init_eval (void)
165 when_entered_debugger = -1; 165 when_entered_debugger = -1;
166} 166}
167 167
168#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
169 || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
170void
171mark_catchlist (struct catchtag *catch)
172{
173 for (; catch; catch = catch->next)
174 {
175 mark_object (catch->tag);
176 mark_object (catch->val);
177 }
178}
179#endif
180
168/* Unwind-protect function used by call_debugger. */ 181/* Unwind-protect function used by call_debugger. */
169 182
170static Lisp_Object 183static Lisp_Object
diff --git a/src/lisp.h b/src/lisp.h
index 0367d9938b7..a6665320da6 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2715,6 +2715,10 @@ extern void mark_object (Lisp_Object);
2715#if defined REL_ALLOC && !defined SYSTEM_MALLOC 2715#if defined REL_ALLOC && !defined SYSTEM_MALLOC
2716extern void refill_memory_reserve (void); 2716extern void refill_memory_reserve (void);
2717#endif 2717#endif
2718#if GC_MARK_STACK
2719extern void mark_stack (char *, char *);
2720#endif
2721extern void flush_stack_call_func (void (*func) (void *arg), void *arg);
2718extern const char *pending_malloc_warning; 2722extern const char *pending_malloc_warning;
2719extern Lisp_Object zero_vector; 2723extern Lisp_Object zero_vector;
2720extern EMACS_INT consing_since_gc; 2724extern EMACS_INT consing_since_gc;
@@ -2902,6 +2906,10 @@ extern Lisp_Object Vautoload_queue;
2902extern Lisp_Object Vsignaling_function; 2906extern Lisp_Object Vsignaling_function;
2903extern Lisp_Object inhibit_lisp_code; 2907extern Lisp_Object inhibit_lisp_code;
2904extern int handling_signal; 2908extern int handling_signal;
2909#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
2910 || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
2911extern void mark_catchlist (struct catchtag *);
2912#endif
2905/* To run a normal hook, use the appropriate function from the list below. 2913/* To run a normal hook, use the appropriate function from the list below.
2906 The calling convention: 2914 The calling convention:
2907 2915
@@ -2951,11 +2959,11 @@ extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
2951extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object); 2959extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
2952extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object); 2960extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object);
2953extern void init_eval (void); 2961extern void init_eval (void);
2954#if BYTE_MARK_STACK
2955extern void mark_backtrace (void);
2956#endif
2957extern void syms_of_eval (void); 2962extern void syms_of_eval (void);
2958 2963
2964/* Defined in thread.c. */
2965extern void mark_threads (void);
2966
2959/* Defined in editfns.c. */ 2967/* Defined in editfns.c. */
2960extern Lisp_Object Qfield; 2968extern Lisp_Object Qfield;
2961extern void insert1 (Lisp_Object); 2969extern void insert1 (Lisp_Object);
@@ -3211,9 +3219,9 @@ extern int read_bytecode_char (int);
3211extern Lisp_Object Qbytecode; 3219extern Lisp_Object Qbytecode;
3212extern void syms_of_bytecode (void); 3220extern void syms_of_bytecode (void);
3213#if BYTE_MARK_STACK 3221#if BYTE_MARK_STACK
3214extern void mark_byte_stack (void); 3222extern void mark_byte_stack (struct byte_stack *);
3215#endif 3223#endif
3216extern void unmark_byte_stack (void); 3224extern void unmark_byte_stack (struct byte_stack *);
3217extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object, 3225extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object,
3218 Lisp_Object, ptrdiff_t, Lisp_Object *); 3226 Lisp_Object, ptrdiff_t, Lisp_Object *);
3219 3227
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}
diff --git a/src/thread.h b/src/thread.h
index b2eb04d42e8..6d61d0e5fcf 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -133,8 +133,13 @@ struct thread_state
133 /* Regexp to use to replace spaces, or NULL meaning don't. */ 133 /* Regexp to use to replace spaces, or NULL meaning don't. */
134 /*re_char*/ unsigned char *m_whitespace_regexp; 134 /*re_char*/ unsigned char *m_whitespace_regexp;
135#define whitespace_regexp (current_thread->m_whitespace_regexp) 135#define whitespace_regexp (current_thread->m_whitespace_regexp)
136
137 /* Threads are kept on a linked list. */
138 struct thread_state *next_thread;
136}; 139};
137 140
138extern struct thread_state *current_thread; 141extern struct thread_state *current_thread;
139 142
143extern void unmark_threads (void);
144
140#endif /* THREAD_H */ 145#endif /* THREAD_H */