1// author: Marc Orr 2 3#include <pthread.h> 4#include <stdio.h> 5#include <stdlib.h> 6 7#define NUM_TRIES 1000 8 9// Make sure that flags and wait sit in different cache lines 10volatile int flags[10]; 11volatile int wait[10]; 12 13pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 14 15void *DoWork1(void *threadid) 16{ 17 flags[0] = flags[0] + 1; 18 wait[0] = 0; 19 pthread_exit(0); 20} 21 22void *DoWork2(void *threadid) 23{ 24 pthread_mutex_lock (&mutex); 25 flags[0] = flags[0] + 1; 26 pthread_mutex_unlock (&mutex); 27 pthread_exit(0); 28} 29 30//////////////////////////////////////////////////////////////////////////////// 31// Program main 32//////////////////////////////////////////////////////////////////////////////// 33int main( int argc, char** argv) 34{ 35 // stuff for thread 36 pthread_t threads[1]; 37 38 // initialize global variables 39 flags[0] = 0; 40 wait[0] = 1; 41 42 // monitor (via gcc intrinsic) 43 __builtin_ia32_monitor ((void *)&flags, 0, 0); 44 45 // invalidate flags in this cpu's cache 46 pthread_create(&threads[0], NULL, DoWork1, NULL); 47 while (wait[0]); 48 49 // launch thread to invalidate address being monitored 50 pthread_create(&threads[0], NULL, DoWork2, NULL); 51 52 // wait for other thread to modify flags 53 int mwait_cnt = 0; 54 do { 55 pthread_mutex_lock (&mutex); 56 if (flags[0] != 2) { 57 pthread_mutex_unlock (&mutex); 58 __builtin_ia32_mwait(0, 0); 59 } else { 60 pthread_mutex_unlock (&mutex); 61 } 62 mwait_cnt++; 63 } while (flags[0] != 2 && mwait_cnt < NUM_TRIES); 64 65 // test may hang if mwait is not working 66 if (flags[0]==2) { 67 printf("mwait regression PASSED, flags[0] = %d\n", flags[0]); 68 } else { 69 printf("mwait regression FAILED, flags[0] = %d\n", flags[0]); 70 } 71 72 return 0; 73} 74