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)

> > if you want to trigger the bug, then you must _both_ read and write data
> > from one cpu. If one cpu writes data, and one cpu reads data, then
> > you'll never trigger the problem.
>
> yep, thats another type of causality violation, will try to generate a
> testcase. [i think i have one, i'm checking it now]

ok, the attached causal.c generates (the i believe simplest) such a
testcase. It's the basic causality test done on two CPUs, where both CPUs
are observers and 'creators' as well. Run it with:

./causal 0 2

to get the causality violation. [to speed up the triggering of a violation
on a >2CPU box, run it twice]

'./causal 1 2' does the stores via LOCK-ed instructions and i have not
managed to trigger the violation.

-- mingo

/*
* 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;

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 > 1000000000) {
data4 = 0;
data3 = 0;
i = 0;
}
b = data2;
a = data1;
if (a < b) {
printf("<%d> %d %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 > 1000000000) {
data2 = 0;
data1 = 0;
i = 0;
}
b = data4;
a = data3;
if (a < b) {
printf("<%d> %d %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(10000) + 5000;

*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.132 / U:0.500 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site