110528Smorr@cs.wisc.edu// author: Marc Orr
210528Smorr@cs.wisc.edu
310528Smorr@cs.wisc.edu#include <pthread.h>
410528Smorr@cs.wisc.edu#include <stdio.h>
510528Smorr@cs.wisc.edu#include <stdlib.h>
610528Smorr@cs.wisc.edu
710528Smorr@cs.wisc.edu#define NUM_TRIES   1000
810528Smorr@cs.wisc.edu
910528Smorr@cs.wisc.edu// Make sure that flags and wait sit in different cache lines
1010528Smorr@cs.wisc.eduvolatile int flags[10];
1110528Smorr@cs.wisc.eduvolatile int wait[10];
1210528Smorr@cs.wisc.edu
1310528Smorr@cs.wisc.edupthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
1410528Smorr@cs.wisc.edu
1510528Smorr@cs.wisc.eduvoid *DoWork1(void *threadid)
1610528Smorr@cs.wisc.edu{
1710528Smorr@cs.wisc.edu    flags[0] = flags[0] + 1;
1810528Smorr@cs.wisc.edu    wait[0] = 0;
1910528Smorr@cs.wisc.edu    pthread_exit(0);
2010528Smorr@cs.wisc.edu}
2110528Smorr@cs.wisc.edu
2210528Smorr@cs.wisc.eduvoid *DoWork2(void *threadid)
2310528Smorr@cs.wisc.edu{
2410528Smorr@cs.wisc.edu    pthread_mutex_lock (&mutex);
2510528Smorr@cs.wisc.edu    flags[0] = flags[0] + 1;
2610528Smorr@cs.wisc.edu    pthread_mutex_unlock (&mutex);
2710528Smorr@cs.wisc.edu    pthread_exit(0);
2810528Smorr@cs.wisc.edu}
2910528Smorr@cs.wisc.edu
3010528Smorr@cs.wisc.edu////////////////////////////////////////////////////////////////////////////////
3110528Smorr@cs.wisc.edu// Program main
3210528Smorr@cs.wisc.edu////////////////////////////////////////////////////////////////////////////////
3310528Smorr@cs.wisc.eduint main( int argc, char** argv)
3410528Smorr@cs.wisc.edu{
3510528Smorr@cs.wisc.edu    // stuff for thread
3610528Smorr@cs.wisc.edu    pthread_t threads[1];
3710528Smorr@cs.wisc.edu
3810528Smorr@cs.wisc.edu    // initialize global variables
3910528Smorr@cs.wisc.edu    flags[0] = 0;
4010528Smorr@cs.wisc.edu    wait[0] = 1;
4110528Smorr@cs.wisc.edu
4210528Smorr@cs.wisc.edu    // monitor (via gcc intrinsic)
4310528Smorr@cs.wisc.edu    __builtin_ia32_monitor ((void *)&flags, 0, 0);
4410528Smorr@cs.wisc.edu
4510528Smorr@cs.wisc.edu    // invalidate flags in this cpu's cache
4610528Smorr@cs.wisc.edu    pthread_create(&threads[0], NULL, DoWork1, NULL);
4711321Ssteve.reinhardt@amd.com    while (wait[0]);
4810528Smorr@cs.wisc.edu
4910528Smorr@cs.wisc.edu    // launch thread to invalidate address being monitored
5010528Smorr@cs.wisc.edu    pthread_create(&threads[0], NULL, DoWork2, NULL);
5110528Smorr@cs.wisc.edu
5210528Smorr@cs.wisc.edu    // wait for other thread to modify flags
5310528Smorr@cs.wisc.edu    int mwait_cnt = 0;
5410528Smorr@cs.wisc.edu    do {
5510528Smorr@cs.wisc.edu        pthread_mutex_lock (&mutex);
5611321Ssteve.reinhardt@amd.com        if (flags[0] != 2) {
5710528Smorr@cs.wisc.edu            pthread_mutex_unlock (&mutex);
5810528Smorr@cs.wisc.edu            __builtin_ia32_mwait(0, 0);
5910528Smorr@cs.wisc.edu        } else {
6010528Smorr@cs.wisc.edu            pthread_mutex_unlock (&mutex);
6110528Smorr@cs.wisc.edu        }
6210528Smorr@cs.wisc.edu        mwait_cnt++;
6311321Ssteve.reinhardt@amd.com    } while (flags[0] != 2 && mwait_cnt < NUM_TRIES);
6410528Smorr@cs.wisc.edu
6510528Smorr@cs.wisc.edu    // test may hang if mwait is not working
6611321Ssteve.reinhardt@amd.com    if (flags[0]==2) {
6710528Smorr@cs.wisc.edu        printf("mwait regression PASSED, flags[0] = %d\n", flags[0]);
6810528Smorr@cs.wisc.edu    } else {
6910528Smorr@cs.wisc.edu        printf("mwait regression FAILED, flags[0] = %d\n", flags[0]);
7010528Smorr@cs.wisc.edu    }
7110528Smorr@cs.wisc.edu
7210528Smorr@cs.wisc.edu    return 0;
7310528Smorr@cs.wisc.edu}
74