📄 mutex.h
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2002 * Sleepycat Software. All rights reserved. * * $Id: mutex.h,v 1.1.1.1 2004/08/19 23:53:56 gopalan Exp $ */#ifndef _DB_MUTEX_H_#define _DB_MUTEX_H_/* * Some of the Berkeley DB ports require single-threading at various * places in the code. In those cases, these #defines will be set. */#define DB_BEGIN_SINGLE_THREAD#define DB_END_SINGLE_THREAD/********************************************************************* * kernel semaphore interface to use with kdb3. *********************************************************************/#ifdef __KERNEL__#define MUTEX_FIELDS #include <asm/semaphore.h> struct semaphore tas; /* Mutex. */ #define MUTEX_ALIGN sizeof(struct semaphore)/*XXX*/#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_DESTROY(x) /*XXX: sema_destroy(x). *Commented for porting to *kdb3. */#define MUTEX_INIT(x) sema_init(x, 1)#define MUTEX_SET(x) (down_interruptible(x) == 0)#define MUTEX_UNSET(x) up(x)#endif#endif /* __KERNEL__ */#ifndef __KERNEL__ /********************************************************************* * POSIX.1 pthreads interface. *********************************************************************///#ifdef HAVE_MUTEX_PTHREADS//#include <pthread.h>//#define MUTEX_FIELDS // pthread_mutex_t mutex; /* Mutex. */ // pthread_cond_t cond; /* Condition variable. *///#endif/********************************************************************* * Solaris lwp threads interface. * * !!! * We use LWP mutexes on Solaris instead of UI or POSIX mutexes (both of * which are available), for two reasons. First, the Solaris C library * includes versions of the both UI and POSIX thread mutex interfaces, but * they are broken in that they don't support inter-process locking, and * there's no way to detect it, e.g., calls to configure the mutexes for * inter-process locking succeed without error. So, we use LWP mutexes so * that we don't fail in fairly undetectable ways because the application * wasn't linked with the appropriate threads library. Second, there were * bugs in SunOS 5.7 (Solaris 7) where if an application loaded the C library * before loading the libthread/libpthread threads libraries (e.g., by using * dlopen to load the DB library), the pwrite64 interface would be translated * into a call to pwrite and DB would drop core. *********************************************************************/#ifdef HAVE_MUTEX_SOLARIS_LWP/* * XXX * Don't change <synch.h> to <sys/lwp.h> -- although lwp.h is listed in the * Solaris manual page as the correct include to use, it causes the Solaris * compiler on SunOS 2.6 to fail. */#include <synch.h>#define MUTEX_FIELDS \ lwp_mutex_t mutex; /* Mutex. */ \ lwp_cond_t cond; /* Condition variable. */#endif/********************************************************************* * Solaris/Unixware threads interface. *********************************************************************/#ifdef HAVE_MUTEX_UI_THREADS#include <thread.h>#include <synch.h>#define MUTEX_FIELDS \ mutex_t mutex; /* Mutex. */ \ cond_t cond; /* Condition variable. */#endif/********************************************************************* * AIX C library functions. *********************************************************************/#ifdef HAVE_MUTEX_AIX_CHECK_LOCK#include <sys/atomic_op.h>typedef int tsl_t;#define MUTEX_ALIGN sizeof(int)#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_INIT(x) 0#define MUTEX_SET(x) (!_check_lock(x, 0, 1))#define MUTEX_UNSET(x) _clear_lock(x, 0)#endif#endif/********************************************************************* * General C library functions (msemaphore). * * !!! * Check for HPPA as a special case, because it requires unusual alignment, * and doesn't support semaphores in malloc(3) or shmget(2) memory. * * !!! * Do not remove the MSEM_IF_NOWAIT flag. The problem is that if a single * process makes two msem_lock() calls in a row, the second one returns an * error. We depend on the fact that we can lock against ourselves in the * locking subsystem, where we set up a mutex so that we can block ourselves. * Tested on OSF1 v4.0. *********************************************************************/#ifdef HAVE_MUTEX_HPPA_MSEM_INIT#define MUTEX_NO_MALLOC_LOCKS#define MUTEX_NO_SHMGET_LOCKS#define MUTEX_ALIGN 16#endif#if defined(HAVE_MUTEX_MSEM_INIT) || defined(HAVE_MUTEX_HPPA_MSEM_INIT)#include <sys/mman.h>typedef msemaphore tsl_t;#ifndef MUTEX_ALIGN#define MUTEX_ALIGN sizeof(int)#endif#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_INIT(x) (msem_init(x, MSEM_UNLOCKED) <= (msemaphore *)0)#define MUTEX_SET(x) (!msem_lock(x, MSEM_IF_NOWAIT))#define MUTEX_UNSET(x) msem_unlock(x, 0)#endif#endif/********************************************************************* * Plan 9 library functions. *********************************************************************/#ifdef HAVE_MUTEX_PLAN9typedef Lock tsl_t;#define MUTEX_ALIGN sizeof(int)#define MUTEX_INIT(x) (memset(x, 0, sizeof(Lock)), 0)#define MUTEX_SET(x) canlock(x)#define MUTEX_UNSET(x) unlock(x)#endif/********************************************************************* * Reliant UNIX C library functions. *********************************************************************/#ifdef HAVE_MUTEX_RELIANTUNIX_INITSPIN#include <ulocks.h>typedef spinlock_t tsl_t;#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_INIT(x) (initspin(x, 1), 0)#define MUTEX_SET(x) (cspinlock(x) == 0)#define MUTEX_UNSET(x) spinunlock(x)#endif#endif/********************************************************************* * General C library functions (POSIX 1003.1 sema_XXX). * * !!! * Never selected by autoconfig in this release (semaphore calls are known * to not work in Solaris 5.5). *********************************************************************/#ifdef HAVE_MUTEX_SEMA_INIT#include <synch.h>typedef sema_t tsl_t;#define MUTEX_ALIGN sizeof(int)#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_DESTROY(x) sema_destroy(x)#define MUTEX_INIT(x) (sema_init(x, 1, USYNC_PROCESS, NULL) != 0)#define MUTEX_SET(x) (sema_wait(x) == 0)#define MUTEX_UNSET(x) sema_post(x)#endif#endif/********************************************************************* * SGI C library functions. *********************************************************************/#ifdef HAVE_MUTEX_SGI_INIT_LOCK#include <abi_mutex.h>typedef abilock_t tsl_t;#define MUTEX_ALIGN sizeof(int)#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_INIT(x) (init_lock(x) != 0)#define MUTEX_SET(x) (!acquire_lock(x))#define MUTEX_UNSET(x) release_lock(x)#endif#endif/********************************************************************* * Solaris C library functions. * * !!! * These are undocumented functions, but they're the only ones that work * correctly as far as we know. *********************************************************************/#ifdef HAVE_MUTEX_SOLARIS_LOCK_TRY#include <sys/machlock.h>typedef lock_t tsl_t;#define MUTEX_ALIGN sizeof(int)#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_INIT(x) 0#define MUTEX_SET(x) _lock_try(x)#define MUTEX_UNSET(x) _lock_clear(x)#endif#endif/********************************************************************* * VMS. *********************************************************************/#ifdef HAVE_MUTEX_VMS#include <sys/mman.h>;#include <builtins.h>typedef unsigned char tsl_t;#define MUTEX_ALIGN sizeof(unsigned int)#ifdef LOAD_ACTUAL_MUTEX_CODE#ifdef __ALPHA#define MUTEX_SET(tsl) (!__TESTBITSSI(tsl, 0))#else /* __VAX */#define MUTEX_SET(tsl) (!(int)_BBSSI(0, tsl))#endif#define MUTEX_UNSET(tsl) (*(tsl) = 0)#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)#endif#endif/********************************************************************* * VxWorks * Use basic binary semaphores in VxWorks, as we currently do not need * any special features. We do need the ability to single-thread the * entire system, however, because VxWorks doesn't support the open(2) * flag O_EXCL, the mechanism we normally use to single thread access * when we're first looking for a DB environment. *********************************************************************/#ifdef HAVE_MUTEX_VXWORKS#include "taskLib.h"typedef SEM_ID tsl_t;#define MUTEX_ALIGN sizeof(unsigned int)#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_SET(tsl) (semTake((*tsl), WAIT_FOREVER) == OK)#define MUTEX_UNSET(tsl) (semGive((*tsl)))#define MUTEX_INIT(tsl) \ ((*(tsl) = semBCreate(SEM_Q_FIFO, SEM_FULL)) == NULL)#define MUTEX_DESTROY(tsl) semDelete(*tsl)#endif/* * Use the taskLock() mutex to eliminate a race where two tasks are * trying to initialize the global lock at the same time. */#undef DB_BEGIN_SINGLE_THREAD#define DB_BEGIN_SINGLE_THREAD \do { \ if (DB_GLOBAL(db_global_init)) \ (void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER); \ else { \ taskLock(); \ if (DB_GLOBAL(db_global_init)) { \ taskUnlock(); \ (void)semTake(DB_GLOBAL(db_global_lock), \ WAIT_FOREVER); \ continue; \ } \ DB_GLOBAL(db_global_lock) = \ semBCreate(SEM_Q_FIFO, SEM_EMPTY); \ if (DB_GLOBAL(db_global_lock) != NULL) \ DB_GLOBAL(db_global_init) = 1; \ taskUnlock(); \ } \} while (DB_GLOBAL(db_global_init) == 0)#undef DB_END_SINGLE_THREAD#define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock))#endif/********************************************************************* * Win16 * * Win16 spinlocks are simple because we cannot possibly be preempted. * * !!! * We should simplify this by always returning a no-need-to-lock lock * when we initialize the mutex. *********************************************************************/#ifdef HAVE_MUTEX_WIN16typedef unsigned int tsl_t;#define MUTEX_ALIGN sizeof(unsigned int)#ifdef LOAD_ACTUAL_MUTEX_CODE#define MUTEX_INIT(x) 0#define MUTEX_SET(tsl) (*(tsl) = 1)#define MUTEX_UNSET(tsl) (*(tsl) = 0)#endif#endif/********************************************************************* * Win32 *********************************************************************/#ifdef HAVE_MUTEX_WIN32#define MUTEX_FIELDS \ LONG tas; \ LONG nwaiters; \ u_int32_t id; /* ID used for creating events */ \#if defined(LOAD_ACTUAL_MUTEX_CODE)#define MUTEX_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1))#define MUTEX_UNSET(tsl) (*(tsl) = 0)#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)#endif#endif/********************************************************************* * 68K/gcc assembly. *********************************************************************/#ifdef HAVE_MUTEX_68K_GCC_ASSEMBLYtypedef unsigned char tsl_t;#ifdef LOAD_ACTUAL_MUTEX_CODE/* * For gcc/68K, 0 is clear, 1 is set. */#define MUTEX_SET(tsl) ({ \ register tsl_t *__l = (tsl); \ int __r; \ asm volatile("tas %1; \n \ seq %0" \ : "=dm" (__r), "=m" (*__l) \ : "1" (*__l) \ ); \ __r & 1; \})#define MUTEX_UNSET(tsl) (*(tsl) = 0)#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)#endif#endif/********************************************************************* * ALPHA/gcc assembly. *********************************************************************/#ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLYtypedef u_int32_t tsl_t;#define MUTEX_ALIGN 4#ifdef LOAD_ACTUAL_MUTEX_CODE/* * For gcc/alpha. Should return 0 if could not acquire the lock, 1 if * lock was acquired properly. */#ifdef __GNUC__static inline intMUTEX_SET(tsl_t *tsl) { register tsl_t *__l = tsl; register tsl_t __r; asm volatile( "1: ldl_l %0,%2\n" " blbs %0,2f\n" " or $31,1,%0\n" " stl_c %0,%1\n" " beq %0,3f\n" " mb\n" " br 3f\n" "2: xor %0,%0\n" "3:" : "=&r"(__r), "=m"(*__l) : "1"(*__l) : "memory"); return __r;}/* * Unset mutex. Judging by Alpha Architecture Handbook, the mb instruction * might be necessary before unlocking */static inline intMUTEX_UNSET(tsl_t *tsl) { asm volatile(" mb\n"); return *tsl = 0;}#endif#ifdef __DECC#include <alpha/builtins.h>#define MUTEX_SET(tsl) (__LOCK_LONG_RETRY((tsl), 1) != 0)#define MUTEX_UNSET(tsl) (*(tsl) = 0)#endif#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)#endif#endif/********************************************************************* * ARM/gcc assembly. *********************************************************************/#ifdef HAVE_MUTEX_ARM_GCC_ASSEMBLYtypedef unsigned char tsl_t;#ifdef LOAD_ACTUAL_MUTEX_CODE/* * For arm/gcc, 0 is clear, 1 is set. */#define MUTEX_SET(tsl) ({ \ int __r; \ asm volatile("swpb %0, %1, [%2]" \ : "=r" (__r) \ : "0" (1), "r" (tsl) \ : "memory" \ ); \ __r & 1; \})#define MUTEX_UNSET(tsl) (*(volatile tsl_t *)(tsl) = 0)#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl)#endif#endif/********************************************************************* * HPPA/gcc assembly. *********************************************************************/#ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLYtypedef u_int32_t tsl_t;#define MUTEX_ALIGN 16#ifdef LOAD_ACTUAL_MUTEX_CODE/* * The PA-RISC has a "load and clear" instead of a "test and set" instruction. * The 32-bit word used by that instruction must be 16-byte aligned. We could * use the "aligned" attribute in GCC but that doesn't work for stack variables. */#define MUTEX_SET(tsl) ({ \ register tsl_t *__l = (tsl); \ int __r; \ asm volatile("ldcws 0(%1),%0" : "=r" (__r) : "r" (__l)); \ __r & 1; \})#define MUTEX_UNSET(tsl) (*(tsl) = -1)#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0)#endif#endif/********************************************************************* * IA64/gcc assembly. *********************************************************************/#ifdef HAVE_MUTEX_IA64_GCC_ASSEMBLY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -