View | Details | Raw Unified | Return to bug 11588 | Differences between
and this patch

Collapse All | Expand All

(-)a/benchtests/Makefile (-1 / +4 lines)
Lines 26-31 bench-math := acos acosh asin asinh atan atanh cos cosh exp exp2 ffs ffsll \ Link Here
26
	      log log2 modf pow rint sin sincos sinh sqrt tan tanh
26
	      log log2 modf pow rint sin sincos sinh sqrt tan tanh
27
27
28
bench-pthread := pthread_once
28
bench-pthread := pthread_once
29
bench-pthread-set := pthread_cond
29
30
30
bench := $(bench-math) $(bench-pthread)
31
bench := $(bench-math) $(bench-pthread)
31
32
Lines 39-51 string-bench-all := $(string-bench) Link Here
39
40
40
stdlib-bench := strtod
41
stdlib-bench := strtod
41
42
42
benchset := $(string-bench-all) $(stdlib-bench)
43
benchset := $(string-bench-all) $(stdlib-bench) $(bench-pthread-set)
43
44
45
CFLAGS-bench-pthread_cond.c += -g
44
CFLAGS-bench-ffs.c += -fno-builtin
46
CFLAGS-bench-ffs.c += -fno-builtin
45
CFLAGS-bench-ffsll.c += -fno-builtin
47
CFLAGS-bench-ffsll.c += -fno-builtin
46
48
47
$(addprefix $(objpfx)bench-,$(bench-math)): $(libm)
49
$(addprefix $(objpfx)bench-,$(bench-math)): $(libm)
48
$(addprefix $(objpfx)bench-,$(bench-pthread)): $(shared-thread-library)
50
$(addprefix $(objpfx)bench-,$(bench-pthread)): $(shared-thread-library)
51
$(addprefix $(objpfx)bench-,$(bench-pthread-set)): $(shared-thread-library) $(libm)
49
52
50
53
51
54
(-)a/benchtests/bench-pthread_cond.c (-1 / +389 lines)
Line 0 Link Here
0
- 
1
/* Measure the performance of pthread_cond_* family of functions.
2
   Copyright (C) 2013-2014 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
5
   The GNU C Library is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU Lesser General Public
7
   License as published by the Free Software Foundation; either
8
   version 2.1 of the License, or (at your option) any later version.
9
10
   The GNU C Library is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Lesser General Public License for more details.
14
15
   You should have received a copy of the GNU Lesser General Public
16
   License along with the GNU C Library; if not, see
17
   <http://www.gnu.org/licenses/>.  */
18
19
20
#include <error.h>
21
#include <errno.h>
22
#include <unistd.h>
23
#include <pthread.h>
24
#include <sched.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <stdint.h>
29
#include <sched.h>
30
#include <time.h>
31
#include <math.h>
32
33
#include "bench-timing.h"
34
35
typedef enum
36
  {
37
    COND_START,
38
    COND_WAITING,
39
    COND_SIGNALED,
40
    COND_STOP
41
  } state_t;
