Question

I'm working in a multi-computer environment where 2 computers will access the same memory over a 32bit PCI bus.

The first computer will only write to the 32bit int.
*int_pointer = number;

The second computer will only read from the 32bit int.
number = *int_pointer;

Both OS's / CPU's are 32bit architecture.
computer with PCI is Intel Based.
computer on the PCI card is power PC.

The case I am worried about is if the write only computer is changing the variable at the same time the read computer is reading it, causing invalid data for the read computer.
I'd like to know if the atomicity of reading / writing to the same position in memory is preserved over multiple computers.

If so, would the following prevent the race condition:

number = *int_pointer;
while(*int_pointer != number) {
    number = *int_pointer;
}

I can guarantee that writes will occur every 16ms*, and reads will occur randomly.

*times will drift since both computers have different timers.

Was it helpful?

Solution 2

To answer my own question:

There is no race condition. The memory controller on the external PCI device will handle all memory read/write operations. Since all data carriers are at least 32bits wide there will not be a race condition within those 32bits.

Since the transfers use a DMA controller the interactions between memory and processors is well behaved.

See Direct Memory Access -PCI

OTHER TIPS

There isn't enough information to answer this definitively.

If either of the CPUs decide to cache the memory at *int_pointer, this will always fail and your extra code will not fix any race condition.

Assuming both CPUs know that memory at *int_pointer is uncacheable, AND that location *int_pointer is aligned on a 4-byte/32-bit boundary AND the CPU on the PCI card has a 32 bit memory interface, AND the pointer is declared as a pointer to volatile AND both your C compilers implement volatile correctly, THEN it is likely that the updates will be atomic.

If any of the above conditions are not met, the result will be unpredictable and your "race detection" code is not likely to work.

Edited to explain why volatile is needed:

Here is your race condition code compiled to MIPS assembler with -O4 and no volatile qualifier. (I used MIPS because the generated code is easier to read than x86 code):

int nonvol(int *ip) {
  int number = *ip;
  while (*ip != number) {
    number = *ip;
  }
  return number;
}

Disassembly output:

        00000000 <nonvol>:
   0:   8c820000        lw      v0,0(a0)
   4:   03e00008        jr      ra

The compiler has optimized the while loop away since it knows that *ip cannot change.

Here's what happens with volatile and the same compiler options:

int vol(volatile int *ip) {
  int number = *ip;
  while (*ip != number) {
    number = *ip;
  }
  return number;
}

Disassembly output:

        00000008 <vol>:
   8:   8c820000        lw      v0,0(a0)
   c:   8c830000        lw      v1,0(a0)
  10:   1443fffd        bne     v0,v1,8 <vol>
  14:   00000000        nop
  18:   03e00008        jr      ra

Now the while loop is not optimized away because using volatile has told the compiler that *ip can change at any time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top