2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996-2009 Oracle. All rights reserved.
15 * Allocate a mutex, application method.
17 * PUBLIC: int __mutex_alloc_pp __P((DB_ENV *, u_int32_t, db_mutex_t *));
20 __mutex_alloc_pp(dbenv, flags, indxp)
31 if ((ret = __db_fchk(env, "DB_ENV->mutex_alloc",
32 flags, DB_MUTEX_PROCESS_ONLY | DB_MUTEX_SELF_BLOCK)) != 0)
36 ret = __mutex_alloc(env, MTX_APPLICATION, flags, indxp);
44 * Destroy a mutex, application method.
46 * PUBLIC: int __mutex_free_pp __P((DB_ENV *, db_mutex_t));
49 __mutex_free_pp(dbenv, indx)
59 if (indx == MUTEX_INVALID)
63 * Internally Berkeley DB passes around the db_mutex_t address on
64 * free, because we want to make absolutely sure the slot gets
65 * overwritten with MUTEX_INVALID. We don't export MUTEX_INVALID,
66 * so we don't export that part of the API, either.
69 ret = __mutex_free(env, &indx);
77 * Lock a mutex, application method.
79 * PUBLIC: int __mutex_lock_pp __P((DB_ENV *, db_mutex_t));
82 __mutex_lock_pp(dbenv, indx)
92 if (indx == MUTEX_INVALID)
96 ret = __mutex_lock(env, indx);
103 * Unlock a mutex, application method.
105 * PUBLIC: int __mutex_unlock_pp __P((DB_ENV *, db_mutex_t));
108 __mutex_unlock_pp(dbenv, indx)
118 if (indx == MUTEX_INVALID)
122 ret = __mutex_unlock(env, indx);
128 * __mutex_get_align --
129 * DB_ENV->mutex_get_align.
131 * PUBLIC: int __mutex_get_align __P((DB_ENV *, u_int32_t *));
134 __mutex_get_align(dbenv, alignp)
143 /* Cannot be set after open, no lock required to read. */
144 *alignp = ((DB_MUTEXREGION *)
145 env->mutex_handle->reginfo.primary)->stat.st_mutex_align;
147 *alignp = dbenv->mutex_align;
152 * __mutex_set_align --
153 * DB_ENV->mutex_set_align.
155 * PUBLIC: int __mutex_set_align __P((DB_ENV *, u_int32_t));
158 __mutex_set_align(dbenv, align)
166 ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_align");
168 if (align == 0 || !POWER_OF_TWO(align)) {
170 "DB_ENV->mutex_set_align: alignment value must be a non-zero power-of-two");
174 dbenv->mutex_align = align;
179 * __mutex_get_increment --
180 * DB_ENV->mutex_get_increment.
182 * PUBLIC: int __mutex_get_increment __P((DB_ENV *, u_int32_t *));
185 __mutex_get_increment(dbenv, incrementp)
187 u_int32_t *incrementp;
190 * We don't maintain the increment in the region (it just makes
191 * no sense). Return whatever we have configured on this handle,
192 * nobody is ever going to notice.
194 *incrementp = dbenv->mutex_inc;
199 * __mutex_set_increment --
200 * DB_ENV->mutex_set_increment.
202 * PUBLIC: int __mutex_set_increment __P((DB_ENV *, u_int32_t));
205 __mutex_set_increment(dbenv, increment)
213 ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_increment");
215 dbenv->mutex_cnt = 0;
216 dbenv->mutex_inc = increment;
222 * DB_ENV->mutex_get_max.
224 * PUBLIC: int __mutex_get_max __P((DB_ENV *, u_int32_t *));
227 __mutex_get_max(dbenv, maxp)
236 /* Cannot be set after open, no lock required to read. */
237 *maxp = ((DB_MUTEXREGION *)
238 env->mutex_handle->reginfo.primary)->stat.st_mutex_cnt;
240 *maxp = dbenv->mutex_cnt;
246 * DB_ENV->mutex_set_max.
248 * PUBLIC: int __mutex_set_max __P((DB_ENV *, u_int32_t));
251 __mutex_set_max(dbenv, max)
259 ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_max");
261 dbenv->mutex_cnt = max;
262 dbenv->mutex_inc = 0;
267 * __mutex_get_tas_spins --
268 * DB_ENV->mutex_get_tas_spins.
270 * PUBLIC: int __mutex_get_tas_spins __P((DB_ENV *, u_int32_t *));
273 __mutex_get_tas_spins(dbenv, tas_spinsp)
275 u_int32_t *tas_spinsp;
282 /* Cannot be set after open, no lock required to read. */
283 *tas_spinsp = ((DB_MUTEXREGION *)env->
284 mutex_handle->reginfo.primary)->stat.st_mutex_tas_spins;
286 *tas_spinsp = dbenv->mutex_tas_spins;
291 * __mutex_set_tas_spins --
292 * DB_ENV->mutex_set_tas_spins.
294 * PUBLIC: int __mutex_set_tas_spins __P((DB_ENV *, u_int32_t));
297 __mutex_set_tas_spins(dbenv, tas_spins)
306 * Bound the value -- less than 1 makes no sense, greater than 1M
311 else if (tas_spins > 1000000)
315 * There's a theoretical race here, but I'm not interested in locking
316 * the test-and-set spin count. The worst possibility is a thread
317 * reads out a bad spin count and spins until it gets the lock, but
318 * that's awfully unlikely.
321 ((DB_MUTEXREGION *)env->mutex_handle
322 ->reginfo.primary)->stat.st_mutex_tas_spins = tas_spins;
324 dbenv->mutex_tas_spins = tas_spins;
328 #if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT)
330 * Provide atomic operations for platforms which have mutexes yet do not have
331 * native atomic operations configured. They are emulated by protected the
332 * operation with a mutex. The address of the atomic value selects which
337 * Map an address to the mutex to use to atomically modify it
339 static inline db_mutex_t atomic_get_mutex(env, v)
344 DB_MUTEXREGION *mtxreg;
347 return (MUTEX_INVALID);
348 index = (u_int)(((uintptr_t) (v)) >> 6) % MAX_ATOMIC_MUTEXES;
349 mtxreg = (DB_MUTEXREGION *)env->mutex_handle->reginfo.primary;
350 return (mtxreg->mtx_atomic[index]);
355 * Use a mutex to provide an atomic increment function
357 * PUBLIC: #if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT)
358 * PUBLIC: atomic_value_t __atomic_inc __P((ENV *, db_atomic_t *));
369 mtx = atomic_get_mutex(env, v);
370 MUTEX_LOCK(env, mtx);
372 MUTEX_UNLOCK(env, mtx);
379 * Use a mutex to provide an atomic decrement function
381 * PUBLIC: #if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT)
382 * PUBLIC: atomic_value_t __atomic_dec __P((ENV *, db_atomic_t *));
393 mtx = atomic_get_mutex(env, v);
394 MUTEX_LOCK(env, mtx);
396 MUTEX_UNLOCK(env, mtx);
402 * atomic_compare_exchange
403 * Use a mutex to provide an atomic decrement function
405 * PRIVATE: int atomic_compare_exchange
406 * PRIVATE: __P((ENV *, db_atomic_t *, atomic_value_t, atomic_value_t));
407 * Returns 1 if the *v was equal to oldval, else 0
410 * Sets the value to newval if and only if returning 1
413 atomic_compare_exchange(env, v, oldval, newval)
416 atomic_value_t oldval;
417 atomic_value_t newval;
422 if (atomic_read(v) != oldval)
425 mtx = atomic_get_mutex(env, v);
426 MUTEX_LOCK(env, mtx);
427 ret = atomic_read(v) == oldval;
429 atomic_init(v, newval);
430 MUTEX_UNLOCK(env, mtx);