2007-11-11 03:51:17 +01:00
|
|
|
/* Common header file that is included by all of qemu. */
|
|
|
|
#ifndef QEMU_COMMON_H
|
|
|
|
#define QEMU_COMMON_H
|
|
|
|
|
2011-07-11 19:24:44 +02:00
|
|
|
#include "compiler.h"
|
2010-01-15 12:56:41 +01:00
|
|
|
#include "config-host.h"
|
|
|
|
|
2011-07-28 12:10:28 +02:00
|
|
|
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
|
|
|
|
#define WORDS_ALIGNED
|
|
|
|
#endif
|
|
|
|
|
2011-03-27 11:04:57 +02:00
|
|
|
#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
|
2010-02-18 21:25:23 +01:00
|
|
|
|
2010-03-29 21:24:00 +02:00
|
|
|
typedef struct QEMUTimer QEMUTimer;
|
|
|
|
typedef struct QEMUFile QEMUFile;
|
2010-06-19 09:47:42 +02:00
|
|
|
typedef struct DeviceState DeviceState;
|
2010-03-29 21:24:00 +02:00
|
|
|
|
2011-03-02 08:56:09 +01:00
|
|
|
struct Monitor;
|
|
|
|
typedef struct Monitor Monitor;
|
|
|
|
|
2007-11-11 03:51:17 +01:00
|
|
|
/* we put basic includes here to avoid repeating them in device drivers */
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
2010-06-13 20:00:50 +02:00
|
|
|
#include <stdbool.h>
|
2007-11-11 03:51:17 +01:00
|
|
|
#include <string.h>
|
2008-11-12 18:18:41 +01:00
|
|
|
#include <strings.h>
|
2007-11-11 03:51:17 +01:00
|
|
|
#include <inttypes.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
2011-03-06 14:23:13 +01:00
|
|
|
#include <sys/time.h>
|
2009-05-13 21:51:49 +02:00
|
|
|
#include <assert.h>
|
2011-06-02 04:21:30 +02:00
|
|
|
#include <signal.h>
|
2011-08-21 05:18:37 +02:00
|
|
|
#include <glib.h>
|
2007-11-11 03:51:17 +01:00
|
|
|
|
2011-03-27 11:04:57 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include "qemu-os-win32.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_POSIX
|
|
|
|
#include "qemu-os-posix.h"
|
|
|
|
#endif
|
|
|
|
|
2007-11-11 03:51:17 +01:00
|
|
|
#ifndef O_LARGEFILE
|
|
|
|
#define O_LARGEFILE 0
|
|
|
|
#endif
|
|
|
|
#ifndef O_BINARY
|
|
|
|
#define O_BINARY 0
|
|
|
|
#endif
|
2009-07-27 16:12:57 +02:00
|
|
|
#ifndef MAP_ANONYMOUS
|
|
|
|
#define MAP_ANONYMOUS MAP_ANON
|
|
|
|
#endif
|
2007-11-11 03:51:17 +01:00
|
|
|
#ifndef ENOMEDIUM
|
|
|
|
#define ENOMEDIUM ENODEV
|
|
|
|
#endif
|
2009-07-28 22:48:31 +02:00
|
|
|
#if !defined(ENOTSUP)
|
2009-07-27 16:13:22 +02:00
|
|
|
#define ENOTSUP 4096
|
|
|
|
#endif
|
2010-10-07 11:50:45 +02:00
|
|
|
#ifndef TIME_MAX
|
|
|
|
#define TIME_MAX LONG_MAX
|
|
|
|
#endif
|
2007-11-11 03:51:17 +01:00
|
|
|
|
2009-07-27 16:12:59 +02:00
|
|
|
#ifndef CONFIG_IOVEC
|
|
|
|
#define CONFIG_IOVEC
|
2008-12-05 21:05:26 +01:00
|
|
|
struct iovec {
|
|
|
|
void *iov_base;
|
|
|
|
size_t iov_len;
|
|
|
|
};
|
2010-01-26 14:49:08 +01:00
|
|
|
/*
|
|
|
|
* Use the same value as Linux for now.
|
|
|
|
*/
|
|
|
|
#define IOV_MAX 1024
|
2008-12-06 20:44:56 +01:00
|
|
|
#else
|
|
|
|
#include <sys/uio.h>
|
2008-12-05 21:05:26 +01:00
|
|
|
#endif
|
|
|
|
|
2010-10-22 23:03:30 +02:00
|
|
|
typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
|
|
|
|
GCC_FMT_ATTR(2, 3);
|
|
|
|
|
2007-11-11 03:51:17 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
#define fsync _commit
|
|
|
|
#define lseek _lseeki64
|
2011-01-23 17:21:20 +01:00
|
|
|
int qemu_ftruncate64(int, int64_t);
|
2007-11-11 03:51:17 +01:00
|
|
|
#define ftruncate qemu_ftruncate64
|
|
|
|
|
|
|
|
static inline char *realpath(const char *path, char *resolved_path)
|
|
|
|
{
|
|
|
|
_fullpath(resolved_path, path, _MAX_PATH);
|
|
|
|
return resolved_path;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-09-12 13:57:37 +02:00
|
|
|
/* icount */
|
|
|
|
void configure_icount(const char *option);
|
|
|
|
extern int use_icount;
|
|
|
|
|
2007-11-11 03:51:17 +01:00
|
|
|
/* FIXME: Remove NEED_CPU_H. */
|
|
|
|
#ifndef NEED_CPU_H
|
|
|
|
|
|
|
|
#include "osdep.h"
|
|
|
|
#include "bswap.h"
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#include "cpu.h"
|
|
|
|
|
|
|
|
#endif /* !defined(NEED_CPU_H) */
|
|
|
|
|
2011-05-29 19:42:51 +02:00
|
|
|
/* main function, renamed */
|
|
|
|
#if defined(CONFIG_COCOA)
|
|
|
|
int qemu_main(int argc, char **argv, char **envp);
|
|
|
|
#endif
|
|
|
|
|
2008-02-17 12:42:19 +01:00
|
|
|
void qemu_get_timedate(struct tm *tm, int offset);
|
|
|
|
int qemu_timedate_diff(struct tm *tm);
|
|
|
|
|
2007-11-11 03:51:17 +01:00
|
|
|
/* cutils.c */
|
|
|
|
void pstrcpy(char *buf, int buf_size, const char *str);
|
|
|
|
char *pstrcat(char *buf, int buf_size, const char *s);
|
|
|
|
int strstart(const char *str, const char *val, const char **ptr);
|
|
|
|
int stristart(const char *str, const char *val, const char **ptr);
|
2009-07-01 20:24:44 +02:00
|
|
|
int qemu_strnlen(const char *s, int max_len);
|
2007-11-11 03:51:17 +01:00
|
|
|
time_t mktimegm(struct tm *tm);
|
2008-12-11 20:37:54 +01:00
|
|
|
int qemu_fls(int i);
|
2009-09-04 19:01:32 +02:00
|
|
|
int qemu_fdatasync(int fd);
|
2010-03-10 11:38:55 +01:00
|
|
|
int fcntl_setfl(int fd, int flag);
|
2010-12-09 14:17:24 +01:00
|
|
|
|
2011-01-26 11:54:58 +01:00
|
|
|
/*
|
|
|
|
* strtosz() suffixes used to specify the default treatment of an
|
|
|
|
* argument passed to strtosz() without an explicit suffix.
|
|
|
|
* These should be defined using upper case characters in the range
|
|
|
|
* A-Z, as strtosz() will use qemu_toupper() on the given argument
|
|
|
|
* prior to comparison.
|
|
|
|
*/
|
2010-12-09 14:17:24 +01:00
|
|
|
#define STRTOSZ_DEFSUFFIX_TB 'T'
|
|
|
|
#define STRTOSZ_DEFSUFFIX_GB 'G'
|
|
|
|
#define STRTOSZ_DEFSUFFIX_MB 'M'
|
|
|
|
#define STRTOSZ_DEFSUFFIX_KB 'K'
|
|
|
|
#define STRTOSZ_DEFSUFFIX_B 'B'
|
2011-01-05 11:41:02 +01:00
|
|
|
int64_t strtosz(const char *nptr, char **end);
|
|
|
|
int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix);
|
2011-07-07 16:13:11 +02:00
|
|
|
int64_t strtosz_suffix_unit(const char *nptr, char **end,
|
|
|
|
const char default_suffix, int64_t unit);
|
2007-11-11 03:51:17 +01:00
|
|
|
|
2009-08-15 09:51:59 +02:00
|
|
|
/* path.c */
|
|
|
|
void init_paths(const char *prefix);
|
|
|
|
const char *path(const char *pathname);
|
|
|
|
|
2008-11-16 14:53:32 +01:00
|
|
|
#define qemu_isalnum(c) isalnum((unsigned char)(c))
|
|
|
|
#define qemu_isalpha(c) isalpha((unsigned char)(c))
|
|
|
|
#define qemu_iscntrl(c) iscntrl((unsigned char)(c))
|
|
|
|
#define qemu_isdigit(c) isdigit((unsigned char)(c))
|
|
|
|
#define qemu_isgraph(c) isgraph((unsigned char)(c))
|
|
|
|
#define qemu_islower(c) islower((unsigned char)(c))
|
|
|
|
#define qemu_isprint(c) isprint((unsigned char)(c))
|
|
|
|
#define qemu_ispunct(c) ispunct((unsigned char)(c))
|
|
|
|
#define qemu_isspace(c) isspace((unsigned char)(c))
|
|
|
|
#define qemu_isupper(c) isupper((unsigned char)(c))
|
|
|
|
#define qemu_isxdigit(c) isxdigit((unsigned char)(c))
|
|
|
|
#define qemu_tolower(c) tolower((unsigned char)(c))
|
|
|
|
#define qemu_toupper(c) toupper((unsigned char)(c))
|
|
|
|
#define qemu_isascii(c) isascii((unsigned char)(c))
|
|
|
|
#define qemu_toascii(c) toascii((unsigned char)(c))
|
|
|
|
|
2010-10-26 10:39:26 +02:00
|
|
|
void *qemu_oom_check(void *ptr);
|
2008-04-11 23:35:42 +02:00
|
|
|
|
2009-12-02 12:24:42 +01:00
|
|
|
int qemu_open(const char *name, int flags, ...);
|
2010-01-20 00:56:09 +01:00
|
|
|
ssize_t qemu_write_full(int fd, const void *buf, size_t count)
|
|
|
|
QEMU_WARN_UNUSED_RESULT;
|
2009-12-02 12:24:42 +01:00
|
|
|
void qemu_set_cloexec(int fd);
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
2010-02-11 00:23:46 +01:00
|
|
|
int qemu_eventfd(int pipefd[2]);
|
2009-12-02 12:24:42 +01:00
|
|
|
int qemu_pipe(int pipefd[2]);
|
|
|
|
#endif
|
|
|
|
|
2011-07-23 22:04:29 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags)
|
|
|
|
#else
|
|
|
|
#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags)
|
|
|
|
#endif
|
|
|
|
|
2007-11-17 18:14:51 +01:00
|
|
|
/* Error handling. */
|
|
|
|
|
2010-09-23 21:28:03 +02:00
|
|
|
void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
2007-11-17 18:14:51 +01:00
|
|
|
|
|
|
|
struct ParallelIOArg {
|
|
|
|
void *buffer;
|
|
|
|
int count;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size);
|
|
|
|
|
|
|
|
/* A load of opaque types so that device init declarations don't have to
|
|
|
|
pull in all the real definitions. */
|
|
|
|
typedef struct NICInfo NICInfo;
|
2008-09-29 01:19:47 +02:00
|
|
|
typedef struct HCIInfo HCIInfo;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct AudioState AudioState;
|
|
|
|
typedef struct BlockDriverState BlockDriverState;
|
2010-08-24 17:22:24 +02:00
|
|
|
typedef struct DriveInfo DriveInfo;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct DisplayState DisplayState;
|
2009-01-15 23:14:11 +01:00
|
|
|
typedef struct DisplayChangeListener DisplayChangeListener;
|
|
|
|
typedef struct DisplaySurface DisplaySurface;
|
2009-03-13 16:02:13 +01:00
|
|
|
typedef struct DisplayAllocator DisplayAllocator;
|
2009-01-15 23:14:11 +01:00
|
|
|
typedef struct PixelFormat PixelFormat;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct TextConsole TextConsole;
|
2008-07-01 18:24:38 +02:00
|
|
|
typedef TextConsole QEMUConsole;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct CharDriverState CharDriverState;
|
2009-10-21 15:25:22 +02:00
|
|
|
typedef struct MACAddr MACAddr;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct VLANState VLANState;
|
2009-10-08 20:58:31 +02:00
|
|
|
typedef struct VLANClientState VLANClientState;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct i2c_bus i2c_bus;
|
|
|
|
typedef struct i2c_slave i2c_slave;
|
|
|
|
typedef struct SMBusDevice SMBusDevice;
|
2009-11-12 06:58:41 +01:00
|
|
|
typedef struct PCIHostState PCIHostState;
|
|
|
|
typedef struct PCIExpressHost PCIExpressHost;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct PCIBus PCIBus;
|
|
|
|
typedef struct PCIDevice PCIDevice;
|
2010-10-19 11:06:34 +02:00
|
|
|
typedef struct PCIExpressDevice PCIExpressDevice;
|
2010-07-13 06:01:42 +02:00
|
|
|
typedef struct PCIBridge PCIBridge;
|
2010-11-16 09:26:09 +01:00
|
|
|
typedef struct PCIEAERMsg PCIEAERMsg;
|
|
|
|
typedef struct PCIEAERLog PCIEAERLog;
|
|
|
|
typedef struct PCIEAERErr PCIEAERErr;
|
2010-10-20 10:18:52 +02:00
|
|
|
typedef struct PCIEPort PCIEPort;
|
|
|
|
typedef struct PCIESlot PCIESlot;
|
2007-11-17 18:14:51 +01:00
|
|
|
typedef struct SerialState SerialState;
|
|
|
|
typedef struct IRQState *qemu_irq;
|
2009-05-10 02:44:56 +02:00
|
|
|
typedef struct PCMCIACardState PCMCIACardState;
|
|
|
|
typedef struct MouseTransformInfo MouseTransformInfo;
|
|
|
|
typedef struct uWireSlave uWireSlave;
|
|
|
|
typedef struct I2SCodec I2SCodec;
|
2009-05-14 23:35:09 +02:00
|
|
|
typedef struct SSIBus SSIBus;
|
2010-03-17 12:07:58 +01:00
|
|
|
typedef struct EventNotifier EventNotifier;
|
2010-03-17 12:08:10 +01:00
|
|
|
typedef struct VirtIODevice VirtIODevice;
|
2011-07-12 13:36:23 +02:00
|
|
|
typedef struct QEMUSGList QEMUSGList;
|
2007-11-17 18:14:51 +01:00
|
|
|
|
2010-02-10 20:25:42 +01:00
|
|
|
typedef uint64_t pcibus_t;
|
|
|
|
|
2011-08-02 16:10:21 +02:00
|
|
|
void tcg_exec_init(unsigned long tb_size);
|
|
|
|
bool tcg_enabled(void);
|
|
|
|
|
|
|
|
void cpu_exec_init_all(void);
|
2010-03-29 21:23:48 +02:00
|
|
|
|
2008-06-30 18:31:04 +02:00
|
|
|
/* CPU save/load. */
|
|
|
|
void cpu_save(QEMUFile *f, void *opaque);
|
|
|
|
int cpu_load(QEMUFile *f, void *opaque, int version_id);
|
|
|
|
|
2009-04-24 20:03:45 +02:00
|
|
|
/* Unblock cpu */
|
|
|
|
void qemu_cpu_kick(void *env);
|
2011-02-01 22:15:59 +01:00
|
|
|
void qemu_cpu_kick_self(void);
|
2011-03-12 17:43:51 +01:00
|
|
|
int qemu_cpu_is_self(void *env);
|
enable vm_clock to "warp" in the iothread+icount case
The previous patch however is not enough, because if the virtual CPU
goes to sleep waiting for a future timer interrupt to wake it up, qemu
deadlocks. The timer interrupt never comes because time is driven by
icount, but the vCPU doesn't run any insns.
You could say that VCPUs should never go to sleep in icount
mode if there is a pending vm_clock timer; rather time should
just warp to the next vm_clock event with no sleep ever taking place.
Even better, you can sleep for some time related to the
time left until the next event, to avoid that the warps are too visible
externally; for example, you could be sending network packets continously
instead of every 100ms.
This is what this patch implements. qemu_clock_warp is called: 1)
whenever a vm_clock timer is adjusted, to ensure the warp_timer is
synchronized; 2) at strategic points in the CPU thread, to make sure
the insn counter is synchronized before the CPU starts running.
In any case, the warp_timer is disabled while the CPU is running,
because the insn counter will then be making progress on its own.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Tested-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2011-04-13 10:03:44 +02:00
|
|
|
bool all_cpu_threads_idle(void);
|
2009-04-24 20:03:45 +02:00
|
|
|
|
2010-05-04 14:45:22 +02:00
|
|
|
/* work queue */
|
|
|
|
struct qemu_work_item {
|
|
|
|
struct qemu_work_item *next;
|
|
|
|
void (*func)(void *data);
|
|
|
|
void *data;
|
|
|
|
int done;
|
|
|
|
};
|
|
|
|
|
2009-04-24 20:03:41 +02:00
|
|
|
#ifdef CONFIG_USER_ONLY
|
|
|
|
#define qemu_init_vcpu(env) do { } while (0)
|
|
|
|
#else
|
|
|
|
void qemu_init_vcpu(void *env);
|
|
|
|
#endif
|
|
|
|
|
2009-01-22 17:59:20 +01:00
|
|
|
typedef struct QEMUIOVector {
|
|
|
|
struct iovec *iov;
|
|
|
|
int niov;
|
|
|
|
int nalloc;
|
2009-01-26 18:17:52 +01:00
|
|
|
size_t size;
|
2009-01-22 17:59:20 +01:00
|
|
|
} QEMUIOVector;
|
|
|
|
|
|
|
|
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint);
|
2009-03-28 18:46:10 +01:00
|
|
|
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov);
|
2009-01-22 17:59:20 +01:00
|
|
|
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len);
|
2010-09-13 18:06:11 +02:00
|
|
|
void qemu_iovec_copy(QEMUIOVector *dst, QEMUIOVector *src, uint64_t skip,
|
|
|
|
size_t size);
|
2009-09-09 17:53:37 +02:00
|
|
|
void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t size);
|
2009-01-22 17:59:20 +01:00
|
|
|
void qemu_iovec_destroy(QEMUIOVector *qiov);
|
2009-02-05 22:23:54 +01:00
|
|
|
void qemu_iovec_reset(QEMUIOVector *qiov);
|
2009-01-22 17:59:20 +01:00
|
|
|
void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf);
|
2009-01-26 18:17:52 +01:00
|
|
|
void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
|
2010-09-13 18:06:11 +02:00
|
|
|
void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
|
2011-02-03 16:12:49 +01:00
|
|
|
void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
|
|
|
|
size_t skip);
|
2009-01-22 17:59:20 +01:00
|
|
|
|
2011-03-30 14:16:25 +02:00
|
|
|
void qemu_progress_init(int enabled, float min_skip);
|
|
|
|
void qemu_progress_end(void);
|
2011-05-09 17:32:20 +02:00
|
|
|
void qemu_progress_print(float delta, int max);
|
2011-03-30 14:16:25 +02:00
|
|
|
|
2011-03-27 11:04:57 +02:00
|
|
|
#define QEMU_FILE_TYPE_BIOS 0
|
|
|
|
#define QEMU_FILE_TYPE_KEYMAP 1
|
|
|
|
char *qemu_find_file(int type, const char *name);
|
|
|
|
|
|
|
|
/* OS specific functions */
|
|
|
|
void os_setup_early_signal_handling(void);
|
|
|
|
char *os_find_datadir(const char *argv0);
|
|
|
|
void os_parse_cmd_args(int index, const char *optarg);
|
|
|
|
void os_pidfile_error(void);
|
|
|
|
|
2009-11-20 01:03:47 +01:00
|
|
|
/* Convert a byte between binary and BCD. */
|
|
|
|
static inline uint8_t to_bcd(uint8_t val)
|
|
|
|
{
|
|
|
|
return ((val / 10) << 4) | (val % 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint8_t from_bcd(uint8_t val)
|
|
|
|
{
|
|
|
|
return ((val >> 4) * 10) + (val & 0x0f);
|
|
|
|
}
|
|
|
|
|
2010-10-29 23:41:01 +02:00
|
|
|
/* compute with 96 bit intermediate result: (a*b)/c */
|
|
|
|
static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
uint64_t ll;
|
|
|
|
struct {
|
|
|
|
#ifdef HOST_WORDS_BIGENDIAN
|
|
|
|
uint32_t high, low;
|
|
|
|
#else
|
|
|
|
uint32_t low, high;
|
|
|
|
#endif
|
|
|
|
} l;
|
|
|
|
} u, res;
|
|
|
|
uint64_t rl, rh;
|
|
|
|
|
|
|
|
u.ll = a;
|
|
|
|
rl = (uint64_t)u.l.low * (uint64_t)b;
|
|
|
|
rh = (uint64_t)u.l.high * (uint64_t)b;
|
|
|
|
rh += (rl >> 32);
|
|
|
|
res.l.high = rh / c;
|
|
|
|
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
|
|
|
|
return res.ll;
|
|
|
|
}
|
|
|
|
|
2009-05-14 20:29:53 +02:00
|
|
|
#include "module.h"
|
|
|
|
|
2007-11-11 03:51:17 +01:00
|
|
|
#endif
|