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 \
eval.o floatfns.o fns.o font.o print.o lread.o \
syntax.o $(UNEXEC_OBJ) bytecode.o \
process.o gnutls.o callproc.o \
- region-cache.o sound.o atimer.o thread.o \
+ region-cache.o sound.o atimer.o thread.o systhread.o \
doprnt.o intervals.o textprop.o composite.o xml.o \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ)
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
}
init_alloc ();
+ init_threads ();
if (do_initial_setlocale)
{
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 . */
#include
+#include "systhread.h"
+
INLINE_HEADER_BEGIN
#ifndef LISP_INLINE
# 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 @@
+/* System thread definitions
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see . */
+
+#include
+#include
+#include "lisp.h"
+
+#ifdef HAVE_PTHREAD
+
+#include
+
+void
+sys_mutex_init (sys_mutex_t *mutex)
+{
+ pthread_mutex_init (mutex, NULL);
+}
+
+void
+sys_mutex_lock (sys_mutex_t *mutex)
+{
+ pthread_mutex_lock (mutex);
+}
+
+void
+sys_mutex_unlock (sys_mutex_t *mutex)
+{
+ pthread_mutex_unlock (mutex);
+}
+
+void
+sys_mutex_destroy (sys_mutex_t *mutex)
+{
+ pthread_mutex_destroy (mutex);
+}
+
+void
+sys_cond_init (sys_cond_t *cond)
+{
+ pthread_cond_init (cond, NULL);
+}
+
+void
+sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
+{
+ pthread_cond_wait (cond, mutex);
+}
+
+void
+sys_cond_signal (sys_cond_t *cond)
+{
+ pthread_cond_signal (cond);
+}
+
+void
+sys_cond_broadcast (sys_cond_t *cond)
+{
+ pthread_cond_broadcast (cond);
+}
+
+void
+sys_cond_destroy (sys_cond_t *cond)
+{
+ pthread_cond_destroy (cond);
+}
+
+void
+lisp_mutex_init (lisp_mutex_t *mutex)
+{
+ mutex->owner = NULL;
+ mutex->count = 0;
+ /* A lisp "mutex" is really a condition variable. */
+ pthread_cond_init (&mutex->condition, NULL);
+}
+
+void
+lisp_mutex_lock (lisp_mutex_t *mutex)
+{
+ struct thread_state *self;
+
+ if (mutex->owner == NULL)
+ {
+ mutex->owner = current_thread;
+ mutex->count = 1;
+ return;
+ }
+ if (mutex->owner == current_thread)
+ {
+ ++mutex->count;
+ return;
+ }
+
+ self = current_thread;
+ while (mutex->owner != NULL /* && EQ (self->error_symbol, Qnil) */)
+ pthread_cond_wait (&mutex->condition, &global_lock);
+
+#if 0
+ if (!EQ (self->error_symbol, Qnil))
+ {
+ Lisp_Object error_symbol = self->error_symbol;
+ Lisp_Object data = self->error_data;
+ self->error_symbol = Qnil;
+ self->error_data = Qnil;
+ Fsignal (error_symbol, error_data);
+ }
+#endif
+
+ mutex->owner = self;
+ mutex->count = 1;
+}
+
+void
+lisp_mutex_unlock (lisp_mutex_t *mutex)
+{
+ struct thread_state *self = current_thread;
+
+ if (mutex->owner != current_thread)
+ error ("blah");
+
+ if (--mutex->count > 0)
+ return;
+
+ mutex->owner = NULL;
+ pthread_cond_broadcast (&mutex->condition);
+
+ post_acquire_global_lock (self);
+}
+
+void
+lisp_mutex_destroy (lisp_mutex_t *mutex)
+{
+ sys_cond_destroy (&mutex->condition);
+}
+
+sys_thread_t
+sys_thread_self (void)
+{
+ return pthread_self ();
+}
+
+int
+sys_thread_equal (sys_thread_t one, sys_thread_t two)
+{
+ return pthread_equal (one, two);
+}
+
+int
+sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
+ void *arg)
+{
+ pthread_attr_t attr;
+ int result = 0;
+
+ if (pthread_attr_init (&attr))
+ return 0;
+
+ if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
+ result = pthread_create (thread_ptr, &attr, func, arg) == 0;
+
+ pthread_attr_destroy (&attr);
+
+ return result;
+}
+
+void
+sys_thread_yield (void)
+{
+ sched_yield ();
+}
+
+#else
+
+#error port me
+
+#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 @@
+/* System thread definitions
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see . */
+
+#ifndef SYSTHREAD_H
+#define SYSTHREAD_H
+
+#ifdef HAVE_PTHREAD
+
+#include
+
+/* A mutex in lisp is represented by a pthread condition variable.
+ The pthread mutex associated with this condition variable is the
+ global lock.
+
+ Using a condition variable lets us implement interruptibility for
+ lisp mutexes. */
+typedef struct
+{
+ struct thread_state *owner;
+ unsigned int count;
+ pthread_cond_t condition;
+} lisp_mutex_t;
+
+/* A system mutex is just a pthread mutex. This is only used for the
+ GIL. */
+typedef pthread_mutex_t sys_mutex_t;
+
+typedef pthread_cond_t sys_cond_t;
+
+/* A system thread. */
+typedef pthread_t sys_thread_t;
+
+#else
+
+#error port me
+
+#endif
+
+typedef void *(thread_creation_function) (void *);
+
+extern void sys_mutex_init (sys_mutex_t *);
+extern void sys_mutex_lock (sys_mutex_t *);
+extern void sys_mutex_unlock (sys_mutex_t *);
+extern void sys_mutex_destroy (sys_mutex_t *);
+
+extern void sys_cond_init (sys_cond_t *);
+extern void sys_cond_wait (sys_cond_t *, sys_mutex_t *);
+extern void sys_cond_signal (sys_cond_t *);
+extern void sys_cond_broadcast (sys_cond_t *);
+extern void sys_cond_destroy (sys_cond_t *);
+
+extern void lisp_mutex_init (lisp_mutex_t *);
+extern void lisp_mutex_lock (lisp_mutex_t *);
+extern void lisp_mutex_unlock (lisp_mutex_t *);
+extern void lisp_mutex_destroy (lisp_mutex_t *);
+
+extern sys_thread_t sys_thread_self (void);
+extern int sys_thread_equal (sys_thread_t, sys_thread_t);
+
+extern int sys_thread_create (sys_thread_t *, thread_creation_function *,
+ void *);
+
+extern void sys_thread_yield (void);
+
+#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;
struct thread_state *all_threads = &the_only_thread;
+sys_mutex_t global_lock;
+
static void
mark_one_thread (struct thread_state *thread)
{
@@ -103,3 +105,10 @@ unmark_threads (void)
if (iter->m_byte_stack_list)
unmark_byte_stack (iter->m_byte_stack_list);
}
+
+void
+init_threads (void)
+{
+ sys_mutex_init (&global_lock);
+ sys_mutex_lock (&global_lock);
+}
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
extern struct thread_state *current_thread;
+extern sys_mutex_t global_lock;
+
extern void unmark_threads (void);
+extern void init_threads (void);
+
#endif /* THREAD_H */