[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] QEMU patch for non-NPTL mode
From: |
Alexander Paramonov |
Subject: |
[Qemu-devel] QEMU patch for non-NPTL mode |
Date: |
Fri, 18 Mar 2011 14:55:36 +0300 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110223 Thunderbird/3.1.8 |
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.
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 <linux/fb.h>
#include <linux/vt.h>
+#include <bits/signum.h>
#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
- [Qemu-devel] QEMU patch for non-NPTL mode,
Alexander Paramonov <=