seqlock 是很不錯的作法, 它唯一不便的是,如果 read 讀到更新到一半的結構,
就要重新讀過, 以下面這個 structure 為例 :
struct data_t_
{
int seq; // sequence number
int data[120]; // user data
} ;
如果用傳統 seqlock 作法, 如果 write 全速盡力地寫,可得 驚人的 (90000)(20534911)
就是每九萬次不需重讀,有重讀了兩千萬次!! 現實生活上當然不會有這種拼命寫的 case ,
這只是測試 !!!
當使用 16 個 buffer 時, 讀的時候去讀上個已經寫好結構的資料,此時要發生重讀機率小很多,
實測是 : 九萬次內沒有發生重讀 !!!!
以下是測試程式 :
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <string.h>
#include <errno.h>
struct data_t_
{
int seq; // sequence number
int data[120]; // user data
} ;
typedef struct data_t_ data_t ;
struct seqlock_t_
{
int current ;
data_t pool[16];
} ;
typedef struct seqlock_t_ seqlock_t ;
seqlock_t sl;
static int iDO = 0 , iREDO = 0;
void process(data_t* d,int* idata)
{
int idx ;
for(idx=0;idx<120;idx++)
idata[idx] = d->data[idx] ;
}
void readx(int *idataread)
{
for (;;)
{
int itmp = sl.current;
int icurr ;
icurr = (itmp==0) ? 15 : itmp -1 ;
//icurr = 1 ;
int seq1 = sl.pool[icurr].seq;
if (seq1 % 2)
continue;
process(&sl.pool[icurr],idataread);
int seq2 = sl.pool[icurr].seq;
if (seq1 == seq2){
++iDO ;
break;
}else{
++iREDO ;
}
}
}
void modify(data_t* d,int* idata)
{
int idx ;
for(idx=0;idx<120;idx++)
{
d->data[idx] = idata[idx] ;
}
}
void writex(int* idata)
{
int idx = sl.current % 16;
//printf("idx=(%d)\n",idx) ;
data_t* d = &sl.pool[idx];
d->seq += 1;
modify(d,idata);
d->seq += 1;
sl.current==(16-1) ? sl.current = 0 : ++sl.current ;
//sl.current=0 ;
}
void *writefunc(void *arg)
{
int idx,idy,idz ;
int idatawrite[120] ;
int *idataread ;
idataread = (int*) malloc(120 * sizeof(int)) ;
for(idx=0;idx<100000000;idx++)
{
for(idy=0;idy<120;idy++)
idatawrite[idy] = idy * idy + idx ;
writex(idatawrite) ;
}//for
printf("writefunc done \n") ;
}
void *readfunc(void *arg)
{
int idx,idy,idz ;
int *idataread ;
idataread = (int*) malloc(120 * sizeof(int)) ;
while(1)
{
++idx ;
readx(idataread) ;
if( (idx%10000)==0)
printf("idataread[0]=(%d)\n",idataread[0]) ;
if(idx >= 90000)
{
printf("going to break while \n") ;
break ;
}
}//while
printf("(%d)(%d)\n",iDO,iREDO) ;
}
int main()
{
sl.current = 0 ;
pthread_t id[2];
int iCPU ;
iCPU = 1;
pthread_create(&id[0],NULL,writefunc,(void *)(long)iCPU );
iCPU = 2;
pthread_create(&id[1],NULL,readfunc,(void *)(long)iCPU );
int i ;
for(i=0;i<2;++i){
pthread_join(id[i],NULL);
}
printf("Done \n") ;
}
留言列表