1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Check that a thread which yields with pause (rep;nop) makes less 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown progress against a pure spinner. 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h> 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_mutex_t m_go = PTHREAD_MUTEX_INITIALIZER; 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_cond_t c_go = PTHREAD_COND_INITIALIZER; 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_cond_t c_running = PTHREAD_COND_INITIALIZER; 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic volatile int alive, running; 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int spin; 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int rep_nop; 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *spinner(void *v) 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock(&m_go); 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(!alive) 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_wait(&c_go, &m_go); 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown running++; 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal(&c_running); 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock(&m_go); 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(alive) 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spin++; 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *rep_nopper(void *v) 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock(&m_go); 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(!alive) 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_wait(&c_go, &m_go); 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown running++; 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal(&c_running); 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock(&m_go); 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(alive) { 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rep_nop++; 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This gives a hint to a P4, telling it to pause 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (ie. we're in a spin-wait loop) 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown asm volatile ("rep; nop" : : : "memory"); 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main() 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t a, b; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&a, NULL, spinner, NULL); 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&b, NULL, rep_nopper, NULL); 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* make sure both threads start at the same time */ 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock(&m_go); 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alive = 1; 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_broadcast(&c_go); 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* make sure they both get started */ 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(running < 2) 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_wait(&c_running, &m_go); 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock(&m_go); 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleep(2); 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alive = 0; 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join(a, NULL); 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join(b, NULL); 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("spin=%d rep_nop=%d rep_nop:spin ratio: %g\n", 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spin, rep_nop, (float)rep_nop / spin); 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (spin > rep_nop) 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("PASS\n"); 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("FAIL spin=%d rep_nop=%d rep_nop:spin ratio: %g\n", 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spin, rep_nop, (float)rep_nop / spin); 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 88