}
else if (MUTEXP (obj))
{
- strout ("#<mutex>", -1, -1, printcharfun, 0);
+ struct Lisp_Mutex *mutex = XMUTEX (obj);
+ strout ("#<mutex", -1, -1, printcharfun, 0);
+ if (mutex->recursive)
+ strout (" recursive", -1, -1, printcharfun, 0);
+ PRINTCHAR ('>');
}
else
{
return 0;
}
-DEFUN ("make-mutex", Fmake_mutex, Smake_mutex, 0, 0, 0,
- doc: /* Make a mutex. */)
- ()
+DEFUN ("make-mutex", Fmake_mutex, Smake_mutex, 0, 1, 0,
+ doc: /* Make a mutex. If RECURSIVE is nil the mutex is not recursive
+ and can be locked once. */)
+ (recursive)
+ Lisp_Object recursive;
{
Lisp_Object ret;
struct Lisp_Mutex *mutex = allocate_mutex ();
mutex->owner = 0;
+ mutex->rec_counter = 0;
+ mutex->recursive = ! NILP (recursive);
XSETMUTEX (ret, mutex);
return ret;
}
struct Lisp_Mutex *mutex = XMUTEX (val);
while (1)
{
- if (mutex->owner == 0 || mutex->owner == pthread_self ())
+ if (mutex->owner == 0
+ || (mutex->recursive && mutex->owner == pthread_self ()))
{
mutex->owner = pthread_self ();
+ mutex->rec_counter++;
return Qt;
}
Lisp_Object val;
{
struct Lisp_Mutex *mutex = XMUTEX (val);
- mutex->owner = 0;
+
+ if (mutex->owner != pthread_self () || mutex->rec_counter == 0)
+ return Qnil;
+
+ mutex->rec_counter--;
+
+ if (mutex->rec_counter == 0)
+ mutex->owner = 0;
+
return Qt;
}
primary_thread.func = Qnil;
primary_thread.initial_specpdl = Qnil;
XSETPVECTYPE (&primary_thread, PVEC_THREAD);
- minibuffer_mutex = Fmake_mutex ();
+ minibuffer_mutex = Fmake_mutex (Qnil);
}
void
struct Lisp_Vector *v_next;
+ /* Is the mutex recursive? */
+ int recursive;
+
/* Thread that owns the mutex. */
pthread_t owner;
+
+ /* Number of times it was recursively owned. */
+ unsigned int rec_counter;
};
struct thread_state