Add 'feature-pthreads' branch to features branch.

This commit is contained in:
Brian Behlendorf 2009-03-19 20:49:52 -07:00
parent 29703a5b4e
commit 54b5b41a58
9 changed files with 236 additions and 168 deletions

View File

@ -1 +1 @@
master
feature-commit-cb

View File

@ -1,8 +1,9 @@
From: Brian Behlendorf <behlendorf1@llnl.gov>
Subject: [PATCH] feature commit cb
Subject: [PATCH] feature pthreads
DMU commit callbacks. Provides an API to attach callbacks to transactions,
which are called by the DMU when they are safely committed to disk.
See Lustre bug 14117 for details.
This converts the userspace code to use the POSIX threads API instead of
the Solaris-only threads API. The API is almost identical and POSIX
threads are a standard, so this is also a no-brainer and it's also
going upstream.
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>

View File

@ -52,7 +52,6 @@
#include <sys/zfs_fuid.h>
#include <sys/arc.h>
#undef ZFS_MAXNAMELEN
#undef verify
#include <libzfs.h>
const char cmdname[] = "zdb";

View File

@ -25,8 +25,6 @@
#include <libzfs.h>
#undef verify /* both libzfs.h and zfs_context.h want to define this */
#include <sys/zfs_context.h>
#include <errno.h>

View File

