Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fast lock on windows #955

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/gauche/pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ typedef pthread_spinlock_t ScmInternalFastlock;
pthread_spin_unlock(&(spin))
#define SCM_INTERNAL_FASTLOCK_DESTROY(spin) \
pthread_spin_destroy(&(spin))
#define SCM_INTERNAL_FASTLOCK_FINALIZATION_NOT_REQUIRED
#else /*!HAVE_PTHREAD_SPINLOCK_T*/
/* We don't provide fast lock */
typedef pthread_mutex_t ScmInternalFastlock;
#define SCM_INTERNAL_FASTLOCK_INIT(fl) SCM_INTERNAL_MUTEX_INIT(fl)
#define SCM_INTERNAL_FASTLOCK_LOCK(fl) SCM_INTERNAL_MUTEX_LOCK(fl)
Expand Down
19 changes: 19 additions & 0 deletions src/gauche/wthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,31 @@ SCM_EXTERN void Scm__InternalCondDestroy(ScmInternalCond *cond);
#undef ScmTimeSpecRec
#endif /*defined(__MINGW64_VERSION_MAJOR)*/

/* Windows fast lock */
#if defined(HAVE_STDATOMIC_H)
#include <stdatomic.h>
typedef volatile struct {
atomic_int lock_state;
int dummy; /* padding */
} win_spinlock_t;
typedef win_spinlock_t ScmInternalFastlock;
#define SCM_INTERNAL_FASTLOCK_INIT(spin) Scm__WinFastLockInit(&(spin))
#define SCM_INTERNAL_FASTLOCK_LOCK(spin) Scm__WinFastLockLock(&(spin))
#define SCM_INTERNAL_FASTLOCK_UNLOCK(spin) Scm__WinFastLockUnlock(&(spin))
#define SCM_INTERNAL_FASTLOCK_DESTROY(spin) Scm__WinFastLockDestroy(&(spin))
#define SCM_INTERNAL_FASTLOCK_FINALIZATION_NOT_REQUIRED
SCM_EXTERN int Scm__WinFastLockInit(ScmInternalFastlock *spin);
SCM_EXTERN int Scm__WinFastLockLock(ScmInternalFastlock *spin);
SCM_EXTERN int Scm__WinFastLockUnlock(ScmInternalFastlock *spin);
SCM_EXTERN int Scm__WinFastLockDestroy(ScmInternalFastlock *spin);
#else /* !HAVE_STDATOMIC_H */
/* We don't provide fast lock */
typedef HANDLE ScmInternalFastlock;
#define SCM_INTERNAL_FASTLOCK_INIT(fl) SCM_INTERNAL_MUTEX_INIT(fl)
#define SCM_INTERNAL_FASTLOCK_LOCK(fl) SCM_INTERNAL_MUTEX_LOCK(fl)
#define SCM_INTERNAL_FASTLOCK_UNLOCK(fl) SCM_INTERNAL_MUTEX_UNLOCK(fl)
#define SCM_INTERNAL_FASTLOCK_DESTROY(fl) SCM_INTERNAL_MUTEX_DESTROY(fl)
#endif /* !HAVE_STDATOMIC_H */

/* Issues a full memory barrier */
#if 0 /* MinGW doesn't seem to have MemoryBarrier() */
Expand Down
19 changes: 7 additions & 12 deletions src/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,20 +270,15 @@ static ScmPort *make_port(ScmClass *klass, ScmObj name, int dir, int type)
port->link = SCM_FALSE;
port->internalFlags = 0;

/* TRANSIENT: On Windows, we use normal mutex for port's fastlock,
which consumes a handle and requires cleanup. Registering a finalizer
for every string port puts significant overhead, so eventually
we'll introduce cleanup-free fastlock; then remove this #ifdef.
*/
if (
#if GAUCHE_WINDOWS
TRUE
#else
type == SCM_PORT_FILE || type == SCM_PORT_PROC
#endif
) {
/* If fast lock doesn't require finalization, we can skip to register
a finalizer for every string port. It reduces significant overhead. */
#if defined(SCM_INTERNAL_FASTLOCK_FINALIZATION_NOT_REQUIRED)
if (type == SCM_PORT_FILE || type == SCM_PORT_PROC) {
Scm_RegisterFinalizer(SCM_OBJ(port), port_finalize, NULL);
}
#else
Scm_RegisterFinalizer(SCM_OBJ(port), port_finalize, NULL);
#endif

return SCM_PORT(port);
}
Expand Down
32 changes: 32 additions & 0 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -2961,6 +2961,38 @@ int Scm__WinMutexLock(HANDLE mutex)
else return 1; /* TODO: proper error handling */
}

/* Windows fast lock */
#if defined(HAVE_STDATOMIC_H)
int Scm__WinFastLockInit(ScmInternalFastlock *spin)
{
(spin->lock_state) = ATOMIC_VAR_INIT(0);
return 0;
}

int Scm__WinFastLockLock(ScmInternalFastlock *spin)
{
while (atomic_exchange_explicit(&(spin->lock_state), 1, memory_order_acquire)) {
while (atomic_load_explicit(&(spin->lock_state), memory_order_relaxed)) {
/* it might be slow */
Sleep(0);
}
}
return 0;
}

int Scm__WinFastLockUnlock(ScmInternalFastlock *spin)
{
atomic_store_explicit(&(spin->lock_state), 0, memory_order_release);
return 0;
}

int Scm__WinFastLockDestroy(ScmInternalFastlock *spin)
{
(void)spin; /* suppress unused var warning */
return 0;
}
#endif /* HAVE_STDATOMIC_H */

/* Win32 conditional variable emulation.
Native condition variable support is only available on Windows Vista
and later. We don't want to drop XP support (yet), so we avoid using
Expand Down