Skip to content

Instantly share code, notes, and snippets.

@krackers
Forked from kazupon/mach_semaphore.c
Created September 19, 2023 04:51
Show Gist options
  • Save krackers/dd3e43500f705a337a87d192467d01a2 to your computer and use it in GitHub Desktop.
Save krackers/dd3e43500f705a337a87d192467d01a2 to your computer and use it in GitHub Desktop.

Revisions

  1. @axelexic axelexic created this gist Feb 25, 2012.
    84 changes: 84 additions & 0 deletions mach_semaphore.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,84 @@
    //
    // Created by Yogesh Swami on 2/24/12.
    // Copyright (c) 2012 __MyCompanyName__. All rights reserved.
    //

    //
    // clang -Wall -Wextra -Wall -o mach_semaphore mach_semaphore.c
    //

    // using mach semaphore for mutually signalling between two threads.
    // Since mach semaphores are essentially mach_ports, once can
    // send receive rights to the semaphore to another process
    // run exactly the same operations done using threads in this example.
    //

    #include <stdio.h>
    #include <string.h>
    #include <mach/mach_init.h>
    #include <mach/task.h>
    #include <mach/semaphore.h>
    #include <mach/sync_policy.h>
    #include <mach/mach_error.h>
    #include <mach/clock_types.h>
    #include <pthread.h>

    mach_timespec_t semaWait = { .tv_sec = 1,
    .tv_nsec = (clock_res_t)0
    };
    semaphore_t sema_one;
    semaphore_t sema_two;

    void* child_entry_point(void * sema){
    semaphore_t s_one = *((semaphore_t*)sema);
    semaphore_t s_two = (s_one == sema_one)? sema_two: sema_one;

    char* name = (s_one == sema_one)? "main ":"child";

    int counter = 5;
    kern_return_t result;
    fprintf(stdout, "---------- %s entry point ---------\n", name);

    // Let the child begin first, this way we don't need to do
    // pthread_detach()
    if(s_one == sema_one)
    semaphore_wait(s_one);

    do {
    fprintf(stdout, "%s > counter = %d. Will sleep for one second.\n", name, counter);
    /* let semaphore one know we are waiting. */
    result = semaphore_timedwait_signal(s_one, s_two, semaWait);
    } while ((counter-- > 0) && ((result == KERN_OPERATION_TIMED_OUT) || (result == KERN_SUCCESS)));

    if(counter > 0){
    fprintf(stderr, "%s > Error with semaphore: <%d %s>\n", name, result, mach_error_string(result));
    }else {
    fprintf(stdout, "%s > Exiting ...\n", name);
    }
    return NULL;
    }

    int main(__unused int argc, __unused char *argv[]) {
    char* main_t = "main", *child_t = "child";
    pthread_t tid;
    kern_return_t ret;
    mach_port_t self = mach_task_self();
    int result;

    ret = semaphore_create(self, &sema_one, SYNC_POLICY_FIFO, 0);
    if(ret != KERN_SUCCESS){
    fprintf(stderr, "semaphore create failed. Error <%d, %s>", ret, mach_error_string(ret));
    return ret;
    }

    ret = semaphore_create(self, &sema_two, SYNC_POLICY_FIFO, 0);
    if(ret != KERN_SUCCESS){
    fprintf(stderr, "semaphore create failed. Error <%d, %s>", ret, mach_error_string(ret));
    return ret;
    }

    result = pthread_create(&tid, NULL, child_entry_point, (void*)&sema_two);
    child_entry_point((void*)&sema_one);

    return ret;
    }