Linux compat 3.7, kernel_thread()
The preferred kernel interface for creating threads has been kthread_create() for a long time now. However, several of the SPLAT tests still use the legacy kernel_thread() function which has finally been dropped (mostly). Update the condvar and rwlock SPLAT tests to use the modern interface. Frankly this is something we should have done a long time ago. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #194
This commit is contained in:
parent
251677e98f
commit
b84412a6e8
|
@ -24,6 +24,7 @@
|
||||||
* Solaris Porting LAyer Tests (SPLAT) Condition Variable Tests.
|
* Solaris Porting LAyer Tests (SPLAT) Condition Variable Tests.
|
||||||
\*****************************************************************************/
|
\*****************************************************************************/
|
||||||
|
|
||||||
|
#include <linux/kthread.h>
|
||||||
#include <sys/condvar.h>
|
#include <sys/condvar.h>
|
||||||
#include "splat-internal.h"
|
#include "splat-internal.h"
|
||||||
|
|
||||||
|
@ -51,20 +52,20 @@
|
||||||
#define SPLAT_CONDVAR_TEST5_DESC "Timeout thread, cv_wait_timeout()"
|
#define SPLAT_CONDVAR_TEST5_DESC "Timeout thread, cv_wait_timeout()"
|
||||||
|
|
||||||
#define SPLAT_CONDVAR_TEST_MAGIC 0x115599DDUL
|
#define SPLAT_CONDVAR_TEST_MAGIC 0x115599DDUL
|
||||||
#define SPLAT_CONDVAR_TEST_NAME "condvar_test"
|
#define SPLAT_CONDVAR_TEST_NAME "condvar"
|
||||||
#define SPLAT_CONDVAR_TEST_COUNT 8
|
#define SPLAT_CONDVAR_TEST_COUNT 8
|
||||||
|
|
||||||
typedef struct condvar_priv {
|
typedef struct condvar_priv {
|
||||||
unsigned long cv_magic;
|
unsigned long cv_magic;
|
||||||
struct file *cv_file;
|
struct file *cv_file;
|
||||||
kcondvar_t cv_condvar;
|
kcondvar_t cv_condvar;
|
||||||
kmutex_t cv_mtx;
|
kmutex_t cv_mtx;
|
||||||
} condvar_priv_t;
|
} condvar_priv_t;
|
||||||
|
|
||||||
typedef struct condvar_thr {
|
typedef struct condvar_thr {
|
||||||
int ct_id;
|
|
||||||
const char *ct_name;
|
const char *ct_name;
|
||||||
condvar_priv_t *ct_cvp;
|
condvar_priv_t *ct_cvp;
|
||||||
|
struct task_struct *ct_thread;
|
||||||
int ct_rc;
|
int ct_rc;
|
||||||
} condvar_thr_t;
|
} condvar_thr_t;
|
||||||
|
|
||||||
|
@ -73,20 +74,17 @@ splat_condvar_test12_thread(void *arg)
|
||||||
{
|
{
|
||||||
condvar_thr_t *ct = (condvar_thr_t *)arg;
|
condvar_thr_t *ct = (condvar_thr_t *)arg;
|
||||||
condvar_priv_t *cv = ct->ct_cvp;
|
condvar_priv_t *cv = ct->ct_cvp;
|
||||||
char name[16];
|
|
||||||
|
|
||||||
ASSERT(cv->cv_magic == SPLAT_CONDVAR_TEST_MAGIC);
|
ASSERT(cv->cv_magic == SPLAT_CONDVAR_TEST_MAGIC);
|
||||||
snprintf(name, sizeof(name),"%s%d",SPLAT_CONDVAR_TEST_NAME,ct->ct_id);
|
|
||||||
daemonize(name);
|
|
||||||
|
|
||||||
mutex_enter(&cv->cv_mtx);
|
mutex_enter(&cv->cv_mtx);
|
||||||
splat_vprint(cv->cv_file, ct->ct_name,
|
splat_vprint(cv->cv_file, ct->ct_name,
|
||||||
"%s thread sleeping with %d waiters\n",
|
"%s thread sleeping with %d waiters\n",
|
||||||
name, atomic_read(&cv->cv_condvar.cv_waiters));
|
ct->ct_thread->comm, atomic_read(&cv->cv_condvar.cv_waiters));
|
||||||
cv_wait(&cv->cv_condvar, &cv->cv_mtx);
|
cv_wait(&cv->cv_condvar, &cv->cv_mtx);
|
||||||
splat_vprint(cv->cv_file, ct->ct_name,
|
splat_vprint(cv->cv_file, ct->ct_name,
|
||||||
"%s thread woken %d waiters remain\n",
|
"%s thread woken %d waiters remain\n",
|
||||||
name, atomic_read(&cv->cv_condvar.cv_waiters));
|
ct->ct_thread->comm, atomic_read(&cv->cv_condvar.cv_waiters));
|
||||||
mutex_exit(&cv->cv_mtx);
|
mutex_exit(&cv->cv_mtx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -96,7 +94,6 @@ static int
|
||||||
splat_condvar_test1(struct file *file, void *arg)
|
splat_condvar_test1(struct file *file, void *arg)
|
||||||
{
|
{
|
||||||
int i, count = 0, rc = 0;
|
int i, count = 0, rc = 0;
|
||||||
long pids[SPLAT_CONDVAR_TEST_COUNT];
|
|
||||||
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
||||||
condvar_priv_t cv;
|
condvar_priv_t cv;
|
||||||
|
|
||||||
|
@ -109,13 +106,15 @@ splat_condvar_test1(struct file *file, void *arg)
|
||||||
* long as we know how many we managed to create and should expect. */
|
* long as we know how many we managed to create and should expect. */
|
||||||
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
||||||
ct[i].ct_cvp = &cv;
|
ct[i].ct_cvp = &cv;
|
||||||
ct[i].ct_id = i;
|
|
||||||
ct[i].ct_name = SPLAT_CONDVAR_TEST1_NAME;
|
ct[i].ct_name = SPLAT_CONDVAR_TEST1_NAME;
|
||||||
ct[i].ct_rc = 0;
|
ct[i].ct_rc = 0;
|
||||||
|
ct[i].ct_thread = kthread_create(splat_condvar_test12_thread,
|
||||||
|
&ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
|
||||||
|
|
||||||
pids[i] = kernel_thread(splat_condvar_test12_thread, &ct[i], 0);
|
if (!IS_ERR(ct[i].ct_thread)) {
|
||||||
if (pids[i] >= 0)
|
wake_up_process(ct[i].ct_thread);
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until all threads are waiting on the condition variable */
|
/* Wait until all threads are waiting on the condition variable */
|
||||||
|
@ -160,7 +159,6 @@ static int
|
||||||
splat_condvar_test2(struct file *file, void *arg)
|
splat_condvar_test2(struct file *file, void *arg)
|
||||||
{
|
{
|
||||||
int i, count = 0, rc = 0;
|
int i, count = 0, rc = 0;
|
||||||
long pids[SPLAT_CONDVAR_TEST_COUNT];
|
|
||||||
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
||||||
condvar_priv_t cv;
|
condvar_priv_t cv;
|
||||||
|
|
||||||
|
@ -173,13 +171,15 @@ splat_condvar_test2(struct file *file, void *arg)
|
||||||
* long as we know how many we managed to create and should expect. */
|
* long as we know how many we managed to create and should expect. */
|
||||||
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
||||||
ct[i].ct_cvp = &cv;
|
ct[i].ct_cvp = &cv;
|
||||||
ct[i].ct_id = i;
|
|
||||||
ct[i].ct_name = SPLAT_CONDVAR_TEST2_NAME;
|
ct[i].ct_name = SPLAT_CONDVAR_TEST2_NAME;
|
||||||
ct[i].ct_rc = 0;
|
ct[i].ct_rc = 0;
|
||||||
|
ct[i].ct_thread = kthread_create(splat_condvar_test12_thread,
|
||||||
|
&ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
|
||||||
|
|
||||||
pids[i] = kernel_thread(splat_condvar_test12_thread, &ct[i], 0);
|
if (!IS_ERR(ct[i].ct_thread)) {
|
||||||
if (pids[i] > 0)
|
wake_up_process(ct[i].ct_thread);
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until all threads are waiting on the condition variable */
|
/* Wait until all threads are waiting on the condition variable */
|
||||||
|
@ -208,17 +208,14 @@ splat_condvar_test34_thread(void *arg)
|
||||||
{
|
{
|
||||||
condvar_thr_t *ct = (condvar_thr_t *)arg;
|
condvar_thr_t *ct = (condvar_thr_t *)arg;
|
||||||
condvar_priv_t *cv = ct->ct_cvp;
|
condvar_priv_t *cv = ct->ct_cvp;
|
||||||
char name[16];
|
|
||||||
clock_t rc;
|
clock_t rc;
|
||||||
|
|
||||||
ASSERT(cv->cv_magic == SPLAT_CONDVAR_TEST_MAGIC);
|
ASSERT(cv->cv_magic == SPLAT_CONDVAR_TEST_MAGIC);
|
||||||
snprintf(name, sizeof(name), "%s%d", SPLAT_CONDVAR_TEST_NAME, ct->ct_id);
|
|
||||||
daemonize(name);
|
|
||||||
|
|
||||||
mutex_enter(&cv->cv_mtx);
|
mutex_enter(&cv->cv_mtx);
|
||||||
splat_vprint(cv->cv_file, ct->ct_name,
|
splat_vprint(cv->cv_file, ct->ct_name,
|
||||||
"%s thread sleeping with %d waiters\n",
|
"%s thread sleeping with %d waiters\n",
|
||||||
name, atomic_read(&cv->cv_condvar.cv_waiters));
|
ct->ct_thread->comm, atomic_read(&cv->cv_condvar.cv_waiters));
|
||||||
|
|
||||||
/* Sleep no longer than 3 seconds, for this test we should
|
/* Sleep no longer than 3 seconds, for this test we should
|
||||||
* actually never sleep that long without being woken up. */
|
* actually never sleep that long without being woken up. */
|
||||||
|
@ -226,11 +223,12 @@ splat_condvar_test34_thread(void *arg)
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
ct->ct_rc = -ETIMEDOUT;
|
ct->ct_rc = -ETIMEDOUT;
|
||||||
splat_vprint(cv->cv_file, ct->ct_name, "%s thread timed out, "
|
splat_vprint(cv->cv_file, ct->ct_name, "%s thread timed out, "
|
||||||
"should have been woken\n", name);
|
"should have been woken\n", ct->ct_thread->comm);
|
||||||
} else {
|
} else {
|
||||||
splat_vprint(cv->cv_file, ct->ct_name,
|
splat_vprint(cv->cv_file, ct->ct_name,
|
||||||
"%s thread woken %d waiters remain\n",
|
"%s thread woken %d waiters remain\n",
|
||||||
name, atomic_read(&cv->cv_condvar.cv_waiters));
|
ct->ct_thread->comm,
|
||||||
|
atomic_read(&cv->cv_condvar.cv_waiters));
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_exit(&cv->cv_mtx);
|
mutex_exit(&cv->cv_mtx);
|
||||||
|
@ -242,7 +240,6 @@ static int
|
||||||
splat_condvar_test3(struct file *file, void *arg)
|
splat_condvar_test3(struct file *file, void *arg)
|
||||||
{
|
{
|
||||||
int i, count = 0, rc = 0;
|
int i, count = 0, rc = 0;
|
||||||
long pids[SPLAT_CONDVAR_TEST_COUNT];
|
|
||||||
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
||||||
condvar_priv_t cv;
|
condvar_priv_t cv;
|
||||||
|
|
||||||
|
@ -255,13 +252,15 @@ splat_condvar_test3(struct file *file, void *arg)
|
||||||
* long as we know how many we managed to create and should expect. */
|
* long as we know how many we managed to create and should expect. */
|
||||||
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
||||||
ct[i].ct_cvp = &cv;
|
ct[i].ct_cvp = &cv;
|
||||||
ct[i].ct_id = i;
|
|
||||||
ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME;
|
ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME;
|
||||||
ct[i].ct_rc = 0;
|
ct[i].ct_rc = 0;
|
||||||
|
ct[i].ct_thread = kthread_create(splat_condvar_test34_thread,
|
||||||
|
&ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
|
||||||
|
|
||||||
pids[i] = kernel_thread(splat_condvar_test34_thread, &ct[i], 0);
|
if (!IS_ERR(ct[i].ct_thread)) {
|
||||||
if (pids[i] >= 0)
|
wake_up_process(ct[i].ct_thread);
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until all threads are waiting on the condition variable */
|
/* Wait until all threads are waiting on the condition variable */
|
||||||
|
@ -311,7 +310,6 @@ static int
|
||||||
splat_condvar_test4(struct file *file, void *arg)
|
splat_condvar_test4(struct file *file, void *arg)
|
||||||
{
|
{
|
||||||
int i, count = 0, rc = 0;
|
int i, count = 0, rc = 0;
|
||||||
long pids[SPLAT_CONDVAR_TEST_COUNT];
|
|
||||||
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
condvar_thr_t ct[SPLAT_CONDVAR_TEST_COUNT];
|
||||||
condvar_priv_t cv;
|
condvar_priv_t cv;
|
||||||
|
|
||||||
|
@ -324,13 +322,15 @@ splat_condvar_test4(struct file *file, void *arg)
|
||||||
* long as we know how many we managed to create and should expect. */
|
* long as we know how many we managed to create and should expect. */
|
||||||
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
for (i = 0; i < SPLAT_CONDVAR_TEST_COUNT; i++) {
|
||||||
ct[i].ct_cvp = &cv;
|
ct[i].ct_cvp = &cv;
|
||||||
ct[i].ct_id = i;
|
|
||||||
ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME;
|
ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME;
|
||||||
ct[i].ct_rc = 0;
|
ct[i].ct_rc = 0;
|
||||||
|
ct[i].ct_thread = kthread_create(splat_condvar_test34_thread,
|
||||||
|
&ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i);
|
||||||
|
|
||||||
pids[i] = kernel_thread(splat_condvar_test34_thread, &ct[i], 0);
|
if (!IS_ERR(ct[i].ct_thread)) {
|
||||||
if (pids[i] >= 0)
|
wake_up_process(ct[i].ct_thread);
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until all threads are waiting on the condition variable */
|
/* Wait until all threads are waiting on the condition variable */
|
||||||
|
|
|
@ -82,7 +82,7 @@ typedef struct rw_priv {
|
||||||
typedef struct rw_thr {
|
typedef struct rw_thr {
|
||||||
const char *rwt_name;
|
const char *rwt_name;
|
||||||
rw_priv_t *rwt_rwp;
|
rw_priv_t *rwt_rwp;
|
||||||
int rwt_id;
|
struct task_struct *rwt_thread;
|
||||||
} rw_thr_t;
|
} rw_thr_t;
|
||||||
|
|
||||||
void splat_init_rw_priv(rw_priv_t *rwp, struct file *file)
|
void splat_init_rw_priv(rw_priv_t *rwp, struct file *file)
|
||||||
|
@ -106,17 +106,15 @@ splat_rwlock_wr_thr(void *arg)
|
||||||
rw_thr_t *rwt = (rw_thr_t *)arg;
|
rw_thr_t *rwt = (rw_thr_t *)arg;
|
||||||
rw_priv_t *rwp = rwt->rwt_rwp;
|
rw_priv_t *rwp = rwt->rwt_rwp;
|
||||||
uint8_t rnd;
|
uint8_t rnd;
|
||||||
char name[16];
|
|
||||||
|
|
||||||
ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
|
ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
|
||||||
snprintf(name, sizeof(name), "rwlock_wr_thr%d", rwt->rwt_id);
|
|
||||||
daemonize(name);
|
|
||||||
get_random_bytes((void *)&rnd, 1);
|
get_random_bytes((void *)&rnd, 1);
|
||||||
msleep((unsigned int)rnd);
|
msleep((unsigned int)rnd);
|
||||||
|
|
||||||
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
||||||
"%s trying to acquire rwlock (%d holding/%d waiting)\n",
|
"%s trying to acquire rwlock (%d holding/%d waiting)\n",
|
||||||
name, rwp->rw_holders, rwp->rw_waiters);
|
rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
|
||||||
spin_lock(&rwp->rw_lock);
|
spin_lock(&rwp->rw_lock);
|
||||||
rwp->rw_waiters++;
|
rwp->rw_waiters++;
|
||||||
spin_unlock(&rwp->rw_lock);
|
spin_unlock(&rwp->rw_lock);
|
||||||
|
@ -127,20 +125,20 @@ splat_rwlock_wr_thr(void *arg)
|
||||||
rwp->rw_holders++;
|
rwp->rw_holders++;
|
||||||
spin_unlock(&rwp->rw_lock);
|
spin_unlock(&rwp->rw_lock);
|
||||||
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
||||||
"%s acquired rwlock (%d holding/%d waiting)\n",
|
"%s acquired rwlock (%d holding/%d waiting)\n",
|
||||||
name, rwp->rw_holders, rwp->rw_waiters);
|
rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
|
||||||
|
|
||||||
/* Wait for control thread to signal we can release the write lock */
|
/* Wait for control thread to signal we can release the write lock */
|
||||||
wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
|
wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
|
||||||
rwp->rw_release == SPLAT_RWLOCK_RELEASE_WR));
|
rwp->rw_release == SPLAT_RWLOCK_RELEASE_WR));
|
||||||
|
|
||||||
spin_lock(&rwp->rw_lock);
|
spin_lock(&rwp->rw_lock);
|
||||||
rwp->rw_completed++;
|
rwp->rw_completed++;
|
||||||
rwp->rw_holders--;
|
rwp->rw_holders--;
|
||||||
spin_unlock(&rwp->rw_lock);
|
spin_unlock(&rwp->rw_lock);
|
||||||
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
||||||
"%s dropped rwlock (%d holding/%d waiting)\n",
|
"%s dropped rwlock (%d holding/%d waiting)\n",
|
||||||
name, rwp->rw_holders, rwp->rw_waiters);
|
rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
|
||||||
|
|
||||||
rw_exit(&rwp->rw_rwlock);
|
rw_exit(&rwp->rw_rwlock);
|
||||||
|
|
||||||
|
@ -153,21 +151,19 @@ splat_rwlock_rd_thr(void *arg)
|
||||||
rw_thr_t *rwt = (rw_thr_t *)arg;
|
rw_thr_t *rwt = (rw_thr_t *)arg;
|
||||||
rw_priv_t *rwp = rwt->rwt_rwp;
|
rw_priv_t *rwp = rwt->rwt_rwp;
|
||||||
uint8_t rnd;
|
uint8_t rnd;
|
||||||
char name[16];
|
|
||||||
|
|
||||||
ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
|
ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
|
||||||
snprintf(name, sizeof(name), "rwlock_rd_thr%d", rwt->rwt_id);
|
|
||||||
daemonize(name);
|
|
||||||
get_random_bytes((void *)&rnd, 1);
|
get_random_bytes((void *)&rnd, 1);
|
||||||
msleep((unsigned int)rnd);
|
msleep((unsigned int)rnd);
|
||||||
|
|
||||||
/* Don't try and take the semaphore until after someone has it */
|
/* Don't try and take the semaphore until after someone has it */
|
||||||
wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
|
wait_event_interruptible(rwp->rw_waitq,
|
||||||
rwp->rw_holders > 0));
|
splat_locked_test(&rwp->rw_lock, rwp->rw_holders > 0));
|
||||||
|
|
||||||
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
||||||
"%s trying to acquire rwlock (%d holding/%d waiting)\n",
|
"%s trying to acquire rwlock (%d holding/%d waiting)\n",
|
||||||
name, rwp->rw_holders, rwp->rw_waiters);
|
rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
|
||||||
spin_lock(&rwp->rw_lock);
|
spin_lock(&rwp->rw_lock);
|
||||||
rwp->rw_waiters++;
|
rwp->rw_waiters++;
|
||||||
spin_unlock(&rwp->rw_lock);
|
spin_unlock(&rwp->rw_lock);
|
||||||
|
@ -178,20 +174,20 @@ splat_rwlock_rd_thr(void *arg)
|
||||||
rwp->rw_holders++;
|
rwp->rw_holders++;
|
||||||
spin_unlock(&rwp->rw_lock);
|
spin_unlock(&rwp->rw_lock);
|
||||||
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
||||||
"%s acquired rwlock (%d holding/%d waiting)\n",
|
"%s acquired rwlock (%d holding/%d waiting)\n",
|
||||||
name, rwp->rw_holders, rwp->rw_waiters);
|
rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
|
||||||
|
|
||||||
/* Wait for control thread to signal we can release the read lock */
|
/* Wait for control thread to signal we can release the read lock */
|
||||||
wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
|
wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
|
||||||
rwp->rw_release == SPLAT_RWLOCK_RELEASE_RD));
|
rwp->rw_release == SPLAT_RWLOCK_RELEASE_RD));
|
||||||
|
|
||||||
spin_lock(&rwp->rw_lock);
|
spin_lock(&rwp->rw_lock);
|
||||||
rwp->rw_completed++;
|
rwp->rw_completed++;
|
||||||
rwp->rw_holders--;
|
rwp->rw_holders--;
|
||||||
spin_unlock(&rwp->rw_lock);
|
spin_unlock(&rwp->rw_lock);
|
||||||
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
splat_vprint(rwp->rw_file, rwt->rwt_name,
|
||||||
"%s dropped rwlock (%d holding/%d waiting)\n",
|
"%s dropped rwlock (%d holding/%d waiting)\n",
|
||||||
name, rwp->rw_holders, rwp->rw_waiters);
|
rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
|
||||||
|
|
||||||
rw_exit(&rwp->rw_rwlock);
|
rw_exit(&rwp->rw_rwlock);
|
||||||
|
|
||||||
|
@ -202,7 +198,6 @@ static int
|
||||||
splat_rwlock_test1(struct file *file, void *arg)
|
splat_rwlock_test1(struct file *file, void *arg)
|
||||||
{
|
{
|
||||||
int i, count = 0, rc = 0;
|
int i, count = 0, rc = 0;
|
||||||
long pids[SPLAT_RWLOCK_TEST_COUNT];
|
|
||||||
rw_thr_t rwt[SPLAT_RWLOCK_TEST_COUNT];
|
rw_thr_t rwt[SPLAT_RWLOCK_TEST_COUNT];
|
||||||
rw_priv_t *rwp;
|
rw_priv_t *rwp;
|
||||||
|
|
||||||
|
@ -214,22 +209,22 @@ splat_rwlock_test1(struct file *file, void *arg)
|
||||||
|
|
||||||
/* Create some threads, the exact number isn't important just as
|
/* Create some threads, the exact number isn't important just as
|
||||||
* long as we know how many we managed to create and should expect. */
|
* long as we know how many we managed to create and should expect. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < SPLAT_RWLOCK_TEST_COUNT; i++) {
|
for (i = 0; i < SPLAT_RWLOCK_TEST_COUNT; i++) {
|
||||||
rwt[i].rwt_rwp = rwp;
|
rwt[i].rwt_rwp = rwp;
|
||||||
rwt[i].rwt_id = i;
|
|
||||||
rwt[i].rwt_name = SPLAT_RWLOCK_TEST1_NAME;
|
rwt[i].rwt_name = SPLAT_RWLOCK_TEST1_NAME;
|
||||||
|
|
||||||
/* The first thread will be the writer */
|
/* The first thread will be the writer */
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
pids[i] = kernel_thread(splat_rwlock_wr_thr, &rwt[i], 0);
|
rwt[i].rwt_thread = kthread_create(splat_rwlock_wr_thr,
|
||||||
|
&rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i);
|
||||||
else
|
else
|
||||||
pids[i] = kernel_thread(splat_rwlock_rd_thr, &rwt[i], 0);
|
rwt[i].rwt_thread = kthread_create(splat_rwlock_rd_thr,
|
||||||
|
&rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i);
|
||||||
|
|
||||||
if (pids[i] >= 0)
|
if (!IS_ERR(rwt[i].rwt_thread)) {
|
||||||
|
wake_up_process(rwt[i].rwt_thread);
|
||||||
count++;
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the writer */
|
/* Wait for the writer */
|
||||||
|
|
Loading…
Reference in New Issue