From 18e79e60b4633323935c7c692e5a125fa46ef9f0 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 18 Sep 2009 10:40:21 +0200 Subject: [PATCH] When Finhibit_yield is not-nil, allow access to any buffer from the current thread. It is needed to avoid deadlocks or undesidered threads switch. This mechanism is implemented storing the previous buffer's owner and restore it when the current thread releases the buffer. --- src/buffer.c | 11 +++++++++-- src/buffer.h | 3 +++ src/thread.c | 8 +++++++- src/thread.h | 2 ++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index b99025409a2..d29a369f5c8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -421,6 +421,7 @@ even if it is dead. The return value is never nil. */) BUF_MARKERS (b) = NULL; b->name = name; b->owner = Qnil; + b->prev_owner = Qnil; /* Put this in the alist of all live buffers. */ XSETBUFFER (buffer, b); @@ -1872,13 +1873,14 @@ acquire_buffer (char *end, void *nb) /* FIXME this check should be in the caller, for better single-threaded performance. */ - if (other_threads_p ()) + if (other_threads_p () && !thread_inhibit_yield_p ()) { /* Let other threads try to acquire a buffer. */ pthread_cond_broadcast (&buffer_cond); /* If our desired buffer is locked, wait for it. */ while (other_threads_p () + && !thread_inhibit_yield_p () && !EQ (new_buffer->owner, Qnil) /* We set the owner to Qt to mean it is being killed. */ && !EQ (new_buffer->owner, Qt)) @@ -1922,9 +1924,13 @@ set_buffer_internal_1 (b) old_buf = current_buffer; if (current_buffer) - current_buffer->owner = Qnil; + { + current_buffer->owner = current_buffer->prev_owner; + current_buffer->prev_owner = Qnil; + } flush_stack_call_func (acquire_buffer, b); /* FIXME: if buffer is killed */ + b->prev_owner = b->owner; b->owner = get_current_thread (); current_buffer = b; last_known_column_point = -1; /* invalidate indentation cache */ @@ -5259,6 +5265,7 @@ init_buffer_once () buffer_defaults.extra_line_spacing = Qnil; buffer_defaults.cursor_in_non_selected_windows = Qt; buffer_defaults.owner = Qnil; + buffer_defaults.prev_owner = Qnil; #ifdef DOS_NT buffer_defaults.buffer_file_type = Qnil; /* TEXT */ diff --git a/src/buffer.h b/src/buffer.h index 168cf1a65e8..d68aca19b21 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -803,6 +803,9 @@ struct buffer /* If non-nil, the thread holding a lock on this buffer. */ Lisp_Object owner; + + /* If non-nil, the previous thread holding a lock on this buffer. */ + Lisp_Object prev_owner; }; diff --git a/src/thread.c b/src/thread.c index cd59ce2533c..f5d5d3ce4da 100644 --- a/src/thread.c +++ b/src/thread.c @@ -96,10 +96,16 @@ unmark_threads (void) unmark_byte_stack (iter->m_byte_stack_list); } +int +thread_inhibit_yield_p () +{ + return inhibit_yield_counter > 0; +} + static void thread_yield_callback (char *end, void *ignore) { - if (inhibit_yield_counter) + if (thread_inhibit_yield_p ()) return; current_thread->stack_top = end; diff --git a/src/thread.h b/src/thread.h index 21f04b3f210..fe3e465d1cb 100644 --- a/src/thread.h +++ b/src/thread.h @@ -92,3 +92,5 @@ extern int other_threads_p P_ ((void)); extern int user_thread_p P_ ((void)); EXFUN (Finhibit_yield, 1); + +extern int thread_inhibit_yield_p P_ ((void)); -- 2.11.4.GIT