先把代码贴上,后面在做讲解。。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/epoll.h>
void set_thread_affinity(int cpuid);
int set_sc(int type,int prority);
void rtclock_gettime(unsigned long long *tt);
int allocate_rtcore();
int release_rtcore();
int smp_comm1();
#define SEND_ONLY 0
#define RT_MODE_ENABLE 1
#define MAX_PROCESS_NUM 64
#define MSG_SIZE 24
struct Process
{
int id;
pid_t pid;
}process;
struct Process *processes;
int nr_process = 4;
int shm_fd;
int epoll_fd;
static pthread_barrier_t *barrier;
static char *shm_buffer;
#define SHARE_RFIFO_PATH "/home/tmp/_fifo"
#define SHARE_WFIFO_PATH "/home/tmp/_fifo"
#define F 2.2E3
int on_cpu;
double dval = 1.23;
double sendbuf[4096];
double recvbuf[4096];
static int testloop = 8000;
static int calcloop = 50;
void delay(int loop)
{
int i,j;
for(i=0; i<loop;i++)
for(j=0; j<100000; j++)
dval = sin(3.1415926 + 0.5*dval);
}
int do_calc(int loop)
{
int i,j;
for(i=0; i<loop; i++) {
for(j=0; j<nr_process; j++) {
dval = sin(recvbuf[j]*3.1415926 + 0.5);
sendbuf[i%sizeof(sendbuf)] += dval;
}
}
}
int process_barrier(char *barrier)
{
char *p = barrier;
int i,sum = 0;
int id = process.id;
unsigned int count=0;
static int flag = 1;
p[id] = flag;
while(sum != nr_process){
sum = 0;
for(i=0; i<nr_process; i++) {
if(p[i] == flag)
sum++;
}
count++;
}
flag = flag ? 0 : 1;
//printf("child%d: barrier num %d\n", process.id, count);
return 0;
}
int do_simulation(int loop_num, int one_loop_num)
{
int i, count = 0, ret = 0;
struct timeval tv1, tv2;
unsigned long long t1,t2,t3,t4,t5,t6;
unsigned long long us1, us2, ms1, ms2;
unsigned long long ms, us;
unsigned long long val, cal, sum_cal, sum_val, avg_cal, avg_val;
unsigned long long tmax_val=0, tmin_val=100000000,tmax_cal=0,tmin_cal=100000000;
int skip = 0, warm = 10;
sum_cal = 0;
sum_val = 0;
for(i=1; i<=loop_num; i++) {
ret = process_barrier((char*)barrier);
if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("process%d pid[%d]: barrier_wait error! %s\n", process.id, process.pid, strerror(errno));
return -1;
}
rtclock_gettime(&t1);
if(i % 5000 == 0) {
//printf("[%d]: t1 %llu, t2 %llu, t3 %llu\n", process.pid,t1,t2,t3);
}
skip = smp_comm1();
rtclock_gettime(&t2);
do_calc(one_loop_num);
rtclock_gettime(&t3);
if(skip)
continue;
if(i > warm) {
val = (t3 - t1)/1000;
if(val > tmax_val) {
tmax_val = val;
}
if(val < tmin_val) {
tmin_val = val;
}
cal = (t3 - t2)/1000;
if(cal > tmax_cal) {
tmax_cal = cal;
}
if(cal < tmin_cal) {
tmin_cal = cal;
}
sum_val += val;
sum_cal += cal;
count++;
}
}
avg_val = sum_val/(loop_num-warm);
avg_cal = sum_cal/(loop_num-warm);
#if 0
tmax_val /= F;tmin_val /= F;avg_val /= F;
tmax_cal /= F;tmin_cal /= F;avg_cal /= F;
#endif
printf("on cpu %d count %d, Jitter %llu, mean %llu max %llu, min %llu | CALC: J %llu mean %llu max %llu min %llu\n", \
process.id+1, count, tmax_val-avg_val, avg_val, tmax_val, tmin_val,\
tmax_cal-avg_cal, avg_cal, tmax_cal, tmin_cal);
return 0;
}
void *process_func(void *args)
{
int ret;
int loop = 1;
char buf[4096];
set_thread_affinity(process.id+1);
sleep(1);
set_sc(0,90);
#if RT_MODE_ENABLE
//allocate_rtcore();
#endif
do_simulation(testloop, calcloop);
#if RT_MODE_ENABLE
release_rtcore();
#endif
err:
exit(ret);
}
void print_shm()
{
int i,j,k;
int idx=0;
char *p;
for(i=0; i<nr_process; i++) {
for(j=0; j<nr_process; j++) {
if(i == j)
continue;
printf("[%d-%d]: ",i,j);
p = shm_buffer+(idx*MSG_SIZE);
for(k=0; k<MSG_SIZE; k++)
printf(" %d", p[k]);
printf("\n");
idx++;
}
}
}
int get_shm_idx(int send_id, int recv_id)
{
int i,j;
int idx = 0;
int tmp;
for(i=0; i<nr_process; i++) {
for(j=0; j<nr_process; j++) {
if(i == j)
continue;
if(send_id == i && recv_id == j)
return idx;
idx++;
}
}
return idx;
}
char* get_shm_offset(int send_id, int recv_id)
{
int idx = 0;
idx = get_shm_idx(send_id, recv_id);
if(idx == nr_process*(nr_process-1))
printf("child%d: cannot find shm !\n", process.id);
return shm_buffer + idx*MSG_SIZE;
}
int smp_recv()
{
int i,j,k,n,sum = 0;
char *p;
char buf[MSG_SIZE];
int flag[256] = {0};
while(sum != nr_process-1) {
for(i=0; i<nr_process; i++) {
if(i == process.id)
continue;
if(flag[i] == 1)
continue;
n = 0;
p = get_shm_offset(i, process.id);
for(j=0; j<MSG_SIZE; j++) {
n += p[j];
}
if(n == MSG_SIZE) {
flag[i] = 1;
sum++;
for(k=0; k<MSG_SIZE; k++)
p[k] = 0;
}
}
}
if(sum != nr_process-1)
printf("child%d: smp_recv sum != nr_process-1\n", process.id);
return 0;
}
int smp_send()
{
int i, j,wlen, rlen;
char *p;
wlen = MSG_SIZE;
rlen = MSG_SIZE;
for(i=0; i<nr_process; i++) {
if(i == process.id)
continue;
p = get_shm_offset(process.id, i);
memset(p, 1, MSG_SIZE);
}
return 0;
}
int smp_comm1()
{
static int i = 0;
static int n = sizeof(recvbuf)/MSG_SIZE;
smp_send();
#if SEND_ONLY
if(++i == n) {
i = 0;
smp_recv();
return 1;
}
#else
smp_recv();
#endif
//printf("[%d] %s %d count=%d\n", process.pid,__func__,__LINE__, ++i);
return 0;
}
int barrier_init()
{
int oflag = 0;
pthread_barrierattr_t ba;
int pshared = PTHREAD_PROCESS_SHARED;
char shm_name[] = "tmp_process_barrier";
/* Initialize a barrier attributes object */
if (pthread_barrierattr_init(&ba) != 0) {
printf("Error at pthread_barrierattr_init()\n");
return -1;
}
/* Set the pshard value to private to shared */
if (pthread_barrierattr_setpshared(&ba, pshared) != 0) {
printf("Error at pthread_barrierattr_setpshared()\n");
return -1;
}
/* Create shared object */
if(process.id == 0) {
shm_unlink(shm_name);
oflag = O_RDWR | O_CREAT | O_EXCL;
}else{
oflag = O_RDWR | O_EXCL;
delay(10);
//usleep(100000);
}
shm_fd = shm_open(shm_name, oflag, S_IRUSR | S_IWUSR);
if (shm_fd == -1) {
perror("Error at shm_open()");
return -1;
}
if (ftruncate(shm_fd, sizeof(pthread_barrier_t)+nr_process) != 0) {
perror("Error at ftruncate()");
shm_unlink(shm_name);
return -1;
}
/* Map the shared memory object to my memory */
barrier = mmap(NULL, sizeof(pthread_barrier_t)+nr_process, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (barrier == MAP_FAILED) {
perror("Error at first mmap()");
shm_unlink(shm_name);
return -1;
}
if(process.id == 0) {
/* Initialize a barrier */
if ((pthread_barrier_init(barrier, &ba, nr_process)) != 0) {
printf("Error at pthread_barrier_init()\n");
return -1;
}
char *p = (char*)barrier;
p[process.id] = 0;
memset(p, 0, sizeof(pthread_barrier_t)+nr_process);
}
/* Cleanup */
if ((pthread_barrierattr_destroy(&ba)) != 0) {
printf("Error at pthread_barrierattr_destroy()\n");
return -1;
}
return 0;
}
int shm_init()
{
int shm_fd;
int oflag;
int shm_size = (nr_process*(nr_process-1))*MSG_SIZE;
char shm_name[] = "tmp_process_shm";
if(process.id == 0) {
shm_unlink(shm_name);
oflag = O_RDWR | O_CREAT | O_EXCL;
shm_fd = shm_open(shm_name, oflag, S_IRUSR | S_IWUSR);
if (shm_fd == -1) {
perror("Error at shm_open()");
return -1;
}
if (ftruncate(shm_fd, shm_size) != 0) {
perror("Error at ftruncate()");
shm_unlink(shm_name);
return -1;
}
}else{
delay(10);
oflag = O_RDWR | O_EXCL;
shm_fd = shm_open(shm_name, oflag, S_IRUSR | S_IWUSR);
if (shm_fd == -1) {
perror("Error at shm_open()");
return -1;
}
}
/* Map the shared memory object to my memory */
shm_buffer = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_buffer == MAP_FAILED) {
perror("Error at first mmap()");
shm_unlink(shm_name);
return -1;
}
//close(shm_fd);
if(process.id == 0) {
memset(shm_buffer, 0, shm_size);
}else {
delay(40);
}
return 0;
}
void *thread_emt(__attribute__((unused)) void *arg)
{
process_func(arg);
}
int main(int argc, char **argv)
{
int i, ret = 0;
int rfd, wfd;
int myid = 0;
int cpu_num;
struct Process *p;
if(argc > 1) {
myid = atoi(argv[1]);
}
if(argc > 2) {
cpu_num = sysconf(_SC_NPROCESSORS_ONLN);
nr_process = atoi(argv[2]);
if(nr_process > cpu_num-2) {
printf("max process is %d!\n", cpu_num-2);
return -1;
}
}
if(argc > 3) {
testloop = atoi(argv[3]);
}
process.id = myid;
process.pid = getpid();
printf("child%d: pid %d, nr_process %d, testloop %d\n", myid,getpid(), nr_process, testloop);
if(mlockall(MCL_CURRENT|MCL_FUTURE) !=0) {
printf("lock memeory error ,exit\n");
exit(1);
}
if(barrier_init() < 0) {
printf("barrier_init error ,exit\n");
exit(1);
}
if(shm_init() < 0) {
printf("shm_init error ,exit\n");
exit(1);
}
ret = process_barrier((char*)barrier);
if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("process%d pid[%d]: barrier_wait error! %s\n", process.id, process.pid, strerror(errno));
goto err;
}
process_func(&process);
ret = process_barrier((char*)barrier);
if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("process%d pid[%d]: barrier_wait error! %s\n", process.id, process.pid, strerror(errno));
goto err;
}
munlockall();
return 0;
err:
return -1;
}