mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-12 06:41:13 +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);
|
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_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
|
||||||
(SCM mutex, SCM timeout),
|
(SCM mutex, SCM timeout),
|
||||||
"Lock mutex @var{mutex}. If the mutex is already locked, "
|
"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
|
#define FUNC_NAME s_scm_timed_lock_mutex
|
||||||
{
|
{
|
||||||
scm_t_timespec cwaittime, *waittime = NULL;
|
scm_t_timespec cwaittime, *waittime = NULL;
|
||||||
struct timeval current_time;
|
|
||||||
struct scm_mutex *m;
|
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);
|
SCM_VALIDATE_MUTEX (1, mutex);
|
||||||
m = SCM_MUTEX_DATA (mutex);
|
m = SCM_MUTEX_DATA (mutex);
|
||||||
|
@ -1159,51 +1224,26 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
|
||||||
waittime = &cwaittime;
|
waittime = &cwaittime;
|
||||||
}
|
}
|
||||||
|
|
||||||
scm_i_scm_pthread_mutex_lock (&m->lock);
|
/* Specialized lock_mutex implementations according to the mutex
|
||||||
|
kind. */
|
||||||
while (1)
|
switch (SCM_MUTEX_KIND (mutex))
|
||||||
{
|
{
|
||||||
if (scm_is_eq (m->owner, SCM_BOOL_F))
|
case SCM_MUTEX_STANDARD:
|
||||||
{
|
ret = lock_mutex (SCM_MUTEX_STANDARD, m, t, waittime);
|
||||||
m->owner = new_owner;
|
break;
|
||||||
scm_i_pthread_mutex_unlock (&m->lock);
|
case SCM_MUTEX_RECURSIVE:
|
||||||
return SCM_BOOL_T;
|
ret = lock_mutex (SCM_MUTEX_RECURSIVE, m, t, waittime);
|
||||||
}
|
break;
|
||||||
else if (scm_is_eq (m->owner, new_owner) &&
|
case SCM_MUTEX_UNOWNED:
|
||||||
SCM_MUTEX_KIND (mutex) != SCM_MUTEX_UNOWNED)
|
ret = lock_mutex (SCM_MUTEX_UNOWNED, m, t, waittime);
|
||||||
{
|
break;
|
||||||
if (SCM_MUTEX_KIND (mutex) == SCM_MUTEX_RECURSIVE)
|
default:
|
||||||
{
|
abort ();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scm_remember_upto_here_1 (mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue