static void sched_process_exit_probe(
    void *__data, struct task_struct *p)
{
  // TODO: Cleanup threads...

  // If this is the main thread of a process, unregister the process.
  if (p->pid == p->tgid) {
    process_unregister(p->tgid);
  }
}
/*
 * Module ioctl interface.
 */
long lttngprofile_module_ioctl(
    struct file *file, unsigned int cmd, unsigned long arg)
{
  u32 hash;
  struct process_key_t key;
  struct process_val_t *val;
  struct lttngprofile_module_msg msg;
  struct task_struct *task = get_current();
  int ret = 0;
  void __user *umsg = (void *) arg;

  if (cmd != LTTNGPROFILE_MODULE_IOCTL)
    return -ENOIOCTLCMD;

  if (copy_from_user(&msg, umsg, sizeof(struct lttngprofile_module_msg)))
    return -EFAULT;

  key.tgid = task->tgid;
  hash = jhash(&key, sizeof(key), 0);

  switch(msg.cmd) {
  case LTTNGPROFILE_MODULE_REGISTER:
    /* check if already registered */
    rcu_read_lock();
    val = find_process(&key, hash);
    if (val) {
      rcu_read_unlock();
      break;
    }
    rcu_read_unlock();
    /* do registration */
    val = kzalloc(sizeof(struct process_val_t), GFP_KERNEL);
    val->tgid = key.tgid;
    val->latency_threshold = msg.latency_threshold;
    hash_add_rcu(process_map, &val->hlist, hash);
    printk("lttngprofile_module_ioctl register %d\n", task->tgid);
    break;
  case LTTNGPROFILE_MODULE_UNREGISTER:
    process_unregister(task->tgid);
    break;
  default:
    ret = -ENOTSUPP;
    break;
  }

  return ret;
}
static void process_message(pep_proxy_t *proxy, msg_t *msg)
{
    char *name  = proxy && proxy->name ? proxy->name : "<unknown>";

    switch (msg->any.type) {
    case MSG_TYPE_REGISTER:
        process_register(proxy, &msg->reg);
        break;
    case MSG_TYPE_UNREGISTER:
        process_unregister(proxy, &msg->unreg);
        break;
    case MSG_TYPE_SET:
        process_set(proxy, &msg->set);
        break;
    default:
        mrp_log_error("Unexpected message 0x%x from client %s.",
                      msg->any.type, name);
        break;
    }
}