DECLARE_BITMAP(sc_exit, NR_syscalls);
DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls);
DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls);
+
+ /*
+ * Reference counters keeping track of number of events enabled
+ * for each bit.
+ */
+ u32 sc_entry_refcount_map[NR_syscalls];
+ u32 sc_exit_refcount_map[NR_syscalls];
+ u32 sc_compat_entry_refcount_map[NR_compat_syscalls];
+ u32 sc_compat_exit_refcount_map[NR_compat_syscalls];
};
static void syscall_entry_event_unknown(struct hlist_head *unknown_action_list_head,
const struct lttng_kernel_event_desc *desc;
unsigned int i;
- if (!IS_ENABLED(CONFIG_COMPAT) && (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT))
+#ifndef CONFIG_COMPAT
+ if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)
return;
-
+#endif
/* iterate over all syscall and create event that match */
for (i = 0; i < table_len; i++) {
struct lttng_kernel_event_common_private *event_priv;
struct hlist_head *head;
- int found = 0;
+ bool found = false;
desc = table[i].desc;
if (!desc) {
*/
head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
- if (lttng_event_enabler_desc_match_event(syscall_event_enabler_common, desc, event_priv->pub))
- found = 1;
+ if (lttng_event_enabler_desc_match_event(syscall_event_enabler_common, desc, event_priv->pub)) {
+ found = true;
+ break;
+ }
}
if (found)
continue;
bool found = false;
struct hlist_head *head;
- if (!IS_ENABLED(CONFIG_COMPAT) && (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT))
+#ifndef CONFIG_COMPAT
+ if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)
return;
-
+#endif
/*
* Considering that currently system calls can only be enabled on a per
* name basis (or wildcard based on a name), unknown syscall events are
*/
head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
- if (lttng_event_enabler_desc_match_event(event_enabler, desc, event_priv->pub))
+ if (lttng_event_enabler_desc_match_event(event_enabler, desc, event_priv->pub)) {
found = true;
+ break;
+ }
}
if (!found)
lttng_syscall_event_enabler_create_event(event_enabler, desc, unknown_dispatch_list, type, -1U);
{
const char *syscall_name;
unsigned long *bitmap;
+ u32 *refcount_map;
int syscall_nr;
syscall_name = get_syscall_name(desc_name, abi, entryexit);
switch (abi) {
case LTTNG_SYSCALL_ABI_NATIVE:
bitmap = filter->sc_entry;
+ refcount_map = filter->sc_entry_refcount_map;
break;
case LTTNG_SYSCALL_ABI_COMPAT:
bitmap = filter->sc_compat_entry;
+ refcount_map = filter->sc_compat_entry_refcount_map;
break;
default:
return -EINVAL;
switch (abi) {
case LTTNG_SYSCALL_ABI_NATIVE:
bitmap = filter->sc_exit;
+ refcount_map = filter->sc_exit_refcount_map;
break;
case LTTNG_SYSCALL_ABI_COMPAT:
bitmap = filter->sc_compat_exit;
+ refcount_map = filter->sc_compat_exit_refcount_map;
break;
default:
return -EINVAL;
default:
return -EINVAL;
}
- if (test_bit(syscall_nr, bitmap))
- return -EEXIST;
- bitmap_set(bitmap, syscall_nr, 1);
+ if (refcount_map[syscall_nr] == U32_MAX)
+ return -EOVERFLOW;
+ if (refcount_map[syscall_nr]++ == 0)
+ bitmap_set(bitmap, syscall_nr, 1);
return 0;
}
WARN_ON_ONCE(event->priv->instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
+ /* Skip unknown syscall */
+ if (syscall_id == -1U)
+ return 0;
+
ret = lttng_syscall_filter_enable(syscall_table->sc_filter,
event->priv->desc->event_name, event->priv->u.syscall.abi,
event->priv->u.syscall.entryexit);
{
const char *syscall_name;
unsigned long *bitmap;
+ u32 *refcount_map;
int syscall_nr;
syscall_name = get_syscall_name(desc_name, abi, entryexit);
switch (abi) {
case LTTNG_SYSCALL_ABI_NATIVE:
bitmap = filter->sc_entry;
+ refcount_map = filter->sc_entry_refcount_map;
break;
case LTTNG_SYSCALL_ABI_COMPAT:
bitmap = filter->sc_compat_entry;
+ refcount_map = filter->sc_compat_entry_refcount_map;
break;
default:
return -EINVAL;
switch (abi) {
case LTTNG_SYSCALL_ABI_NATIVE:
bitmap = filter->sc_exit;
+ refcount_map = filter->sc_exit_refcount_map;
break;
case LTTNG_SYSCALL_ABI_COMPAT:
bitmap = filter->sc_compat_exit;
+ refcount_map = filter->sc_compat_exit_refcount_map;
break;
default:
return -EINVAL;
default:
return -EINVAL;
}
- if (!test_bit(syscall_nr, bitmap))
- return -EEXIST;
- bitmap_clear(bitmap, syscall_nr, 1);
-
+ if (refcount_map[syscall_nr] == 0)
+ return -ENOENT;
+ if (--refcount_map[syscall_nr] == 0)
+ bitmap_clear(bitmap, syscall_nr, 1);
return 0;
}
int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event)
{
struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
+ unsigned int syscall_id = event->priv->u.syscall.syscall_id;
int ret;
+ /* Skip unknown syscall */
+ if (syscall_id == -1U)
+ return 0;
+
ret = lttng_syscall_filter_disable(syscall_table->sc_filter,
event->priv->desc->event_name, event->priv->u.syscall.abi,
event->priv->u.syscall.entryexit);