struct hlist_head rhead;
};
-/* FIXME: sync with stop */
+static atomic_t rm_uprobes_child_cnt = ATOMIC_INIT(0);
+
static unsigned long cb_clean_child(void *data)
{
struct clean_data *cdata = (struct clean_data *)data;
/* disarm urp for child */
urinst_info_put_current_hlist(&cdata->rhead, child);
+ atomic_dec(&rm_uprobes_child_cnt);
return 0;
}
/* set jumper */
ret = set_jump_cb((unsigned long)ri->ret_addr, regs,
cb_clean_child, &cdata, sizeof(cdata));
- if (ret == 0)
+ if (ret == 0) {
+ atomic_inc(&rm_uprobes_child_cnt);
ri->ret_addr = (unsigned long *)get_jump_addr();
+ }
}
}
-/* FIXME: sync with stop */
+static atomic_t pre_handler_cp_cnt = ATOMIC_INIT(0);
+
static unsigned long cp_cb(void *data)
{
if (atomic_read(&stop_flag))
call_mm_release(current);
+ atomic_dec(&pre_handler_cp_cnt);
return 0;
}
if (ret < 0) {
pr_err("set_kjump_cp, ret=%d\n", ret);
ret = 0;
+ } else {
+ atomic_inc(&pre_handler_cp_cnt);
}
out:
return ret;
} while (atomic_read(©_process_cnt));
swap_unregister_kretprobe_bottom(&cp_kretprobe);
swap_unregister_kprobe(&cp_kprobe);
+
+ do {
+ synchronize_sched();
+ } while (atomic_read(&rm_uprobes_child_cnt)
+ || atomic_read(&pre_handler_cp_cnt));
}
******************************************************************************
*/
-/* FIXME: sync with stop */
+static atomic_t mm_release_cnt = ATOMIC_INIT(0);
+
static unsigned long mr_cb(void *data)
{
struct task_struct *task = *(struct task_struct **)data;
}
up_write(&mm->mmap_sem);
+ atomic_dec(&mm_release_cnt);
+
return 0;
}
if (ret < 0) {
printk("##### ERROR: mr_pre_handler, ret=%d\n", ret);
ret = 0;
+ } else {
+ atomic_inc(&mm_release_cnt);
}
+
out:
return ret;
}
static void unregister_mr(void)
{
swap_unregister_kprobe(&mr_kprobe);
+ do {
+ synchronize_sched();
+ } while (atomic_read(&mm_release_cnt));
}