Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : PulseAudio is free software; you can redistribute it and/or modify
5 : : it under the terms of the GNU Lesser General Public License as published
6 : : by the Free Software Foundation; either version 2.1 of the License,
7 : : or (at your option) any later version.
8 : :
9 : : PulseAudio is distributed in the hope that it will be useful, but
10 : : WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : : General Public License for more details.
13 : :
14 : : You should have received a copy of the GNU Lesser General Public License
15 : : along with PulseAudio; if not, write to the Free Software
16 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 : : USA.
18 : : ***/
19 : :
20 : : #ifdef HAVE_CONFIG_H
21 : : #include <config.h>
22 : : #endif
23 : :
24 : : #ifdef HAVE_PTHREAD
25 : : #include <pthread.h>
26 : : #endif
27 : :
28 : : #include <pulsecore/thread.h>
29 : : #include <pulsecore/once.h>
30 : : #include <pulsecore/log.h>
31 : : #include <pulsecore/core-util.h>
32 : : #include <pulsecore/atomic.h>
33 : : #include <pulse/xmalloc.h>
34 : :
35 : : static pa_once once = PA_ONCE_INIT;
36 : : static volatile unsigned n_run = 0;
37 : : static const char * volatile ran_by = NULL;
38 : : #ifdef HAVE_PTHREAD
39 : : static pthread_barrier_t barrier;
40 : : #endif
41 : : static unsigned n_cpu;
42 : :
43 : : #define N_ITERATIONS 500
44 : : #define N_THREADS 100
45 : :
46 : 500 : static void once_func(void) {
47 : 500 : n_run++;
48 : 500 : ran_by = (const char*) pa_thread_get_data(pa_thread_self());
49 : 500 : }
50 : :
51 : 49991 : static void thread_func(void *data) {
52 : : #ifdef HAVE_PTHREAD
53 : : int r;
54 : :
55 : : #ifdef HAVE_PTHREAD_SETAFFINITY_NP
56 : : static pa_atomic_t i_cpu = PA_ATOMIC_INIT(0);
57 : : cpu_set_t mask;
58 : :
59 : 49991 : CPU_ZERO(&mask);
60 [ + ]: 49991 : CPU_SET((size_t) (pa_atomic_inc(&i_cpu) % n_cpu), &mask);
61 [ - + ]: 49991 : pa_assert_se(pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == 0);
62 : : #endif
63 : :
64 : 49971 : pa_log_debug("started up: %s", (char *) data);
65 : :
66 : 49984 : r = pthread_barrier_wait(&barrier);
67 [ - + ]: 48766 : pa_assert(r == 0 || r == PTHREAD_BARRIER_SERIAL_THREAD);
68 : : #endif /* HAVE_PTHREAD */
69 : :
70 : 48766 : pa_run_once(&once, once_func);
71 : 49165 : }
72 : :
73 : 1 : int main(int argc, char *argv[]) {
74 : : unsigned n, i;
75 : :
76 [ - + ]: 1 : if (!getenv("MAKE_CHECK"))
77 : 0 : pa_log_set_level(PA_LOG_DEBUG);
78 : :
79 : 1 : n_cpu = pa_ncpus();
80 : :
81 [ + + ]: 501 : for (n = 0; n < N_ITERATIONS; n++) {
82 : : pa_thread* threads[N_THREADS];
83 : :
84 : : #ifdef HAVE_PTHREAD
85 [ - + ]: 500 : pa_assert_se(pthread_barrier_init(&barrier, NULL, N_THREADS) == 0);
86 : : #endif
87 : :
88 : : /* Yes, kinda ugly */
89 : : pa_zero(once);
90 : :
91 [ + + ]: 50500 : for (i = 0; i < N_THREADS; i++)
92 : 50000 : threads[i] = pa_thread_new("once", thread_func, pa_sprintf_malloc("Thread #%i", i+1));
93 : :
94 [ + + ]: 50500 : for (i = 0; i < N_THREADS; i++)
95 : 50000 : pa_thread_join(threads[i]);
96 : :
97 [ - + ]: 500 : pa_assert(n_run == 1);
98 : 500 : pa_log_info("ran by %s", ran_by);
99 : :
100 [ + + ]: 50500 : for (i = 0; i < N_THREADS; i++) {
101 : 50000 : pa_xfree(pa_thread_get_data(threads[i]));
102 : 50000 : pa_thread_free(threads[i]);
103 : : }
104 : :
105 : 500 : n_run = 0;
106 : 500 : ran_by = NULL;
107 : :
108 : : #ifdef HAVE_PTHREAD
109 [ - + ]: 500 : pa_assert_se(pthread_barrier_destroy(&barrier) == 0);
110 : : #endif
111 : : }
112 : :
113 : : return 0;
114 : : }
|