//http://www.novickscode.com/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <features.h>

struct timespec diff_timespec(struct timespec start, struct timespec end);
long long nanosec_elapsed(struct timespec diff);

#define ITERS_PER_TEST 500000

unsigned long counter = 0;

pthread_mutex_t mutex;
pthread_rwlock_t rwlock;
pthread_spinlock_t spinlock;
typedef void* thread_func_t(void*);

void* atomic(void* arg){

    int i;
    for (i = 0 ; i < ITERS_PER_TEST; ++i) {
        __sync_fetch_and_add( &counter, 1 );
    }
}

void* mutexfunc(void* arg){

    int i;
    for (i = 0 ; i < ITERS_PER_TEST; ++i) {
        pthread_mutex_lock(&mutex);
        counter++;
        pthread_mutex_unlock(&mutex);
    }
}

void* spin(void* arg){

    int i;
    for (i = 0 ; i < ITERS_PER_TEST; ++i) {
        pthread_spin_lock(&spinlock);
        counter++;
        pthread_spin_unlock(&spinlock);
    }
}

void* read_lock(void* arg){

    int i;
    for (i = 0 ; i < ITERS_PER_TEST; ++i) {
        pthread_rwlock_rdlock(&rwlock);
        counter++;
        pthread_rwlock_unlock(&rwlock);
    }
}

void* write_lock(void* arg){

    int i;
    for (i = 0 ; i < ITERS_PER_TEST; ++i) {
        pthread_rwlock_wrlock(&rwlock);
        counter++;
        pthread_rwlock_unlock(&rwlock);
    }
}

void do_test(thread_func_t func, unsigned short threads, const char* name){

    int i;
    struct timespec start;
    struct timespec end;
    struct timespec diff;

    pthread_t thread_array[threads];
    counter = 0;

    clock_gettime(CLOCK_MONOTONIC, &start);

    for (i = 0; i < threads; ++i){
        if (pthread_create( &thread_array[i], NULL, func, NULL)){
            printf("error creating threads, exiting");
            exit(1);
        }
    }

    for (i = 0; i < threads; i++)
        pthread_join( thread_array[i], NULL );


    clock_gettime(CLOCK_MONOTONIC, &end);
    diff = diff_timespec(start, end);
    printf("%14s %2d threads took %16lld nanoseconds, global counter = %lu\n", name, threads, nanosec_elapsed(diff), counter);
}

void do_all_tests(int threads){
    printf("*************************************\n");
    fflush(stdout);
    do_test(&atomic, threads, "atomic");
    do_test(&mutexfunc, threads, "mutex");
    do_test(&spin, threads, "spin");
    do_test(&read_lock, threads, "read_lock");
    do_test(&write_lock, threads, "write_lock");
    printf("*************************************\n");
    fflush(stdout);
}

int main(int argc, char** argv)
{
    pthread_mutex_init(&mutex, NULL);
    pthread_rwlock_init(&rwlock, NULL);
    pthread_spin_init(&spinlock, 0);

    do_all_tests(1);
    do_all_tests(2);
    do_all_tests(4);

    pthread_mutex_destroy(&mutex);
    pthread_rwlock_destroy(&rwlock);
    pthread_spin_destroy(&spinlock);


    return 0;
}

struct timespec diff_timespec(struct timespec start, struct timespec end)
{
    struct timespec result;

    if (end.tv_nsec < start.tv_nsec){
        result.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
        result.tv_sec = end.tv_sec - 1 - start.tv_sec;
    }
    else{
        result.tv_nsec = end.tv_nsec - start.tv_nsec;
        result.tv_sec = end.tv_sec - start.tv_sec;
    }

    return result;
}

long long nanosec_elapsed(struct timespec diff){
    return ((long long)diff.tv_sec * 1000000000) + diff.tv_nsec;
}

 

 

創作者介紹
創作者 hedgezzz 的頭像
hedgezzz

hedgezzz的部落格

hedgezzz 發表在 痞客邦 留言(0) 人氣()