Thread (14 messages) read the whole thread 14 messages, 3 authors, 2021-07-26

Re: [RFC PATCH 4/4 v0.3] sched/umcg: RFC: implement UMCG syscalls

From: Peter Oskolkov <hidden>
Date: 2021-07-21 23:44:57
Also in: lkml

On Wed, Jul 21, 2021 at 12:56 PM Thierry Delisle [off-list ref] wrote:
 > Yes, this is naturally supported in the current patchset on the kernel
 > side, and is supported in libumcg (to be posted, later when the kernel
 > side is settled); internally at Google, some applications use
 > different "groups" of workers/servers per NUMA node.

Good to know. Cforall has the same feature, where we refer to these groups
as "clusters". https://doi.org/10.1002/spe.2925 (Section 7)

 > Please see the attached atomic_stack.h file - I use it in my tests,
 > things seem to be working. Specifically, atomic_stack_gc does the
 > cleanup. For the kernel side of things, see the third patch in this
 > patchset.

I don't believe the atomic_stack_gc function is robust enough to be
offering
any guarantee. I believe that once a node is unlinked, its next pointer
should
be reset immediately, e.g., by writing 0xDEADDEADDEADDEAD. Do your tests
work
if the next pointer is reset immediately on reclaimed nodes?
In my tests reclaimed nodes have their next pointers immediately set
to point to the list head. If the kernel gets a node with its @next
pointing to something else, then yes, things break down (the kernel
kills the process); this has happened occasionally when I had a bug in
the userspace code.
As far as I can tell, the reclaimed nodes in atomic_stack_gc still contain
valid next fields. I believe there is a race which can lead to the kernel
reading reclaimed nodes. If atomic_stack_gc does not reset the fields,
this bug
could be hidden in the testing.
Could you, please, provide a bit more details on when/how the race can
happen? Servers add themselves to the list, so there can be no races
there (servers going idle: add-to-the-list; wait; gc (under a lock);
restore @next; do stuff).

Workers are trickier, as they can be woken by signals and then block
again, but stray signals are so bad here that I'm thinking of actually
not letting sleeping workers wake on signals. Other than signals
waking queued/unqueued idle workers, are there any other potential
races here?
An more aggressive test is to put each node in a different page and
remove read
permissions when the node is reclaimed. I'm not sure this applies when the
kernel is the one reading.


 > To keep the kernel side light and simple. To also protect the kernel
 > from spinning if userspace misbehaves. Basically, the overall approach
 > is to delegate most of the work to the userspace, and keep the bare
 > minimum in the kernel.

I'll try to keep this in mind then.


After some thought, I'll suggest a scheme to significantly reduce
complexity.
As I understand, the idle_workers_ptr are linked to form one or more
Multi-Producer Single-Consumer queues. If each head is augmented with a
single
volatile tid-sized word, servers that want to go idle can simply write
their id
in the word. When the kernel adds something to the idle_workers_ptr
list, it
simply does an XCHG with 0 or any INVALID_TID. This scheme only supports
one
server blocking per idle_workers_ptr list. To keep the "kernel side
light and
simple", you can simply ask that any extra servers must synchronize
among each
other to pick which server is responsible for wait on behalf of everyone.
I'm not yet convinced that the single-linked-list approach is
infeasible. And if it is, a simple fix would be to have two pointers
per list in struct umcg_task: head and next.

Thanks,
Peter
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help