diff options
author | Tino Calancha <tino.calancha@gmail.com> | 2016-12-10 23:04:12 +0900 |
---|---|---|
committer | Tino Calancha <tino.calancha@gmail.com> | 2016-12-10 23:04:12 +0900 |
commit | ae31a7fac5c1cb8d5d3cb3238d15a5e3b791fd69 (patch) | |
tree | 2dd1b0284abcc06c0d80500d6d8e86505ec05130 | |
parent | afd162d0d782a4889e0c99dc3458a66e36da7cd4 (diff) | |
parent | 828b4560cd4a0d8cb9b7a7a3e20ff0c53ba86cfa (diff) | |
download | emacs-test-concurrency.tar.gz |
Merge with remote reptest-concurrency
-rw-r--r-- | doc/lispref/elisp.texi | 3 | ||||
-rw-r--r-- | doc/lispref/objects.texi | 69 | ||||
-rw-r--r-- | src/lisp.h | 2 | ||||
-rw-r--r-- | src/regex.c | 1 | ||||
-rw-r--r-- | src/thread.c | 71 | ||||
-rw-r--r-- | src/xgselect.c | 3 |
6 files changed, 114 insertions, 35 deletions
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi index 415dbe66fac..4a53a0cd364 100644 --- a/doc/lispref/elisp.texi +++ b/doc/lispref/elisp.texi @@ -349,6 +349,9 @@ Editing Types * Window Configuration Type:: Recording the way a frame is subdivided. * Frame Configuration Type:: Recording the status of all frames. * Process Type:: A subprocess of Emacs running on the underlying OS. +* Thread Type:: A thread of Emacs Lisp execution. +* Mutex Type:: An exclusive lock for thread synchronization. +* Condition Variable Type:: Condition variable for thread synchronization. * Stream Type:: Receive or send characters. * Keymap Type:: What function a keystroke invokes. * Overlay Type:: How an overlay is represented. diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index a76fbb1af7f..5e608bcc093 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -1410,6 +1410,9 @@ editing. * Window Configuration Type:: Recording the way a frame is subdivided. * Frame Configuration Type:: Recording the status of all frames. * Process Type:: A subprocess of Emacs running on the underlying OS. +* Thread Type:: A thread of Emacs Lisp execution. +* Mutex Type:: An exclusive lock for thread synchronization. +* Condition Variable Type:: Condition variable for thread synchronization. * Stream Type:: Receive or send characters. * Keymap Type:: What function a keystroke invokes. * Overlay Type:: How an overlay is represented. @@ -1625,6 +1628,63 @@ giving the name of the process: return information about, send input or signals to, and receive output from processes. +@node Thread Type +@subsection Thread Type + + A @dfn{thread} in Emacs represents a separate thread of Emacs Lisp +execution. It runs its own Lisp program, has its own current buffer, +and can have subprocesses locked to it, i.e.@: subprocesses whose +output only this thread can accept. @xref{Threads}. + + Thread objects have no read syntax. They print in hash notation, +giving the name of the thread (if it has been given a name) or its +address in core: + +@example +@group +(all-threads) + @result{} (#<thread 0176fc40>) +@end group +@end example + +@node Mutex Type +@subsection Mutex Type + + A @dfn{mutex} is an exclusive lock that threads can own and disown, +in order to synchronize between them. @xref{Mutexes}. + + Mutex objects have no read syntax. They print in hash notation, +giving the name of the mutex (if it has been given a name) or its +address in core: + +@example +@group +(make-mutex "my-mutex") + @result{} #<mutex my-mutex> +(make-mutex) + @result{} #<mutex 01c7e4e0> +@end group +@end example + +@node Condition Variable Type +@subsection Condition Variable Type + + A @dfn{condition variable} is a device for a more complex thread +synchronization than the one supported by a mutex. A thread can wait +on a condition variable, to be woken up when some other thread +notifies the condition. + + Condition variable objects have no read syntax. They print in hash +notation, giving the name of the condition variable (if it has been +given a name) or its address in core: + +@example +@group +(make-condition-variable (make-mutex)) + @result{} #<condvar 01c45ae8> +@end group +@end example + @node Stream Type @subsection Stream Type @@ -1830,6 +1890,9 @@ with references to further information. @item commandp @xref{Interactive Call, commandp}. +@item condition-variable-p +@xref{Condition Variables, condition-variable-p}. + @item consp @xref{List-related Predicates, consp}. @@ -1875,6 +1938,9 @@ with references to further information. @item markerp @xref{Predicates on Markers, markerp}. +@item mutexp +@xref{Mutexes, mutexp}. + @item wholenump @xref{Predicates on Numbers, wholenump}. @@ -1908,6 +1974,9 @@ with references to further information. @item syntax-table-p @xref{Syntax Tables, syntax-table-p}. +@item threadp +@xref{Basic Thread Functions, threadp}. + @item vectorp @xref{Vectors, vectorp}. diff --git a/src/lisp.h b/src/lisp.h index 72ea50d5f27..3c7c3dde904 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -845,6 +845,7 @@ enum pvec_type PVEC_THREAD, PVEC_MUTEX, PVEC_CONDVAR, + /* These should be last, check internal_equal to see why. */ PVEC_COMPILED, PVEC_CHAR_TABLE, @@ -3229,6 +3230,7 @@ union specbinding } bt; }; +/* These 3 are defined as macros in thread.h. */ /* extern union specbinding *specpdl; */ /* extern union specbinding *specpdl_ptr; */ /* extern ptrdiff_t specpdl_size; */ diff --git a/src/regex.c b/src/regex.c index e7231d3882b..f1686cf700c 100644 --- a/src/regex.c +++ b/src/regex.c @@ -1140,6 +1140,7 @@ print_double_string (re_char *where, re_char *string1, ssize_t size1, #endif /* not DEBUG */ #ifndef emacs + /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ diff --git a/src/thread.c b/src/thread.c index dda262984c0..ae2ce3dc02b 100644 --- a/src/thread.c +++ b/src/thread.c @@ -144,7 +144,7 @@ static int lisp_mutex_unlock (lisp_mutex_t *mutex) { if (mutex->owner != current_thread) - error ("blah"); + error ("Cannot unlock mutex owned by another thread"); if (--mutex->count > 0) return 0; @@ -301,7 +301,7 @@ finalize_one_mutex (struct Lisp_Mutex *mutex) DEFUN ("make-condition-variable", Fmake_condition_variable, Smake_condition_variable, 1, 2, 0, - doc: /* Make a condition variable. + doc: /* Make a condition variable associated with MUTEX. A condition variable provides a way for a thread to sleep while waiting for a state change. @@ -355,27 +355,27 @@ condition_wait_callback (void *arg) } DEFUN ("condition-wait", Fcondition_wait, Scondition_wait, 1, 1, 0, - doc: /* Wait for the condition variable to be notified. -CONDITION is the condition variable to wait on. + doc: /* Wait for the condition variable COND to be notified. +COND is the condition variable to wait on. -The mutex associated with CONDITION must be held when this is called. +The mutex associated with COND must be held when this is called. It is an error if it is not held. -This releases the mutex and waits for CONDITION to be notified or for +This releases the mutex and waits for COND to be notified or for this thread to be signalled with `thread-signal'. When -`condition-wait' returns, the mutex will again be locked by this -thread. */) - (Lisp_Object condition) +`condition-wait' returns, COND's mutex will again be locked by +this thread. */) + (Lisp_Object cond) { struct Lisp_CondVar *cvar; struct Lisp_Mutex *mutex; - CHECK_CONDVAR (condition); - cvar = XCONDVAR (condition); + CHECK_CONDVAR (cond); + cvar = XCONDVAR (cond); mutex = XMUTEX (cvar->mutex); if (!lisp_mutex_owned_p (&mutex->mutex)) - error ("fixme"); + error ("Condition variable's mutex is not held by current thread"); flush_stack_call_func (condition_wait_callback, cvar); @@ -409,28 +409,28 @@ condition_notify_callback (void *arg) } DEFUN ("condition-notify", Fcondition_notify, Scondition_notify, 1, 2, 0, - doc: /* Notify a condition variable. -This wakes a thread waiting on CONDITION. + doc: /* Notify COND, a condition variable. +This wakes a thread waiting on COND. If ALL is non-nil, all waiting threads are awoken. -The mutex associated with CONDITION must be held when this is called. +The mutex associated with COND must be held when this is called. It is an error if it is not held. -This releases the mutex when notifying CONDITION. When +This releases COND's mutex when notifying COND. When `condition-notify' returns, the mutex will again be locked by this thread. */) - (Lisp_Object condition, Lisp_Object all) + (Lisp_Object cond, Lisp_Object all) { struct Lisp_CondVar *cvar; struct Lisp_Mutex *mutex; struct notify_args args; - CHECK_CONDVAR (condition); - cvar = XCONDVAR (condition); + CHECK_CONDVAR (cond); + cvar = XCONDVAR (cond); mutex = XMUTEX (cvar->mutex); if (!lisp_mutex_owned_p (&mutex->mutex)) - error ("fixme"); + error ("Condition variable's mutex is not held by current thread"); args.cvar = cvar; args.all = !NILP (all); @@ -440,26 +440,26 @@ thread. */) } DEFUN ("condition-mutex", Fcondition_mutex, Scondition_mutex, 1, 1, 0, - doc: /* Return the mutex associated with CONDITION. */) - (Lisp_Object condition) + doc: /* Return the mutex associated with condition variable COND. */) + (Lisp_Object cond) { struct Lisp_CondVar *cvar; - CHECK_CONDVAR (condition); - cvar = XCONDVAR (condition); + CHECK_CONDVAR (cond); + cvar = XCONDVAR (cond); return cvar->mutex; } DEFUN ("condition-name", Fcondition_name, Scondition_name, 1, 1, 0, - doc: /* Return the name of CONDITION. -If no name was given when CONDITION was created, return nil. */) - (Lisp_Object condition) + doc: /* Return the name of condition variable COND. +If no name was given when COND was created, return nil. */) + (Lisp_Object cond) { struct Lisp_CondVar *cvar; - CHECK_CONDVAR (condition); - cvar = XCONDVAR (condition); + CHECK_CONDVAR (cond); + cvar = XCONDVAR (cond); return cvar->name; } @@ -540,7 +540,7 @@ mark_one_thread (struct thread_state *thread) mark_object (thread->m_last_thing_searched); - if (thread->m_saved_last_thing_searched) + if (!NILP (thread->m_saved_last_thing_searched)) mark_object (thread->m_saved_last_thing_searched); } @@ -678,7 +678,7 @@ finalize_one_thread (struct thread_state *state) DEFUN ("make-thread", Fmake_thread, Smake_thread, 1, 2, 0, doc: /* Start a new thread and run FUNCTION in it. When the function exits, the thread dies. -If NAME is given, it names the new thread. */) +If NAME is given, it must be a string; it names the new thread. */) (Lisp_Object function, Lisp_Object name) { sys_thread_t thr; @@ -843,8 +843,9 @@ thread_join_callback (void *arg) } DEFUN ("thread-join", Fthread_join, Sthread_join, 1, 1, 0, - doc: /* Wait for a thread to exit. -This blocks the current thread until THREAD exits. + doc: /* Wait for THREAD to exit. +This blocks the current thread until THREAD exits or until +the current thread is signaled. It is an error for a thread to try to join itself. */) (Lisp_Object thread) { @@ -854,7 +855,7 @@ It is an error for a thread to try to join itself. */) tstate = XTHREAD (thread); if (tstate == current_thread) - error ("cannot join current thread"); + error ("Cannot join current thread"); if (thread_alive_p (tstate)) flush_stack_call_func (thread_join_callback, tstate); @@ -863,7 +864,7 @@ It is an error for a thread to try to join itself. */) } DEFUN ("all-threads", Fall_threads, Sall_threads, 0, 0, 0, - doc: /* Return a list of all threads. */) + doc: /* Return a list of all the live threads. */) (void) { Lisp_Object result = Qnil; diff --git a/src/xgselect.c b/src/xgselect.c index e418e1a3c4e..2f23764ae41 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -76,6 +76,9 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, if (gfds_size < n_gfds) { + /* Avoid using SAFE_NALLOCA, as that implicitly refers to the + current thread. Using xnmalloc avoids thread-switching + problems here. */ gfds = xnmalloc (n_gfds, sizeof *gfds); must_free = 1; gfds_size = n_gfds; |