Skip to content
  • David Hildenbrand's avatar
    e2de2c49
    util: Introduce ThreadContext user-creatable object · e2de2c49
    David Hildenbrand authored
    
    
    Setting the CPU affinity of QEMU threads is a bit problematic, because
    QEMU doesn't always have permissions to set the CPU affinity itself,
    for example, with seccomp after initialized by QEMU:
        -sandbox enable=on,resourcecontrol=deny
    
    General information about CPU affinities can be found in the man page of
    taskset:
        CPU affinity is a scheduler property that "bonds" a process to a given
        set of CPUs on the system. The Linux scheduler will honor the given CPU
        affinity and the process will not run on any other CPUs.
    
    While upper layers are already aware of how to handle CPU affinities for
    long-lived threads like iothreads or vcpu threads, especially short-lived
    threads, as used for memory-backend preallocation, are more involved to
    handle. These threads are created on demand and upper layers are not even
    able to identify and configure them.
    
    Introduce the concept of a ThreadContext, that is essentially a thread
    used for creating new threads. All threads created via that context
    thread inherit the configured CPU affinity. Consequently, it's
    sufficient to create a ThreadContext and configure it once, and have all
    threads created via that ThreadContext inherit the same CPU affinity.
    
    The CPU affinity of a ThreadContext can be configured two ways:
    
    (1) Obtaining the thread id via the "thread-id" property and setting the
        CPU affinity manually (e.g., via taskset).
    
    (2) Setting the "cpu-affinity" property and letting QEMU try set the
        CPU affinity itself. This will fail if QEMU doesn't have permissions
        to do so anymore after seccomp was initialized.
    
    A simple QEMU example to set the CPU affinity to host CPU 0,1,6,7 would be:
        qemu-system-x86_64 -S \
          -object thread-context,id=tc1,cpu-affinity=0-1,cpu-affinity=6-7
    
    And we can query it via HMP/QMP:
        (qemu) qom-get tc1 cpu-affinity
        [
            0,
            1,
            6,
            7
        ]
    
    But note that due to dynamic library loading this example will not work
    before we actually make use of thread_context_create_thread() in QEMU
    code, because the type will otherwise not get registered. We'll wire
    this up next to make it work.
    
    In general, the interface behaves like pthread_setaffinity_np(): host
    CPU numbers that are currently not available are ignored; only host CPU
    numbers that are impossible with the current kernel will fail. If the
    list of host CPU numbers does not include a single CPU that is
    available, setting the CPU affinity will fail.
    
    A ThreadContext can be reused, simply by reconfiguring the CPU affinity.
    Note that the CPU affinity of previously created threads will not get
    adjusted.
    
    Reviewed-by: default avatarMichal Privoznik <mprivozn@redhat.com>
    Acked-by: default avatarMarkus Armbruster <armbru@redhat.com>
    Message-Id: <20221014134720.168738-4-david@redhat.com>
    Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
    e2de2c49
    util: Introduce ThreadContext user-creatable object
    David Hildenbrand authored
    
    
    Setting the CPU affinity of QEMU threads is a bit problematic, because
    QEMU doesn't always have permissions to set the CPU affinity itself,
    for example, with seccomp after initialized by QEMU:
        -sandbox enable=on,resourcecontrol=deny
    
    General information about CPU affinities can be found in the man page of
    taskset:
        CPU affinity is a scheduler property that "bonds" a process to a given
        set of CPUs on the system. The Linux scheduler will honor the given CPU
        affinity and the process will not run on any other CPUs.
    
    While upper layers are already aware of how to handle CPU affinities for
    long-lived threads like iothreads or vcpu threads, especially short-lived
    threads, as used for memory-backend preallocation, are more involved to
    handle. These threads are created on demand and upper layers are not even
    able to identify and configure them.
    
    Introduce the concept of a ThreadContext, that is essentially a thread
    used for creating new threads. All threads created via that context
    thread inherit the configured CPU affinity. Consequently, it's
    sufficient to create a ThreadContext and configure it once, and have all
    threads created via that ThreadContext inherit the same CPU affinity.
    
    The CPU affinity of a ThreadContext can be configured two ways:
    
    (1) Obtaining the thread id via the "thread-id" property and setting the
        CPU affinity manually (e.g., via taskset).
    
    (2) Setting the "cpu-affinity" property and letting QEMU try set the
        CPU affinity itself. This will fail if QEMU doesn't have permissions
        to do so anymore after seccomp was initialized.
    
    A simple QEMU example to set the CPU affinity to host CPU 0,1,6,7 would be:
        qemu-system-x86_64 -S \
          -object thread-context,id=tc1,cpu-affinity=0-1,cpu-affinity=6-7
    
    And we can query it via HMP/QMP:
        (qemu) qom-get tc1 cpu-affinity
        [
            0,
            1,
            6,
            7
        ]
    
    But note that due to dynamic library loading this example will not work
    before we actually make use of thread_context_create_thread() in QEMU
    code, because the type will otherwise not get registered. We'll wire
    this up next to make it work.
    
    In general, the interface behaves like pthread_setaffinity_np(): host
    CPU numbers that are currently not available are ignored; only host CPU
    numbers that are impossible with the current kernel will fail. If the
    list of host CPU numbers does not include a single CPU that is
    available, setting the CPU affinity will fail.
    
    A ThreadContext can be reused, simply by reconfiguring the CPU affinity.
    Note that the CPU affinity of previously created threads will not get
    adjusted.
    
    Reviewed-by: default avatarMichal Privoznik <mprivozn@redhat.com>
    Acked-by: default avatarMarkus Armbruster <armbru@redhat.com>
    Message-Id: <20221014134720.168738-4-david@redhat.com>
    Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Loading