From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LpHaP-0002LJ-9i for qemu-devel@nongnu.org; Thu, 02 Apr 2009 03:43:41 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LpHaK-0002L7-LM for qemu-devel@nongnu.org; Thu, 02 Apr 2009 03:43:40 -0400 Received: from [199.232.76.173] (port=54810 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LpHaK-0002L4-F0 for qemu-devel@nongnu.org; Thu, 02 Apr 2009 03:43:36 -0400 Received: from mx20.gnu.org ([199.232.41.8]:12444) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LpHaJ-0004UH-Pc for qemu-devel@nongnu.org; Thu, 02 Apr 2009 03:43:36 -0400 Received: from an-out-0708.google.com ([209.85.132.245]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LpHaI-0005kx-RV for qemu-devel@nongnu.org; Thu, 02 Apr 2009 03:43:35 -0400 Received: by an-out-0708.google.com with SMTP id c5so301338anc.37 for ; Thu, 02 Apr 2009 00:43:32 -0700 (PDT) MIME-Version: 1.0 Date: Thu, 2 Apr 2009 15:43:31 +0800 Message-ID: From: doremi Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] Qemu threading support? Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Hello, These days I have to add multi-threading support for Qemu (Performace is not important for me). But it's very complicated, could anybody do me a favor? Thanks~ (host machine is x86_64, target is x86) The following steps are how I try to do: 1. Adding a structure LOOKUP_TABLE in vl.c +#define num_thread 2 + +struct LOOKUP_TABLE { + pthread_t tid; + CPUState* env_ptr; +} lookup_tbl[num_thread]; + +static CPUState* lookup(pthread_t tid) +{ + int i = 0; + // while(lookup_tbl[0].tid == 0); + /* we examined in host_alarm_handler */ + for (i = 0; i < num_thread; ++i) { + if (lookup_tbl[i].tid == tid) + return lookup_tbl[i].env_ptr; + } + printf("Error FILE: %s, LINE: %d\n", __FILE__, __LINE__); + return NULL; +} + 2. modify host_alarm_handler() in vl.c +#if 0 if (env) { /* stop the currently executing cpu because a timer occured */ cpu_interrupt(env, CPU_INTERRUPT_EXIT); } +#endif + int j; + for (j = 0; j < num_thread; ++j) { + if (lookup_tbl[j].tid != 0) + pthread_kill(lookup_tbl[j].tid, SIGUSR1); + } 3. adding 2 thread function in vl.c +static void *cpu_exec2(void *ptr) +{ + lookup_tbl[1].env_ptr = ptr; + for (;;) { + lookup_tbl[1].env_ptr = ptr; + cpu_exec(ptr); + lookup_tbl[1].env_ptr = NULL; + main_loop_wait(0); + } + return NULL; +} + +static void *cpu_exec1(void *ptr) +{ + lookup_tbl[0].env_ptr = ptr; + + pthread_create(&lookup_tbl[1].tid, NULL, cpu_exec2, first_cpu->next_cpu); + + for (;;) { + lookup_tbl[0].env_ptr = ptr; + cpu_exec(ptr); + lookup_tbl[0].env_ptr = NULL; + main_loop_wait(0); + } + return NULL; +} 4. adding some functions for thread signal +static void thread_signal_handler(int sig) +{ + struct CPUState *env1; + env1 = lookup(pthread_self()); + //env1 = first_cpu; + if (env1) { /* ???? if (env) ... */ + cpu_interrupt(env1, CPU_INTERRUPT_EXIT); + } +} + +static void init_signal(void) +{ + struct sigaction act; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = thread_signal_handler; + sigaction(SIGUSR1, &act, NULL); +} 5. main_loop() in vl.c + int rets[num_thread], *status[num_thread]; cur_cpu = first_cpu; next_cpu = cur_cpu->next_cpu ?: first_cpu; + + memset(lookup_tbl, 0, sizeof(lookup_tbl)); + pthread_create(&lookup_tbl[0].tid, NULL, cpu_exec1, first_cpu); 6. in cpu-all.h register CPUState *cpu_single_env asm("r12"); First, I try create 2 thread, each thread's cpu_single_env is replaced to asm("r12"), because cpu_single_env is a global variable, If I put it into a register, it implied local variable. Second, each thread execute the same thing: cpu_exec() and then force main_loop_wait(0) Third, I modified host_alarm_handler(), if a timer interrupt occurred, the original method is check whether env is NULL or not, then call cpu_interrupt(). The new way is call pthread_kill() to every thread by SIGUSR1, when every thread get the signal, it will check lookup_tbl's env is valid or not, then call cpu_interrupt My objective is to build a multi-thread qemu, and run linux kernel, and the performace and atomic operation is not important, but these code doesn't work, it may segmentation fault when disas_insn(pc_start = 0). What can I do for next step? Which or where step I was wrong? Or can anybody give me a multi-thread qemu (even if it doesn't work prefect), thanks~ all my code is in http://140.123.102.106/qemu.tgz compile argument: ./configure --target-list=i386-softmmu --disable-kqemu