系统SMP能力测试

1)启动一个线程,不停进行加锁、解锁操作一定时间,统计操作次数 ;

2)假设核数为N,启动N个线程,使用posix接口将其分别绑定到0...N-1核,并行进行独立的加锁、解锁操作相同时间(各线程操作各自的锁),统计各自的操作次数;

3)比较C0...Cn 相等


#include "testfrmw.h"
#include "smp_test.h"


volatile int cap_count[CPU_NUM];
volatile int cap_count_temp[CPU_NUM];
volatile int cap_count_base;
pthread_mutex_t cap_pth_mutex[CPU_NUM];


int cap_main_ret = 0;


static void get_dynamic_range(void)
{
    int history_count;


    history_count = cap_count[0];
    sleep(TEST_UNIT);
    cap_count_base = cap_count[0] - history_count;
}


static int get_base_count(void)
{
    int ret;
    pthread_t base_pid;
    int base_coreid = 0;
    smp_arg_stru arg_stru;
    arg_stru.pcount = &cap_count[0];
    arg_stru.pmutex = &cap_pth_mutex[0];


    ret = smp_base_init(&base_pid,&arg_stru,base_coreid);
    if(ret)
    {
        printf("smp_base_init fail!\n");
        goto fail;
    }


    get_dynamic_range();


    ret = smp_cycling(&base_pid, &arg_stru,1);
    if(ret)
    {
        printf("smp_cycling fail!\n");
        goto fail;
    }


    return 0;


fail:
    smp_cycling(&base_pid, &arg_stru,1);
    return ret;
}


static void normal_get_dynamic_range(void)
{
    int id;


    memcpy((void*)cap_count_temp,(void*)cap_count,sizeof(cap_count));
    sleep(TEST_UNIT);
    for(id = 0; id < CPU_NUM; id++)
        cap_count_temp[id] = cap_count[id] - cap_count_temp[id];
}


static int get_normal_count(void)
{
    int id;
    int ret;
    pthread_t t_id[CPU_NUM];
    smp_arg_stru arg_stru[CPU_NUM];


    //每核创建一个常驻线程
    for(id = 0; id < CPU_NUM; id++)
    {
        arg_stru[id].pcount = &cap_count[id];
        arg_stru[id].pmutex = &cap_pth_mutex[id];


        ret = smp_base_init(&t_id[id],&arg_stru[id],id);
        if(ret)
        {
            printf("smp_base_init fail!\n");
            goto fail;
        }
    }


    normal_get_dynamic_range();


    ret = smp_cycling(t_id, arg_stru,CPU_NUM);
    if(ret)
    {
        printf("smp_cycling fail!\n");
        goto fail;
    }
    return 0;


fail:
    smp_cycling(t_id, arg_stru,CPU_NUM);
    return ret;
}


static int check_result(void)
{
    int id;
    int gap = cap_count_base/10;


    for(id = 0; id < CPU_NUM; id++)
    {
        if(absolute_value(cap_count_temp[id]-cap_count_base) > gap)
        {
            printf("cap_check_result fail on cpu%d\n",id);
            return 1;
        }
    }
    return 0;
}


static void *main_thread(void *arg)
{
    int ret;
    ret = get_base_count();
    if(ret)
    {
        printf("get_base_count fail!\n");
        goto fail;
    }
    ret = get_normal_count();
    if(ret)
    {
        printf("get_normal_count fail!\n");
        goto fail;
    }


    ret = check_result();
    if(ret)
    {
        printf("cap_check_result fail!\n");
        goto fail;
    }


    *(int*)arg = 0;
    return arg;


fail:
    *(int*)arg = ret;
    return arg;


}


#ifndef USE_CUNIT
 int main(void)
#else
 static int main_entry(void)
#endif
 {
    pthread_t main_pid;
    pthread_attr_t attr;
    int* p_main_ret = &cap_main_ret;


    if(set_pthread_attr(&attr,MAIN_PROC_PRIORITY,SCHED_FIFO))
    {
        printf("set_pthread_attr fail!\n");
        return PTS_FAIL;
    }


    //创建主线程,绑到主核,优先级设置高于子线程
    if(pthread_create(&main_pid,&attr,main_thread,p_main_ret))
    {
        printf("create main thread fail!\n");
        return PTS_FAIL;
    }
    if(bind_thread_to_cpu(main_pid,MAIN_CORE_ID))
    {
        printf("bind_thread_to_cpu fail!\n");
        return PTS_FAIL;
    }


    if(pthread_join(main_pid,&p_main_ret))
    {
        printf("pthread_join main thread fail!\n");
        return PTS_FAIL;
    }


    if(*p_main_ret != 0)
    {
        printf("TEST FAIL\n");
        return PTS_FAIL;
    }


    printf("TEST PASSED\n");
    return PTS_PASS;
 }
#ifdef USE_CUNIT
 DEFINE_TC_ENTRY(smp_cap_1_1, main_entry);
#endif

其中,smp_test.h

#ifndef SMP_TEST_H
#define SMP_TEST_H


#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#include <sched.h>


