mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-10 14:00:21 +02:00
Optimize lock-mutex
* libguile/threads.c (lock_mutex, scm_timed_lock_mutex): As with unlock_mutex before, optimize by specializing to the mutex kind. Also, avoid lock thrashing after a return from block_self.
This commit is contained in:
parent
950e728e7a
commit
e0f17417e6
1 changed files with 85 additions and 45 deletions
|
@ -1139,6 +1139,71 @@ scm_lock_mutex (SCM mx)
|
|||
return scm_timed_lock_mutex (mx, SCM_UNDEFINED);
|
||||
}
|
||||
|
||||
static inline SCM
|
||||
lock_mutex (enum scm_mutex_kind kind, struct scm_mutex *m,
|
||||
scm_i_thread *current_thread, scm_t_timespec *waittime)
|
||||
#define FUNC_NAME "lock-mutex"
|
||||
{
|
||||
scm_i_scm_pthread_mutex_lock (&m->lock);
|
||||
|
||||
if (scm_is_eq (m->owner, SCM_BOOL_F))
|
||||
{
|
||||
m->owner = current_thread->handle;
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
else if (kind == SCM_MUTEX_RECURSIVE &&
|
||||
scm_is_eq (m->owner, current_thread->handle))
|
||||
{
|
||||
m->level++;
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
else if (kind == SCM_MUTEX_STANDARD &&
|
||||
scm_is_eq (m->owner, current_thread->handle))
|
||||
{
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
SCM_MISC_ERROR ("mutex already locked by thread", SCM_EOL);
|
||||
}
|
||||
else
|
||||
while (1)
|
||||
{
|
||||
int err = block_self (m->waiting, &m->lock, waittime);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
if (scm_is_eq (m->owner, SCM_BOOL_F))
|
||||
{
|
||||
m->owner = current_thread->handle;
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else if (err == ETIMEDOUT)
|
||||
{
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
else if (err == EINTR)
|
||||
{
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
scm_async_tick ();
|
||||
scm_i_scm_pthread_mutex_lock (&m->lock);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Shouldn't happen. */
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
errno = err;
|
||||
SCM_SYSERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
|
||||
(SCM mutex, SCM timeout),
|
||||
"Lock mutex @var{mutex}. If the mutex is already locked, "
|
||||
|
@ -1146,9 +1211,9 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
|
|||
#define FUNC_NAME s_scm_timed_lock_mutex
|
||||
{
|
||||
scm_t_timespec cwaittime, *waittime = NULL;
|
||||
struct timeval current_time;
|
||||
struct scm_mutex *m;
|
||||
SCM new_owner = scm_current_thread();
|
||||
scm_i_thread *t = SCM_I_CURRENT_THREAD;
|
||||
SCM ret;
|
||||
|
||||
SCM_VALIDATE_MUTEX (1, mutex);
|
||||
m = SCM_MUTEX_DATA (mutex);
|
||||
|
@ -1159,51 +1224,26 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
|
|||
waittime = &cwaittime;
|
||||
}
|
||||
|
||||
scm_i_scm_pthread_mutex_lock (&m->lock);
|
||||
|
||||
while (1)
|
||||
/* Specialized lock_mutex implementations according to the mutex
|
||||
kind. */
|
||||
switch (SCM_MUTEX_KIND (mutex))
|
||||
{
|
||||
if (scm_is_eq (m->owner, SCM_BOOL_F))
|
||||
{
|
||||
m->owner = new_owner;
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
else if (scm_is_eq (m->owner, new_owner) &&
|
||||
SCM_MUTEX_KIND (mutex) != SCM_MUTEX_UNOWNED)
|
||||
{
|
||||
if (SCM_MUTEX_KIND (mutex) == SCM_MUTEX_RECURSIVE)
|
||||
{
|
||||
m->level++;
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
else
|
||||
{
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
SCM_MISC_ERROR ("mutex already locked by thread", SCM_EOL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (waittime != NULL)
|
||||
{
|
||||
gettimeofday (¤t_time, NULL);
|
||||
if (current_time.tv_sec > waittime->tv_sec ||
|
||||
(current_time.tv_sec == waittime->tv_sec &&
|
||||
current_time.tv_usec * 1000 > waittime->tv_nsec))
|
||||
{
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
}
|
||||
block_self (m->waiting, &m->lock, waittime);
|
||||
scm_remember_upto_here_1 (mutex);
|
||||
scm_i_pthread_mutex_unlock (&m->lock);
|
||||
SCM_TICK;
|
||||
scm_i_scm_pthread_mutex_lock (&m->lock);
|
||||
}
|
||||
case SCM_MUTEX_STANDARD:
|
||||
ret = lock_mutex (SCM_MUTEX_STANDARD, m, t, waittime);
|
||||
break;
|
||||
case SCM_MUTEX_RECURSIVE:
|
||||
ret = lock_mutex (SCM_MUTEX_RECURSIVE, m, t, waittime);
|
||||
break;
|
||||
case SCM_MUTEX_UNOWNED:
|
||||
ret = lock_mutex (SCM_MUTEX_UNOWNED, m, t, waittime);
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
scm_remember_upto_here_1 (mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue