1 /* Copyright (C) 2004 MySQL AB
2 Copyright (C) 2004-2016 Alexey Kopytov <akopytov@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #ifdef _WIN32
24 # include "sb_win.h"
25 #endif
26
27 #ifdef HAVE_PTHREAD_H
28 # include <pthread.h>
29 #endif
30
31 #include "sysbench.h"
32 #include "sb_ck_pr.h"
33 #include "sb_rand.h"
34
35 typedef struct
36 {
37 pthread_mutex_t mutex;
38 char pad[256];
39 } thread_lock;
40
41
42 /* Mutex test arguments */
43 static sb_arg_t mutex_args[] =
44 {
45 SB_OPT("mutex-num", "total size of mutex array", "4096", INT),
46 SB_OPT("mutex-locks", "number of mutex locks to do per thread", "50000", INT),
47 SB_OPT("mutex-loops", "number of empty loops to do outside mutex lock",
48 "10000", INT),
49
50 SB_OPT_END
51 };
52
53 /* Mutex test operations */
54 static int mutex_init(void);
55 static void mutex_print_mode(void);
56 static sb_event_t mutex_next_event(int);
57 static int mutex_execute_event(sb_event_t *, int);
58 static int mutex_done(void);
59
60 static sb_test_t mutex_test =
61 {
62 .sname = "mutex",
63 .lname = "Mutex performance test",
64 .ops = {
65 .init = mutex_init,
66 .print_mode = mutex_print_mode,
67 .next_event = mutex_next_event,
68 .execute_event = mutex_execute_event,
69 .done = mutex_done
70 },
71 .args = mutex_args
72 };
73
74
75 static thread_lock *thread_locks;
76 static unsigned int mutex_num;
77 static unsigned int mutex_loops;
78 static unsigned int mutex_locks;
79 static unsigned int global_var;
80
81 static TLS int tls_counter;
82
register_test_mutex(sb_list_t * tests)83 int register_test_mutex(sb_list_t *tests)
84 {
85 SB_LIST_ADD_TAIL(&mutex_test.listitem, tests);
86
87 return 0;
88 }
89
90
mutex_init(void)91 int mutex_init(void)
92 {
93 unsigned int i;
94
95 mutex_num = sb_get_value_int("mutex-num");
96 mutex_loops = sb_get_value_int("mutex-loops");
97 mutex_locks = sb_get_value_int("mutex-locks");
98
99 thread_locks = (thread_lock *)malloc(mutex_num * sizeof(thread_lock));
100 if (thread_locks == NULL)
101 {
102 log_text(LOG_FATAL, "Memory allocation failure!");
103 return 1;
104 }
105
106 for (i = 0; i < mutex_num; i++)
107 pthread_mutex_init(&thread_locks[i].mutex, NULL);
108
109 return 0;
110 }
111
112
mutex_done(void)113 int mutex_done(void)
114 {
115 unsigned int i;
116
117 for(i=0; i < mutex_num; i++)
118 pthread_mutex_destroy(&thread_locks[i].mutex);
119 free(thread_locks);
120
121 return 0;
122 }
123
124
mutex_next_event(int thread_id)125 sb_event_t mutex_next_event(int thread_id)
126 {
127 sb_event_t sb_req;
128 sb_mutex_request_t *mutex_req = &sb_req.u.mutex_request;
129
130 (void) thread_id; /* unused */
131
132 /* Perform only one request per thread */
133 if (tls_counter++ > 0)
134 sb_req.type = SB_REQ_TYPE_NULL;
135 else
136 {
137 sb_req.type = SB_REQ_TYPE_MUTEX;
138 mutex_req->nlocks = mutex_locks;
139 mutex_req->nloops = mutex_loops;
140 }
141
142 return sb_req;
143 }
144
145
mutex_execute_event(sb_event_t * sb_req,int thread_id)146 int mutex_execute_event(sb_event_t *sb_req, int thread_id)
147 {
148 unsigned int i;
149 unsigned int current_lock;
150 sb_mutex_request_t *mutex_req = &sb_req->u.mutex_request;
151
152 (void) thread_id; /* unused */
153
154 do
155 {
156 current_lock = sb_rand_uniform(0, mutex_num - 1);
157
158 for (i = 0; i < mutex_req->nloops; i++)
159 ck_pr_barrier();
160
161 pthread_mutex_lock(&thread_locks[current_lock].mutex);
162 global_var++;
163 pthread_mutex_unlock(&thread_locks[current_lock].mutex);
164 mutex_req->nlocks--;
165 }
166 while (mutex_req->nlocks > 0);
167
168 return 0;
169 }
170
171
mutex_print_mode(void)172 void mutex_print_mode(void)
173 {
174 log_text(LOG_INFO, "Doing mutex performance test");
175 }
176
177