1

I have unnamed semaphores that I am placing in shared memory in one process following the method that I found here on SO

In P0:

/* addr is a pointer to the base of the shared memory area */
sem_t *sem = (sem_t*) addr;
void *usableSharedMemory = (char*) addr + sizeof(sem_t)
sem_init(sem, 1, 0);

In P1:

if ((addr = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
  exit(EXIT_FAILURE);
}

sem_t *my_sem = (sem_t*) addr;
...
sem_post(my_sem);
...
sem_wait(my_sem);

If I call sem_getvalue(my_sem) before and after a post or wait, the value of the semaphore does not change. I have prints like this to debug:

int v = 0;
v = sem_getvalue(rsem, &v);
printf("BEFORE-POST:%d\n", v);
sem_post(rsem);
v = sem_getvalue(rsem, &v);
printf("AFTER-POST:%d\n", v);

Before and after the call to sem_post, the semaphore value is zero (0).

Anthony O
  • 622
  • 7
  • 26
  • What return values do you get from `sem_init()`, `sem_post()`, and `sem_wait()`? Because you're not checking any of those for failure. You also don't show how you place the semaphore into shared memory so other processes can access it. – Andrew Henle Oct 30 '19 at 14:12

1 Answers1

1

I haven't used this kind of semaphore before, but I see a number of things one could trip over.

I'm not excited about the funky pointer math that the other SO post was suggesting, and I can't tell from here whether both processes are actually talking to the same chunk of shared memory.

A good idea in this case is to avoid the pointer math and use a struct to overlay the shared memory segment so you have a clear organization, and add a magic number so everybody can tell if they're getting a valid segment or some random bogus memory:

#define MYSHM_MAGIC 12345987  // can be anything random-ish

struct mysharedmem {
    int     magicvalue;
    sem_t   MySemaphore;
    void    *UsableMemory;
};

This structure overlays whatever your shared memory segment is and allows you to use consistent and more readable access methods, especially if you add additional variables that all sides agree on. The code that creates the segment should initialize it:

// in P1 ?
struct mysharedmem *myshm = mmap(NULL, SIZE, ...);

myshm->magic = MYSHM_MAGIC;
sem_init(&myshm->MySemaphore, 1, 0);
...

and then in the other process, once you obtain the shared address, actually ask the segment "did you come from the place I think?" by checking the magic number. The value of the number doesn't matter, only that both sides agree.

// In P0 ?
struct mysharedmem *myshm = addr; // obtained somehow

if (myshm->magic != MYSHM_MAGIC)
{
    error - we don't see the special magic number
}
.. do stuff

How does P0 obtain a handle to the shared memory segment created by the P1?

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
  • This is a good idea. The handle is obtained by calling mmap on the name of the shared memory to get the first byte in shared memory, and then casting that address to a sem_t pointer. – Anthony O Oct 29 '19 at 04:30
  • I'm not sure that I saw a name of shared memory where it's initially allocated, so perhaps the issue here is the two processes aren't talking to the same memory. The magic number test should bear that out. – Steve Friedl Oct 29 '19 at 04:32