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,¶m); 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; } |