lkml.org 
[lkml]   [1999]   [Nov]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: spin_unlock optimization(i386)

in fact it's the overflow situation that triggers a causality violation
even on dual boxes. Code attached, it produces:

hell:~> ./causal 0 2
<78266> data3:0 < data4:100001
<thread1> BROKE causality! Weakly ordered memory?

but data4 is always kept smaller than data3! both data4 and data3 are only
ever modified by one of the CPUs, and this is observed on another CPU. The
above shows exactly the case we were worried about:

}
if (i > OVERFLOW) {
data4 = 0;
data3 = 0;

but the second store showed up on the other CPU before the first store.

[if 'causal 1 2' is used (which variant uses the LOCK prefix) then the
assert doesnt seem to trigger.]

i think part of the picture is that the above 'overflow branch' surely is
incorrectly predicted when it triggers. This might open up the window.

{ unless my code is buggy ;) }

Ingo

/*
* Linux SMP memory model and SMP causality tester, Ingo Molnar
*
* Copyright (C) 1999, Ingo Molnar <mingo@redhat.com>
*/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <linux/unistd.h>

volatile static int started = 0;
static int numthreads;
int lock = 0;

#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
#define inc(x) __asm__ __volatile__ ("incl %0": "=m"(x): :"memory")
#define lock_inc(x) __asm__ __volatile__ ("lock; incl %0": "=m"(x): :"memory")

volatile int data1 = 0, data2 = 0;
volatile int data3 = 0, data4 = 0;

#define OVERFLOW 10000

static int test_locking(int cpu)
{
int a, b, i = 0;

switch (cpu) {
case 0:
for (;;) {
i++;
if (lock) {
lock_inc(data3);
lock_inc(data4);
} else {
inc(data3);
inc(data4);
}
if (i > OVERFLOW) {
data4 = 0;
data3 = 0;
i = 0;
}
b = data2;
a = data1;
if (a < b) {
printf("<%d> data1:%d < data2:%d\n", i, a, b);
return 1;
}
}
case 1:
for (;;) {
i++;
if (lock) {
lock_inc(data1);
lock_inc(data2);
} else {
inc(data1);
inc(data2);
}
if (i > OVERFLOW) {
data2 = 0;
data1 = 0;
i = 0;
}
b = data4;
a = data3;
if (a < b) {
printf("<%d> data3:%d < data4:%d\n", i, a, b);
return 1;
}
}
default:
return 1;
}
}

void test_causality (int cpu)
{
asm volatile ("lock; incl %0":"=m"(started));
while (numthreads != started) mb();

test_locking(cpu);

printf("<thread%d> BROKE causality! Weakly ordered memory?\n", cpu);
exit(0);
}

static void start_thread(int cpu)
{
char *newstack = (char *) malloc(100000) + 50000;

*newstack = cpu;
__asm__ __volatile__(
"int $0x80 \n\t" /* Linux/i386 system call */
"testl %0,%0 \n\t" /* check return value */
"jne 1f \n\t" /* jump if parent */
"call *%2 \n\t" /* start subthread function */
"movl %1,%0 \n\t"
"int $0x80 \n\t" /* exit system call: exit subthread */
"1: \n\t"
: :"a" (__NR_clone),"i" (__NR_exit), "r" (test_causality),
"b" (0xaf00 | SIGCHLD), "c" (newstack));
return;
}

int main (int argc, char * * argv)
{
int i;

if (argc != 3) {
printf("usage: causal <LOCK:0/1> <kids:3-8>\n");
exit(0);
}
lock = atol(argv[1]);
numthreads = atol(argv[2]);

for (i = 0; i < numthreads; i++) {
start_thread(i);
}
return (0);
}

\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.107 / U:0.796 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site