diff --git a/include/sys/condvar.h b/include/sys/condvar.h index 59407c2d..709a86d3 100644 --- a/include/sys/condvar.h +++ b/include/sys/condvar.h @@ -35,12 +35,13 @@ * calling any of the wait/signal funs, and passed into the wait funs. */ #define CV_MAGIC 0x346545f4 -#define CV_POISON 0x95 +#define CV_DESTROY 0x346545f5 typedef struct { int cv_magic; wait_queue_head_t cv_event; wait_queue_head_t cv_destroy; + atomic_t cv_refs; atomic_t cv_waiters; kmutex_t *cv_mutex; } kcondvar_t; diff --git a/include/sys/kmem.h b/include/sys/kmem.h index 0149e754..e71a443a 100644 --- a/include/sys/kmem.h +++ b/include/sys/kmem.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/include/sys/types.h b/include/sys/types.h index 0c3d88ec..35905eb9 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -42,6 +42,8 @@ #include #include #include +#include +#include #ifndef HAVE_UINTPTR_T typedef unsigned long uintptr_t; diff --git a/module/spl/spl-condvar.c b/module/spl/spl-condvar.c index e9f727d7..6ed6579b 100644 --- a/module/spl/spl-condvar.c +++ b/module/spl/spl-condvar.c @@ -48,6 +48,7 @@ __cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg) init_waitqueue_head(&cvp->cv_event); init_waitqueue_head(&cvp->cv_destroy); atomic_set(&cvp->cv_waiters, 0); + atomic_set(&cvp->cv_refs, 1); cvp->cv_mutex = NULL; /* We may be called when there is a non-zero preempt_count or @@ -63,12 +64,13 @@ EXPORT_SYMBOL(__cv_init); static int cv_destroy_wakeup(kcondvar_t *cvp) { - if ((cvp->cv_mutex != NULL) || - (waitqueue_active(&cvp->cv_event)) || - (atomic_read(&cvp->cv_waiters) > 0)) - return 0; + if (!atomic_read(&cvp->cv_waiters) && !atomic_read(&cvp->cv_refs)) { + ASSERT(cvp->cv_mutex == NULL); + ASSERT(!waitqueue_active(&cvp->cv_event)); + return 1; + } - return 1; + return 0; } void @@ -78,11 +80,15 @@ __cv_destroy(kcondvar_t *cvp) ASSERT(cvp); ASSERT(cvp->cv_magic == CV_MAGIC); - /* Block until all waiters have woken */ + cvp->cv_magic = CV_DESTROY; + atomic_dec(&cvp->cv_refs); + + /* Block until all waiters are woken and references dropped. */ while (cv_destroy_wakeup(cvp) == 0) wait_event_timeout(cvp->cv_destroy, cv_destroy_wakeup(cvp), 1); ASSERT3P(cvp->cv_mutex, ==, NULL); + ASSERT3S(atomic_read(&cvp->cv_refs), ==, 0); ASSERT3S(atomic_read(&cvp->cv_waiters), ==, 0); ASSERT3S(waitqueue_active(&cvp->cv_event), ==, 0); @@ -100,6 +106,7 @@ cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state) ASSERT(mp); ASSERT(cvp->cv_magic == CV_MAGIC); ASSERT(mutex_owned(mp)); + atomic_inc(&cvp->cv_refs); if (cvp->cv_mutex == NULL) cvp->cv_mutex = mp; @@ -124,6 +131,7 @@ cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state) } finish_wait(&cvp->cv_event, &wait); + atomic_dec(&cvp->cv_refs); SEXIT; } @@ -157,6 +165,7 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp, ASSERT(mp); ASSERT(cvp->cv_magic == CV_MAGIC); ASSERT(mutex_owned(mp)); + atomic_inc(&cvp->cv_refs); if (cvp->cv_mutex == NULL) cvp->cv_mutex = mp; @@ -166,8 +175,10 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp, /* XXX - Does not handle jiffie wrap properly */ time_left = expire_time - jiffies; - if (time_left <= 0) + if (time_left <= 0) { + atomic_dec(&cvp->cv_refs); SRETURN(-1); + } prepare_to_wait_exclusive(&cvp->cv_event, &wait, state); atomic_inc(&cvp->cv_waiters); @@ -186,6 +197,7 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp, } finish_wait(&cvp->cv_event, &wait); + atomic_dec(&cvp->cv_refs); SRETURN(time_left > 0 ? time_left : -1); } @@ -210,6 +222,7 @@ __cv_signal(kcondvar_t *cvp) SENTRY; ASSERT(cvp); ASSERT(cvp->cv_magic == CV_MAGIC); + atomic_inc(&cvp->cv_refs); /* All waiters are added with WQ_FLAG_EXCLUSIVE so only one * waiter will be set runable with each call to wake_up(). @@ -218,6 +231,7 @@ __cv_signal(kcondvar_t *cvp) if (atomic_read(&cvp->cv_waiters) > 0) wake_up(&cvp->cv_event); + atomic_dec(&cvp->cv_refs); SEXIT; } EXPORT_SYMBOL(__cv_signal); @@ -225,15 +239,17 @@ EXPORT_SYMBOL(__cv_signal); void __cv_broadcast(kcondvar_t *cvp) { + SENTRY; ASSERT(cvp); ASSERT(cvp->cv_magic == CV_MAGIC); - SENTRY; + atomic_inc(&cvp->cv_refs); /* 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); + atomic_dec(&cvp->cv_refs); SEXIT; } EXPORT_SYMBOL(__cv_broadcast); diff --git a/module/splat/splat-atomic.c b/module/splat/splat-atomic.c index 6162d6ab..efb01578 100644 --- a/module/splat/splat-atomic.c +++ b/module/splat/splat-atomic.c @@ -24,6 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) Atomic Tests. \*****************************************************************************/ +#include +#include #include "splat-internal.h" #define SPLAT_ATOMIC_NAME "atomic" @@ -49,7 +51,7 @@ typedef enum { typedef struct atomic_priv { unsigned long ap_magic; struct file *ap_file; - spinlock_t ap_lock; + struct mutex ap_lock; wait_queue_head_t ap_waitq; volatile uint64_t ap_atomic; volatile uint64_t ap_atomic_exited; @@ -67,10 +69,10 @@ splat_atomic_work(void *priv) ap = (atomic_priv_t *)priv; ASSERT(ap->ap_magic == SPLAT_ATOMIC_TEST_MAGIC); - spin_lock(&ap->ap_lock); + mutex_lock(&ap->ap_lock); op = ap->ap_op; wake_up(&ap->ap_waitq); - spin_unlock(&ap->ap_lock); + mutex_unlock(&ap->ap_lock); splat_vprint(ap->ap_file, SPLAT_ATOMIC_TEST1_NAME, "Thread %d successfully started: %lu/%lu\n", op, @@ -140,13 +142,13 @@ splat_atomic_test1(struct file *file, void *arg) ap.ap_magic = SPLAT_ATOMIC_TEST_MAGIC; ap.ap_file = file; - spin_lock_init(&ap.ap_lock); + mutex_init(&ap.ap_lock); init_waitqueue_head(&ap.ap_waitq); ap.ap_atomic = SPLAT_ATOMIC_INIT_VALUE; ap.ap_atomic_exited = 0; for (i = 0; i < SPLAT_ATOMIC_COUNT_64; i++) { - spin_lock(&ap.ap_lock); + mutex_lock(&ap.ap_lock); ap.ap_op = i; thr = (kthread_t *)thread_create(NULL, 0, splat_atomic_work, @@ -154,14 +156,14 @@ splat_atomic_test1(struct file *file, void *arg) minclsyspri); if (thr == NULL) { rc = -ESRCH; - spin_unlock(&ap.ap_lock); + mutex_unlock(&ap.ap_lock); break; } /* Prepare to wait, the new thread will wake us once it * has made a copy of the unique private passed data */ prepare_to_wait(&ap.ap_waitq, &wait, TASK_UNINTERRUPTIBLE); - spin_unlock(&ap.ap_lock); + mutex_unlock(&ap.ap_lock); schedule(); } diff --git a/module/splat/splat-condvar.c b/module/splat/splat-condvar.c index 14000adb..69fefc95 100644 --- a/module/splat/splat-condvar.c +++ b/module/splat/splat-condvar.c @@ -24,6 +24,7 @@ * Solaris Porting LAyer Tests (SPLAT) Condition Variable Tests. \*****************************************************************************/ +#include #include "splat-internal.h" #define SPLAT_CONDVAR_NAME "condvar" diff --git a/module/splat/splat-cred.c b/module/splat/splat-cred.c index db36ece9..0efabd85 100644 --- a/module/splat/splat-cred.c +++ b/module/splat/splat-cred.c @@ -24,6 +24,7 @@ * Solaris Porting LAyer Tests (SPLAT) Credential Tests. \*****************************************************************************/ +#include #include "splat-internal.h" #define SPLAT_CRED_NAME "cred" diff --git a/module/splat/splat-ctl.c b/module/splat/splat-ctl.c index 399b09c4..c68281a8 100644 --- a/module/splat/splat-ctl.c +++ b/module/splat/splat-ctl.c @@ -43,6 +43,14 @@ * of regression tests or particular tests. \*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include #include "splat-internal.h" static spl_class *splat_class; @@ -63,7 +71,7 @@ splat_open(struct inode *inode, struct file *file) if (info == NULL) return -ENOMEM; - spin_lock_init(&info->info_lock); + mutex_init(&info->info_lock); info->info_size = SPLAT_INFO_BUFFER_SIZE; info->info_buffer = (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE); if (info->info_buffer == NULL) { @@ -92,6 +100,7 @@ splat_release(struct inode *inode, struct file *file) ASSERT(info); ASSERT(info->info_buffer); + mutex_destroy(&info->info_lock); vfree(info->info_buffer); kfree(info); @@ -106,10 +115,10 @@ splat_buffer_clear(struct file *file, splat_cfg_t *kcfg, unsigned long arg) ASSERT(info); ASSERT(info->info_buffer); - spin_lock(&info->info_lock); + mutex_lock(&info->info_lock); memset(info->info_buffer, 0, info->info_size); info->info_head = info->info_buffer; - spin_unlock(&info->info_lock); + mutex_unlock(&info->info_lock); return 0; } @@ -124,7 +133,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg) ASSERT(info); ASSERT(info->info_buffer); - spin_lock(&info->info_lock); + mutex_lock(&info->info_lock); if (kcfg->cfg_arg1 > 0) { size = kcfg->cfg_arg1; @@ -149,7 +158,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg) if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg))) rc = -EFAULT; out: - spin_unlock(&info->info_lock); + mutex_unlock(&info->info_lock); return rc; } @@ -500,7 +509,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf, ASSERT(info); ASSERT(info->info_buffer); - spin_lock(&info->info_lock); + mutex_lock(&info->info_lock); /* Write beyond EOF */ if (*ppos >= info->info_size) { @@ -520,7 +529,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf, *ppos += count; rc = count; out: - spin_unlock(&info->info_lock); + mutex_unlock(&info->info_lock); return rc; } @@ -537,7 +546,7 @@ static ssize_t splat_read(struct file *file, char __user *buf, ASSERT(info); ASSERT(info->info_buffer); - spin_lock(&info->info_lock); + mutex_lock(&info->info_lock); /* Read beyond EOF */ if (*ppos >= info->info_size) @@ -555,7 +564,7 @@ static ssize_t splat_read(struct file *file, char __user *buf, *ppos += count; rc = count; out: - spin_unlock(&info->info_lock); + mutex_unlock(&info->info_lock); return rc; } @@ -571,7 +580,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin) ASSERT(info); ASSERT(info->info_buffer); - spin_lock(&info->info_lock); + mutex_lock(&info->info_lock); switch (origin) { case 0: /* SEEK_SET - No-op just do it */ @@ -590,7 +599,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin) rc = offset; } - spin_unlock(&info->info_lock); + mutex_unlock(&info->info_lock); return rc; } diff --git a/module/splat/splat-generic.c b/module/splat/splat-generic.c index f9c3c7ec..38df14d3 100644 --- a/module/splat/splat-generic.c +++ b/module/splat/splat-generic.c @@ -24,6 +24,7 @@ * Solaris Porting LAyer Tests (SPLAT) Generic Tests. \*****************************************************************************/ +#include #include "splat-internal.h" #define SPLAT_GENERIC_NAME "generic" diff --git a/module/splat/splat-internal.h b/module/splat/splat-internal.h index 501e42c3..14303a10 100644 --- a/module/splat/splat-internal.h +++ b/module/splat/splat-internal.h @@ -25,47 +25,6 @@ #ifndef _SPLAT_INTERNAL_H #define _SPLAT_INTERNAL_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "spl-device.h" #include "spl-debug.h" #include "splat-ctl.h" @@ -162,7 +121,7 @@ typedef struct splat_subsystem { #define SPLAT_INFO_BUFFER_REDZONE 256 typedef struct splat_info { - spinlock_t info_lock; + struct mutex info_lock; int info_size; char *info_buffer; char *info_head; /* Internal kernel use only */ @@ -177,7 +136,7 @@ typedef struct splat_info { ASSERT(_info_); \ ASSERT(_info_->info_buffer); \ \ - spin_lock(&_info_->info_lock); \ + mutex_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) > \ @@ -189,7 +148,7 @@ typedef struct splat_info { _info_->info_head += _rc_; \ } \ \ - spin_unlock(&_info_->info_lock); \ + mutex_unlock(&_info_->info_lock); \ _rc_; \ }) diff --git a/module/splat/splat-kmem.c b/module/splat/splat-kmem.c index d0ad9a66..30750aa0 100644 --- a/module/splat/splat-kmem.c +++ b/module/splat/splat-kmem.c @@ -24,6 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) Kmem Tests. \*****************************************************************************/ +#include +#include #include "splat-internal.h" #define SPLAT_KMEM_NAME "kmem" @@ -69,11 +71,11 @@ #define SPLAT_KMEM_TEST10_NAME "slab_lock" #define SPLAT_KMEM_TEST10_DESC "Slab locking test" -#ifdef _LP64 +#if 0 #define SPLAT_KMEM_TEST11_ID 0x010b #define SPLAT_KMEM_TEST11_NAME "slab_overcommit" #define SPLAT_KMEM_TEST11_DESC "Slab memory overcommit test" -#endif /* _LP64 */ +#endif #define SPLAT_KMEM_TEST12_ID 0x010c #define SPLAT_KMEM_TEST12_NAME "vmem_size" @@ -1006,7 +1008,7 @@ splat_kmem_test10(struct file *file, void *arg) return rc; } -#ifdef _LP64 +#if 0 /* * This test creates N threads with a shared kmem cache which overcommits * memory by 4x. This makes it impossible for the slab to satify the @@ -1037,7 +1039,7 @@ splat_kmem_test11(struct file *file, void *arg) return rc; } -#endif /* _LP64 */ +#endif /* * Check vmem_size() behavior by acquiring the alloc/free/total vmem @@ -1290,10 +1292,10 @@ splat_kmem_init(void) SPLAT_KMEM_TEST9_ID, splat_kmem_test9); SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST10_NAME, SPLAT_KMEM_TEST10_DESC, SPLAT_KMEM_TEST10_ID, splat_kmem_test10); -#ifdef _LP64 +#if 0 SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST11_NAME, SPLAT_KMEM_TEST11_DESC, SPLAT_KMEM_TEST11_ID, splat_kmem_test11); -#endif /* _LP64 */ +#endif SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST12_NAME, SPLAT_KMEM_TEST12_DESC, SPLAT_KMEM_TEST12_ID, splat_kmem_test12); SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST13_NAME, SPLAT_KMEM_TEST13_DESC, @@ -1308,9 +1310,9 @@ splat_kmem_fini(splat_subsystem_t *sub) ASSERT(sub); SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST13_ID); SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST12_ID); -#ifdef _LP64 +#if 0 SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST11_ID); -#endif /* _LP64 */ +#endif SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST10_ID); SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST9_ID); SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST8_ID); diff --git a/module/splat/splat-kobj.c b/module/splat/splat-kobj.c index f0720dbf..c7679541 100644 --- a/module/splat/splat-kobj.c +++ b/module/splat/splat-kobj.c @@ -24,6 +24,7 @@ * Solaris Porting LAyer Tests (SPLAT) Kobj Tests. \*****************************************************************************/ +#include #include "splat-internal.h" #define SPLAT_KOBJ_NAME "kobj" diff --git a/module/splat/splat-linux.c b/module/splat/splat-linux.c index 07126411..5303df4e 100644 --- a/module/splat/splat-linux.c +++ b/module/splat/splat-linux.c @@ -23,6 +23,7 @@ * Solaris Porting LAyer Tests (SPLAT) Kernel Compatibility Tests. \*****************************************************************************/ +#include #include "splat-internal.h" #define SPLAT_LINUX_NAME "linux" diff --git a/module/splat/splat-list.c b/module/splat/splat-list.c index d517e7d2..34b570f3 100644 --- a/module/splat/splat-list.c +++ b/module/splat/splat-list.c @@ -24,6 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) List Tests. \*****************************************************************************/ +#include +#include #include "splat-internal.h" #define SPLAT_LIST_NAME "list" diff --git a/module/splat/splat-mutex.c b/module/splat/splat-mutex.c index d134e49c..9e6b2470 100644 --- a/module/splat/splat-mutex.c +++ b/module/splat/splat-mutex.c @@ -24,6 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) Mutex Tests. \*****************************************************************************/ +#include +#include #include "splat-internal.h" #define SPLAT_MUTEX_NAME "mutex" diff --git a/module/splat/splat-random.c b/module/splat/splat-random.c index 3ee580df..63d96444 100644 --- a/module/splat/splat-random.c +++ b/module/splat/splat-random.c @@ -24,6 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) Random Number Generator Tests. \*****************************************************************************/ +#include +#include #include "splat-internal.h" #define SPLAT_KRNG_NAME "krng" diff --git a/module/splat/splat-rwlock.c b/module/splat/splat-rwlock.c index 2b9dee93..9e335d75 100644 --- a/module/splat/splat-rwlock.c +++ b/module/splat/splat-rwlock.c @@ -24,6 +24,9 @@ * Solaris Porting LAyer Tests (SPLAT) Read/Writer Lock Tests. \*****************************************************************************/ +#include +#include +#include #include "splat-internal.h" #define SPLAT_RWLOCK_NAME "rwlock" diff --git a/module/splat/splat-taskq.c b/module/splat/splat-taskq.c index 73142f9b..38b563cc 100644 --- a/module/splat/splat-taskq.c +++ b/module/splat/splat-taskq.c @@ -24,6 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) Task Queue Tests. \*****************************************************************************/ +#include +#include #include "splat-internal.h" #define SPLAT_TASKQ_NAME "taskq" diff --git a/module/splat/splat-thread.c b/module/splat/splat-thread.c index 0f504836..c54cbcd8 100644 --- a/module/splat/splat-thread.c +++ b/module/splat/splat-thread.c @@ -24,6 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) Thread Tests. \*****************************************************************************/ +#include +#include #include "splat-internal.h" #define SPLAT_THREAD_NAME "thread" diff --git a/module/splat/splat-time.c b/module/splat/splat-time.c index 3b06b9ef..e6f8dc68 100644 --- a/module/splat/splat-time.c +++ b/module/splat/splat-time.c @@ -24,6 +24,7 @@ * Solaris Porting LAyer Tests (SPLAT) Time Tests. \*****************************************************************************/ +#include #include "splat-internal.h" #define SPLAT_TIME_NAME "time" diff --git a/module/splat/splat-vnode.c b/module/splat/splat-vnode.c index a57edf0d..7d1c75f1 100644 --- a/module/splat/splat-vnode.c +++ b/module/splat/splat-vnode.c @@ -24,8 +24,8 @@ * Solaris Porting LAyer Tests (SPLAT) Vnode Tests. \*****************************************************************************/ +#include #include "splat-internal.h" -#include #define SPLAT_VNODE_NAME "vnode" #define SPLAT_VNODE_DESC "Kernel Vnode Tests" diff --git a/module/splat/splat-zlib.c b/module/splat/splat-zlib.c index 465d3409..852cf818 100644 --- a/module/splat/splat-zlib.c +++ b/module/splat/splat-zlib.c @@ -24,6 +24,9 @@ * Solaris Porting LAyer Tests (SPLAT) Zlib Compression Tests. \*****************************************************************************/ +#include +#include +#include #include "splat-internal.h" #define SPLAT_ZLIB_NAME "zlib"