diff options
| author | Paul Eggert | 2019-04-24 13:35:14 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-04-24 13:37:15 -0700 |
| commit | 4c90369d77d3db1cbd37df7857e4706176fd7ba2 (patch) | |
| tree | 424f9c8b819feef66314316974290bd7f1edc8fd /src/thread.c | |
| parent | c5358e831f05cdd110f12a4260e6fb607c66c0b4 (diff) | |
| download | emacs-4c90369d77d3db1cbd37df7857e4706176fd7ba2.tar.gz emacs-4c90369d77d3db1cbd37df7857e4706176fd7ba2.zip | |
Simplify thread initialization and GC
* src/lisp.h (PVECHEADERSIZE): New macro.
(XSETPVECTYPESIZE): Use it.
* src/search.c (syms_of_search): No need to initialize or
staticpro last_thing_searched or saved_last_thing_searched, as
the thread code arranges for initialization and GC.
* src/thread.c (main_thread): Initialize statically.
(Fmake_mutex, Fmake_condition_variable, Fmake_thread):
Use ALLOCATE_ZEROED_PSEUDOVECTOR rather than zeroing by hand.
(mark_one_thread): No need to mark Lisp_Object members.
(init_main_thread, init_threads_once): Remove. All uses removed.
Diffstat (limited to 'src/thread.c')
| -rw-r--r-- | src/thread.c | 92 |
1 files changed, 30 insertions, 62 deletions
diff --git a/src/thread.c b/src/thread.c index 670680f2b0d..e2deadd7a83 100644 --- a/src/thread.c +++ b/src/thread.c | |||
| @@ -35,7 +35,21 @@ union aligned_thread_state | |||
| 35 | }; | 35 | }; |
| 36 | verify (GCALIGNED (union aligned_thread_state)); | 36 | verify (GCALIGNED (union aligned_thread_state)); |
| 37 | 37 | ||
| 38 | static union aligned_thread_state main_thread; | 38 | static union aligned_thread_state main_thread |
| 39 | = {{ | ||
| 40 | .header.size = PVECHEADERSIZE (PVEC_THREAD, | ||
| 41 | PSEUDOVECSIZE (struct thread_state, | ||
| 42 | event_object), | ||
| 43 | VECSIZE (struct thread_state)), | ||
| 44 | .m_last_thing_searched = LISPSYM_INITIALLY (Qnil), | ||
| 45 | .m_saved_last_thing_searched = LISPSYM_INITIALLY (Qnil), | ||
| 46 | .name = LISPSYM_INITIALLY (Qnil), | ||
| 47 | .function = LISPSYM_INITIALLY (Qnil), | ||
| 48 | .result = LISPSYM_INITIALLY (Qnil), | ||
| 49 | .error_symbol = LISPSYM_INITIALLY (Qnil), | ||
| 50 | .error_data = LISPSYM_INITIALLY (Qnil), | ||
| 51 | .event_object = LISPSYM_INITIALLY (Qnil), | ||
| 52 | }}; | ||
| 39 | 53 | ||
| 40 | struct thread_state *current_thread = &main_thread.s; | 54 | struct thread_state *current_thread = &main_thread.s; |
| 41 | 55 | ||
| @@ -261,19 +275,15 @@ NAME, if given, is used as the name of the mutex. The name is | |||
| 261 | informational only. */) | 275 | informational only. */) |
| 262 | (Lisp_Object name) | 276 | (Lisp_Object name) |
| 263 | { | 277 | { |
| 264 | struct Lisp_Mutex *mutex; | ||
| 265 | Lisp_Object result; | ||
| 266 | |||
| 267 | if (!NILP (name)) | 278 | if (!NILP (name)) |
| 268 | CHECK_STRING (name); | 279 | CHECK_STRING (name); |
| 269 | 280 | ||
| 270 | mutex = ALLOCATE_PSEUDOVECTOR (struct Lisp_Mutex, name, PVEC_MUTEX); | 281 | struct Lisp_Mutex *mutex |
| 271 | memset ((char *) mutex + offsetof (struct Lisp_Mutex, mutex), | 282 | = ALLOCATE_ZEROED_PSEUDOVECTOR (struct Lisp_Mutex, name, PVEC_MUTEX); |
| 272 | 0, sizeof (struct Lisp_Mutex) - offsetof (struct Lisp_Mutex, | ||
| 273 | mutex)); | ||
| 274 | mutex->name = name; | 283 | mutex->name = name; |
| 275 | lisp_mutex_init (&mutex->mutex); | 284 | lisp_mutex_init (&mutex->mutex); |
| 276 | 285 | ||
| 286 | Lisp_Object result; | ||
| 277 | XSETMUTEX (result, mutex); | 287 | XSETMUTEX (result, mutex); |
| 278 | return result; | 288 | return result; |
| 279 | } | 289 | } |
| @@ -379,21 +389,17 @@ NAME, if given, is the name of this condition variable. The name is | |||
| 379 | informational only. */) | 389 | informational only. */) |
| 380 | (Lisp_Object mutex, Lisp_Object name) | 390 | (Lisp_Object mutex, Lisp_Object name) |
| 381 | { | 391 | { |
| 382 | struct Lisp_CondVar *condvar; | ||
| 383 | Lisp_Object result; | ||
| 384 | |||
| 385 | CHECK_MUTEX (mutex); | 392 | CHECK_MUTEX (mutex); |
| 386 | if (!NILP (name)) | 393 | if (!NILP (name)) |
| 387 | CHECK_STRING (name); | 394 | CHECK_STRING (name); |
| 388 | 395 | ||
| 389 | condvar = ALLOCATE_PSEUDOVECTOR (struct Lisp_CondVar, name, PVEC_CONDVAR); | 396 | struct Lisp_CondVar *condvar |
| 390 | memset ((char *) condvar + offsetof (struct Lisp_CondVar, cond), | 397 | = ALLOCATE_ZEROED_PSEUDOVECTOR (struct Lisp_CondVar, name, PVEC_CONDVAR); |
| 391 | 0, sizeof (struct Lisp_CondVar) - offsetof (struct Lisp_CondVar, | ||
| 392 | cond)); | ||
| 393 | condvar->mutex = mutex; | 398 | condvar->mutex = mutex; |
| 394 | condvar->name = name; | 399 | condvar->name = name; |
| 395 | sys_cond_init (&condvar->cond); | 400 | sys_cond_init (&condvar->cond); |
| 396 | 401 | ||
| 402 | Lisp_Object result; | ||
| 397 | XSETCONDVAR (result, condvar); | 403 | XSETCONDVAR (result, condvar); |
| 398 | return result; | 404 | return result; |
| 399 | } | 405 | } |
| @@ -637,10 +643,8 @@ mark_one_thread (struct thread_state *thread) | |||
| 637 | mark_object (tem); | 643 | mark_object (tem); |
| 638 | } | 644 | } |
| 639 | 645 | ||
| 640 | mark_object (thread->m_last_thing_searched); | 646 | /* No need to mark Lisp_Object members like m_last_thing_searched, |
| 641 | 647 | as mark_threads_callback does that by calling mark_object. */ | |
| 642 | if (!NILP (thread->m_saved_last_thing_searched)) | ||
| 643 | mark_object (thread->m_saved_last_thing_searched); | ||
| 644 | } | 648 | } |
| 645 | 649 | ||
| 646 | static void | 650 | static void |
| @@ -792,12 +796,6 @@ When the function exits, the thread dies. | |||
| 792 | If NAME is given, it must be a string; it names the new thread. */) | 796 | If NAME is given, it must be a string; it names the new thread. */) |
| 793 | (Lisp_Object function, Lisp_Object name) | 797 | (Lisp_Object function, Lisp_Object name) |
| 794 | { | 798 | { |
| 795 | sys_thread_t thr; | ||
| 796 | struct thread_state *new_thread; | ||
| 797 | Lisp_Object result; | ||
| 798 | const char *c_name = NULL; | ||
| 799 | size_t offset = offsetof (struct thread_state, m_stack_bottom); | ||
| 800 | |||
| 801 | /* Can't start a thread in temacs. */ | 799 | /* Can't start a thread in temacs. */ |
| 802 | if (!initialized) | 800 | if (!initialized) |
| 803 | emacs_abort (); | 801 | emacs_abort (); |
| @@ -805,20 +803,13 @@ If NAME is given, it must be a string; it names the new thread. */) | |||
| 805 | if (!NILP (name)) | 803 | if (!NILP (name)) |
| 806 | CHECK_STRING (name); | 804 | CHECK_STRING (name); |
| 807 | 805 | ||
| 808 | new_thread = ALLOCATE_PSEUDOVECTOR (struct thread_state, event_object, | 806 | struct thread_state *new_thread |
| 809 | PVEC_THREAD); | 807 | = ALLOCATE_ZEROED_PSEUDOVECTOR (struct thread_state, event_object, |
| 810 | memset ((char *) new_thread + offset, 0, | 808 | PVEC_THREAD); |
| 811 | sizeof (struct thread_state) - offset); | ||
| 812 | |||
| 813 | new_thread->function = function; | 809 | new_thread->function = function; |
| 814 | new_thread->name = name; | 810 | new_thread->name = name; |
| 815 | new_thread->m_last_thing_searched = Qnil; /* copy from parent? */ | 811 | /* Perhaps copy m_last_thing_searched from parent? */ |
| 816 | new_thread->m_saved_last_thing_searched = Qnil; | ||
| 817 | new_thread->m_current_buffer = current_thread->m_current_buffer; | 812 | new_thread->m_current_buffer = current_thread->m_current_buffer; |
| 818 | new_thread->result = Qnil; | ||
| 819 | new_thread->error_symbol = Qnil; | ||
| 820 | new_thread->error_data = Qnil; | ||
| 821 | new_thread->event_object = Qnil; | ||
| 822 | 813 | ||
| 823 | new_thread->m_specpdl_size = 50; | 814 | new_thread->m_specpdl_size = 50; |
| 824 | new_thread->m_specpdl = xmalloc ((1 + new_thread->m_specpdl_size) | 815 | new_thread->m_specpdl = xmalloc ((1 + new_thread->m_specpdl_size) |
| @@ -833,9 +824,8 @@ If NAME is given, it must be a string; it names the new thread. */) | |||
| 833 | new_thread->next_thread = all_threads; | 824 | new_thread->next_thread = all_threads; |
| 834 | all_threads = new_thread; | 825 | all_threads = new_thread; |
| 835 | 826 | ||
| 836 | if (!NILP (name)) | 827 | char const *c_name = !NILP (name) ? SSDATA (ENCODE_UTF_8 (name)) : NULL; |
| 837 | c_name = SSDATA (ENCODE_UTF_8 (name)); | 828 | sys_thread_t thr; |
| 838 | |||
| 839 | if (! sys_thread_create (&thr, c_name, run_thread, new_thread)) | 829 | if (! sys_thread_create (&thr, c_name, run_thread, new_thread)) |
| 840 | { | 830 | { |
| 841 | /* Restore the previous situation. */ | 831 | /* Restore the previous situation. */ |
| @@ -848,6 +838,7 @@ If NAME is given, it must be a string; it names the new thread. */) | |||
| 848 | } | 838 | } |
| 849 | 839 | ||
| 850 | /* FIXME: race here where new thread might not be filled in? */ | 840 | /* FIXME: race here where new thread might not be filled in? */ |
| 841 | Lisp_Object result; | ||
| 851 | XSETTHREAD (result, new_thread); | 842 | XSETTHREAD (result, new_thread); |
| 852 | return result; | 843 | return result; |
| 853 | } | 844 | } |
| @@ -1060,22 +1051,6 @@ thread_check_current_buffer (struct buffer *buffer) | |||
| 1060 | 1051 | ||
| 1061 | 1052 | ||
| 1062 | 1053 | ||
| 1063 | static void | ||
| 1064 | init_main_thread (void) | ||
| 1065 | { | ||
| 1066 | main_thread.s.header.size | ||
| 1067 | = PSEUDOVECSIZE (struct thread_state, event_object); | ||
| 1068 | XSETPVECTYPE (&main_thread.s, PVEC_THREAD); | ||
| 1069 | main_thread.s.m_last_thing_searched = Qnil; | ||
| 1070 | main_thread.s.m_saved_last_thing_searched = Qnil; | ||
| 1071 | main_thread.s.name = Qnil; | ||
| 1072 | main_thread.s.function = Qnil; | ||
| 1073 | main_thread.s.result = Qnil; | ||
| 1074 | main_thread.s.error_symbol = Qnil; | ||
| 1075 | main_thread.s.error_data = Qnil; | ||
| 1076 | main_thread.s.event_object = Qnil; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | bool | 1054 | bool |
| 1080 | main_thread_p (const void *ptr) | 1055 | main_thread_p (const void *ptr) |
| 1081 | { | 1056 | { |
| @@ -1091,15 +1066,8 @@ in_current_thread (void) | |||
| 1091 | } | 1066 | } |
| 1092 | 1067 | ||
| 1093 | void | 1068 | void |
| 1094 | init_threads_once (void) | ||
| 1095 | { | ||
| 1096 | init_main_thread (); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | void | ||
| 1100 | init_threads (void) | 1069 | init_threads (void) |
| 1101 | { | 1070 | { |
| 1102 | init_main_thread (); | ||
| 1103 | sys_cond_init (&main_thread.s.thread_condvar); | 1071 | sys_cond_init (&main_thread.s.thread_condvar); |
| 1104 | sys_mutex_init (&global_lock); | 1072 | sys_mutex_init (&global_lock); |
| 1105 | sys_mutex_lock (&global_lock); | 1073 | sys_mutex_lock (&global_lock); |