aboutsummaryrefslogtreecommitdiffstats
path: root/src/systhread.c
diff options
context:
space:
mode:
authorTom Tromey2012-08-15 13:03:17 -0600
committerTom Tromey2012-08-15 13:03:17 -0600
commit14b3dc5e4f2cdefde1ba04ddd3525115e7ca7dce (patch)
treeaf04882e838fea858d9672dac6c19eab374505b9 /src/systhread.c
parent2d525b793f1b0fd2b6f66881310bec8684bceffe (diff)
downloademacs-14b3dc5e4f2cdefde1ba04ddd3525115e7ca7dce.tar.gz
emacs-14b3dc5e4f2cdefde1ba04ddd3525115e7ca7dce.zip
This introduces the low-level system threading support. It also adds
the global lock. The low-level support is a bit over-eager, in that even at the end of the present series, it will not all be used. I think thiat is ok since I plan to use it all eventually -- in particular for the emacs lisp mutex implementation. I've only implemented the pthreads-based version. I think it should be relatively clear how to port this to other systems, though. I'd also like to do a "no threads" port that will turn most things into no-ops, and have thread-creation fail. I was thinking perhaps I'd make a future (provide 'threads) conditional on threads actually working. One other minor enhancement available here is to make it possible to set the name of the new thread at the OS layer. That way gdb, e.g., could display thread names.
Diffstat (limited to 'src/systhread.c')
-rw-r--r--src/systhread.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/systhread.c b/src/systhread.c
new file mode 100644
index 00000000000..b7147c4fc95
--- /dev/null
+++ b/src/systhread.c
@@ -0,0 +1,189 @@
1/* System thread definitions
2 Copyright (C) 2012 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19#include <config.h>
20#include <setjmp.h>
21#include "lisp.h"
22
23#ifdef HAVE_PTHREAD
24
25#include <sched.h>
26
27void
28sys_mutex_init (sys_mutex_t *mutex)
29{
30 pthread_mutex_init (mutex, NULL);
31}
32
33void
34sys_mutex_lock (sys_mutex_t *mutex)
35{
36 pthread_mutex_lock (mutex);
37}
38
39void
40sys_mutex_unlock (sys_mutex_t *mutex)
41{
42 pthread_mutex_unlock (mutex);
43}
44
45void
46sys_mutex_destroy (sys_mutex_t *mutex)
47{
48 pthread_mutex_destroy (mutex);
49}
50
51void
52sys_cond_init (sys_cond_t *cond)
53{
54 pthread_cond_init (cond, NULL);
55}
56
57void
58sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
59{
60 pthread_cond_wait (cond, mutex);
61}
62
63void
64sys_cond_signal (sys_cond_t *cond)
65{
66 pthread_cond_signal (cond);
67}
68
69void
70sys_cond_broadcast (sys_cond_t *cond)
71{
72 pthread_cond_broadcast (cond);
73}
74
75void
76sys_cond_destroy (sys_cond_t *cond)
77{
78 pthread_cond_destroy (cond);
79}
80
81void
82lisp_mutex_init (lisp_mutex_t *mutex)
83{
84 mutex->owner = NULL;
85 mutex->count = 0;
86 /* A lisp "mutex" is really a condition variable. */
87 pthread_cond_init (&mutex->condition, NULL);
88}
89
90void
91lisp_mutex_lock (lisp_mutex_t *mutex)
92{
93 struct thread_state *self;
94
95 if (mutex->owner == NULL)
96 {
97 mutex->owner = current_thread;
98 mutex->count = 1;
99 return;
100 }
101 if (mutex->owner == current_thread)
102 {
103 ++mutex->count;
104 return;
105 }
106
107 self = current_thread;
108 while (mutex->owner != NULL /* && EQ (self->error_symbol, Qnil) */)
109 pthread_cond_wait (&mutex->condition, &global_lock);
110
111#if 0
112 if (!EQ (self->error_symbol, Qnil))
113 {
114 Lisp_Object error_symbol = self->error_symbol;
115 Lisp_Object data = self->error_data;
116 self->error_symbol = Qnil;
117 self->error_data = Qnil;
118 Fsignal (error_symbol, error_data);
119 }
120#endif
121
122 mutex->owner = self;
123 mutex->count = 1;
124}
125
126void
127lisp_mutex_unlock (lisp_mutex_t *mutex)
128{
129 struct thread_state *self = current_thread;
130
131 if (mutex->owner != current_thread)
132 error ("blah");
133
134 if (--mutex->count > 0)
135 return;
136
137 mutex->owner = NULL;
138 pthread_cond_broadcast (&mutex->condition);
139
140 post_acquire_global_lock (self);
141}
142
143void
144lisp_mutex_destroy (lisp_mutex_t *mutex)
145{
146 sys_cond_destroy (&mutex->condition);
147}
148
149sys_thread_t
150sys_thread_self (void)
151{
152 return pthread_self ();
153}
154
155int
156sys_thread_equal (sys_thread_t one, sys_thread_t two)
157{
158 return pthread_equal (one, two);
159}
160
161int
162sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
163 void *arg)
164{
165 pthread_attr_t attr;
166 int result = 0;
167
168 if (pthread_attr_init (&attr))
169 return 0;
170
171 if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
172 result = pthread_create (thread_ptr, &attr, func, arg) == 0;
173
174 pthread_attr_destroy (&attr);
175
176 return result;
177}
178
179void
180sys_thread_yield (void)
181{
182 sched_yield ();
183}
184
185#else
186
187#error port me
188
189#endif