Skip to content

SCX eBPF macro ARRAY_ELEM_PTR

v6.12

The ARRAY_ELEM_PTR macro obtains a verified pointer to an array element.

Definition

#define ARRAY_ELEM_PTR(arr, i, n) (typeof(arr[i]) *)    \
({                                                      \
    u64 __base = (u64)arr;                              \
    u64 __addr = (u64)&(arr[i]) - __base;               \
    asm volatile (                                      \
        "if %0 <= %[max] goto +2\n"                     \
        "%0 = 0\n"                                      \
        "goto +1\n"                                     \
        "%0 += %1\n"                                    \
        : "+r"(__addr)                                  \
        : "r"(__base),                                  \
          [max]"r"(sizeof(arr[0]) * ((n) - 1)));        \
    __addr;                                             \
})

Usage

Similar to MEMBER_VPTR but is intended for use with arrays where the element count needs to be explicit. It can be used in cases where a global array is defined with an initial size but is intended to be be resized before loading the BPF program. Without this version of the macro, MEMBER_VPTR will use the compile time size of the array to compute the max, which will result in rejection by the verifier.

Parameters

arr: array to index into

i: array index

n: number of elements in array

Example

/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
 * Copyright (c) 2022 Tejun Heo <tj@kernel.org>
 * Copyright (c) 2022 David Vernet <dvernet@meta.com>
 */

u64 RESIZABLE_ARRAY(data, cpu_started_at);

void BPF_STRUCT_OPS(central_running, struct task_struct *p)
{
    s32 cpu = scx_bpf_task_cpu(p);
    u64 *started_at = ARRAY_ELEM_PTR(cpu_started_at, cpu, nr_cpu_ids);
    if (started_at)
        *started_at = scx_bpf_now() ?: 1;  /* 0 indicates idle */
}