[parisc-linux] Re: + parisc-add-ptr-compatpatch.patch added to -mm tree

Ingo Molnar mingo at elte.hu
Sat Apr 8 17:58:04 MDT 2006


* Andrew Morton <akpm at osdl.org> wrote:

> > Looks good to me, should this go in through my tree? I've nothing really
> > queued from CVS that needs to be merged for 2.6.16, so I'm happy either
> > way if it goes in through your tree.
> > 
> 
> It's post-2.6.16 stuff.  Hopefully you'll have had a chance to test 
> the robust-futex code by then, but afaik there's not a sane test suite 
> available and you need to install some devel branch of glibc (horror).  
> Ingo?

There's only one complication i can imagine on PARISC: truly atomic 
futex_atomic_cmpxchg_inuser() is not possible in any sane way because 
any spinlock based cmpxchg exposes itself to userspace locking up the 
kernel - no good. [We could in theory do something about it by imposing 
some sort of deadline on the maximum time the spinning-on-userspace-lock 
can take - but i dont think it's worth the trouble.]

So i'd suggest to simply implement a non-atomic variant - that will be 
pretty good already: once we determine in futex_handle_death() that "the 
dying thread owns this futex", that condition is not supposed to change, 
and any subsequent races are pretty academic anyway. Maybe i'll rename 
it to futex_cmpxchg_inuser(), to relax the atomicity requirements.

Testability - i've got some simple testcode for x86 (attached below).  
Ulrich has the glibc changes, but indeed they are not for mortals :)

> As for who merges, umm, dunno.  I guess it'd be simplest if I were to 
> do so, unless you have other needs for ptr_to_compat() in the 
> meanwhile.

These changes can go upstream independently of the robust-futex stuff - 
they are a sensible enhancement to compat.h.

	Ingo

-----{ test-robust-list.c }------------------------>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <linux/futex.h>
#include <sys/time.h>

#define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)) : "memory"); \
	return __res; \
}

#define _syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1,type2 arg2) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
	: "=a" (__res) \
	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)) : "memory"); \
	return __res; \
}

#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
	long __res; \
	__asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
                  "d" ((long)(arg3)) : "memory"); \
	return __res; \
}


struct robust_list {
	struct robust_list *next;
};

struct lock {
	unsigned int futex_val;
	struct robust_list entry;
};

struct robust_list_head {
	struct robust_list list;
	unsigned long futex_offset;
	struct robust_list *pending_lock;
};

#define __NR_sys_set_robust_list 311
#define __NR_sys_get_robust_list 312

_syscall2 (long, sys_set_robust_list, struct robust_list_head *, head, size_t, len)
_syscall3 (long, sys_get_robust_list, int, tid, struct robust_list_head **, head, size_t *, len_ptr)

static struct robust_list_head head;
#define NR_LOCKS 1000
static struct lock locks[NR_LOCKS];

int main (void)
{
	struct robust_list_head *tmp = NULL;
	struct robust_list *prev;
	struct lock *lock;
	size_t len;
	long ret;
	int i;

	printf("locks size: %d\n", sizeof(struct lock) * NR_LOCKS);
#if 0
	// create a deliberately circular list:
	locks[0].entry.next = &locks[0].entry;
	locks[0].futex_val = getpid();
	head.list.next = &locks[0].entry;
#else
	prev = &head.list;
	for (i = 0; i < NR_LOCKS; i++) {
		lock = locks + i;
		lock->futex_val = getpid();
		prev->next = &lock->entry;
		prev = &lock->entry;
	}
	lock->entry.next = &head.list;
	head.pending_lock = &lock->entry;
#endif

	head.futex_offset = (unsigned long) &lock->futex_val -
				(unsigned long) &lock->entry;
	printf("offset: %08lx\n", head.futex_offset);

	printf("head: %p, head.next: %p\n", &head, head.list.next);
	ret = sys_set_robust_list(&head, sizeof(head));
	printf("set_robust_list(%p): %ld\n", &head, ret);

	ret = sys_get_robust_list(0, &tmp, &len);
	printf("get_robust_list(): %ld, %p, %d\n", ret, tmp, len);
	ret = sys_get_robust_list(getppid(), &tmp, &len);
	printf("get_robust_list(parent): %ld, %p, %d\n", ret, tmp, len);
	ret = sys_get_robust_list(1, &tmp, &len);
	printf("get_robust_list(init): %ld, %p, %d\n", ret, tmp, len);

	return 0;
}




More information about the parisc-linux mailing list