diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.in | 2 | ||||
| -rw-r--r-- | src/emacs.c | 1 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/systhread.c | 189 | ||||
| -rw-r--r-- | src/systhread.h | 80 | ||||
| -rw-r--r-- | src/thread.c | 9 | ||||
| -rw-r--r-- | src/thread.h | 4 |
7 files changed, 286 insertions, 1 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 2d1bdd097ef..01034ca98d5 100644 --- a/src/Makefile.in +++ b/src/Makefile.in | |||
| @@ -336,7 +336,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ | |||
| 336 | eval.o floatfns.o fns.o font.o print.o lread.o \ | 336 | eval.o floatfns.o fns.o font.o print.o lread.o \ |
| 337 | syntax.o $(UNEXEC_OBJ) bytecode.o \ | 337 | syntax.o $(UNEXEC_OBJ) bytecode.o \ |
| 338 | process.o gnutls.o callproc.o \ | 338 | process.o gnutls.o callproc.o \ |
| 339 | region-cache.o sound.o atimer.o thread.o \ | 339 | region-cache.o sound.o atimer.o thread.o systhread.o \ |
| 340 | doprnt.o intervals.o textprop.o composite.o xml.o \ | 340 | doprnt.o intervals.o textprop.o composite.o xml.o \ |
| 341 | $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) | 341 | $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) |
| 342 | obj = $(base_obj) $(NS_OBJC_OBJ) | 342 | obj = $(base_obj) $(NS_OBJC_OBJ) |
diff --git a/src/emacs.c b/src/emacs.c index e1acd365e29..443fe594795 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1270,6 +1270,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1270 | } | 1270 | } |
| 1271 | 1271 | ||
| 1272 | init_alloc (); | 1272 | init_alloc (); |
| 1273 | init_threads (); | ||
| 1273 | 1274 | ||
| 1274 | if (do_initial_setlocale) | 1275 | if (do_initial_setlocale) |
| 1275 | { | 1276 | { |
diff --git a/src/lisp.h b/src/lisp.h index a6665320da6..b0ed9be9f07 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -29,6 +29,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 29 | 29 | ||
| 30 | #include <intprops.h> | 30 | #include <intprops.h> |
| 31 | 31 | ||
| 32 | #include "systhread.h" | ||
| 33 | |||
| 32 | INLINE_HEADER_BEGIN | 34 | INLINE_HEADER_BEGIN |
| 33 | #ifndef LISP_INLINE | 35 | #ifndef LISP_INLINE |
| 34 | # define LISP_INLINE INLINE | 36 | # define LISP_INLINE INLINE |
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 | ||
diff --git a/src/systhread.h b/src/systhread.h new file mode 100644 index 00000000000..bf9358c21c6 --- /dev/null +++ b/src/systhread.h | |||
| @@ -0,0 +1,80 @@ | |||
| 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 | #ifndef SYSTHREAD_H | ||
| 20 | #define SYSTHREAD_H | ||
| 21 | |||
| 22 | #ifdef HAVE_PTHREAD | ||
| 23 | |||
| 24 | #include <pthread.h> | ||
| 25 | |||
| 26 | /* A mutex in lisp is represented by a pthread condition variable. | ||
| 27 | The pthread mutex associated with this condition variable is the | ||
| 28 | global lock. | ||
| 29 | |||
| 30 | Using a condition variable lets us implement interruptibility for | ||
| 31 | lisp mutexes. */ | ||
| 32 | typedef struct | ||
| 33 | { | ||
| 34 | struct thread_state *owner; | ||
| 35 | unsigned int count; | ||
| 36 | pthread_cond_t condition; | ||
| 37 | } lisp_mutex_t; | ||
| 38 | |||
| 39 | /* A system mutex is just a pthread mutex. This is only used for the | ||
| 40 | GIL. */ | ||
| 41 | typedef pthread_mutex_t sys_mutex_t; | ||
| 42 | |||
| 43 | typedef pthread_cond_t sys_cond_t; | ||
| 44 | |||
| 45 | /* A system thread. */ | ||
| 46 | typedef pthread_t sys_thread_t; | ||
| 47 | |||
| 48 | #else | ||
| 49 | |||
| 50 | #error port me | ||
| 51 | |||
| 52 | #endif | ||
| 53 | |||
| 54 | typedef void *(thread_creation_function) (void *); | ||
| 55 | |||
| 56 | extern void sys_mutex_init (sys_mutex_t *); | ||
| 57 | extern void sys_mutex_lock (sys_mutex_t *); | ||
| 58 | extern void sys_mutex_unlock (sys_mutex_t *); | ||
| 59 | extern void sys_mutex_destroy (sys_mutex_t *); | ||
| 60 | |||
| 61 | extern void sys_cond_init (sys_cond_t *); | ||
| 62 | extern void sys_cond_wait (sys_cond_t *, sys_mutex_t *); | ||
| 63 | extern void sys_cond_signal (sys_cond_t *); | ||
| 64 | extern void sys_cond_broadcast (sys_cond_t *); | ||
| 65 | extern void sys_cond_destroy (sys_cond_t *); | ||
| 66 | |||
| 67 | extern void lisp_mutex_init (lisp_mutex_t *); | ||
| 68 | extern void lisp_mutex_lock (lisp_mutex_t *); | ||
| 69 | extern void lisp_mutex_unlock (lisp_mutex_t *); | ||
| 70 | extern void lisp_mutex_destroy (lisp_mutex_t *); | ||
| 71 | |||
| 72 | extern sys_thread_t sys_thread_self (void); | ||
| 73 | extern int sys_thread_equal (sys_thread_t, sys_thread_t); | ||
| 74 | |||
| 75 | extern int sys_thread_create (sys_thread_t *, thread_creation_function *, | ||
| 76 | void *); | ||
| 77 | |||
| 78 | extern void sys_thread_yield (void); | ||
| 79 | |||
| 80 | #endif /* SYSTHREAD_H */ | ||
diff --git a/src/thread.c b/src/thread.c index ba2d66320fa..19faa1bafae 100644 --- a/src/thread.c +++ b/src/thread.c | |||
| @@ -27,6 +27,8 @@ struct thread_state *current_thread = &the_only_thread; | |||
| 27 | 27 | ||
| 28 | struct thread_state *all_threads = &the_only_thread; | 28 | struct thread_state *all_threads = &the_only_thread; |
| 29 | 29 | ||
| 30 | sys_mutex_t global_lock; | ||
| 31 | |||
| 30 | static void | 32 | static void |
| 31 | mark_one_thread (struct thread_state *thread) | 33 | mark_one_thread (struct thread_state *thread) |
| 32 | { | 34 | { |
| @@ -103,3 +105,10 @@ unmark_threads (void) | |||
| 103 | if (iter->m_byte_stack_list) | 105 | if (iter->m_byte_stack_list) |
| 104 | unmark_byte_stack (iter->m_byte_stack_list); | 106 | unmark_byte_stack (iter->m_byte_stack_list); |
| 105 | } | 107 | } |
| 108 | |||
| 109 | void | ||
| 110 | init_threads (void) | ||
| 111 | { | ||
| 112 | sys_mutex_init (&global_lock); | ||
| 113 | sys_mutex_lock (&global_lock); | ||
| 114 | } | ||
diff --git a/src/thread.h b/src/thread.h index 6d61d0e5fcf..020346b9af2 100644 --- a/src/thread.h +++ b/src/thread.h | |||
| @@ -140,6 +140,10 @@ struct thread_state | |||
| 140 | 140 | ||
| 141 | extern struct thread_state *current_thread; | 141 | extern struct thread_state *current_thread; |
| 142 | 142 | ||
| 143 | extern sys_mutex_t global_lock; | ||
| 144 | |||
| 143 | extern void unmark_threads (void); | 145 | extern void unmark_threads (void); |
| 144 | 146 | ||
| 147 | extern void init_threads (void); | ||
| 148 | |||
| 145 | #endif /* THREAD_H */ | 149 | #endif /* THREAD_H */ |