Path: ...!weretis.net!feeder9.news.weretis.net!news.nk.ca!rocksolid2!i2pn2.org!.POSTED!not-for-mail From: mitchalsup@aol.com (MitchAlsup1) Newsgroups: comp.arch Subject: Re: MSI interrupts Date: Thu, 27 Mar 2025 21:47:03 +0000 Organization: Rocksolid Light Message-ID: <34434320650f5844b18b1c0b684acf43@www.novabbs.org> References: <7a093bbb356e3bda3782c15ca27e98a7@www.novabbs.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Info: i2pn2.org; logging-data="2030063"; mail-complaints-to="usenet@i2pn2.org"; posting-account="o5SwNDfMfYu6Mv4wwLiW6e/jbA93UAdzFodw5PEa6eU"; User-Agent: Rocksolid Light X-Rslight-Posting-User: cb29269328a20fe5719ed6a1c397e21f651bda71 X-Spam-Checker-Version: SpamAssassin 4.0.0 X-Rslight-Site: $2y$10$.B20EjE9jVgX8hRR9vLozO5.U/GccFK2vLmhp8paoOP.u3IHnMAUa Bytes: 4599 Lines: 128 On Thu, 27 Mar 2025 17:19:21 +0000, Dan Cross wrote: > In article <7a093bbb356e3bda3782c15ca27e98a7@www.novabbs.org>, > MitchAlsup1 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)