WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: Xen-Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 2/3] make check infrastructure for xen/ directory
From: Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>
Date: Fri, 9 Dec 2005 16:55:46 +1100
Delivery-date: Fri, 09 Dec 2005 05:56:49 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: Xen-Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.9i
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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 2/3] make check infrastructure for xen/ directory, Tony Breeds <=