Skip to content

Instantly share code, notes, and snippets.

@Hamayama
Created October 27, 2023 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hamayama/0eb5234311054d6dbbe8e75727040aef to your computer and use it in GitHub Desktop.
Save Hamayama/0eb5234311054d6dbbe8e75727040aef to your computer and use it in GitHub Desktop.
Windows で spin lock と mutex lock のテスト (MSYS2/MinGW-w64)
@set PATH=C:\msys64\mingw32\bin;C:\msys64\usr\local\bin;C:\msys64\usr\bin;C:\msys64\bin;%PATH%
set MSYSTEM=MINGW32
for %%i in (
spinlock mutexlock
) do (
gcc -g -O2 -Wall -Wextra -o %%i_32.exe %%i.c
)
pause
@set PATH=C:\msys64\mingw64\bin;C:\msys64\usr\local\bin;C:\msys64\usr\bin;C:\msys64\bin;%PATH%
set MSYSTEM=MINGW64
for %%i in (
spinlock mutexlock
) do (
gcc -g -O2 -Wall -Wextra -o %%i_64.exe %%i.c
)
pause
@set PATH=C:\msys64\mingw32\bin;C:\msys64\usr\local\bin;C:\msys64\usr\bin;C:\msys64\bin;%PATH%
@set MSYSTEM=MINGW32
@rem gdb spinlock_32.exe
C:\msys64\usr\bin\time.exe -p ./spinlock_32.exe
C:\msys64\usr\bin\time.exe -p ./mutexlock_32.exe
pause
@set PATH=C:\msys64\mingw64\bin;C:\msys64\usr\local\bin;C:\msys64\usr\bin;C:\msys64\bin;%PATH%
@set MSYSTEM=MINGW64
@rem gdb spinlock_64.exe
C:\msys64\usr\bin\time.exe -p ./spinlock_64.exe
C:\msys64\usr\bin\time.exe -p ./mutexlock_64.exe
pause
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <stdatomic.h>
/* Mutex lock function */
#define SCM_INTERNAL_MUTEX_INIT(mutex) ((mutex) = Scm__WinCreateMutex())
#define SCM_INTERNAL_MUTEX_LOCK(mutex) Scm__WinMutexLock(mutex)
#define SCM_INTERNAL_MUTEX_UNLOCK(mutex) ReleaseMutex(mutex)
#define SCM_INTERNAL_MUTEX_DESTROY(mutex) CloseHandle(mutex)
#define SCM_INTERNAL_MUTEX_INITIALIZER INVALID_HANDLE_VALUE
typedef HANDLE ScmInternalMutex;
HANDLE Scm__WinCreateMutex()
{
HANDLE m = CreateMutex(NULL, FALSE, NULL);
//if (m == NULL) Scm_SysError("couldn't create a mutex");
return m;
}
int Scm__WinMutexLock(HANDLE mutex)
{
DWORD r = WaitForSingleObject(mutex, INFINITE);
if (r == WAIT_OBJECT_0) return 0;
else return 1; /* TODO: proper error handling */
}
/* Multithreading test */
#define THREAD_NUM 100
#define COUNT_NUM 1000000
double count = 0;
ScmInternalMutex mutex = SCM_INTERNAL_MUTEX_INITIALIZER;
//unsigned __stdcall countup(void *args) {
// (void)args;
DWORD WINAPI countup(LPVOID lpParameter) {
(void)lpParameter;
for (int i = 0; i < COUNT_NUM; i++) {
SCM_INTERNAL_MUTEX_LOCK(mutex);
count++;
SCM_INTERNAL_MUTEX_UNLOCK(mutex);
}
return 0;
}
int main(void) {
HANDLE hThread[THREAD_NUM];
SCM_INTERNAL_MUTEX_INIT(mutex);
for (int i = 0; i < THREAD_NUM; i++) {
//hThread[i] = (HANDLE)_beginthreadex(NULL, 0, countup, NULL, CREATE_SUSPENDED, NULL);
hThread[i] = CreateThread(NULL, 0, countup, NULL, CREATE_SUSPENDED, NULL);
}
for (int i = 0; i < THREAD_NUM; i++) {
ResumeThread(hThread[i]);
}
//Sleep(10000);
// The maximum number of waiting objects is 64 .
//WaitForMultipleObjects(THREAD_NUM, hThread, TRUE, INFINITE);
for (int i = 0; i < THREAD_NUM; i++) {
WaitForSingleObject(hThread[i], INFINITE);
}
for (int i = 0; i < THREAD_NUM; i++) {
CloseHandle(hThread[i]);
}
SCM_INTERNAL_MUTEX_DESTROY(mutex);
printf("count=%f\n", count);
return 0;
}
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <stdatomic.h>
/* Spin lock function */
#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
typedef volatile struct {
atomic_int lock_state;
int dummy; /* padding */
} win_spinlock_t;
typedef win_spinlock_t ScmInternalFastlock;
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;
}
/* Multithreading test */
#define THREAD_NUM 100
#define COUNT_NUM 1000000
double count = 0;
ScmInternalFastlock spin;
//unsigned __stdcall countup(void *args) {
// (void)args;
DWORD WINAPI countup(LPVOID lpParameter) {
(void)lpParameter;
for (int i = 0; i < COUNT_NUM; i++) {
SCM_INTERNAL_FASTLOCK_LOCK(spin);
count++;
SCM_INTERNAL_FASTLOCK_UNLOCK(spin);
}
return 0;
}
int main(void) {
HANDLE hThread[THREAD_NUM];
SCM_INTERNAL_FASTLOCK_INIT(spin);
for (int i = 0; i < THREAD_NUM; i++) {
//hThread[i] = (HANDLE)_beginthreadex(NULL, 0, countup, NULL, CREATE_SUSPENDED, NULL);
hThread[i] = CreateThread(NULL, 0, countup, NULL, CREATE_SUSPENDED, NULL);
}
for (int i = 0; i < THREAD_NUM; i++) {
ResumeThread(hThread[i]);
}
//Sleep(10000);
// The maximum number of waiting objects is 64 .
//WaitForMultipleObjects(THREAD_NUM, hThread, TRUE, INFINITE);
for (int i = 0; i < THREAD_NUM; i++) {
WaitForSingleObject(hThread[i], INFINITE);
}
for (int i = 0; i < THREAD_NUM; i++) {
CloseHandle(hThread[i]);
}
SCM_INTERNAL_FASTLOCK_DESTROY(spin);
printf("count=%f\n", count);
return 0;
}
> C:\msys64\usr\bin\time.exe -p ./spinlock_32.exe
count=100000000.000000
real 2.65
user 0.01
sys 0.01
> C:\msys64\usr\bin\time.exe -p ./mutexlock_32.exe
count=100000000.000000
real 376.80
user 0.01
sys 0.00
> C:\msys64\usr\bin\time.exe -p ./spinlock_64.exe
count=100000000.000000
real 2.98
user 0.00
sys 0.01
> C:\msys64\usr\bin\time.exe -p ./mutexlock_64.exe
count=100000000.000000
real 364.81
user 0.00
sys 0.01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment