My question is: what's the best way to implement mutual exclusion for a shared memory segment. I want to ensure that while updating a shared memory segment that another process will not get read part of the segment before and the other part after the update. (I also want to ensure that the update itself is not clobbered by another update.)
My update looks something like this:
semkey = ftok(CONFIG_FILE,1);
shmid = shmget(semkey, SHARED_POOL_SIZE, 0444);
if (-1 == shmid) {
/* new shared memory segment -- initialize */
isnew = 1;
shmid = shmget(semkey, SHARED_POOL_SIZE,
IPC_CREAT | IPC_CREAT | SHM_NORESERVE | shm_unlocked );
shmctl(shmid, IPC_STAT, &semstat);
}
else {
/* already exists -- grab pointer to it */
shmctl(shmid, IPC_STAT, &semstat);
stat(CONFIG_FILE, &confstat);
}
/* shmid is ID of our shared memory segment */
if (shmid < 0 || isnew || confstat.st_mtime > semstat.shm_ctime) {
/* update it */
/* parse the file */
config_parse(&config);
pconfig = shmat(shmid, NULL, 0);
/* update the shared segment */
if ((void*)-1 != pconfig) {
/* MUTAL WRITE EXCLUSION NEEDED HERE */
memcpy(pconfig, &config, sizeof(struct config_data));
/* update the timestamp */
shmctl(shmid, IPC_SET, &semstat);
/* END MUTEX */
shmdt(pconfig);
}
}
My reader code looks like this:
semkey = ftok(CONFIG_FILE,1);
shmid = shmget(semkey,128, 0444);
pconfig = shmat(shmid, NULL, SHM_RDONLY);
if ((void*)-1 == pconfig) {
/* error recovery */
}
else {
/* NEED MUTEX HERE */
memcpy(&config, pconfig, sizeof(struct config_data));
/* END MUTEX */
}