diff options
| author | Tom Tromey | 2012-08-15 13:16:33 -0600 |
|---|---|---|
| committer | Tom Tromey | 2012-08-15 13:16:33 -0600 |
| commit | dbb33d4e99cc9d68dea0b1c137afdb9f19121022 (patch) | |
| tree | ec56568a9e85458f4c502e21f3565afcd764075d /src | |
| parent | 8d3566c6a0eb3977c3115ae100a357f8d63cf77e (diff) | |
| download | emacs-dbb33d4e99cc9d68dea0b1c137afdb9f19121022.tar.gz emacs-dbb33d4e99cc9d68dea0b1c137afdb9f19121022.zip | |
This adds thread-blocker, a function to examine what a thread is
blocked on. I thought this would be another nice debugging addition.
Diffstat (limited to 'src')
| -rw-r--r-- | src/thread.c | 31 | ||||
| -rw-r--r-- | src/thread.h | 4 |
2 files changed, 34 insertions, 1 deletions
diff --git a/src/thread.c b/src/thread.c index 9ec418f9871..40c8be9f4d5 100644 --- a/src/thread.c +++ b/src/thread.c | |||
| @@ -66,17 +66,27 @@ mutex_lock_callback (void *arg) | |||
| 66 | lisp_mutex_lock (&mutex->mutex); | 66 | lisp_mutex_lock (&mutex->mutex); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static Lisp_Object | ||
| 70 | do_unwind_mutex_lock (Lisp_Object ignore) | ||
| 71 | { | ||
| 72 | current_thread->event_object = Qnil; | ||
| 73 | return Qnil; | ||
| 74 | } | ||
| 75 | |||
| 69 | DEFUN ("mutex-lock", Fmutex_lock, Smutex_lock, 1, 1, 0, | 76 | DEFUN ("mutex-lock", Fmutex_lock, Smutex_lock, 1, 1, 0, |
| 70 | doc: /* FIXME */) | 77 | doc: /* FIXME */) |
| 71 | (Lisp_Object obj) | 78 | (Lisp_Object obj) |
| 72 | { | 79 | { |
| 73 | struct Lisp_Mutex *mutex; | 80 | struct Lisp_Mutex *mutex; |
| 81 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 74 | 82 | ||
| 75 | CHECK_MUTEX (obj); | 83 | CHECK_MUTEX (obj); |
| 76 | mutex = XMUTEX (obj); | 84 | mutex = XMUTEX (obj); |
| 77 | 85 | ||
| 86 | current_thread->event_object = obj; | ||
| 87 | record_unwind_protect (do_unwind_mutex_lock, Qnil); | ||
| 78 | flush_stack_call_func (mutex_lock_callback, mutex); | 88 | flush_stack_call_func (mutex_lock_callback, mutex); |
| 79 | return Qnil; | 89 | return unbind_to (count, Qnil); |
| 80 | } | 90 | } |
| 81 | 91 | ||
| 82 | static void | 92 | static void |
| @@ -361,6 +371,7 @@ If NAME is given, it names the new thread. */) | |||
| 361 | new_thread->m_current_buffer = current_thread->m_current_buffer; | 371 | new_thread->m_current_buffer = current_thread->m_current_buffer; |
| 362 | new_thread->error_symbol = Qnil; | 372 | new_thread->error_symbol = Qnil; |
| 363 | new_thread->error_data = Qnil; | 373 | new_thread->error_data = Qnil; |
| 374 | new_thread->event_object = Qnil; | ||
| 364 | 375 | ||
| 365 | new_thread->m_specpdl_size = 50; | 376 | new_thread->m_specpdl_size = 50; |
| 366 | new_thread->m_specpdl = xmalloc (new_thread->m_specpdl_size | 377 | new_thread->m_specpdl = xmalloc (new_thread->m_specpdl_size |
| @@ -454,17 +465,33 @@ DEFUN ("thread-alive-p", Fthread_alive_p, Sthread_alive_p, 1, 1, 0, | |||
| 454 | return tstate->m_specpdl == NULL ? Qnil : Qt; | 465 | return tstate->m_specpdl == NULL ? Qnil : Qt; |
| 455 | } | 466 | } |
| 456 | 467 | ||
| 468 | DEFUN ("thread-blocker", Fthread_blocker, Sthread_blocker, 1, 1, 0, | ||
| 469 | doc: /* FIXME */) | ||
| 470 | (Lisp_Object thread) | ||
| 471 | { | ||
| 472 | struct thread_state *tstate; | ||
| 473 | |||
| 474 | CHECK_THREAD (thread); | ||
| 475 | tstate = XTHREAD (thread); | ||
| 476 | |||
| 477 | return tstate->event_object; | ||
| 478 | } | ||
| 479 | |||
| 457 | static void | 480 | static void |
| 458 | thread_join_callback (void *arg) | 481 | thread_join_callback (void *arg) |
| 459 | { | 482 | { |
| 460 | struct thread_state *tstate = arg; | 483 | struct thread_state *tstate = arg; |
| 461 | struct thread_state *self = current_thread; | 484 | struct thread_state *self = current_thread; |
| 485 | Lisp_Object thread; | ||
| 462 | 486 | ||
| 487 | XSETTHREAD (thread, tstate); | ||
| 488 | self->event_object = thread; | ||
| 463 | self->wait_condvar = &tstate->thread_condvar; | 489 | self->wait_condvar = &tstate->thread_condvar; |
| 464 | while (tstate->m_specpdl != NULL && EQ (self->error_symbol, Qnil)) | 490 | while (tstate->m_specpdl != NULL && EQ (self->error_symbol, Qnil)) |
| 465 | sys_cond_wait (self->wait_condvar, &global_lock); | 491 | sys_cond_wait (self->wait_condvar, &global_lock); |
| 466 | 492 | ||
| 467 | self->wait_condvar = NULL; | 493 | self->wait_condvar = NULL; |
| 494 | self->event_object = Qnil; | ||
| 468 | post_acquire_global_lock (self); | 495 | post_acquire_global_lock (self); |
| 469 | } | 496 | } |
| 470 | 497 | ||
| @@ -515,6 +542,7 @@ init_primary_thread (void) | |||
| 515 | primary_thread.function = Qnil; | 542 | primary_thread.function = Qnil; |
| 516 | primary_thread.error_symbol = Qnil; | 543 | primary_thread.error_symbol = Qnil; |
| 517 | primary_thread.error_data = Qnil; | 544 | primary_thread.error_data = Qnil; |
| 545 | primary_thread.event_object = Qnil; | ||
| 518 | 546 | ||
| 519 | sys_cond_init (&primary_thread.thread_condvar); | 547 | sys_cond_init (&primary_thread.thread_condvar); |
| 520 | } | 548 | } |
| @@ -544,6 +572,7 @@ syms_of_threads (void) | |||
| 544 | defsubr (&Sthread_signal); | 572 | defsubr (&Sthread_signal); |
| 545 | defsubr (&Sthread_alive_p); | 573 | defsubr (&Sthread_alive_p); |
| 546 | defsubr (&Sthread_join); | 574 | defsubr (&Sthread_join); |
| 575 | defsubr (&Sthread_blocker); | ||
| 547 | defsubr (&Sall_threads); | 576 | defsubr (&Sall_threads); |
| 548 | defsubr (&Smake_mutex); | 577 | defsubr (&Smake_mutex); |
| 549 | defsubr (&Smutex_lock); | 578 | defsubr (&Smutex_lock); |
diff --git a/src/thread.h b/src/thread.h index 1a193b1e4ae..d21887a0928 100644 --- a/src/thread.h +++ b/src/thread.h | |||
| @@ -44,6 +44,10 @@ struct thread_state | |||
| 44 | Lisp_Object error_symbol; | 44 | Lisp_Object error_symbol; |
| 45 | Lisp_Object error_data; | 45 | Lisp_Object error_data; |
| 46 | 46 | ||
| 47 | /* If we are waiting for some event, this holds the object we are | ||
| 48 | waiting on. */ | ||
| 49 | Lisp_Object event_object; | ||
| 50 | |||
| 47 | /* m_gcprolist must be the first non-lisp field. */ | 51 | /* m_gcprolist must be the first non-lisp field. */ |
| 48 | /* Recording what needs to be marked for gc. */ | 52 | /* Recording what needs to be marked for gc. */ |
| 49 | struct gcpro *m_gcprolist; | 53 | struct gcpro *m_gcprolist; |