better locks
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 14 May 2003 21:51:13 +0000 (21:51 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 14 May 2003 21:51:13 +0000 (21:51 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@169 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-i386.h
exec.c

index 44411b0caaa818e498a456daed00ce8f8d392516..008ff8cd2b77d22563957cb68fe7cea12d4f77f9 100644 (file)
@@ -542,4 +542,104 @@ static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
 #define offsetof(type, field) ((size_t) &((type *)0)->field)
 #endif
 
+#ifdef __powerpc__
+static inline int testandset (int *p)
+{
+    int ret;
+    __asm__ __volatile__ (
+                          "0:    lwarx %0,0,%1 ;"
+                          "      xor. %0,%3,%0;"
+                          "      bne 1f;"
+                          "      stwcx. %2,0,%1;"
+                          "      bne- 0b;"
+                          "1:    "
+                          : "=&r" (ret)
+                          : "r" (p), "r" (1), "r" (0)
+                          : "cr0", "memory");
+    return ret;
+}
+#endif
+
+#ifdef __i386__
+static inline int testandset (int *p)
+{
+    char ret;
+    long int readval;
+    
+    __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+                          : "=q" (ret), "=m" (*p), "=a" (readval)
+                          : "r" (1), "m" (*p), "a" (0)
+                          : "memory");
+    return ret;
+}
+#endif
+
+#ifdef __s390__
+static inline int testandset (int *p)
+{
+    int ret;
+
+    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
+                         "   jl    0b"
+                         : "=&d" (ret)
+                         : "r" (1), "a" (p), "0" (*p) 
+                         : "cc", "memory" );
+    return ret;
+}
+#endif
+
+#ifdef __alpha__
+int testandset (int *p)
+{
+    int ret;
+    unsigned long one;
+
+    __asm__ __volatile__ ("0:  mov 1,%2\n"
+                         "     ldl_l %0,%1\n"
+                         "     stl_c %2,%1\n"
+                         "     beq %2,1f\n"
+                         ".subsection 2\n"
+                         "1:   br 0b\n"
+                         ".previous"
+                         : "=r" (ret), "=m" (*p), "=r" (one)
+                         : "m" (*p));
+    return ret;
+}
+#endif
+
+#ifdef __sparc__
+static inline int testandset (int *p)
+{
+       int ret;
+
+       __asm__ __volatile__("ldstub    [%1], %0"
+                            : "=r" (ret)
+                            : "r" (p)
+                            : "memory");
+
+       return (ret ? 1 : 0);
+}
+#endif
+
+typedef int spinlock_t;
+
+#define SPIN_LOCK_UNLOCKED 0
+
+static inline void spin_lock(spinlock_t *lock)
+{
+    while (testandset(lock));
+}
+
+static inline void spin_unlock(spinlock_t *lock)
+{
+    *lock = 0;
+}
+
+static inline int spin_trylock(spinlock_t *lock)
+{
+    return !testandset(lock);
+}
+
+extern spinlock_t tb_lock;
+
 #endif /* CPU_I386_H */
diff --git a/exec.c b/exec.c
index 0ed49c69576ff11a29ce2461d2c6841b4d9da8ff..8804bfab78a0c230d4a1cb1be595cbeaf43ec003 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -42,6 +42,8 @@
 TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
 TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
 int nb_tbs;
+/* any access to the tbs or the page table must use this lock */
+spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
 
 uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
 uint8_t *code_gen_ptr;
@@ -172,6 +174,7 @@ void page_set_flags(unsigned long start, unsigned long end, int flags)
     end = TARGET_PAGE_ALIGN(end);
     if (flags & PAGE_WRITE)
         flags |= PAGE_WRITE_ORG;
+    spin_lock(&tb_lock);
     for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
         p = page_find_alloc(addr >> TARGET_PAGE_BITS);
         /* if the write protection is set, then we invalidate the code
@@ -183,6 +186,7 @@ void page_set_flags(unsigned long start, unsigned long end, int flags)
         }
         p->flags = flags;
     }
+    spin_unlock(&tb_lock);
 }
 
 void cpu_x86_tblocks_init(void)