mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 11:18:52 +03:00
Initial commit. All spl source written up to this point wrapped
in an initial reasonable autoconf style build system. This does not yet build but the configure system does appear to work properly and integrate with the kernel. Hopefully the next commit gets us back to a buildable version we can run the test suite against. git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@1 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
EXTRA_DIST = spl.h splat.h splat-ctl.h
|
||||
EXTRA_DIST += linux-condvar.h linux-kmem.h linux-random.h linux-thread.h
|
||||
EXTRA_DIST += linux-types.h linux-cred.h linux-kstat.h linux-rwlock.h
|
||||
EXTRA_DIST += linux-time.h linux-callb.h linux-generic.h linux-mutex.h
|
||||
EXTRA_DIST += linux-taskq.h linux-timer.h
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef _SYS_LINUX_CALLB_H
|
||||
#define _SYS_LINUX_CALLB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/linux-mutex.h>
|
||||
|
||||
#define DEBUG_CALLB
|
||||
|
||||
#ifndef DEBUG_CALLB
|
||||
#define CALLB_CPR_ASSERT(cp) BUG_ON(!(MUTEX_HELD((cp)->cc_lockp)));
|
||||
#else
|
||||
#define CALLB_CPR_ASSERT(cp)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct callb_cpr {
|
||||
kmutex_t *cc_lockp;
|
||||
} callb_cpr_t;
|
||||
|
||||
#define CALLB_CPR_INIT(cp, lockp, func, name) { \
|
||||
(cp)->cc_lockp = lockp; \
|
||||
}
|
||||
|
||||
#define CALLB_CPR_SAFE_BEGIN(cp) { \
|
||||
CALLB_CPR_ASSERT(cp); \
|
||||
}
|
||||
|
||||
#define CALLB_CPR_SAFE_END(cp, lockp) { \
|
||||
CALLB_CPR_ASSERT(cp); \
|
||||
}
|
||||
|
||||
#define CALLB_CPR_EXIT(cp) { \
|
||||
ASSERT(MUTEX_HELD((cp)->cc_lockp)); \
|
||||
mutex_exit((cp)->cc_lockp); \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_CALLB_H */
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
#ifndef _SYS_LINUX_CONDVAR_H
|
||||
#define _SYS_LINUX_CONDVAR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <linux/wait.h>
|
||||
|
||||
/* The kcondvar_t struct is protected by mutex taken externally before
|
||||
* calling any of the wait/signal funs, and passed into the wait funs.
|
||||
*/
|
||||
#define CV_MAGIC 0x346545f4
|
||||
#define CV_POISON 0x95
|
||||
|
||||
typedef struct {
|
||||
int cv_magic;
|
||||
char *cv_name;
|
||||
wait_queue_head_t cv_event;
|
||||
atomic_t cv_waiters;
|
||||
kmutex_t *cv_mutex; /* only for verification purposes */
|
||||
} kcondvar_t;
|
||||
|
||||
typedef enum { CV_DEFAULT=0, CV_DRIVER } kcv_type_t;
|
||||
|
||||
static __inline__ void
|
||||
cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg)
|
||||
{
|
||||
BUG_ON(cvp == NULL);
|
||||
BUG_ON(type != CV_DEFAULT);
|
||||
BUG_ON(arg != NULL);
|
||||
|
||||
cvp->cv_magic = CV_MAGIC;
|
||||
init_waitqueue_head(&cvp->cv_event);
|
||||
atomic_set(&cvp->cv_waiters, 0);
|
||||
cvp->cv_mutex = NULL;
|
||||
cvp->cv_name = NULL;
|
||||
|
||||
if (name) {
|
||||
cvp->cv_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
|
||||
if (cvp->cv_name)
|
||||
strcpy(cvp->cv_name, name);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
cv_destroy(kcondvar_t *cvp)
|
||||
{
|
||||
BUG_ON(cvp == NULL);
|
||||
BUG_ON(cvp->cv_magic != CV_MAGIC);
|
||||
BUG_ON(atomic_read(&cvp->cv_waiters) != 0);
|
||||
BUG_ON(waitqueue_active(&cvp->cv_event));
|
||||
|
||||
if (cvp->cv_name)
|
||||
kfree(cvp->cv_name);
|
||||
|
||||
memset(cvp, CV_POISON, sizeof(*cvp));
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
cv_wait(kcondvar_t *cvp, kmutex_t *mtx)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
int flag = 1;
|
||||
|
||||
BUG_ON(cvp == NULL || mtx == NULL);
|
||||
BUG_ON(cvp->cv_magic != CV_MAGIC);
|
||||
BUG_ON(!mutex_owned(mtx));
|
||||
|
||||
if (cvp->cv_mutex == NULL)
|
||||
cvp->cv_mutex = mtx;
|
||||
|
||||
/* Ensure the same mutex is used by all callers */
|
||||
BUG_ON(cvp->cv_mutex != mtx);
|
||||
|
||||
for (;;) {
|
||||
prepare_to_wait_exclusive(&cvp->cv_event, &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
/* Must occur after we are added to the list but only once */
|
||||
if (flag) {
|
||||
atomic_inc(&cvp->cv_waiters);
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
/* XXX - The correct thing to do here may be to wake up and
|
||||
* force the caller to handle the signal. Spurious wakeups
|
||||
* should already be safely handled by the caller. */
|
||||
if (signal_pending(current))
|
||||
flush_signals(current);
|
||||
|
||||
/* Mutex should be dropped after prepare_to_wait() this
|
||||
* ensures we're linked in to the waiters list and avoids the
|
||||
* race where 'cvp->cv_waiters > 0' but the list is empty. */
|
||||
mutex_exit(mtx);
|
||||
schedule();
|
||||
mutex_enter(mtx);
|
||||
|
||||
/* XXX - The correct thing to do here may be to wake up and
|
||||
* force the caller to handle the signal. Spurious wakeups
|
||||
* should already be safely handled by the caller. */
|
||||
if (signal_pending(current))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
atomic_dec(&cvp->cv_waiters);
|
||||
finish_wait(&cvp->cv_event, &wait);
|
||||
}
|
||||
|
||||
/* 'expire_time' argument is an absolute wall clock time in jiffies.
|
||||
* Return value is time left (expire_time - now) or -1 if timeout occurred.
|
||||
*/
|
||||
static __inline__ clock_t
|
||||
cv_timedwait(kcondvar_t *cvp, kmutex_t *mtx, clock_t expire_time)
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
clock_t time_left;
|
||||
int flag = 1;
|
||||
|
||||
BUG_ON(cvp == NULL || mtx == NULL);
|
||||
BUG_ON(cvp->cv_magic != CV_MAGIC);
|
||||
BUG_ON(!mutex_owned(mtx));
|
||||
|
||||
if (cvp->cv_mutex == NULL)
|
||||
cvp->cv_mutex = mtx;
|
||||
|
||||
/* XXX - Does not handle jiffie wrap properly */
|
||||
time_left = expire_time - jiffies;
|
||||
if (time_left <= 0)
|
||||
return -1;
|
||||
|
||||
/* Ensure the same mutex is used by all callers */
|
||||
BUG_ON(cvp->cv_mutex != mtx);
|
||||
|
||||
for (;;) {
|
||||
prepare_to_wait_exclusive(&cvp->cv_event, &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
if (flag) {
|
||||
atomic_inc(&cvp->cv_waiters);
|
||||
flag = 0;
|
||||
}
|
||||
|
||||
/* XXX - The correct thing to do here may be to wake up and
|
||||
* force the caller to handle the signal. Spurious wakeups
|
||||
* should already be safely handled by the caller. */
|
||||
if (signal_pending(current))
|
||||
flush_signals(current);
|
||||
|
||||
/* Mutex should be dropped after prepare_to_wait() this
|
||||
* ensures we're linked in to the waiters list and avoids the
|
||||
* race where 'cvp->cv_waiters > 0' but the list is empty. */
|
||||
mutex_exit(mtx);
|
||||
time_left = schedule_timeout(time_left);
|
||||
mutex_enter(mtx);
|
||||
|
||||
/* XXX - The correct thing to do here may be to wake up and
|
||||
* force the caller to handle the signal. Spurious wakeups
|
||||
* should already be safely handled by the caller. */
|
||||
if (signal_pending(current)) {
|
||||
if (time_left > 0)
|
||||
continue;
|
||||
|
||||
flush_signals(current);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
atomic_dec(&cvp->cv_waiters);
|
||||
finish_wait(&cvp->cv_event, &wait);
|
||||
|
||||
return (time_left > 0 ? time_left : -1);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
cv_signal(kcondvar_t *cvp)
|
||||
{
|
||||
BUG_ON(cvp == NULL);
|
||||
BUG_ON(cvp->cv_magic != CV_MAGIC);
|
||||
|
||||
/* All waiters are added with WQ_FLAG_EXCLUSIVE so only one
|
||||
* waiter will be set runable with each call to wake_up().
|
||||
* Additionally wake_up() holds a spin_lock assoicated with
|
||||
* the wait queue to ensure we don't race waking up processes. */
|
||||
if (atomic_read(&cvp->cv_waiters) > 0)
|
||||
wake_up(&cvp->cv_event);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
cv_broadcast(kcondvar_t *cvp)
|
||||
{
|
||||
BUG_ON(cvp == NULL);
|
||||
BUG_ON(cvp->cv_magic != CV_MAGIC);
|
||||
|
||||
/* Wake_up_all() will wake up all waiters even those which
|
||||
* have the WQ_FLAG_EXCLUSIVE flag set. */
|
||||
if (atomic_read(&cvp->cv_waiters) > 0)
|
||||
wake_up_all(&cvp->cv_event);
|
||||
}
|
||||
#endif /* _SYS_LINUX_CONDVAR_H */
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef _SYS_LINUX_CRED_H
|
||||
#define _SYS_LINUX_CRED_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* XXX - Portions commented out because we really just want to have the type
|
||||
* defined and the contents aren't nearly so important at the moment. */
|
||||
typedef struct cred {
|
||||
uint_t cr_ref; /* reference count */
|
||||
uid_t cr_uid; /* effective user id */
|
||||
gid_t cr_gid; /* effective group id */
|
||||
uid_t cr_ruid; /* real user id */
|
||||
gid_t cr_rgid; /* real group id */
|
||||
uid_t cr_suid; /* "saved" user id (from exec) */
|
||||
gid_t cr_sgid; /* "saved" group id (from exec) */
|
||||
uint_t cr_ngroups; /* number of groups returned by */
|
||||
/* crgroups() */
|
||||
#if 0
|
||||
cred_priv_t cr_priv; /* privileges */
|
||||
projid_t cr_projid; /* project */
|
||||
struct zone *cr_zone; /* pointer to per-zone structure */
|
||||
struct ts_label_s *cr_label; /* pointer to the effective label */
|
||||
credsid_t *cr_ksid; /* pointer to SIDs */
|
||||
#endif
|
||||
gid_t cr_groups[1]; /* cr_groups size not fixed */
|
||||
/* audit info is defined dynamically */
|
||||
/* and valid only when audit enabled */
|
||||
/* auditinfo_addr_t cr_auinfo; audit info */
|
||||
} cred_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_CRED_H */
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef _SYS_LINUX_GENERIC_H
|
||||
#define _SYS_LINUX_GENERIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Missing defines.
|
||||
*/
|
||||
#define INT32_MAX INT_MAX
|
||||
#define UINT64_MAX (~0ULL)
|
||||
#define NBBY 8
|
||||
#define ENOTSUP ENOTSUPP
|
||||
#define MAXNAMELEN 256
|
||||
#define MAXPATHLEN PATH_MAX
|
||||
#define __va_list va_list
|
||||
#define _KERNEL 1
|
||||
#define max_ncpus 64
|
||||
|
||||
/* 0..MAX_PRIO-1: Process priority
|
||||
* 0..MAX_RT_PRIO-1: RT priority tasks
|
||||
* MAX_RT_PRIO..MAX_PRIO-1: SCHED_NORMAL tasks
|
||||
*
|
||||
* Treat shim tasks as SCHED_NORMAL tasks
|
||||
*/
|
||||
#define minclsyspri (MAX_RT_PRIO)
|
||||
#define maxclsyspri (MAX_PRIO-1)
|
||||
|
||||
#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20)
|
||||
#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20)
|
||||
|
||||
#define kred NULL
|
||||
|
||||
#define FREAD 1
|
||||
#define FWRITE 2
|
||||
#define FCREAT O_CREAT
|
||||
#define FTRUNC O_TRUNC
|
||||
#define FOFFMAX O_LARGEFILE
|
||||
#define FSYNC O_SYNC
|
||||
#define FDSYNC O_DSYNC
|
||||
#define FRSYNC O_RSYNC
|
||||
#define FEXCL O_EXCL
|
||||
|
||||
#define FNODSYNC 0x10000 /* fsync pseudo flag */
|
||||
#define FNOFOLLOW 0x20000 /* don't follow symlinks */
|
||||
|
||||
/* Missing macros
|
||||
*/
|
||||
#define PAGESIZE PAGE_SIZE
|
||||
|
||||
/* from Solaris sys/byteorder.h */
|
||||
#define BSWAP_8(x) ((x) & 0xff)
|
||||
#define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8))
|
||||
#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16))
|
||||
#define BSWAP_64(x) ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32))
|
||||
|
||||
/* Map some simple functions.
|
||||
*/
|
||||
#define bzero(ptr,size) memset(ptr,0,size)
|
||||
#define bcopy(src,dest,size) memcpy(dest,src,size)
|
||||
#define ASSERT(x) BUG_ON(!(x))
|
||||
#define ASSERT3U(left,OP,right) BUG_ON(!((left) OP (right)))
|
||||
|
||||
/* Missing globals
|
||||
*/
|
||||
static int p0 = 0;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_GENERIC_H */
|
||||
@@ -0,0 +1,173 @@
|
||||
#ifndef _SYS_LINUX_KMEM_H
|
||||
#define _SYS_LINUX_KMEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#undef DEBUG_KMEM
|
||||
#undef DEBUG_KMEM_UNIMPLEMENTED
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/spinlock.h>
|
||||
/*
|
||||
* Memory allocation interfaces
|
||||
*/
|
||||
#define KM_SLEEP GFP_KERNEL
|
||||
#define KM_NOSLEEP GFP_ATOMIC
|
||||
#undef KM_PANIC /* No linux analog */
|
||||
#define KM_PUSHPAGE (GFP_KERNEL | GFP_HIGH)
|
||||
#define KM_VMFLAGS GFP_LEVEL_MASK
|
||||
#define KM_FLAGS __GFP_BITS_MASK
|
||||
|
||||
#ifdef DEBUG_KMEM
|
||||
/* Shim layer memory accounting */
|
||||
extern atomic_t kmem_alloc_used;
|
||||
extern unsigned int kmem_alloc_max;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_KMEM
|
||||
#define __kmem_alloc(size, flags, allocator) \
|
||||
({ void *_ptr_; \
|
||||
\
|
||||
/* Marked unlikely because we should never be doing this */ \
|
||||
if (unlikely((size) > (PAGE_SIZE * 2))) \
|
||||
printk("Warning: kmem_alloc(%d, 0x%x) large alloc at %s:%d " \
|
||||
"(%d/%d)\n", (int)(size), (int)(flags), \
|
||||
__FILE__, __LINE__, \
|
||||
atomic_read(&kmem_alloc_used), kmem_alloc_max); \
|
||||
\
|
||||
_ptr_ = (void *)allocator((size), (flags)); \
|
||||
if (_ptr_ == NULL) { \
|
||||
printk("Warning: kmem_alloc(%d, 0x%x) failed at %s:%d " \
|
||||
"(%d/%d)\n", (int)(size), (int)(flags), \
|
||||
__FILE__, __LINE__, \
|
||||
atomic_read(&kmem_alloc_used), kmem_alloc_max); \
|
||||
atomic_add((size), &kmem_alloc_used); \
|
||||
if (unlikely(atomic_read(&kmem_alloc_used) > kmem_alloc_max)) \
|
||||
kmem_alloc_max = atomic_read(&kmem_alloc_used); \
|
||||
} \
|
||||
\
|
||||
_ptr_; \
|
||||
})
|
||||
|
||||
#define kmem_alloc(size, flags) __kmem_alloc(size, flags, kmalloc)
|
||||
#define kmem_zalloc(size, flags) __kmem_alloc(size, flags, kzalloc)
|
||||
|
||||
#define kmem_free(ptr, size) \
|
||||
({ \
|
||||
BUG_ON(!ptr); \
|
||||
atomic_sub((size), &kmem_alloc_used); \
|
||||
memset(ptr, 0x5a, (size)); /* Poison */ \
|
||||
kfree(ptr); \
|
||||
(ptr) = (void *)0xdeadbeef; \
|
||||
})
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define kmem_alloc(size, flags) kmalloc(size, flags)
|
||||
#define kmem_zalloc(size, flags) kzalloc(size, flags)
|
||||
#define kmem_free(ptr, size) kfree(ptr)
|
||||
|
||||
#endif /* DEBUG_KMEM */
|
||||
|
||||
|
||||
#ifdef DEBUG_KMEM_UNIMPLEMENTED
|
||||
static __inline__ void *
|
||||
kmem_alloc_tryhard(size_t size, size_t *alloc_size, int kmflags)
|
||||
{
|
||||
#error "kmem_alloc_tryhard() not implemented"
|
||||
}
|
||||
#endif /* DEBUG_KMEM_UNIMPLEMENTED */
|
||||
|
||||
/*
|
||||
* Slab allocation interfaces
|
||||
*/
|
||||
#undef KMC_NOTOUCH /* No linux analog */
|
||||
#define KMC_NODEBUG 0x00000000 /* Default beahvior */
|
||||
#define KMC_NOMAGAZINE /* No linux analog */
|
||||
#define KMC_NOHASH /* No linux analog */
|
||||
#define KMC_QCACHE /* No linux analog */
|
||||
|
||||
#define KMC_REAP_CHUNK 256
|
||||
#define KMC_DEFAULT_SEEKS DEFAULT_SEEKS
|
||||
|
||||
/* Defined by linux slab.h
|
||||
* typedef struct kmem_cache_s kmem_cache_t;
|
||||
*/
|
||||
|
||||
/* No linux analog
|
||||
* extern int kmem_ready;
|
||||
* extern pgcnt_t kmem_reapahead;
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_KMEM_UNIMPLEMENTED
|
||||
static __inline__ void kmem_init(void) {
|
||||
#error "kmem_init() not implemented"
|
||||
}
|
||||
|
||||
static __inline__ void kmem_thread_init(void) {
|
||||
#error "kmem_thread_init() not implemented"
|
||||
}
|
||||
|
||||
static __inline__ void kmem_mp_init(void) {
|
||||
#error "kmem_mp_init() not implemented"
|
||||
}
|
||||
|
||||
static __inline__ void kmem_reap_idspace(void) {
|
||||
#error "kmem_reap_idspace() not implemented"
|
||||
}
|
||||
|
||||
static __inline__ size_t kmem_avail(void) {
|
||||
#error "kmem_avail() not implemented"
|
||||
}
|
||||
|
||||
static __inline__ size_t kmem_maxavail(void) {
|
||||
#error "kmem_maxavail() not implemented"
|
||||
}
|
||||
|
||||
static __inline__ uint64_t kmem_cache_stat(kmem_cache_t *cache) {
|
||||
#error "kmem_cache_stat() not implemented"
|
||||
}
|
||||
#endif /* DEBUG_KMEM_UNIMPLEMENTED */
|
||||
|
||||
/* XXX - Used by arc.c to adjust its memory footprint. We may want
|
||||
* to use this hook in the future to adjust behavior based on
|
||||
* debug levels. For now it's safe to always return 0.
|
||||
*/
|
||||
static __inline__ int
|
||||
kmem_debugging(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef int (*kmem_constructor_t)(void *, void *, int);
|
||||
typedef void (*kmem_destructor_t)(void *, void *);
|
||||
typedef void (*kmem_reclaim_t)(void *);
|
||||
|
||||
kmem_cache_t *
|
||||
__kmem_cache_create(char *name, size_t size, size_t align,
|
||||
int (*constructor)(void *, void *, int),
|
||||
void (*destructor)(void *, void *),
|
||||
void (*reclaim)(void *),
|
||||
void *priv, void *vmp, int flags);
|
||||
|
||||
void
|
||||
__kmem_cache_destroy(kmem_cache_t *cache);
|
||||
|
||||
#define kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) \
|
||||
__kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags)
|
||||
#define kmem_cache_destroy(cache) __kmem_cache_destroy(cache)
|
||||
#define kmem_cache_alloc(cache, flags) kmem_cache_alloc(cache, flags)
|
||||
#define kmem_cache_free(cache, ptr) kmem_cache_free(cache, ptr)
|
||||
#define kmem_cache_reap_now(cache) kmem_cache_shrink(cache)
|
||||
#define kmem_reap() __kmem_reap()
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_KMEM_H */
|
||||
@@ -0,0 +1,136 @@
|
||||
#ifndef _SYS_LINUX_KSTAT_H
|
||||
#define _SYS_LINUX_KSTAT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/linux-types.h>
|
||||
|
||||
/* XXX - The minimum functionality here is stubbed out but nothing works. */
|
||||
|
||||
#define KSTAT_STRLEN 31 /* 30 chars + NULL; must be 16 * n - 1 */
|
||||
|
||||
#define KSTAT_TYPE_RAW 0 /* can be anything */
|
||||
/* ks_ndata >= 1 */
|
||||
#define KSTAT_TYPE_NAMED 1 /* name/value pair */
|
||||
/* ks_ndata >= 1 */
|
||||
#define KSTAT_TYPE_INTR 2 /* interrupt statistics */
|
||||
/* ks_ndata == 1 */
|
||||
#define KSTAT_TYPE_IO 3 /* I/O statistics */
|
||||
/* ks_ndata == 1 */
|
||||
#define KSTAT_TYPE_TIMER 4 /* event timer */
|
||||
/* ks_ndata >= 1 */
|
||||
|
||||
#define KSTAT_NUM_TYPES 5
|
||||
|
||||
|
||||
#define KSTAT_DATA_CHAR 0
|
||||
#define KSTAT_DATA_INT32 1
|
||||
#define KSTAT_DATA_UINT32 2
|
||||
#define KSTAT_DATA_INT64 3
|
||||
#define KSTAT_DATA_UINT64 4
|
||||
|
||||
|
||||
#define KSTAT_FLAG_VIRTUAL 0x01
|
||||
#define KSTAT_FLAG_VAR_SIZE 0x02
|
||||
#define KSTAT_FLAG_WRITABLE 0x04
|
||||
#define KSTAT_FLAG_PERSISTENT 0x08
|
||||
#define KSTAT_FLAG_DORMANT 0x10
|
||||
#define KSTAT_FLAG_INVALID 0x2
|
||||
|
||||
|
||||
typedef int kid_t; /* unique kstat id */
|
||||
|
||||
typedef struct kstat_s {
|
||||
/*
|
||||
* Fields relevant to both kernel and user
|
||||
*/
|
||||
hrtime_t ks_crtime; /* creation time (from gethrtime()) */
|
||||
struct kstat_s *ks_next; /* kstat chain linkage */
|
||||
kid_t ks_kid; /* unique kstat ID */
|
||||
char ks_module[KSTAT_STRLEN]; /* provider module name */
|
||||
uchar_t ks_resv; /* reserved, currently just padding */
|
||||
int ks_instance; /* provider module's instance */
|
||||
char ks_name[KSTAT_STRLEN]; /* kstat name */
|
||||
uchar_t ks_type; /* kstat data type */
|
||||
char ks_class[KSTAT_STRLEN]; /* kstat class */
|
||||
uchar_t ks_flags; /* kstat flags */
|
||||
void *ks_data; /* kstat type-specific data */
|
||||
uint_t ks_ndata; /* # of type-specific data records */
|
||||
size_t ks_data_size; /* total size of kstat data section */
|
||||
hrtime_t ks_snaptime; /* time of last data shapshot */
|
||||
/*
|
||||
* Fields relevant to kernel only
|
||||
*/
|
||||
int (*ks_update)(struct kstat *, int); /* dynamic update */
|
||||
void *ks_private; /* arbitrary provider-private data */
|
||||
int (*ks_snapshot)(struct kstat *, void *, int);
|
||||
void *ks_lock; /* protects this kstat's data */
|
||||
} kstat_t;
|
||||
|
||||
typedef struct kstat_named_s {
|
||||
char name[KSTAT_STRLEN]; /* name of counter */
|
||||
uchar_t data_type; /* data type */
|
||||
union {
|
||||
char c[16]; /* enough for 128-bit ints */
|
||||
int32_t i32;
|
||||
uint32_t ui32;
|
||||
struct {
|
||||
union {
|
||||
char *ptr; /* NULL-term string */
|
||||
char __pad[8]; /* 64-bit padding */
|
||||
} addr;
|
||||
uint32_t len; /* # bytes for strlen + '\0' */
|
||||
} str;
|
||||
/*
|
||||
* The int64_t and uint64_t types are not valid for a maximally conformant
|
||||
* 32-bit compilation environment (cc -Xc) using compilers prior to the
|
||||
* introduction of C99 conforming compiler (reference ISO/IEC 9899:1990).
|
||||
* In these cases, the visibility of i64 and ui64 is only permitted for
|
||||
* 64-bit compilation environments or 32-bit non-maximally conformant
|
||||
* C89 or C90 ANSI C compilation environments (cc -Xt and cc -Xa). In the
|
||||
* C99 ANSI C compilation environment, the long long type is supported.
|
||||
* The _INT64_TYPE is defined by the implementation (see sys/int_types.h).
|
||||
*/
|
||||
int64_t i64;
|
||||
uint64_t ui64;
|
||||
long l;
|
||||
ulong_t ul;
|
||||
|
||||
/* These structure members are obsolete */
|
||||
|
||||
longlong_t ll;
|
||||
u_longlong_t ull;
|
||||
float f;
|
||||
double d;
|
||||
} value; /* value of counter */
|
||||
} kstat_named_t;
|
||||
|
||||
|
||||
static __inline__ kstat_t *
|
||||
kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
|
||||
const char *ks_class, uchar_t ks_type, uint_t ks_ndata,
|
||||
uchar_t ks_flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
kstat_install(kstat_t *ksp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
kstat_delete(kstat_t *ksp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_KSTAT_H */
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
#ifndef _SYS_LINUX_MUTEX_H
|
||||
#define _SYS_LINUX_MUTEX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* See the "Big Theory Statement" in solaris mutex.c.
|
||||
*
|
||||
* Spin mutexes apparently aren't needed by zfs so we assert
|
||||
* if ibc is non-zero.
|
||||
*
|
||||
* Our impementation of adaptive mutexes aren't really adaptive.
|
||||
* They go to sleep every time.
|
||||
*/
|
||||
|
||||
#define MUTEX_DEFAULT 0
|
||||
#define MUTEX_HELD(x) (mutex_owned(x))
|
||||
|
||||
#define KM_MAGIC 0x42424242
|
||||
#define KM_POISON 0x84
|
||||
|
||||
typedef struct {
|
||||
int km_magic;
|
||||
char *km_name;
|
||||
struct task_struct *km_owner;
|
||||
struct semaphore km_sem;
|
||||
} kmutex_t;
|
||||
|
||||
#undef mutex_init
|
||||
static __inline__ void
|
||||
mutex_init(kmutex_t *mp, char *name, int type, void *ibc)
|
||||
{
|
||||
BUG_ON(ibc != NULL); /* XXX - Spin mutexes not needed? */
|
||||
BUG_ON(type != MUTEX_DEFAULT); /* XXX - Only default type supported? */
|
||||
|
||||
mp->km_magic = KM_MAGIC;
|
||||
sema_init(&mp->km_sem, 1);
|
||||
mp->km_owner = NULL;
|
||||
mp->km_name = NULL;
|
||||
|
||||
if (name) {
|
||||
mp->km_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
|
||||
if (mp->km_name)
|
||||
strcpy(mp->km_name, name);
|
||||
}
|
||||
}
|
||||
|
||||
#undef mutex_destroy
|
||||
static __inline__ void
|
||||
mutex_destroy(kmutex_t *mp)
|
||||
{
|
||||
BUG_ON(mp->km_magic != KM_MAGIC);
|
||||
|
||||
if (mp->km_name)
|
||||
kfree(mp->km_name);
|
||||
|
||||
memset(mp, KM_POISON, sizeof(*mp));
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
mutex_enter(kmutex_t *mp)
|
||||
{
|
||||
BUG_ON(mp->km_magic != KM_MAGIC);
|
||||
down(&mp->km_sem); /* Will check in_atomic() for us */
|
||||
BUG_ON(mp->km_owner != NULL);
|
||||
mp->km_owner = current;
|
||||
}
|
||||
|
||||
/* Return 1 if we acquired the mutex, else zero.
|
||||
*/
|
||||
static __inline__ int
|
||||
mutex_tryenter(kmutex_t *mp)
|
||||
{
|
||||
int result;
|
||||
|
||||
BUG_ON(mp->km_magic != KM_MAGIC);
|
||||
result = down_trylock(&mp->km_sem); /* returns 0 if acquired */
|
||||
if (result == 0) {
|
||||
BUG_ON(mp->km_owner != NULL);
|
||||
mp->km_owner = current;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
mutex_exit(kmutex_t *mp)
|
||||
{
|
||||
BUG_ON(mp->km_magic != KM_MAGIC);
|
||||
BUG_ON(mp->km_owner != current);
|
||||
mp->km_owner = NULL;
|
||||
up(&mp->km_sem);
|
||||
}
|
||||
|
||||
/* Return 1 if mutex is held by current process, else zero.
|
||||
*/
|
||||
static __inline__ int
|
||||
mutex_owned(kmutex_t *mp)
|
||||
{
|
||||
BUG_ON(mp->km_magic != KM_MAGIC);
|
||||
return (mp->km_owner == current);
|
||||
}
|
||||
|
||||
/* Return owner if mutex is owned, else NULL.
|
||||
*/
|
||||
static __inline__ kthread_t *
|
||||
mutex_owner(kmutex_t *mp)
|
||||
{
|
||||
BUG_ON(mp->km_magic != KM_MAGIC);
|
||||
return mp->km_owner;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_MUTEX_H */
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _SYS_LINUX_RANDOM_H
|
||||
#define _SYS_LINUX_RANDOM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <linux/random.h>
|
||||
|
||||
/* FIXME:
|
||||
* Should add support for blocking in the future to
|
||||
* ensure that proper entopy is collected. ZFS doesn't
|
||||
* use it at the moment so this is good enough for now.
|
||||
* Always will succeed by returning 0.
|
||||
*/
|
||||
static __inline__ int
|
||||
random_get_bytes(uint8_t *ptr, size_t len)
|
||||
{
|
||||
BUG_ON(len < 0);
|
||||
get_random_bytes((void *)ptr,(int)len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Always will succeed by returning 0. */
|
||||
static __inline__ int
|
||||
random_get_pseudo_bytes(uint8_t *ptr, size_t len)
|
||||
{
|
||||
BUG_ON(len < 0);
|
||||
get_random_bytes((void *)ptr,(int)len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_RANDOM_H */
|
||||
@@ -0,0 +1,223 @@
|
||||
#ifndef _SYS_LINUX_RWLOCK_H
|
||||
#define _SYS_LINUX_RWLOCK_H
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <asm/current.h>
|
||||
#include <sys/linux-types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RW_DRIVER = 2, /* driver (DDI) rwlock */
|
||||
RW_DEFAULT = 4 /* kernel default rwlock */
|
||||
} krw_type_t;
|
||||
|
||||
typedef enum {
|
||||
RW_WRITER,
|
||||
RW_READER
|
||||
} krw_t;
|
||||
|
||||
#define RW_READ_HELD(x) (rw_read_held((x)))
|
||||
#define RW_WRITE_HELD(x) (rw_write_held((x)))
|
||||
#define RW_LOCK_HELD(x) (rw_lock_held((x)))
|
||||
#define RW_ISWRITER(x) (rw_iswriter(x))
|
||||
|
||||
#define RW_MAGIC 0x3423645a
|
||||
#define RW_POISON 0xa6
|
||||
|
||||
typedef struct {
|
||||
int rw_magic;
|
||||
char *rw_name;
|
||||
struct rw_semaphore rw_sem;
|
||||
struct task_struct *rw_owner; /* holder of the write lock */
|
||||
} krwlock_t;
|
||||
|
||||
static __inline__ void
|
||||
rw_init(krwlock_t *rwlp, char *name, krw_type_t type, void *arg)
|
||||
{
|
||||
BUG_ON(type != RW_DEFAULT); /* XXX no irq handler use */
|
||||
BUG_ON(arg != NULL); /* XXX no irq handler use */
|
||||
rwlp->rw_magic = RW_MAGIC;
|
||||
rwlp->rw_owner = NULL; /* no one holds the write lock yet */
|
||||
init_rwsem(&rwlp->rw_sem);
|
||||
rwlp->rw_name = NULL;
|
||||
|
||||
if (name) {
|
||||
rwlp->rw_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
|
||||
if (rwlp->rw_name)
|
||||
strcpy(rwlp->rw_name, name);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
rw_destroy(krwlock_t *rwlp)
|
||||
{
|
||||
BUG_ON(rwlp == NULL);
|
||||
BUG_ON(rwlp->rw_magic != RW_MAGIC);
|
||||
BUG_ON(rwlp->rw_owner != NULL);
|
||||
spin_lock(&rwlp->rw_sem.wait_lock);
|
||||
BUG_ON(!list_empty(&rwlp->rw_sem.wait_list));
|
||||
spin_unlock(&rwlp->rw_sem.wait_lock);
|
||||
|
||||
if (rwlp->rw_name)
|
||||
kfree(rwlp->rw_name);
|
||||
|
||||
memset(rwlp, RW_POISON, sizeof(krwlock_t));
|
||||
}
|
||||
|
||||
/* Return 0 if the lock could not be obtained without blocking.
|
||||
*/
|
||||
static __inline__ int
|
||||
rw_tryenter(krwlock_t *rwlp, krw_t rw)
|
||||
{
|
||||
int result;
|
||||
|
||||
BUG_ON(rwlp->rw_magic != RW_MAGIC);
|
||||
switch (rw) {
|
||||
/* these functions return 1 if success, 0 if contention */
|
||||
case RW_READER:
|
||||
/* Here the Solaris code would return 0
|
||||
* if there were any write waiters. Specifically
|
||||
* thinking about the case where readers may have
|
||||
* the lock and we would also allow this thread
|
||||
* to grab the read lock with a writer waiting in the
|
||||
* queue. This doesn't seem like a correctness
|
||||
* issue, so just call down_read_trylock()
|
||||
* for the test. We may have to revisit this if
|
||||
* it becomes an issue */
|
||||
result = down_read_trylock(&rwlp->rw_sem);
|
||||
break;
|
||||
case RW_WRITER:
|
||||
result = down_write_trylock(&rwlp->rw_sem);
|
||||
if (result) {
|
||||
/* there better not be anyone else
|
||||
* holding the write lock here */
|
||||
BUG_ON(rwlp->rw_owner != NULL);
|
||||
rwlp->rw_owner = current;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
rw_enter(krwlock_t *rwlp, krw_t rw)
|
||||
{
|
||||
BUG_ON(rwlp->rw_magic != RW_MAGIC);
|
||||
switch (rw) {
|
||||
case RW_READER:
|
||||
/* Here the Solaris code would block
|
||||
* if there were any write waiters. Specifically
|
||||
* thinking about the case where readers may have
|
||||
* the lock and we would also allow this thread
|
||||
* to grab the read lock with a writer waiting in the
|
||||
* queue. This doesn't seem like a correctness
|
||||
* issue, so just call down_read()
|
||||
* for the test. We may have to revisit this if
|
||||
* it becomes an issue */
|
||||
down_read(&rwlp->rw_sem);
|
||||
break;
|
||||
case RW_WRITER:
|
||||
down_write(&rwlp->rw_sem);
|
||||
|
||||
/* there better not be anyone else
|
||||
* holding the write lock here */
|
||||
BUG_ON(rwlp->rw_owner != NULL);
|
||||
rwlp->rw_owner = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
rw_exit(krwlock_t *rwlp)
|
||||
{
|
||||
BUG_ON(rwlp->rw_magic != RW_MAGIC);
|
||||
|
||||
/* rw_owner is held by current
|
||||
* thread iff it is a writer */
|
||||
if (rwlp->rw_owner == current) {
|
||||
rwlp->rw_owner = NULL;
|
||||
up_write(&rwlp->rw_sem);
|
||||
} else {
|
||||
up_read(&rwlp->rw_sem);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
rw_downgrade(krwlock_t *rwlp)
|
||||
{
|
||||
BUG_ON(rwlp->rw_magic != RW_MAGIC);
|
||||
BUG_ON(rwlp->rw_owner != current);
|
||||
rwlp->rw_owner = NULL;
|
||||
downgrade_write(&rwlp->rw_sem);
|
||||
}
|
||||
|
||||
/* Return 0 if unable to perform the upgrade.
|
||||
* Might be wise to fix the caller
|
||||
* to acquire the write lock first?
|
||||
*/
|
||||
static __inline__ int
|
||||
rw_tryupgrade(krwlock_t *rwlp)
|
||||
{
|
||||
int result;
|
||||
BUG_ON(rwlp->rw_magic != RW_MAGIC);
|
||||
|
||||
spin_lock(&rwlp->rw_sem.wait_lock);
|
||||
|
||||
/* Check if there is anyone waiting for the
|
||||
* lock. If there is, then we know we should
|
||||
* not try to upgrade the lock */
|
||||
if (!list_empty(&rwlp->rw_sem.wait_list)) {
|
||||
printk(KERN_WARNING "There are threads waiting\n");
|
||||
spin_unlock(&rwlp->rw_sem.wait_lock);
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
|
||||
/* Note that activity is protected by
|
||||
* the wait_lock. Don't try to upgrade
|
||||
* if there are multiple readers currently
|
||||
* holding the lock */
|
||||
if (rwlp->rw_sem.activity > 1) {
|
||||
#else
|
||||
/* Don't try to upgrade
|
||||
* if there are multiple readers currently
|
||||
* holding the lock */
|
||||
if ((rwlp->rw_sem.count & RWSEM_ACTIVE_MASK) > 1) {
|
||||
#endif
|
||||
spin_unlock(&rwlp->rw_sem.wait_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Here it should be safe to drop the
|
||||
* read lock and reacquire it for writing since
|
||||
* we know there are no waiters */
|
||||
up_read(&rwlp->rw_sem);
|
||||
|
||||
/* returns 1 if success, 0 if contention */
|
||||
result = down_write_trylock(&rwlp->rw_sem);
|
||||
|
||||
/* Check if upgrade failed. Should not ever happen
|
||||
* if we got to this point */
|
||||
BUG_ON(!result);
|
||||
BUG_ON(rwlp->rw_owner != NULL);
|
||||
rwlp->rw_owner = current;
|
||||
spin_unlock(&rwlp->rw_sem.wait_lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __inline__ kthread_t *
|
||||
rw_owner(krwlock_t *rwlp)
|
||||
{
|
||||
BUG_ON(rwlp->rw_magic != RW_MAGIC);
|
||||
return rwlp->rw_owner;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_RWLOCK_H */
|
||||
@@ -0,0 +1,86 @@
|
||||
#ifndef _SYS_LINUX_TASKQ_H
|
||||
#define _SYS_LINUX_TASKQ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Task Queues - As of linux 2.6.x task queues have been replaced by a
|
||||
* similar construct called work queues. The big difference on the linux
|
||||
* side is that functions called from work queues run in process context
|
||||
* and not interrupt context.
|
||||
*
|
||||
* One nice feature of Solaris which does not exist in linux work
|
||||
* queues in the notion of a dynamic work queue. Rather than implementing
|
||||
* this in the shim layer I'm hardcoding one-thread per work queue.
|
||||
*
|
||||
* XXX - This may end up being a significant performance penalty which
|
||||
* forces us to implement dynamic workqueues. Which is all very doable
|
||||
* with a little effort.
|
||||
*/
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <sys/linux-types.h>
|
||||
|
||||
#undef DEBUG_TASKQ_UNIMPLEMENTED
|
||||
|
||||
#define TASKQ_NAMELEN 31
|
||||
#define taskq_t workq_t
|
||||
|
||||
typedef struct workqueue_struct workq_t;
|
||||
typedef unsigned long taskqid_t;
|
||||
typedef void (*task_func_t)(void *);
|
||||
|
||||
/*
|
||||
* Public flags for taskq_create(): bit range 0-15
|
||||
*/
|
||||
#define TASKQ_PREPOPULATE 0x0000 /* XXX - Workqueues fully populate */
|
||||
#define TASKQ_CPR_SAFE 0x0000 /* XXX - No analog */
|
||||
#define TASKQ_DYNAMIC 0x0000 /* XXX - Worksqueues not dynamic */
|
||||
|
||||
/*
|
||||
* Flags for taskq_dispatch. TQ_SLEEP/TQ_NOSLEEP should be same as
|
||||
* KM_SLEEP/KM_NOSLEEP.
|
||||
*/
|
||||
#define TQ_SLEEP 0x00 /* XXX - Workqueues don't support */
|
||||
#define TQ_NOSLEEP 0x00 /* these sorts of flags. They */
|
||||
#define TQ_NOQUEUE 0x00 /* always run in application */
|
||||
#define TQ_NOALLOC 0x00 /* context and can sleep. */
|
||||
|
||||
|
||||
#ifdef DEBUG_TASKQ_UNIMPLEMENTED
|
||||
static __inline__ void taskq_init(void) {
|
||||
#error "taskq_init() not implemented"
|
||||
}
|
||||
|
||||
static __inline__ taskq_t *
|
||||
taskq_create_instance(const char *, int, int, pri_t, int, int, uint_t) {
|
||||
#error "taskq_create_instance() not implemented"
|
||||
}
|
||||
|
||||
extern void nulltask(void *);
|
||||
extern void taskq_suspend(taskq_t *);
|
||||
extern int taskq_suspended(taskq_t *);
|
||||
extern void taskq_resume(taskq_t *);
|
||||
|
||||
#endif /* DEBUG_TASKQ_UNIMPLEMENTED */
|
||||
|
||||
extern taskqid_t __taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
|
||||
extern taskq_t *__taskq_create(const char *, int, pri_t, int, int, uint_t);
|
||||
|
||||
#define taskq_create(name, thr, pri, min, max, flags) \
|
||||
__taskq_create(name, thr, pri, min, max, flags)
|
||||
#define taskq_dispatch(tq, func, priv, flags) \
|
||||
__taskq_dispatch(tq, func, priv, flags)
|
||||
#define taskq_destory(tq) destroy_workqueue(tq)
|
||||
#define taskq_wait(tq) flush_workqueue(tq)
|
||||
#define taskq_member(tq, kthr) 1 /* XXX -Just be true */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_TASKQ_H */
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef _SYS_LINUX_THREAD_H
|
||||
#define _SYS_LINUX_THREAD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <sys/linux-types.h>
|
||||
#include <sys/linux-generic.h>
|
||||
|
||||
/*
|
||||
* Thread interfaces
|
||||
*/
|
||||
#define TP_MAGIC 0x53535353
|
||||
|
||||
#define TS_SLEEP TASK_INTERRUPTIBLE
|
||||
#define TS_RUN TASK_RUNNING
|
||||
#define TS_ZOMB EXIT_ZOMBIE
|
||||
#define TS_STOPPED TASK_STOPPED
|
||||
#if 0
|
||||
#define TS_FREE 0x00 /* No clean linux mapping */
|
||||
#define TS_ONPROC 0x04 /* No clean linux mapping */
|
||||
#define TS_WAIT 0x20 /* No clean linux mapping */
|
||||
#endif
|
||||
|
||||
#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \
|
||||
__thread_create(stk, stksize, func, arg, len, pp, state, pri)
|
||||
#define thread_exit() __thread_exit()
|
||||
#define curthread get_current()
|
||||
|
||||
/* We just need a valid type to pass around, it's unused */
|
||||
typedef struct proc_s {
|
||||
int foo;
|
||||
} proc_t;
|
||||
|
||||
kthread_t * __thread_create(caddr_t stk, size_t stksize,
|
||||
void (*proc)(void *), void *args,
|
||||
size_t len, proc_t *pp, int state,
|
||||
pri_t pri);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_THREAD_H */
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef _SYS_TIME_H
|
||||
#define _SYS_TIME_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.16 */
|
||||
|
||||
/*
|
||||
* Structure returned by gettimeofday(2) system call,
|
||||
* and used in other calls.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <sys/linux-types.h>
|
||||
|
||||
extern unsigned long long monotonic_clock(void);
|
||||
typedef struct timespec timestruc_t; /* definition per SVr4 */
|
||||
typedef longlong_t hrtime_t;
|
||||
|
||||
#define TIME32_MAX INT32_MAX
|
||||
#define TIME32_MIN INT32_MIN
|
||||
|
||||
#define SEC 1
|
||||
#define MILLISEC 1000
|
||||
#define MICROSEC 1000000
|
||||
#define NANOSEC 1000000000
|
||||
|
||||
#define hz \
|
||||
({ \
|
||||
BUG_ON(HZ < 100 || HZ > MICROSEC); \
|
||||
HZ; \
|
||||
})
|
||||
|
||||
#define gethrestime(ts) getnstimeofday((ts))
|
||||
|
||||
static __inline__ hrtime_t
|
||||
gethrtime(void) {
|
||||
/* BUG_ON(cur_timer == timer_none); */
|
||||
|
||||
/* Solaris expects a long long here but monotonic_clock() returns an
|
||||
* unsigned long long. Note that monotonic_clock() returns the number
|
||||
* of nanoseconds passed since kernel initialization. Even for a signed
|
||||
* long long this will not "go negative" for ~292 years.
|
||||
*/
|
||||
return monotonic_clock();
|
||||
}
|
||||
|
||||
static __inline__ time_t
|
||||
gethrestime_sec(void)
|
||||
{
|
||||
timestruc_t now;
|
||||
|
||||
gethrestime(&now);
|
||||
return (now.tv_sec);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_TIME_H */
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _SYS_LINUX_TIMER_H
|
||||
#define _SYS_LINUX_TIMER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#define lbolt ((clock_t)jiffies)
|
||||
#define lbolt64 ((int64_t)get_jiffies_64())
|
||||
|
||||
#define delay(ticks) schedule_timeout((long timeout)(ticks))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_TIMER_H */
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef _SYS_LINUX_TYPES_H
|
||||
#define _SYS_LINUX_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum { B_FALSE=0, B_TRUE=1 } boolean_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef unsigned long intptr_t;
|
||||
typedef unsigned long ulong_t;
|
||||
typedef unsigned int uint_t;
|
||||
typedef unsigned char uchar_t;
|
||||
typedef unsigned long long u_longlong_t;
|
||||
typedef unsigned long long u_offset_t;
|
||||
typedef unsigned long long rlim64_t;
|
||||
typedef long long longlong_t;
|
||||
typedef long long offset_t;
|
||||
typedef struct task_struct kthread_t;
|
||||
typedef struct vmem { } vmem_t;
|
||||
typedef short pri_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_LINUX_TYPES_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef _SYS_SPL_H
|
||||
#define _SYS_SPL_H
|
||||
|
||||
#endif /* _SYS_SPL_H */
|
||||
@@ -0,0 +1,211 @@
|
||||
#ifndef _SYS_KZT_H
|
||||
#define _SYS_KZT_H
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <asm/ioctls.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/list.h>
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#define KZT_VERSION "v1.0"
|
||||
#define KZT_VERSION_SIZE 64
|
||||
|
||||
#define KZT_MAJOR 229 /* XXX - Arbitrary */
|
||||
#define KZT_MINORS 1
|
||||
#define KZT_DEV "/dev/kztctl"
|
||||
|
||||
#define KZT_NAME_SIZE 12
|
||||
#define KZT_DESC_SIZE 60
|
||||
|
||||
typedef struct kzt_user {
|
||||
char name[KZT_NAME_SIZE]; /* short name */
|
||||
char desc[KZT_DESC_SIZE]; /* short description */
|
||||
int id; /* unique numeric id */
|
||||
} kzt_user_t;
|
||||
|
||||
#define KZT_CFG_MAGIC 0x15263748U
|
||||
typedef struct kzt_cfg {
|
||||
unsigned int cfg_magic; /* Unique magic */
|
||||
int cfg_cmd; /* Config command */
|
||||
int cfg_arg1; /* Config command arg 1 */
|
||||
int cfg_rc1; /* Config response 1 */
|
||||
union {
|
||||
struct {
|
||||
int size;
|
||||
kzt_user_t descs[0];
|
||||
} kzt_subsystems;
|
||||
struct {
|
||||
int size;
|
||||
kzt_user_t descs[0];
|
||||
} kzt_tests;
|
||||
} cfg_data;
|
||||
} kzt_cfg_t;
|
||||
|
||||
#define KZT_CMD_MAGIC 0x9daebfc0U
|
||||
typedef struct kzt_cmd {
|
||||
unsigned int cmd_magic; /* Unique magic */
|
||||
int cmd_subsystem; /* Target subsystem */
|
||||
int cmd_test; /* Subsystem test */
|
||||
int cmd_data_size; /* Extra opaque data */
|
||||
char cmd_data_str[0]; /* Opaque data region */
|
||||
} kzt_cmd_t;
|
||||
|
||||
/* Valid ioctls */
|
||||
#define KZT_CFG _IOWR('f', 101, long)
|
||||
#define KZT_CMD _IOWR('f', 102, long)
|
||||
|
||||
/* Valid configuration commands */
|
||||
#define KZT_CFG_BUFFER_CLEAR 0x001 /* Clear text buffer */
|
||||
#define KZT_CFG_BUFFER_SIZE 0x002 /* Resize text buffer */
|
||||
#define KZT_CFG_SUBSYSTEM_COUNT 0x101 /* Number of subsystem */
|
||||
#define KZT_CFG_SUBSYSTEM_LIST 0x102 /* List of N subsystems */
|
||||
#define KZT_CFG_TEST_COUNT 0x201 /* Number of tests */
|
||||
#define KZT_CFG_TEST_LIST 0x202 /* List of N tests */
|
||||
|
||||
/* Valid subsystem and test commands defined in each subsystem, we do
|
||||
* need to be careful to avoid colisions. That alone may argue to define
|
||||
* them all here, for now we just define the global error codes.
|
||||
*/
|
||||
#define KZT_SUBSYSTEM_UNKNOWN 0xF00
|
||||
#define KZT_TEST_UNKNOWN 0xFFF
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define KZT_SUBSYSTEM_INIT(type) \
|
||||
({ kzt_subsystem_t *_sub_; \
|
||||
\
|
||||
_sub_ = (kzt_subsystem_t *)kzt_##type##_init(); \
|
||||
if (_sub_ == NULL) { \
|
||||
printk(KERN_ERR "Error initializing: " #type "\n"); \
|
||||
} else { \
|
||||
spin_lock(&kzt_module_lock); \
|
||||
list_add_tail(&(_sub_->subsystem_list), \
|
||||
&kzt_module_list); \
|
||||
spin_unlock(&kzt_module_lock); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define KZT_SUBSYSTEM_FINI(type) \
|
||||
({ kzt_subsystem_t *_sub_, *_tmp_; \
|
||||
int _id_, _flag_ = 0; \
|
||||
\
|
||||
_id_ = kzt_##type##_id(); \
|
||||
spin_lock(&kzt_module_lock); \
|
||||
list_for_each_entry_safe(_sub_, _tmp_, &kzt_module_list, \
|
||||
subsystem_list) { \
|
||||
if (_sub_->desc.id == _id_) { \
|
||||
list_del_init(&(_sub_->subsystem_list)); \
|
||||
spin_unlock(&kzt_module_lock); \
|
||||
kzt_##type##_fini(_sub_); \
|
||||
spin_lock(&kzt_module_lock); \
|
||||
_flag_ = 1; \
|
||||
} \
|
||||
} \
|
||||
spin_unlock(&kzt_module_lock); \
|
||||
\
|
||||
if (!_flag_) \
|
||||
printk(KERN_ERR "Error finalizing: " #type "\n"); \
|
||||
})
|
||||
|
||||
#define KZT_TEST_INIT(sub, n, d, tid, func) \
|
||||
({ kzt_test_t *_test_; \
|
||||
\
|
||||
_test_ = (kzt_test_t *)kmalloc(sizeof(*_test_), GFP_KERNEL); \
|
||||
if (_test_ == NULL) { \
|
||||
printk(KERN_ERR "Error initializing: " n "/" #tid" \n");\
|
||||
} else { \
|
||||
memset(_test_, 0, sizeof(*_test_)); \
|
||||
strncpy(_test_->desc.name, n, KZT_NAME_SIZE); \
|
||||
strncpy(_test_->desc.desc, d, KZT_DESC_SIZE); \
|
||||
_test_->desc.id = tid; \
|
||||
_test_->test = func; \
|
||||
INIT_LIST_HEAD(&(_test_->test_list)); \
|
||||
spin_lock(&((sub)->test_lock)); \
|
||||
list_add_tail(&(_test_->test_list),&((sub)->test_list));\
|
||||
spin_unlock(&((sub)->test_lock)); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define KZT_TEST_FINI(sub, tid) \
|
||||
({ kzt_test_t *_test_, *_tmp_; \
|
||||
int _flag_ = 0; \
|
||||
\
|
||||
spin_lock(&((sub)->test_lock)); \
|
||||
list_for_each_entry_safe(_test_, _tmp_, \
|
||||
&((sub)->test_list), test_list) { \
|
||||
if (_test_->desc.id == tid) { \
|
||||
list_del_init(&(_test_->test_list)); \
|
||||
_flag_ = 1; \
|
||||
} \
|
||||
} \
|
||||
spin_unlock(&((sub)->test_lock)); \
|
||||
\
|
||||
if (!_flag_) \
|
||||
printk(KERN_ERR "Error finalizing: " #tid "\n"); \
|
||||
})
|
||||
|
||||
typedef int (*kzt_test_func_t)(struct file *, void *);
|
||||
|
||||
typedef struct kzt_test {
|
||||
struct list_head test_list;
|
||||
kzt_user_t desc;
|
||||
kzt_test_func_t test;
|
||||
} kzt_test_t;
|
||||
|
||||
typedef struct kzt_subsystem {
|
||||
struct list_head subsystem_list;/* List had to chain entries */
|
||||
kzt_user_t desc;
|
||||
spinlock_t test_lock;
|
||||
struct list_head test_list;
|
||||
} kzt_subsystem_t;
|
||||
|
||||
#define KZT_INFO_BUFFER_SIZE 65536
|
||||
#define KZT_INFO_BUFFER_REDZONE 256
|
||||
|
||||
typedef struct kzt_info {
|
||||
spinlock_t info_lock;
|
||||
int info_size;
|
||||
char *info_buffer;
|
||||
char *info_head; /* Internal kernel use only */
|
||||
} kzt_info_t;
|
||||
|
||||
#define sym2str(sym) (char *)(#sym)
|
||||
|
||||
#define kzt_print(file, format, args...) \
|
||||
({ kzt_info_t *_info_ = (kzt_info_t *)file->private_data; \
|
||||
int _rc_; \
|
||||
\
|
||||
ASSERT(_info_); \
|
||||
ASSERT(_info_->info_buffer); \
|
||||
\
|
||||
spin_lock(&_info_->info_lock); \
|
||||
\
|
||||
/* Don't allow the kernel to start a write in the red zone */ \
|
||||
if ((int)(_info_->info_head - _info_->info_buffer) > \
|
||||
(KZT_INFO_BUFFER_SIZE -KZT_INFO_BUFFER_REDZONE)) { \
|
||||
_rc_ = -EOVERFLOW; \
|
||||
} else { \
|
||||
_rc_ = sprintf(_info_->info_head, format, args); \
|
||||
if (_rc_ >= 0) \
|
||||
_info_->info_head += _rc_; \
|
||||
} \
|
||||
\
|
||||
spin_unlock(&_info_->info_lock); \
|
||||
_rc_; \
|
||||
})
|
||||
|
||||
#define kzt_vprint(file, test, format, args...) \
|
||||
kzt_print(file, "%*s: " format, KZT_NAME_SIZE, test, args)
|
||||
|
||||
kzt_subsystem_t * kzt_condvar_init(void);
|
||||
kzt_subsystem_t * kzt_kmem_init(void);
|
||||
kzt_subsystem_t * kzt_mutex_init(void);
|
||||
kzt_subsystem_t * kzt_krng_init(void);
|
||||
kzt_subsystem_t * kzt_rwlock_init(void);
|
||||
kzt_subsystem_t * kzt_taskq_init(void);
|
||||
kzt_subsystem_t * kzt_thread_init(void);
|
||||
kzt_subsystem_t * kzt_time_init(void);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _SYS_KZT_H */
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef _KZT_H
|
||||
#define _KZT_H
|
||||
|
||||
#include <sys/splat-ctl.h>
|
||||
|
||||
#define DEV_NAME "/dev/kztctl"
|
||||
#define COLOR_BLACK "\033[0;30m"
|
||||
#define COLOR_DK_GRAY "\033[1;30m"
|
||||
#define COLOR_BLUE "\033[0;34m"
|
||||
#define COLOR_LT_BLUE "\033[1;34m"
|
||||
#define COLOR_GREEN "\033[0;32m"
|
||||
#define COLOR_LT_GREEN "\033[1;32m"
|
||||
#define COLOR_CYAN "\033[0;36m"
|
||||
#define COLOR_LT_CYAN "\033[1;36m"
|
||||
#define COLOR_RED "\033[0;31m"
|
||||
#define COLOR_LT_RED "\033[1;31m"
|
||||
#define COLOR_PURPLE "\033[0;35m"
|
||||
#define COLOR_LT_PURPLE "\033[1;35m"
|
||||
#define COLOR_BROWN "\033[0;33m"
|
||||
#define COLOR_YELLOW "\033[1;33m"
|
||||
#define COLOR_LT_GRAY "\033[0;37m"
|
||||
#define COLOR_WHITE "\033[1;37m"
|
||||
#define COLOR_RESET "\033[0m"
|
||||
|
||||
typedef struct subsystem {
|
||||
uu_list_node_t sub_node; /* Linkage for global subsystem list */
|
||||
kzt_user_t sub_desc; /* Subsystem description */
|
||||
uu_list_t *sub_tests; /* Assocated subsystem tests list */
|
||||
} subsystem_t;
|
||||
|
||||
typedef struct test {
|
||||
uu_list_node_t test_node; /* Linkage for globals test list */
|
||||
kzt_user_t test_desc; /* Test description */
|
||||
subsystem_t *test_sub; /* Parent subsystem */
|
||||
} test_t;
|
||||
|
||||
typedef struct cmd_args {
|
||||
int args_verbose; /* Verbose flag */
|
||||
int args_do_list; /* Display all tests flag */
|
||||
int args_do_all; /* Run all tests flag */
|
||||
int args_do_color; /* Colorize output */
|
||||
int args_exit_on_error; /* Exit on first error flag */
|
||||
uu_list_t *args_tests; /* Requested subsystems/tests */
|
||||
} cmd_args_t;
|
||||
|
||||
#endif /* _KZT_H */
|
||||
|
||||
Reference in New Issue
Block a user