all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Spencer Baugh <sbaugh@janestreet.com>
To: emacs-devel@gnu.org
Subject: Re: Releasing the thread global_lock from the module API
Date: Fri, 01 Mar 2024 12:34:36 -0500	[thread overview]
Message-ID: <ierbk7xua8j.fsf@janestreet.com> (raw)
In-Reply-To: 86cysdrja3.fsf@gnu.org

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Spencer Baugh <sbaugh@janestreet.com>
>> Cc: Philipp Stephani <phst@google.com>
>> Date: Fri, 01 Mar 2024 09:53:41 -0500
>> 
>> In other languages with an FFI and a global interpreter lock taken by
>> threads, such as Python, it's possible for a native function called from
>> the interpreter to release the global lock, and then re-acquire it
>> before calling any interpreter functions (or automatically re-acquire it
>> upon returning to the interpreter).
>> 
>> This allows for a limited form of actual parallelism: if a native
>> function is doing work that doesn't involve the Python interpreter,
>> e.g. doing numerical computations in native code, it can release the
>> lock so that it can run in parallel with other threads.  If the native
>> function needs to call a function which does involve the Python
>> interpreter, it can re-acquire the global lock around that call.
>> 
>> Could the same functionality be added to the Emacs module API?  Then
>> module code could release the global lock when doing Emacs-independent
>> computation, and re-acquire the lock when calling into Emacs.  This
>> would allow a limited form of parallelism: if a Lisp thread is calling
>> module code which releases the lock, then the module code could run in
>> parallel with the rest of Emacs on that thread.
>
> It isn't clear what exactly do you want added, since calls to
> thread-yield and similar APIs (like sleep-for and
> accept-process-output), which release and re-acquire the global lock,
> are already possible from Lisp threads.  What exactly is missing?

Those release and re-acquire the global lock, yes, but they don't allow
module code to run on the thread while the global lock is released.

>> This should be safe, because this is in effect already possibly through
>> thread-yield: that can be called from anywhere in a Lisp thread, and
>> releases the global lock, calls the operating system thread_yield
>> function, and then re-acquires the global lock.  If instead of doing
>> thread_yield, it did some computation, e.g.
>> 
>> int x = 0
>> for (int i = 0; i<999999; i++)
>>   x += i;
>> 
>> that would have the same effect as yielding, but the computation would
>> run in parallel with the main Emacs thread.  This is what would happen
>> if module code released the lock, did some Emacs-independent work, and
>> then re-acquired the lock.
>
> If a module wants to do some Emacs-independent work, it can start a
> native thread and do it there, no?  So again, what is missing?

Yes, it's true that a module can provide parallelism in that way.  The
issue is whether Emacs can run in parallel with the module.

Today, we can do:
- Lisp thread A calls module_work
- On thread A, module_work starts native threads X and Y,
  and does Emacs-independent work across all of these threads in parallel.
- On thread A, module_work finishes and returns to Lisp.

All Lisp threads will be blocked while the Lisp thread A is running the
module.

We can't do:
- Lisp thread A calls module_work
- On thread A, module_work releases the global lock.
- On thread A, module_work starts native threads X and Y,
  and does Emacs-independent work across all of these threads in parallel.
- Unrelated Lisp thread B is able to take the global lock and run Lisp code
  in parallel with module_work on thread A.
- On thread A, module_work finishes and returns to Lisp.

Releasing the global lock allows Lisp thread B to run while Lisp thread
A is running the module.

>> As an additional bonus, this would allow the module API to extend Lisp
>> threads: if a C library provides some blocking function which does some
>> complicated form of IO, a module providing bindings for that C library
>> can release global_lock before calling that function, and then
>> re-acquire the lock after the function returns.  Then Lisp threads
>> calling this module function will not block the main Emacs thread.
>
> I think this is already possible, see above.  I guess I'm missing
> something.

I don't think it is.  How would a module release global_lock, call a C
library function on the current thread, and then re-acquire the global
lock?  Can you say how you would do that with the APIs we have today?




  reply	other threads:[~2024-03-01 17:34 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-01 14:53 Releasing the thread global_lock from the module API Spencer Baugh
2024-03-01 16:47 ` Eli Zaretskii
2024-03-01 17:34   ` Spencer Baugh [this message]
2024-03-01 18:44     ` Eli Zaretskii
2024-03-01 19:02       ` Spencer Baugh
2024-03-01 19:26         ` Eli Zaretskii
2024-03-01 19:51           ` Spencer Baugh
2024-03-01 20:42             ` Eli Zaretskii
2024-03-01 21:21               ` Spencer Baugh
2024-03-01 21:34                 ` Eli Zaretskii
2024-03-01 21:56                   ` Spencer Baugh
2024-03-02  6:43                     ` Eli Zaretskii
2024-03-02 16:39                       ` sbaugh
2024-03-02 17:02                         ` Eli Zaretskii
2024-03-02 20:33                           ` Spencer Baugh
2024-03-03  6:13                             ` Eli Zaretskii
2024-03-03 13:19                               ` sbaugh
2024-03-03 15:42                                 ` Dmitry Gutov
2024-03-03 15:51                                 ` Eli Zaretskii
2024-03-01 19:30     ` tomas
2024-03-01 23:53       ` Dmitry Gutov
2024-03-02  5:57         ` tomas
2024-03-02 15:35           ` Dmitry Gutov
2024-03-02 16:31             ` tomas
2024-03-02 21:41               ` sbaugh
2024-03-03  6:25                 ` tomas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ierbk7xua8j.fsf@janestreet.com \
    --to=sbaugh@janestreet.com \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.