Re: frlock and barrier discussion

From: Andrea Arcangeli (andrea@suse.de)
Date: Thu Jan 30 2003 - 13:26:22 EST


On Thu, Jan 30, 2003 at 07:20:33PM +0100, Manfred Spraul wrote:
> Stephen wrote:
>
> [snip - memory barrier for fr_write_begin]
>
> >Using mb() is more paranoid than necessary.
>
>
> What about the memory barrier in fr_read_begin?
> If I understand the Intel documentation correctly, then i386 doesn't need
> them:
> "Writes by a single processor are observed in the same order by all
> processors"
>
> I think "smp_read_barrier_depends()" (i.e. a nop for i386) is sufficient.

I don't see what you mean, there is no dependency we can rely on between
the read of the sequence number and the critical section reads, the
critical section reads has nothing to do with the sequence number reads
and the frlock itself.

> Attached is a test app - could someone try it? I don't have access to a SMP
> system right now.
>
>
> What about permitting arch overrides for the memory barriers? E.g. ia64 has
> acquire and release memory barriers - it doesn't map to the Linux
> wmb()/rmb() scheme.
>
> --
> Manfred
>
>
>
>
>
>
>
>
>
>
>
>

> /*
> * frlock: test for Intel memory ordering.
> * Copyright (C) 1999,2003 by Manfred Spraul.
> *
> * Redistribution of this file is permitted under the terms of the GNU
> * Public License (GPL)
> * $Header: /pub/home/manfred/cvs-tree/movopt/frlock.cpp,v 1.2 2003/01/26 10:41:39 manfred Exp $
> */
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> #include <pthread.h>
> #include <assert.h>
>
> static volatile int g_val1;
> static volatile int g_val2;
> static volatile int g_seq1;
> static volatile int g_seq2;
>
> static volatile int start;
> #define MB() __asm__ __volatile__ ("lock;addl $0,(%%esp)\n\t" \
> :/* no output*/ \
> :/* no input*/:"cc","memory")
>
> #define DELAY() do { int i; for(i=0;i<1000;i++); } while(0)
>
> void* threadfnc(void* param)
> {
> while(!start);
> if(1 == (int)param)
> goto cpu1;
> if(2 == (int)param)
> goto cpu2;
> assert(0);
> cpu1:
> { // reader:
> for(;;) {
> int x1,x2,val1,val2;
>
> x1 = g_seq1;
> val1 = g_val1;
> val2 = g_val2;
> x2 = g_seq2;
> if (x1 == x2) {
> if (val1 != val2) {
> printf("Bad! memory ordering violation with %d/%d: %d/%d.\n", x1, x2, val1, val2);
> }
> }
> }
> }
> cpu2:
> { // writer:
> int target = 0;
> for (;;) {
>
> // write 1:
> target++;
> g_seq1 = target;
> g_val1 = target;
> g_val2 = target;
> g_seq2 = target;
> DELAY();
>
> // write 2:
> target++;
> g_seq1 = target;
> g_val1 = target;
> MB();
> g_val2 = target;
> g_seq2 = target;
> DELAY();
>
> // write 3:
> target++;
> g_seq1 = target;
> g_val2 = target;
> g_val1 = target;
> g_seq2 = target;
> DELAY();
>
> // write 4:
> target++;
> g_seq1 = target;
> g_val2 = target;
> MB();
> g_val1 = target;
> g_seq2 = target;
> DELAY();
>
>
>
> // write 5:
> target++;
> g_seq1 = target;
> g_val1 = target;
> MB(); MB();
> g_val2 = target;
> g_seq2 = target;
> DELAY();
>
> // write 6:
> target++;
> g_seq1 = target;
> g_val1 = target;
> MB(); DELAY();
> g_val2 = target;
> g_seq2 = target;
> DELAY();
>
> // write 7:
> target++;
> g_seq1 = target;
> g_val2 = target;
> MB(); MB();
> g_val1 = target;
> g_seq2 = target;
> DELAY();
>
> // write 8:
> target++;
> g_seq1 = target;
> g_val2 = target;
> MB(); DELAY();
> g_val1 = target;
> g_seq2 = target;
> DELAY();
> }
> }
> }
>
> void start_thread(int id)
> {
> pthread_t thread;
> int res;
>
> res = pthread_create(&thread,NULL,threadfnc,(void*)id);
> if(res != 0)
> assert(false);
> }
>
>
>
> int main()
> {
> printf("movopt:\n");
> start_thread(1);
> start_thread(2);
> printf(" starting, please wait.\n");
> fflush(stdout);
> start = 1;
> for(;;) sleep(1000);
> }

Andrea
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Jan 31 2003 - 22:00:24 EST