drd/tests/swapcontext: Improve the portability of this test further
[valgrind.git] / none / tests / x86 / yield.c
blob78fc1f4216a2929076b15716e9868952f1f37185
1 /*
2 Check that a thread which yields with pause (rep;nop) makes less
3 progress against a pure spinner.
4 */
5 #include <pthread.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
10 static pthread_mutex_t m_go = PTHREAD_MUTEX_INITIALIZER;
11 static pthread_cond_t c_go = PTHREAD_COND_INITIALIZER;
12 static pthread_cond_t c_running = PTHREAD_COND_INITIALIZER;
14 static volatile int alive, running;
16 static int spin;
17 static int rep_nop;
19 static void *spinner(void *v)
21 pthread_mutex_lock(&m_go);
22 while(!alive)
23 pthread_cond_wait(&c_go, &m_go);
24 running++;
25 pthread_cond_signal(&c_running);
26 pthread_mutex_unlock(&m_go);
28 while(alive)
29 spin++;
31 return 0;
34 static void *rep_nopper(void *v)
36 pthread_mutex_lock(&m_go);
37 while(!alive)
38 pthread_cond_wait(&c_go, &m_go);
39 running++;
40 pthread_cond_signal(&c_running);
41 pthread_mutex_unlock(&m_go);
43 while(alive) {
44 rep_nop++;
45 // This gives a hint to a P4, telling it to pause
46 // (ie. we're in a spin-wait loop)
47 asm volatile ("rep; nop" : : : "memory");
50 return 0;
53 int main()
55 pthread_t a, b;
57 pthread_create(&a, NULL, spinner, NULL);
58 pthread_create(&b, NULL, rep_nopper, NULL);
60 /* make sure both threads start at the same time */
61 pthread_mutex_lock(&m_go);
62 alive = 1;
63 pthread_cond_broadcast(&c_go);
65 /* make sure they both get started */
66 while(running < 2)
67 pthread_cond_wait(&c_running, &m_go);
68 pthread_mutex_unlock(&m_go);
70 sleep(2);
72 alive = 0;
73 pthread_join(a, NULL);
74 pthread_join(b, NULL);
76 if (0)
77 printf("spin=%d rep_nop=%d rep_nop:spin ratio: %g\n",
78 spin, rep_nop, (float)rep_nop / spin);
80 if (spin > rep_nop)
81 printf("PASS\n");
82 else
83 printf("FAIL spin=%d rep_nop=%d rep_nop:spin ratio: %g\n",
84 spin, rep_nop, (float)rep_nop / spin);
86 return 0;