Skip to content

Instantly share code, notes, and snippets.

@kazupon
Created October 6, 2012 00:52
Show Gist options
  • Save kazupon/3843288 to your computer and use it in GitHub Desktop.
Save kazupon/3843288 to your computer and use it in GitHub Desktop.
Using mach_semaphore on Mac OS X to mutually signaling between two threads. This could be extended to work with different processes.
//
// 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment