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
|