Windows thread callback support

vmware
Howard Chu 13 years ago
parent e562f53e10
commit 248fd1c7b8
  1. 77
      libraries/libmdb/mdb.c

@ -2568,11 +2568,8 @@ mdb_env_open2(MDB_env *env, unsigned int flags)
} }
#ifndef _WIN32
/** Release a reader thread's slot in the reader lock table. /** Release a reader thread's slot in the reader lock table.
* This function is called automatically when a thread exits. * This function is called automatically when a thread exits.
* Windows doesn't support destructor callbacks for thread-specific storage,
* so this function is not compiled there.
* @param[in] ptr This points to the slot in the reader lock table. * @param[in] ptr This points to the slot in the reader lock table.
*/ */
static void static void
@ -2584,6 +2581,60 @@ mdb_env_reader_dest(void *ptr)
reader->mr_pid = 0; reader->mr_pid = 0;
reader->mr_tid = 0; reader->mr_tid = 0;
} }
#ifdef _WIN32
/** Junk for arranging thread-specific callbacks on Windows. This is
* necessarily platform and compiler-specific. Windows supports up
* to 1088 keys. Let's assume nobody opens more than 64 environments
* in a single process, for now. They can override this if needed.
*/
#ifndef MAX_TLS_KEYS
#define MAX_TLS_KEYS 64
#endif
static pthread_key_t mdb_tls_keys[MAX_TLS_KEYS];
static int mdb_tls_nkeys;
static void NTAPI mdb_tls_callback(PVOID module, DWORD reason, PVOID ptr)
{
int i;
switch(reason) {
case DLL_PROCESS_ATTACH: break;
case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH:
for (i=0; i<mdb_tls_nkeys; i++) {
MDB_reader *r = pthread_getspecific(mdb_tls_keys[i]);
mdb_env_reader_dest(r);
}
break;
case DLL_PROCESS_DETACH: break;
}
}
#ifdef __GNUC__
#ifdef _WIN64
const PIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (".CRT$XLB"))) = mdb_tls_callback;
#else
PIMAGE_TLS_CALLBACK mdb_tls_cbp __attribute__((section (".CRT$XLB"))) = mdb_tls_callback;
#endif
#else
#ifdef _WIN64
/* Force some symbol references.
* _tls_used forces the linker to create the TLS directory if not already done
* mdb_tls_cbp prevents whole-program-optimizer from dropping the symbol.
*/
#pragma comment(linker, "/INCLUDE:_tls_used")
#pragma comment(linker, "/INCLUDE:mdb_tls_cbp")
#pragma const_seg(".CRT$XLB")
extern const PIMAGE_TLS_CALLBACK mdb_tls_callback;
const PIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
#pragma const_seg()
#else /* WIN32 */
#pragma comment(linker, "/INCLUDE:__tls_used")
#pragma comment(linker, "/INCLUDE:_mdb_tls_cbp")
#pragma data_seg(".CRT$XLB")
PIMAGE_TLS_CALLBACK mdb_tls_cbp = mdb_tls_callback;
#pragma data_seg()
#endif /* WIN 32/64 */
#endif /* !__GNUC__ */
#endif #endif
/** Downgrade the exclusive lock on the region back to shared */ /** Downgrade the exclusive lock on the region back to shared */
@ -3040,6 +3091,15 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode)
env->me_path = strdup(path); env->me_path = strdup(path);
DPRINTF("opened dbenv %p", (void *) env); DPRINTF("opened dbenv %p", (void *) env);
pthread_key_create(&env->me_txkey, mdb_env_reader_dest); pthread_key_create(&env->me_txkey, mdb_env_reader_dest);
#ifdef _WIN32
/* Windows TLS callbacks need help finding their TLS info. */
if (mdb_tls_nkeys < MAX_TLS_KEYS)
mdb_tls_keys[mdb_tls_nkeys++] = env->me_txkey;
else {
rc = ENOMEM;
goto leave;
}
#endif
LAZY_RWLOCK_INIT(&env->me_dblock, NULL); LAZY_RWLOCK_INIT(&env->me_dblock, NULL);
if (excl) if (excl)
mdb_env_share_locks(env); mdb_env_share_locks(env);
@ -3087,6 +3147,17 @@ mdb_env_close(MDB_env *env)
LAZY_RWLOCK_DESTROY(&env->me_dblock); LAZY_RWLOCK_DESTROY(&env->me_dblock);
pthread_key_delete(env->me_txkey); pthread_key_delete(env->me_txkey);
#ifdef _WIN32
/* Delete our key from the global list */
{ int i;
for (i=0; i<mdb_tls_nkeys; i++)
if (mdb_tls_keys[i] == env->me_txkey) {
mdb_tls_keys[i] = mdb_tls_keys[mdb_tls_nkeys-1];
mdb_tls_nkeys--;
break;
}
}
#endif
if (env->me_map) { if (env->me_map) {
munmap(env->me_map, env->me_mapsize); munmap(env->me_map, env->me_mapsize);

Loading…
Cancel
Save