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> 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, This converts the userspace code to use the POSIX threads API instead of
which are called by the DMU when they are safely committed to disk. the Solaris-only threads API. The API is almost identical and POSIX
See Lustre bug 14117 for details. 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> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,6 +36,7 @@
#include <sys/zfs_context.h> #include <sys/zfs_context.h>
#include <sys/zmod.h> #include <sys/zmod.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <sys/time.h>
#include <sys/systeminfo.h> #include <sys/systeminfo.h>
/* /*
@ -57,13 +58,17 @@ struct utsname utsname = {
*/ */
/*ARGSUSED*/ /*ARGSUSED*/
kthread_t * 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, pthread_attr_t attr;
&tid) == 0); 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); return ((void *)(uintptr_t)tid);
} }
@ -96,30 +101,37 @@ kstat_delete(kstat_t *ksp)
* ========================================================================= * =========================================================================
*/ */
void 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->m_owner = NULL;
mp->initialized = B_TRUE; mp->m_magic = MTX_MAGIC;
(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); VERIFY3S(pthread_mutex_init(&mp->m_lock, NULL), ==, 0);
} }
void 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); 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->m_owner = (void *)-1UL;
mp->initialized = B_FALSE; mp->m_magic = 0;
} }
void void
mutex_enter(kmutex_t *mp) 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 != (void *)-1UL);
ASSERT(mp->m_owner != curthread); 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); ASSERT(mp->m_owner == NULL);
mp->m_owner = curthread; mp->m_owner = curthread;
} }
@ -127,9 +139,9 @@ mutex_enter(kmutex_t *mp)
int int
mutex_tryenter(kmutex_t *mp) mutex_tryenter(kmutex_t *mp)
{ {
ASSERT(mp->initialized == B_TRUE); ASSERT(mp->m_magic == MTX_MAGIC);
ASSERT(mp->m_owner != (void *)-1UL); 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); ASSERT(mp->m_owner == NULL);
mp->m_owner = curthread; mp->m_owner = curthread;
return (1); return (1);
@ -141,16 +153,16 @@ mutex_tryenter(kmutex_t *mp)
void void
mutex_exit(kmutex_t *mp) mutex_exit(kmutex_t *mp)
{ {
ASSERT(mp->initialized == B_TRUE); ASSERT(mp->m_magic == MTX_MAGIC);
ASSERT(mutex_owner(mp) == curthread); ASSERT(mutex_owner(mp) == curthread);
mp->m_owner = NULL; mp->m_owner = NULL;
VERIFY(mutex_unlock(&mp->m_lock) == 0); VERIFY3S(pthread_mutex_unlock(&mp->m_lock), ==, 0);
} }
void * void *
mutex_owner(kmutex_t *mp) mutex_owner(kmutex_t *mp)
{ {
ASSERT(mp->initialized == B_TRUE); ASSERT(mp->m_magic == MTX_MAGIC);
return (mp->m_owner); return (mp->m_owner);
} }
@ -163,31 +175,48 @@ mutex_owner(kmutex_t *mp)
void void
rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 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->rw_owner = NULL;
rwlp->initialized = B_TRUE; rwlp->rw_wr_owner = NULL;
rwlp->rw_readers = 0;
rwlp->rw_magic = RW_MAGIC;
} }
void void
rw_destroy(krwlock_t *rwlp) rw_destroy(krwlock_t *rwlp)
{ {
rwlock_destroy(&rwlp->rw_lock); ASSERT(rwlp->rw_magic == RW_MAGIC);
rwlp->rw_owner = (void *)-1UL;
rwlp->initialized = B_FALSE; VERIFY3S(pthread_rwlock_destroy(&rwlp->rw_lock), ==, 0);
rwlp->rw_magic = 0;
} }
void void
rw_enter(krwlock_t *rwlp, krw_t rw) rw_enter(krwlock_t *rwlp, krw_t rw)
{ {
ASSERT(!RW_LOCK_HELD(rwlp)); ASSERT(rwlp->rw_magic == RW_MAGIC);
ASSERT(rwlp->initialized == B_TRUE);
ASSERT(rwlp->rw_owner != (void *)-1UL);
ASSERT(rwlp->rw_owner != curthread); ASSERT(rwlp->rw_owner != curthread);
ASSERT(rwlp->rw_wr_owner != curthread);
if (rw == RW_READER) if (rw == RW_READER) {
VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); VERIFY3S(pthread_rwlock_rdlock(&rwlp->rw_lock), ==, 0);
else ASSERT(rwlp->rw_wr_owner == NULL);
VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
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; rwlp->rw_owner = curthread;
} }
@ -195,11 +224,16 @@ rw_enter(krwlock_t *rwlp, krw_t rw)
void void
rw_exit(krwlock_t *rwlp) rw_exit(krwlock_t *rwlp)
{ {
ASSERT(rwlp->initialized == B_TRUE); ASSERT(rwlp->rw_magic == RW_MAGIC);
ASSERT(rwlp->rw_owner != (void *)-1UL); 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; rwlp->rw_owner = NULL;
VERIFY(rw_unlock(&rwlp->rw_lock) == 0); VERIFY3S(pthread_rwlock_unlock(&rwlp->rw_lock), ==, 0);
} }
int int
@ -207,19 +241,29 @@ rw_tryenter(krwlock_t *rwlp, krw_t rw)
{ {
int rv; int rv;
ASSERT(rwlp->initialized == B_TRUE); ASSERT(rwlp->rw_magic == RW_MAGIC);
ASSERT(rwlp->rw_owner != (void *)-1UL);
if (rw == RW_READER) if (rw == RW_READER)
rv = rw_tryrdlock(&rwlp->rw_lock); rv = pthread_rwlock_tryrdlock(&rwlp->rw_lock);
else else
rv = rw_trywrlock(&rwlp->rw_lock); rv = pthread_rwlock_trywrlock(&rwlp->rw_lock);
if (rv == 0) { 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; rwlp->rw_owner = curthread;
return (1); return (1);
} }
VERIFY3S(rv, ==, EBUSY);
return (0); return (0);
} }
@ -227,8 +271,7 @@ rw_tryenter(krwlock_t *rwlp, krw_t rw)
int int
rw_tryupgrade(krwlock_t *rwlp) rw_tryupgrade(krwlock_t *rwlp)
{ {
ASSERT(rwlp->initialized == B_TRUE); ASSERT(rwlp->rw_magic == RW_MAGIC);
ASSERT(rwlp->rw_owner != (void *)-1UL);
return (0); return (0);
} }
@ -242,22 +285,34 @@ rw_tryupgrade(krwlock_t *rwlp)
void void
cv_init(kcondvar_t *cv, char *name, int type, void *arg) 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 void
cv_destroy(kcondvar_t *cv) 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 void
cv_wait(kcondvar_t *cv, kmutex_t *mp) cv_wait(kcondvar_t *cv, kmutex_t *mp)
{ {
ASSERT(cv->cv_magic == CV_MAGIC);
ASSERT(mutex_owner(mp) == curthread); ASSERT(mutex_owner(mp) == curthread);
mp->m_owner = NULL; mp->m_owner = NULL;
int ret = cond_wait(cv, &mp->m_lock); int ret = pthread_cond_wait(&cv->cv, &mp->m_lock);
VERIFY(ret == 0 || ret == EINTR); if (ret != 0)
VERIFY3S(ret, ==, EINTR);
mp->m_owner = curthread; mp->m_owner = curthread;
} }
@ -265,29 +320,38 @@ clock_t
cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
{ {
int error; int error;
struct timeval tv;
timestruc_t ts; timestruc_t ts;
clock_t delta; clock_t delta;
ASSERT(cv->cv_magic == CV_MAGIC);
top: top:
delta = abstime - lbolt; delta = abstime - lbolt;
if (delta <= 0) if (delta <= 0)
return (-1); return (-1);
ts.tv_sec = delta / hz; VERIFY(gettimeofday(&tv, NULL) == 0);
ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
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); ASSERT(mutex_owner(mp) == curthread);
mp->m_owner = NULL; 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; mp->m_owner = curthread;
if (error == ETIME) if (error == ETIMEDOUT)
return (-1); return (-1);
if (error == EINTR) if (error == EINTR)
goto top; goto top;
ASSERT(error == 0); VERIFY3S(error, ==, 0);
return (1); return (1);
} }
@ -295,13 +359,15 @@ top:
void void
cv_signal(kcondvar_t *cv) cv_signal(kcondvar_t *cv)
{ {
VERIFY(cond_signal(cv) == 0); ASSERT(cv->cv_magic == CV_MAGIC);
VERIFY3S(pthread_cond_signal(&cv->cv), ==, 0);
} }
void void
cv_broadcast(kcondvar_t *cv) 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")) if (dprintf_find_string("pid"))
(void) printf("%d ", getpid()); (void) printf("%d ", getpid());
if (dprintf_find_string("tid")) if (dprintf_find_string("tid"))
(void) printf("%u ", thr_self()); (void) printf("%u ", (uint_t) pthread_self());
if (dprintf_find_string("cpu")) if (dprintf_find_string("cpu"))
(void) printf("%u ", getcpuid()); (void) printf("%u ", getcpuid());
if (dprintf_find_string("time")) if (dprintf_find_string("time"))

View File

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