* multi-threaded Emacs
@ 2008-11-29 13:32 Giuseppe Scrivano
2008-11-29 20:26 ` Stefan Monnier
` (2 more replies)
0 siblings, 3 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-29 13:32 UTC (permalink / raw
To: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1823 bytes --]
Hello,
I attached a small patch that enables basic threads in Emacs; it is just
a proof of concept and not usable yet, my goal was the execution of the
elisp code I included at the bottom.
In the new file thread.c these functions are defined:
(create-thread)
(with-thread id '(code))
(kill-thread id)
The first one creates a suspended thread that is waiting for requests.
These requests are done by with-thread that allows the execution of
'(code) on the specified thread. `kill-thread' is used to terminate a
thread execution by its id.
It is a prototype and the code is not very clean, still a lot of work
must be done in order to have working threads, but I think that have a
multi-threaded Emacs worths this effort.
My idea is to share global variables among threads while local bindings
are done locally to threads.
I haven't well investigated all problems that will raise using threads
in Emacs, the first one that come to my attention is the garbage
collector and at the moment I simply disable GC while there are running
threads.
The following elisp code can be used now, it is not safe as the new
thread id is not freed after it is used:
(progn
(setq i 0)
(setq j 0)
(with-thread (create-thread) '(while (< i 20)
(sleep-for 0.2)
(print "hello")
(setq i (1+ i))))
(while (< j 20)
(print "world")
(sleep-for 0.25)
(setq j (1+ j))))
`with-thread' allows to use the same thread multiple times like:
(with-thread foo '(do-something-complex))
(with-thread bar '(do-another-complex-thing))
(with-thread foo '(do-another-complex-thing))
The third call will block the calling thread until `foo' has completed
its previous execution.
What do you think about?
Regards,
Giuseppe
[-- Attachment #2: emacs_multithread.diff.gz --]
[-- Type: application/octet-stream, Size: 12001 bytes --]
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-29 13:32 multi-threaded Emacs Giuseppe Scrivano
@ 2008-11-29 20:26 ` Stefan Monnier
2008-11-29 21:01 ` Giuseppe Scrivano
2008-11-29 22:06 ` Tom Tromey
2008-11-30 16:43 ` Richard M Stallman
2008-11-30 16:44 ` Richard M Stallman
2 siblings, 2 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-11-29 20:26 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
> I attached a small patch that enables basic threads in Emacs; it is just
> a proof of concept and not usable yet, my goal was the execution of the
> elisp code I included at the bottom.
[...]
> It is a prototype and the code is not very clean, still a lot of work
> must be done in order to have working threads, but I think that have a
> multi-threaded Emacs worths this effort.
[...]
> What do you think about?
I agree that multithreading is a worthwhile goal, even tho it's going to
be a long ride. It involves several problems:
- handling thread-specific data: gcprolist, mark_byte_stack, and things
like that. You've tackled this one. I don't find your solution very
elegant, but I can't think of a much better one, unless pthreads does
provide some kind of thread-specific variables. I guess the only
improvement is to put those vars together, so we have an array of
structs (that then contain gcprolist, and mark_byte_stack fields)
rather than several arrays. And then define `gcprolist' as a macro
that expands into "thread_data[current_thread()].gcprolist", so as to
reduce the amount of source-code changes.
- dynamic-scoping: your handling of specpdl is naive and
fundamentally flawed. For multithreading, we will have to completely
change the implementation technique of dynamic-scoping.
- synchronization to access all the global variables/objects.
You haven't yet have time to tackle this (other than in `put', it
seems), and it's going to be difficult.
- concurrent GC (later to be refined to parallel concurrent GC ;-).
- redisplay in its own thread (later to be refined to one redisplay
thread per terminal, then per frame, then per window ;-).
A first step will be to restrict the implementation such that there's no
parallelism: only one thread executes at any given time (i.e. have
a single lock and have all thread grab the lock before doing any actual
work).
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-29 20:26 ` Stefan Monnier
@ 2008-11-29 21:01 ` Giuseppe Scrivano
2008-11-29 22:21 ` Stefan Monnier
2008-11-29 22:06 ` Tom Tromey
1 sibling, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-29 21:01 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
Hello,
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> - handling thread-specific data: gcprolist, mark_byte_stack, and things
> like that. You've tackled this one. I don't find your solution very
> elegant, but I can't think of a much better one, unless pthreads does
> provide some kind of thread-specific variables. I guess the only
> improvement is to put those vars together, so we have an array of
> structs (that then contain gcprolist, and mark_byte_stack fields)
> rather than several arrays. And then define `gcprolist' as a macro
> that expands into "thread_data[current_thread()].gcprolist", so as to
> reduce the amount of source-code changes.
Yes, we can put thread-specific data together in a struct; what about
buffer data? `current_buffer' must be different for every thread so as
many other global variables, should it be defined in the same
thread_data struct?
> - dynamic-scoping: your handling of specpdl is naive and
> fundamentally flawed. For multithreading, we will have to completely
> change the implementation technique of dynamic-scoping.
I know but it was the easier way to have quickly a working
proof-of-concept as I concentrated my efforts mainly on the syntax.
Do you have any idea about how dynamic scoping should be handled in a
multi-threaded environment?
> - synchronization to access all the global variables/objects.
> You haven't yet have time to tackle this (other than in `put', it
> seems), and it's going to be difficult.
Why do you think that a global lock (or several ones for separate kind
of data) will not be enough? It is not easy but I think it can be done
in a reasonable time without many troubles.
> - concurrent GC (later to be refined to parallel concurrent GC ;-).
>
> - redisplay in its own thread (later to be refined to one redisplay
> thread per terminal, then per frame, then per window ;-).
I think that this is the most difficult part, a new GC and how handle
redisplay.
Different threads can use the same buffer and a buffer can have no
threads actually using it. I would simplify this part, maybe leave the
redisplay task only to a thread.
> A first step will be to restrict the implementation such that there's no
> parallelism: only one thread executes at any given time (i.e. have
> a single lock and have all thread grab the lock before doing any actual
> work).
IMHO it is better to avoid this middle solution and try to solve
directly the problem, it will not give real benefits and having only one
thread executes at a given time can be done differently, like saving and
restoring the thread call stack. Real threads will not suffer I/O bound
operations and Emacs will be able to use more cores at the same time, if
needed.
Thanks,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-29 20:26 ` Stefan Monnier
2008-11-29 21:01 ` Giuseppe Scrivano
@ 2008-11-29 22:06 ` Tom Tromey
1 sibling, 0 replies; 89+ messages in thread
From: Tom Tromey @ 2008-11-29 22:06 UTC (permalink / raw
To: Stefan Monnier; +Cc: Giuseppe Scrivano, emacs-devel
>>>>> "Stefan" == Stefan Monnier <monnier@iro.umontreal.ca> writes:
Stefan> - handling thread-specific data: gcprolist, mark_byte_stack, and things
Stefan> like that. You've tackled this one. I don't find your solution very
Stefan> elegant, but I can't think of a much better one, unless pthreads does
Stefan> provide some kind of thread-specific variables.
pthreads provides the clunky pthread_getspecific / pthread_setspecific
API.
However, it is worth noting that recent versions of GCC support a
__thread storage class, which provides efficient support for
thread-local variables. IMO, for anything that is performance
sensitive, it is worth structuring the code so that this can be used.
See (info "(gcc)Thread-Local")
Tom
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-29 21:01 ` Giuseppe Scrivano
@ 2008-11-29 22:21 ` Stefan Monnier
2008-11-30 11:35 ` Giuseppe Scrivano
0 siblings, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-11-29 22:21 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
>> - handling thread-specific data: gcprolist, mark_byte_stack, and things
>> like that. You've tackled this one. I don't find your solution very
>> elegant, but I can't think of a much better one, unless pthreads does
>> provide some kind of thread-specific variables. I guess the only
>> improvement is to put those vars together, so we have an array of
>> structs (that then contain gcprolist, and mark_byte_stack fields)
>> rather than several arrays. And then define `gcprolist' as a macro
>> that expands into "thread_data[current_thread()].gcprolist", so as to
>> reduce the amount of source-code changes.
> Yes, we can put thread-specific data together in a struct; what about
> buffer data? `current_buffer' must be different for every thread so as
> many other global variables, should it be defined in the same
> thread_data struct?
Yes, some additional variables will need to be made
thread-specific, indeed. For some of them, we may be able to simply use
dynamic-scoping (once this is implemented).
>> - dynamic-scoping: your handling of specpdl is naive and
>> fundamentally flawed. For multithreading, we will have to completely
>> change the implementation technique of dynamic-scoping.
> I know but it was the easier way to have quickly a working
> proof-of-concept as I concentrated my efforts mainly on the syntax.
> Do you have any idea about how dynamic scoping should be handled in a
> multi-threaded environment?
Currently, we basically use the following implementation:
(defun get-var (sym)
(symbol-value 'var))
(defun set-var (sym val)
(setf (symbol-value 'var) val))
(defmacro let-var (sym val body)
`(let ((oldval (get-var ,sym)))
(set-var ,sym ,val)
(unwind-protect
,body
(set-var ,sym ,val))))
we could instead use something like
(defun get-var (sym)
(cdr (assq sym specpdl)))
(defun set-var (sym val)
(set-cdr (assq sym specpdl) val))
(defmacro let-var (sym val body)
`(let ((oldpdl specpdl))
(push (cons ,sym ,val) specpdl)
(unwind-protect
,body
(setq specpdl oldpdl))))
where specpdl is a per-thread variable. Or
(defun get-var (sym)
(cdr (assq thread (symbol-value sym))))
(defun set-var (sym val)
(set-cdr (assq thread (symbol-value sym)) val))
(defmacro let-var (sym val body)
`(let ((oldval (get-var ,sym)))
(set-var ,sym ,val)
(unwind-protect
,body
(set-var ,sym ,val))))
This latter one might be the simplest: it basically adapts the
notion of buffer-local/frame-local/terminal-local to also include
thread-local. Currently, only one form of locality is supported at
a time (a var can't be both buffer-local and terminal-local), so this
would need to be worked out (frame-local and buffer-local was allowed
in Emacs-21 but its behavior was not clearly defined and had corner
case bugs).
Clearly this can have drastic consequences w.r.t the performance of
`get-var'. And its interaction with buffer-local bindings needs to be
thought through. We mostly want to handle the default-directory case
where a variable is local to every buffer and can also be
dynamically bound.
>> - synchronization to access all the global variables/objects.
>> You haven't yet have time to tackle this (other than in `put', it
>> seems), and it's going to be difficult.
> Why do you think that a global lock (or several ones for separate kind
> of data) will not be enough? It is not easy but I think it can be done
> in a reasonable time without many troubles.
I'm not sure what you mean by "a global lock". The question is not only
how many locks, but what they protect. My proposal further down to
start with "only one thread active at a time" is what I'd call "a global
lock".
>> - concurrent GC (later to be refined to parallel concurrent GC ;-).
>> - redisplay in its own thread (later to be refined to one redisplay
>> thread per terminal, then per frame, then per window ;-).
> I think that this is the most difficult part, a new GC and how handle
> redisplay.
Actually, a new GC is not indispensable. We will most likely start by
keeping the same GC and just stopping all threads when a GC is needed.
>> A first step will be to restrict the implementation such that there's no
>> parallelism: only one thread executes at any given time (i.e. have
>> a single lock and have all thread grab the lock before doing any actual
>> work).
> IMHO it is better to avoid this middle solution and try to solve
> directly the problem, it will not give real benefits and having only one
> thread executes at a given time can be done differently, like saving and
> restoring the thread call stack.
Experience shows that making a program concurrent (or even parallel)
requires a lot of work and can only be done step by step, and after each
step appears new opportunities. I don't see my proposal as
a "middle" solution. It's just one step out of many. Before knowing
what other steps are most needed, we will need experience using those
primitives in Elisp packages, so the most pressing step is to provide
the primitives in a robust way.
> Real threads will not suffer I/O bound operations and Emacs will be
> able to use more cores at the same time, if needed.
That can come later. Parallelism is important, but it will require
changes in Elisp packages, so the first thing is to provide facilities
so that Elisp packages can start using concurrency. Then we can worry
about taking advantage of parallelism.
If we want to get parallelism without changing Elisp packages, then
I can only see two places where we could do that:
- parallelise redisplay.
- make the GC concurrent (and/or parallel).
Both are pretty difficult. Interestingly, they're also mostly
orthogonal to the issue of providing concurrency primitives to Elisp.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-29 22:21 ` Stefan Monnier
@ 2008-11-30 11:35 ` Giuseppe Scrivano
2008-11-30 21:46 ` Stefan Monnier
0 siblings, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-30 11:35 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
Hello,
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> Currently, we basically use the following implementation:
>
> (defun get-var (sym)
> (symbol-value 'var))
> (defun set-var (sym val)
> (setf (symbol-value 'var) val))
> (defmacro let-var (sym val body)
> `(let ((oldval (get-var ,sym)))
> (set-var ,sym ,val)
> (unwind-protect
> ,body
> (set-var ,sym ,val))))
>
> we could instead use something like
>
> (defun get-var (sym)
> (cdr (assq sym specpdl)))
> (defun set-var (sym val)
> (set-cdr (assq sym specpdl) val))
> (defmacro let-var (sym val body)
> `(let ((oldpdl specpdl))
> (push (cons ,sym ,val) specpdl)
> (unwind-protect
> ,body
> (setq specpdl oldpdl))))
>
> where specpdl is a per-thread variable. Or
>
> (defun get-var (sym)
> (cdr (assq thread (symbol-value sym))))
> (defun set-var (sym val)
> (set-cdr (assq thread (symbol-value sym)) val))
> (defmacro let-var (sym val body)
> `(let ((oldval (get-var ,sym)))
> (set-var ,sym ,val)
> (unwind-protect
> ,body
> (set-var ,sym ,val))))
>
> This latter one might be the simplest: it basically adapts the
> notion of buffer-local/frame-local/terminal-local to also include
> thread-local. Currently, only one form of locality is supported at
> a time (a var can't be both buffer-local and terminal-local), so this
> would need to be worked out (frame-local and buffer-local was allowed
> in Emacs-21 but its behavior was not clearly defined and had corner
> case bugs).
I don't think that thread-local data has the same meaning as
buffer-local, frame-local or terminal-local. Thread-local data should be
handled transparently to the user, I don't see it very useful (if not
dangerous) to give the possibility to store data on a specific thread
beside temporary variables.
Probably it is good idea to modify `with-thread' to don't accept a
thread id, but simply the code to execute on a different thread, the
caller thread local bindings will be copied to the called thread.
Do you see any situation that there is need to store a value on a
specific thread?
> I'm not sure what you mean by "a global lock". The question is not only
> how many locks, but what they protect. My proposal further down to
> start with "only one thread active at a time" is what I'd call "a global
> lock".
If we use a lock (or locks) to protect shared data still threads can be
executed in parallel while they working on thread local data. On the
other hand, with only one active thread we are sure that we are not
forgetting to protect something.
Thanks,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-29 13:32 multi-threaded Emacs Giuseppe Scrivano
2008-11-29 20:26 ` Stefan Monnier
@ 2008-11-30 16:43 ` Richard M Stallman
2008-11-30 17:34 ` Giuseppe Scrivano
2008-11-30 22:17 ` Miles Bader
2008-11-30 16:44 ` Richard M Stallman
2 siblings, 2 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-11-30 16:43 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
The main issue about multiple threads in Emacs is,
when should a thread-switch be possible? I think it should
be allowed only where quitting is allowed. Otherwise,
internal data can be made inconsistent.
Does pthreads provide the option to forbid thread-switching except
when the code calls a specific function? If so, we could make the
QUIT macro run that function if there is more than one thread.
(create-thread)
(with-thread id '(code))
(kill-thread id)
It seems to me that `with-thread' should be renamed to
`run-in-thread'. Meanwhile, `with-thread' should be a macro that
creates a new thread, starts running the body code in it, and will
kill it when that body code finishes.
It is un-Lispy to represent threads with numbers. They should be
represented by objects that contain info about them. If there is a
table of threads, it should not have a fixed size -- it should be
extended with realloc whenever it gets full.
What should happen when another thread gets an error? Should Emacs
run the debugger in that thread? (Probably rather annoying.) Kill
the thread? Leave the thread somehow suspended to be examined (but
how?). Kill the thread, and leave some info about the error in the
dead thread object? Perhaps there should be a way to specify a choice
for each thread.
I haven't well investigated all problems that will raise using threads
in Emacs, the first one that come to my attention is the garbage
collector and at the moment I simply disable GC while there are running
threads.
It should not be hard to find all the existing threads and mark all
their stacks and specpdls.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-29 13:32 multi-threaded Emacs Giuseppe Scrivano
2008-11-29 20:26 ` Stefan Monnier
2008-11-30 16:43 ` Richard M Stallman
@ 2008-11-30 16:44 ` Richard M Stallman
2 siblings, 0 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-11-30 16:44 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
(create-thread)
(with-thread id '(code))
(kill-thread id)
It seems to me that `with-thread' should be renamed to
`run-in-thread'. Meanwhile, `with-thread' should be a macro that
creates a new thread, starts running the body code in it, and will
kill it when that body code finishes.
It would be cleaner to represent threads by objects that contain info
about them rather than IDs. If there is a table of threads, it should
not have a fixed size -- it should be extensible, as many other tables
inside Emacs are.
Instead of indexing by a thread number each time you access certain
data structures, you should swap the current thread's pointers in and
out of the usual variables as part of switching threads. That would
mean far less changes throughout the evaluator.
What should happen when another thread gets an error? Should it run
the debugger in that thread? (Probably rather annoying.) Kill the
thread? Leave the thread somehow suspended to be examined (but how?).
Kill the thread, and leave some info on the error in the dead thread object?
I haven't well investigated all problems that will raise using threads
in Emacs, the first one that come to my attention is the garbage
collector and at the moment I simply disable GC while there are running
threads.
It should not be hard to find all the existing threads and mark all
their stacks.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 16:43 ` Richard M Stallman
@ 2008-11-30 17:34 ` Giuseppe Scrivano
2008-11-30 21:51 ` Stefan Monnier
` (2 more replies)
2008-11-30 22:17 ` Miles Bader
1 sibling, 3 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-30 17:34 UTC (permalink / raw
To: rms; +Cc: emacs-devel
Hi Richard,
Richard M Stallman <rms@gnu.org> writes:
> The main issue about multiple threads in Emacs is,
> when should a thread-switch be possible? I think it should
> be allowed only where quitting is allowed. Otherwise,
> internal data can be made inconsistent.
>
> Does pthreads provide the option to forbid thread-switching except
> when the code calls a specific function? If so, we could make the
> QUIT macro run that function if there is more than one thread.
Internal data shared among threads must be accessed only inside critical
sections in the .c code to have atomic operations on it.
The elisp programmer must not care about what other threads are doing
and using the shared data, only the thread local data is guaranteed to
be accessed only by a thread.
It may seem a limitation but it will allow us a real parallelism with
different threads executed at the same time, in this way we can take
advantage of modern multi-cores machines.
> (create-thread)
> (with-thread id '(code))
> (kill-thread id)
>
> It seems to me that `with-thread' should be renamed to
> `run-in-thread'. Meanwhile, `with-thread' should be a macro that
> creates a new thread, starts running the body code in it, and will
> kill it when that body code finishes.
>
> It is un-Lispy to represent threads with numbers. They should be
> represented by objects that contain info about them. If there is a
> table of threads, it should not have a fixed size -- it should be
> extended with realloc whenever it gets full.
Right, I used numbers to represent threads (and many other
simplifications) to have quickly something working and understand what
later can be a problem.
> What should happen when another thread gets an error? Should Emacs
> run the debugger in that thread? (Probably rather annoying.) Kill
> the thread? Leave the thread somehow suspended to be examined (but
> how?). Kill the thread, and leave some info about the error in the
> dead thread object? Perhaps there should be a way to specify a choice
> for each thread.
I would avoid something magic and kill the thread. What do you think
about running the debugger without interrupting the execution of other
threads?
If another thread will get an error then another debugger is executed in
a new buffer. Potentially every thread can cause the execution of a
debugger in a new buffer and have the possibility to be investigated
separately from others.
> It should not be hard to find all the existing threads and mark all
> their stacks and specpdls.
I like the Stefan's idea of stopping all running threads while the GC is
executed, in this way we can use the current GC without big changes.
At least until a concurrent [parallel] GC will be alive.
Regards,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 11:35 ` Giuseppe Scrivano
@ 2008-11-30 21:46 ` Stefan Monnier
2008-11-30 22:25 ` Giuseppe Scrivano
2008-12-06 22:50 ` Tom Tromey
0 siblings, 2 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-11-30 21:46 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
> I don't think that thread-local data has the same meaning as
> buffer-local, frame-local or terminal-local.
Indeed. But the implementation may use the same code (to a large
extent at least).
> Do you see any situation that there is need to store a value on a
> specific thread?
let-binding, of course. It's probably the only one that matters
(besides the internal ones like current_buffer).
>> I'm not sure what you mean by "a global lock". The question is not only
>> how many locks, but what they protect. My proposal further down to
>> start with "only one thread active at a time" is what I'd call "a global
>> lock".
> If we use a lock (or locks) to protect shared data still threads can be
> executed in parallel while they working on thread local data.
That basically means adding lock&unlock around `symbol-value' and
pretty much every primitive. I expect this will take a significant
amount of work, will lead to a significant performance hit, and will not
expose much parallelism, if any.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 17:34 ` Giuseppe Scrivano
@ 2008-11-30 21:51 ` Stefan Monnier
2008-11-30 22:10 ` Giuseppe Scrivano
2008-11-30 22:20 ` Miles Bader
2008-12-01 14:06 ` Richard M Stallman
2 siblings, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-11-30 21:51 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: rms, emacs-devel
> Internal data shared among threads must be accessed only inside critical
> sections in the .c code to have atomic operations on it.
So what happens when you execute two thread both doing
(setq a (1+ a))
if you only do the locking in C, that means that `setq' will be atomic
and reading `a' is atomic, but the whole increment is not atomic.
As mentioned earlier, synchronization primitives will need to be
provided to Elisp.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 21:51 ` Stefan Monnier
@ 2008-11-30 22:10 ` Giuseppe Scrivano
0 siblings, 0 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-30 22:10 UTC (permalink / raw
To: Stefan Monnier; +Cc: rms, emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> Internal data shared among threads must be accessed only inside critical
>> sections in the .c code to have atomic operations on it.
>
> So what happens when you execute two thread both doing
>
> (setq a (1+ a))
>
> if you only do the locking in C, that means that `setq' will be atomic
> and reading `a' is atomic, but the whole increment is not atomic.
>
> As mentioned earlier, synchronization primitives will need to be
> provided to Elisp.
Yes, the locking in C is needed to make atomic Elisp primitives, it is
only the first step.
For atomic expressions there is need to add these functions in Elisp
too that delegate the job to the C functions.
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 16:43 ` Richard M Stallman
2008-11-30 17:34 ` Giuseppe Scrivano
@ 2008-11-30 22:17 ` Miles Bader
1 sibling, 0 replies; 89+ messages in thread
From: Miles Bader @ 2008-11-30 22:17 UTC (permalink / raw
To: rms; +Cc: Giuseppe Scrivano, emacs-devel
Richard M Stallman <rms@gnu.org> writes:
>
> (create-thread)
> (with-thread id '(code))
> (kill-thread id)
>
> It seems to me that `with-thread' should be renamed to
> `run-in-thread'. Meanwhile, `with-thread' should be a macro that
> creates a new thread, starts running the body code in it, and will
> kill it when that body code finishes.
Also, create-thread should be "make-thread".
-Miles
--
((lambda (x) (list x x)) (lambda (x) (list x x)))
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 17:34 ` Giuseppe Scrivano
2008-11-30 21:51 ` Stefan Monnier
@ 2008-11-30 22:20 ` Miles Bader
2008-11-30 23:09 ` Stefan Monnier
2008-11-30 23:09 ` Giuseppe Scrivano
2008-12-01 14:06 ` Richard M Stallman
2 siblings, 2 replies; 89+ messages in thread
From: Miles Bader @ 2008-11-30 22:20 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: rms, emacs-devel
BTW, there was a huge thread maybe a year (?) or so ago about this subject.
Have you read it?
IIRC, the basic consensus was that some sort of explicitly
non-preemptive threading was probably the best solution for emacs.
-Miles
--
I'm beginning to think that life is just one long Yoko Ono album; no rhyme
or reason, just a lot of incoherent shrieks and then it's over. --Ian Wolff
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 21:46 ` Stefan Monnier
@ 2008-11-30 22:25 ` Giuseppe Scrivano
2008-11-30 23:03 ` Stefan Monnier
2008-12-06 22:50 ` Tom Tromey
1 sibling, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-30 22:25 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> let-binding, of course. It's probably the only one that matters
> (besides the internal ones like current_buffer).
Isn't enough to have a separate `specpdl' for every thread?
> That basically means adding lock&unlock around `symbol-value' and
> pretty much every primitive. I expect this will take a significant
> amount of work, will lead to a significant performance hit, and will not
> expose much parallelism, if any.
We can increase parallelism by adding different critical sections (but
it will be more difficult to handle from Elisp).
In any case I don't expect the code flow to stay long time in a critical
section; mostly they are read/write to global variables that are done
quickly.
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 22:25 ` Giuseppe Scrivano
@ 2008-11-30 23:03 ` Stefan Monnier
2008-11-30 23:30 ` Giuseppe Scrivano
0 siblings, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-11-30 23:03 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
>> let-binding, of course. It's probably the only one that matters
>> (besides the internal ones like current_buffer).
> Isn't enough to have a separate `specpdl' for every thread?
Not sure what you mean. My above text is talking about the provided
behavior, not about the implementation that provides it.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 22:20 ` Miles Bader
@ 2008-11-30 23:09 ` Stefan Monnier
2008-11-30 23:09 ` Giuseppe Scrivano
1 sibling, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-11-30 23:09 UTC (permalink / raw
To: Miles Bader; +Cc: emacs-devel, Giuseppe Scrivano, rms
> IIRC, the basic consensus was that some sort of explicitly
> non-preemptive threading was probably the best solution for emacs.
At least as a first step, yes.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 22:20 ` Miles Bader
2008-11-30 23:09 ` Stefan Monnier
@ 2008-11-30 23:09 ` Giuseppe Scrivano
2008-12-01 0:10 ` Chetan Pandya
2008-12-01 3:55 ` Stefan Monnier
1 sibling, 2 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-30 23:09 UTC (permalink / raw
To: Miles Bader; +Cc: rms, emacs-devel
Miles Bader <miles@gnu.org> writes:
> BTW, there was a huge thread maybe a year (?) or so ago about this subject.
> Have you read it?
>
> IIRC, the basic consensus was that some sort of explicitly
> non-preemptive threading was probably the best solution for emacs.
>
> -Miles
I found a thread of 3 years ago (maybe is it this one? Time passes very
fast :) ) but I didn't find any conclusion.
Anyway, a non-preemptive threading will not give any real parallelism
and it will require more changes in the Elisp packages to use threads as
they will need to say explicitly when give the control to another
thread.
Instead `run-in-thread' will setup the call stack and finally give the
control to the thread. The only change required in the Elisp packages
to be used in a multithreaded environment is to protect global data
accesses with a lock/unlock, but how many times does it happen to change
the value of a global variable?
Both solutions require changes in Elisp, a non-preemptive threading
needs to explicitly yield the control to another thread, while having
real threads needs to specify when access to global data must be
protected. The latter one differently allows parallelism and I guess
less changes in the Elisp code too (if writes to global data are less
frequent than specify when exit from the current thread).
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 23:03 ` Stefan Monnier
@ 2008-11-30 23:30 ` Giuseppe Scrivano
2008-12-01 3:37 ` Stefan Monnier
0 siblings, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-11-30 23:30 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>>> let-binding, of course. It's probably the only one that matters
>>> (besides the internal ones like current_buffer).
>> Isn't enough to have a separate `specpdl' for every thread?
>
> Not sure what you mean. My above text is talking about the provided
> behavior, not about the implementation that provides it.
>
>
> Stefan
Sorry, I wasn't clear. If we will store thread local data only on
`specpdl', and I think it is the proper way, thread local data will not
be persistent among calls to `run-in-thread'.
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 23:09 ` Giuseppe Scrivano
@ 2008-12-01 0:10 ` Chetan Pandya
2008-12-01 3:55 ` Stefan Monnier
1 sibling, 0 replies; 89+ messages in thread
From: Chetan Pandya @ 2008-12-01 0:10 UTC (permalink / raw
To: Miles Bader, Giuseppe Scrivano; +Cc: rms, emacs-devel
--- On Sun, 11/30/08, Giuseppe Scrivano <gscrivano@gnu.org> wrote:
> From: Giuseppe Scrivano <gscrivano@gnu.org>
> Subject: Re: multi-threaded Emacs
> To: "Miles Bader" <miles@gnu.org>
> Cc: rms@gnu.org, emacs-devel@gnu.org
> Date: Sunday, November 30, 2008, 11:09 PM
> Miles Bader <miles@gnu.org> writes:
>
> > BTW, there was a huge thread maybe a year (?) or so
> ago about this subject.
> > Have you read it?
> >
> > IIRC, the basic consensus was that some sort of
> explicitly
> > non-preemptive threading was probably the best
> solution for emacs.
> >
> > -Miles
>
> I found a thread of 3 years ago (maybe is it this one?
> Time passes very
> fast :) ) but I didn't find any conclusion.
>
> Anyway, a non-preemptive threading will not give any real
> parallelism
> and it will require more changes in the Elisp packages to
> use threads as
> they will need to say explicitly when give the control to
> another
> thread.
> Instead `run-in-thread' will setup the call stack and
> finally give the
> control to the thread. The only change required in the
> Elisp packages
> to be used in a multithreaded environment is to protect
> global data
> accesses with a lock/unlock, but how many times does it
> happen to change
> the value of a global variable?
>
> Both solutions require changes in Elisp, a non-preemptive
> threading
> needs to explicitly yield the control to another thread,
> while having
> real threads needs to specify when access to global data
> must be
> protected. The latter one differently allows parallelism
> and I guess
> less changes in the Elisp code too (if writes to global
> data are less
> frequent than specify when exit from the current thread).
>
> Giuseppe
A non-preemptive threading model can also yield implicitly, but can have unexpected consequences - for example a global variable changing value between two uses within a function, or if two values that are modified together. In general, such transaction semantics have to be coded explicitly in a preemptive threading model, where as with a cooperative model, one has to be aware of only a few of such points.
Perhaps these things were discussed earlier. I will take a look.
Chetan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 23:30 ` Giuseppe Scrivano
@ 2008-12-01 3:37 ` Stefan Monnier
0 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-01 3:37 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
>>>> let-binding, of course. It's probably the only one that matters
>>>> (besides the internal ones like current_buffer).
>>> Isn't enough to have a separate `specpdl' for every thread?
>> Not sure what you mean. My above text is talking about the provided
>> behavior, not about the implementation that provides it.
> Sorry, I wasn't clear. If we will store thread local data only on
> `specpdl', and I think it is the proper way, thread local data will not
> be persistent among calls to `run-in-thread'.
You mean you want to use the code #2 rather than code #3 to implement
dynamic scoping? That might be OK, but I think it's going to take more
work than #3 and will require more care w.r.t performance impact since
it tends to make `symbol-value' algorithmically slower.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 23:09 ` Giuseppe Scrivano
2008-12-01 0:10 ` Chetan Pandya
@ 2008-12-01 3:55 ` Stefan Monnier
1 sibling, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-01 3:55 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel, rms, Miles Bader
> Anyway, a non-preemptive threading will not give any real parallelism
I admire your enthusiasm, but I think that if you don't want to get
burned, you should set yourself more realistic goals. Parallelism is
going to require a very large amount of work. We'll hopefully get there
at some point, but there are many useful steps to have to take before we
get there.
> and it will require more changes in the Elisp packages to use threads as
> they will need to say explicitly when give the control to another
> thread.
Actually no. There are already `yield' points in Elisp: basically
whenever we wait for a process or wait for user input. So there's no
need to change too many things before we can start using cooperative
threading (another name for "a single thread active at a time").
It's still useful because it introduces the multiple stacks, which will
allow for example using one thread per terminal, so that doing M-x in
one terminal will not screw over the other terminals. Also it'll make
asynchronous execution easier. So it'll be useful to Elisp packages.
It'll also be a useful implementation step on the way to parallelism,
since it will make us deal with multiple stacks, dynamic scoping, ...
We will already be able to try to tackle things like: be able to edit
a file in a window while Gnus is waiting for your newsserver to send the
list of new groups.
Then we can think of making concurrency more fine-grained to try and get
parallelism.
> accesses with a lock/unlock, but how many times does it happen to change
> the value of a global variable?
*All* the time. Elisp is really terrible in this respect. Remember:
all buffers are part of the "global state", same for pretty much all
objects. Currently even "local variables" are actually global,
tho admittedly, fixing dynamic-scoping will/should improve this part.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 17:34 ` Giuseppe Scrivano
2008-11-30 21:51 ` Stefan Monnier
2008-11-30 22:20 ` Miles Bader
@ 2008-12-01 14:06 ` Richard M Stallman
2008-12-01 18:57 ` Giuseppe Scrivano
2 siblings, 1 reply; 89+ messages in thread
From: Richard M Stallman @ 2008-12-01 14:06 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
Internal data shared among threads must be accessed only inside critical
sections in the .c code to have atomic operations on it.
I don't think we want to make such pervasive and inconvenient changes
in the C code. What we want, I think, is to allow thread switches
only inside the QUIT macro.
Being able to program in terms of multiple threads will be useful for
situations such as multiple terminals. However, I don't see much need
in Emacs for real parallelism.
> It should not be hard to find all the existing threads and mark all
> their stacks and specpdls.
I like the Stefan's idea of stopping all running threads while the GC is
executed, in this way we can use the current GC without big changes.
At least until a concurrent [parallel] GC will be alive.
Making GCC handle the existence of multiple threads should be easy
with the approach I suggested above, once thread switching is
controlled.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-01 14:06 ` Richard M Stallman
@ 2008-12-01 18:57 ` Giuseppe Scrivano
2008-12-01 20:34 ` Stefan Monnier
2008-12-02 16:02 ` Richard M Stallman
0 siblings, 2 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-01 18:57 UTC (permalink / raw
To: rms; +Cc: emacs-devel
Richard M Stallman <rms@gnu.org> writes:
> I don't think we want to make such pervasive and inconvenient changes
> in the C code. What we want, I think, is to allow thread switches
> only inside the QUIT macro.
If we don't want to do immediately all changes at one time and proceed
slowly to a real parallelism then we can start with a concurrent threads
model. I think that concurrent threads can't be considered the final
solution, what I would like to optimize using threads is I/O bound and a
concurrent model can do it only in part. If an Elisp primitive is
waiting for some data from a file or a socket, Emacs will hang until it
is ready. This problem can't be solved by concurrent threads that will
switch only inside the QUIT macro.
If we will implement a concurrent threads model and introduce the QUIT
macro after it can't be used by parallel threads as accesses to shared
data must be synchronized differently.
IMHO, concurrent threads itself are not very useful, they can be useful
if considered a first step in the direction of a real parallelism.
I know it is a lot of work and the question (as in everything) is: does
benefits we will have worth this effort?
Regards,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-01 18:57 ` Giuseppe Scrivano
@ 2008-12-01 20:34 ` Stefan Monnier
2008-12-01 22:41 ` joakim
2008-12-02 16:02 ` Richard M Stallman
1 sibling, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-01 20:34 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: rms, emacs-devel
> solution, what I would like to optimize using threads is I/O bound and a
> concurrent model can do it only in part. If an Elisp primitive is
> waiting for some data from a file or a socket, Emacs will hang until it
> is ready. This problem can't be solved by concurrent threads that will
Actually, no: while Emacs is waiting for socket data, it can already run
other async code, such as process filters.
So we can solve most I/O bound problems just by using a very coarse
notion of concurrency. We already partly do it, except we're currently
limited to a single stack, which makes coding painful and prevents some
useful cases.
Providing a cooperative threading model will remove this problem. But,
no it's not a "final solution": I hope there never will be a final
solution, because Emacs will always need to evolve.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-01 20:34 ` Stefan Monnier
@ 2008-12-01 22:41 ` joakim
0 siblings, 0 replies; 89+ messages in thread
From: joakim @ 2008-12-01 22:41 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel, Giuseppe Scrivano, rms
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>> solution, what I would like to optimize using threads is I/O bound and a
>> concurrent model can do it only in part. If an Elisp primitive is
>> waiting for some data from a file or a socket, Emacs will hang until it
>> is ready. This problem can't be solved by concurrent threads that will
>
> Actually, no: while Emacs is waiting for socket data, it can already run
> other async code, such as process filters.
>
> So we can solve most I/O bound problems just by using a very coarse
> notion of concurrency. We already partly do it, except we're currently
> limited to a single stack, which makes coding painful and prevents some
> useful cases.
>
> Providing a cooperative threading model will remove this problem. But,
> no it's not a "final solution": I hope there never will be a final
> solution, because Emacs will always need to evolve.
Beautifully put.
>
> Stefan
>
--
Joakim Verona
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-01 18:57 ` Giuseppe Scrivano
2008-12-01 20:34 ` Stefan Monnier
@ 2008-12-02 16:02 ` Richard M Stallman
2008-12-02 22:22 ` Stefan Monnier
1 sibling, 1 reply; 89+ messages in thread
From: Richard M Stallman @ 2008-12-02 16:02 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel
If an Elisp primitive is
waiting for some data from a file or a socket, Emacs will hang until it
is ready.
This is a real issue, but the solution is so easy
that it is not a real problem.
Activies that can wait a long time
use wait_reading_process_output
which already implements some parallelism.
Naturally we would arrange to enable thread-switching there.
IMHO, concurrent threads itself are not very useful, they can be useful
if considered a first step in the direction of a real parallelism.
If "concurrent threads" means "threads that can only switch where the
program lets them", they are very useful in Emacs for the sake of multiple
terminals.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-02 16:02 ` Richard M Stallman
@ 2008-12-02 22:22 ` Stefan Monnier
2008-12-02 22:41 ` Giuseppe Scrivano
2008-12-02 23:10 ` Florian Beck
0 siblings, 2 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-02 22:22 UTC (permalink / raw
To: rms; +Cc: Giuseppe Scrivano, emacs-devel
> If "concurrent threads" means "threads that can only switch where the
> program lets them", they are very useful in Emacs for the sake of multiple
> terminals.
I rarely use multiple terminals, and when I use them, the current
restrictions are mostly bearable. OTOH I very often would like to keep
using my Emacs while it's byte-compiling some files, or while Gnus is
fetching some newsgroup.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-02 22:22 ` Stefan Monnier
@ 2008-12-02 22:41 ` Giuseppe Scrivano
2008-12-03 2:17 ` Stefan Monnier
2008-12-02 23:10 ` Florian Beck
1 sibling, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-02 22:41 UTC (permalink / raw
To: Stefan Monnier; +Cc: rms, emacs-devel
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
> I rarely use multiple terminals, and when I use them, the current
> restrictions are mostly bearable. OTOH I very often would like to keep
> using my Emacs while it's byte-compiling some files, or while Gnus is
> fetching some newsgroup.
This is exactly the problem I had when I first thought of threads.
Do you think we can solve it (at least partially) using a concurrent
model?
Thanks,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-02 22:22 ` Stefan Monnier
2008-12-02 22:41 ` Giuseppe Scrivano
@ 2008-12-02 23:10 ` Florian Beck
1 sibling, 0 replies; 89+ messages in thread
From: Florian Beck @ 2008-12-02 23:10 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel, rms, Giuseppe Scrivano
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>> If "concurrent threads" means "threads that can only switch where the
>> program lets them", they are very useful in Emacs for the sake of multiple
>> terminals.
>
> I rarely use multiple terminals, and when I use them, the current
> restrictions are mostly bearable. OTOH I very often would like to keep
> using my Emacs while it's byte-compiling some files, or while Gnus is
> fetching some newsgroup.
As a user, I would love to see asynchronous processes.
However, I would also like to see redisplay+font-locking making use of
the four to eight processor cores that will become standard during emacs24's
lifetime. Font-locking is a powerful and quite user-accessible feature
which is currently limited by processor speed.
--
Florian Beck
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-02 22:41 ` Giuseppe Scrivano
@ 2008-12-03 2:17 ` Stefan Monnier
2008-12-03 18:26 ` Giuseppe Scrivano
0 siblings, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-03 2:17 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: rms, emacs-devel
>> I rarely use multiple terminals, and when I use them, the current
>> restrictions are mostly bearable. OTOH I very often would like to keep
>> using my Emacs while it's byte-compiling some files, or while Gnus is
>> fetching some newsgroup.
> This is exactly the problem I had when I first thought of threads.
> Do you think we can solve it (at least partially) using a concurrent
> model?
Of course. Even just with cooperative threads.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-03 2:17 ` Stefan Monnier
@ 2008-12-03 18:26 ` Giuseppe Scrivano
2008-12-03 20:14 ` Stefan Monnier
2008-12-05 2:59 ` Richard M Stallman
0 siblings, 2 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-03 18:26 UTC (permalink / raw
To: Stefan Monnier; +Cc: rms, emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>>> I rarely use multiple terminals, and when I use them, the current
>>> restrictions are mostly bearable. OTOH I very often would like to keep
>>> using my Emacs while it's byte-compiling some files, or while Gnus is
>>> fetching some newsgroup.
>
>> This is exactly the problem I had when I first thought of threads.
>
>> Do you think we can solve it (at least partially) using a concurrent
>> model?
>
> Of course. Even just with cooperative threads.
Yes, I was referring to the cooperating threads model using a QUIT
macro. How can it be used by gnus while fetching new data? Will it
give the control to another thread immediately after the trasfer begins?
I am concentrating on this example because usually when I fetch my
emails, I wish to have threads in Emacs.
Thanks,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-03 18:26 ` Giuseppe Scrivano
@ 2008-12-03 20:14 ` Stefan Monnier
2008-12-05 2:59 ` Richard M Stallman
2008-12-05 2:59 ` Richard M Stallman
1 sibling, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-03 20:14 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: rms, emacs-devel
> Yes, I was referring to the cooperating threads model using a QUIT
> macro.
Actually, yielding in QUIT will take a lot of work. It's definitely not
"cooperative" seen from Elisp's point of view (where QUIT can be run
implicitly all over the place).
By cooperative thread model, I mean that we can switch context either
when we already do (i.e. when waiting for user/process/network input),
or when running some new `yield' Elisp function.
> How can it be used by gnus while fetching new data? Will it
> give the control to another thread immediately after the trasfer begins?
As written above (and earlier as well), Emacs will switch threads when
waiting for network input.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-03 7:59 Re[2]: " ak70
@ 2008-12-04 8:45 ` Richard M Stallman
[not found] ` <87prk8mhg9.fsf@vanilla.net.mt>
2008-12-04 13:21 ` Stefan Monnier
1 sibling, 1 reply; 89+ messages in thread
From: Richard M Stallman @ 2008-12-04 8:45 UTC (permalink / raw
To: ak70; +Cc: gscrivano, emacs-devel
It could be a useful package to develop further, for general purposes.
I cannot tell whether it might be useful in Emacs because your message
does not address the crucial questions.
It uses the two level scheduling model, i.e. we have m user level
threads running on top of n kernel threads.
Is the distinction between user-level threads and kernel threads
a matter of optimization, or is it a user-level feature?
Under what circumstances does it switch threads?
For the user, how does this differ from pthreads?
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-03 7:59 Re[2]: " ak70
2008-12-04 8:45 ` Richard M Stallman
@ 2008-12-04 13:21 ` Stefan Monnier
1 sibling, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-04 13:21 UTC (permalink / raw
To: ak70; +Cc: emacs-devel@gnu.org, Giuseppe Scrivano, rms@gnu.org
> Hi, guys. I have a generic user-level thread library on Linux.
> Maybe it can help.
Thanks. But note that the problem with Emacs and cuncurrency doesn't
have much to do with the presence or absence of threads libraries.
There are already plenty of libraries implementing threads. The problem
to change Emacs's Lisp and C code so as to be able to take advantage
of them.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-03 20:14 ` Stefan Monnier
@ 2008-12-05 2:59 ` Richard M Stallman
2008-12-05 7:40 ` Giuseppe Scrivano
2008-12-05 15:36 ` Stefan Monnier
0 siblings, 2 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-12-05 2:59 UTC (permalink / raw
To: Stefan Monnier; +Cc: gscrivano, emacs-devel
Actually, yielding in QUIT will take a lot of work. It's definitely not
"cooperative" seen from Elisp's point of view (where QUIT can be run
implicitly all over the place).
I am surprised. Perhaps you're right, but why do you think so?
Anywhere that calls QUIT is a place where it is safe for an error to happen,
so why not a thread switch?
A slightly more conservative approach would be to thread-switch from
QUIT on certain circumstances, such as, if the innermost
unwind-protect has calls to Lisp code inside it. We could arrange
for the specpdl to have the requisite info.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-03 18:26 ` Giuseppe Scrivano
2008-12-03 20:14 ` Stefan Monnier
@ 2008-12-05 2:59 ` Richard M Stallman
2008-12-05 15:40 ` Stefan Monnier
1 sibling, 1 reply; 89+ messages in thread
From: Richard M Stallman @ 2008-12-05 2:59 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: monnier, emacs-devel
Yes, I was referring to the cooperating threads model using a QUIT
macro. How can it be used by gnus while fetching new data?
Does the code that gnus runs to fetch new data involve ever doing the
QUIT macro? If it has a loop, then yes. If it reads from a net
connection, then it calls wait_reading_process_output. So it should be able
to operate in parallel with other things, even with cooperating threads.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 2:59 ` Richard M Stallman
@ 2008-12-05 7:40 ` Giuseppe Scrivano
2008-12-05 8:20 ` Miles Bader
2008-12-06 8:30 ` Richard M Stallman
2008-12-05 15:36 ` Stefan Monnier
1 sibling, 2 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-05 7:40 UTC (permalink / raw
To: rms; +Cc: Stefan Monnier, emacs-devel
Richard M Stallman <rms@gnu.org> writes:
> Actually, yielding in QUIT will take a lot of work. It's definitely not
> "cooperative" seen from Elisp's point of view (where QUIT can be run
> implicitly all over the place).
>
> I am surprised. Perhaps you're right, but why do you think so?
> Anywhere that calls QUIT is a place where it is safe for an error to happen,
> so why not a thread switch?
The cooperative threads approach moves to Elisp packages more work as
they will have explicitly to yield control but it simplifies a lot the C
code.
I already started to change my code to allow only the execution of a
thread at a time and add a `yield' primitive.
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 7:40 ` Giuseppe Scrivano
@ 2008-12-05 8:20 ` Miles Bader
2008-12-05 9:42 ` Paul R
2008-12-05 11:02 ` Helmut Eller
2008-12-06 8:30 ` Richard M Stallman
1 sibling, 2 replies; 89+ messages in thread
From: Miles Bader @ 2008-12-05 8:20 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel, rms, Stefan Monnier
Giuseppe Scrivano <gscrivano@gnu.org> writes:
>> I am surprised. Perhaps you're right, but why do you think so?
>> Anywhere that calls QUIT is a place where it is safe for an error to happen,
>> so why not a thread switch?
>
> The cooperative threads approach moves to Elisp packages more work as
> they will have explicitly to yield control but it simplifies a lot the
> C code. I already started to change my code to allow only the
> execution of a thread at a time and add a `yield' primitive.
No, it will will likely have almost no effect on lisp code, because
99.9% of the code won't be affected, and the lack of pre-emption allows
that code to continue making traditional assumptions.
The only changes required will be in places that are known to be
long-running, where sticking in a few strategic calls to (yield) will
probably relieve most of the problem.
This is because emacs, being an interactive system, generally doesn't
have a lot of long-running code. It's the relatively few exceptions to
this rule (e.g. gnus reading in new messages) that are the main issues
in practice. Fixing those places will probably yield a lot of benefit
for (relatively) small amount of work.
-Miles
--
Brain, n. An apparatus with which we think we think.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 8:20 ` Miles Bader
@ 2008-12-05 9:42 ` Paul R
2008-12-05 10:10 ` Eli Zaretskii
2008-12-05 11:02 ` Helmut Eller
1 sibling, 1 reply; 89+ messages in thread
From: Paul R @ 2008-12-05 9:42 UTC (permalink / raw
To: emacs-devel
Miles> This is because emacs, being an interactive system, generally
Miles> doesn't have a lot of long-running code. It's the relatively few
Miles> exceptions to this rule (e.g. gnus reading in new messages) that
Miles> are the main issues in practice. Fixing those places will
Miles> probably yield a lot of benefit for (relatively) small amount of
Miles> work.
I hope this would allow a better on-the-fly processing of text as well.
I'm thinking of spell checking, code validation (this is called flymake
in emacs IIRC), or even a smoother syntax highlighting.
--
Paul
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 9:42 ` Paul R
@ 2008-12-05 10:10 ` Eli Zaretskii
2008-12-05 10:35 ` Paul R
0 siblings, 1 reply; 89+ messages in thread
From: Eli Zaretskii @ 2008-12-05 10:10 UTC (permalink / raw
To: Paul R; +Cc: emacs-devel
> From: Paul R <paul.r.ml@gmail.com>
> Date: Fri, 05 Dec 2008 10:42:04 +0100
>
> I hope this would allow a better on-the-fly processing of text as well.
> I'm thinking of spell checking, code validation (this is called flymake
> in emacs IIRC), or even a smoother syntax highlighting.
Any Emacs feature which, like spell-checking, uses a subprocess to do
its job, already uses a kind of non-preemptive multi-threading built
into wait_reading_process_output and its subroutines. This is because
Emacs checks all the possible sources of input, including sub-process
output, when it is idle.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 10:10 ` Eli Zaretskii
@ 2008-12-05 10:35 ` Paul R
0 siblings, 0 replies; 89+ messages in thread
From: Paul R @ 2008-12-05 10:35 UTC (permalink / raw
To: Emacs Devel
Eli> Any Emacs feature which, like spell-checking, uses a subprocess to
Eli> do its job, already uses a kind of non-preemptive multi-threading
Eli> built into wait_reading_process_output and its subroutines. This is
Eli> because Emacs checks all the possible sources of input, including
Eli> sub-process output, when it is idle.
Indeed, I tried flyspell again and I felt it a lot more responsive than
I was expecting. With threads this could be extended to features not
relying on external processes.
Also, fontlocking is immediate except for multiline matches, which only
happens when idle for some time. I can feel it, but maybe the major
modes I'm using don't make proper use of fontlocking feature.
--
Paul
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 8:20 ` Miles Bader
2008-12-05 9:42 ` Paul R
@ 2008-12-05 11:02 ` Helmut Eller
2008-12-05 15:39 ` Stefan Monnier
` (2 more replies)
1 sibling, 3 replies; 89+ messages in thread
From: Helmut Eller @ 2008-12-05 11:02 UTC (permalink / raw
To: emacs-devel
* Miles Bader [2008-12-05 09:20+0100] writes:
> This is because emacs, being an interactive system, generally doesn't
> have a lot of long-running code. It's the relatively few exceptions to
> this rule (e.g. gnus reading in new messages) that are the main issues
> in practice. Fixing those places will probably yield a lot of benefit
> for (relatively) small amount of work.
I'm wondering what the exact problem with Gnus is.
Certainly, downloading the next article takes a bit of time but threads
wont make the download any faster. Is there something the user wants to
do while waiting for the next article?
There's also something called "gnus-async" which supposedly downloads
articles in the background. It's clearly possible to do I/O in the
background with ordinary process-filters; we need no threads for that.
It's probably a bit harder to parse messages in process-filters as with
threads, but threads are also tricky (preemptive or not).
Opening a connection can also take some time, but again, it can be done
asynchronously with the :nowait argument to make-network-process. I
don't know if Gnus uses this possibility. It would be interesting to
know what is easier: adding threads or rewriting Gnus with
process-filters.
Threads could probably be used to "stop" the current command and
continue it in the background. Something like job control in a shell.
That would be a nice feature, but I don't know if it is worth all the
complexity that threads introduce.
Helmut.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
[not found] ` <E1L8ZUB-0002x3-VT@fencepost.gnu.org>
@ 2008-12-05 13:27 ` Li Lin
[not found] ` <87prk64ilv.fsf@vanilla.net.mt>
0 siblings, 1 reply; 89+ messages in thread
From: Li Lin @ 2008-12-05 13:27 UTC (permalink / raw
To: rms; +Cc: emacs-devel
First, all context switches between user-level threads have to be done
manually, i.e. if you need a switch, you have to call
cthread_yield(). However, on SMP systems, since we have more than one
kernel threads, user-level threads may be interrupted randmonly, but
still no user-level context switch will happen unless you yield the CPU explicitly.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 2:59 ` Richard M Stallman
2008-12-05 7:40 ` Giuseppe Scrivano
@ 2008-12-05 15:36 ` Stefan Monnier
2008-12-06 19:25 ` Richard M Stallman
1 sibling, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-05 15:36 UTC (permalink / raw
To: rms; +Cc: gscrivano, emacs-devel
> Actually, yielding in QUIT will take a lot of work. It's definitely not
> "cooperative" seen from Elisp's point of view (where QUIT can be run
> implicitly all over the place).
> I am surprised. Perhaps you're right, but why do you think so?
> Anywhere that calls QUIT is a place where it is safe for an error to happen,
> so why not a thread switch?
It will be safe in the sense that it won't cause a crash. But it will
mess up Elisp's semantics. Consider:
(dotimes (i 1000) (toto))
if you run this code twice in separate threads and allow context
switches at QUIT, then you'll basically be doing "preemptive
concurrency" seen from Elisp's point of view. Among other things, the
two threads will be fighting over the value of `i'.
So before this level of concurrency can be made to work we'll need to
fix dynamic scoping to be "per-thread" rather than global.
Note that the `yield' primitive won't be easy to use for the same kind
of reason (until we fix dynamic-scoping that is).
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 11:02 ` Helmut Eller
@ 2008-12-05 15:39 ` Stefan Monnier
2008-12-05 16:22 ` Ted Zlatanov
2008-12-05 16:57 ` Tom Tromey
2 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-05 15:39 UTC (permalink / raw
To: Helmut Eller; +Cc: emacs-devel
> I'm wondering what the exact problem with Gnus is.
Nothing in particular. Gnus is already doing a fair bit of effort to
run asynchronously. But, e.g. refreshing the *Group* buffer can take
a long time (especially if you use IMAP) and during this time, your
Emacs can't be used, even though it's not necessarily using all of
your CPU.
Similarly when downloading a large article (with say some movie
attached).
For those reasons I always have at least 2 Emacs processes running: one
for Gnus and one for pretty much everything else.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 2:59 ` Richard M Stallman
@ 2008-12-05 15:40 ` Stefan Monnier
0 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-05 15:40 UTC (permalink / raw
To: rms; +Cc: Giuseppe Scrivano, emacs-devel
> Yes, I was referring to the cooperating threads model using a QUIT
> macro. How can it be used by gnus while fetching new data?
> Does the code that gnus runs to fetch new data involve ever doing the
> QUIT macro?
Yes, the QUIT macro is executed pretty much all the time.
> If it has a loop, then yes. If it reads from a net
> connection, then it calls wait_reading_process_output.
It does both.
> So it should be able to operate in parallel with other things, even
> with cooperating threads.
Indeed.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 11:02 ` Helmut Eller
2008-12-05 15:39 ` Stefan Monnier
@ 2008-12-05 16:22 ` Ted Zlatanov
2008-12-05 16:57 ` Tom Tromey
2 siblings, 0 replies; 89+ messages in thread
From: Ted Zlatanov @ 2008-12-05 16:22 UTC (permalink / raw
To: emacs-devel
On Fri, 05 Dec 2008 12:02:19 +0100 Helmut Eller <eller.helmut@gmail.com> wrote:
HE> I'm wondering what the exact problem with Gnus is.
HE> Certainly, downloading the next article takes a bit of time but threads
HE> wont make the download any faster. Is there something the user wants to
HE> do while waiting for the next article?
Even assuming all server interactions can be backgrounded (they can't
AFAIK because of their current design, interacting with the global data
all over the place), one place that's slow is article splitting. You
fetch an article, then run some rules (e.g. spam filters and registry
searches) to decide where it will go. This can be 90% parallelized, I
would guess.
Reading mail normally has never been so slow that I wished it could be
done in the background.
Saving the newsrc file is sometimes slow, so backgrounding it would be
nice. Of course, you don't want to garble that data so it's important
to do it right.
The Gnus registry should be asynchronous for:
- tracking article move/delete/copy/spool operations
- saving the registry file
- interacting with spam.el
spam.el should be asynchronous for:
- running a spam backend on an article
- determining the spam score of an article
- telling the registry the results of spam processing
Ted
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 11:02 ` Helmut Eller
2008-12-05 15:39 ` Stefan Monnier
2008-12-05 16:22 ` Ted Zlatanov
@ 2008-12-05 16:57 ` Tom Tromey
2008-12-06 4:41 ` Miles Bader
2008-12-06 7:44 ` Helmut Eller
2 siblings, 2 replies; 89+ messages in thread
From: Tom Tromey @ 2008-12-05 16:57 UTC (permalink / raw
To: Helmut Eller; +Cc: emacs-devel
>>>>> "Helmut" == Helmut Eller <eller.helmut@gmail.com> writes:
Helmut> I'm wondering what the exact problem with Gnus is.
Getting new news blocks all of Emacs, sometimes for a long time.
Also, entering a newsgroup can sometimes take quite a while.
It seems to me that this could be fixed in Gnus, by installing a
special keymap (to prevent the user from trying "bad" things) and then
doing a lot more work in the process filter. This is a pain, of
course.
Entering a newsgroup is trickier since I am sure that it is not always
blocked on I/O. Even this could be done -- say by doing small
increments of work each time a timer fires.
But, the problem is not limited to Gnus. If you do a big update in
PCL-CVS (or psvn), Emacs will pause while preparing the buffer. Some
VC things did this, too, in 22 (but now are async, I think).
I've also noticed that ERC can cause Emacs to be unusable for long
periods, I think when it has trouble contacting the nameserver. Also,
ERC tends to disconnect from the server if Emacs pauses for too long
-- I got much more sensitive to problems in this area once I started
using ERC...
The promise of threads isn't just that it can fix these, but that it
opens Emacs to new applications without hurting usability. Maybe
there are other ways to accomplish the same thing, though.
Tom
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
[not found] ` <87prk64ilv.fsf@vanilla.net.mt>
@ 2008-12-05 18:37 ` Giuseppe Scrivano
2008-12-06 21:58 ` Magnus Henoch
0 siblings, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-05 18:37 UTC (permalink / raw
To: Li Lin; +Cc: emacs-devel
Personally I don't think there is need to use a library that at the
moment is usable only on an architecture, it will be a serious
portability problem for Emacs (that probably after "Hello World" is the
most portable program out there).
All we need for a multi-threaded Emacs can be done quite easily with
pthreads.
Giuseppe
Li Lin <ak70@vanilla.net.mt> writes:
> SMASH has many different implementations. Basically, we create one
> kernel thread for each CPU(or core) in which a user-level thread
> scheduler runs, and the thread is bounded to the corresponding CPU. The
> context switches among user-level threads are done though a explicit
> call to the function cthread_yield(). However, it is the native
> scheduler that manages the kernel threads.
> So on uniprocessor machines, it is purely cooperative, on multi-CPU(or
> -core) machines it is a mixture of cooperative and preemptive
> threads. However, it is not difficult to modify it so that on
> uniprocessor machine we still have more than one kernel threads.
> I attached Kurt's thesis about SMASH. Although a lot of implementation
> details has changed, his orginal thesis is still a good reference.
> The attachment is a DVI file. If you can read it, then I can send you
> the latex source of it, but you have to compile it by yourself.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 16:57 ` Tom Tromey
@ 2008-12-06 4:41 ` Miles Bader
2008-12-06 7:44 ` Helmut Eller
1 sibling, 0 replies; 89+ messages in thread
From: Miles Bader @ 2008-12-06 4:41 UTC (permalink / raw
To: Tom Tromey; +Cc: Helmut Eller, emacs-devel
Tom Tromey <tromey@redhat.com> writes:
> The promise of threads isn't just that it can fix these, but that it
> opens Emacs to new applications without hurting usability. Maybe
> there are other ways to accomplish the same thing, though.
I think most of these things _could_ be done by judicious use of process
filters etc... but it's a big pain, maybe requiring completely
re-designing various parts of gnus. My hope is that with cooperative
threading, the changes required would be far smaller, maybe even just
sticking in calls to (yield) at strategic locations.
-miles
--
Alliance, n. In international politics, the union of two thieves who have
their hands so deeply inserted in each other's pockets that they cannot
separately plunder a third.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 16:57 ` Tom Tromey
2008-12-06 4:41 ` Miles Bader
@ 2008-12-06 7:44 ` Helmut Eller
2008-12-06 22:31 ` Stefan Monnier
1 sibling, 1 reply; 89+ messages in thread
From: Helmut Eller @ 2008-12-06 7:44 UTC (permalink / raw
To: emacs-devel
* Tom Tromey [2008-12-05 17:57+0100] writes:
> The promise of threads isn't just that it can fix these, but that it
> opens Emacs to new applications without hurting usability. Maybe
> there are other ways to accomplish the same thing, though.
It also opens possibilities for concurrency related bugs.
We will see how it turns out.
Helmut.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 7:40 ` Giuseppe Scrivano
2008-12-05 8:20 ` Miles Bader
@ 2008-12-06 8:30 ` Richard M Stallman
1 sibling, 0 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-12-06 8:30 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: monnier, emacs-devel
The cooperative threads approach moves to Elisp packages more work as
they will have explicitly to yield control but it simplifies a lot the C
code.
If thread-switching occurs inside QUIT, then Lisp code will never
need to explicitly say where switching occurs.
On the other hand, if thread-switching only occurs in
wait_reading_process_output, Lisp programs could permit
thread-switching by doing (accept-process-output).
The former would be more convenient. Stefan said it has
problems, but didn't explain them yet.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 15:36 ` Stefan Monnier
@ 2008-12-06 19:25 ` Richard M Stallman
2008-12-06 22:41 ` Stefan Monnier
2008-12-07 16:15 ` Giuseppe Scrivano
0 siblings, 2 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-12-06 19:25 UTC (permalink / raw
To: Stefan Monnier; +Cc: gscrivano, emacs-devel
It will be safe in the sense that it won't cause a crash. But it will
mess up Elisp's semantics. Consider:
(dotimes (i 1000) (toto))
if you run this code twice in separate threads and allow context
switches at QUIT, then you'll basically be doing "preemptive
concurrency" seen from Elisp's point of view. Among other things, the
two threads will be fighting over the value of `i'.
Each thread should have its own local bindings. To do this
requires swapping bindings in and out of the specpdls
when switching threads. It is not hard.
This makes thread switches slower, and that makes it desirable
to do them less often.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-05 18:37 ` Giuseppe Scrivano
@ 2008-12-06 21:58 ` Magnus Henoch
0 siblings, 0 replies; 89+ messages in thread
From: Magnus Henoch @ 2008-12-06 21:58 UTC (permalink / raw
To: emacs-devel
Giuseppe Scrivano <gscrivano@gnu.org> writes:
> Personally I don't think there is need to use a library that at the
> moment is usable only on an architecture, it will be a serious
> portability problem for Emacs (that probably after "Hello World" is the
> most portable program out there).
> All we need for a multi-threaded Emacs can be done quite easily with
> pthreads.
Or GNU pth, which I'm surprised that noone has mentioned. It does
cooperative threading with a pthread-like interface, yielding at I/O
operations and some other syscalls.
http://www.gnu.org/software/pth/
Of course, whoever writes the code gets to choose the library. Good
luck with your endeavour! I look forward to the results.
Magnus
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-06 7:44 ` Helmut Eller
@ 2008-12-06 22:31 ` Stefan Monnier
0 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-06 22:31 UTC (permalink / raw
To: Helmut Eller; +Cc: emacs-devel
> It also opens possibilities for concurrency related bugs.
You mean "it holds promises of concurrency bugs"? Yes, very much so :-(
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-06 19:25 ` Richard M Stallman
@ 2008-12-06 22:41 ` Stefan Monnier
2008-12-06 23:41 ` Giuseppe Scrivano
2008-12-07 16:02 ` Richard M Stallman
2008-12-07 16:15 ` Giuseppe Scrivano
1 sibling, 2 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-06 22:41 UTC (permalink / raw
To: rms; +Cc: gscrivano, emacs-devel
> It will be safe in the sense that it won't cause a crash. But it will
> mess up Elisp's semantics. Consider:
> (dotimes (i 1000) (toto))
> if you run this code twice in separate threads and allow context
> switches at QUIT, then you'll basically be doing "preemptive
> concurrency" seen from Elisp's point of view. Among other things, the
> two threads will be fighting over the value of `i'.
> Each thread should have its own local bindings. To do this
> requires swapping bindings in and out of the specpdls
> when switching threads. It is not hard.
> This makes thread switches slower, and that makes it desirable
> to do them less often.
It might be an acceptable temporary solution, but in the long term we
will want to allow true parallelism, so such trickery will not be
an option.
Whether it'll be a valuable intermediate point or not, I cannot say.
My gut feeling is that we'd better work on a solution that will work in
the longer run. Currently my guess is that generalizing the existing
buffer-local/frame-local/terminal-local machinery to include
thread-local is going to work well, with fairly limited changes.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-11-30 21:46 ` Stefan Monnier
2008-11-30 22:25 ` Giuseppe Scrivano
@ 2008-12-06 22:50 ` Tom Tromey
2008-12-07 3:31 ` Stefan Monnier
1 sibling, 1 reply; 89+ messages in thread
From: Tom Tromey @ 2008-12-06 22:50 UTC (permalink / raw
To: Stefan Monnier; +Cc: Giuseppe Scrivano, emacs-devel
>> Do you see any situation that there is need to store a value on a
>> specific thread?
Stefan> let-binding, of course. It's probably the only one that matters
Stefan> (besides the internal ones like current_buffer).
I've been wondering how `flet' will be handled.
Tom
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-06 22:41 ` Stefan Monnier
@ 2008-12-06 23:41 ` Giuseppe Scrivano
2008-12-07 20:51 ` Stefan Monnier
2008-12-07 16:02 ` Richard M Stallman
1 sibling, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-06 23:41 UTC (permalink / raw
To: Stefan Monnier; +Cc: rms, emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> It will be safe in the sense that it won't cause a crash. But it will
>> mess up Elisp's semantics. Consider:
>
>> (dotimes (i 1000) (toto))
>
>> if you run this code twice in separate threads and allow context
>> switches at QUIT, then you'll basically be doing "preemptive
>> concurrency" seen from Elisp's point of view. Among other things, the
>> two threads will be fighting over the value of `i'.
>
>> Each thread should have its own local bindings. To do this
>> requires swapping bindings in and out of the specpdls
>> when switching threads. It is not hard.
>
>> This makes thread switches slower, and that makes it desirable
>> to do them less often.
>
> It might be an acceptable temporary solution, but in the long term we
> will want to allow true parallelism, so such trickery will not be
> an option.
Actually I am using what Richard suggested. Every thread has a specpdl
and on a thread switch I copy the current symbol value inside its
specbinding cell.
Still there is much to do but now I am able to do this:
(setq a-thread (make-thread))
#<thread 1>
(progn
(run-in-thread a-thread '(dotimes (i 2)
(print "hello")
(yield)))
(dotimes (i 2)
(print "world")
(yield)))
"hello"
"world"
"hello"
"world"
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-06 22:50 ` Tom Tromey
@ 2008-12-07 3:31 ` Stefan Monnier
0 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-07 3:31 UTC (permalink / raw
To: Tom Tromey; +Cc: Giuseppe Scrivano, emacs-devel
>>> Do you see any situation that there is need to store a value on a
>>> specific thread?
Stefan> let-binding, of course. It's probably the only one that matters
Stefan> (besides the internal ones like current_buffer).
> I've been wondering how `flet' will be handled.
Good question. Luckily, it's too often used and it's easy to grep for
it, so it hopefully will be fixable somehow, although it may require
a completely different implementation technique, or different semantics.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-06 22:41 ` Stefan Monnier
2008-12-06 23:41 ` Giuseppe Scrivano
@ 2008-12-07 16:02 ` Richard M Stallman
2008-12-07 20:52 ` Stefan Monnier
1 sibling, 1 reply; 89+ messages in thread
From: Richard M Stallman @ 2008-12-07 16:02 UTC (permalink / raw
To: Stefan Monnier; +Cc: gscrivano, emacs-devel
> Each thread should have its own local bindings. To do this
> requires swapping bindings in and out of the specpdls
> when switching threads. It is not hard.
Currently my guess is that generalizing the existing
buffer-local/frame-local/terminal-local machinery to include
thread-local is going to work well, with fairly limited changes.
That seems like a misunderstanding. What I am talking about does
not involve adding another kind of binding. It is a matter of
correctly implementing the existing kinds of binding in the context
of multiple threads.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-06 19:25 ` Richard M Stallman
2008-12-06 22:41 ` Stefan Monnier
@ 2008-12-07 16:15 ` Giuseppe Scrivano
2008-12-08 18:26 ` Richard M Stallman
1 sibling, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-07 16:15 UTC (permalink / raw
To: rms; +Cc: Stefan Monnier, emacs-devel
Hi,
I uploaded here a patch with the current status of my work:
http://it.gnu.org/~gscrivano/files/concurrent_threads_7_12.diff.gz
The patch adds these Elisp primitives:
(make-thread)
(run-in-thread)
(kill-thread)
(yield)
Now the garbage collector can be executed by any thread, local bindings
are done as you suggested, the symbol value is changed when Emacs
switches to another thread.
Every thread has its own current_buffer so they can work independently
on different buffers.
New code is not very clean yet, differently from the first patch I
submitted, now all thread local storage data is in a `thread_data'
struct and (make-thread) returns an object.
Any comment? (Good impressions are welcome).
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-06 23:41 ` Giuseppe Scrivano
@ 2008-12-07 20:51 ` Stefan Monnier
2008-12-07 23:51 ` Giuseppe Scrivano
0 siblings, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-07 20:51 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: rms, emacs-devel
>>> Each thread should have its own local bindings. To do this
>>> requires swapping bindings in and out of the specpdls
>>> when switching threads. It is not hard.
[...]
> Actually I am using what Richard suggested. Every thread has a specpdl
> and on a thread switch I copy the current symbol value inside its
> specbinding cell.
Switching the value of specpdl is not enough. Try
(progn
(run-in-thread a-thread '(dotimes (i 2)
(print "hello")
(yield)))
(let ((i 5))
(while (< i 7)
(print "world")
(yield)
(setq i (1+ i))))
What Richard suggests is that upon a thread-switch we walk up the specpdl
stack, undoing all the bindings, then switch specpdl to the one of the
other thread and walk down that one to reestablish the local bindings of
the new thread.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-07 16:02 ` Richard M Stallman
@ 2008-12-07 20:52 ` Stefan Monnier
0 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-07 20:52 UTC (permalink / raw
To: rms; +Cc: gscrivano, emacs-devel
>> Each thread should have its own local bindings. To do this
>> requires swapping bindings in and out of the specpdls
>> when switching threads. It is not hard.
> Currently my guess is that generalizing the existing
> buffer-local/frame-local/terminal-local machinery to include
> thread-local is going to work well, with fairly limited changes.
> That seems like a misunderstanding.
No, it's not a misunderstanding. I'm just suggesting a different
implementation technique.
> What I am talking about does not involve adding another kind of
> binding. It is a matter of correctly implementing the existing kinds
> of binding in the context of multiple threads.
Indeed, it is, and there several alternatives.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-07 20:51 ` Stefan Monnier
@ 2008-12-07 23:51 ` Giuseppe Scrivano
2008-12-08 3:06 ` Chetan Pandya
2008-12-08 15:50 ` Stefan Monnier
0 siblings, 2 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-07 23:51 UTC (permalink / raw
To: Stefan Monnier; +Cc: rms, emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
> Switching the value of specpdl is not enough. Try
>
> (progn
> (run-in-thread a-thread '(dotimes (i 2)
> (print "hello")
> (yield)))
>
> (let ((i 5))
> (while (< i 7)
> (print "world")
> (yield)
> (setq i (1+ i))))
>
> What Richard suggests is that upon a thread-switch we walk up the specpdl
> stack, undoing all the bindings, then switch specpdl to the one of the
> other thread and walk down that one to reestablish the local bindings of
> the new thread.
It is exactly what I do in save_thread_bindings () and
restore_thread_bindings ().
Trying your code (plus initializing the thread and another ')' at the
end) I have:
(progn
(run-in-thread a-thread '(dotimes (i 2)
(print "hello")
(yield)))
(let ((i 5))
(while (< i 7)
(print "world")
(yield)
(setq i (1+ i)))))
"hello"
"world"
"hello"
"world"
Regards,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-07 23:51 ` Giuseppe Scrivano
@ 2008-12-08 3:06 ` Chetan Pandya
2008-12-08 15:50 ` Stefan Monnier
1 sibling, 0 replies; 89+ messages in thread
From: Chetan Pandya @ 2008-12-08 3:06 UTC (permalink / raw
To: Stefan Monnier, Giuseppe Scrivano; +Cc: rms, emacs-devel
I am wondering if there is eally an expectation build a multi-threading emacs. There are also all of the global variables in C code that might need to be saved and restored e.g. while loading a file.
Chetan
--- On Sun, 12/7/08, Giuseppe Scrivano <gscrivano@gnu.org> wrote:
> From: Giuseppe Scrivano <gscrivano@gnu.org>
> Subject: Re: multi-threaded Emacs
> To: "Stefan Monnier" <monnier@iro.umontreal.ca>
> Cc: rms@gnu.org, emacs-devel@gnu.org
> Date: Sunday, December 7, 2008, 11:51 PM
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
> >
> > Switching the value of specpdl is not enough. Try
> >
> > (progn
> > (run-in-thread a-thread '(dotimes (i 2)
> > (print "hello")
> > (yield)))
> >
> > (let ((i 5))
> > (while (< i 7)
> > (print "world")
> > (yield)
> > (setq i (1+ i))))
> >
> > What Richard suggests is that upon a thread-switch we
> walk up the specpdl
> > stack, undoing all the bindings, then switch specpdl
> to the one of the
> > other thread and walk down that one to reestablish the
> local bindings of
> > the new thread.
>
> It is exactly what I do in save_thread_bindings () and
> restore_thread_bindings ().
>
> Trying your code (plus initializing the thread and another
> ')' at the
> end) I have:
>
> (progn
> (run-in-thread a-thread '(dotimes (i 2)
> (print "hello")
> (yield)))
>
> (let ((i 5))
> (while (< i 7)
> (print "world")
> (yield)
> (setq i (1+ i)))))
>
> "hello"
>
> "world"
>
> "hello"
>
> "world"
>
>
> Regards,
> Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-07 23:51 ` Giuseppe Scrivano
2008-12-08 3:06 ` Chetan Pandya
@ 2008-12-08 15:50 ` Stefan Monnier
1 sibling, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-08 15:50 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: rms, emacs-devel
> It is exactly what I do in save_thread_bindings () and
> restore_thread_bindings ().
Wonderful, thanks.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-07 16:15 ` Giuseppe Scrivano
@ 2008-12-08 18:26 ` Richard M Stallman
2008-12-08 19:49 ` Giuseppe Scrivano
0 siblings, 1 reply; 89+ messages in thread
From: Richard M Stallman @ 2008-12-08 18:26 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: monnier, emacs-devel
What is the condition for thread-switching in your latest version?
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-08 18:26 ` Richard M Stallman
@ 2008-12-08 19:49 ` Giuseppe Scrivano
2008-12-09 2:15 ` dhruva
2008-12-09 17:26 ` Richard M Stallman
0 siblings, 2 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-08 19:49 UTC (permalink / raw
To: rms; +Cc: monnier, emacs-devel
Richard M Stallman <rms@gnu.org> writes:
> What is the condition for thread-switching in your latest version?
The `yield' primitive must be explicitly called.
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-08 19:49 ` Giuseppe Scrivano
@ 2008-12-09 2:15 ` dhruva
2008-12-09 2:49 ` Stephen J. Turnbull
2008-12-09 17:26 ` Richard M Stallman
1 sibling, 1 reply; 89+ messages in thread
From: dhruva @ 2008-12-09 2:15 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: emacs-devel, rms, monnier
Hello,
On Tue, Dec 9, 2008 at 1:19 AM, Giuseppe Scrivano <gscrivano@gnu.org> wrote:
> Richard M Stallman <rms@gnu.org> writes:
>
>> What is the condition for thread-switching in your latest version?
>
> The `yield' primitive must be explicitly called.
I hope there will be a branch with this code sometime soon being
updated from HEAD constantly. I will then be able to play with this
along with the bleeding edge features on HEAD.
-dhruva
--
Contents reflect my personal views only!
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 2:15 ` dhruva
@ 2008-12-09 2:49 ` Stephen J. Turnbull
2008-12-09 2:53 ` dhruva
2008-12-09 9:36 ` Andreas Schwab
0 siblings, 2 replies; 89+ messages in thread
From: Stephen J. Turnbull @ 2008-12-09 2:49 UTC (permalink / raw
To: dhruva; +Cc: monnier, Giuseppe Scrivano, rms, emacs-devel
dhruva writes:
> I hope there will be a branch with this code sometime soon being
> updated from HEAD constantly. I will then be able to play with this
> along with the bleeding edge features on HEAD.
Why don't you just make one? I'm seriously asking; there are several
tools such as cvs2svn and tailor. Those two are both written in
Python, which means they should be fairly portable, including to
Windows.
Have you tried one or more of these and failed?
Making a serious mirror and providing the service to third parties is
a relatively demanding task. But for local use you can put up with
the occasional CRLF vs. NL bogosity and other minor issues that
typically arise. Ie, maintaining a local mirror is well within the
scope of effort suggested by "play with bleeding edge features."
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 2:49 ` Stephen J. Turnbull
@ 2008-12-09 2:53 ` dhruva
2008-12-09 9:36 ` Andreas Schwab
1 sibling, 0 replies; 89+ messages in thread
From: dhruva @ 2008-12-09 2:53 UTC (permalink / raw
To: Stephen J. Turnbull; +Cc: monnier, Giuseppe Scrivano, rms, emacs-devel
Hello Stephen,
On Tue, Dec 9, 2008 at 8:19 AM, Stephen J. Turnbull <stephen@xemacs.org> wrote:
> dhruva writes:
>
> > I hope there will be a branch with this code sometime soon being
> > updated from HEAD constantly. I will then be able to play with this
> > along with the bleeding edge features on HEAD.
>
> Why don't you just make one? I'm seriously asking; there are several
> tools such as cvs2svn and tailor. Those two are both written in
> Python, which means they should be fairly portable, including to
> Windows.
I have not used cvs2svn myself but suggested it and have seen it being
used at my previous place of work (moving ~10 years of CVS history to
svn and it went fine though I was told of issues in doing an
incremental update. They ended up doing a one time conversion and
stopped usage of CVS. Like a flip switch approach!).
> Have you tried one or more of these and failed?
Well, the point is to have a branch where the main author can push and
I could pull. I can always have a patch queue (as in mercurial) or do
it through some extra wizardry in git. I do not want to get into
merging changes that are not mine and mess up and start reporting
problems that are truly my own.
Off topic:
I have tried tailor, since I work on p4 at work, I have tried git-p4
and have developed my very own p4 to hg. I find tailor to be very
flaky. Like you correctly mentioned in a different thread that it
needs care, I ran out of patience. However, I did contribute a minor
fix to make it work with newer hg (sometime back).
To summarize, based on my experience, I find tools that are part of
git are quite robust (among the few I have used or tested).
-dhruva
--
Contents reflect my personal views only!
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 2:49 ` Stephen J. Turnbull
2008-12-09 2:53 ` dhruva
@ 2008-12-09 9:36 ` Andreas Schwab
1 sibling, 0 replies; 89+ messages in thread
From: Andreas Schwab @ 2008-12-09 9:36 UTC (permalink / raw
To: Stephen J. Turnbull; +Cc: emacs-devel, monnier, rms, Giuseppe Scrivano
"Stephen J. Turnbull" <stephen@xemacs.org> writes:
> Why don't you just make one? I'm seriously asking; there are several
> tools such as cvs2svn and tailor.
IMHO the best tool for converting a CVS repo is parsecvs.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-08 19:49 ` Giuseppe Scrivano
2008-12-09 2:15 ` dhruva
@ 2008-12-09 17:26 ` Richard M Stallman
2008-12-09 19:10 ` Giuseppe Scrivano
2008-12-09 19:40 ` Stefan Monnier
1 sibling, 2 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-12-09 17:26 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: monnier, emacs-devel
> What is the condition for thread-switching in your latest version?
The `yield' primitive must be explicitly called.
I think that interface won't work very well, because it would require
changing every Lisp program to make it cooperate with other threads.
We need to put this into the C level.
If making QUIT do this is not safe, we could write another macro
YIELD to do it, and call that macro where appropriate.
But that macro needs to be very fast when it does NOT switch threads!
Here's an idea. Suppose the YIELD macro increments a counter and
switches threads (round robin?) when that counter reaches a certain
number. Every thread-switch would reset the counter to 0.
Of course, waiting (in wait_reading_process_output) would also
switch threads.
2.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 17:26 ` Richard M Stallman
@ 2008-12-09 19:10 ` Giuseppe Scrivano
2008-12-10 18:18 ` Richard M Stallman
2008-12-10 18:18 ` Richard M Stallman
2008-12-09 19:40 ` Stefan Monnier
1 sibling, 2 replies; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-09 19:10 UTC (permalink / raw
To: rms; +Cc: monnier, emacs-devel
Richard M Stallman <rms@gnu.org> writes:
> > What is the condition for thread-switching in your latest version?
>
> The `yield' primitive must be explicitly called.
>
> I think that interface won't work very well, because it would require
> changing every Lisp program to make it cooperate with other threads.
> We need to put this into the C level.
I think it is not safe to call `yield' from the C code, except special
cases like `run-in-thread'. Every thread must be completely separated
from each other to allow a switch during its execution and it is not
true while threads are accessing global variables.
For example, we can't switch threads while they are executing:
(setq a-global-variable (foo a-global-variable))
This is the reason why YIELD must be explicit at Elisp level, because
the developer knows exactly that a switch can happen at that point.
In future every thread should be executed indipendently from each other
(adding synchronization primitives where they are needed) to allow real
parallelism.
> If making QUIT do this is not safe, we could write another macro
> YIELD to do it, and call that macro where appropriate.
>
> But that macro needs to be very fast when it does NOT switch threads!
Elisp developers shouldn't worry about yield efficiency because if there
are not other active threads, nothing will be done and `yield' returns
immediately.
> Here's an idea. Suppose the YIELD macro increments a counter and
> switches threads (round robin?) when that counter reaches a certain
> number. Every thread-switch would reset the counter to 0.
> Of course, waiting (in wait_reading_process_output) would also
> switch threads.
Thread switching is implemented using round robin. Why would you like
to reduce the amount of switches using a counter? I think that thread
switching doesn't take a lot of time that we need to call it carefully,
instead I think that more often we call it and more responsive Emacs
will look.
I was thinking about change the scheduler policy to give a bigger
priority to threads that are working on a buffer currently visible to
the user. What I really expect from Emacs threads is that I can
continue working while some other tasks are executed in the background,
like fetching emails. Personally I will not care much if it took N+1
seconds instead of N if I could continue work on another buffer.
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 17:26 ` Richard M Stallman
2008-12-09 19:10 ` Giuseppe Scrivano
@ 2008-12-09 19:40 ` Stefan Monnier
2008-12-10 18:18 ` Richard M Stallman
1 sibling, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-09 19:40 UTC (permalink / raw
To: rms; +Cc: Giuseppe Scrivano, emacs-devel
>> What is the condition for thread-switching in your latest version?
> The `yield' primitive must be explicitly called.
> I think that interface won't work very well, because it would require
> changing every Lisp program to make it cooperate with other threads.
> We need to put this into the C level.
I think if `yield' is called in accept-process-output and read_char, the
remaining places where `yield' might be needed will be fairly few.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 19:10 ` Giuseppe Scrivano
@ 2008-12-10 18:18 ` Richard M Stallman
2008-12-10 18:18 ` Richard M Stallman
1 sibling, 0 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-12-10 18:18 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: monnier, emacs-devel
For example, we can't switch threads while they are executing:
(setq a-global-variable (foo a-global-variable))
In most cases, there is no problem, because the code in the other thread
won't change this global variable.
I think it is better to have a variable `inhibit-thread-switch'
which you could bind around such sections when there is really an issue.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 19:10 ` Giuseppe Scrivano
2008-12-10 18:18 ` Richard M Stallman
@ 2008-12-10 18:18 ` Richard M Stallman
1 sibling, 0 replies; 89+ messages in thread
From: Richard M Stallman @ 2008-12-10 18:18 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: monnier, emacs-devel
Why would you like
to reduce the amount of switches using a counter?
Because it takes a substantial time. Just swapping the specpdls
takes time.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-09 19:40 ` Stefan Monnier
@ 2008-12-10 18:18 ` Richard M Stallman
2008-12-11 1:59 ` Stefan Monnier
0 siblings, 1 reply; 89+ messages in thread
From: Richard M Stallman @ 2008-12-10 18:18 UTC (permalink / raw
To: Stefan Monnier; +Cc: gscrivano, emacs-devel
I think if `yield' is called in accept-process-output and read_char, the
remaining places where `yield' might be needed will be fairly few.
That sort of thing could be enough for the thread-per-terminal job.
It would also be good for specially written parallel programs.
But that's as far as it would go.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-10 18:18 ` Richard M Stallman
@ 2008-12-11 1:59 ` Stefan Monnier
2008-12-11 14:41 ` Ted Zlatanov
2008-12-11 19:07 ` Paul R
0 siblings, 2 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-11 1:59 UTC (permalink / raw
To: rms; +Cc: gscrivano, emacs-devel
> I think if `yield' is called in accept-process-output and read_char, the
> remaining places where `yield' might be needed will be fairly few.
> That sort of thing could be enough for the thread-per-terminal job.
> It would also be good for specially written parallel programs.
> But that's as far as it would go.
Indeed. Further than that, we'd need more explicit
synchronization primitives. We could probably start with
a (atomically &rest BODY) which guarantees that BODY will be properly
protected from other threads that it will appear to be
executed atomically.
Such a primitive should also include constraints such as "BODY cannot
include non-undoable operations", e.g. it can't save to a file.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 1:59 ` Stefan Monnier
@ 2008-12-11 14:41 ` Ted Zlatanov
2008-12-11 18:30 ` Stefan Monnier
2008-12-11 19:07 ` Paul R
1 sibling, 1 reply; 89+ messages in thread
From: Ted Zlatanov @ 2008-12-11 14:41 UTC (permalink / raw
To: emacs-devel
On Wed, 10 Dec 2008 20:59:41 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
SM> Further than that, we'd need more explicit synchronization
SM> primitives. We could probably start with a (atomically &rest BODY)
SM> which guarantees that BODY will be properly protected from other
SM> threads that it will appear to be executed atomically. Such a
SM> primitive should also include constraints such as "BODY cannot
SM> include non-undoable operations", e.g. it can't save to a file.
Would it help to look at the C level and figure out which functions are
atomic (no I/O operations, IIUC), and perhaps mark them so with an
attribute? Then any ELisp function that builds on atomics is atomic
itself, presumably (except for macros and other trickery).
Ted
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 14:41 ` Ted Zlatanov
@ 2008-12-11 18:30 ` Stefan Monnier
2008-12-11 18:42 ` Ted Zlatanov
0 siblings, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-11 18:30 UTC (permalink / raw
To: Ted Zlatanov; +Cc: emacs-devel
> Then any ELisp function that builds on atomics is atomic
> itself, presumably (except for macros and other trickery).
No, atomicity does not work that way, sadly.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 18:30 ` Stefan Monnier
@ 2008-12-11 18:42 ` Ted Zlatanov
2008-12-11 19:01 ` Paul R
2008-12-11 20:53 ` Stefan Monnier
0 siblings, 2 replies; 89+ messages in thread
From: Ted Zlatanov @ 2008-12-11 18:42 UTC (permalink / raw
To: emacs-devel
On Thu, 11 Dec 2008 13:30:26 -0500 Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>> Then any ELisp function that builds on atomics is atomic
>> itself, presumably (except for macros and other trickery).
SM> No, atomicity does not work that way, sadly.
"atomic" was a bad word choice on my part. I meant "safe to put in an
(atomically) body as you described it." I think if functions A and B
are safe, then any function C that only uses A and B is safe too. Does
that make more sense?
Ted
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 18:42 ` Ted Zlatanov
@ 2008-12-11 19:01 ` Paul R
2008-12-11 20:53 ` Stefan Monnier
1 sibling, 0 replies; 89+ messages in thread
From: Paul R @ 2008-12-11 19:01 UTC (permalink / raw
To: Ted Zlatanov; +Cc: emacs-devel
SM> No, atomicity does not work that way, sadly.
Ted> "atomic" was a bad word choice on my part. I meant "safe to put in
Ted> an (atomically) body as you described it." I think if functions
Ted> A and B are safe, then any function C that only uses A and B is
Ted> safe too. Does that make more sense?
I guess Stefan means he wants a way to operate within a transaction, so
that the state of emacs (the state being defined by the all the values
of every variables accessible from the scope) is either changed exactly
as desired, or not touched at all.
If C is defined as "A then B" with A and B atomics, then if you run C,
and A is a success and B is a failure, then C won't have the 'atomic'
property, because C will exit with state half changed. Now if you totaly
avoid sequential execution (avoid the "imperative style"), so that you
construct C of B and B of A, indeed having A atomic is enought. But any
software, in particular emacs, is full of sequential processing with
intermediate states between instructions.
BTW, I'm not sure why stefan wants this atomic construction at the lisp
level, but for sure I would be amazed to see that !
--
Paul
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 1:59 ` Stefan Monnier
2008-12-11 14:41 ` Ted Zlatanov
@ 2008-12-11 19:07 ` Paul R
2008-12-11 20:54 ` Stefan Monnier
1 sibling, 1 reply; 89+ messages in thread
From: Paul R @ 2008-12-11 19:07 UTC (permalink / raw
To: Stefan Monnier; +Cc: emacs-devel, rms, gscrivano
Stefan> Indeed. Further than that, we'd need more explicit
Stefan> synchronization primitives. We could probably start with
Stefan> a (atomically &rest BODY) which guarantees that BODY will be
Stefan> properly protected from other threads that it will appear to be
Stefan> executed atomically.
Isn't it what critical sections are for ? (critical &rest BODY) would
execute body with no thread switching. I think this feature is not
necessary with cooperative-only threading because a critical section is
any section that does not contain any 'yield' instruction.
--
Paul
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 18:42 ` Ted Zlatanov
2008-12-11 19:01 ` Paul R
@ 2008-12-11 20:53 ` Stefan Monnier
2008-12-12 19:03 ` Giuseppe Scrivano
1 sibling, 1 reply; 89+ messages in thread
From: Stefan Monnier @ 2008-12-11 20:53 UTC (permalink / raw
To: Ted Zlatanov; +Cc: emacs-devel
>>> Then any ELisp function that builds on atomics is atomic
>>> itself, presumably (except for macros and other trickery).
SM> No, atomicity does not work that way, sadly.
> "atomic" was a bad word choice on my part. I meant "safe to put in an
> (atomically) body as you described it." I think if functions A and B
> are safe, then any function C that only uses A and B is safe too. Does
> that make more sense?
Yes, that makes sense. Hopefully, most functions are "safe" in
this respect.
BTW, implementing "atomically" is not necessarily that hard.
Of course, it can be implemented with an "optimistic locking" discipline
where we track changes and undo them if the transaction aborts, but
until we get there, there are meny much simpler implementations which
will be useful. A first implementation is
(defmacro atomically (&rest body)
`(let ((inhibit-thread-switch t))
,@body))
A better one, yet still trivial, is
(defconst the-lock (make-lock))
(defmacro atomically (&rest body)
`(progn
(lock-grab the-lock)
(unwind-protect
(progn ,@body)
(lock-release the-lock))))
-- Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 19:07 ` Paul R
@ 2008-12-11 20:54 ` Stefan Monnier
0 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-11 20:54 UTC (permalink / raw
To: Paul R; +Cc: emacs-devel, rms, gscrivano
Stefan> Indeed. Further than that, we'd need more explicit
Stefan> synchronization primitives. We could probably start with
Stefan> a (atomically &rest BODY) which guarantees that BODY will be
Stefan> properly protected from other threads that it will appear to be
Stefan> executed atomically.
> Isn't it what critical sections are for ? (critical &rest BODY) would
> execute body with no thread switching. I think this feature is not
> necessary with cooperative-only threading because a critical section is
> any section that does not contain any 'yield' instruction.
We're talking about non-cooperative scenarios (e.g. yield in QUIT).
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-11 20:53 ` Stefan Monnier
@ 2008-12-12 19:03 ` Giuseppe Scrivano
2008-12-13 3:08 ` Stefan Monnier
0 siblings, 1 reply; 89+ messages in thread
From: Giuseppe Scrivano @ 2008-12-12 19:03 UTC (permalink / raw
To: Stefan Monnier; +Cc: Ted Zlatanov, emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> Yes, that makes sense. Hopefully, most functions are "safe" in
> this respect.
>
> BTW, implementing "atomically" is not necessarily that hard.
>
> Of course, it can be implemented with an "optimistic locking" discipline
> where we track changes and undo them if the transaction aborts, but
> until we get there, there are meny much simpler implementations which
> will be useful. A first implementation is
>
> (defmacro atomically (&rest body)
> `(let ((inhibit-thread-switch t))
> ,@body))
>
> A better one, yet still trivial, is
>
> (defconst the-lock (make-lock))
> (defmacro atomically (&rest body)
> `(progn
> (lock-grab the-lock)
> (unwind-protect
> (progn ,@body)
> (lock-release the-lock))))
>
IMHO the first is the better solution for a cooperative model. There is
only a thread active at a time, introduce lock/unlock can easily cause
deadlocks, at least for the current threads scheduler implementation.
We will need lock/unlock when we will use parallel threads and we must
protect critical sections.
Personally, I would avoid to introduce `atomically' now with a
cooperative model but I prefer instead an explicit `yield'. In this way
Elisp packages that use `yield' can benefit of threads and at the same
time it will not break old packages designed to work with a single
thread. Using `atomically' and hidden `yield's all around can break old
packages that don't know about threads.
On the other hand, my wish is to have an Emacs with parallel threads
someday, surely it will needs explicit threads synchronization and
`atomically' must be introduced in any case. It will break any Elisp
package that doesn't use where it is needed. If we introduce it now,
Elisp packages will probably work well later too.
These are the advantages/disadvantages we will have choosing explicit
yield or using atomically to inhibit thread switches. After all it is
just choose when "cause" problems in Elisp packages, now with
cooperative threads or later with parallel ones.
What do you think? Do you want to have `atomically' now?
Regards,
Giuseppe
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: multi-threaded Emacs
2008-12-12 19:03 ` Giuseppe Scrivano
@ 2008-12-13 3:08 ` Stefan Monnier
0 siblings, 0 replies; 89+ messages in thread
From: Stefan Monnier @ 2008-12-13 3:08 UTC (permalink / raw
To: Giuseppe Scrivano; +Cc: Ted Zlatanov, emacs-devel
> Personally, I would avoid to introduce `atomically' now with a
> cooperative model but I prefer instead an explicit `yield'.
It looks like I wasn't clear, but if you look back in this thread,
you'll see that I only mentioned `atomically' in the context of "when
explicit yields is not enough".
IOW I fully agree that explicit yields (plus some implicit ones when
waiting) are just fine for now.
Stefan
^ permalink raw reply [flat|nested] 89+ messages in thread
end of thread, other threads:[~2008-12-13 3:08 UTC | newest]
Thread overview: 89+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-29 13:32 multi-threaded Emacs Giuseppe Scrivano
2008-11-29 20:26 ` Stefan Monnier
2008-11-29 21:01 ` Giuseppe Scrivano
2008-11-29 22:21 ` Stefan Monnier
2008-11-30 11:35 ` Giuseppe Scrivano
2008-11-30 21:46 ` Stefan Monnier
2008-11-30 22:25 ` Giuseppe Scrivano
2008-11-30 23:03 ` Stefan Monnier
2008-11-30 23:30 ` Giuseppe Scrivano
2008-12-01 3:37 ` Stefan Monnier
2008-12-06 22:50 ` Tom Tromey
2008-12-07 3:31 ` Stefan Monnier
2008-11-29 22:06 ` Tom Tromey
2008-11-30 16:43 ` Richard M Stallman
2008-11-30 17:34 ` Giuseppe Scrivano
2008-11-30 21:51 ` Stefan Monnier
2008-11-30 22:10 ` Giuseppe Scrivano
2008-11-30 22:20 ` Miles Bader
2008-11-30 23:09 ` Stefan Monnier
2008-11-30 23:09 ` Giuseppe Scrivano
2008-12-01 0:10 ` Chetan Pandya
2008-12-01 3:55 ` Stefan Monnier
2008-12-01 14:06 ` Richard M Stallman
2008-12-01 18:57 ` Giuseppe Scrivano
2008-12-01 20:34 ` Stefan Monnier
2008-12-01 22:41 ` joakim
2008-12-02 16:02 ` Richard M Stallman
2008-12-02 22:22 ` Stefan Monnier
2008-12-02 22:41 ` Giuseppe Scrivano
2008-12-03 2:17 ` Stefan Monnier
2008-12-03 18:26 ` Giuseppe Scrivano
2008-12-03 20:14 ` Stefan Monnier
2008-12-05 2:59 ` Richard M Stallman
2008-12-05 7:40 ` Giuseppe Scrivano
2008-12-05 8:20 ` Miles Bader
2008-12-05 9:42 ` Paul R
2008-12-05 10:10 ` Eli Zaretskii
2008-12-05 10:35 ` Paul R
2008-12-05 11:02 ` Helmut Eller
2008-12-05 15:39 ` Stefan Monnier
2008-12-05 16:22 ` Ted Zlatanov
2008-12-05 16:57 ` Tom Tromey
2008-12-06 4:41 ` Miles Bader
2008-12-06 7:44 ` Helmut Eller
2008-12-06 22:31 ` Stefan Monnier
2008-12-06 8:30 ` Richard M Stallman
2008-12-05 15:36 ` Stefan Monnier
2008-12-06 19:25 ` Richard M Stallman
2008-12-06 22:41 ` Stefan Monnier
2008-12-06 23:41 ` Giuseppe Scrivano
2008-12-07 20:51 ` Stefan Monnier
2008-12-07 23:51 ` Giuseppe Scrivano
2008-12-08 3:06 ` Chetan Pandya
2008-12-08 15:50 ` Stefan Monnier
2008-12-07 16:02 ` Richard M Stallman
2008-12-07 20:52 ` Stefan Monnier
2008-12-07 16:15 ` Giuseppe Scrivano
2008-12-08 18:26 ` Richard M Stallman
2008-12-08 19:49 ` Giuseppe Scrivano
2008-12-09 2:15 ` dhruva
2008-12-09 2:49 ` Stephen J. Turnbull
2008-12-09 2:53 ` dhruva
2008-12-09 9:36 ` Andreas Schwab
2008-12-09 17:26 ` Richard M Stallman
2008-12-09 19:10 ` Giuseppe Scrivano
2008-12-10 18:18 ` Richard M Stallman
2008-12-10 18:18 ` Richard M Stallman
2008-12-09 19:40 ` Stefan Monnier
2008-12-10 18:18 ` Richard M Stallman
2008-12-11 1:59 ` Stefan Monnier
2008-12-11 14:41 ` Ted Zlatanov
2008-12-11 18:30 ` Stefan Monnier
2008-12-11 18:42 ` Ted Zlatanov
2008-12-11 19:01 ` Paul R
2008-12-11 20:53 ` Stefan Monnier
2008-12-12 19:03 ` Giuseppe Scrivano
2008-12-13 3:08 ` Stefan Monnier
2008-12-11 19:07 ` Paul R
2008-12-11 20:54 ` Stefan Monnier
2008-12-05 2:59 ` Richard M Stallman
2008-12-05 15:40 ` Stefan Monnier
2008-12-02 23:10 ` Florian Beck
2008-11-30 22:17 ` Miles Bader
2008-11-30 16:44 ` Richard M Stallman
-- strict thread matches above, loose matches on Subject: below --
2008-12-03 7:59 Re[2]: " ak70
2008-12-04 8:45 ` Richard M Stallman
[not found] ` <87prk8mhg9.fsf@vanilla.net.mt>
[not found] ` <E1L8ZUB-0002x3-VT@fencepost.gnu.org>
2008-12-05 13:27 ` Li Lin
[not found] ` <87prk64ilv.fsf@vanilla.net.mt>
2008-12-05 18:37 ` Giuseppe Scrivano
2008-12-06 21:58 ` Magnus Henoch
2008-12-04 13:21 ` Stefan Monnier
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.