-
-
Save rolfbjarne/13b9e57874e60fe3d130 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <pthread.h> | |
#include <mach/mach.h> | |
#include <unistd.h> | |
mach_port_t notify_port; | |
#define THREAD_COUNT 10 | |
int32_t counter = THREAD_COUNT; | |
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
pthread_cond_t cond; | |
pthread_key_t key; | |
struct message | |
{ | |
mach_msg_header_t header; | |
int32_t type; | |
char data[256]; | |
}; | |
static void * | |
listener (void *z) | |
{ | |
int err; | |
struct message message; | |
fprintf (stderr, "listener started\n"); | |
while (1) { | |
/* Receive a message. */ | |
err = mach_msg (&message.header, /* The header */ | |
MACH_RCV_MSG, /* Flags */ | |
0, sizeof (message), /* Send/Max receive size */ | |
notify_port, /* Receive port */ | |
MACH_MSG_TIMEOUT_NONE, /* No timeout */ | |
MACH_PORT_NULL); /* No notification */ | |
if (err) { | |
fprintf (stderr, "mach_msg: %i\n", err); | |
} else if (message.header.msgh_id == MACH_NOTIFY_DEAD_NAME) { | |
int tid = (int) ((int *) &message) [8]; | |
fprintf (stderr, "got dead name msg for port %i %i (tid = %i)\n", MACH_MSGH_BITS_LOCAL (message.header.msgh_bits), message.header.msgh_bits, tid); | |
pthread_mutex_lock (&mutex); | |
counter--; | |
pthread_cond_broadcast (&cond); | |
pthread_mutex_unlock (&mutex); | |
} else { | |
fprintf (stderr, "got unexpected message: %i\n", message.header.msgh_id); | |
} | |
} | |
fprintf (stderr, "listener stopped\n"); | |
} | |
static void | |
key_dtor (void *ptr) | |
{ | |
fprintf (stderr, "key_dtor %i for %i\n", (int) (long long) ptr, mach_thread_self ()); | |
} | |
static void | |
inizialize () | |
{ | |
kern_return_t rv; | |
rv = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, ¬ify_port); | |
if (rv != KERN_SUCCESS) | |
fprintf (stderr, "Failed 1\n"); | |
else | |
fprintf (stderr, "allocated notification port %i\n", notify_port); | |
pthread_key_create (&key, key_dtor); | |
pthread_t l; | |
pthread_create (&l, NULL, listener, NULL); | |
} | |
static void | |
xamarin_thread_death_handler () | |
{ | |
mach_port_t previous; | |
kern_return_t rv; | |
rv = mach_port_request_notification (mach_task_self (), mach_thread_self (), MACH_NOTIFY_DEAD_NAME, 0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous); | |
if (rv != KERN_SUCCESS) | |
fprintf (stderr, "requested: %i\n", rv); | |
else | |
fprintf (stderr, "requested notification successfully for task %i previos port: %i\n", mach_thread_self (), previous); | |
} | |
static void * | |
thread_main (void *ptr) | |
{ | |
// fprintf (stderr, "thread %i executing\n", (int) ptr); | |
xamarin_thread_death_handler (); | |
pthread_setspecific (key, ptr); | |
// fprintf (stderr, "thread %i executed\n", (int) ptr); | |
return NULL; | |
} | |
int main () | |
{ | |
inizialize (); | |
pthread_cond_init (&cond, NULL); | |
for (int i = 0; i < 10; i++) { | |
pthread_t pid; | |
pthread_create (&pid, NULL, thread_main, (void *) (long long) (i + 1)); | |
} | |
pthread_mutex_lock (&mutex); | |
while (counter > 0) { | |
pthread_cond_wait (&cond, &mutex); | |
fprintf (stderr, "%i threads left\n", counter); | |
} | |
pthread_mutex_unlock (&mutex); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment