[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/3] make check infrastructure for xen/ directory



Signed-off-by: Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>

----- Forwarded message from Rusty Russell <rusty@xxxxxxxxxxxxxxx> -----

To: Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>
From: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Subject: [PATCH 2/3] make check infrastructure for xen/ directory
Date: Fri, 09 Dec 2005 16:46:27 +1100

This introduces some fake xen core components and headers, so we can
test each C source file in xen/common in isolation.  The behaviour of
the functions is controlled by the test code, and it also contains extra
sanity checks (eg. memory leaks, locks held, irqs disabled).

Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/test/fake-include.h 
xen-unstable.hg-check/xen/test/fake-include.h
--- xen-unstable.hg-mainline/xen/test/fake-include.h    1970-01-01 
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/test/fake-include.h       2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,237 @@
+#ifndef _XEN_TEST_FAKE_INCLUDE
+#define _XEN_TEST_FAKE_INCLUDE
+
+#if (ULONG_MAX >> (CHAR_BIT*4)) == 0
+#define BITS_PER_LONG (CHAR_BIT*4)
+#elif (ULONG_MAX >> (CHAR_BIT*8)) == 0
+#define BITS_PER_LONG (CHAR_BIT*8)
+#else
+#error Cannot determine BITS_PER_LONG
+#endif
+
+#define BITS_TO_LONGS(bits) \
+    (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define DECLARE_BITMAP(name,bits) \
+    unsigned long name[BITS_TO_LONGS(bits)]
+
+/* FIXME: Get rid of EXPORT_SYMBOL */
+#define EXPORT_SYMBOL(sym)
+
+#define __user
+
+#define BUG_ON(x) assert(!(x))
+#define ASSERT(x) assert(x)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
+#define MAX_EVTCHNS        NR_EVENT_CHANNELS
+#define EVTCHNS_PER_BUCKET 128
+#define NR_EVTCHN_BUCKETS  (MAX_EVTCHNS / EVTCHNS_PER_BUCKET)
+
+#include "../include/xen/list.h"
+#include "../include/public/xen.h"
+
+unsigned int hweight32(unsigned int w);
+
+/* Linux-style typedefs */
+typedef int64_t s64;
+typedef uint64_t u64;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int8_t s8;
+typedef uint8_t u8;
+
+typedef int64_t s_time_t;
+
+typedef struct {
+       struct list_head _list;
+       const char *_name;
+       int _l;
+} spinlock_t;
+typedef struct {
+       struct list_head _list;
+       const char *_name;
+       unsigned int _w; unsigned int _r;
+} rwlock_t;
+
+#define __cacheline_aligned
+#define unlikely(x) (x)
+#define xmalloc(type)  ((type *)fake_xmalloc(sizeof(type), __FILE__, __LINE__))
+#define xmalloc_array(type, num) ((type *)fake_xmalloc(sizeof(type) * (num), 
__FILE__, __LINE__))
+void *fake_xmalloc(size_t size, const char *file, int line);
+void fake_xfree(void *p);
+#define xfree(p) fake_xfree(p)
+
+#define for_each_online_cpu(i) for ((i) = 0; (i) < NR_CPUS; (i)++)
+
+extern void printk(const char *format, ...)
+__attribute__ ((format (printf, 1, 2)));
+#define printf printk
+
+/* FIXME: Not used in Xen */
+#define __init
+
+#define NR_CPUS 2
+#define NR_PIRQS 256
+
+s_time_t NOW(void);
+
+void cpu_raise_softirq(unsigned int cpu, unsigned int nr);
+int smp_processor_id(void);
+
+typedef void keyhandler_t(unsigned char key);
+void register_keyhandler(unsigned char key, keyhandler_t *handler,
+                        char *desc);
+
+#define __stringify_1(x)       #x
+#define __stringify(x)         __stringify_1(x)
+
+void spin_lock_init(spinlock_t *lock);
+void _spin_lock_irq(spinlock_t *lock, const char *name);
+void spin_unlock_irq(spinlock_t *lock);
+#define spin_lock_irqsave(lock, flags) \
+       _spin_lock_irqsave((lock), &(flags), __stringify(lock))
+void _spin_lock_irqsave(spinlock_t *lock, unsigned long *flags,
+                       const char *name);
+void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
+void _spin_lock(spinlock_t *lock, const char *name);
+void spin_unlock(spinlock_t *lock);
+void _spin_lock_recursive(spinlock_t *lock, const char *name);
+void spin_unlock_recursive(spinlock_t *lock);
+#define spin_lock(lock) _spin_lock(lock, __stringify(lock))
+#define spin_lock_recursive(lock) \
+       _spin_lock_recursive(lock, __stringify(lock))
+#define spin_lock_irq(lock) _spin_lock_irq((lock), __stringify(lock))
+#define SPIN_LOCK_UNLOCKED ((spinlock_t){ ._l = 88 })
+
+void _write_lock(rwlock_t *lock, const char *name);
+void _read_lock(rwlock_t *lock, const char *name);
+#define write_lock(lock) _write_lock((lock), __stringify(lock))
+#define read_lock(lock) _read_lock((lock), __stringify(lock))
+void write_unlock(rwlock_t *lock);
+void read_unlock(rwlock_t *lock);
+
+#define copy_from_user(to, from, n) \
+       fake_copy_from_user((to), (from), (n), __FILE__, __LINE__)
+unsigned long fake_copy_from_user(void *to, const void __user *from,
+                                 unsigned n, const char *file, int line);
+#define copy_to_user(to, from, n) \
+       fake_copy_to_user((to), (from), (n), __FILE__, __LINE__)
+unsigned long fake_copy_to_user(void __user *to, const void *from,
+                               unsigned n, const char *file, int line);
+
+#define prefetch(x) (0)
+
+#define __initcall(x) 
+
+typedef unsigned long cpumask_t;
+#define CPUMAP_RUNANYWHERE 0xFFFFFFFF
+
+typedef struct { int _val; } atomic_t;
+void atomic_set(atomic_t *a, int i);
+#define _atomic_set(a, i) atomic_set(&(a), (i))
+int atomic_read(atomic_t *a);
+#define _atomic_read(a) atomic_read(&(a))
+void atomic_inc(atomic_t *v);
+int atomic_dec_and_test(atomic_t *a);
+atomic_t atomic_compareandswap(atomic_t old, atomic_t new, atomic_t *v);
+unsigned int __cmpxchg(volatile void *ptr, 
+                      unsigned long old, 
+                      unsigned long new, 
+                      int size);
+
+void set_bit(int bit, void *addr);
+void clear_bit(int bit, void *addr);
+int test_bit(int bit, void *addr);
+int test_and_set_bit(int bit, void *addr);
+int test_and_clear_bit(int bit, void *addr);
+
+struct domain {
+       domid_t          domain_id;
+       spinlock_t       big_lock;
+       shared_info_t   *shared_info;
+       atomic_t         refcnt;
+       void            *ssid;
+       unsigned long    domain_flags;
+       int              shutdown_code;
+       struct list_head page_list;
+       struct list_head xenpage_list;
+       spinlock_t       page_alloc_lock;
+       struct domain   *next_in_list;
+       struct domain   *next_in_hashbucket;
+       struct vcpu     *vcpu[MAX_VIRT_CPUS];
+       cpumask_t        cpumask;
+       unsigned long    vm_assist;
+       struct evtchn   *evtchn[NR_EVTCHN_BUCKETS];
+       spinlock_t       evtchn_lock;
+       u16              pirq_to_evtchn[NR_PIRQS];
+       unsigned int     tot_pages;
+       unsigned int     max_pages;
+       xen_domain_handle_t handle;
+       u32              pirq_mask[NR_PIRQS/32];
+};
+
+struct vcpu {
+       int              vcpu_id;
+       int              processor;
+       struct domain   *domain;
+       struct vcpu     *next_in_list;
+       atomic_t         pausecnt;
+       unsigned long    vcpu_flags;
+       u16              virq_to_evtchn[NR_VIRQS];
+       s_time_t         cpu_time;
+       cpumap_t         cpumap;
+};
+
+struct cpu_info {
+    struct cpu_user_regs guest_cpu_user_regs;
+    unsigned int         processor_id;
+    struct vcpu         *current_ed;
+};
+
+/* evntchn state values */
+#define ECS_FREE         0
+#define ECS_RESERVED     1
+#define ECS_UNBOUND      2
+#define ECS_INTERDOMAIN  3
+#define ECS_PIRQ         4
+#define ECS_VIRQ         5
+#define ECS_IPI          6
+
+struct evtchn
+{
+    u16 state;
+    u16 notify_vcpu_id;
+    union {
+        struct {
+            domid_t remote_domid;
+        } unbound;
+        struct {
+            u16            remote_port;
+            struct domain *remote_dom;
+        } interdomain;
+        u16 pirq;
+        u16 virq;
+    } u;
+};
+
+extern struct vcpu *current;
+void domain_destruct(struct domain *d);
+void put_domain(struct domain *d);
+int get_domain(struct domain *d);
+int IS_PRIV(struct domain *d);
+
+struct domain *find_domain_by_id(domid_t dom);
+
+void put_domain(struct domain *d);
+
+#define IDLE_DOMAIN_ID   (0x7FFFU)
+#define is_idle_task(_d) (test_bit(_DOMF_idle_domain, &(_d)->domain_flags))
+
+#define RW_LOCK_UNLOCKED ((rwlock_t) { ._r = 0, ._w = 0 })
+#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+
+#define always_inline
+#endif /* _XEN_TEST_FAKE_INCLUDE */
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/test/fake-support.h 
xen-unstable.hg-check/xen/test/fake-support.h
--- xen-unstable.hg-mainline/xen/test/fake-support.h    1970-01-01 
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/test/fake-support.h       2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,81 @@
+/* Routines for tests to manipulate the results of the fake xen functions */
+#ifndef _FAKE_SUPPORT_H
+#define _FAKE_SUPPORT_H
+
+#include "fake-include.h"
+
+/* Use these in tests to create __user pointers. */
+void __user *fake_to_user(const void *p);
+void *fake_from_user(const void __user *p);
+
+/* Use this to make sure all memory has been initialized (under
+ * valgrind).  Ignore return val. */
+int fake_check_memory(void *mem, unsigned len);
+
+/* Locks held and irqs blocked. */
+extern unsigned int fake_lock_count;
+extern unsigned int fake_irq_state;
+
+/* cpu_raise_softirq */
+extern unsigned int fake_cpu_raise_softirq_in_cpu;
+extern unsigned int fake_cpu_raise_softirq_in_nr;
+
+/* register_keyhandler */
+extern unsigned char fake_register_keyhandler_in_key;
+extern keyhandler_t *fake_register_keyhandler_in_handler;
+extern char *fake_register_keyhandler_in_desc;
+
+/* NOW */
+extern s_time_t fake_NOW_out;
+
+/* get_domain */
+extern struct domain *fake_get_domain_in_d;
+extern int fake_get_domain_out;
+
+/* IS_PRIV */
+extern struct domain *_fake_IS_PRIV_in_d;
+extern int fake_IS_PRIV_out;
+
+/* xmalloc */
+extern int fake_xmalloc_out_FAIL;
+/* Adjust this if you know how many bytes will be allocated/freed */
+extern unsigned int fake_xmalloc_expected;
+/* Use these flags to indicate that something will be allocated/freed */
+extern int fake_expect_xmalloc, fake_expect_xfree;
+
+/* Sometimes the lock is not in scope, so we use name. */
+extern void fake_must_have_spinlock(const char *);
+extern void fake_must_have_readlock(const char *);
+extern void fake_must_have_writelock(const char *);
+
+/* xfree */
+extern void *fake_xfree_in_ptr;
+
+/* find_domain_by_id */
+extern struct domain *fake_find_domain_out;
+
+/* Test suite command line processor */
+extern void parse_test_args(int argc, char *argv[]);
+
+/* Dynamic suppression registration */
+extern void register_suppression(const char *file, int line);
+
+/* Checks no locks held, no irqs disabled, no memory leaks */
+extern void fake_check_status(const char *file, int line);
+
+#define test_cond(expr)        \
+do {                                                           \
+       int _x = (expr);                                        \
+       fake_check_status(__FILE__, __LINE__);                  \
+       if (!(_x))                                              \
+               test_cond_fail(#expr, __FILE__, __LINE__,       \
+                               __PRETTY_FUNCTION__);           \
+} while (0)
+
+
+extern void __attribute__((noreturn)) test_cond_fail(const char *expression, 
+                                                     const char *file,
+                                                    int line, 
+                                                    const char *function);
+
+#endif /* _FAKE_SUPPORT_H */
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/test/fake.c xen-unstable.hg-check/xen/test/fake.c
--- xen-unstable.hg-mainline/xen/test/fake.c    1970-01-01 10:00:00.000000000 
+1000
+++ xen-unstable.hg-check/xen/test/fake.c       2005-12-09 16:33:19.000000000 
+1100
@@ -0,0 +1,671 @@
+/*  Generic routines which most things in the Xen core expect.
+    Copyright (C) 2005 Rusty Russell IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "fake-support.h"
+
+/* All these functions can be overridden by individual tests. */
+#define __override __attribute__((weak))
+
+struct suppression {
+       struct list_head list;
+       int  line;
+       char *file;
+};
+
+enum test_is {ON=0, OFF=1};
+
+enum option_bits {
+       XMALLOC_FAIL=0,
+       USERCOPY_FAIL=1,
+};
+
+struct option {
+       enum option_bits bit;
+       char *name;
+};
+
+static struct option options[] = { 
+       { .bit = XMALLOC_FAIL,  .name = "xmalloc"  },
+       { .bit = USERCOPY_FAIL, .name = "usercopy" },
+};
+
+static char *arg_prefixes[] = {
+       "--fail-tests=", 
+       "--fail-", 
+       "--nofail-tests=", 
+       "--nofail-",
+};
+
+static char *sep = ",";
+static char *negate = "--no";
+
+static unsigned long active_tests = ULONG_MAX;
+
+struct failure {
+       struct list_head list;
+       const char *file;
+       int line;
+};
+static LIST_HEAD(failures);
+static LIST_HEAD(suppressions);
+
+void register_suppression(const char *file, int line)
+{
+       struct suppression *s;
+
+       s = malloc(sizeof(*s));
+       s->file = file;
+       s->line = line;
+       list_add_tail(&s->list, &suppressions);
+}
+
+static void print_failures(const char *file, int line)
+{
+       struct failure *i;
+
+       fprintf(stderr, "--failures=");
+       list_for_each_entry(i, &failures, list)
+               fprintf(stderr, "%s:%i,", i->file, i->line);
+       fprintf(stderr, "%s:%i\n", file, line);
+}
+
+static int should_i_fail(const char *file, int line, int option_bit)
+{
+       int status;
+       pid_t pid;
+       struct failure *f;
+       struct suppression *s;
+
+       if (!(active_tests & (1<<option_bit)))
+               return 0;
+
+       list_for_each_entry(s, &suppressions, list) {
+               if (s->line == line && strcmp(s->file, file) == 0) {
+                       return 0;
+               }
+       }
+
+       pid = fork();
+       if (pid == 0) {
+               f = malloc(sizeof(*f));
+               f->file = file;
+               f->line = line;
+               list_add_tail(&f->list, &failures);
+               return 1;
+       }
+
+       if (pid == -1) {
+               fprintf(stderr, "Failed to fork() child: %s\n", 
+                       strerror(errno));
+               exit(1);
+       }
+
+       waitpid(pid, &status, 0);
+       if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
+               /* 7 means child already printed error msg. */
+               if (!WIFEXITED(status) || WEXITSTATUS(status) != 7) {
+                       fprintf(stderr, "Child %d %s %i\n", (int)pid,
+                               WIFEXITED(status) ? "exited with status"
+                               : "died with signal",
+                               WIFEXITED(status) ? WEXITSTATUS(status)
+                               : WTERMSIG(status));
+                       print_failures(file, line);
+               }
+               exit(7);
+       }
+       return 0;
+}
+
+unsigned int __override hweight32(unsigned int w)
+{
+        unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+
+        res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+        res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+        res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+        return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+void __override atomic_set(atomic_t *a, int i)
+{
+       a->_val = ~i;
+}
+
+int __override atomic_dec_and_test(atomic_t *a)
+{
+       assert(~(a->_val) != 0);
+       a->_val = ~(~a->_val - 1);
+       return (~a->_val == 0);
+}
+
+void __override atomic_inc(atomic_t *a)
+{
+       a->_val = ~(~a->_val + 1);
+}
+
+int __override atomic_read(atomic_t *a)
+{
+       return ~a->_val;
+}
+
+unsigned int __override __cmpxchg(volatile void *ptr, 
+                                 unsigned long old, 
+                                 unsigned long new, 
+                                 int size)
+{
+       unsigned long prev;
+
+       switch (size) {
+       case 1:
+               prev = *(u8 *)ptr;
+               if (prev == old)
+                       *(u8 *)ptr = new;
+               break;
+       case 2:
+               prev = *(u16 *)ptr;
+               if (prev == old)
+                       *(u16 *)ptr = new;
+               break;
+       case 4:
+               prev = *(u32 *)ptr;
+               if (prev == old)
+                       *(u32 *)ptr = new;
+               break;
+#ifdef __x86_64__
+       case 8:
+               prev = *(u64 *)ptr;
+               if (prev == old)
+                       *(u64 *)ptr = new;
+               break;
+#endif
+       default:
+               assert(0);
+       }
+       return prev;
+}
+
+atomic_t __override atomic_compareandswap(atomic_t old, atomic_t new, atomic_t 
*v)
+{
+       atomic_t rc;
+       rc._val = __cmpxchg(&v->_val, old._val, new._val, sizeof(*v));
+       return rc;
+}
+
+void __override printk(const char *format, ...)
+{
+       abort();
+}
+
+unsigned int fake_cpu_raise_softirq_in_cpu;
+unsigned int fake_cpu_raise_softirq_in_nr;
+void __override cpu_raise_softirq(unsigned int cpu, unsigned int nr)
+{
+       fake_cpu_raise_softirq_in_cpu = cpu;
+       fake_cpu_raise_softirq_in_nr = nr;
+}
+
+unsigned char fake_register_keyhandler_in_key;
+keyhandler_t *fake_register_keyhandler_in_handler;
+char *fake_register_keyhandler_in_desc;
+void __override register_keyhandler(unsigned char key, keyhandler_t *handler,
+                                   char *desc)
+{
+       fake_register_keyhandler_in_key = key;
+       fake_register_keyhandler_in_handler = handler;
+       fake_register_keyhandler_in_desc = desc;
+}
+
+unsigned int fake_lock_count = 0;
+unsigned int fake_irq_state = 0;
+void __override spin_lock_init(spinlock_t *lock)
+{
+       *lock = SPIN_LOCK_UNLOCKED;
+}
+
+static LIST_HEAD(spinlocks);
+void _spin_lock(spinlock_t *lock, const char *name)
+{
+       assert(lock->_l == 88);
+       list_add(&lock->_list, &spinlocks);
+       lock->_name = name;
+       lock->_l = 89;
+       fake_lock_count++;
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+       assert(lock->_l == 89);
+       list_del(&lock->_list);
+       *lock = SPIN_LOCK_UNLOCKED;
+       assert(fake_lock_count > 0);
+       fake_lock_count--;
+}
+
+void __override _spin_lock_irqsave(spinlock_t *lock, unsigned long *flags,
+                                  const char *name)
+{
+       _spin_lock(lock, name);
+       *flags = (776 + (long)lock) | fake_irq_state;
+       fake_irq_state = 1;
+}
+
+void __override _spin_lock_irq(spinlock_t *lock, const char *name)
+{
+       _spin_lock(lock, name);
+       assert(fake_irq_state == 0);
+       fake_irq_state = 1;
+}
+
+void __override spin_unlock_irq(spinlock_t *lock)
+{
+       spin_unlock(lock);
+       assert(fake_irq_state == 1);
+       fake_irq_state = 0;
+}
+
+void __override spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+{
+       spin_unlock(lock);
+       assert((flags & ~0x1UL) == 776 + (long)lock);
+       fake_irq_state = (flags & 1);
+}
+
+static LIST_HEAD(rwlocks);
+void __override _write_lock(rwlock_t *lock, const char *name)
+{
+       list_add(&lock->_list, &rwlocks);
+       lock->_name = name;
+       assert(lock->_w == 0);
+       assert(lock->_r == 0);
+       lock->_w = 1;
+}
+
+void __override _read_lock(rwlock_t *lock, const char *name)
+{
+       list_add(&lock->_list, &rwlocks);
+       lock->_name = name;
+       assert(lock->_w == 0);
+       assert(lock->_r == 0);
+       lock->_r = 1;
+}
+
+void __override write_unlock(rwlock_t *lock)
+{
+       list_del(&lock->_list);
+       assert(lock->_w == 1);
+       assert(lock->_r == 0);
+       lock->_w = 0;
+}
+
+void __override read_unlock(rwlock_t *lock)
+{
+       list_del(&lock->_list);
+       assert(lock->_w == 0);
+       assert(lock->_r == 1);
+       lock->_r = 0;
+}
+
+/* FIXME: Recursion isn't actually supported in this test suite */
+void __override _spin_lock_recursive(spinlock_t *lock, const char *name)
+{
+       _spin_lock(lock, name);
+}
+
+void __override spin_unlock_recursive(spinlock_t *lock)
+{
+       spin_unlock(lock);
+}
+
+
+int __override smp_processor_id(void)
+{
+       return 0;
+}
+
+s_time_t fake_NOW_out;
+s_time_t __override NOW(void)
+{
+       return fake_NOW_out;
+}
+
+void __override domain_destruct(struct domain *d)
+{
+       free(d);
+}
+
+struct domain *fake_put_domain_in_d;
+void __override put_domain(struct domain *d)
+{
+       fake_put_domain_in_d = d;
+       if (atomic_dec_and_test(&d->refcnt))
+               domain_destruct(d);
+}
+
+struct domain *fake_get_domain_in_d;
+int fake_get_domain_out = 1;
+int __override get_domain(struct domain *d)
+{
+       fake_get_domain_in_d = d;
+       if (!fake_get_domain_out)
+               return 0;
+       atomic_inc(&d->refcnt);
+       return 1;
+}
+
+struct domain *fake_find_domain_out;
+struct domain *__override find_domain_by_id(domid_t dom)
+{
+       if (!fake_find_domain_out)
+               return NULL;
+
+       atomic_inc(&fake_find_domain_out->refcnt);
+       return fake_find_domain_out;
+}
+
+void __override set_bit(int bit, void *addr)
+{
+       unsigned long *bitmap = (unsigned long *)addr;
+       bitmap[bit/BITS_PER_LONG] |= (1 << (bit%BITS_PER_LONG));
+}
+
+void __override clear_bit(int bit, void *addr)
+{
+       unsigned long *bitmap = (unsigned long *)addr;
+       bitmap[bit/BITS_PER_LONG] &= ~(1 << (bit%BITS_PER_LONG));
+}
+
+int __override test_bit(int bit, void *addr)
+{
+       unsigned long *bitmap = (unsigned long *)addr;
+
+       return bitmap[bit/BITS_PER_LONG] & (1 << (bit%BITS_PER_LONG));
+}
+
+int __override test_and_set_bit(int bit, void *addr)
+{
+       int old = test_bit(bit, addr);
+       set_bit(bit, addr);
+
+       return old;
+}
+
+int __override test_and_clear_bit(int bit, void *addr)
+{
+       int old = test_bit(bit, addr);
+       clear_bit(bit, addr);
+
+       return old;
+}
+
+/* Use these in tests to create __user pointers: we bit-invert them. */
+void __user *__override fake_to_user(const void *p)
+{
+       return (void *)~((unsigned long)p);
+}
+       
+void *__override fake_from_user(const void __user *p)
+{
+       return (void *)~((unsigned long)p);
+}
+
+unsigned long __override fake_copy_from_user(void *to,
+                                            const void __user *from,
+                                            unsigned n,
+                                            const char *file,
+                                            int line)
+{
+       if (should_i_fail(file, line, USERCOPY_FAIL))
+               return 1;
+
+       memcpy(to, fake_from_user(from), n);
+       return 0;
+}
+
+unsigned long __override fake_copy_to_user(void __user *to, const void *from,
+                                          unsigned n,
+                                          const char *file,
+                                          int line)
+{
+       if (should_i_fail(file, line, USERCOPY_FAIL))
+               return 1;
+
+       memcpy(fake_from_user(to), from, n);
+       return 0;
+}
+
+struct fake_xmalloc_hdr
+{
+       const char *file;
+       int line;
+       size_t size;
+};
+
+static int fake_xmalloc_bytes;
+unsigned int fake_xmalloc_expected;
+int fake_expect_xmalloc, fake_expect_xfree;
+void *fake_xmalloc(size_t size, const char *file, int line)
+{
+       struct fake_xmalloc_hdr *h;
+       if (should_i_fail(file, line, XMALLOC_FAIL))
+               return NULL;
+
+       h = malloc(sizeof(*h) + size);
+       h->file = file;
+       h->line = line;
+       h->size = size;
+
+       fake_xmalloc_bytes += size;
+       return h+1;
+}
+
+struct domain *fake_IS_PRIV_in_d;
+/* Assume privilege unless told otherwise */
+int fake_IS_PRIV_out = 1;
+int __override IS_PRIV(struct domain *d)
+{
+       fake_IS_PRIV_in_d = d;
+       return fake_IS_PRIV_out;
+}
+
+void *fake_xfree_in_ptr;
+void fake_xfree(void *ptr)
+{
+       struct fake_xmalloc_hdr *h;
+
+       if (ptr == NULL) 
+               return;
+
+       fake_xfree_in_ptr = ptr;
+
+       h = ((struct fake_xmalloc_hdr *)ptr)-1;
+
+       fake_xmalloc_bytes -= h->size;
+       assert(fake_xmalloc_bytes >= 0);
+
+       free(h);
+}
+
+struct vcpu *current;
+
+/* Use this to check that memory has been fully initialized (valgrind).
+ * We don't use memcheck.h's VALGRIND_CHECK_DEFINED since we don't want to
+ * depend on valgrind.  Ignore return value. */
+int fake_check_memory(void *mem, unsigned len)
+{
+       unsigned int i, sum = 0;
+
+       for (i = 0; i < len; i++) 
+               sum += ((char *)mem)[i];
+
+       /* Valgrind not that bright: as soon as we "use" result it will
+        * complain if uninitialized */
+       if (sum)
+               return 100;
+       return 0;
+}
+
+static void process_test_arg(char *arg, enum test_is state)
+{
+       char *arg_pos;
+
+       arg_pos = strtok(arg, sep);
+       do {
+               int i;
+               unsigned long mask = 0UL;
+               int found = 0;
+
+               if (arg_pos == NULL)
+                       break;
+
+               for(i=0; i<ARRAY_SIZE(options); i++) {
+                       if (strcmp("all", arg_pos) == 0) {
+                               found = 1;
+                               mask = ULONG_MAX;
+                               if (state == OFF) {
+                                       mask = 0UL;
+                               }
+                       } else if (strcmp("none", arg_pos) == 0) {
+                               found = 1;
+                               mask = 0UL;
+                               if (state == OFF) {
+                                       mask = ULONG_MAX;
+                               }
+                       } else if (strcmp(options[i].name, arg_pos) == 0) {
+                               found = 1;
+                               mask = (1<<options[i].bit);
+                       }
+
+                       if (found) {
+                               if (state == ON) {
+                                       active_tests |= mask;
+                               } else {
+                                       active_tests ^= ~mask;
+                               }
+
+                               break;
+                       }
+
+               }
+
+       } while ((arg_pos = strtok(NULL, sep)) != NULL);
+}
+
+void parse_test_args(int argc, char *argv[])
+{
+       int i = 0;
+
+       while (++i < argc) {
+               int j;
+               for(j=0; j<ARRAY_SIZE(arg_prefixes); j++) {
+                       int len = strlen(arg_prefixes[j]);
+
+                       if (strncmp(arg_prefixes[j], argv[i], len) == 0) {
+                               enum test_is state = ON;
+                               if (strstr(arg_prefixes[j], negate) != NULL) {
+                                       state = OFF;
+                               }
+                               process_test_arg(argv[i] +len, state);
+                       }
+               }
+       }
+}
+
+static void __attribute__((noreturn))
+test_fail(const char *file, int line, const char *function,
+         const char *expression)
+{
+       fprintf(stderr, "%s:%d: %s: Fake Assertion `%s' failed.\n",
+                       file, line, function, expression);
+       abort();
+}
+
+/* assert */
+void test_cond_fail(const char *expression, const char *file,
+                    int line, const char *function)
+{
+       /* Failures will... err... cause failure. */
+       if (!list_empty(&failures))
+               exit(0);
+
+       test_fail(file, line, function, expression);
+}
+
+void fake_must_have_spinlock(const char *name)
+{
+       spinlock_t *i;
+       list_for_each_entry(i, &spinlocks, _list)
+               if (strcmp(i->_name, name) == 0)
+                       return;
+       assert(0);
+}
+
+void fake_must_have_readlock(const char *name)
+{
+       rwlock_t *i;
+       list_for_each_entry(i, &rwlocks, _list)
+               if (strcmp(i->_name, name) == 0) {
+                       assert(i->_r && !i->_w);
+                       return;
+               }
+       assert(0);
+}
+
+void fake_must_have_writelock(const char *name)
+{
+       rwlock_t *i;
+       list_for_each_entry(i, &rwlocks, _list)
+               if (strcmp(i->_name, name) == 0) {
+                       assert(i->_w && !i->_r);
+                       return;
+               }
+       assert(0);
+}
+
+/* Checks no locks held, no irqs disabled, no memory leaks */
+void fake_check_status(const char *file, int line)
+{
+       if (fake_expect_xmalloc) {
+               if (fake_xmalloc_bytes <= fake_xmalloc_expected)
+                       test_cond_fail("xmalloc expected", file, line,
+                                      "test_cond");
+               fake_xmalloc_expected = fake_xmalloc_bytes;
+               fake_expect_xmalloc = 0;
+       } else if (fake_expect_xfree) {
+               if (fake_xmalloc_bytes >= fake_xmalloc_expected)
+                       test_cond_fail("xfree expected", file, line,
+                                      "test_cond");
+               fake_xmalloc_expected = fake_xmalloc_bytes;
+               fake_expect_xfree = 0;
+       } else if (fake_xmalloc_bytes != fake_xmalloc_expected)
+               test_fail(file, line, "test_cond", "xmalloc leak");
+       if (fake_lock_count != 0)
+               test_fail(file, line, "test_cond", "spinlock leak");
+       if (fake_irq_state != 0)
+               test_fail(file, line, "test_cond", "irq leak");
+}

-- 
 ccontrol: http://freshmeat.net/projects/ccontrol

----- End forwarded message -----

Yours Tony

   linux.conf.au       http://linux.conf.au/ || http://lca2006.linux.org.au/
   Jan 23-28 2006      The Australian Linux Technical Conference!


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.