Eu tenho andado a experimentar programação concorrente em C. Fiz forks de processos e criação de threads com trincos (mutex) no Mac (Darwin), mas os semáforos com contador estavam a dar resultados inesperados. Aparentemente o sem_wait() não surtia efeito.
Acabei então por descobrir que o Mac não implementa semáforos baseados em memória (sem_init() e sem_destroy()), apenas semáforos com nome (sem_open() e sem_close()). Também reparei que a função sem_getvalue() não está implementada (é opcional em POSIX).
#include <stdio.h>
#include <semaphore.h>
int main(int argc, char *argv[])
{
sem_t semaphore;
int retval;
if (sem_init(&semaphore, 0, 1) == -1) {
perror("sem_init");
}
if (sem_getvalue(&semaphore, &retval) == -1) {
perror("sem_getvalue");
}
// sem_wait(&semaphore);
// sem_post(&semaphore);
if (sem_destroy(&semaphore) == -1) {
perror("sem_destroy");
}
return 0;
}
Este código produz o seguinte output:
sem_init: Function not implemented sem_getvalue: Function not implemented sem_destroy: Function not implemented
A alternativa então é usar semáforos com nome.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
int main(int argc, char *argv[])
{
sem_t *semaphore;
if ((semaphore = sem_open("/semaphore", O_CREAT, 0644, 1)) == SEM_FAILED ) {
perror("sem_open");
exit(EXIT_FAILURE);
}
// sem_wait(semaphore);
// sem_post(semaphore);
if (sem_close(semaphore) == -1) {
perror("sem_close");
exit(EXIT_FAILURE);
}
if (sem_unlink("/semaphore") == -1) {
perror("sem_unlink");
exit(EXIT_FAILURE);
}
puts("Done");
exit(EXIT_SUCCESS);
}
// Output: Done
Para as assinaturas das funções e mais detalhes, aceder às páginas do manual no Terminal:
$ man sem_open $ man sem_close $ man sem_unlink
De notar que como o semáforo agora é um apontador, as funções sem_wait(), sem_post(), etc…, recebem como argumento o próprio apontador, e não o seu endereço de memória.