http://www.stroustrup.com/C++11FAQ.html#memory-model
the page describe that :
// thread 1:
char c;
c = 1;
int x = c;
// thread 2:
char b;
b = 1;
int y = b;
.....
However, most modern processors cannot read or write a single character, it must read or write a whole word, so the assignment to c really is ``read the word containing c, replace the c part, and write the word back again.'' Since the assignment to b is similar, there are plenty of opportunities for the two threads to clobber each other even though the threads do not (according to their source text) share data!
I have a struct :
struct data_
{
volatile char c ;
volatile char b ;
} __attribute__(( aligned(2) ));
typedef struct data_ data ;
and global vars:
data dx ;
int x,y ;
Thread1 :
dx.c = 1 ;
x = dx.c ;
Thread2 :
dx.b = 1 ;
y = dx.b ;
Compiled at gcc 4.4.6 , and run it 1,000,000 times , look like I don't get any value that not (x==1 && y==1) !!!!
struct data_
{
volatile char c ;
volatile char b ;
} __attribute__(( aligned(2) ));
I put char c and char b in a structure aligned(2) on purpose so that they both belong to the same word , and according to the webpage describe , I might have the chance to get results not (x==1 && y==1) , the fact is that run the test 1,000,000 time , all get (x==1 && y==1) , is that because gcc do any tricks ? or something I missed ?
Edit :
Thread1 :
int ilocal ;
while(1)
{
sem_wait(sem1) ;
dx.c = 1 ;
x = dx.c ;
ilocal = __sync_add_and_fetch(&icnt,1) ;
if(ilocal == 2)
sem_post(sem3) ;
++icnt1 ;
}
Thread2 :
int ilocal ;
while(1)
{
sem_wait(sem2) ;
dx.b = 1 ;
y = dx.b ;
ilocal = __sync_add_and_fetch(&icnt,1) ;
if(ilocal == 2)
sem_post(sem3) ;
++icnt2 ;
}
Main :
int idx,iflag1=0,iflag2=0 ;
for(idx=0;idx<1000000;idx++)
{
icnt = 0 ; dx.c=0 ; dx.b=0 ;
sem_post(sem1) ;
sem_post(sem2) ;
sem_wait(sem3) ;
if( ! ((x==1)&&(y==1)) )
{
printf("result that (x==%d && y==%d) \n",x,y) ;
++iflag1 ;
}else{
++iflag2 ;
}
} //while
printf("iflag1=(%d),iflag2=(%d)\n",iflag1,iflag2) ;
printf("icnt1=(%d),icnt2=(%d) \n",icnt1,icnt2) ;
gcc memorylocate.c -lpthread -o memorylocate.exe
sizeof data=(64) //source already change to __attribute__(( aligned(64) )
iflag1=(0),iflag2=(1000000)
icnt1=(1000000),icnt2=(1000000)
Edit2 :
I think I finally figure it out !!
struct { char c ; char b ;}
c and b would be different memory location , so that they can be thread-safe access !! the cpu can access single-byte char atomiclly !!!!!
I change code to :
struct data_
{
unsigned char c:4 ;
unsigned char b:4 ;
} ;
and in main :
for(idx=0;idx<1000000;idx++)
{
icnt = 0 ; dx.c=0 ; dx.b=0 ;
sem_post(sem1) ;
sem_post(sem2) ;
sem_wait(sem3) ;
if( ! ((dx.c==1)&&(dx.b==1)) )
{
printf("result that (x==%d && y==%d) \n",x,y) ;
++iflag1 ;
}else{
++iflag2 ;
}
} //while
I observe there are results that not (dx.c==1)&&(dx.b==1) !! This is because the dx.c and dx.b is in the same memory location in this case !!!!
So I make a mistake , the most important thing to decide is memory location , struct {char c; char b;} , char c and char b is in different memory location , the test result is correct !!!!