BRL-CAD
bu_semaphore.c
Go to the documentation of this file.
1 /* B U _ S E M A P H O R E . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2013-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file bu_semaphore.c
21  *
22  * Tests libbu semaphore locking.
23  *
24  */
25 
26 #include "common.h"
27 
28 #include "bu.h"
29 
30 
31 const int SEM = BU_SEM_LAST+1;
32 
33 
35  size_t ncpu;
36  int *parallel;
37  int *running;
38  size_t reps;
39  size_t *counter;
40 };
41 
42 
43 static int
44 repeat_test(size_t reps)
45 {
46  size_t i;
47 
48  for (i = 0; i < reps; i++)
50 
51  for (i = 0; i < reps; i++)
53 
54  return 1;
55 }
56 
57 
58 
59 static void
60 increment_thread(int cpu, void *pargs)
61 {
62  struct increment_thread_args *args = (struct increment_thread_args *)pargs;
63  size_t i = 0;
64 
66  if (*args->running)
67  *args->parallel = 1;
68  *args->running = cpu+1;
70 
71  for (i = 0; i < args->reps; i++) {
73  ++*args->counter;
75  }
76 
77  while (args->ncpu > 1 && i++ < UINT32_MAX-1 && !*args->parallel) {
79  ++*args->counter;
80  --*args->counter;
82  }
83 
85  *args->running = 0;
87 
88  return;
89 }
90 
91 
92 static int
93 parallel_test(size_t ncpu, size_t reps)
94 {
95  int parallel = 0;
96  int running = 0;
97 
98  size_t counter = 0;
99  size_t expected = reps * ncpu;
100 
101  struct increment_thread_args args;
102 
103  args.ncpu = ncpu;
104  args.parallel = &parallel;
105  args.running = &running;
106  args.reps = reps;
107  args.counter = &counter;
108 
109  /* By default, bu_parallel() refuses to create more threads than
110  * there are CPUs on the host system. Setting the
111  * BU_DEBUG_PARALLEL flag makes bu_debug() create the specified
112  * number of threads even if the host system doesn't have that
113  * many actual CPUs. This permits multithreaded testing on
114  * systems with fewer than necessary (e.g. 1) cores.
115  */
117 
118  bu_parallel(increment_thread, ncpu, &args);
119 
120  if (counter != expected) {
121  bu_log("bu_semaphore parallel increment test: counter is %lu, expected %lu\n [FAIL]", counter, expected);
122  return 0;
123  }
124 
125  if ((ncpu > 1) && !parallel) {
126  bu_log("bu_semaphore parallel thread test: did not run in parallel [FAIL]\n");
127  return 0;
128  }
129 
130  return 1;
131 }
132 
133 
134 int
135 main(int argc, char **argv)
136 {
137  const char * const USAGE = "Usage: %s [-P ncpu] [-n reps]\n";
138 
139  int c;
140  int success;
141  size_t nreps = 1000;
142  unsigned long nreps_opt;
143  size_t ncpu = bu_avail_cpus();
144  unsigned long ncpu_opt;
145 
146  while ((c = bu_getopt(argc, argv, "n:P:")) != -1) {
147  switch (c) {
148  case 'n':
149  nreps_opt = (uint32_t)strtoul(bu_optarg, NULL, 0);
150  if (nreps_opt > 0 && nreps_opt < UINT32_MAX-1)
151  nreps = (size_t)nreps_opt;
152  break;
153  case 'P':
154  ncpu_opt = (size_t)strtoul(bu_optarg, NULL, 0);
155  if (ncpu_opt > 0 && ncpu_opt < MAX_PSW)
156  ncpu = ncpu_opt;
157  break;
158  default:
159  bu_exit(1, USAGE, argv[0]);
160  }
161  }
162 
163  /* nreps is a minimum */
164  success = repeat_test(nreps) && parallel_test(ncpu, nreps);
165 
166  return !(success);
167 }
168 
169 
170 /*
171  * Local Variables:
172  * mode: C
173  * tab-width: 8
174  * indent-tabs-mode: t
175  * c-file-style: "stroustrup"
176  * End:
177  * ex: shiftwidth=4 tabstop=8
178  */
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
#define BU_DEBUG_PARALLEL
Definition: debug.h:58
void bu_semaphore_init(unsigned int nsemaphores)
Definition: semaphore.c:82
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
#define BU_SEM_LAST
Definition: parallel.h:185
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
int main(int argc, char **argv)
Definition: bu_semaphore.c:135
size_t counter[MAX_PSW]
Definition: bu_parallel.c:42
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
const int SEM
Definition: bu_semaphore.c:31
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
size_t bu_avail_cpus(void)
Definition: parallel.c:193
#define MAX_PSW
Definition: parallel.h:48
void bu_parallel(void(*func)(int func_ncpu, void *func_data), int ncpu, void *data)
void bu_semaphore_free(void)
Definition: semaphore.c:144
int bu_debug
Definition: globals.c:87
#define USAGE
Definition: bntester.c:38