-
Notifications
You must be signed in to change notification settings - Fork 28
/
mutex_performance.c
116 lines (86 loc) · 2.69 KB
/
mutex_performance.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* This file is licensed under CC0 for illustrative purposes. You can
* do whatever you like with this piece of code. Any warranty, explicit
* or implicit, is disclaimed. */
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <windows.h>
#if defined USE_SRWLOCK
# define my_mutex_t SRWLOCK
# define my_init(m) InitializeSRWLock(m)
# define my_lock(m) AcquireSRWLockExclusive(m)
# define my_unlock(m) ReleaseSRWLockExclusive(m)
#elif defined USE_CRITICAL_SECTION
# define my_mutex_t CRITICAL_SECTION
# define my_init(m) InitializeCriticalSection(m)
# define my_lock(m) EnterCriticalSection(m)
# define my_unlock(m) LeaveCriticalSection(m)
#elif defined USE_WINPTHREAD
# include <pthread.h>
# define my_mutex_t pthread_mutex_t
# define my_init(m) pthread_mutex_init(m, NULL)
# define my_lock(m) pthread_mutex_lock(m)
# define my_unlock(m) pthread_mutex_unlock(m)
#elif defined USE_MCFGTHREAD
# include <mcfgthread/mutex.h>
# define my_mutex_t _MCF_mutex
# define my_init(m) _MCF_mutex_init(m)
# define my_lock(m) _MCF_mutex_lock_slow(m, NULL)
# define my_unlock(m) _MCF_mutex_unlock_slow(m)
#else
# error No mutex type has been selected.
#endif
#define NTHRD 16
#define NITER 1000000
HANDLE start;
HANDLE threads[NTHRD];
my_mutex_t mutex;
volatile double dst = 12345;
volatile double src = 54321;
LARGE_INTEGER t0, t1, tf;
static
DWORD
__stdcall
thread_proc(void* arg)
{
(void) arg;
WaitForSingleObject(start, INFINITE);
for(intptr_t k = 0; k < NITER; ++k) {
my_lock(&mutex);
double temp = src;
my_unlock(&mutex);
temp = log(temp);
my_lock(&mutex);
dst = src;
my_unlock(&mutex);
SwitchToThread();
}
fprintf(stderr, "thread %d quitting\n", (int) GetCurrentThreadId());
return 0;
}
int
main(void)
{
start = CreateEventW(NULL, TRUE, FALSE, NULL);
assert(start);
my_init(&mutex);
#define xstr1(x) xstr2(x)
#define xstr2(x) #x
fprintf(stderr, "using `%s`:\n # of threads = %d\n # of iterations = %d\n",
xstr1(my_mutex_t), NTHRD, NITER);
for(intptr_t k = 0; k < NTHRD; ++k) {
threads[k] = CreateThread(NULL, 0, thread_proc, NULL, 0, NULL);
assert(threads[k]);
}
fprintf(stderr, "main waiting\n");
SetEvent(start);
QueryPerformanceCounter(&t0);
for(intptr_t k = 0; k < NTHRD; ++k) {
WaitForSingleObject(threads[k], INFINITE);
CloseHandle(threads[k]);
}
QueryPerformanceCounter(&t1);
QueryPerformanceFrequency(&tf);
fprintf(stderr, "total time:\n %.3f milliseconds\n",
(double) (t1.QuadPart - t0.QuadPart) * 1000 / tf.QuadPart);
}