Reputation: 63
Right now I'm working on my project and I have a question about initialization of semaphores. Actually I'm programming on Mac OS X, but I tried to compile me project on Linux and it doesn't compile. On OS X it compiles but every time just crashing at the moment of initialization.
sem_t *mutex_1, *mutex_2, *mutex_3, *reader, *writer;
int initialization_semaphores (void)
{
int ERROR = EOK;
if ((mutex_1 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
ERROR = ESEM;
if ((mutex_2 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
ERROR = ESEM;
if ((mutex_3 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
ERROR = ESEM;
if ((reader = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
ERROR = ESEM;
if ((writer = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
ERROR = ESEM;
if (ERROR == EOK) {
if (sem_init(mutex_1, 1, 1) == -1)
ERROR = ESEM;
if (sem_init(mutex_2, 1, 1) == -1)
ERROR = ESEM;
if (sem_init(mutex_3, 1, 1) == -1)
ERROR = ESEM;
if (sem_init(reader, 1, 1) == -1)
ERROR = ESEM;
if (sem_init(writer, 1, 1) == -1)
ERROR = ESEM;
}
}
When I tried to compile it on linux I see this:
/tmp/ccmkN9G7.o: In function `initialization_semaphores':
readerWriter.c:(.text+0x1a2): undefined reference to `sem_init'
readerWriter.c:(.text+0x1cb): undefined reference to `sem_init'
readerWriter.c:(.text+0x1f4): undefined reference to `sem_init'
readerWriter.c:(.text+0x21d): undefined reference to `sem_init'
readerWriter.c:(.text+0x246): undefined reference to `sem_init'
readerWriter.c:(.text+0x275): undefined reference to `shm_open'
Is it right? :
int ERROR = EOK;
mutex_1 = sem_open("mutex1", O_CREAT, S_IRUSR | S_IWUSR, 1);
mutex_2 = sem_open("mutex2", O_CREAT, S_IRUSR | S_IWUSR, 1);
mutex_3 = sem_open("mutex3", O_CREAT, S_IRUSR | S_IWUSR, 1);
reader = sem_open("reader", O_CREAT, S_IRUSR | S_IWUSR, 1);
writer = sem_open("writer", O_CREAT, S_IRUSR | S_IWUSR, 1);
Upvotes: 3
Views: 1177
Reputation: 232
There's a workaround on Mac OSX.
#include <dispatch/dispatch.h>
typedef dispatch_semaphore_t sem_t;
void sem_init(sem_t* sem, bool is_pshared, unsigned value)
{
*sem = dispatch_semaphore_create(value);
}
static void sem_destroy(sem_t* sem)
{
dispatch_release(*sem);
}
static void sem_post(sem_t* sem)
{
dispatch_semaphore_signal(*sem);
}
static void sem_wait(sem_t* sem)
{
dispatch_semaphore_wait(*sem, DISPATCH_TIME_FOREVER);
}
However, I don't know how to do sem_getvalue()
-- if anyone knows, please let me know.
Upvotes: 0
Reputation: 215547
Mac OSX is non-conformant and does not support sem_init
. The function exists but it silently fails or worse, leaving you with a non-working semaphore.
I'd encourage you to file a bug with Apple, since this is a real, long-standing problem that's affecting application portability badly. The more people who complain, the more hope there is of getting it fixed.
As for working around it, you can try to find/write a replacement implementation of all the POSIX semaphore functions and link your program to that, or you could switch to using sem_open
instead of mmap
and sem_init
.
(As long as you're already going through the overhead of mapping a whole page for each semaphore, sem_open
doesn't really cost you anything more. Where this bug is really a show-stopper is when you want to include your semaphores inside an existing struct
.)
Upvotes: 5