Skip to content

Commit 7a16609

Browse files
oleg-nesterovPeter Zijlstra
authored andcommitted
uprobes: kill xol_area->slot_count
Add the new helper, xol_get_slot_nr() which does find_first_zero_bit() + test_and_set_bit(). xol_take_insn_slot() can wait for the "xol_get_slot_nr() < UINSNS_PER_PAGE" event instead of "area->slot_count < UINSNS_PER_PAGE". So we can kill area->slot_count and avoid atomic_inc() + atomic_dec(), this simplifies the code and can slightly improve the performance. Signed-off-by: Oleg Nesterov <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent c16e2fd commit 7a16609

File tree

1 file changed

+15
-14
lines changed

1 file changed

+15
-14
lines changed

kernel/events/uprobes.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ static LIST_HEAD(delayed_uprobe_list);
9999
*/
100100
struct xol_area {
101101
wait_queue_head_t wq; /* if all slots are busy */
102-
atomic_t slot_count; /* number of in-use slots */
103102
unsigned long *bitmap; /* 0 = free slot */
104103

105104
struct page *page;
@@ -1556,7 +1555,6 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
15561555
init_waitqueue_head(&area->wq);
15571556
/* Reserve the 1st slot for get_trampoline_vaddr() */
15581557
set_bit(0, area->bitmap);
1559-
atomic_set(&area->slot_count, 1);
15601558
insns = arch_uprobe_trampoline(&insns_size);
15611559
arch_uprobe_copy_ixol(area->page, 0, insns, insns_size);
15621560

@@ -1629,24 +1627,28 @@ void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
16291627
}
16301628
}
16311629

1630+
static unsigned long xol_get_slot_nr(struct xol_area *area)
1631+
{
1632+
unsigned long slot_nr;
1633+
1634+
slot_nr = find_first_zero_bit(area->bitmap, UINSNS_PER_PAGE);
1635+
if (slot_nr < UINSNS_PER_PAGE) {
1636+
if (!test_and_set_bit(slot_nr, area->bitmap))
1637+
return slot_nr;
1638+
}
1639+
1640+
return UINSNS_PER_PAGE;
1641+
}
1642+
16321643
/*
16331644
* - search for a free slot.
16341645
*/
16351646
static unsigned long xol_take_insn_slot(struct xol_area *area)
16361647
{
1637-
unsigned int slot_nr;
1648+
unsigned long slot_nr;
16381649

1639-
for (;;) {
1640-
slot_nr = find_first_zero_bit(area->bitmap, UINSNS_PER_PAGE);
1641-
if (slot_nr < UINSNS_PER_PAGE) {
1642-
if (!test_and_set_bit(slot_nr, area->bitmap))
1643-
break;
1644-
continue;
1645-
}
1646-
wait_event(area->wq, (atomic_read(&area->slot_count) < UINSNS_PER_PAGE));
1647-
}
1650+
wait_event(area->wq, (slot_nr = xol_get_slot_nr(area)) < UINSNS_PER_PAGE);
16481651

1649-
atomic_inc(&area->slot_count);
16501652
return area->vaddr + slot_nr * UPROBE_XOL_SLOT_BYTES;
16511653
}
16521654

@@ -1682,7 +1684,6 @@ static void xol_free_insn_slot(struct uprobe_task *utask)
16821684

16831685
slot_nr = offset / UPROBE_XOL_SLOT_BYTES;
16841686
clear_bit(slot_nr, area->bitmap);
1685-
atomic_dec(&area->slot_count);
16861687
smp_mb__after_atomic(); /* pairs with prepare_to_wait() */
16871688
if (waitqueue_active(&area->wq))
16881689
wake_up(&area->wq);

0 commit comments

Comments
 (0)