00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019
00020
00021
00022
00023 #define LOAD_ACTUAL_MUTEX_CODE
00024 #include "dbinc/mutex_int.h"
00025
00026
00027 #undef MUTEX_DIAG
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 static _TCHAR hex_digits[] = _T("0123456789abcdef");
00040 static SECURITY_DESCRIPTOR null_sd;
00041 static SECURITY_ATTRIBUTES all_sa;
00042 static int security_initialized = 0;
00043
00044 static __inline int get_handle(dbenv, mutexp, eventp)
00045 DB_ENV *dbenv;
00046 DB_MUTEX *mutexp;
00047 HANDLE *eventp;
00048 {
00049 _TCHAR idbuf[] = _T("db.m00000000");
00050 _TCHAR *p = idbuf + 12;
00051 int ret = 0;
00052 u_int32_t id;
00053
00054 for (id = (mutexp)->id; id != 0; id >>= 4)
00055 *--p = hex_digits[id & 0xf];
00056
00057 if (!security_initialized) {
00058 InitializeSecurityDescriptor(&null_sd,
00059 SECURITY_DESCRIPTOR_REVISION);
00060 SetSecurityDescriptorDacl(&null_sd, TRUE, 0, FALSE);
00061 all_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
00062 all_sa.bInheritHandle = FALSE;
00063 all_sa.lpSecurityDescriptor = &null_sd;
00064 security_initialized = 1;
00065 }
00066
00067 if ((*eventp = CreateEvent(&all_sa, FALSE, FALSE, idbuf)) == NULL) {
00068 ret = __os_get_errno();
00069 __db_err(dbenv, "Win32 create event failed: %s",
00070 db_strerror(ret));
00071 }
00072
00073 return (ret);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082 int
00083 __db_win32_mutex_init(dbenv, mutex, flags)
00084 DB_ENV *dbenv;
00085 db_mutex_t mutex;
00086 u_int32_t flags;
00087 {
00088 DB_MUTEX *mutexp;
00089 DB_MUTEXMGR *mtxmgr;
00090 DB_MUTEXREGION *mtxregion;
00091
00092 mtxmgr = dbenv->mutex_handle;
00093 mtxregion = mtxmgr->reginfo.primary;
00094 mutexp = MUTEXP_SET(mutex);
00095
00096 mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp);
00097
00098 return (0);
00099 }
00100
00101
00102
00103
00104
00105
00106
00107 int
00108 __db_win32_mutex_lock(dbenv, mutex)
00109 DB_ENV *dbenv;
00110 db_mutex_t mutex;
00111 {
00112 DB_MUTEX *mutexp;
00113 DB_MUTEXMGR *mtxmgr;
00114 DB_MUTEXREGION *mtxregion;
00115 HANDLE event;
00116 u_int32_t nspins;
00117 int ms, ret;
00118 #ifdef MUTEX_DIAG
00119 LARGE_INTEGER now;
00120 #endif
00121
00122 if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00123 return (0);
00124
00125 mtxmgr = dbenv->mutex_handle;
00126 mtxregion = mtxmgr->reginfo.primary;
00127 mutexp = MUTEXP_SET(mutex);
00128
00129 event = NULL;
00130 ms = 50;
00131 ret = 0;
00132
00133 loop:
00134 for (nspins =
00135 mtxregion->stat.st_mutex_tas_spins; nspins > 0; --nspins) {
00136
00137
00138
00139
00140 if (mutexp->tas || !MUTEX_SET(&mutexp->tas)) {
00141
00142
00143
00144
00145 #ifdef MUTEX_PAUSE
00146 MUTEX_PAUSE
00147 #endif
00148 continue;
00149 }
00150
00151 #ifdef DIAGNOSTIC
00152 if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00153 char buf[DB_THREADID_STRLEN];
00154 __db_err(dbenv,
00155 "Win32 lock failed: mutex already locked by %s",
00156 dbenv->thread_id_string(dbenv,
00157 mutexp->pid, mutexp->tid, buf));
00158 return (__db_panic(dbenv, EACCES));
00159 }
00160 #endif
00161 F_SET(mutexp, DB_MUTEX_LOCKED);
00162 dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid);
00163 CHECK_MTX_THREAD(dbenv, mutexp);
00164
00165 #ifdef HAVE_STATISTICS
00166 if (event == NULL)
00167 ++mutexp->mutex_set_nowait;
00168 else
00169 ++mutexp->mutex_set_wait;
00170 #endif
00171 if (event != NULL) {
00172 CloseHandle(event);
00173 InterlockedDecrement(&mutexp->nwaiters);
00174 #ifdef MUTEX_DIAG
00175 if (ret != WAIT_OBJECT_0) {
00176 QueryPerformanceCounter(&now);
00177 printf("[%I64d]: Lost signal on mutex %p, "
00178 "id %d, ms %d\n",
00179 now.QuadPart, mutexp, mutexp->id, ms);
00180 }
00181 #endif
00182 }
00183
00184 #ifdef DIAGNOSTIC
00185
00186
00187
00188
00189 if (F_ISSET(dbenv, DB_ENV_YIELDCPU))
00190 __os_yield(NULL, 1);
00191 #endif
00192
00193 return (0);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 if (event == NULL) {
00203 #ifdef MUTEX_DIAG
00204 QueryPerformanceCounter(&now);
00205 printf("[%I64d]: Waiting on mutex %p, id %d\n",
00206 now.QuadPart, mutexp, mutexp->id);
00207 #endif
00208 InterlockedIncrement(&mutexp->nwaiters);
00209 if ((ret = get_handle(dbenv, mutexp, &event)) != 0)
00210 goto err;
00211 }
00212 if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED) {
00213 ret = __os_get_errno();
00214 goto err;
00215 }
00216 if ((ms <<= 1) > MS_PER_SEC)
00217 ms = MS_PER_SEC;
00218
00219 PANIC_CHECK(dbenv);
00220 goto loop;
00221
00222 err: __db_err(dbenv, "Win32 lock failed: %s", db_strerror(ret));
00223 return (__db_panic(dbenv, ret));
00224 }
00225
00226
00227
00228
00229
00230
00231
00232 int
00233 __db_win32_mutex_unlock(dbenv, mutex)
00234 DB_ENV *dbenv;
00235 db_mutex_t mutex;
00236 {
00237 DB_MUTEX *mutexp;
00238 DB_MUTEXMGR *mtxmgr;
00239 DB_MUTEXREGION *mtxregion;
00240 HANDLE event;
00241 int ret;
00242 #ifdef MUTEX_DIAG
00243 LARGE_INTEGER now;
00244 #endif
00245 if (!MUTEX_ON(dbenv) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
00246 return (0);
00247
00248 mtxmgr = dbenv->mutex_handle;
00249 mtxregion = mtxmgr->reginfo.primary;
00250 mutexp = MUTEXP_SET(mutex);
00251
00252 #ifdef DIAGNOSTIC
00253 if (!mutexp->tas || !F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
00254 __db_err(dbenv, "Win32 unlock failed: lock already unlocked");
00255 return (__db_panic(dbenv, EACCES));
00256 }
00257 #endif
00258 F_CLR(mutexp, DB_MUTEX_LOCKED);
00259 MUTEX_UNSET(&mutexp->tas);
00260
00261 if (mutexp->nwaiters > 0) {
00262 if ((ret = get_handle(dbenv, mutexp, &event)) != 0)
00263 goto err;
00264
00265 #ifdef MUTEX_DIAG
00266 QueryPerformanceCounter(&now);
00267 printf("[%I64d]: Signalling mutex %p, id %d\n",
00268 now.QuadPart, mutexp, mutexp->id);
00269 #endif
00270 if (!PulseEvent(event)) {
00271 ret = __os_get_errno();
00272 CloseHandle(event);
00273 goto err;
00274 }
00275
00276 CloseHandle(event);
00277 }
00278
00279 return (0);
00280
00281 err: __db_err(dbenv, "Win32 unlock failed: %s", db_strerror(ret));
00282 return (__db_panic(dbenv, ret));
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 int
00292 __db_win32_mutex_destroy(dbenv, mutex)
00293 DB_ENV *dbenv;
00294 db_mutex_t mutex;
00295 {
00296 return (0);
00297 }