42
43
/* Uncomment to run benchmarks at RT priority */
44
/* #define REALTIME 1	*/
45
46
#define TIMEDWAIT_FLAG	(1<<0)
47
#define BROADCAST_FLAG	(1<<1)
48
#define ROUNDTRIP_FLAG	(1<<2)
49
50
typedef struct
51
{
52
  pthread_t tid;
53
  pthread_cond_t cond;
54
  pthread_mutex_t mutex;
55
  volatile state_t state;
56
  uint32_t flags;
57
  size_t iters;
58
  timing_t start;
59
  timing_t stop;
60
} params_t;
61
62
typedef struct
63
{
64
  timing_t sum;
65
  timing_t min;
66
  timing_t max;
67
  size_t n;
68
  double rmean;
69
  double rvar;
70
} stats_t;
71
72
static stats_t g_stats;
73
static pthread_mutex_t g_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
74
75
static void
76
init_stats (void)
77
{
78
  bzero (&g_stats, sizeof (stats_t));
79
}
80
81
static void
82
update_stats (params_t *p)
83
{
84
  timing_t diff;
85
  double delta;
86
87
  pthread_mutex_lock (&g_stats_mutex);
88
89
  g_stats.n++;
90
  TIMING_DIFF (diff, p->start, p->stop);
91
  TIMING_ACCUM (g_stats.sum, diff);
92
  if (diff > g_stats.max)
93
    g_stats.max = diff;
94
  if (diff < g_stats.min || g_stats.min == 0)
95
    g_stats.min = diff;
96
  delta = diff - g_stats.rmean;
97
  g_stats.rmean += delta / g_stats.n;
98
  g_stats.rvar += delta * (diff - g_stats.rmean);
99
100
  pthread_mutex_unlock (&g_stats_mutex);
101
}
102
103
static void
104
print_stats (size_t niters, size_t nthreads)
105
{
106
  double variance;
107
108
  variance = (g_stats.n > 1) ? g_stats.rvar/(g_stats.n - 1) : 0.0;
109
110
  printf ("%-14u%-11u", (unsigned int) niters, (unsigned int) nthreads);
111
  printf ("%-11g", (double) g_stats.sum / (double) g_stats.n);
112
  printf ("%-8u%-12u", (unsigned int) g_stats.min, (unsigned int) g_stats.max);
113
  printf ("%-15e%g\n", variance, sqrt (variance));
114
}
115
116
static void
117
create_thread (params_t *p, void *(*function) (void *))
118
{
119
  pthread_attr_t attr;
120
  pthread_condattr_t cond_attr;
121
#ifdef REALTIME
122
  int priority;
123
  struct sched_param schedp;
124
#endif
125
126
  p->state = COND_START;
127
  p->start = 0;
128
  p->stop = 0;
129
130
  if (pthread_mutex_init (&p->mutex, NULL) != 0)
131
    error (EXIT_FAILURE, errno, "pthread_mutex_init failed");
132
133
  if (pthread_condattr_init (&cond_attr) != 0)
134
    error (EXIT_FAILURE, errno, "pthread_condattr_init failed");
135
136
  if (p->flags & TIMEDWAIT_FLAG)
137
    if (pthread_condattr_setclock (&cond_attr, CLOCK_MONOTONIC) != 0)
138
      error (EXIT_FAILURE, errno, "pthread_condattr_setclock failed");
139
140
  if (pthread_cond_init (&p->cond, &cond_attr) != 0)
141
    error (EXIT_FAILURE, errno, "pthread_cond_init failed");
142
143
  if (pthread_attr_init (&attr) != 0)
144
    error (EXIT_FAILURE, errno, "pthread_attr_init failed");
145
146
#ifdef REALTIME
147
  priority = sched_get_priority_max (SCHED_FIFO);
148
  if (priority == -1)
149
    error (EXIT_FAILURE, errno, "sched_get_priority_max failed");
150
151
  schedp.sched_priority = priority - 1;
152
  if (sched_setscheduler (getpid (), SCHED_FIFO, &schedp) != 0)
153
    error (EXIT_FAILURE, errno, "sched_setscheduler failed");
154
155
  if (pthread_attr_setschedpolicy (&attr, SCHED_FIFO) != 0)
156
    error (EXIT_FAILURE, errno, "sched_setscheduler failed");
157
158
  if (pthread_attr_setschedparam (&attr, &schedp) != 0)
159
    error (EXIT_FAILURE, errno, "sched_setscheduler failed");
160
#endif
161
162
  if (pthread_create (&p->tid, &attr, function, (void *) p) != 0)
163
    error (EXIT_FAILURE, errno, "pthread_create failed");
164
}
165
166
static void *
167
signaler (void *arg)
168
{
169
  params_t *p = (params_t *) arg;
170
  uint32_t i;
171
172
  for (i = 0; i < p->iters; i++)
173
    {
174
      pthread_mutex_lock (&p->mutex);
175
      if (p->flags & BROADCAST_FLAG)
176
	{
177
	  TIMING_NOW (p->start);
178
	  if (pthread_cond_broadcast (&p->cond) != 0)
179
	    error (EXIT_FAILURE, errno, "pthread_cond_broadcast failed");
180
	}
181
      else
182
	{
183
	  TIMING_NOW (p->start);
184
	  if (pthread_cond_signal (&p->cond) != 0)
185
	    error (EXIT_FAILURE, errno, "pthread_cond_signal failed");
186
	}
187
      TIMING_NOW (p->stop);
188
      update_stats (p);
189
      pthread_mutex_unlock (&p->mutex);
190
    }
191
192
  return NULL;
193
}
194
195
static void
196
do_signal_test (size_t niters, size_t nthreads, uint32_t flags)
197
{
198
  uint32_t i;
199
  params_t *params;
200
201
  init_stats ();
202
203
  params = (params_t *) malloc (sizeof (params_t) * nthreads);
204
  if (params == NULL)
205
    error (EXIT_FAILURE, errno, "out of memory");
206
207
  for (i = 0; i < nthreads; i++)
208
    {
209
      params[i].iters = niters;
210
      params[i].flags = flags;
211
      create_thread (&params[i], signaler);
212
    }
213
214
  for (i = 0; i < nthreads; i++)
215
    pthread_join (params[i].tid, NULL);
216
217
  printf ("%s\t",
218
	  (flags & BROADCAST_FLAG) ?
219
	  "broadcast (w/o waiters)" : "signal (w/o waiters)");
220
  print_stats (niters, nthreads);
221
222
  free (params);
223
}
224
225
static void *
226
waiter (void *arg)
227
{
228
  params_t *p = (params_t *) arg;
229
  struct timespec ts;
230
231
  while (p->state == COND_START)
232
    {
233
      pthread_mutex_lock (&p->mutex);
234
      p->state = COND_WAITING;
235
      if (p->flags & TIMEDWAIT_FLAG)
236
	{
237
	  if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0)
238
	    error (EXIT_FAILURE, errno, "clock_gettime failed");
239
240
	  /* Long timeout value, for this benchmark
241
	     we do not want to time out. */
242
	  ts.tv_sec += 60;
243
	  if (pthread_cond_timedwait (&p->cond, &p->mutex, &ts) != 0)
244
	    error (EXIT_FAILURE, errno, "pthread_cond_timedwait failed");
245
	}
246
      else
247
	{
248
	  if (pthread_cond_wait (&p->cond, &p->mutex) != 0)
249
	    error (EXIT_FAILURE, errno, "pthread_cond_wait failed");
250
	}
251
      if (p->flags & ROUNDTRIP_FLAG)
252
	{
253
	  TIMING_NOW (p->stop);
254
	  update_stats (p);
255
	}
256
      if (p->state == COND_STOP)
257
	{
258
	  pthread_mutex_unlock (&p->mutex);
259
	  break;
260
	}
261
      p->state = COND_SIGNALED;
262
      pthread_mutex_unlock (&p->mutex);
263
264
      while (p->state == COND_SIGNALED)
265
	sched_yield ();
266
    }
