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") ;
}

 

 

arrow
arrow
    全站熱搜

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