]> git.eshelyaron.com Git - emacs.git/commitdiff
When Finhibit_yield is not-nil, allow access to any buffer from the
authorGiuseppe Scrivano <gscrivano@gnu.org>
Fri, 18 Sep 2009 08:40:21 +0000 (10:40 +0200)
committerGiuseppe Scrivano <gscrivano@gnu.org>
Fri, 18 Sep 2009 08:40:21 +0000 (10:40 +0200)
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
src/buffer.h
src/thread.c
src/thread.h

index b99025409a26779a607cb55ad3b2206758056895..d29a369f5c8b0d7fed1f363b1d6f02f8eee1f4d0 100644 (file)
@@ -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 */
index 168cf1a65e8b26e42af4f6765e5e4f667397b3a8..d68aca19b214f35c1d0016d68af0333295658589 100644 (file)
@@ -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;
 };
 
 \f
index cd59ce2533c6c1e7d67ef63a82cad2b6fd6c1134..f5d5d3ce4dae1c2ec85ea08425a11769555156e4 100644 (file)
@@ -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;
index 21f04b3f210ec951b93b6acb73cc8a74c638795d..fe3e465d1cbdd34d5f0fbbf2aec22fd4ae193a5e 100644 (file)
@@ -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));