267
268
  return NULL;
269
}
270
271
static void
272
signal_waiter (params_t *p)
273
{
274
  pthread_mutex_lock (&p->mutex);
275
  while (p->state == COND_START)
276
    {
277
      pthread_mutex_unlock (&p->mutex);
278
      sched_yield ();
279
      pthread_mutex_lock (&p->mutex);
280
    }
281
282
  if (p->flags & BROADCAST_FLAG)
283
    {
284
      TIMING_NOW (p->start);
285
      if (pthread_cond_broadcast (&p->cond) != 0)
286
	error (EXIT_FAILURE, errno, "pthread_cond_broadcast failed");
287
    }
288
  else
289
    {
290
      TIMING_NOW (p->start);
291
      if (pthread_cond_signal (&p->cond) != 0)
292
	error (EXIT_FAILURE, errno, "pthread_cond_signal failed");
293
    }
294
  if (!(p->flags & ROUNDTRIP_FLAG))
295
    {
296
      TIMING_NOW (p->stop);
297
      update_stats (p);
298
    }
299
300
  do
301
    {
302
      pthread_mutex_unlock (&p->mutex);
303
      sched_yield ();
304
      pthread_mutex_lock (&p->mutex);
305
    }
306
  while (p->state != COND_SIGNALED);
307
308
  p->state = COND_START;
309
  pthread_mutex_unlock (&p->mutex);
310
}
311
312
static void
313
stop_waiter (params_t *p)
314
{
315
  pthread_mutex_lock (&p->mutex);
316
  while (p->state != COND_WAITING)
317
    {
318
      pthread_mutex_unlock (&p->mutex);
319
      sched_yield ();
320
      pthread_mutex_lock (&p->mutex);
321
    }
322
  p->state = COND_STOP;
323
  pthread_cond_signal (&p->cond);
324
  pthread_mutex_unlock (&p->mutex);
325
326
  pthread_join (p->tid, NULL);
327
}
328
329
static void
330
do_test (size_t niters, size_t nthreads, uint32_t flags)
331
{
332
  size_t i, j;
333
  params_t *params;
334
335
  init_stats ();
336
337
  params = (params_t *) malloc (sizeof (params_t) * nthreads);
338
  if (params == NULL)
339
    error (EXIT_FAILURE, errno, "out of memory");
340
341
  for (i = 0; i < nthreads; i++)
342
    {
343
      params[i].flags = flags;
344
      create_thread (&params[i], waiter);
345
    }
346
347
  for (i = 0; i < niters; i++)
348
    for (j = 0; j < nthreads; j++)
349
      signal_waiter (&params[j]);
350
351
  for (i = 0; i < nthreads; i++)
352
    stop_waiter (&params[i]);
353
354
  if (flags & ROUNDTRIP_FLAG)
355
    printf ("%s/%s\t",
356
	    (flags & BROADCAST_FLAG) ? "broadcast" : "signal",
357
	    (flags & TIMEDWAIT_FLAG) ? "timedwait" : "wait\t");
358
  else
359
    printf ("%s\t\t",
360
	    (flags & BROADCAST_FLAG) ? "broadcast" : "signal\t");
361
  print_stats (niters, nthreads);
362
363
  free (params);
364
}
365
366
int
367
test_main (void)
368
{
369
  int ret;
370
371
  printf ("pthread_cond_[test]\titerations    threads    mean       min     "
372
	  "max         variance       std. deviation\n");
373
  printf ("-----------------------------------------------------------------"
374
	  "--------------------------------------------\n");
375
  do_signal_test (1000000, 100, 0);
376
  do_signal_test (1000000, 100, BROADCAST_FLAG);
377
  do_test (1000000, 1, 0);
378
  do_test (1000000, 1, BROADCAST_FLAG);
379
  do_test (100000, 100, ROUNDTRIP_FLAG);
380
  do_test (100000, 100, TIMEDWAIT_FLAG | ROUNDTRIP_FLAG);
381
  do_test (100000, 100, BROADCAST_FLAG | ROUNDTRIP_FLAG);
382
  do_test (100000, 100, BROADCAST_FLAG | TIMEDWAIT_FLAG | ROUNDTRIP_FLAG);
383
384
  return EXIT_SUCCESS;
385
}
386
387
#define TIMEOUT (4 * 60)
388
#define TEST_FUNCTION test_main ()
389
#include "../test-skeleton.c"

Return to bug 11588