//#define CPU_NUM (4)
#define MAIN_PROC_PRIORITY (10)
#define CHILD_PROC_PRIORITY (9)
#define MAIN_CORE_ID (0)
#define TEST_UNIT (1)


typedef struct
{
    pthread_mutex_t* pmutex;
    int* pcount;
}smp_arg_stru;


extern int set_pthread_attr(pthread_attr_t* p_attr, int prio, int policy);
extern int bind_thread_to_cpu(pthread_t thread,int cpu_id);
extern void *smp_thread_proc(void *arg);
extern int smp_pthread_init(pthread_t* pid,smp_arg_stru* p_arg_stru,int core_id);
extern int smp_base_init(pthread_t* pid,smp_arg_stru* p_arg_stru,int core_id);
extern int smp_cycling(pthread_t* p_thread_id, smp_arg_stru* p_arg_stru, int count);
extern unsigned int absolute_value(int intValue);


#endif

smp_test_comm.c



#include "smp_test.h"


int set_pthread_attr(pthread_attr_t* p_attr, int prio, int policy)
{
    int ret;
    struct sched_param param;


    param.sched_priority = prio;


    ret = pthread_attr_init(p_attr);
    if(ret)
    {
        printf("pthread_attr_init fail.\n");
        return ret;
    }
    ret = pthread_attr_setschedpolicy(p_attr, policy);
    if(ret)
    {
        printf("pthread_attr_setschedpolicy fail.\n");
        return ret;
    }
    ret = pthread_attr_setschedparam(p_attr,&param);
    if(ret)
    {
        printf("pthread_attr_setschedparam fail.\n");
        return ret;
    }


    return 0;
}


int bind_thread_to_cpu(pthread_t thread,int cpu_id)
{
    cpu_set_t mask;
    int ret;


    CPU_ZERO(&mask);
    CPU_SET(cpu_id, &mask);


    ret = pthread_setaffinity_np(thread, sizeof(mask), &mask);
    if(ret)
    {
        printf("pthread_setaffinity_np fail!\n");
        return ret;
    }
    usleep(100000);
    return 0;
}


void *smp_thread_proc(void *arg)
{
    int id;
    long sum;
    smp_arg_stru* p_arg_stru = (smp_arg_stru*)arg;


    if((p_arg_stru->pcount == NULL)||(p_arg_stru->pmutex == NULL))
    {
        printf("smp_thread_proc arg null,please check!\n");
        pthread_exit(NULL);
    }
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);


    while(1)
    {
        if(pthread_mutex_lock(p_arg_stru->pmutex))
        {
            printf("pthread_mutex_lock fail!\n");
            pthread_exit(NULL);
        }


        for(id = 0,sum = 0; id < 100000; id++)
            sum += id;


        (*p_arg_stru->pcount)++;


        if(pthread_mutex_unlock(p_arg_stru->pmutex))
        {
            printf("pthread_mutex_unlock fail,sum:0x%lx\n",sum);
            pthread_exit(NULL);
        }


        //设置取消点
        pthread_testcancel();
    }
}


int smp_pthread_init(pthread_t* pid,smp_arg_stru* p_arg_stru,int core_id)
{
    int ret;
    pthread_attr_t attr;


    ret = set_pthread_attr(&attr,CHILD_PROC_PRIORITY,SCHED_RR);
    if(ret)
    {
        printf("set_pthread_attr fail!\n");
        return ret;
    }


    ret = pthread_create(pid,&attr,smp_thread_proc,(void*)p_arg_stru);
    if(ret)
    {
        printf("create base thread fail!\n");
        return ret;
    }
    ret = bind_thread_to_cpu(*pid,core_id);
    if(ret)
    {
        printf("bind_thread_to_cpu%d fail!\n",core_id);
        return ret;
    }
    usleep(100000);


    return 0;
}


int smp_base_init(pthread_t* pid,smp_arg_stru* p_arg_stru,int core_id)
{
    int ret;
    pthread_attr_t attr;


    ret = pthread_mutex_init(p_arg_stru->pmutex,NULL);
    if(ret)
    {
        printf("pthread_mutex_init fail!\n");
        return ret;
    }


    ret = smp_pthread_init(pid, p_arg_stru, core_id);
    if(ret)
    {
        printf("smp_pthread_init fail!\n");
        return ret;
    }


    return 0;
}


int smp_cycling(pthread_t* p_thread_id, smp_arg_stru* p_arg_stru, int count)
{
    int id;
    int ret;


    for(id = 0; id < count; id++)
    {
        ret = pthread_cancel(*(p_thread_id + id));
        if(ret)
        {
            printf("pthread_cancel fail on cpu%d!\n",id);
            return ret;
        }
        usleep(50000);
        if(p_arg_stru)
        {
            ret = pthread_mutex_destroy((p_arg_stru+id)->pmutex);
            if(ret)
            {
                printf("pthread_mutex_destroy fail on cpu%d!\n",id);
                return ret;
            }
        }
        usleep(50000);
    }


    return 0;
}


unsigned int absolute_value(int intValue)
{
    if(intValue > 0)
        return intValue;
    else
        return -intValue;
}


猜你喜欢

转载自blog.csdn.net/gaojy19881225/article/details/80527521