diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2007-07-30 11:58:31 +0300 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2007-07-30 11:58:31 +0300 |
commit | cab228435bde1b5496522c03a4ce9840f2ef3701 (patch) | |
tree | 2c37b65d176e2de097603333f4de071c31eeff3d /db/mutex | |
parent | 2d07882d45e9e575c00f8f402d4c7271bb65cfe9 (diff) | |
download | librpm-tizen-cab228435bde1b5496522c03a4ce9840f2ef3701.tar.gz librpm-tizen-cab228435bde1b5496522c03a4ce9840f2ef3701.tar.bz2 librpm-tizen-cab228435bde1b5496522c03a4ce9840f2ef3701.zip |
Update internal BDB to version 4.6.18.
Diffstat (limited to 'db/mutex')
-rw-r--r-- | db/mutex/mut_alloc.c | 6 | ||||
-rw-r--r-- | db/mutex/mut_failchk.c | 5 | ||||
-rw-r--r-- | db/mutex/mut_fcntl.c | 7 | ||||
-rw-r--r-- | db/mutex/mut_method.c | 5 | ||||
-rw-r--r-- | db/mutex/mut_pthread.c | 29 | ||||
-rw-r--r-- | db/mutex/mut_region.c | 99 | ||||
-rw-r--r-- | db/mutex/mut_stat.c | 99 | ||||
-rw-r--r-- | db/mutex/mut_stub.c | 234 | ||||
-rw-r--r-- | db/mutex/mut_tas.c | 45 | ||||
-rw-r--r-- | db/mutex/mut_win32.c | 24 | ||||
-rw-r--r-- | db/mutex/mutex.c | 392 | ||||
-rw-r--r-- | db/mutex/test_mutex.c (renamed from db/mutex/tm.c) | 435 | ||||
-rw-r--r-- | db/mutex/uts4_cc.s | 5 |
13 files changed, 678 insertions, 707 deletions
diff --git a/db/mutex/mut_alloc.c b/db/mutex/mut_alloc.c index bfc453dc6..12789cce1 100644 --- a/db/mutex/mut_alloc.c +++ b/db/mutex/mut_alloc.c @@ -1,10 +1,9 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 1999,2007 Oracle. All rights reserved. * - * $Id: mut_alloc.c,v 12.15 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_alloc.c,v 12.18 2007/05/17 15:15:45 bostic Exp $ */ #include "db_config.h" @@ -119,6 +118,7 @@ __mutex_alloc_int(dbenv, locksys, alloc_id, flags, indxp) *indxp = mtxregion->mutex_next; mutexp = MUTEXP_SET(*indxp); + DB_ASSERT(dbenv, ((uintptr_t)mutexp & (dbenv->mutex_align - 1)) == 0); mtxregion->mutex_next = mutexp->mutex_next_link; --mtxregion->stat.st_mutex_free; diff --git a/db/mutex/mut_failchk.c b/db/mutex/mut_failchk.c index 3d9d46a98..707dc57cf 100644 --- a/db/mutex/mut_failchk.c +++ b/db/mutex/mut_failchk.c @@ -1,10 +1,9 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 2005-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 2005,2007 Oracle. All rights reserved. * - * $Id: mut_failchk.c,v 12.3 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_failchk.c,v 12.5 2007/05/17 15:15:45 bostic Exp $ */ #include "db_config.h" diff --git a/db/mutex/mut_fcntl.c b/db/mutex/mut_fcntl.c index eb4c6ef7f..03a55a6fc 100644 --- a/db/mutex/mut_fcntl.c +++ b/db/mutex/mut_fcntl.c @@ -1,10 +1,9 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 1996,2007 Oracle. All rights reserved. * - * $Id: mut_fcntl.c,v 12.20 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_fcntl.c,v 12.23 2007/05/17 15:15:45 bostic Exp $ */ #include "db_config.h" @@ -73,7 +72,7 @@ __db_fcntl_mutex_lock(dbenv, mutex) * up to 1 second. */ for (ms = 1; F_ISSET(mutexp, DB_MUTEX_LOCKED);) { - __os_sleep(NULL, 0, ms * USEC_PER_MS); + __os_sleep(NULL, 0, ms * US_PER_MS); if ((ms <<= 1) > MS_PER_SEC) ms = MS_PER_SEC; } diff --git a/db/mutex/mut_method.c b/db/mutex/mut_method.c index 08da11d94..47a2aebf5 100644 --- a/db/mutex/mut_method.c +++ b/db/mutex/mut_method.c @@ -1,10 +1,9 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 1996,2007 Oracle. All rights reserved. * - * $Id: mut_method.c,v 12.12 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_method.c,v 12.14 2007/05/17 15:15:45 bostic Exp $ */ #include "db_config.h" diff --git a/db/mutex/mut_pthread.c b/db/mutex/mut_pthread.c index 08c7b388b..58c916e1c 100644 --- a/db/mutex/mut_pthread.c +++ b/db/mutex/mut_pthread.c @@ -1,15 +1,19 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1999-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 1999,2007 Oracle. All rights reserved. * - * $Id: mut_pthread.c,v 12.19 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_pthread.c,v 12.24 2007/06/21 16:39:20 ubell Exp $ */ #include "db_config.h" #include "db_int.h" + +/* + * This is where we load in architecture/compiler specific mutex code. + */ +#define LOAD_ACTUAL_MUTEX_CODE #include "dbinc/mutex_int.h" #ifdef HAVE_MUTEX_SOLARIS_LWP @@ -181,7 +185,7 @@ __db_pthread_mutex_lock(dbenv, mutex) mtxregion = mtxmgr->reginfo.primary; mutexp = MUTEXP_SET(mutex); -#ifdef HAVE_STATISTICS +#if defined(HAVE_STATISTICS) && !defined(HAVE_MUTEX_HYBRID) /* * We want to know which mutexes are contentious, but don't want to * do an interlocked test here -- that's slower when the underlying @@ -200,6 +204,17 @@ __db_pthread_mutex_lock(dbenv, mutex) goto err; if (F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)) { + /* + * If we are using hybrid mutexes then the pthread mutexes + * are only used to wait after spinning on the TAS mutex. + * Set the wait flag before checking to see if the mutex + * is still locked. The holder will clear the bit before + * checking the wait flag. + */ +#ifdef HAVE_MUTEX_HYBRID + mutexp->wait++; + MUTEX_MEMBAR(mutexp->wait); +#endif while (F_ISSET(mutexp, DB_MUTEX_LOCKED)) { RET_SET((pthread_cond_wait( &mutexp->cond, &mutexp->mutex)), ret); @@ -223,9 +238,13 @@ __db_pthread_mutex_lock(dbenv, mutex) } } +#ifdef HAVE_MUTEX_HYBRID + mutexp->wait--; +#else F_SET(mutexp, DB_MUTEX_LOCKED); dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid); CHECK_MTX_THREAD(dbenv, mutexp); +#endif /* * According to HP-UX engineers contacted by Netscape, @@ -297,7 +316,7 @@ __db_pthread_mutex_unlock(dbenv, mutex) mtxregion = mtxmgr->reginfo.primary; mutexp = MUTEXP_SET(mutex); -#ifdef DIAGNOSTIC +#if !defined(HAVE_MUTEX_HYBRID) && defined(DIAGNOSTIC) if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) { __db_errx( dbenv, "pthread unlock failed: lock already unlocked"); diff --git a/db/mutex/mut_region.c b/db/mutex/mut_region.c index 6e1b4f3ad..99ad80c70 100644 --- a/db/mutex/mut_region.c +++ b/db/mutex/mut_region.c @@ -1,10 +1,9 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 1996,2007 Oracle. All rights reserved. * - * $Id: mut_region.c,v 12.18 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_region.c,v 12.25 2007/05/17 15:15:45 bostic Exp $ */ #include "db_config.h" @@ -13,8 +12,10 @@ #include "dbinc/log.h" #include "dbinc/lock.h" #include "dbinc/mp.h" +#include "dbinc/txn.h" #include "dbinc/mutex_int.h" +static size_t __mutex_align_size __P((DB_ENV *)); static int __mutex_region_init __P((DB_ENV *, DB_MUTEXMGR *)); static size_t __mutex_region_size __P((DB_ENV *)); @@ -22,11 +23,12 @@ static size_t __mutex_region_size __P((DB_ENV *)); * __mutex_open -- * Open a mutex region. * - * PUBLIC: int __mutex_open __P((DB_ENV *)); + * PUBLIC: int __mutex_open __P((DB_ENV *, int)); */ int -__mutex_open(dbenv) +__mutex_open(dbenv, create_ok) DB_ENV *dbenv; + int create_ok; { DB_MUTEXMGR *mtxmgr; DB_MUTEXREGION *mtxregion; @@ -57,20 +59,21 @@ __mutex_open(dbenv) __lock_region_mutex_count(dbenv) + __log_region_mutex_count(dbenv) + __memp_region_mutex_count(dbenv) + + __txn_region_mutex_count(dbenv) + dbenv->mutex_inc + 100; /* Create/initialize the mutex manager structure. */ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_MUTEXMGR), &mtxmgr)) != 0) return (ret); - /* Join/create the txn region. */ + /* Join/create the mutex region. */ mtxmgr->reginfo.dbenv = dbenv; mtxmgr->reginfo.type = REGION_TYPE_MUTEX; mtxmgr->reginfo.id = INVALID_REGION_ID; mtxmgr->reginfo.flags = REGION_JOIN_OK; - if (F_ISSET(dbenv, DB_ENV_CREATE)) + if (create_ok) F_SET(&mtxmgr->reginfo, REGION_CREATE_OK); - if ((ret = __db_r_attach(dbenv, + if ((ret = __env_region_attach(dbenv, &mtxmgr->reginfo, __mutex_region_size(dbenv))) != 0) goto err; @@ -82,7 +85,7 @@ __mutex_open(dbenv) /* Set the local addresses. */ mtxregion = mtxmgr->reginfo.primary = R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary); - mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_offset); + mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_off); dbenv->mutex_handle = mtxmgr; @@ -123,20 +126,11 @@ __mutex_open(dbenv) } } - /* - * Initialize thread tracking. We want to do this as early - * as possible in case we die. This sits in the mutex region - * so do it now. - */ - if ((ret = __env_thread_init(dbenv, - F_ISSET(&mtxmgr->reginfo, REGION_CREATE))) != 0) - goto err; - return (0); err: dbenv->mutex_handle = NULL; if (mtxmgr->reginfo.addr != NULL) - (void)__db_r_detach(dbenv, &mtxmgr->reginfo, 0); + (void)__env_region_detach(dbenv, &mtxmgr->reginfo, 0); __os_free(dbenv, mtxmgr); return (ret); @@ -159,8 +153,8 @@ __mutex_region_init(dbenv, mtxmgr) COMPQUIET(mutexp, NULL); - if ((ret = __db_shalloc(&mtxmgr->reginfo, - sizeof(DB_MUTEXREGION), 0, &mtxmgr->reginfo.primary)) != 0) { + if ((ret = __env_alloc(&mtxmgr->reginfo, + sizeof(DB_MUTEXREGION), &mtxmgr->reginfo.primary)) != 0) { __db_errx(dbenv, "Unable to allocate memory for the mutex region"); return (ret); @@ -174,8 +168,7 @@ __mutex_region_init(dbenv, mtxmgr) dbenv, MTX_MUTEX_REGION, 0, &mtxregion->mtx_region)) != 0) return (ret); - mtxregion->mutex_size = - (size_t)DB_ALIGN(sizeof(DB_MUTEX), dbenv->mutex_align); + mtxregion->mutex_size = __mutex_align_size(dbenv); mtxregion->stat.st_mutex_align = dbenv->mutex_align; mtxregion->stat.st_mutex_cnt = dbenv->mutex_cnt; @@ -183,22 +176,29 @@ __mutex_region_init(dbenv, mtxmgr) /* * Get a chunk of memory to be used for the mutexes themselves. Each - * piece of the memory must be properly aligned. + * piece of the memory must be properly aligned, and that alignment + * may be more restrictive than the memory alignment returned by the + * underlying allocation code. We already know how much memory each + * mutex in the array will take up, but we need to offset the first + * mutex in the array so the array begins properly aligned. * * The OOB mutex (MUTEX_INVALID) is 0. To make this work, we ignore * the first allocated slot when we build the free list. We have to * correct the count by 1 here, though, otherwise our counter will be * off by 1. */ - if ((ret = __db_shalloc(&mtxmgr->reginfo, + if ((ret = __env_alloc(&mtxmgr->reginfo, + mtxregion->stat.st_mutex_align + (mtxregion->stat.st_mutex_cnt + 1) * mtxregion->mutex_size, - mtxregion->stat.st_mutex_align, &mutex_array)) != 0) { + &mutex_array)) != 0) { __db_errx(dbenv, "Unable to allocate memory for mutexes from the region"); return (ret); } - mtxregion->mutex_offset = R_OFFSET(&mtxmgr->reginfo, mutex_array); + mtxregion->mutex_off_alloc = R_OFFSET(&mtxmgr->reginfo, mutex_array); + mutex_array = ALIGNP_INC(mutex_array, mtxregion->stat.st_mutex_align); + mtxregion->mutex_off = R_OFFSET(&mtxmgr->reginfo, mutex_array); mtxmgr->mutex_array = mutex_array; /* @@ -225,13 +225,13 @@ __mutex_region_init(dbenv, mtxmgr) } /* - * __mutex_dbenv_refresh -- + * __mutex_env_refresh -- * Clean up after the mutex region on a close or failed open. * - * PUBLIC: int __mutex_dbenv_refresh __P((DB_ENV *)); + * PUBLIC: int __mutex_env_refresh __P((DB_ENV *)); */ int -__mutex_dbenv_refresh(dbenv) +__mutex_env_refresh(dbenv) DB_ENV *dbenv; { DB_MUTEXMGR *mtxmgr; @@ -257,12 +257,12 @@ __mutex_dbenv_refresh(dbenv) __mutex_resource_return(dbenv, reginfo); #endif /* Discard the mutex array. */ - __db_shalloc_free( - reginfo, R_ADDR(reginfo, mtxregion->mutex_offset)); + __env_alloc_free( + reginfo, R_ADDR(reginfo, mtxregion->mutex_off_alloc)); } /* Detach from the region. */ - ret = __db_r_detach(dbenv, reginfo, 0); + ret = __env_region_detach(dbenv, reginfo, 0); __os_free(dbenv, mtxmgr); @@ -272,6 +272,18 @@ __mutex_dbenv_refresh(dbenv) } /* + * __mutex_align_size -- + * Return how much memory each mutex will take up if an array of them + * are to be properly aligned, individually, within the array. + */ +static size_t +__mutex_align_size(dbenv) + DB_ENV *dbenv; +{ + return ((size_t)DB_ALIGN(sizeof(DB_MUTEX), (dbenv)->mutex_align)); +} + +/* * __mutex_region_size -- * Return the amount of space needed for the mutex region. */ @@ -282,16 +294,11 @@ __mutex_region_size(dbenv) size_t s; s = sizeof(DB_MUTEXMGR) + 1024; - s += dbenv->mutex_cnt * - __db_shalloc_size(sizeof(DB_MUTEX), dbenv->mutex_align); - /* - * Allocate space for thread info blocks. Max is only advisory, - * so we allocate 25% more. - */ - s += (dbenv->thr_max + dbenv->thr_max/4) * - __db_shalloc_size(sizeof(DB_THREAD_INFO), sizeof(roff_t)); - s += dbenv->thr_nbucket * - __db_shalloc_size(sizeof(DB_HASHTAB), sizeof(roff_t)); + + /* We discard one mutex for the OOB slot. */ + s += __env_alloc_size( + (dbenv->mutex_cnt + 1) *__mutex_align_size(dbenv)); + return (s); } @@ -320,8 +327,8 @@ __mutex_resource_return(dbenv, infop) * * Walk the list of mutexes and destroy any live ones. * - * This is just like joining a region -- the REGINFO we're handed - * is the same as the one returned by __db_r_attach(), all we have + * This is just like joining a region -- the REGINFO we're handed is + * the same as the one returned by __env_region_attach(), all we have * to do is fill in the links. * * !!! @@ -334,7 +341,7 @@ __mutex_resource_return(dbenv, infop) mtxmgr->reginfo = *infop; mtxregion = mtxmgr->reginfo.primary = R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary); - mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_offset); + mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_off); /* * This is a little strange, but the mutex_handle is what all of the diff --git a/db/mutex/mut_stat.c b/db/mutex/mut_stat.c index 1e642fe2f..829d54a8f 100644 --- a/db/mutex/mut_stat.c +++ b/db/mutex/mut_stat.c @@ -1,10 +1,9 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 1996,2007 Oracle. All rights reserved. * - * $Id: mut_stat.c,v 12.17 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_stat.c,v 12.26 2007/05/17 17:18:01 bostic Exp $ */ #include "db_config.h" @@ -19,22 +18,21 @@ static int __mutex_print_all __P((DB_ENV *, u_int32_t)); static const char *__mutex_print_id __P((int)); static int __mutex_print_stats __P((DB_ENV *, u_int32_t)); static void __mutex_print_summary __P((DB_ENV *)); +static int __mutex_stat __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t)); /* - * __mutex_stat -- - * DB_ENV->mutex_stat. + * __mutex_stat_pp -- + * DB_ENV->mutex_stat pre/post processing. * - * PUBLIC: int __mutex_stat __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t)); + * PUBLIC: int __mutex_stat_pp __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t)); */ int -__mutex_stat(dbenv, statp, flags) +__mutex_stat_pp(dbenv, statp, flags) DB_ENV *dbenv; DB_MUTEX_STAT **statp; u_int32_t flags; { - DB_MUTEXMGR *mtxmgr; - DB_MUTEXREGION *mtxregion; - DB_MUTEX_STAT *stats; + DB_THREAD_INFO *ip; int ret; PANIC_CHECK(dbenv); @@ -43,6 +41,29 @@ __mutex_stat(dbenv, statp, flags) "DB_ENV->mutex_stat", flags, DB_STAT_CLEAR)) != 0) return (ret); + ENV_ENTER(dbenv, ip); + REPLICATION_WRAP(dbenv, (__mutex_stat(dbenv, statp, flags)), ret); + ENV_LEAVE(dbenv, ip); + return (ret); +} + +/* + * __mutex_stat -- + * DB_ENV->mutex_stat. + */ +static int +__mutex_stat(dbenv, statp, flags) + DB_ENV *dbenv; + DB_MUTEX_STAT **statp; + u_int32_t flags; +{ + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + DB_MUTEX_STAT *stats; + int ret; + + PANIC_CHECK(dbenv); + *statp = NULL; mtxmgr = dbenv->mutex_handle; mtxregion = mtxmgr->reginfo.primary; @@ -70,17 +91,17 @@ __mutex_stat(dbenv, statp, flags) } /* - * __mutex_stat_print - * DB_ENV->mutex_stat_print method. + * __mutex_stat_print_pp -- + * DB_ENV->mutex_stat_print pre/post processing. * - * PUBLIC: int __mutex_stat_print __P((DB_ENV *, u_int32_t)); + * PUBLIC: int __mutex_stat_print_pp __P((DB_ENV *, u_int32_t)); */ int -__mutex_stat_print(dbenv, flags) +__mutex_stat_print_pp(dbenv, flags) DB_ENV *dbenv; u_int32_t flags; { - u_int32_t orig_flags; + DB_THREAD_INFO *ip; int ret; PANIC_CHECK(dbenv); @@ -89,8 +110,28 @@ __mutex_stat_print(dbenv, flags) flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0) return (ret); + ENV_ENTER(dbenv, ip); + REPLICATION_WRAP(dbenv, (__mutex_stat_print(dbenv, flags)), ret); + ENV_LEAVE(dbenv, ip); + return (ret); +} + +/* + * __mutex_stat_print + * DB_ENV->mutex_stat_print method. + * + * PUBLIC: int __mutex_stat_print __P((DB_ENV *, u_int32_t)); + */ +int +__mutex_stat_print(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + u_int32_t orig_flags; + int ret; + orig_flags = flags; - LF_CLR(DB_STAT_CLEAR); + LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM); if (flags == 0 || LF_ISSET(DB_STAT_ALL)) { ret = __mutex_print_stats(dbenv, orig_flags); __mutex_print_summary(dbenv); @@ -149,10 +190,6 @@ __mutex_print_stats(dbenv, flags) u_int32_t flags; { DB_MUTEX_STAT *sp; - DB_MUTEXMGR *mtxmgr; - DB_MUTEXREGION *mtxregion; - REGINFO *infop; - THREAD_INFO *thread; int ret; if ((ret = __mutex_stat(dbenv, &sp, LF_ISSET(DB_STAT_CLEAR))) != 0) @@ -176,20 +213,6 @@ __mutex_print_stats(dbenv, flags) __os_ufree(dbenv, sp); - /* - * Dump out the info we have on thread tracking, we do it here only - * because we share the region. - */ - if (dbenv->thr_hashtab != NULL) { - mtxmgr = dbenv->mutex_handle; - mtxregion = mtxmgr->reginfo.primary; - infop = &mtxmgr->reginfo; - thread = R_ADDR(infop, mtxregion->thread_off); - STAT_ULONG("Thread blocks allocated", thread->thr_count); - STAT_ULONG("Thread allocation threshold", thread->thr_max); - STAT_ULONG("Thread hash buckets", thread->thr_nbucket); - } - return (0); } @@ -222,7 +245,7 @@ __mutex_print_all(dbenv, flags) mtxmgr = dbenv->mutex_handle; mtxregion = mtxmgr->reginfo.primary; - __db_print_reginfo(dbenv, &mtxmgr->reginfo, "Mutex"); + __db_print_reginfo(dbenv, &mtxmgr->reginfo, "Mutex", flags); __db_msg(dbenv, "%s", DB_GLOBAL(db_line)); __db_msg(dbenv, "DB_MUTEXREGION structure:"); @@ -282,6 +305,8 @@ __mutex_print_debug_single(dbenv, tag, mutex, flags) DB_MSGBUF_INIT(&mb); mbp = &mb; + if (LF_ISSET(DB_STAT_SUBSYSTEM)) + LF_CLR(DB_STAT_CLEAR); __db_msgadd(dbenv, mbp, "%lu\t%s ", (u_long)mutex, tag); __mutex_print_debug_stats(dbenv, mbp, mutex, flags); DB_MSGBUF_FLUSH(dbenv, mbp); @@ -427,7 +452,7 @@ __mutex_clear(dbenv, mutex) #else /* !HAVE_STATISTICS */ int -__mutex_stat(dbenv, statp, flags) +__mutex_stat_pp(dbenv, statp, flags) DB_ENV *dbenv; DB_MUTEX_STAT **statp; u_int32_t flags; @@ -439,7 +464,7 @@ __mutex_stat(dbenv, statp, flags) } int -__mutex_stat_print(dbenv, flags) +__mutex_stat_print_pp(dbenv, flags) DB_ENV *dbenv; u_int32_t flags; { diff --git a/db/mutex/mut_stub.c b/db/mutex/mut_stub.c new file mode 100644 index 000000000..d4620c771 --- /dev/null +++ b/db/mutex/mut_stub.c @@ -0,0 +1,234 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996,2007 Oracle. All rights reserved. + * + * $Id: mut_stub.c,v 12.4 2007/05/17 15:15:45 bostic Exp $ + */ + +#ifndef HAVE_MUTEX_SUPPORT +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" + +/* + * If the library wasn't compiled with mutex support, various routines + * aren't available. Stub them here, returning an appropriate error. + */ +static int __db_nomutex __P((DB_ENV *)); + +/* + * __db_nomutex -- + * Error when a Berkeley DB build doesn't include mutexes. + */ +static int +__db_nomutex(dbenv) + DB_ENV *dbenv; +{ + __db_errx(dbenv, + "library build did not include support for mutexes"); + return (DB_OPNOTSUP); +} + +int +__mutex_alloc_pp(dbenv, flags, indxp) + DB_ENV *dbenv; + u_int32_t flags; + db_mutex_t *indxp; +{ + COMPQUIET(flags, 0); + COMPQUIET(indxp, NULL); + return (__db_nomutex(dbenv)); +} + +int +__mutex_alloc(dbenv, alloc_id, flags, indxp) + DB_ENV *dbenv; + int alloc_id; + u_int32_t flags; + db_mutex_t *indxp; +{ + COMPQUIET(dbenv, NULL); + COMPQUIET(alloc_id, 0); + COMPQUIET(flags, 0); + *indxp = MUTEX_INVALID; + return (0); +} + +void +__mutex_clear(dbenv, mutex) + DB_ENV *dbenv; + db_mutex_t mutex; +{ + COMPQUIET(dbenv, NULL); + COMPQUIET(mutex, MUTEX_INVALID); +} + +int +__mutex_free_pp(dbenv, indx) + DB_ENV *dbenv; + db_mutex_t indx; +{ + COMPQUIET(indx, 0); + return (__db_nomutex(dbenv)); +} + +int +__mutex_free(dbenv, indxp) + DB_ENV *dbenv; + db_mutex_t *indxp; +{ + COMPQUIET(dbenv, NULL); + *indxp = MUTEX_INVALID; + return (0); +} + +int +__mutex_get_align(dbenv, alignp) + DB_ENV *dbenv; + u_int32_t *alignp; +{ + COMPQUIET(alignp, NULL); + return (__db_nomutex(dbenv)); +} + +int +__mutex_get_increment(dbenv, incrementp) + DB_ENV *dbenv; + u_int32_t *incrementp; +{ + COMPQUIET(incrementp, NULL); + return (__db_nomutex(dbenv)); +} + +int +__mutex_get_max(dbenv, maxp) + DB_ENV *dbenv; + u_int32_t *maxp; +{ + COMPQUIET(maxp, NULL); + return (__db_nomutex(dbenv)); +} + +int +__mutex_get_tas_spins(dbenv, tas_spinsp) + DB_ENV *dbenv; + u_int32_t *tas_spinsp; +{ + COMPQUIET(tas_spinsp, NULL); + return (__db_nomutex(dbenv)); +} + +int +__mutex_lock_pp(dbenv, indx) + DB_ENV *dbenv; + db_mutex_t indx; +{ + COMPQUIET(indx, 0); + return (__db_nomutex(dbenv)); +} + +void +__mutex_print_debug_single(dbenv, tag, mutex, flags) + DB_ENV *dbenv; + const char *tag; + db_mutex_t mutex; + u_int32_t flags; +{ + COMPQUIET(dbenv, NULL); + COMPQUIET(tag, NULL); + COMPQUIET(mutex, MUTEX_INVALID); + COMPQUIET(flags, 0); +} + +void +__mutex_print_debug_stats(dbenv, mbp, mutex, flags) + DB_ENV *dbenv; + DB_MSGBUF *mbp; + db_mutex_t mutex; + u_int32_t flags; +{ + COMPQUIET(dbenv, NULL); + COMPQUIET(mbp, NULL); + COMPQUIET(mutex, MUTEX_INVALID); + COMPQUIET(flags, 0); +} + +int +__mutex_set_align(dbenv, align) + DB_ENV *dbenv; + u_int32_t align; +{ + COMPQUIET(align, 0); + return (__db_nomutex(dbenv)); +} + +int +__mutex_set_increment(dbenv, increment) + DB_ENV *dbenv; + u_int32_t increment; +{ + COMPQUIET(increment, 0); + return (__db_nomutex(dbenv)); +} + +int +__mutex_set_max(dbenv, max) + DB_ENV *dbenv; + u_int32_t max; +{ + COMPQUIET(max, 0); + return (__db_nomutex(dbenv)); +} + +int +__mutex_set_tas_spins(dbenv, tas_spins) + DB_ENV *dbenv; + u_int32_t tas_spins; +{ + COMPQUIET(tas_spins, 0); + return (__db_nomutex(dbenv)); +} + +void +__mutex_set_wait_info(dbenv, mutex, waitp, nowaitp) + DB_ENV *dbenv; + db_mutex_t mutex; + u_int32_t *waitp, *nowaitp; +{ + COMPQUIET(dbenv, NULL); + COMPQUIET(mutex, MUTEX_INVALID); + *waitp = *nowaitp = 0; +} + +int +__mutex_stat_pp(dbenv, statp, flags) + DB_ENV *dbenv; + DB_MUTEX_STAT **statp; + u_int32_t flags; +{ + COMPQUIET(statp, NULL); + COMPQUIET(flags, 0); + return (__db_nomutex(dbenv)); +} + +int +__mutex_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_nomutex(dbenv)); +} + +int +__mutex_unlock_pp(dbenv, indx) + DB_ENV *dbenv; + db_mutex_t indx; +{ + COMPQUIET(indx, 0); + return (__db_nomutex(dbenv)); +} +#endif /* !HAVE_MUTEX_SUPPORT */ diff --git a/db/mutex/mut_tas.c b/db/mutex/mut_tas.c index bbe25fa8e..c9f3cddcf 100644 --- a/db/mutex/mut_tas.c +++ b/db/mutex/mut_tas.c @@ -1,10 +1,9 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 1996,2007 Oracle. All rights reserved. * - * $Id: mut_tas.c,v 12.20 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_tas.c,v 12.27 2007/06/21 16:39:20 ubell Exp $ */ #include "db_config.h" @@ -12,7 +11,7 @@ #include "db_int.h" /* - * This is where we load in the actual test-and-set mutex code. + * This is where we load in architecture/compiler specific mutex code. */ #define LOAD_ACTUAL_MUTEX_CODE #include "dbinc/mutex_int.h" @@ -51,6 +50,11 @@ __db_tas_mutex_init(dbenv, mutex, flags) __db_syserr(dbenv, ret, "TAS: mutex initialize"); return (__os_posix_err(ret)); } +#ifdef HAVE_MUTEX_HYBRID + if ((ret = __db_pthread_mutex_init(dbenv, + mutex, flags | DB_MUTEX_SELF_BLOCK)) != 0) + return (ret); +#endif return (0); } @@ -69,8 +73,11 @@ __db_tas_mutex_lock(dbenv, mutex) DB_MUTEXMGR *mtxmgr; DB_MUTEXREGION *mtxregion; u_int32_t nspins; +#ifdef HAVE_MUTEX_HYBRID + int ret; +#else u_long ms, max_ms; - +#endif if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) return (0); @@ -85,6 +92,7 @@ __db_tas_mutex_lock(dbenv, mutex) ++mutexp->mutex_set_nowait; #endif +#ifndef HAVE_MUTEX_HYBRID /* * Wait 1ms initially, up to 10ms for mutexes backing logical database * locks, and up to 25 ms for mutual exclusion data structure mutexes. @@ -92,6 +100,7 @@ __db_tas_mutex_lock(dbenv, mutex) */ ms = 1; max_ms = F_ISSET(mutexp, DB_MUTEX_LOGICAL_LOCK) ? 10 : 25; +#endif loop: /* Attempt to acquire the resource for N spins. */ for (nspins = @@ -167,9 +176,14 @@ relock: } /* Wait for the lock to become available. */ - __os_sleep(dbenv, 0, ms * USEC_PER_MS); +#ifdef HAVE_MUTEX_HYBRID + if ((ret = __db_pthread_mutex_lock(dbenv, mutex)) != 0) + return (ret); +#else + __os_sleep(dbenv, 0, ms * US_PER_MS); if ((ms <<= 1) > max_ms) ms = max_ms; +#endif /* * We're spinning. The environment might be hung, and somebody else @@ -196,6 +210,9 @@ __db_tas_mutex_unlock(dbenv, mutex) DB_MUTEX *mutexp; DB_MUTEXMGR *mtxmgr; DB_MUTEXREGION *mtxregion; +#ifdef HAVE_MUTEX_HYBRID + int ret; +#endif if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) return (0); @@ -210,8 +227,15 @@ __db_tas_mutex_unlock(dbenv, mutex) return (__db_panic(dbenv, EACCES)); } #endif + F_CLR(mutexp, DB_MUTEX_LOCKED); +#ifdef HAVE_MUTEX_HYBRID + MUTEX_MEMBAR(mutexp->flags); + if (mutexp->wait && + (ret = __db_pthread_mutex_unlock(dbenv, mutex)) != 0) + return (ret); +#endif MUTEX_UNSET(&mutexp->tas); return (0); @@ -231,6 +255,9 @@ __db_tas_mutex_destroy(dbenv, mutex) DB_MUTEX *mutexp; DB_MUTEXMGR *mtxmgr; DB_MUTEXREGION *mtxregion; +#ifdef HAVE_MUTEX_HYBRID + int ret; +#endif if (!MUTEX_ON(dbenv)) return (0); @@ -241,5 +268,11 @@ __db_tas_mutex_destroy(dbenv, mutex) MUTEX_DESTROY(&mutexp->tas); +#ifdef HAVE_MUTEX_HYBRID + if ((ret = __db_pthread_mutex_destroy(dbenv, mutex)) != 0) + return (ret); +#endif + + COMPQUIET(mutexp, NULL); /* MUTEX_DESTROY may not be defined. */ return (0); } diff --git a/db/mutex/mut_win32.c b/db/mutex/mut_win32.c index 083784310..2d0385e90 100644 --- a/db/mutex/mut_win32.c +++ b/db/mutex/mut_win32.c @@ -1,10 +1,9 @@ /* * See the file LICENSE for redistribution information. * - * Copyright (c) 2002-2006 - * Oracle Corporation. All rights reserved. + * Copyright (c) 2002,2007 Oracle. All rights reserved. * - * $Id: mut_win32.c,v 12.21 2006/08/24 14:46:16 bostic Exp $ + * $Id: mut_win32.c,v 12.25 2007/06/28 11:14:04 alexg Exp $ */ #include "db_config.h" @@ -48,6 +47,7 @@ static __inline int get_handle(dbenv, mutexp, eventp) for (id = (mutexp)->id; id != 0; id >>= 4) *--p = hex_digits[id & 0xf]; +#ifndef DB_WINCE if (!security_initialized) { InitializeSecurityDescriptor(&null_sd, SECURITY_DESCRIPTOR_REVISION); @@ -57,6 +57,7 @@ static __inline int get_handle(dbenv, mutexp, eventp) all_sa.lpSecurityDescriptor = &null_sd; security_initialized = 1; } +#endif if ((*eventp = CreateEvent(&all_sa, FALSE, FALSE, idbuf)) == NULL) { ret = __os_get_syserr(); @@ -111,6 +112,9 @@ __db_win32_mutex_lock(dbenv, mutex) #ifdef MUTEX_DIAG LARGE_INTEGER now; #endif +#ifdef DB_WINCE + volatile db_threadid_t tmp_tid; +#endif if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) return (0); @@ -130,6 +134,20 @@ loop: /* Attempt to acquire the resource for N spins. */ * We can avoid the (expensive) interlocked instructions if * the mutex is already "set". */ +#ifdef DB_WINCE + /* + * Memory mapped regions on Windows CE cause problems with + * InterlockedExchange calls. Each page in a mapped region + * needs to have been written to prior to an + * InterlockedExchange call, or the InterlockedExchange call + * hangs. This does not seem to be documented anywhere. For + * now, read/write a non-critical piece of memory from the + * shared region prior to attempting an InterlockedExchange + * operation. + */ + tmp_tid = mutexp->tid; + mutexp->tid = tmp_tid; +#endif if (mutexp->tas || !MUTEX_SET(&mutexp->tas)) { /* * Some systems (notably those with newer Intel CPUs) diff --git a/db/mutex/mutex.c b/db/mutex/mutex.c deleted file mode 100644 index 9d925d113..000000000 --- a/db/mutex/mutex.c +++ /dev/null @@ -1,392 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1999-2004 - * Sleepycat Software. All rights reserved. - * - * $Id: mutex.c,v 11.43 2004/10/15 16:59:44 bostic Exp $ - */ - -#include "db_config.h" - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - -#include "db_int.h" - -#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES) -#include "dbinc/db_shash.h" -#include "dbinc/lock.h" -#include "dbinc/log.h" -#include "dbinc/mp.h" -#include "dbinc/txn.h" -#endif - -static int __db_mutex_alloc_int __P((DB_ENV *, REGINFO *, DB_MUTEX **)); -#ifdef HAVE_MUTEX_SYSTEM_RESOURCES -static REGMAINT * __db_mutex_maint __P((DB_ENV *, REGINFO *)); -#endif - -/* - * __db_mutex_setup -- - * External interface to allocate, and/or initialize, record - * mutexes. - * - * PUBLIC: int __db_mutex_setup __P((DB_ENV *, REGINFO *, void *, u_int32_t)); - */ -int -__db_mutex_setup(dbenv, infop, ptr, flags) - DB_ENV *dbenv; - REGINFO *infop; - void *ptr; - u_int32_t flags; -{ - DB_MUTEX *mutex; - REGMAINT *maint; - u_int32_t iflags, offset; - int ret; - - ret = 0; - /* - * If they indicated the region is not locked, then lock it. - * This is only needed when we have unusual mutex resources. - * (I.e. MUTEX_NO_MALLOC_LOCKS or HAVE_MUTEX_SYSTEM_RESOURCES) - */ -#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES) - if (!LF_ISSET(MUTEX_NO_RLOCK)) - R_LOCK(dbenv, infop); -#endif - /* - * Allocate the mutex if they asked us to. - */ - mutex = NULL; - if (LF_ISSET(MUTEX_ALLOC)) { - if ((ret = __db_mutex_alloc_int(dbenv, infop, ptr)) != 0) - goto err; - mutex = *(DB_MUTEX **)ptr; - } else - mutex = (DB_MUTEX *)ptr; - - /* - * Set up to initialize the mutex. - */ - iflags = LF_ISSET(MUTEX_LOGICAL_LOCK | MUTEX_THREAD | MUTEX_SELF_BLOCK); - switch (infop->type) { - case REGION_TYPE_LOCK: - offset = P_TO_UINT32(mutex) + DB_FCNTL_OFF_LOCK; - break; - case REGION_TYPE_MPOOL: - offset = P_TO_UINT32(mutex) + DB_FCNTL_OFF_MPOOL; - break; - default: - offset = P_TO_UINT32(mutex) + DB_FCNTL_OFF_GEN; - break; - } - maint = NULL; -#ifdef HAVE_MUTEX_SYSTEM_RESOURCES - if (!LF_ISSET(MUTEX_NO_RECORD)) - maint = (REGMAINT *)__db_mutex_maint(dbenv, infop); -#endif - - ret = __db_mutex_init(dbenv, mutex, offset, iflags, infop, maint); -err: -#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES) - if (!LF_ISSET(MUTEX_NO_RLOCK)) - R_UNLOCK(dbenv, infop); -#endif - /* - * If we allocated the mutex but had an error on init'ing, - * then we must free it before returning. - * !!! - * Free must be done after releasing region lock. - */ - if (ret != 0 && LF_ISSET(MUTEX_ALLOC) && mutex != NULL) { - __db_mutex_free(dbenv, infop, mutex); - *(DB_MUTEX **)ptr = NULL; - } - return (ret); -} - -/* - * __db_mutex_alloc_int -- - * Allocate and initialize a mutex. - */ -static int -__db_mutex_alloc_int(dbenv, infop, storep) - DB_ENV *dbenv; - REGINFO *infop; - DB_MUTEX **storep; -{ - int ret; - - /* - * If the architecture supports mutexes in heap memory, use heap memory. - * If it doesn't, we have to allocate space in a region. If allocation - * in the region fails, fallback to allocating from the mpool region, - * because it's big, it almost always exists and if it's entirely dirty, - * we can free buffers until memory is available. - */ -#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES) - ret = __db_shalloc(infop, sizeof(DB_MUTEX), MUTEX_ALIGN, storep); - - if (ret == ENOMEM && MPOOL_ON(dbenv)) { - DB_MPOOL *dbmp; - - dbmp = dbenv->mp_handle; - if ((ret = __memp_alloc(dbmp, - dbmp->reginfo, NULL, sizeof(DB_MUTEX), NULL, storep)) == 0) - (*storep)->flags = MUTEX_MPOOL; - } else - (*storep)->flags = 0; -#else - COMPQUIET(dbenv, NULL); - COMPQUIET(infop, NULL); - ret = __os_calloc(dbenv, 1, sizeof(DB_MUTEX), storep); -#endif - if (ret != 0) - __db_err(dbenv, "Unable to allocate memory for mutex"); - return (ret); -} - -/* - * __db_mutex_free -- - * Free a mutex. - * - * PUBLIC: void __db_mutex_free __P((DB_ENV *, REGINFO *, DB_MUTEX *)); - */ -void -__db_mutex_free(dbenv, infop, mutexp) - DB_ENV *dbenv; - REGINFO *infop; - DB_MUTEX *mutexp; -{ -#if defined(MUTEX_NO_MALLOC_LOCKS) || defined(HAVE_MUTEX_SYSTEM_RESOURCES) - R_LOCK(dbenv, infop); -#if defined(HAVE_MUTEX_SYSTEM_RESOURCES) - if (F_ISSET(mutexp, MUTEX_INITED)) - __db_shlocks_clear(mutexp, infop, NULL); -#endif - if (F_ISSET(mutexp, MUTEX_MPOOL)) { - DB_MPOOL *dbmp; - - dbmp = dbenv->mp_handle; - R_LOCK(dbenv, dbmp->reginfo); - __db_shalloc_free(&dbmp->reginfo[0], mutexp); - R_UNLOCK(dbenv, dbmp->reginfo); - } else - __db_shalloc_free(infop, mutexp); - R_UNLOCK(dbenv, infop); -#else - COMPQUIET(dbenv, NULL); - COMPQUIET(infop, NULL); - __os_free(dbenv, mutexp); -#endif -} - -#ifdef HAVE_MUTEX_SYSTEM_RESOURCES -/* - * __db_shreg_locks_record -- - * Record an entry in the shared locks area. - * Region lock must be held in caller. - */ -static int -__db_shreg_locks_record(dbenv, mutexp, infop, rp) - DB_ENV *dbenv; - DB_MUTEX *mutexp; - REGINFO *infop; - REGMAINT *rp; -{ - u_int i; - - if (!F_ISSET(mutexp, MUTEX_INITED)) - return (0); - DB_ASSERT(mutexp->reg_off == INVALID_ROFF); - rp->stat.st_records++; - i = (roff_t *)R_ADDR(infop, rp->regmutex_hint) - &rp->regmutexes[0]; - if (rp->regmutexes[i] != INVALID_ROFF) { - /* - * Our hint failed, search for an open slot. - */ - rp->stat.st_hint_miss++; - for (i = 0; i < rp->reglocks; i++) - if (rp->regmutexes[i] == INVALID_ROFF) - break; - if (i == rp->reglocks) { - rp->stat.st_max_locks++; - __db_err(dbenv, - "Region mutexes: Exceeded maximum lock slots %lu", - (u_long)rp->reglocks); - return (ENOMEM); - } - } else - rp->stat.st_hint_hit++; - /* - * When we get here, i is an empty slot. Record this - * mutex, set hint to point to the next slot and we are done. - */ - rp->regmutexes[i] = R_OFFSET(infop, mutexp); - mutexp->reg_off = R_OFFSET(infop, &rp->regmutexes[i]); - rp->regmutex_hint = (i < rp->reglocks - 1) ? - R_OFFSET(infop, &rp->regmutexes[i+1]) : - R_OFFSET(infop, &rp->regmutexes[0]); - return (0); -} - -/* - * __db_shreg_locks_clear -- - * Erase an entry in the shared locks area. - * - * PUBLIC: void __db_shreg_locks_clear __P((DB_MUTEX *, REGINFO *, REGMAINT *)); - */ -void -__db_shreg_locks_clear(mutexp, infop, rp) - DB_MUTEX *mutexp; - REGINFO *infop; - REGMAINT *rp; -{ - /* - * !!! - * Assumes the caller's region lock is held. - */ - if (!F_ISSET(mutexp, MUTEX_INITED)) - return; - /* - * This function is generally only called on a forcible remove of an - * environment. We recorded our index in the mutex, find and clear it. - */ - DB_ASSERT(mutexp->reg_off != INVALID_ROFF); - DB_ASSERT(*(roff_t *)R_ADDR(infop, mutexp->reg_off) == \ - R_OFFSET(infop, mutexp)); - *(roff_t *)R_ADDR(infop, mutexp->reg_off) = 0; - if (rp != NULL) { - rp->regmutex_hint = mutexp->reg_off; - rp->stat.st_clears++; - } - mutexp->reg_off = INVALID_ROFF; - __db_mutex_destroy(mutexp); -} - -/* - * __db_shreg_locks_destroy -- - * Destroy all mutexes in a region's range. - * - * PUBLIC: void __db_shreg_locks_destroy __P((REGINFO *, REGMAINT *)); - */ -void -__db_shreg_locks_destroy(infop, rp) - REGINFO *infop; - REGMAINT *rp; -{ - u_int32_t i; - - /* - * Go through the list of all mutexes and destroy them. - */ - for (i = 0; i < rp->reglocks; i++) - if (rp->regmutexes[i] != 0) { - rp->stat.st_destroys++; - __db_mutex_destroy(R_ADDR(infop, rp->regmutexes[i])); - } -} - -/* - * __db_shreg_mutex_init -- - * Initialize a shared memory mutex. - * - * PUBLIC: int __db_shreg_mutex_init __P((DB_ENV *, DB_MUTEX *, u_int32_t, - * PUBLIC: u_int32_t, REGINFO *, REGMAINT *)); - */ -int -__db_shreg_mutex_init(dbenv, mutexp, offset, flags, infop, rp) - DB_ENV *dbenv; - DB_MUTEX *mutexp; - u_int32_t offset; - u_int32_t flags; - REGINFO *infop; - REGMAINT *rp; -{ - int ret; - - if ((ret = __db_mutex_init_int(dbenv, mutexp, offset, flags)) != 0) - return (ret); - /* - * Some mutexes cannot be recorded, but we want one interface. - * So, if we have no REGMAINT, then just return. - */ - if (rp == NULL) - return (ret); - /* - * !!! - * Since __db_mutex_init_int is a macro, we may not be - * using the 'offset' as it is only used for one type - * of mutex. We COMPQUIET it here, after the call above. - */ - COMPQUIET(offset, 0); - ret = __db_shreg_locks_record(dbenv, mutexp, infop, rp); - - /* - * If we couldn't record it and we are returning an error, - * we need to destroy the mutex we just created. - */ - if (ret) - __db_mutex_destroy(mutexp); - - return (ret); -} - -/* - * __db_shreg_maintinit -- - * Initialize a region's maintenance information. - * - * PUBLIC: void __db_shreg_maintinit __P((REGINFO *, void *addr, size_t)); - */ -void -__db_shreg_maintinit(infop, addr, size) - REGINFO *infop; - void *addr; - size_t size; -{ - REGMAINT *rp; - u_int32_t i; - - rp = (REGMAINT *)addr; - memset(addr, 0, sizeof(REGMAINT)); - rp->reglocks = size / sizeof(roff_t); - rp->regmutex_hint = R_OFFSET(infop, &rp->regmutexes[0]); - for (i = 0; i < rp->reglocks; i++) - rp->regmutexes[i] = INVALID_ROFF; -} - -static REGMAINT * -__db_mutex_maint(dbenv, infop) - DB_ENV *dbenv; - REGINFO *infop; -{ - roff_t moff; - - switch (infop->type) { - case REGION_TYPE_LOCK: - moff = ((DB_LOCKREGION *) - R_ADDR(infop, infop->rp->primary))->maint_off; - break; - case REGION_TYPE_LOG: - moff = ((LOG *)R_ADDR(infop, infop->rp->primary))->maint_off; - break; - case REGION_TYPE_MPOOL: - moff = ((MPOOL *)R_ADDR(infop, infop->rp->primary))->maint_off; - break; - case REGION_TYPE_TXN: - moff = ((DB_TXNREGION *) - R_ADDR(infop, infop->rp->primary))->maint_off; - break; - default: - __db_err(dbenv, - "Attempting to record mutex in a region not set up to do so"); - return (NULL); - } - return ((REGMAINT *)R_ADDR(infop, moff)); -} -#endif /* HAVE_MUTEX_SYSTEM_RESOURCES */ diff --git a/db/mutex/tm.c b/db/mutex/test_mutex.c index de647fa1f..b0fc8397b 100644 --- a/db/mutex/tm.c +++ b/db/mutex/test_mutex.c @@ -1,7 +1,7 @@ /* * Standalone mutex tester for Berkeley DB mutexes. * - * $Id: tm.c,v 12.14 2006/07/17 15:16:46 bostic Exp $ + * $Id: test_mutex.c,v 12.21 2007/06/21 16:02:29 bostic Exp $ */ #include "db_config.h" @@ -10,11 +10,9 @@ #include <sys/wait.h> -#if defined(MUTEX_THREAD_TEST) -#include <pthread.h> -#endif - #ifdef DB_WIN32 +#define MUTEX_THREAD_TEST 1 + extern int getopt(int, char * const *, const char *); typedef HANDLE os_pid_t; @@ -32,24 +30,38 @@ typedef HANDLE os_thread_t; typedef pid_t os_pid_t; -#ifdef MUTEX_THREAD_TEST +/* + * There's only one mutex implementation that can't support thread-level + * locking: UNIX/fcntl mutexes. + * + * The general Berkeley DB library configuration doesn't look for the POSIX + * pthread functions, with one exception -- pthread_yield. + * + * Use these two facts to decide if we're going to build with or without + * threads. + */ +#if !defined(HAVE_MUTEX_FCNTL) && defined(HAVE_PTHREAD_YIELD) +#define MUTEX_THREAD_TEST 1 + +#include <pthread.h> + typedef pthread_t os_thread_t; -#endif #define os_thread_create(thrp, attr, func, arg) \ pthread_create((thrp), (attr), (func), (arg)) #define os_thread_join(thr, statusp) pthread_join((thr), (statusp)) #define os_thread_self() pthread_self() -#endif +#endif /* HAVE_PTHREAD_YIELD */ +#endif /* !DB_WIN32 */ -#define OS_BAD_PID (os_pid_t)-1 +#define OS_BAD_PID ((os_pid_t)-1) #define TESTDIR "TESTDIR" /* Working area */ #define MT_FILE "TESTDIR/mutex.file" #define MT_FILE_QUIT "TESTDIR/mutex.file.quit" /* - * The backing file layout: + * The backing data layout: * TM[1] per-thread mutex array lock * TM[nthreads] per-thread mutex array * TM[maxlocks] per-lock mutex array @@ -61,7 +73,7 @@ typedef struct { } TM; DB_ENV *dbenv; /* Backing environment */ -size_t len; /* Backing file size. */ +size_t len; /* Backing data chunk size. */ u_int8_t *gm_addr; /* Global mutex */ u_int8_t *lm_addr; /* Locker mutexes */ @@ -72,27 +84,37 @@ os_thread_t *kidsp; /* Locker threads */ os_thread_t wakep; /* Wakeup thread */ #endif -int maxlocks = 20; /* -l: Backing locks. */ -int nlocks = 10000; /* -n: Locks per processes. */ -int nprocs = 20; /* -p: Processes. */ -int nthreads = 1; /* -t: Threads. */ -int verbose; /* -v: Verbosity. */ +#ifndef HAVE_MMAP +u_int nprocs = 1; /* -p: Processes. */ +u_int nthreads = 20; /* -t: Threads. */ +#elif MUTEX_THREAD_TEST +u_int nprocs = 5; /* -p: Processes. */ +u_int nthreads = 4; /* -t: Threads. */ +#else +u_int nprocs = 20; /* -p: Processes. */ +u_int nthreads = 1; /* -t: Threads. */ +#endif + +u_int maxlocks = 20; /* -l: Backing locks. */ +u_int nlocks = 10000; /* -n: Locks per process. */ +int verbose; /* -v: Verbosity. */ +const char *progname; + +void data_off(u_int8_t *, DB_FH *); +void data_on(u_int8_t **, u_int8_t **, u_int8_t **, DB_FH **, int); int locker_start(u_long); int locker_wait(void); -void map_file(u_int8_t **, u_int8_t **, u_int8_t **, DB_FH **); os_pid_t os_spawn(const char *, char *const[]); -int os_wait(os_pid_t *, int); +int os_wait(os_pid_t *, u_int); void *run_lthread(void *); void *run_wthread(void *); os_pid_t spawn_proc(u_long, char *, char *); void tm_env_close(void); int tm_env_init(void); -void tm_file_init(void); void tm_mutex_destroy(void); void tm_mutex_init(void); void tm_mutex_stats(void); -void unmap_file(u_int8_t *, DB_FH *); int usage(void); int wakeup_start(u_long); int wakeup_wait(void); @@ -107,31 +129,38 @@ main(argc, argv) extern char *optarg; os_pid_t wakeup_pid, *pids; u_long id; + u_int i; DB_FH *fhp, *map_fhp; - int ch, err, i; + int ch, err; char *p, *tmpath, cmd[1024]; + if ((progname = __db_rpath(argv[0])) == NULL) + progname = argv[0]; + else + ++progname; + rtype = PARENT; id = 0; tmpath = argv[0]; while ((ch = getopt(argc, argv, "l:n:p:T:t:v")) != EOF) switch (ch) { case 'l': - maxlocks = atoi(optarg); + maxlocks = (u_int)atoi(optarg); break; case 'n': - nlocks = atoi(optarg); + nlocks = (u_int)atoi(optarg); break; case 'p': - nprocs = atoi(optarg); + nprocs = (u_int)atoi(optarg); break; case 't': - if ((nthreads = atoi(optarg)) == 0) + if ((nthreads = (u_int)atoi(optarg)) == 0) nthreads = 1; #if !defined(MUTEX_THREAD_TEST) if (nthreads != 1) { - (void)fprintf(stderr, - "tm: thread support not available or not compiled for this platform.\n"); + fprintf(stderr, + "%s: thread support not available or not compiled for this platform.\n", + progname); return (EXIT_FAILURE); } #endif @@ -146,7 +175,7 @@ main(argc, argv) return (usage()); if ((p = strchr(optarg, '=')) == NULL) return (usage()); - id = atoi(p + 1); + id = (u_long)atoi(p + 1); break; case 'v': verbose = 1; @@ -164,7 +193,8 @@ main(argc, argv) */ if (nprocs == 1 && nthreads == 1) { fprintf(stderr, - "tm: running in a single process requires multiple threads\n"); + "%s: running in a single process requires multiple threads\n", + progname); return (EXIT_FAILURE); } @@ -178,12 +208,12 @@ main(argc, argv) if (rtype == LOCKER || rtype == WAKEUP) { __os_sleep(dbenv, 3, 0); /* Let everyone catch up. */ /* Initialize random numbers. */ - srand((u_int)time(NULL) % getpid()); + srand((u_int)time(NULL) % (u_int)getpid()); if (tm_env_init() != 0) /* Join the environment. */ exit(EXIT_FAILURE); - /* Join the backing file. */ - map_file(&gm_addr, &tm_addr, &lm_addr, &map_fhp); + /* Join the backing data. */ + data_on(&gm_addr, &tm_addr, &lm_addr, &map_fhp, 0); if (verbose) printf( "Backing file: global (%#lx), threads (%#lx), locks (%#lx)\n", @@ -195,7 +225,7 @@ main(argc, argv) if ((rtype == LOCKER ? locker_wait() : wakeup_wait()) != 0) exit(EXIT_FAILURE); - unmap_file(gm_addr, map_fhp); /* Detach from backing file. */ + data_off(gm_addr, map_fhp); /* Detach from backing data. */ tm_env_close(); /* Detach from environment. */ @@ -213,20 +243,17 @@ main(argc, argv) (void)system(cmd); printf( - "tm: %d processes, %d threads/process, %d lock requests from %d locks\n", - nprocs, nthreads, nlocks, maxlocks); - printf("tm: backing file %lu bytes\n", (u_long)len); + "%s: %u processes, %u threads/process, %u lock requests from %u locks\n", + progname, nprocs, nthreads, nlocks, maxlocks); + printf("%s: backing data %lu bytes\n", progname, (u_long)len); if (tm_env_init() != 0) /* Create the environment. */ exit(EXIT_FAILURE); - - tm_file_init(); /* Initialize backing file. */ - - /* Map in the backing file. */ - map_file(&gm_addr, &tm_addr, &lm_addr, &map_fhp); + /* Create the backing data. */ + data_on(&gm_addr, &tm_addr, &lm_addr, &map_fhp, 1); if (verbose) printf( - "backing file: global (%#lx), threads (%#lx), locks (%#lx)\n", + "backing data: global (%#lx), threads (%#lx), locks (%#lx)\n", (u_long)gm_addr, (u_long)tm_addr, (u_long)lm_addr); tm_mutex_init(); /* Initialize mutexes. */ @@ -234,7 +261,7 @@ main(argc, argv) if (nprocs > 1) { /* Run the multi-process test. */ /* Allocate array of locker process IDs. */ if ((pids = calloc(nprocs, sizeof(os_pid_t))) == NULL) { - fprintf(stderr, "tm: %s\n", strerror(errno)); + fprintf(stderr, "%s: %s\n", progname, strerror(errno)); goto fail; } @@ -243,7 +270,7 @@ main(argc, argv) if ((pids[i] = spawn_proc(id, tmpath, "locker")) == OS_BAD_PID) { fprintf(stderr, - "tm: failed to spawn a locker\n"); + "%s: failed to spawn a locker\n", progname); goto fail; } id += nthreads; @@ -252,29 +279,32 @@ main(argc, argv) /* Spawn wakeup process/thread. */ if ((wakeup_pid = spawn_proc(id, tmpath, "wakeup")) == OS_BAD_PID) { - fprintf(stderr, "tm: failed to spawn waker\n"); + fprintf(stderr, + "%s: failed to spawn waker\n", progname); goto fail; } ++id; /* Wait for all lockers to exit. */ if ((err = os_wait(pids, nprocs)) != 0) { - fprintf(stderr, "locker wait failed with %d\n", err); + fprintf(stderr, "%s: locker wait failed with %d\n", + progname, err); goto fail; } /* Signal wakeup process to exit. */ if ((err = __os_open( - dbenv, MT_FILE_QUIT, DB_OSO_CREATE, 0664, &fhp)) != 0) { - fprintf(stderr, "tm: open %s\n", db_strerror(err)); + dbenv, MT_FILE_QUIT, 0, DB_OSO_CREATE, 0664, &fhp)) != 0) { + fprintf(stderr, + "%s: open %s\n", progname, db_strerror(err)); goto fail; } (void)__os_closehandle(dbenv, fhp); /* Wait for wakeup process/thread. */ if ((err = os_wait(&wakeup_pid, 1)) != 0) { - fprintf(stderr, - "%lu: exited %d\n", (u_long)wakeup_pid, err); + fprintf(stderr, "%s: %lu: exited %d\n", + progname, (u_long)wakeup_pid, err); goto fail; } } else { /* Run the single-process test. */ @@ -292,8 +322,9 @@ main(argc, argv) /* Signal wakeup process to exit. */ if ((err = __os_open( - dbenv, MT_FILE_QUIT, DB_OSO_CREATE, 0664, &fhp)) != 0) { - fprintf(stderr, "tm: open %s\n", db_strerror(err)); + dbenv, MT_FILE_QUIT, 0, DB_OSO_CREATE, 0664, &fhp)) != 0) { + fprintf(stderr, + "%s: open %s\n", progname, db_strerror(err)); goto fail; } (void)__os_closehandle(dbenv, fhp); @@ -306,14 +337,14 @@ main(argc, argv) tm_mutex_stats(); /* Display run statistics. */ tm_mutex_destroy(); /* Destroy mutexes. */ - unmap_file(gm_addr, map_fhp); /* Detach from backing file. */ + data_off(gm_addr, map_fhp); /* Detach from backing data. */ tm_env_close(); /* Detach from environment. */ - printf("tm: test succeeded\n"); + printf("%s: test succeeded\n", progname); return (EXIT_SUCCESS); -fail: printf("tm: FAILED!\n"); +fail: printf("%s: FAILED!\n", progname); return (EXIT_FAILURE); } @@ -322,7 +353,8 @@ locker_start(id) u_long id; { #if defined(MUTEX_THREAD_TEST) - int err, i; + u_int i; + int err; /* * Spawn off threads. We have nthreads all locking and going to @@ -330,14 +362,14 @@ locker_start(id) */ if ((kidsp = (os_thread_t *)calloc(sizeof(os_thread_t), nthreads)) == NULL) { - fprintf(stderr, "tm: %s\n", strerror(errno)); + fprintf(stderr, "%s: %s\n", progname, strerror(errno)); return (1); } for (i = 0; i < nthreads; i++) if ((err = os_thread_create( &kidsp[i], NULL, run_lthread, (void *)(id + i))) != 0) { - fprintf(stderr, "tm: failed spawning thread: %s\n", - db_strerror(err)); + fprintf(stderr, "%s: failed spawning thread: %s\n", + progname, db_strerror(err)); return (1); } return (0); @@ -350,14 +382,15 @@ int locker_wait() { #if defined(MUTEX_THREAD_TEST) - int i; + u_int i; void *retp; /* Wait for the threads to exit. */ for (i = 0; i < nthreads; i++) { - os_thread_join(kidsp[i], &retp); + (void)os_thread_join(kidsp[i], &retp); if (retp != NULL) { - fprintf(stderr, "tm: thread exited with error\n"); + fprintf(stderr, + "%s: thread exited with error\n", progname); return (1); } } @@ -372,7 +405,8 @@ run_lthread(arg) { TM *gp, *mp, *tp; u_long id, tid; - int err, i, lock, nl; + u_int lock, nl; + int err, i; id = (uintptr_t)arg; #if defined(MUTEX_THREAD_TEST) @@ -388,21 +422,21 @@ run_lthread(arg) for (nl = nlocks; nl > 0;) { /* Select and acquire a data lock. */ - lock = rand() % maxlocks; + lock = (u_int)rand() % maxlocks; mp = (TM *)(lm_addr + lock * sizeof(TM)); if (verbose) printf("%03lu: lock %d (mtx: %lu)\n", id, lock, (u_long)mp->mutex); if ((err = dbenv->mutex_lock(dbenv, mp->mutex)) != 0) { - fprintf(stderr, "%03lu: never got lock %d: %s\n", - id, lock, db_strerror(err)); + fprintf(stderr, "%s: %03lu: never got lock %d: %s\n", + progname, id, lock, db_strerror(err)); return ((void *)1); } if (mp->id != 0) { fprintf(stderr, - "RACE! (%03lu granted lock %d held by %03lu)\n", - id, lock, mp->id); + "%s: RACE! (%03lu granted lock %d held by %03lu)\n", + progname, id, lock, mp->id); return ((void *)1); } mp->id = id; @@ -412,11 +446,11 @@ run_lthread(arg) * we still hold the mutex. */ for (i = 0; i < 3; ++i) { - __os_sleep(dbenv, 0, rand() % 3); + __os_sleep(dbenv, 0, (u_long)rand() % 3); if (mp->id != id) { fprintf(stderr, - "RACE! (%03lu stole lock %d from %03lu)\n", - mp->id, lock, id); + "%s: RACE! (%03lu stole lock %d from %03lu)\n", + progname, mp->id, lock, id); return ((void *)1); } } @@ -432,14 +466,14 @@ run_lthread(arg) * The wakeup thread will wake us up. */ if ((err = dbenv->mutex_lock(dbenv, gp->mutex)) != 0) { - fprintf(stderr, - "%03lu: global lock: %s\n", id, db_strerror(err)); + fprintf(stderr, "%s: %03lu: global lock: %s\n", + progname, id, db_strerror(err)); return ((void *)1); } if (tp->id != 0 && tp->id != id) { fprintf(stderr, - "%03lu: per-thread mutex isn't mine, owned by %03lu\n", - id, tp->id); + "%s: %03lu: per-thread mutex isn't mine, owned by %03lu\n", + progname, id, tp->id); return ((void *)1); } tp->id = id; @@ -448,23 +482,26 @@ run_lthread(arg) id, (u_long)tp->mutex); if (tp->wakeme) { fprintf(stderr, - "%03lu: wakeup flag incorrectly set\n", id); + "%s: %03lu: wakeup flag incorrectly set\n", + progname, id); return ((void *)1); } tp->wakeme = 1; if ((err = dbenv->mutex_unlock(dbenv, gp->mutex)) != 0) { fprintf(stderr, - "%03lu: global unlock: %s\n", id, db_strerror(err)); + "%s: %03lu: global unlock: %s\n", + progname, id, db_strerror(err)); return ((void *)1); } if ((err = dbenv->mutex_lock(dbenv, tp->mutex)) != 0) { - fprintf(stderr, "%03lu: per-thread lock: %s\n", - id, db_strerror(err)); + fprintf(stderr, "%s: %03lu: per-thread lock: %s\n", + progname, id, db_strerror(err)); return ((void *)1); } /* Time passes... */ if (tp->wakeme) { - fprintf(stderr, "%03lu: wakeup flag not cleared\n", id); + fprintf(stderr, "%s: %03lu: wakeup flag not cleared\n", + progname, id); return ((void *)1); } @@ -476,18 +513,13 @@ run_lthread(arg) mp->id = 0; if ((err = dbenv->mutex_unlock(dbenv, mp->mutex)) != 0) { fprintf(stderr, - "%03lu: lock release: %s\n", id, db_strerror(err)); + "%s: %03lu: lock release: %s\n", + progname, id, db_strerror(err)); return ((void *)1); } - if (--nl % 100 == 0) { - fprintf(stderr, "%03lu: %d\n", id, nl); - /* - * Windows buffers stderr and the output looks wrong - * without this. - */ - fflush(stderr); - } + if (--nl % 100 == 0) + printf("%03lu: %d\n", id, nl); } return (NULL); @@ -505,8 +537,8 @@ wakeup_start(id) */ if ((err = os_thread_create( &wakep, NULL, run_wthread, (void *)id)) != 0) { - fprintf(stderr, "tm: failed spawning wakeup thread: %s\n", - db_strerror(err)); + fprintf(stderr, "%s: failed spawning wakeup thread: %s\n", + progname, db_strerror(err)); return (1); } return (0); @@ -524,9 +556,10 @@ wakeup_wait() /* * A file is created when the wakeup thread is no longer needed. */ - os_thread_join(wakep, &retp); + (void)os_thread_join(wakep, &retp); if (retp != NULL) { - fprintf(stderr, "tm: wakeup thread exited with error\n"); + fprintf(stderr, + "%s: wakeup thread exited with error\n", progname); return (1); } #endif @@ -543,7 +576,8 @@ run_wthread(arg) { TM *gp, *tp; u_long id, tid; - int check_id, err; + u_int check_id; + int err; id = (uintptr_t)arg; #if defined(MUTEX_THREAD_TEST) @@ -574,30 +608,30 @@ run_wthread(arg) if (verbose) { printf("%03lu: wakeup thread %03lu (mtx: %lu)\n", id, tp->id, (u_long)tp->mutex); - fflush(stdout); + (void)fflush(stdout); } /* Acquire the global lock. */ if ((err = dbenv->mutex_lock(dbenv, gp->mutex)) != 0) { - fprintf(stderr, - "wakeup: global lock: %s\n", db_strerror(err)); + fprintf(stderr, "%s: wakeup: global lock: %s\n", + progname, db_strerror(err)); return ((void *)1); } tp->wakeme = 0; if ((err = dbenv->mutex_unlock(dbenv, tp->mutex)) != 0) { - fprintf(stderr, - "wakeup: unlock: %s\n", db_strerror(err)); + fprintf(stderr, "%s: wakeup: unlock: %s\n", + progname, db_strerror(err)); return ((void *)1); } - if ((err = dbenv->mutex_unlock(dbenv, gp->mutex))) { - fprintf(stderr, - "wakeup: global unlock: %s\n", db_strerror(err)); + if ((err = dbenv->mutex_unlock(dbenv, gp->mutex)) != 0) { + fprintf(stderr, "%s: wakeup: global unlock: %s\n", + progname, db_strerror(err)); return ((void *)1); } - __os_sleep(dbenv, 0, rand() % 3); + __os_sleep(dbenv, 0, (u_long)rand() % 3); } return (NULL); } @@ -618,11 +652,11 @@ tm_env_init() * reporting. */ if ((ret = db_env_create(&dbenv, 0)) != 0) { - fprintf(stderr, "tm: %s\n", db_strerror(ret)); + fprintf(stderr, "%s: %s\n", progname, db_strerror(ret)); return (1); } dbenv->set_errfile(dbenv, stderr); - dbenv->set_errpfx(dbenv, "tm"); + dbenv->set_errpfx(dbenv, progname); /* Allocate enough mutexes. */ if ((ret = dbenv->mutex_set_increment(dbenv, @@ -658,40 +692,6 @@ tm_env_close() } /* - * tm_file_init -- - * Initialize the backing file. - */ -void -tm_file_init() -{ - DB_FH *fhp; - int err; - size_t nwrite; - - /* Initialize the backing file. */ - if (verbose) - printf("Create the backing file.\n"); - - (void)unlink(MT_FILE); - - if ((err = __os_open(dbenv, MT_FILE, - DB_OSO_CREATE | DB_OSO_TRUNC, 0666, &fhp)) == -1) { - (void)fprintf(stderr, - "%s: open: %s\n", MT_FILE, db_strerror(err)); - exit(EXIT_FAILURE); - } - - if ((err = __os_seek(dbenv, fhp, 0, 0, len)) != 0 || - (err = __os_write(dbenv, fhp, &err, 1, &nwrite)) != 0 || - nwrite != 1) { - (void)fprintf(stderr, - "%s: seek/write: %s\n", MT_FILE, db_strerror(err)); - exit(EXIT_FAILURE); - } - (void)__os_closehandle(dbenv, fhp); -} - -/* * tm_mutex_init -- * Initialize the mutexes. */ @@ -699,14 +699,15 @@ void tm_mutex_init() { TM *mp; - int err, i; + u_int i; + int err; if (verbose) printf("Allocate the global mutex: "); mp = (TM *)gm_addr; if ((err = dbenv->mutex_alloc(dbenv, 0, &mp->mutex)) != 0) { - fprintf(stderr, - "DB_ENV->mutex_alloc (global): %s\n", db_strerror(err)); + fprintf(stderr, "%s: DB_ENV->mutex_alloc (global): %s\n", + progname, db_strerror(err)); exit(EXIT_FAILURE); } if (verbose) @@ -721,14 +722,14 @@ tm_mutex_init() if ((err = dbenv->mutex_alloc( dbenv, DB_MUTEX_SELF_BLOCK, &mp->mutex)) != 0) { fprintf(stderr, - "DB_ENV->mutex_alloc (per-thread %d): %s\n", - i, db_strerror(err)); + "%s: DB_ENV->mutex_alloc (per-thread %d): %s\n", + progname, i, db_strerror(err)); exit(EXIT_FAILURE); } if ((err = dbenv->mutex_lock(dbenv, mp->mutex)) != 0) { fprintf(stderr, - "DB_ENV->mutex_lock (per-thread %d): %s\n", - i, db_strerror(err)); + "%s: DB_ENV->mutex_lock (per-thread %d): %s\n", + progname, i, db_strerror(err)); exit(EXIT_FAILURE); } if (verbose) @@ -743,8 +744,8 @@ tm_mutex_init() mp = (TM *)(lm_addr + i * sizeof(TM)); if ((err = dbenv->mutex_alloc(dbenv, 0, &mp->mutex)) != 0) { fprintf(stderr, - "DB_ENV->mutex_alloc (per-lock: %d): %s\n", - i, db_strerror(err)); + "%s: DB_ENV->mutex_alloc (per-lock: %d): %s\n", + progname, i, db_strerror(err)); exit(EXIT_FAILURE); } if (verbose) @@ -762,14 +763,15 @@ void tm_mutex_destroy() { TM *gp, *mp; - int err, i; + u_int i; + int err; if (verbose) printf("Destroy the global mutex.\n"); gp = (TM *)gm_addr; if ((err = dbenv->mutex_free(dbenv, gp->mutex)) != 0) { - fprintf(stderr, - "DB_ENV->mutex_free (global): %s\n", db_strerror(err)); + fprintf(stderr, "%s: DB_ENV->mutex_free (global): %s\n", + progname, db_strerror(err)); exit(EXIT_FAILURE); } @@ -779,8 +781,8 @@ tm_mutex_destroy() mp = (TM *)(tm_addr + i * sizeof(TM)); if ((err = dbenv->mutex_free(dbenv, mp->mutex)) != 0) { fprintf(stderr, - "DB_ENV->mutex_free (per-thread %d): %s\n", - i, db_strerror(err)); + "%s: DB_ENV->mutex_free (per-thread %d): %s\n", + progname, i, db_strerror(err)); exit(EXIT_FAILURE); } } @@ -791,13 +793,11 @@ tm_mutex_destroy() mp = (TM *)(lm_addr + i * sizeof(TM)); if ((err = dbenv->mutex_free(dbenv, mp->mutex)) != 0) { fprintf(stderr, - "DB_ENV->mutex_free (per-lock: %d): %s\n", - i, db_strerror(err)); + "%s: DB_ENV->mutex_free (per-lock: %d): %s\n", + progname, i, db_strerror(err)); exit(EXIT_FAILURE); } } - - (void)unlink(MT_FILE); } /* @@ -809,8 +809,8 @@ tm_mutex_stats() { #ifdef HAVE_STATISTICS TM *mp; - int i; u_int32_t set_wait, set_nowait; + u_int i; printf("Per-lock mutex statistics.\n"); for (i = 0; i < maxlocks; ++i) { @@ -823,32 +823,64 @@ tm_mutex_stats() } /* - * map_file -- - * Map in the backing file. + * data_on -- + * Map in or allocate the backing data space. */ void -map_file(gm_addrp, tm_addrp, lm_addrp, fhpp) +data_on(gm_addrp, tm_addrp, lm_addrp, fhpp, init) u_int8_t **gm_addrp, **tm_addrp, **lm_addrp; DB_FH **fhpp; + int init; { - void *addr; DB_FH *fhp; + size_t nwrite; int err; + void *addr; -#ifndef MAP_FAILED -#define MAP_FAILED (void *)-1 -#endif -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif - if ((err = __os_open(dbenv, MT_FILE, 0, 0, &fhp)) != 0) { - fprintf(stderr, "%s: open %s\n", MT_FILE, db_strerror(err)); - exit(EXIT_FAILURE); - } + fhp = NULL; - if ((err = __os_mapfile(dbenv, MT_FILE, fhp, len, 0, &addr)) != 0) { - fprintf(stderr, "%s: mmap: %s\n", MT_FILE, db_strerror(err)); - exit(EXIT_FAILURE); + /* + * In a single process, use heap memory. + */ + if (nprocs == 1) { + if (init) { + if ((err = + __os_calloc(dbenv, (size_t)len, 1, &addr)) != 0) + exit(EXIT_FAILURE); + } else { + fprintf(stderr, + "%s: init should be set for single process call\n", + progname); + exit(EXIT_FAILURE); + } + } else { + if (init) { + if (verbose) + printf("Create the backing file.\n"); + + if ((err = __os_open(dbenv, MT_FILE, 0, + DB_OSO_CREATE | DB_OSO_TRUNC, 0666, &fhp)) == -1) { + fprintf(stderr, "%s: %s: open: %s\n", + progname, MT_FILE, db_strerror(err)); + exit(EXIT_FAILURE); + } + + if ((err = __os_seek(dbenv, fhp, 0, 0, len)) != 0 || + (err = + __os_write(dbenv, fhp, &err, 1, &nwrite)) != 0 || + nwrite != 1) { + fprintf(stderr, "%s: %s: seek/write: %s\n", + progname, MT_FILE, db_strerror(err)); + exit(EXIT_FAILURE); + } + } else + if ((err = + __os_open(dbenv, MT_FILE, 0, 0, 0, &fhp)) != 0) + exit(EXIT_FAILURE); + + if ((err = + __os_mapfile(dbenv, MT_FILE, fhp, len, 0, &addr)) != 0) + exit(EXIT_FAILURE); } *gm_addrp = (u_int8_t *)addr; @@ -862,23 +894,21 @@ map_file(gm_addrp, tm_addrp, lm_addrp, fhpp) } /* - * unmap_file -- - * Discard backing file map. + * data_off -- + * Discard or de-allocate the backing data space. */ void -unmap_file(addr, fhp) +data_off(addr, fhp) u_int8_t *addr; DB_FH *fhp; { - int err; - - if ((err = __os_unmapfile(dbenv, addr, len)) != 0) { - fprintf(stderr, "munmap: %s\n", db_strerror(err)); - exit(EXIT_FAILURE); - } - if ((err = __os_closehandle(dbenv, fhp)) != 0) { - fprintf(stderr, "close: %s\n", db_strerror(err)); - exit(EXIT_FAILURE); + if (nprocs == 1) + __os_free(dbenv, addr); + else { + if (__os_unmapfile(dbenv, addr, len) != 0) + exit(EXIT_FAILURE); + if (__os_closehandle(dbenv, fhp) != 0) + exit(EXIT_FAILURE); } } @@ -889,8 +919,8 @@ unmap_file(addr, fhp) int usage() { - (void)fprintf(stderr, "%s\n\t%s\n", - "usage: tm [-v] [-l maxlocks]", + fprintf(stderr, "usage: %s %s\n\t%s\n", progname, + "[-v] [-l maxlocks]", "[-n locks] [-p procs] [-T locker=ID|wakeup=ID] [-t threads]"); return (EXIT_FAILURE); } @@ -900,11 +930,12 @@ usage() * Wait for an array of N procs. */ int -os_wait(procs, nprocs) +os_wait(procs, n) os_pid_t *procs; - int nprocs; + u_int n; { - int i, status; + u_int i; + int status; #if defined(DB_WIN32) DWORD ret; #endif @@ -913,29 +944,29 @@ os_wait(procs, nprocs) #if defined(DB_WIN32) do { - ret = WaitForMultipleObjects(nprocs, procs, FALSE, INFINITE); + ret = WaitForMultipleObjects(n, procs, FALSE, INFINITE); i = ret - WAIT_OBJECT_0; - if (i < 0 || i >= nprocs) + if (i < 0 || i >= n) return (__os_posix_err(__os_get_syserr())); if ((GetExitCodeProcess(procs[i], &ret) == 0) || (ret != 0)) return (ret); /* remove the process handle from the list */ - while (++i < nprocs) + while (++i < n) procs[i - 1] = procs[i]; - } while (--nprocs); + } while (--n); #elif !defined(HAVE_VXWORKS) do { - if ((i = wait(&status)) == -1) + if (wait(&status) == -1) return (__os_posix_err(__os_get_syserr())); if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0) { - for (i = 0; i < nprocs; i++) - kill(procs[i], SIGKILL); + for (i = 0; i < n; i++) + (void)kill(procs[i], SIGKILL); return (WEXITSTATUS(status)); } - } while (--nprocs); + } while (--n); #endif return (0); @@ -983,7 +1014,7 @@ os_spawn(path, argv) COMPQUIET(status, 0); #ifdef HAVE_VXWORKS - fprintf(stderr, "ERROR: os_spawn not supported for VxWorks.\n"); + fprintf(stderr, "%s: os_spawn not supported for VxWorks.\n", progname); return (OS_BAD_PID); #elif defined(HAVE_QNX) /* @@ -1003,7 +1034,7 @@ os_spawn(path, argv) return (OS_BAD_PID); return (pid); } else { - execv(path, argv); + (void)execv(path, argv); exit(EXIT_FAILURE); } #endif diff --git a/db/mutex/uts4_cc.s b/db/mutex/uts4_cc.s index a8f2498ab..526ac3196 100644 --- a/db/mutex/uts4_cc.s +++ b/db/mutex/uts4_cc.s @@ -1,9 +1,8 @@ / See the file LICENSE for redistribution information. / - / Copyright (c) 1997-2006 - / Oracle Corporation. All rights reserved. + / Copyright (c) 1997,2007 Oracle. All rights reserved. / - / $Id: uts4_cc.s,v 12.3 2006/08/24 14:46:16 bostic Exp $ + / $Id: uts4_cc.s,v 12.5 2007/05/17 15:15:45 bostic Exp $ / / int uts_lock ( int *p, int i ); / Update the lock word pointed to by p with the |