heldercorreia.com

autodidata, programador e consultor

Semáforos no MacOSX

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.

Comentários