// // 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 #include #include #include #include #include #include #include #include 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; }