Re: AVL trees vs. Red-Black trees

Oliver Xymoron (oxymoron@waste.org)
Mon, 29 Nov 1999 16:20:35 -0600 (CST)


On Mon, 29 Nov 1999, Ingo Molnar wrote:

> On Mon, 29 Nov 1999, Andrea Arcangeli wrote:
>
> > Unfortunately the empirical test tells that something must be going wrong.
>
> (you mean Manfred's testcase, right?) Can you extract the testcase from
> assembly into the 'causal.c' testcode by any chance?

Did you see my simplified version of Manfred's code? Just look at func1
and func2:

/*
* movopt: test for Intel memory ordering.
* Copyright (C) 1999 by Manfred Spraul.
*
* Redistribution of this file is permitted under the terms of the GNU
* Public License (GPL)
* $Header: /pub/cvs/ms/movopt/movopt.cpp,v 1.3 1999/11/25 23:38:44 manfreds Ex
p $
*/

/*
NOTE: this code will run _extremely_ slowly on UP systems

func1 and func2 are the functions that may race with each other

cpu1 and cpu2 are thread functions that synchronize func1 and func2
while adjusting timings
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>

#define USE_MB 0
#define USE_ASM 1

volatile int start = 0;
volatile int current_state = 0;
volatile int lock = 1;
volatile int ready = 0;
volatile int go = 0;

#if USE_ASM == 0 /* doesn't compile, here for explanation */

static inline void func1()
{
set_current_state(1);
if(lock!=1)
while (current_state!=0)
;
}

static inline void func2()
{
lock=0;
current_state=0;
mb();
}

#else
static inline void func1()
{
__asm__ __volatile(
#if USE_MB == 0
"movl $1,%1\n\t" /* set current_state = 1 */
#else
"lock;bts $0,%1\n\t"
#endif
"movl %0,%%eax\n\t" /* lock into %%eax */
"cmpl $1,%%eax\n\t"
"jne dont_sleep\n"
"retry:\n\t"
"movl %1, %%eax\n\t"
"cmpl $0,%%eax\n\t"
"jne retry\n"
"dont_sleep:\n"
: /* no output */
: "m" (lock), "m" (current_state)
: "eax", "cc", "memory");
}

static inline void func2()
{
__asm__ __volatile(
"movl $0,%0\n\t"
"movl $0,%1\n\t"
"lock; addl $0,(%%esp)\n\t" /* flush our write buffers*/
: /* no output */
: "m" (lock), "m" (current_state)
: "memory");
}
#endif

void* cpu1(void* param)
{
/* 1: always sleep
10 000: never sleep
PII/350: lock-up at delay=217
*/
volatile int delay = 1;

int i=0,j;

while(!start)
;

for(;i<50000000;i++) {
lock = 1;
current_state = 0;
go = 0;
while(!ready)
;
go = 1;

for(j=0;j<delay;j++)
;

func1();

if((i%5000)==0) {
printf("delay %d: ok\n",delay);
delay++;
}
}

printf("thread %d finished.\n",(int)param);
exit(0);
}

void* cpu2(void* param)
{
/* increase this value if no lock-up occurs,
eg: 2000
*/
volatile int delay2 = 300;

int i=0,j;

while(!start)
;

for(;;) {
ready = 1;
while(!go)
;
ready = 0;
go = 0;

for(j=0;j<delay2;j++)
;

func2();
}
}

typedef void *threadfunc(void *);

void start_thread(threadfunc *f)
{
pthread_t thread;
int res;

res = pthread_create(&thread,NULL,f,NULL);
if(res != 0)
assert(0);
}

int main()
{
printf("movopt:\n");
start_thread(cpu1);
start_thread(cpu2);
printf(" starting, please wait.\n");
fflush(stdout);
start = 1;
for(;;) sleep(1000);
}

--
 "Love the dolphins," she advised him. "Write by W.A.S.T.E.." 

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