return ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS);
}
+struct Lisp_Mutex *
+allocate_mutex ()
+{
+ return ALLOCATE_PSEUDOVECTOR (struct Lisp_Mutex, owner, PVEC_MUTEX);
+}
+
DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
doc: /* Return a newly created vector of length LENGTH, with each element being INIT.
PVEC_FONT = 0x200000,
PVEC_OTHER = 0x400000,
PVEC_THREAD = 0x800000,
+ PVEC_MUTEX = 0x1000000,
PVEC_TYPE_MASK = 0xfffe00
#if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to
#define XCHAR_TABLE(a) (eassert (CHAR_TABLE_P (a)), (struct Lisp_Char_Table *) XPNTR(a))
#define XSUB_CHAR_TABLE(a) (eassert (SUB_CHAR_TABLE_P (a)), (struct Lisp_Sub_Char_Table *) XPNTR(a))
#define XBOOL_VECTOR(a) (eassert (BOOL_VECTOR_P (a)), (struct Lisp_Bool_Vector *) XPNTR(a))
+#define XMUTEX(a) (eassert (MUTEXP(a)),(struct Lisp_Mutex *) XPNTR(a))
/* Construct a Lisp_Object from a value or address. */
#define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
#define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE))
#define XSETTHREAD(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_THREAD))
+#define XSETMUTEX(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_MUTEX))
/* Convenience macros for dealing with Lisp arrays. */
#define BOOL_VECTOR_P(x) PSEUDOVECTORP (x, PVEC_BOOL_VECTOR)
#define FRAMEP(x) PSEUDOVECTORP (x, PVEC_FRAME)
#define THREADP(x) PSEUDOVECTORP (x, PVEC_THREAD)
+#define MUTEXP(x) PSEUDOVECTORP (x, PVEC_MUTEX)
/* Test for image (image . spec) */
#define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage))
extern struct window *allocate_window P_ ((void));
extern struct frame *allocate_frame P_ ((void));
extern struct Lisp_Process *allocate_process P_ ((void));
+extern struct Lisp_Mutex *allocate_mutex P_ ((void));
extern struct terminal *allocate_terminal P_ ((void));
extern int gc_in_progress;
extern int abort_on_gc;
}
PRINTCHAR ('>');
}
+ else if (MUTEXP (obj))
+ {
+ strout ("#<mutex>", -1, -1, printcharfun, 0);
+ }
else
{
EMACS_INT size = XVECTOR (obj)->size;
return Qnil;
}
+DEFUN ("make-mutex", Fmake_mutex, Smake_mutex, 0, 0, 0,
+ doc: /* Make a mutex. */)
+ ()
+{
+ Lisp_Object ret;
+ struct Lisp_Mutex *mutex = allocate_mutex ();
+ mutex->owner = 0;
+ XSETMUTEX (ret, mutex);
+ return ret;
+}
+
+DEFUN ("mutex-lock", Fmutex_lock, Smutex_lock, 1, 1, 0,
+ doc: /* Lock a mutex. */)
+ (val)
+ Lisp_Object val;
+{
+ struct Lisp_Mutex *mutex = XMUTEX (val);
+ while (1)
+ {
+ if (mutex->owner == 0 || mutex->owner == pthread_self ())
+ {
+ mutex->owner = pthread_self ();
+ return Qt;
+ }
+
+ thread_yield ();
+ }
+
+ return Qt;
+}
+
+DEFUN ("mutex-unlock", Fmutex_unlock, Smutex_unlock, 1, 1, 0,
+ doc: /* Unlock a mutex. */)
+ (val)
+ Lisp_Object val;
+{
+ struct Lisp_Mutex *mutex = XMUTEX (val);
+ mutex->owner = 0;
+ return Qt;
+}
+
int
thread_select (n, rfd, wfd, xfd, tmo)
int n;
defsubr (&Srun_in_thread);
defsubr (&Syield);
defsubr (&Sinhibit_yield);
+ defsubr (&Smake_mutex);
+ defsubr (&Smutex_lock);
+ defsubr (&Smutex_unlock);
}
#include "regex.h"
+struct Lisp_Mutex
+{
+ EMACS_UINT size;
+
+ struct Lisp_Vector *v_next;
+
+ /* Thread that owns the mutex. */
+ pthread_t owner;
+};
+
struct thread_state
{
EMACS_UINT size;