Sujet : Re: MSI interrupts
De : mitchalsup (at) *nospam* aol.com (MitchAlsup1)
Groupes : comp.archDate : 27. Mar 2025, 22:47:03
Autres entêtes
Organisation : Rocksolid Light
Message-ID : <34434320650f5844b18b1c0b684acf43@www.novabbs.org>
References : 1 2 3 4 5
User-Agent : Rocksolid Light
On Thu, 27 Mar 2025 17:19:21 +0000, Dan Cross wrote:
In article <7a093bbb356e3bda3782c15ca27e98a7@www.novabbs.org>,
MitchAlsup1 <mitchalsup@aol.com> wrote:
-------------------
Or maybe even just swapping places between two elements in a
linked list. For example:
>
void
swap_places(Node **head, Node *a, Node *b)
{
Node *hp, *an, *ap, *bn, *bp;
>
assert(head != NULL);
assert(a != NULL);
assert(b != NULL);
>
if (a == b)
return;
>
esmLOCKprefetch(*head);
This should be a load not prefetch--you want the value of *head
if (*head == a) // see !
*head = b;
else if (*head == b)
*head = a;
There is a ESM rule that states:: all participating cache lines
must be touched before any participating cache lines can be
modified.
Also note: Participating cache lines are checked for write permission
at touch time, and on cache miss, read with intent to modify.
>
an = esmLOCKload(a->next);
ap = esmLOCKload(a->prev);
bn = esmLOCKload(b->next);
bp = esmLOCKload(b->prev);
>
b->next = an;
if (an != NULL) {
esmLOCKprefetch(an->prev);
an->prev = b;
}
b->prev = ap;
if (ap != NULL) {
esmLOCKprefetch(ap->next);
ap->next = b;
}
>
a->next = bn;
if (bn != NULL) {
esmLOCKprefetch(bn->prev);
bn->prev = a;
}
if (bp != NULL) {
esmLOCKprefetch(bp->next);
bp->next = a;
}
esmLOCKstore(a->prev, bp);
}
>
>
- Dan C.
What I think you want:: (ignoring the 9 participants limit)
void
swap_places(Node **head, Node *a, Node *b)
{
Node *hp, *an, *ap, *bn, *bp;
>
assert(head != NULL);
assert(a != NULL);
assert(b != NULL);
>
if (a == b)
return;
top_of_ATOMIC_event:
// this is the recovery point is you don't use esmINTERFERENCE()
// the very next instruction begins the event.
esmLOCKprefetch( an = esmLOCKload(a->next) );
esmLOCKprefetch( ap = esmLOCKload(a->prev) );
esmLOCKprefetch( bn = esmLOCKload(b->next) );
esmLOCKprefetch( bp = esmLOCKload(b->prev) );
Node *Ehead = esmLOCKload(*head);
// by placing all the the touching before any manifestation, you put
// all the touch latency* in the code before it has tried to damage any
// participating memory location. (*) and TLB latency and 2nd party
// observation of your event.
// this would be the point where you would insert if( esmINTERFERENCE(
))
// if you wanted control at a known failure point rather than at the
// top of the event on failure.
if (Ehead == a)
*head = b;
else if (Ehead == b)
*head = a;
>
b->next = an;
if (an != NULL) {
an->prev = b;
}
b->prev = ap;
if (ap != NULL) {
ap->next = b;
}
>
a->next = bn;
if (bn != NULL) {
bn->prev = a;
}
if (bp != NULL) {
bp->next = a;
}
esmLOCKstore(a->prev, bp);
}
// now manifestation has lowest possible latency (as seen by this core
alone)