Commit de4624c9 authored by Eli Zaretskii's avatar Eli Zaretskii

Merge branch 'concurrency'

Conflicts (resolved):
	configure.ac
	src/Makefile.in
	src/alloc.c
	src/bytecode.c
	src/emacs.c
	src/eval.c
	src/lisp.h
	src/process.c
	src/regex.c
	src/regex.h
parents a486fabb e7bde34e
......@@ -355,6 +355,7 @@ OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support])
OPTION_DEFAULT_OFF([modules],[compile with dynamic modules support])
OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support])
AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB],
[use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])],
......@@ -1643,7 +1644,7 @@ AC_CHECK_HEADERS_ONCE(
sys/sysinfo.h
coff.h pty.h
sys/resource.h
sys/utsname.h pwd.h utmp.h util.h)
sys/utsname.h pwd.h utmp.h util.h sys/prctl.h)
AC_CACHE_CHECK([for ADDR_NO_RANDOMIZE],
[emacs_cv_personality_addr_no_randomize],
......@@ -2305,6 +2306,22 @@ if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then
fi
AC_SUBST([LIB_PTHREAD])
AC_MSG_CHECKING([for thread support])
threads_enabled=no
if test "$with_threads" = yes; then
if test "$emacs_cv_pthread_lib" != no; then
AC_DEFINE(THREADS_ENABLED, 1,
[Define to 1 if you want elisp thread support.])
threads_enabled=yes
elif test "${opsys}" = "mingw32"; then
dnl MinGW can do native Windows threads even without pthreads
AC_DEFINE(THREADS_ENABLED, 1,
[Define to 1 if you want elisp thread support.])
threads_enabled=yes
fi
fi
AC_MSG_RESULT([$threads_enabled])
dnl Check for need for bigtoc support on IBM AIX
case ${host_os} in
......@@ -3871,7 +3888,7 @@ pthread_sigmask strsignal setitimer \
sendto recvfrom getsockname getifaddrs freeifaddrs \
gai_strerror sync \
getpwent endpwent getgrent endgrent \
cfmakeraw cfsetspeed copysign __executable_start log2)
cfmakeraw cfsetspeed copysign __executable_start log2 prctl)
LIBS=$OLD_LIBS
dnl No need to check for posix_memalign if aligned_alloc works.
......@@ -5314,6 +5331,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D
Does Emacs have dynamic modules support? ${HAVE_MODULES}
Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}
Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS}
Does Emacs have threading support in lisp? ${threads_enabled}
"])
if test -n "${EMACSDATA}"; then
......
......@@ -125,6 +125,7 @@ srcs = \
$(srcdir)/symbols.texi \
$(srcdir)/syntax.texi \
$(srcdir)/text.texi \
$(srcdir)/threads.texi \
$(srcdir)/tips.texi \
$(srcdir)/variables.texi \
$(srcdir)/windows.texi \
......
......@@ -219,6 +219,7 @@ To view this manual in other formats, click
* Syntax Tables:: The syntax table controls word and list parsing.
* Abbrevs:: How Abbrev mode works, and its data structures.
* Threads:: Concurrency in Emacs Lisp.
* Processes:: Running and communicating with subprocesses.
* Display:: Features for controlling the screen display.
* System Interface:: Getting the user id, system type, environment
......@@ -1322,6 +1323,12 @@ Abbrevs and Abbrev Expansion
* Abbrev Table Properties:: How to read and set abbrev table properties.
Which properties have which effect.
Threads
* Basic Thread Functions:: Basic thread functions.
* Mutexes:: Mutexes allow exclusive access to data.
* Condition Variables:: Inter-thread events.
Processes
* Subprocess Creation:: Functions that start subprocesses.
......@@ -1628,6 +1635,7 @@ Object Internals
@include searching.texi
@include syntax.texi
@include abbrevs.texi
@include threads.texi
@include processes.texi
@include display.texi
......
......@@ -1925,6 +1925,15 @@ with references to further information.
@item string-or-null-p
@xref{Predicates for Strings, string-or-null-p}.
@item threadp
@xref{Basic Thread Functions, threadp}.
@item mutexp
@xref{Mutexes, mutexp}.
@item condition-variable-p
@xref{Condition Variables, condition-variable-p}.
@end table
The most general way to check the type of an object is to call the
......@@ -1938,11 +1947,12 @@ types. In most cases, it is more convenient to use type predicates than
This function returns a symbol naming the primitive type of
@var{object}. The value is one of the symbols @code{bool-vector},
@code{buffer}, @code{char-table}, @code{compiled-function},
@code{cons}, @code{finalizer}, @code{float}, @code{font-entity},
@code{font-object}, @code{font-spec}, @code{frame}, @code{hash-table},
@code{integer}, @code{marker}, @code{overlay}, @code{process},
@code{string}, @code{subr}, @code{symbol}, @code{vector},
@code{window}, or @code{window-configuration}.
@code{condition-variable}, @code{cons}, @code{finalizer},
@code{float}, @code{font-entity}, @code{font-object},
@code{font-spec}, @code{frame}, @code{hash-table}, @code{integer},
@code{marker}, @code{mutex}, @code{overlay}, @code{process},
@code{string}, @code{subr}, @code{symbol}, @code{thread},
@code{vector}, @code{window}, or @code{window-configuration}.
@example
(type-of 1)
......
......@@ -1400,6 +1400,7 @@ Emacs tries to read it.
* Filter Functions:: Filter functions accept output from the process.
* Decoding Output:: Filters can get unibyte or multibyte strings.
* Accepting Output:: How to wait until process output arrives.
* Processes and Threads:: How processes and threads interact.
@end menu
@node Process Buffers
......@@ -1791,6 +1792,35 @@ got output from @var{process}, or from any process if @var{process} is
arrived.
@end defun
@node Processes and Threads
@subsection Processes and Threads
@cindex processes, threads
Because threads were a relatively late addition to Emacs Lisp, and
due to the way dynamic binding was sometimes used in conjunction with
@code{accept-process-output}, by default a process is locked to the
thread that created it. When a process is locked to a thread, output
from the process can only be accepted by that thread.
A Lisp program can specify to which thread a process is to be
locked, or instruct Emacs to unlock a process, in which case its
output can be processed by any thread. Only a single thread will wait
for output from a given process at one time---once one thread begins
waiting for output, the process is temporarily locked until
@code{accept-process-output} or @code{sit-for} returns.
If the thread exits, all the processes locked to it are unlocked.
@defun process-thread process
Return the thread to which @var{process} is locked. If @var{process}
is unlocked, return @code{nil}.
@end defun
@defun set-process-thread process thread
Set the locking thread of @var{process} to @var{thread}. @var{thread}
may be @code{nil}, in which case the process is unlocked.
@end defun
@node Sentinels
@section Sentinels: Detecting Process Status Changes
@cindex process sentinel
......
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
@c Copyright (C) 2012, 2013
@c Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Threads
@chapter Threads
@cindex threads
@cindex concurrency
Emacs Lisp provides a limited form of concurrency, called
@dfn{threads}. All the threads in a given instance of Emacs share the
same memory. Concurrency in Emacs Lisp is ``mostly cooperative'',
meaning that Emacs will only switch execution between threads at
well-defined times. However, the Emacs thread support has been
designed in a way to later allow more fine-grained concurrency, and
correct programs should not rely on cooperative threading.
Currently, thread switching will occur upon explicit request via
@code{thread-yield}, when waiting for keyboard input or for process
output (e.g., during @code{accept-process-output}), or during blocking
operations relating to threads, such as mutex locking or
@code{thread-join}.
Emacs Lisp provides primitives to create and control threads, and
also to create and control mutexes and condition variables, useful for
thread synchronization.
While global variables are shared among all Emacs Lisp threads,
local variables are not---a dynamic @code{let} binding is local. Each
thread also has its own current buffer (@pxref{Current Buffer}) and
its own match data (@pxref{Match Data}).
Note that @code{let} bindings are treated specially by the Emacs
Lisp implementation. There is no way to duplicate this unwinding and
rewinding behavior other than by using @code{let}. For example, a
manual implementation of @code{let} written using
@code{unwind-protect} cannot arrange for variable values to be
thread-specific.
In the case of lexical bindings (@pxref{Variable Scoping}), a
closure is an object like any other in Emacs Lisp, and bindings in a
closure are shared by any threads invoking the closure.
@menu
* Basic Thread Functions:: Basic thread functions.
* Mutexes:: Mutexes allow exclusive access to data.
* Condition Variables:: Inter-thread events.
@end menu
@node Basic Thread Functions
@section Basic Thread Functions
Threads can be created and waited for. A thread cannot be exited
directly, but the current thread can be exited implicitly, and other
threads can be signaled.
@defun make-thread function &optional name
Create a new thread of execution which invokes @var{function}. When
@var{function} returns, the thread exits.
The new thread is created with no local variable bindings in effect.
The new thread's current buffer is inherited from the current thread.
@var{name} can be supplied to give a name to the thread. The name is
used for debugging and informational purposes only; it has no meaning
to Emacs. If @var{name} is provided, it must be a string.
This function returns the new thread.
@end defun
@defun threadp object
This function returns @code{t} if @var{object} represents an Emacs
thread, @code{nil} otherwise.
@end defun
@defun thread-join thread
Block until @var{thread} exits, or until the current thread is
signaled. If @var{thread} has already exited, this returns
immediately.
@end defun
@defun thread-signal thread error-symbol data
Like @code{signal} (@pxref{Signaling Errors}), but the signal is
delivered in the thread @var{thread}. If @var{thread} is the current
thread, then this just calls @code{signal} immediately.
@code{thread-signal} will cause a thread to exit a call to
@code{mutex-lock}, @code{condition-wait}, or @code{thread-join}.
@end defun
@defun thread-yield
Yield execution to the next runnable thread.
@end defun
@defun thread-name thread
Return the name of @var{thread}, as specified to @code{make-thread}.
@end defun
@defun thread-alive-p thread
Return @code{t} if @var{thread} is alive, or @code{nil} if it is not.
A thread is alive as long as its function is still executing.
@end defun
@defun thread--blocker thread
Return the object that @var{thread} is waiting on. This function is
primarily intended for debugging, and is given a ``double hyphen''
name to indicate that.
If @var{thread} is blocked in @code{thread-join}, this returns the
thread for which it is waiting.
If @var{thread} is blocked in @code{mutex-lock}, this returns the mutex.
If @var{thread} is blocked in @code{condition-wait}, this returns the
condition variable.
Otherwise, this returns @code{nil}.
@end defun
@defun current-thread
Return the current thread.
@end defun
@defun all-threads
Return a list of all the live thread objects. A new list is returned
by each invocation.
@end defun
@node Mutexes
@section Mutexes
A @dfn{mutex} is an exclusive lock. At any moment, zero or one
threads may own a mutex. If a thread attempts to acquire a mutex, and
the mutex is already owned by some other thread, then the acquiring
thread will block until the mutex becomes available.
Emacs Lisp mutexes are of a type called @dfn{recursive}, which means
that a thread can re-acquire a mutex it owns any number of times. A
mutex keeps a count of how many times it has been acquired, and each
acquisition of a mutex must be paired with a release. The last
release by a thread of a mutex reverts it to the unowned state,
potentially allowing another thread to acquire the mutex.
@defun mutexp object
This function returns @code{t} if @var{object} represents an Emacs
mutex, @code{nil} otherwise.
@end defun
@defun make-mutex &optional name
Create a new mutex and return it. If @var{name} is specified, it is a
name given to the mutex. It must be a string. The name is for
debugging purposes only; it has no meaning to Emacs.
@end defun
@defun mutex-name mutex
Return the name of @var{mutex}, as specified to @code{make-mutex}.
@end defun
@defun mutex-lock mutex
This will block until this thread acquires @var{mutex}, or until this
thread is signaled using @code{thread-signal}. If @var{mutex} is
already owned by this thread, this simply returns.
@end defun
@defun mutex-unlock mutex
Release @var{mutex}. If @var{mutex} is not owned by this thread, this
will signal an error.
@end defun
@defmac with-mutex mutex body@dots{}
This macro is the simplest and safest way to evaluate forms while
holding a mutex. It acquires @var{mutex}, invokes @var{body}, and
then releases @var{mutex}. It returns the result of @var{body}.
@end defmac
@node Condition Variables
@section Condition Variables
A @dfn{condition variable} is a way for a thread to block until some
event occurs. A thread can wait on a condition variable, to be woken
up when some other thread notifies the condition.
A condition variable is associated with a mutex and, conceptually,
with some condition. For proper operation, the mutex must be
acquired, and then a waiting thread must loop, testing the condition
and waiting on the condition variable. For example:
@example
(with-mutex mutex
(while (not global-variable)
(condition-wait cond-var)))
@end example
The mutex ensures atomicity, and the loop is for robustness---there
may be spurious notifications.
Similarly, the mutex must be held before notifying the condition.
The typical, and best, approach is to acquire the mutex, make the
changes associated with this condition, and then notify it:
@example
(with-mutex mutex
(setq global-variable (some-computation))
(condition-notify cond-var))
@end example
@defun make-condition-variable mutex &optional name
Make a new condition variable associated with @var{mutex}. If
@var{name} is specified, it is a name given to the condition variable.
It must be a string. The name is for debugging purposes only; it has
no meaning to Emacs.
@end defun
@defun condition-variable-p object
This function returns @code{t} if @var{object} represents a condition
variable, @code{nil} otherwise.
@end defun
@defun condition-wait cond
Wait for another thread to notify @var{cond}, a condition variable.
This function will block until the condition is notified, or until a
signal is delivered to this thread using @code{thread-signal}.
It is an error to call @code{condition-wait} without holding the
condition's associated mutex.
@code{condition-wait} releases the associated mutex while waiting.
This allows other threads to acquire the mutex in order to notify the
condition.
@end defun
@defun condition-notify cond &optional all
Notify @var{cond}. The mutex with @var{cond} must be held before
calling this. Ordinarily a single waiting thread is woken by
@code{condition-notify}; but if @var{all} is not @code{nil}, then all
threads waiting on @var{cond} are notified.
@code{condition-notify} releases the associated mutex while waiting.
This allows other threads to acquire the mutex in order to wait on the
condition.
@c why bother?
@end defun
@defun condition-name cond
Return the name of @var{cond}, as passed to
@code{make-condition-variable}.
@end defun
@defun condition-mutex cond
Return the mutex associated with @var{cond}. Note that the associated
mutex cannot be changed.
@end defun
......@@ -313,7 +313,7 @@ type. Here are these commands:
xbufobjfwd xkbobjfwd xbuflocal xbuffer xsymbol xstring xvector xframe
xwinconfig xcompiled xcons xcar xcdr xsubr xprocess xfloat xscrollbar
xchartable xsubchartable xboolvector xhashtable xlist xcoding
xcharset xfontset xfont
xcharset xfontset xfont xbytecode
Each one of them applies to a certain type or class of types.
(Some of these types are not visible in Lisp, because they exist only
......
......@@ -4951,6 +4951,20 @@ as a list.")
(match-string 1 subdir) subdir))
"-pkg.el"))
;;; Thread support.
(defmacro with-mutex (mutex &rest body)
"Invoke BODY with MUTEX held, releasing MUTEX when done.
This is the simplest safe way to acquire and release a mutex."
(declare (indent 1) (debug t))
(let ((sym (make-symbol "mutex")))
`(let ((,sym ,mutex))
(mutex-lock ,sym)
(unwind-protect
(progn ,@body)
(mutex-unlock ,sym)))))
;;; Misc.
......
......@@ -53,6 +53,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <ws2tcpip.h>
/* process.c uses uint16_t (from C99) for IPv6, but
apparently it is not defined in some versions of mingw and msvc. */
#include <stdint.h>
#ifndef UINT16_C
typedef unsigned short uint16_t;
#endif
......
......@@ -1215,6 +1215,21 @@ document xwhichsymbols
maximum number of symbols referencing it to produce.
end
define xbytecode
set $bt = byte_stack_list
while $bt
xgetptr $bt->byte_string
set $ptr = (struct Lisp_String *) $ptr
xprintbytestr $ptr
printf "\n0x%x => ", $bt->byte_string
xwhichsymbols $bt->byte_string 5
set $bt = $bt->next
end
end
document xbytecode
Print a backtrace of the byte code stack.
end
# Show Lisp backtrace after normal backtrace.
define hookpost-backtrace
set $bt = backtrace_top ()
......
......@@ -409,6 +409,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
$(XWIDGETS_OBJ) \
profiler.o decompress.o \
thread.o systhread.o \
$(if $(HYBRID_MALLOC),sheap.o) \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
......
......@@ -438,10 +438,6 @@ struct mem_node
enum mem_type type;
};
/* Base address of stack. Set in main. */
Lisp_Object *stack_base;
/* Root of the tree describing allocated Lisp memory. */
static struct mem_node *mem_root;
......@@ -3190,8 +3186,7 @@ vector_nbytes (struct Lisp_Vector *v)
}
/* Release extra resources still in use by VECTOR, which may be any
vector-like object. For now, this is used just to free data in
font objects. */
vector-like object. */
static void
cleanup_vector (struct Lisp_Vector *vector)
......@@ -3212,6 +3207,13 @@ cleanup_vector (struct Lisp_Vector *vector)
drv->close ((struct font *) vector);
}
}
if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD))
finalize_one_thread ((struct thread_state *) vector);
else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MUTEX))
finalize_one_mutex ((struct Lisp_Mutex *) vector);
else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR))
finalize_one_condvar ((struct Lisp_CondVar *) vector);
}
/* Reclaim space used by unmarked vectors. */
......@@ -5047,14 +5049,13 @@ test_setjmp (void)
would be necessary, each one starting with one byte more offset
from the stack start. */
static void
mark_stack (void *end)
void
mark_stack (char *bottom, char *end)
{
/* This assumes that the stack is a contiguous region in memory. If
that's not the case, something has to be done here to iterate
over the stack segments. */
mark_memory (stack_base, end);
mark_memory (bottom, end);
/* Allow for marking a secondary stack, like the register stack on the
ia64. */
......@@ -5063,6 +5064,81 @@ mark_stack (void *end)
#endif
}
/* This is a trampoline function that flushes registers to the stack,
and then calls FUNC. ARG is passed through to FUNC verbatim.
This function must be called whenever Emacs is about to release the
global interpreter lock. This lets the garbage collector easily
find roots in registers on threads that are not actively running
Lisp.
It is invalid to run any Lisp code or to allocate any GC memory
from FUNC. */
void
flush_stack_call_func (void (*func) (void *arg), void *arg)
{
void *end;
struct thread_state *self = current_thread;
#ifdef HAVE___BUILTIN_UNWIND_INIT
/* Force callee-saved registers and register windows onto the stack.
This is the preferred method if available, obviating the need for
machine dependent methods. */
__builtin_unwind_init ();
end = &end;
#else /* not HAVE___BUILTIN_UNWIND_INIT */
#ifndef GC_SAVE_REGISTERS_ON_STACK
/* jmp_buf may not be aligned enough on darwin-ppc64 */
union aligned_jmpbuf {
Lisp_Object o;
sys_jmp_buf j;
} j;
volatile bool stack_grows_down_p = (char *) &j > (char *) stack_bottom;
#endif
/* This trick flushes the register windows so that all the state of
the process is contained in the stack. */
/* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is
needed on ia64 too. See mach_dep.c, where it also says inline
assembler doesn't work with relevant proprietary compilers. */
#ifdef __sparc__
#if defined (__sparc64__) && defined (__FreeBSD__)
/* FreeBSD does not have a ta 3 handler. */
asm ("flushw");
#else
asm ("ta 3");
#endif
#endif
/* Save registers that we need to see on the stack. We need to see
registers used to hold register variables and registers used to
pass parameters. */
#ifdef GC_SAVE_REGISTERS_ON_STACK
GC_SAVE_REGISTERS_ON_STACK (end);
#else /* not GC_SAVE_REGISTERS_ON_STACK */
#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that
setjmp will definitely work, test it
and print a message with the result
of the test. */
if (!setjmp_tested_p)
{
setjmp_tested_p = 1;
test_setjmp ();
}
#endif /* GC_SETJMP_WORKS */
sys_setjmp (j.j);
end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j;
#endif /* not GC_SAVE_REGISTERS_ON_STACK */
#endif /* not HAVE___BUILTIN_UNWIND_INIT */
self->stack_top = end;
(*func) (arg);
eassert (current_thread == self);
}
static bool
c_symbol_p (struct Lisp_Symbol *sym)
{
......@@ -5768,24 +5844,14 @@ garbage_collect_1 (void *end)
mark_object (*staticvec[i]);
mark_pinned_symbols ();
mark_specpdl ();
mark_terminals ();
mark_kboards ();
mark_threads ();
#ifdef USE_GTK
xg_mark_data ();
#endif
mark_stack (end);
{
struct handler *handler;
for (handler = handlerlist; handler; handler = handler->next)
{
mark_object (handler->tag_or_ch);
mark_object (handler->val);
}
}
#ifdef HAVE_WINDOW_SYSTEM
mark_fringe_data ();
#endif
......@@ -5817,6 +5883,8 @@ garbage_collect_1 (void *end)
gc_sweep ();
unmark_threads ();
/* Clear the mark bits that we set in certain root slots. */
VECTOR_UNMARK (&buffer_defaults);
VECTOR_UNMARK (&buffer_local_symbols);
......
......@@ -48,8 +48,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "w32heap.h" /* for mmap_* */
#endif