emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Patch for fields of `struct buffer'


From: Tom Tromey
Subject: Re: Patch for fields of `struct buffer'
Date: Sun, 30 Jan 2011 13:23:53 -0700
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux)

Tom>     In order to implement thread-specific let-binding of buffer-local
Tom>     variables, we must introduce an indirection into the C code, so that
Tom>     lookups of these variables see the thread-specific value, if any.

RMS> This makes thread-switching faster but makes access slower.

Yes.  I think that is the right tradeoff given my long term goal, which
is preemptive multi-threading.

Also, the cost from this patch (and its successor) only applies to
DEFVAR_PER_BUFFER and DEFVAR_KBOARD variables.  That is because these
are the only variables which are referred to by C code and which also
already require a double indirection.  Ordinary DEFVARs will be handled
by a much more efficient approach, and ordinary Lisp variables are
already reasonably expensive.  See below for a full explanation.

RMS> Moreover, it is a big change.  Why not use a mechanism like that of
RMS> buffer-local variables?  It would be much easier and perhaps
RMS> better.

Thread-local bindings in most cases will involve a variable forwarding
object akin to Lisp_Buffer_Local_Value.  There are several cases to
consider.

* DEFVAR_LISP and other true globals.
  These will be handled efficiently by using pointer tricks.  Each
  global will have a corresponding pointer to it, and each thread will
  have its own copy of all of these.  A given pointer will either point
  to the main thread's slot, or the current thread's slot, depending on
  whether the variable in question is let-bound.
  That is:

     struct emacs_globals {
        Lisp_Var f_something;
        Lisp_Var *f_something_ptr;
     };
     #define something *(current_thread->f_something_ptr)

  I think the performance overhead of this is pretty minimal,
  particularly on systems with decent TLS support.  GNU/Linux has this.

  This has some space overhead.  Each new thread will need a few K of
  memory just to start up.

* DEFVAR_PER_BUFFER and DEFVAR_KBOARD.
  Currently in the C code these are referenced directly in struct buffer.
  For the threading code, when there is a let-binding, we will put a
  Lisp_ThreadLocal object into the slot instead.  A Lisp_ThreadLocal is
  a forwarding object somewhat like Lisp_Buffer_Local_Value; it has a
  slot for the variable's global value and then an alist mapping threads
  to values.

  The overhead here could perhaps be reduced by use of an inline
  function that checks for the common case of no thread-local binding,
  something like:

  inline Lisp_Object *find_slot (Lisp_Object *field) {
    if (likely (! THREADLOCALP (*field)))
      return field;
    return find_variable_location (field);
  }

  #define B_(buf, field)  *find_slot (&((buf)->field))

* Ordinary Lisp variables, not defined by C code.
  These will always involve an indirection through find_variable_location.
  However, ordinary Lisp variable access may already involve various
  indirections due to Lisp_Buffer_Local_Value, Lisp_Buffer_Objfwd, etc.
  I think another possible indirection is probably not too bad.  We
  could use the same inline function here to minimize the cost.

RMS> I hope you are not trying to implement truly asynchronous thread
RMS> switching, because that is going to cause lots of timing errors
RMS> in C code that isn't ready for this.

Yes, I realize this.  My initial goal is to implement cooperative
threading only (with I/O considered as a yield point as well).  In fact,
I think we will probably have to be even more restrictive than this, and
disallow background threads from redisplay and the debugger (though I am
not positive, there is a lot there that I do not know about).

However, in the long run I would like to see preemptive threading.  I
would rather make decisions now that support this goal, and I believe
that planning to do any work at all at thread-switch time is bad for
this.

Tom



reply via email to

[Prev in Thread] Current Thread [Next in Thread]