Home | History | Annotate | Download | only in x86
      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>
      9 
     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;
     13 
     14 static volatile int alive, running;
     15 
     16 static int spin;
     17 static int rep_nop;
     18 
     19 static void *spinner(void *v)
     20 {
     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);
     27 
     28 	while(alive)
     29 		spin++;
     30 
     31 	return 0;
     32 }
     33 
     34 static void *rep_nopper(void *v)
     35 {
     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);
     42 
     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");
     48 	}
     49 
     50 	return 0;
     51 }
     52 
     53 int main()
     54 {
     55 	pthread_t a, b;
     56 
     57 	pthread_create(&a, NULL, spinner, NULL);
     58 	pthread_create(&b, NULL, rep_nopper, NULL);
     59 
     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);
     64 
     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);
     69 
     70 	sleep(2);
     71 
     72 	alive = 0;
     73 	pthread_join(a, NULL);
     74 	pthread_join(b, NULL);
     75 
     76 	if (0)
     77 		printf("spin=%d rep_nop=%d rep_nop:spin ratio: %g\n",
     78 		       spin, rep_nop, (float)rep_nop / spin);
     79 
     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);
     85 
     86 	return 0;
     87 }
     88