From patchwork Tue Mar 22 12:16:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 87905 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 70A78B6F7C for ; Tue, 22 Mar 2011 23:19:45 +1100 (EST) Received: from localhost ([127.0.0.1]:41757 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q20Yn-0002sQ-8T for incoming@patchwork.ozlabs.org; Tue, 22 Mar 2011 08:19:41 -0400 Received: from [140.186.70.92] (port=51342 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q20X1-0001x4-O7 for qemu-devel@nongnu.org; Tue, 22 Mar 2011 08:17:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q20Wz-0000AT-7o for qemu-devel@nongnu.org; Tue, 22 Mar 2011 08:17:51 -0400 Received: from moutng.kundenserver.de ([212.227.17.9]:59174) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q20Wy-00008w-SQ for qemu-devel@nongnu.org; Tue, 22 Mar 2011 08:17:49 -0400 Received: from [192.168.100.1] (wlp38-1-78-238-229-36.fbx.proxad.net [78.238.229.36]) by mrelayeu.kundenserver.de (node=mreu4) with ESMTP (Nemesis) id 0LkEpj-1PRIrj0X07-00cRl4; Tue, 22 Mar 2011 13:17:44 +0100 Subject: Re: [Qemu-devel] QEMU patch for non-NPTL mode From: Laurent Vivier To: Alexander Paramonov In-Reply-To: <4D834838.7040507@gmail.com> References: <4D834838.7040507@gmail.com> Date: Tue, 22 Mar 2011 13:16:02 +0100 Message-ID: <1300796162.3930.11.camel@Quad> Mime-Version: 1.0 X-Mailer: Evolution 2.30.3 X-Provags-ID: V02:K0:EBEr9YxAvEqwxHA555uaRCuJ6a6pruJx04+l2Jn8E5m w/I8bBkIfuyXYZYHx0hlrcORGZ0a9Evpi2z1zNzmZX9v4o830b a+S12b4z5SE+Zxq4RW/usU9qIyHwpXueuaXHcLfb7eLz6EHYum ZmcGAB68nIphl1u68qRv2KervuQOBhNTYiVmHYwKOStjNkEQjg q3sqAViD1NbKtOueOUZeAn7RVQb2/hFfdDWgJhtA1o= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 212.227.17.9 Cc: qemu-devel@nongnu.org X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Le vendredi 18 mars 2011 à 14:55 +0300, Alexander Paramonov a écrit : > Hello! We use QEMU to run ARM-compiled soft on PC Linux OS. Our soft is > linked with uClibc library in non-NPTL mode. So there are some problems > in running multi-threaded applications under QEMU: > 1. Both uClibc and gLibc use 32 and 33 signals and conflict. > 2. Signals processing was not thread-safe. > Here's a patch which makes our soft working fine. Perhaps, you would > find something useful and apply it in yout further QEMU versions. > > Alexander, Terminal Technologies, Russia. Hi, I've tested the signals processing part with m68k-linux-user and it works fine (debian etch-m68k doesn't have NPTL support). But your patch doesn't apply cleanly (a carriage return on line 119, some blanks on lines start) and it doesn't follow coding style (tabulation and brace). Moreover, I think it should be split into two patches. You can find attached the patches I applied to my development tree. Regards, Laurent > diff -ruN qemu_orig/linux-user/qemu.h qemu_patched/linux-user/qemu.h > --- qemu_orig/linux-user/qemu.h 2011-02-16 17:44:05.000000000 +0300 > +++ qemu_patched/linux-user/qemu.h 2011-03-17 19:16:13.000000000 +0300 > @@ -80,6 +80,7 @@ > struct sigqueue { > struct sigqueue *next; > target_siginfo_t info; > + pid_t pid; > }; > > struct emulated_sigtable { > diff -ruN qemu_orig/linux-user/signal.c qemu_patched/linux-user/signal.c > --- qemu_orig/linux-user/signal.c 2011-02-16 17:44:05.000000000 +0300 > +++ qemu_patched/linux-user/signal.c 2011-03-18 14:29:57.991141322 +0300 > @@ -314,6 +314,8 @@ > for(i = 1; i < _NSIG; i++) { > if (host_to_target_signal_table[i] == 0) > host_to_target_signal_table[i] = i; > + if (i >= SIGRTMIN && i <= SIGRTMAX) > + host_to_target_signal_table[i] = __SIGRTMIN + (i - SIGRTMIN); > } > for(i = 1; i < _NSIG; i++) { > j = host_to_target_signal_table[i]; > @@ -473,6 +475,7 @@ > *pq = q; > q->info = *info; > q->next = NULL; > + q->pid = getpid(); > k->pending = 1; > /* signal that a new signal is pending */ > ts->signal_pending = 1; > @@ -4896,21 +4899,34 @@ > target_sigset_t target_old_set; > struct emulated_sigtable *k; > struct target_sigaction *sa; > - struct sigqueue *q; > - TaskState *ts = cpu_env->opaque; > + struct sigqueue *q, *q_prev; > + TaskState *ts = thread_env->opaque; > > if (!ts->signal_pending) > return; > > - /* FIXME: This is not threadsafe. */ > k = ts->sigtab; > + int signal_pending = 0; > for(sig = 1; sig <= TARGET_NSIG; sig++) { > if (k->pending) > - goto handle_signal; > + { > + q = k->first; > + q_prev = NULL; > + while (q) > + { > + if (q->pid == getpid()) > + goto handle_signal; > + else > + signal_pending = 1; > + q_prev = q; > + q = q->next; > + } > + } > k++; > } > + > /* if no signal is pending, just return */ > - ts->signal_pending = 0; > + ts->signal_pending = signal_pending; > return; > > handle_signal: > @@ -4918,10 +4934,19 @@ > fprintf(stderr, "qemu: process signal %d\n", sig); > #endif > /* dequeue signal */ > - q = k->first; > - k->first = q->next; > - if (!k->first) > - k->pending = 0; > + if (q_prev == k->first) > + { > + q = k->first; > + k->first = q->next; > + if (!k->first) > + { > + k->pending = 0; > + } > + } > + else if (q_prev) > + q_prev->next = q->next; > + else > + k->pending = 0; > > sig = gdb_handlesig (cpu_env, sig); > if (!sig) { > diff -ruN qemu_orig/linux-user/syscall.c qemu_patched/linux-user/syscall.c > --- qemu_orig/linux-user/syscall.c 2011-02-16 17:44:05.000000000 +0300 > +++ qemu_patched/linux-user/syscall.c 2011-03-18 14:32:47.107641348 +0300 > @@ -88,6 +88,7 @@ > #endif > #include > #include > +#include > #include "linux_loop.h" > #include "cpu-uname.h" > > @@ -3827,6 +3828,12 @@ > #ifdef __ia64__ > ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, > new_env); > #else > + unsigned int clone_sig = flags & CSIGNAL; > + if (clone_sig >= __SIGRTMIN && clone_sig <= __SIGRTMIN+2) > + { > + flags &= ~CSIGNAL; > + flags |= SIGRTMIN + (clone_sig - __SIGRTMIN); > + } > ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); > #endif > #endif > From bda825012e189a6dfcae0f0bd761ebe0e20b93f4 Mon Sep 17 00:00:00 2001 From: Alexander Paramonov Date: Mon, 21 Mar 2011 16:49:23 +0100 Subject: [PATCH 2/2] linux-user: Both uClibc and gLibc use 32 and 33 signals and conflict. Signed-off-by: Alexander Paramonov Signed-off-by: Laurent Vivier --- linux-user/signal.c | 2 ++ linux-user/syscall.c | 7 +++++++ 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 93d2c44..4adf74a 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -314,6 +314,8 @@ void signal_init(void) for(i = 1; i < _NSIG; i++) { if (host_to_target_signal_table[i] == 0) host_to_target_signal_table[i] = i; + if (i >= SIGRTMIN && i <= SIGRTMAX) + host_to_target_signal_table[i] = __SIGRTMIN + (i - SIGRTMIN); } for(i = 1; i < _NSIG; i++) { j = host_to_target_signal_table[i]; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 23d7a63..8f218bd 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -91,6 +91,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #endif #include #include +#include #include "linux_loop.h" #include "cpu-uname.h" @@ -3845,6 +3846,12 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, #ifdef __ia64__ ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env); #else + unsigned int clone_sig = flags & CSIGNAL; + if (clone_sig >= __SIGRTMIN && clone_sig <= __SIGRTMIN+2) + { + flags &= ~CSIGNAL; + flags |= SIGRTMIN + (clone_sig - __SIGRTMIN); + } ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); #endif #endif -- 1.7.1