diff options
| author | Tom Tromey | 2012-08-15 13:03:17 -0600 |
|---|---|---|
| committer | Tom Tromey | 2012-08-15 13:03:17 -0600 |
| commit | 14b3dc5e4f2cdefde1ba04ddd3525115e7ca7dce (patch) | |
| tree | af04882e838fea858d9672dac6c19eab374505b9 /src/systhread.c | |
| parent | 2d525b793f1b0fd2b6f66881310bec8684bceffe (diff) | |
| download | emacs-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.c | 189 |
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 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 3 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along 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 | |||
| 27 | void | ||
| 28 | sys_mutex_init (sys_mutex_t *mutex) | ||
| 29 | { | ||
| 30 | pthread_mutex_init (mutex, NULL); | ||
| 31 | } | ||
| 32 | |||
| 33 | void | ||
| 34 | sys_mutex_lock (sys_mutex_t *mutex) | ||
| 35 | { | ||
| 36 | pthread_mutex_lock (mutex); | ||
| 37 | } | ||
| 38 | |||
| 39 | void | ||
| 40 | sys_mutex_unlock (sys_mutex_t *mutex) | ||
| 41 | { | ||
| 42 | pthread_mutex_unlock (mutex); | ||
| 43 | } | ||
| 44 | |||
| 45 | void | ||
| 46 | sys_mutex_destroy (sys_mutex_t *mutex) | ||
| 47 | { | ||
| 48 | pthread_mutex_destroy (mutex); | ||
| 49 | } | ||
| 50 | |||
| 51 | void | ||
| 52 | sys_cond_init (sys_cond_t *cond) | ||
| 53 | { | ||
| 54 | pthread_cond_init (cond, NULL); | ||
| 55 | } | ||
| 56 | |||
| 57 | void | ||
| 58 | sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex) | ||
| 59 | { | ||
| 60 | pthread_cond_wait (cond, mutex); | ||
| 61 | } | ||
| 62 | |||
| 63 | void | ||
| 64 | sys_cond_signal (sys_cond_t *cond) | ||
| 65 | { | ||
| 66 | pthread_cond_signal (cond); | ||
| 67 | } | ||
| 68 | |||
| 69 | void | ||
| 70 | sys_cond_broadcast (sys_cond_t *cond) | ||
| 71 | { | ||
| 72 | pthread_cond_broadcast (cond); | ||
| 73 | } | ||
| 74 | |||
| 75 | void | ||
| 76 | sys_cond_destroy (sys_cond_t *cond) | ||
| 77 | { | ||
| 78 | pthread_cond_destroy (cond); | ||
| 79 | } | ||
| 80 | |||
| 81 | void | ||
| 82 | lisp_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 | |||
| 90 | void | ||
| 91 | lisp_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 | |||
| 126 | void | ||
| 127 | lisp_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 | |||
| 143 | void | ||
| 144 | lisp_mutex_destroy (lisp_mutex_t *mutex) | ||
| 145 | { | ||
| 146 | sys_cond_destroy (&mutex->condition); | ||
| 147 | } | ||
| 148 | |||
| 149 | sys_thread_t | ||
| 150 | sys_thread_self (void) | ||
| 151 | { | ||
| 152 | return pthread_self (); | ||
| 153 | } | ||
| 154 | |||
| 155 | int | ||
| 156 | sys_thread_equal (sys_thread_t one, sys_thread_t two) | ||
| 157 | { | ||
| 158 | return pthread_equal (one, two); | ||
| 159 | } | ||
| 160 | |||
| 161 | int | ||
| 162 | sys_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 | |||
| 179 | void | ||
| 180 | sys_thread_yield (void) | ||
| 181 | { | ||
| 182 | sched_yield (); | ||
| 183 | } | ||
| 184 | |||
| 185 | #else | ||
| 186 | |||
| 187 | #error port me | ||
| 188 | |||
| 189 | #endif | ||