aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTom Tromey2012-08-15 13:11:22 -0600
committerTom Tromey2012-08-15 13:11:22 -0600
commit51100bb8d36f68842ab55fd0501af56dfc58cc51 (patch)
tree6c94b7f893304276b43c57bd12eff92d914a7cd2 /src
parent1dcacbc64721b1a4de58aa36460b0a39e766be63 (diff)
downloademacs-51100bb8d36f68842ab55fd0501af56dfc58cc51.tar.gz
emacs-51100bb8d36f68842ab55fd0501af56dfc58cc51.zip
This supplies the mutex implementation for Emacs Lisp.
A lisp mutex is implemented using a condition variable, so that we can interrupt a mutex-lock operation by calling thread-signal on the blocking thread. I did things this way because pthread_mutex_lock can't readily be interrupted.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c2
-rw-r--r--src/data.c15
-rw-r--r--src/lisp.h9
-rw-r--r--src/print.c8
-rw-r--r--src/thread.c83
-rw-r--r--src/thread.h3
6 files changed, 117 insertions, 3 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 69742a325d1..80d22d61d66 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3104,6 +3104,8 @@ sweep_vectors (void)
3104 3104
3105 if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD)) 3105 if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD))
3106 finalize_one_thread ((struct thread_state *) vector); 3106 finalize_one_thread ((struct thread_state *) vector);
3107 else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MUTEX))
3108 finalize_one_mutex ((struct Lisp_Mutex *) vector);
3107 3109
3108 next = ADVANCE (vector, nbytes); 3110 next = ADVANCE (vector, nbytes);
3109 3111
diff --git a/src/data.c b/src/data.c
index fd2194fe1ae..b47c2d12aff 100644
--- a/src/data.c
+++ b/src/data.c
@@ -94,7 +94,7 @@ static Lisp_Object Qchar_table, Qbool_vector, Qhash_table;
94static Lisp_Object Qsubrp, Qmany, Qunevalled; 94static Lisp_Object Qsubrp, Qmany, Qunevalled;
95Lisp_Object Qfont_spec, Qfont_entity, Qfont_object; 95Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;
96static Lisp_Object Qdefun; 96static Lisp_Object Qdefun;
97Lisp_Object Qthread; 97Lisp_Object Qthread, Qmutex;
98 98
99Lisp_Object Qinteractive_form; 99Lisp_Object Qinteractive_form;
100 100
@@ -214,6 +214,8 @@ for example, (type-of 1) returns `integer'. */)
214 return Qfont_object; 214 return Qfont_object;
215 if (THREADP (object)) 215 if (THREADP (object))
216 return Qthread; 216 return Qthread;
217 if (MUTEXP (object))
218 return Qmutex;
217 return Qvector; 219 return Qvector;
218 220
219 case Lisp_Float: 221 case Lisp_Float:
@@ -471,6 +473,15 @@ DEFUN ("threadp", Fthreadp, Sthreadp, 1, 1, 0,
471 return Qnil; 473 return Qnil;
472} 474}
473 475
476DEFUN ("mutexp", Fmutexp, Smutexp, 1, 1, 0,
477 doc: /* Return t if OBJECT is a mutex. */)
478 (Lisp_Object object)
479{
480 if (MUTEXP (object))
481 return Qt;
482 else
483 return Qnil;
484}
474 485
475/* Extract and set components of lists */ 486/* Extract and set components of lists */
476 487
@@ -3105,6 +3116,7 @@ syms_of_data (void)
3105 DEFSYM (Qbool_vector, "bool-vector"); 3116 DEFSYM (Qbool_vector, "bool-vector");
3106 DEFSYM (Qhash_table, "hash-table"); 3117 DEFSYM (Qhash_table, "hash-table");
3107 DEFSYM (Qthread, "thread"); 3118 DEFSYM (Qthread, "thread");
3119 DEFSYM (Qmutex, "mutex");
3108 /* Used by Fgarbage_collect. */ 3120 /* Used by Fgarbage_collect. */
3109 DEFSYM (Qinterval, "interval"); 3121 DEFSYM (Qinterval, "interval");
3110 DEFSYM (Qmisc, "misc"); 3122 DEFSYM (Qmisc, "misc");
@@ -3148,6 +3160,7 @@ syms_of_data (void)
3148 defsubr (&Sbyte_code_function_p); 3160 defsubr (&Sbyte_code_function_p);
3149 defsubr (&Schar_or_string_p); 3161 defsubr (&Schar_or_string_p);
3150 defsubr (&Sthreadp); 3162 defsubr (&Sthreadp);
3163 defsubr (&Smutexp);
3151 defsubr (&Scar); 3164 defsubr (&Scar);
3152 defsubr (&Scdr); 3165 defsubr (&Scdr);
3153 defsubr (&Scar_safe); 3166 defsubr (&Scar_safe);
diff --git a/src/lisp.h b/src/lisp.h
index 52a523259db..f0c831852f6 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -366,6 +366,7 @@ enum pvec_type
366 PVEC_SUBR, 366 PVEC_SUBR,
367 PVEC_OTHER, 367 PVEC_OTHER,
368 PVEC_THREAD, 368 PVEC_THREAD,
369 PVEC_MUTEX,
369 /* These last 4 are special because we OR them in fns.c:internal_equal, 370 /* These last 4 are special because we OR them in fns.c:internal_equal,
370 so they have to use a disjoint bit pattern: 371 so they have to use a disjoint bit pattern:
371 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE 372 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE
@@ -555,6 +556,7 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
555 ((struct Lisp_Bool_Vector *) \ 556 ((struct Lisp_Bool_Vector *) \
556 XUNTAG (a, Lisp_Vectorlike))) 557 XUNTAG (a, Lisp_Vectorlike)))
557#define XTHREAD(a) (eassert (THREADP (a)), (struct thread_state *) XPNTR(a)) 558#define XTHREAD(a) (eassert (THREADP (a)), (struct thread_state *) XPNTR(a))
559#define XMUTEX(a) (eassert (MUTEXP (a)), (struct Lisp_Mutex *) XPNTR(a))
558 560
559/* Construct a Lisp_Object from a value or address. */ 561/* Construct a Lisp_Object from a value or address. */
560 562
@@ -606,6 +608,7 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper)
606#define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR)) 608#define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
607#define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE)) 609#define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE))
608#define XSETTHREAD(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_THREAD)) 610#define XSETTHREAD(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_THREAD))
611#define XSETMUTEX(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_MUTEX))
609 612
610/* Convenience macros for dealing with Lisp arrays. */ 613/* Convenience macros for dealing with Lisp arrays. */
611 614
@@ -1705,6 +1708,7 @@ typedef struct {
1705#define BOOL_VECTOR_P(x) PSEUDOVECTORP (x, PVEC_BOOL_VECTOR) 1708#define BOOL_VECTOR_P(x) PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
1706#define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME) 1709#define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME)
1707#define THREADP(x) PSEUDOVECTORP (x, PVEC_THREAD) 1710#define THREADP(x) PSEUDOVECTORP (x, PVEC_THREAD)
1711#define MUTEXP(x) PSEUDOVECTORP (x, PVEC_MUTEX)
1708 1712
1709/* Test for image (image . spec) */ 1713/* Test for image (image . spec) */
1710#define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage)) 1714#define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage))
@@ -1826,6 +1830,9 @@ typedef struct {
1826#define CHECK_THREAD(x) \ 1830#define CHECK_THREAD(x) \
1827 CHECK_TYPE (THREADP (x), Qthreadp, x) 1831 CHECK_TYPE (THREADP (x), Qthreadp, x)
1828 1832
1833#define CHECK_MUTEX(x) \
1834 CHECK_TYPE (MUTEXP (x), Qmutexp, x)
1835
1829/* Since we can't assign directly to the CAR or CDR fields of a cons 1836/* Since we can't assign directly to the CAR or CDR fields of a cons
1830 cell, use these when checking that those fields contain numbers. */ 1837 cell, use these when checking that those fields contain numbers. */
1831#define CHECK_NUMBER_CAR(x) \ 1838#define CHECK_NUMBER_CAR(x) \
@@ -2448,7 +2455,7 @@ extern Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp;
2448extern Lisp_Object Qbuffer_or_string_p; 2455extern Lisp_Object Qbuffer_or_string_p;
2449extern Lisp_Object Qfboundp; 2456extern Lisp_Object Qfboundp;
2450extern Lisp_Object Qchar_table_p, Qvector_or_char_table_p; 2457extern Lisp_Object Qchar_table_p, Qvector_or_char_table_p;
2451extern Lisp_Object Qthreadp; 2458extern Lisp_Object Qthreadp, Qmutexp;
2452 2459
2453extern Lisp_Object Qcdr; 2460extern Lisp_Object Qcdr;
2454 2461
diff --git a/src/print.c b/src/print.c
index 4537521b9fa..42e7241ecba 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1955,6 +1955,14 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag
1955 } 1955 }
1956 PRINTCHAR ('>'); 1956 PRINTCHAR ('>');
1957 } 1957 }
1958 else if (MUTEXP (obj))
1959 {
1960 int len;
1961 strout ("#<mutex ", -1, -1, printcharfun);
1962 len = sprintf (buf, "%p", XMUTEX (obj));
1963 strout (buf, len, len, printcharfun);
1964 PRINTCHAR ('>');
1965 }
1958 else 1966 else
1959 { 1967 {
1960 ptrdiff_t size = ASIZE (obj); 1968 ptrdiff_t size = ASIZE (obj);
diff --git a/src/thread.c b/src/thread.c
index 5da2e10f1ae..80557e5d5ee 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -35,7 +35,83 @@ static struct thread_state *all_threads = &primary_thread;
35 35
36sys_mutex_t global_lock; 36sys_mutex_t global_lock;
37 37
38Lisp_Object Qthreadp; 38Lisp_Object Qthreadp, Qmutexp;
39
40
41
42struct Lisp_Mutex
43{
44 struct vectorlike_header header;
45
46 lisp_mutex_t mutex;
47};
48
49DEFUN ("make-mutex", Fmake_mutex, Smake_mutex, 0, 0, 0,
50 doc: /* FIXME */)
51 (void)
52{
53 struct Lisp_Mutex *mutex;
54 Lisp_Object result;
55
56 mutex = ALLOCATE_PSEUDOVECTOR (struct Lisp_Mutex, mutex, PVEC_MUTEX);
57 memset ((char *) mutex + offsetof (struct Lisp_Mutex, mutex),
58 0, sizeof (struct Lisp_Mutex) - offsetof (struct Lisp_Mutex,
59 mutex));
60 lisp_mutex_init (&mutex->mutex);
61
62 XSETMUTEX (result, mutex);
63 return result;
64}
65
66static void
67mutex_lock_callback (void *arg)
68{
69 struct Lisp_Mutex *mutex = arg;
70
71 /* This calls post_acquire_global_lock. */
72 lisp_mutex_lock (&mutex->mutex);
73}
74
75DEFUN ("mutex-lock", Fmutex_lock, Smutex_lock, 1, 1, 0,
76 doc: /* FIXME */)
77 (Lisp_Object obj)
78{
79 struct Lisp_Mutex *mutex;
80
81 CHECK_MUTEX (obj);
82 mutex = XMUTEX (obj);
83
84 flush_stack_call_func (mutex_lock_callback, mutex);
85 return Qnil;
86}
87
88static void
89mutex_unlock_callback (void *arg)
90{
91 struct Lisp_Mutex *mutex = arg;
92
93 /* This calls post_acquire_global_lock. */
94 lisp_mutex_unlock (&mutex->mutex);
95}
96
97DEFUN ("mutex-unlock", Fmutex_unlock, Smutex_unlock, 1, 1, 0,
98 doc: /* FIXME */)
99 (Lisp_Object obj)
100{
101 struct Lisp_Mutex *mutex;
102
103 CHECK_MUTEX (obj);
104 mutex = XMUTEX (obj);
105
106 flush_stack_call_func (mutex_unlock_callback, mutex);
107 return Qnil;
108}
109
110void
111finalize_one_mutex (struct Lisp_Mutex *mutex)
112{
113 lisp_mutex_destroy (&mutex->mutex);
114}
39 115
40 116
41 117
@@ -463,7 +539,12 @@ syms_of_threads (void)
463 defsubr (&Sthread_alive_p); 539 defsubr (&Sthread_alive_p);
464 defsubr (&Sthread_join); 540 defsubr (&Sthread_join);
465 defsubr (&Sall_threads); 541 defsubr (&Sall_threads);
542 defsubr (&Smake_mutex);
543 defsubr (&Smutex_lock);
544 defsubr (&Smutex_unlock);
466 545
467 Qthreadp = intern_c_string ("threadp"); 546 Qthreadp = intern_c_string ("threadp");
468 staticpro (&Qthreadp); 547 staticpro (&Qthreadp);
548 Qmutexp = intern_c_string ("mutexp");
549 staticpro (&Qmutexp);
469} 550}
diff --git a/src/thread.h b/src/thread.h
index 3b533316817..d3ec38a22b9 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -168,6 +168,8 @@ struct thread_state
168 struct thread_state *next_thread; 168 struct thread_state *next_thread;
169}; 169};
170 170
171struct Lisp_Mutex;
172
171extern struct thread_state *current_thread; 173extern struct thread_state *current_thread;
172 174
173extern sys_mutex_t global_lock; 175extern sys_mutex_t global_lock;
@@ -175,6 +177,7 @@ extern void post_acquire_global_lock (struct thread_state *);
175 177
176extern void unmark_threads (void); 178extern void unmark_threads (void);
177extern void finalize_one_thread (struct thread_state *state); 179extern void finalize_one_thread (struct thread_state *state);
180extern void finalize_one_mutex (struct Lisp_Mutex *);
178 181
179extern void init_threads_once (void); 182extern void init_threads_once (void);
180extern void init_threads (void); 183extern void init_threads (void);