@ -138,7 +138,7 @@ typedef struct ztest_args {
spa_t *za_spa;
objset_t *za_os;
zilog_t *za_zilog;
thread_t za_thread;
pthread_t za_thread;
uint64_t za_instance;
uint64_t za_random;
uint64_t za_diroff;
@ -225,27 +225,27 @@ ztest_info_t ztest_info[] = {
* The callbacks are ordered by txg number.
*/
typedef struct ztest_cb_list {
mutex_t zcl_callbacks_lock;
list_t zcl_callbacks;
pthread_mutex_t zcl_callbacks_lock;
list_t zcl_callbacks;
} ztest_cb_list_t;
/*
* Stuff we need to share writably between parent and child.
*/
typedef struct ztest_shared {
mutex_t zs_vdev_lock;
rwlock_t zs_name_lock;
uint64_t zs_vdev_primaries;
uint64_t zs_vdev_aux;
uint64_t zs_enospc_count;
hrtime_t zs_start_time;
hrtime_t zs_stop_time;
uint64_t zs_alloc;
uint64_t zs_space;
ztest_info_t zs_info[ZTEST_FUNCS];
mutex_t zs_sync_lock[ZTEST_SYNC_LOCKS];
uint64_t zs_seq[ZTEST_SYNC_LOCKS];
ztest_cb_list_t zs_cb_list;
pthread_mutex_t zs_vdev_lock;
pthread_rwlock_t zs_name_lock;
uint64_t zs_vdev_primaries;
uint64_t zs_vdev_aux;
uint64_t zs_enospc_count;
hrtime_t zs_start_time;
hrtime_t zs_stop_time;
uint64_t zs_alloc;
uint64_t zs_space;
ztest_info_t zs_info[ZTEST_FUNCS];
pthread_mutex_t zs_sync_lock[ZTEST_SYNC_LOCKS];
uint64_t zs_seq[ZTEST_SYNC_LOCKS];
ztest_cb_list_t zs_cb_list;
} ztest_shared_t;
static char ztest_dev_template[] = "%s/%s.%llua";
@ -817,7 +817,7 @@ ztest_spa_create_destroy(ztest_args_t *za)
* Attempt to create an existing pool. It shouldn't matter
* what's in the nvroot; we should fail with EEXIST.
*/
(void) rw_rdlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_rdlock(&ztest_shared->zs_name_lock);
nvroot = make_vdev_root("/dev/bogus", NULL, 0, 0, 0, 0, 0, 1);
error = spa_create(za->za_pool, nvroot, NULL, NULL, NULL);
nvlist_free(nvroot);
@ -833,7 +833,7 @@ ztest_spa_create_destroy(ztest_args_t *za)
fatal(0, "spa_destroy() = %d", error);
spa_close(spa, FTAG);
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
}
static vdev_t *
@ -863,7 +863,7 @@ ztest_vdev_add_remove(ztest_args_t *za)
nvlist_t *nvroot;
int error;
(void) mutex_lock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_lock(&ztest_shared->zs_vdev_lock);
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
@ -881,7 +881,7 @@ ztest_vdev_add_remove(ztest_args_t *za)
error = spa_vdev_add(spa, nvroot);
nvlist_free(nvroot);
(void) mutex_unlock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_unlock(&ztest_shared->zs_vdev_lock);
if (error == ENOSPC)
ztest_record_enospc("spa_vdev_add");
@ -910,7 +910,7 @@ ztest_vdev_aux_add_remove(ztest_args_t *za)
aux = ZPOOL_CONFIG_L2CACHE;
}
(void) mutex_lock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_lock(&ztest_shared->zs_vdev_lock);
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
@ -966,7 +966,7 @@ ztest_vdev_aux_add_remove(ztest_args_t *za)
fatal(0, "spa_vdev_remove(%llu) = %d", guid, error);
}
(void) mutex_unlock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_unlock(&ztest_shared->zs_vdev_lock);
}
/*
@ -992,7 +992,7 @@ ztest_vdev_attach_detach(ztest_args_t *za)
int oldvd_is_log;
int error, expected_error;
(void) mutex_lock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_lock(&ztest_shared->zs_vdev_lock);
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
@ -1052,7 +1052,7 @@ ztest_vdev_attach_detach(ztest_args_t *za)
if (error != 0 && error != ENODEV && error != EBUSY &&
error != ENOTSUP)
fatal(0, "detach (%s) returned %d", oldpath, error);
(void) mutex_unlock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_unlock(&ztest_shared->zs_vdev_lock);
return;
}
@ -1145,7 +1145,7 @@ ztest_vdev_attach_detach(ztest_args_t *za)
(longlong_t)newsize, replacing, error, expected_error);
}
(void) mutex_unlock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_unlock(&ztest_shared->zs_vdev_lock);
}
/*
@ -1161,7 +1161,7 @@ ztest_vdev_LUN_growth(ztest_args_t *za)
size_t fsize;
int fd;
(void) mutex_lock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_lock(&ztest_shared->zs_vdev_lock);
/*
* Pick a random leaf vdev.
@ -1192,7 +1192,7 @@ ztest_vdev_LUN_growth(ztest_args_t *za)
(void) close(fd);
}
(void) mutex_unlock(&ztest_shared->zs_vdev_lock);
(void) pthread_mutex_unlock(&ztest_shared->zs_vdev_lock);
}
/* ARGSUSED */
@ -1291,7 +1291,7 @@ ztest_dmu_objset_create_destroy(ztest_args_t *za)
uint64_t seq;
uint64_t objects;
(void) rw_rdlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_rdlock(&ztest_shared->zs_name_lock);
(void) snprintf(name, 100, "%s/%s_temp_%llu", za->za_pool, za->za_pool,
(u_longlong_t)za->za_instance);
@ -1334,7 +1334,7 @@ ztest_dmu_objset_create_destroy(ztest_args_t *za)
if (error) {
if (error == ENOSPC) {
ztest_record_enospc("dmu_objset_create");
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
return;
}
fatal(0, "dmu_objset_create(%s) = %d", name, error);
@ -1416,7 +1416,7 @@ ztest_dmu_objset_create_destroy(ztest_args_t *za)
if (error)
fatal(0, "dmu_objset_destroy(%s) = %d", name, error);
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
}
/*
@ -1430,7 +1430,7 @@ ztest_dmu_snapshot_create_destroy(ztest_args_t *za)
char snapname[100];
char osname[MAXNAMELEN];
(void) rw_rdlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_rdlock(&ztest_shared->zs_name_lock);
dmu_objset_name(os, osname);
(void) snprintf(snapname, 100, "%s@%llu", osname,
(u_longlong_t)za->za_instance);
@ -1443,7 +1443,7 @@ ztest_dmu_snapshot_create_destroy(ztest_args_t *za)
ztest_record_enospc("dmu_take_snapshot");
else if (error != 0 && error != EEXIST)
fatal(0, "dmu_take_snapshot() = %d", error);
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
}
/*
@ -1941,7 +1941,7 @@ ztest_dmu_write_parallel(ztest_args_t *za)
int bs = ZTEST_DIROBJ_BLOCKSIZE;
int do_free = 0;
uint64_t off, txg, txg_how;
mutex_t *lp;
pthread_mutex_t *lp;
char osname[MAXNAMELEN];
char iobuf[SPA_MAXBLOCKSIZE];
blkptr_t blk = { 0 };
@ -1991,7 +1991,7 @@ ztest_dmu_write_parallel(ztest_args_t *za)
txg = dmu_tx_get_txg(tx);
lp = &ztest_shared->zs_sync_lock[b];
(void) mutex_lock(lp);
(void) pthread_mutex_lock(lp);
wbt->bt_objset = dmu_objset_id(os);
wbt->bt_object = ZTEST_DIROBJ;
@ -2044,7 +2044,7 @@ ztest_dmu_write_parallel(ztest_args_t *za)
dmu_write(os, ZTEST_DIROBJ, off, btsize, wbt, tx);
}
(void) mutex_unlock(lp);
(void) pthread_mutex_unlock(lp);
if (ztest_random(1000) == 0)
(void) poll(NULL, 0, 1); /* open dn_notxholds window */
@ -2063,13 +2063,13 @@ ztest_dmu_write_parallel(ztest_args_t *za)
/*
* dmu_sync() the block we just wrote.
*/
(void) mutex_lock(lp);
(void) pthread_mutex_lock(lp);
blkoff = P2ALIGN_TYPED(off, bs, uint64_t);
error = dmu_buf_hold(os, ZTEST_DIROBJ, blkoff, FTAG, &db);
za->za_dbuf = db;
if (error) {
(void) mutex_unlock(lp);
(void) pthread_mutex_unlock(lp);
return;
}
blkoff = off - blkoff;
@ -2077,7 +2077,7 @@ ztest_dmu_write_parallel(ztest_args_t *za)
dmu_buf_rele(db, FTAG);
za->za_dbuf = NULL;
(void) mutex_unlock(lp);
(void) pthread_mutex_unlock(lp);
if (error)
return;
@ -2656,7 +2656,7 @@ ztest_dsl_prop_get_set(ztest_args_t *za)
char osname[MAXNAMELEN];
int error;
(void) rw_rdlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_rdlock(&ztest_shared->zs_name_lock);
dmu_objset_name(os, osname);
@ -2695,7 +2695,7 @@ ztest_dsl_prop_get_set(ztest_args_t *za)
}
}
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
}
/*
@ -2859,7 +2859,7 @@ ztest_spa_rename(ztest_args_t *za)
int error;
spa_t *spa;
(void) rw_wrlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_wrlock(&ztest_shared->zs_name_lock);
oldname = za->za_pool;
newname = umem_alloc(strlen(oldname) + 5, UMEM_NOFAIL);
@ -2911,7 +2911,7 @@ ztest_spa_rename(ztest_args_t *za)
umem_free(newname, strlen(newname) + 1);
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
}
@ -3149,15 +3149,18 @@ ztest_spa_import_export(char *oldname, char *newname)
nvlist_free(config);
}
static void
ztest_resume(spa_t *spa)
static void *
ztest_resume(void *arg)
{
spa_t *spa = arg;
if (spa_suspended(spa)) {
spa_vdev_state_enter(spa);
vdev_clear(spa, NULL);
(void) spa_vdev_state_exit(spa, NULL, 0);
zio_resume(spa);
}
return (NULL);
}
static void *
@ -3247,20 +3250,19 @@ ztest_run(char *pool)
ztest_args_t *za;
spa_t *spa;
char name[100];
thread_t resume_tid;
pthread_t resume_tid;
ztest_exiting = B_FALSE;
(void) _mutex_init(&zs->zs_vdev_lock, USYNC_THREAD, NULL);
(void) rwlock_init(&zs->zs_name_lock, USYNC_THREAD, NULL);
(void) _mutex_init(&zs->zs_cb_list.zcl_callbacks_lock, USYNC_THREAD,
NULL);
(void) pthread_mutex_init(&zs->zs_vdev_lock, NULL);
(void) pthread_rwlock_init(&zs->zs_name_lock, NULL);
(void) pthread_mutex_init(&zs->zs_cb_list.zcl_callbacks_lock, NULL);
list_create(&zs->zs_cb_list.zcl_callbacks, sizeof (ztest_cb_data_t),
offsetof(ztest_cb_data_t, zcd_node));
for (t = 0; t < ZTEST_SYNC_LOCKS; t++)
(void) _mutex_init(&zs->zs_sync_lock[t], USYNC_THREAD, NULL);
(void) pthread_mutex_init(&zs->zs_sync_lock[t], NULL);
/*
* Destroy one disk before we even start.
@ -3327,8 +3329,7 @@ ztest_run(char *pool)
/*
* Create a thread to periodically resume suspended I/O.
*/
VERIFY(thr_create(0, 0, ztest_resume_thread, spa, THR_BOUND,
&resume_tid) == 0);
VERIFY(pthread_create(&resume_tid, NULL, ztest_resume_thread, spa)==0);
/*
* Verify that we can safely inquire about about any object,
@ -3377,7 +3378,7 @@ ztest_run(char *pool)
if (t < zopt_datasets) {
int test_future = FALSE;
(void) rw_rdlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_rdlock(&ztest_shared->zs_name_lock);
(void) snprintf(name, 100, "%s/%s_%d", pool, pool, d);
error = dmu_objset_create(name, DMU_OST_OTHER, NULL, 0,
ztest_create_cb, NULL);
@ -3385,7 +3386,7 @@ ztest_run(char *pool)
test_future = TRUE;
} else if (error == ENOSPC) {
zs->zs_enospc_count++;
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
break;
} else if (error != 0) {
fatal(0, "dmu_objset_create(%s) = %d",
@ -3396,7 +3397,7 @@ ztest_run(char *pool)
if (error)
fatal(0, "dmu_objset_open('%s') = %d",
name, error);
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
if (test_future)
ztest_dmu_check_future_leak(&za[t]);
zil_replay(za[d].za_os, za[d].za_os,
@ -3404,12 +3405,12 @@ ztest_run(char *pool)
za[d].za_zilog = zil_open(za[d].za_os, NULL);
}
VERIFY(thr_create(0, 0, ztest_thread, &za[t], THR_BOUND,
&za[t].za_thread) == 0);
VERIFY(pthread_create(&za[t].za_thread, NULL, ztest_thread,
&za[t]) == 0);
}
while (--t >= 0) {
VERIFY(thr_join(za[t].za_thread, NULL, NULL) == 0);
VERIFY(pthread_join(za[t].za_thread, NULL) == 0);
if (t < zopt_datasets) {
zil_close(za[t].za_zilog);
dmu_objset_close(za[t].za_os);
@ -3428,14 +3429,14 @@ ztest_run(char *pool)
* If we had out-of-space errors, destroy a random objset.
*/
if (zs->zs_enospc_count != 0) {
(void) rw_rdlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_rdlock(&ztest_shared->zs_name_lock);
d = (int)ztest_random(zopt_datasets);
(void) snprintf(name, 100, "%s/%s_%d", pool, pool, d);
if (zopt_verbose >= 3)
(void) printf("Destroying %s to free up space\n", name);
(void) dmu_objset_find(name, ztest_destroy_cb, &za[d],
DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
(void) rw_unlock(&ztest_shared->zs_name_lock);
(void) pthread_rwlock_unlock(&ztest_shared->zs_name_lock);
}
txg_wait_synced(spa_get_dsl(spa), 0);
@ -3444,7 +3445,7 @@ ztest_run(char *pool)
/* Kill the resume thread */
ztest_exiting = B_TRUE;
VERIFY(thr_join(resume_tid, NULL, NULL) == 0);
VERIFY(pthread_join(resume_tid, NULL) == 0);
ztest_resume(spa);
/*
@ -3460,9 +3461,9 @@ ztest_run(char *pool)
list_destroy(&zs->zs_cb_list.zcl_callbacks);
(void) _mutex_destroy(&zs->zs_cb_list.zcl_callbacks_lock);
(void) rwlock_destroy(&zs->zs_name_lock);
(void) _mutex_destroy(&zs->zs_vdev_lock);
(void) pthread_mutex_destroy(&zs->zs_cb_list.zcl_callbacks_lock);
(void) pthread_rwlock_destroy(&zs->zs_name_lock);
(void) pthread_mutex_destroy(&zs->zs_vdev_lock);
}
void

View File

@ -37,7 +37,6 @@
#include <stdlib.h>
#include <string.h>
#include <sys/debug.h>
#include <thread.h>
#include <unistd.h>
#if !defined(TEXT_DOMAIN)
@ -70,11 +69,12 @@ static va_list uu_panic_args;
static pthread_t uu_panic_thread;
static uint32_t _uu_main_error;
static __thread int _uu_main_thread = 0;
void
uu_set_error(uint_t code)
{
if (thr_main() != 0) {
if (_uu_main_thread) {
_uu_main_error = code;
return;
}
@ -103,7 +103,7 @@ uu_set_error(uint_t code)
uint32_t
uu_error(void)
{
if (thr_main() != 0)
if (_uu_main_thread)
return (_uu_main_error);
if (uu_error_key_setup < 0) /* can't happen? */
@ -251,5 +251,6 @@ uu_release_child(void)
static void
uu_init(void)
{
_uu_main_thread = 1;
(void) pthread_atfork(uu_lockup, uu_release, uu_release_child);
}

View File

@ -50,8 +50,7 @@ extern "C" {
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <synch.h>
#include <thread.h>
#include <pthread.h>
#include <assert.h>
#include <alloca.h>
#include <umem.h>
@ -104,6 +103,7 @@ extern void vpanic(const char *, __va_list);
#define fm_panic panic
/* This definition is copied from assert.h. */
#ifndef verify
#if defined(__STDC__)
#if __STDC_VERSION__ - 0 >= 199901L
#define verify(EX) (void)((EX) || \
@ -114,7 +114,10 @@ extern void vpanic(const char *, __va_list);
#else
#define verify(EX) (void)((EX) || (_assert("EX", __FILE__, __LINE__), 0))
#endif /* __STDC__ */
#endif
#undef VERIFY
#undef ASSERT
#define VERIFY verify
#define ASSERT assert
@ -187,15 +190,18 @@ _NOTE(CONSTCOND) } while (0)
/*
* Threads
*/
#define curthread ((void *)(uintptr_t)thr_self())
#define curthread ((void *)(uintptr_t)pthread_self())
#define tsd_get(key) pthread_getspecific(key)
#define tsd_set(key, val) pthread_setspecific(key, val)
typedef struct kthread kthread_t;
typedef void (*thread_func_t)(void *);
#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \
zk_thread_create(func, arg)
#define thread_exit() thr_exit(NULL)
zk_thread_create((thread_func_t)func, arg)
#define thread_exit() pthread_exit(NULL)
extern kthread_t *zk_thread_create(void (*func)(), void *arg);
extern kthread_t *zk_thread_create(thread_func_t func, void *arg);
#define issig(why) (FALSE)
#define ISSIG(thr, why) (FALSE)
@ -203,28 +209,18 @@ extern kthread_t *zk_thread_create(void (*func)(), void *arg);
/*
* Mutexes
*/
#define MTX_MAGIC 0x9522f51362a6e326ull
typedef struct kmutex {
void *m_owner;
boolean_t initialized;
mutex_t m_lock;
uint64_t m_magic;
pthread_mutex_t m_lock;
} kmutex_t;
#define MUTEX_DEFAULT USYNC_THREAD
#undef MUTEX_HELD
#define MUTEX_HELD(m) _mutex_held(&(m)->m_lock)
#define MUTEX_DEFAULT 0
#define MUTEX_HELD(m) ((m)->m_owner == curthread)
/*
* Argh -- we have to get cheesy here because the kernel and userland
* have different signatures for the same routine.
*/
extern int _mutex_init(mutex_t *mp, int type, void *arg);
extern int _mutex_destroy(mutex_t *mp);
#define mutex_init(mp, b, c, d) zmutex_init((kmutex_t *)(mp))
#define mutex_destroy(mp) zmutex_destroy((kmutex_t *)(mp))
extern void zmutex_init(kmutex_t *mp);
extern void zmutex_destroy(kmutex_t *mp);
extern void mutex_init(kmutex_t *mp, char *name, int type, void *cookie);
extern void mutex_destroy(kmutex_t *mp);
extern void mutex_enter(kmutex_t *mp);
extern void mutex_exit(kmutex_t *mp);
extern int mutex_tryenter(kmutex_t *mp);
@ -233,23 +229,24 @@ extern void *mutex_owner(kmutex_t *mp);
/*
* RW locks
*/
#define RW_MAGIC 0x4d31fb123648e78aull
typedef struct krwlock {
void *rw_owner;
boolean_t initialized;
rwlock_t rw_lock;
void *rw_owner;
void *rw_wr_owner;
uint64_t rw_magic;
pthread_rwlock_t rw_lock;
uint_t rw_readers;
} krwlock_t;
typedef int krw_t;
#define RW_READER 0
#define RW_WRITER 1
#define RW_DEFAULT USYNC_THREAD
#define RW_DEFAULT 0
#undef RW_READ_HELD
#define RW_READ_HELD(x) _rw_read_held(&(x)->rw_lock)
#undef RW_WRITE_HELD
#define RW_WRITE_HELD(x) _rw_write_held(&(x)->rw_lock)
#define RW_READ_HELD(x) ((x)->rw_readers > 0)
#define RW_WRITE_HELD(x) ((x)->rw_wr_owner == curthread)
#define RW_LOCK_HELD(x) (RW_READ_HELD(x) || RW_WRITE_HELD(x))
extern void rw_init(krwlock_t *rwlp, char *name, int type, void *arg);
extern void rw_destroy(krwlock_t *rwlp);
@ -267,9 +264,13 @@ extern gid_t *crgetgroups(cred_t *cr);
/*
* Condition variables
*/
typedef cond_t kcondvar_t;
#define CV_MAGIC 0xd31ea9a83b1b30c4ull
typedef struct kcondvar {
uint64_t cv_magic;
pthread_cond_t cv;
} kcondvar_t;
#define CV_DEFAULT USYNC_THREAD
#define CV_DEFAULT 0
extern void cv_init(kcondvar_t *cv, char *name, int type, void *arg);
extern void cv_destroy(kcondvar_t *cv);
@ -443,7 +444,8 @@ extern void delay(clock_t ticks);
#define minclsyspri 60
#define maxclsyspri 99
#define CPU_SEQID (thr_self() & (max_ncpus - 1))
/* XXX: not portable */
#define CPU_SEQID (pthread_self() & (max_ncpus - 1))
#define kcred NULL
#define CRED() NULL

View File

@ -36,6 +36,7 @@
#include <sys/zfs_context.h>
#include <sys/zmod.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include <sys/systeminfo.h>
/*
@ -57,13 +58,17 @@ struct utsname utsname = {
*/
/*ARGSUSED*/
kthread_t *
zk_thread_create(void (*func)(), void *arg)
zk_thread_create(thread_func_t func, void *arg)
{
thread_t tid;
pthread_t tid;
VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
&tid) == 0);
pthread_attr_t attr;
VERIFY(pthread_attr_init(&attr) == 0);
VERIFY(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);
VERIFY(pthread_create(&tid, &attr, (void *(*)(void *))func, arg) == 0);
/* XXX: not portable */
return ((void *)(uintptr_t)tid);
}
@ -96,30 +101,37 @@ kstat_delete(kstat_t *ksp)
* =========================================================================
*/
void
zmutex_init(kmutex_t *mp)
mutex_init(kmutex_t *mp, char *name, int type, void *cookie)
{
ASSERT(type == MUTEX_DEFAULT);
ASSERT(cookie == NULL);
#ifdef IM_FEELING_LUCKY
ASSERT(mp->m_magic != MTX_MAGIC);
#endif
mp->m_owner = NULL;
mp->initialized = B_TRUE;
(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
mp->m_magic = MTX_MAGIC;
VERIFY3S(pthread_mutex_init(&mp->m_lock, NULL), ==, 0);
}
void
zmutex_destroy(kmutex_t *mp)
mutex_destroy(kmutex_t *mp)
{
ASSERT(mp->initialized == B_TRUE);
ASSERT(mp->m_magic == MTX_MAGIC);
ASSERT(mp->m_owner == NULL);
(void) _mutex_destroy(&(mp)->m_lock);
VERIFY3S(pthread_mutex_destroy(&(mp)->m_lock), ==, 0);
mp->m_owner = (void *)-1UL;
mp->initialized = B_FALSE;
mp->m_magic = 0;
}
void
mutex_enter(kmutex_t *mp)
{
ASSERT(mp->initialized == B_TRUE);
ASSERT(mp->m_magic == MTX_MAGIC);
ASSERT(mp->m_owner != (void *)-1UL);
ASSERT(mp->m_owner != curthread);
VERIFY(mutex_lock(&mp->m_lock) == 0);
VERIFY3S(pthread_mutex_lock(&mp->m_lock), ==, 0);
ASSERT(mp->m_owner == NULL);
mp->m_owner = curthread;
}
@ -127,9 +139,9 @@ mutex_enter(kmutex_t *mp)
int
mutex_tryenter(kmutex_t *mp)
{
ASSERT(mp->initialized == B_TRUE);
ASSERT(mp->m_magic == MTX_MAGIC);
ASSERT(mp->m_owner != (void *)-1UL);
if (0 == mutex_trylock(&mp->m_lock)) {
if (0 == pthread_mutex_trylock(&mp->m_lock)) {
ASSERT(mp->m_owner == NULL);
mp->m_owner = curthread;
return (1);
@ -141,16 +153,16 @@ mutex_tryenter(kmutex_t *mp)
void
mutex_exit(kmutex_t *mp)
{
ASSERT(mp->initialized == B_TRUE);
ASSERT(mp->m_magic == MTX_MAGIC);
ASSERT(mutex_owner(mp) == curthread);
mp->m_owner = NULL;
VERIFY(mutex_unlock(&mp->m_lock) == 0);
VERIFY3S(pthread_mutex_unlock(&mp->m_lock), ==, 0);
}
void *
mutex_owner(kmutex_t *mp)
{
ASSERT(mp->initialized == B_TRUE);
ASSERT(mp->m_magic == MTX_MAGIC);
return (mp->m_owner);
}
@ -163,31 +175,48 @@ mutex_owner(kmutex_t *mp)
void
rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
{
rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
ASSERT(type == RW_DEFAULT);
ASSERT(arg == NULL);
#ifdef IM_FEELING_LUCKY
ASSERT(rwlp->rw_magic != RW_MAGIC);
#endif
VERIFY3S(pthread_rwlock_init(&rwlp->rw_lock, NULL), ==, 0);
rwlp->rw_owner = NULL;
rwlp->initialized = B_TRUE;
rwlp->rw_wr_owner = NULL;
rwlp->rw_readers = 0;
rwlp->rw_magic = RW_MAGIC;
}
void
rw_destroy(krwlock_t *rwlp)
{
rwlock_destroy(&rwlp->rw_lock);
rwlp->rw_owner = (void *)-1UL;
rwlp->initialized = B_FALSE;
ASSERT(rwlp->rw_magic == RW_MAGIC);
VERIFY3S(pthread_rwlock_destroy(&rwlp->rw_lock), ==, 0);
rwlp->rw_magic = 0;
}
void
rw_enter(krwlock_t *rwlp, krw_t rw)
{
ASSERT(!RW_LOCK_HELD(rwlp));
ASSERT(rwlp->initialized == B_TRUE);
ASSERT(rwlp->rw_owner != (void *)-1UL);
ASSERT(rwlp->rw_magic == RW_MAGIC);
ASSERT(rwlp->rw_owner != curthread);
ASSERT(rwlp->rw_wr_owner != curthread);
if (rw == RW_READER)
VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
else
VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
if (rw == RW_READER) {
VERIFY3S(pthread_rwlock_rdlock(&rwlp->rw_lock), ==, 0);
ASSERT(rwlp->rw_wr_owner == NULL);
atomic_inc_uint(&rwlp->rw_readers);
} else {
VERIFY3S(pthread_rwlock_wrlock(&rwlp->rw_lock), ==, 0);
ASSERT(rwlp->rw_wr_owner == NULL);
ASSERT3U(rwlp->rw_readers, ==, 0);
rwlp->rw_wr_owner = curthread;
}
rwlp->rw_owner = curthread;
}
@ -195,11 +224,16 @@ rw_enter(krwlock_t *rwlp, krw_t rw)
void
rw_exit(krwlock_t *rwlp)
{
ASSERT(rwlp->initialized == B_TRUE);
ASSERT(rwlp->rw_owner != (void *)-1UL);
ASSERT(rwlp->rw_magic == RW_MAGIC);
ASSERT(RW_LOCK_HELD(rwlp));
if (RW_READ_HELD(rwlp))
atomic_dec_uint(&rwlp->rw_readers);
else
rwlp->rw_wr_owner = NULL;
rwlp->rw_owner = NULL;
VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
VERIFY3S(pthread_rwlock_unlock(&rwlp->rw_lock), ==, 0);
}
int
@ -207,19 +241,29 @@ rw_tryenter(krwlock_t *rwlp, krw_t rw)
{
int rv;
ASSERT(rwlp->initialized == B_TRUE);
ASSERT(rwlp->rw_owner != (void *)-1UL);
ASSERT(rwlp->rw_magic == RW_MAGIC);
if (rw == RW_READER)
rv = rw_tryrdlock(&rwlp->rw_lock);
rv = pthread_rwlock_tryrdlock(&rwlp->rw_lock);
else
rv = rw_trywrlock(&rwlp->rw_lock);
rv = pthread_rwlock_trywrlock(&rwlp->rw_lock);
if (rv == 0) {
ASSERT(rwlp->rw_wr_owner == NULL);
if (rw == RW_READER)
atomic_inc_uint(&rwlp->rw_readers);
else {
ASSERT3U(rwlp->rw_readers, ==, 0);
rwlp->rw_wr_owner = curthread;
}
rwlp->rw_owner = curthread;
return (1);
}
VERIFY3S(rv, ==, EBUSY);
return (0);
}
@ -227,8 +271,7 @@ rw_tryenter(krwlock_t *rwlp, krw_t rw)
int
rw_tryupgrade(krwlock_t *rwlp)
{
ASSERT(rwlp->initialized == B_TRUE);
ASSERT(rwlp->rw_owner != (void *)-1UL);
ASSERT(rwlp->rw_magic == RW_MAGIC);
return (0);
}
@ -242,22 +285,34 @@ rw_tryupgrade(krwlock_t *rwlp)
void
cv_init(kcondvar_t *cv, char *name, int type, void *arg)
{
VERIFY(cond_init(cv, type, NULL) == 0);
ASSERT(type == CV_DEFAULT);
#ifdef IM_FEELING_LUCKY
ASSERT(cv->cv_magic != CV_MAGIC);
#endif
cv->cv_magic = CV_MAGIC;
VERIFY3S(pthread_cond_init(&cv->cv, NULL), ==, 0);
}
void
cv_destroy(kcondvar_t *cv)
{
VERIFY(cond_destroy(cv) == 0);
ASSERT(cv->cv_magic == CV_MAGIC);
VERIFY3S(pthread_cond_destroy(&cv->cv), ==, 0);
cv->cv_magic = 0;
}
void
cv_wait(kcondvar_t *cv, kmutex_t *mp)
{
ASSERT(cv->cv_magic == CV_MAGIC);
ASSERT(mutex_owner(mp) == curthread);
mp->m_owner = NULL;
int ret = cond_wait(cv, &mp->m_lock);
VERIFY(ret == 0 || ret == EINTR);
int ret = pthread_cond_wait(&cv->cv, &mp->m_lock);
if (ret != 0)
VERIFY3S(ret, ==, EINTR);
mp->m_owner = curthread;
}
@ -265,29 +320,38 @@ clock_t
cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
{
int error;
struct timeval tv;
timestruc_t ts;
clock_t delta;
ASSERT(cv->cv_magic == CV_MAGIC);
top:
delta = abstime - lbolt;
if (delta <= 0)
return (-1);
ts.tv_sec = delta / hz;
ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
VERIFY(gettimeofday(&tv, NULL) == 0);
ts.tv_sec = tv.tv_sec + delta / hz;
ts.tv_nsec = tv.tv_usec * 1000 + (delta % hz) * (NANOSEC / hz);
if (ts.tv_nsec >= NANOSEC) {
ts.tv_sec++;
ts.tv_nsec -= NANOSEC;
}
ASSERT(mutex_owner(mp) == curthread);
mp->m_owner = NULL;
error = cond_reltimedwait(cv, &mp->m_lock, &ts);
error = pthread_cond_timedwait(&cv->cv, &mp->m_lock, &ts);
mp->m_owner = curthread;
if (error == ETIME)
if (error == ETIMEDOUT)
return (-1);
if (error == EINTR)
goto top;
ASSERT(error == 0);
VERIFY3S(error, ==, 0);
return (1);
}
@ -295,13 +359,15 @@ top:
void
cv_signal(kcondvar_t *cv)
{
VERIFY(cond_signal(cv) == 0);
ASSERT(cv->cv_magic == CV_MAGIC);
VERIFY3S(pthread_cond_signal(&cv->cv), ==, 0);
}
void
cv_broadcast(kcondvar_t *cv)
{
VERIFY(cond_broadcast(cv) == 0);
ASSERT(cv->cv_magic == CV_MAGIC);
VERIFY3S(pthread_cond_broadcast(&cv->cv), ==, 0);
}
/*
@ -543,7 +609,7 @@ __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
if (dprintf_find_string("pid"))
(void) printf("%d ", getpid());
if (dprintf_find_string("tid"))
(void) printf("%u ", thr_self());
(void) printf("%u ", (uint_t) pthread_self());
if (dprintf_find_string("cpu"))
(void) printf("%u ", getcpuid());
if (dprintf_find_string("time"))

View File

@ -42,7 +42,7 @@ struct taskq {
krwlock_t tq_threadlock;
kcondvar_t tq_dispatch_cv;
kcondvar_t tq_wait_cv;
thread_t *tq_threadlist;
pthread_t *tq_threadlist;
int tq_flags;
int tq_active;
int tq_nthreads;
@ -185,7 +185,7 @@ taskq_create(const char *name, int nthreads, pri_t pri,
tq->tq_maxalloc = maxalloc;
tq->tq_task.task_next = &tq->tq_task;
tq->tq_task.task_prev = &tq->tq_task;
tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP);
tq->tq_threadlist = kmem_alloc(nthreads * sizeof (pthread_t), KM_SLEEP);
if (flags & TASKQ_PREPOPULATE) {
mutex_enter(&tq->tq_lock);
@ -195,8 +195,8 @@ taskq_create(const char *name, int nthreads, pri_t pri,
}
for (t = 0; t < nthreads; t++)
(void) thr_create(0, 0, taskq_thread,
tq, THR_BOUND, &tq->tq_threadlist[t]);
VERIFY(pthread_create(&tq->tq_threadlist[t],
NULL, taskq_thread, tq) == 0);
return (tq);
}
@ -226,9 +226,9 @@ taskq_destroy(taskq_t *tq)
mutex_exit(&tq->tq_lock);
for (t = 0; t < nthreads; t++)
(void) thr_join(tq->tq_threadlist[t], NULL, NULL);
VERIFY(pthread_join(tq->tq_threadlist[t], NULL) == 0);
kmem_free(tq->tq_threadlist, nthreads * sizeof (thread_t));
kmem_free(tq->tq_threadlist, nthreads * sizeof (pthread_t));
rw_destroy(&tq->tq_threadlock);
mutex_destroy(&tq->tq_lock);
@ -247,7 +247,7 @@ taskq_member(taskq_t *tq, void *t)
return (1);
for (i = 0; i < tq->tq_nthreads; i++)
if (tq->tq_threadlist[i] == (thread_t)(uintptr_t)t)
if (tq->tq_threadlist[i] == (pthread_t)(uintptr_t)t)
return (1);
return (0);