[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