Skip to content

Instantly share code, notes, and snippets.

@rolfbjarne
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rolfbjarne/13b9e57874e60fe3d130 to your computer and use it in GitHub Desktop.
Save rolfbjarne/13b9e57874e60fe3d130 to your computer and use it in GitHub Desktop.
#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, &notify_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