I create a shared memory used to share data between processes. The shared memory saves data using a data structure:
struct shared_cfg {
volatile uint32_t idx;
volatile uint32_t cfg_lock;
...
};
In my program:
- different processes should get an unique value of "idx" every time.
- after process P1 modified the viraible "idx", process P2 is expected to use the new value of "idx" and update it.
- Then P1 will get the new value that saved by P2.
- ...
But I found that when the concurrency increases, P2 occasionally read the old value of "idx", which means P1 and P2 got the same value of idx:
typedef volatile uint32_t lock_t
void lock_idx(lock_t *lock)
{
uint32_t old_lock = 0;
do {
old_lock = __sync_val_compare_and_swap(lock, 0, 1);
if (old_lock == 1)
usleep(10*1000);
else
break;
} while (old_lock == 1);
}
void unlock(lock_t *lock)
{
__sync_lock_test_and_set(lock, 0);
}
idx = 0;
P1:
lock_idx(&cfg_lock);
idx = idx + 1;
unlock_idx(&cfg_lock);
P2
lock_idx(&cfg_lock);
idx = idx + 1;
unlock_idx(&cfg_lock);
I insert memory barrier by API "mm*fence" before and after the modification of "idx", but the problem still exist:
idx = 0;
P1:
lock_idx(&cfg_lock);
_mm_mfence()
idx = idx + 1
_mm_mfence()
unlock_idx(&cfg_lock);
P2:
lock_idx(&cfg_lock);
_mm_mfence()
idx = idx + 1
_mm_mfence()
unlock_idx(&cfg_lock);
The error log is like this:
P1: get lock
P1: idx is 1; update idx to 2
P1: unlock
P2: get lock
P2: idx is 2; update idx to 3
P2: unlock
...
P1: get lock
P1: idx is 63; update idx to 64
P1: unlock
P2: get lock
P2: idx is 63; update idx to 64
P2: unlock
...
How to share variables between multiple processes by shared memory?