mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
baddc4e91c
innodb-5.1-ss1318 innodb-5.1-ss1330 innodb-5.1-ss1332 innodb-5.1-ss1340 Fixes: - Bug #21409: Incorrect result returned when in READ-COMMITTED with query_cache ON At low transaction isolation levels we let each consistent read set its own snapshot. - Bug #23666: strange Innodb_row_lock_time_% values in show status; also millisecs wrong On Windows ut_usectime returns secs and usecs relative to the UNIX epoch (which is Jan, 1 1970). - Bug #25494: LATEST DEADLOCK INFORMATION is not always cleared lock_deadlock_recursive(): When the search depth or length is exceeded, rewind lock_latest_err_file and display the two transactions at the point of aborting the search. - Bug #25927: Foreign key with ON DELETE SET NULL on NOT NULL can crash server Prevent ALTER TABLE ... MODIFY ... NOT NULL on columns for which there is a foreign key constraint ON ... SET NULL. - Bug #26835: Repeatable corruption of utf8-enabled tables inside InnoDB The bug could be reproduced as follows: Define a table so that the first column of the clustered index is a VARCHAR or a UTF-8 CHAR in a collation where sequences of bytes of differing length are considered equivalent. Insert and delete a record. Before the delete-marked record is purged, insert another record whose first column is of different length but equivalent to the first record. Under certain conditions, the insertion can be incorrectly performed as update-in-place. Likewise, an operation that could be done as update-in-place can unnecessarily be performed as delete and insert, but that would not cause corruption but merely degraded performance.
228 lines
5.1 KiB
C
228 lines
5.1 KiB
C
/******************************************************
|
|
The thread local storage
|
|
|
|
(c) 1995 Innobase Oy
|
|
|
|
Created 10/5/1995 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "thr0loc.h"
|
|
#ifdef UNIV_NONINL
|
|
#include "thr0loc.ic"
|
|
#endif
|
|
|
|
#include "sync0sync.h"
|
|
#include "hash0hash.h"
|
|
#include "mem0mem.h"
|
|
#include "srv0srv.h"
|
|
|
|
/*
|
|
IMPLEMENTATION OF THREAD LOCAL STORAGE
|
|
======================================
|
|
|
|
The threads sometimes need private data which depends on the thread id.
|
|
This is implemented as a hash table, where the hash value is calculated
|
|
from the thread id, to prepare for a large number of threads. The hash table
|
|
is protected by a mutex. If you need modify the program and put new data to
|
|
the thread local storage, just add it to struct thr_local_struct in the
|
|
header file. */
|
|
|
|
/* Mutex protecting the local storage hash table */
|
|
mutex_t thr_local_mutex;
|
|
|
|
/* The hash table. The module is not yet initialized when it is NULL. */
|
|
hash_table_t* thr_local_hash = NULL;
|
|
|
|
/* The private data for each thread should be put to
|
|
the structure below and the accessor functions written
|
|
for the field. */
|
|
typedef struct thr_local_struct thr_local_t;
|
|
|
|
struct thr_local_struct{
|
|
os_thread_id_t id; /* id of the thread which owns this struct */
|
|
os_thread_t handle; /* operating system handle to the thread */
|
|
ulint slot_no;/* the index of the slot in the thread table
|
|
for this thread */
|
|
ibool in_ibuf;/* TRUE if the the thread is doing an ibuf
|
|
operation */
|
|
hash_node_t hash; /* hash chain node */
|
|
ulint magic_n;
|
|
};
|
|
|
|
#define THR_LOCAL_MAGIC_N 1231234
|
|
|
|
/***********************************************************************
|
|
Returns the local storage struct for a thread. */
|
|
static
|
|
thr_local_t*
|
|
thr_local_get(
|
|
/*==========*/
|
|
/* out: local storage */
|
|
os_thread_id_t id) /* in: thread id of the thread */
|
|
{
|
|
thr_local_t* local;
|
|
|
|
try_again:
|
|
ut_ad(thr_local_hash);
|
|
ut_ad(mutex_own(&thr_local_mutex));
|
|
|
|
/* Look for the local struct in the hash table */
|
|
|
|
local = NULL;
|
|
|
|
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
|
|
local, os_thread_eq(local->id, id));
|
|
if (local == NULL) {
|
|
mutex_exit(&thr_local_mutex);
|
|
|
|
thr_local_create();
|
|
|
|
mutex_enter(&thr_local_mutex);
|
|
|
|
goto try_again;
|
|
}
|
|
|
|
ut_ad(local->magic_n == THR_LOCAL_MAGIC_N);
|
|
|
|
return(local);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Gets the slot number in the thread table of a thread. */
|
|
|
|
ulint
|
|
thr_local_get_slot_no(
|
|
/*==================*/
|
|
/* out: slot number */
|
|
os_thread_id_t id) /* in: thread id of the thread */
|
|
{
|
|
ulint slot_no;
|
|
thr_local_t* local;
|
|
|
|
mutex_enter(&thr_local_mutex);
|
|
|
|
local = thr_local_get(id);
|
|
|
|
slot_no = local->slot_no;
|
|
|
|
mutex_exit(&thr_local_mutex);
|
|
|
|
return(slot_no);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Sets the slot number in the thread table of a thread. */
|
|
|
|
void
|
|
thr_local_set_slot_no(
|
|
/*==================*/
|
|
os_thread_id_t id, /* in: thread id of the thread */
|
|
ulint slot_no)/* in: slot number */
|
|
{
|
|
thr_local_t* local;
|
|
|
|
mutex_enter(&thr_local_mutex);
|
|
|
|
local = thr_local_get(id);
|
|
|
|
local->slot_no = slot_no;
|
|
|
|
mutex_exit(&thr_local_mutex);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Returns pointer to the 'in_ibuf' field within the current thread local
|
|
storage. */
|
|
|
|
ibool*
|
|
thr_local_get_in_ibuf_field(void)
|
|
/*=============================*/
|
|
/* out: pointer to the in_ibuf field */
|
|
{
|
|
thr_local_t* local;
|
|
|
|
mutex_enter(&thr_local_mutex);
|
|
|
|
local = thr_local_get(os_thread_get_curr_id());
|
|
|
|
mutex_exit(&thr_local_mutex);
|
|
|
|
return(&(local->in_ibuf));
|
|
}
|
|
|
|
/***********************************************************************
|
|
Creates a local storage struct for the calling new thread. */
|
|
|
|
void
|
|
thr_local_create(void)
|
|
/*==================*/
|
|
{
|
|
thr_local_t* local;
|
|
|
|
if (thr_local_hash == NULL) {
|
|
thr_local_init();
|
|
}
|
|
|
|
local = mem_alloc(sizeof(thr_local_t));
|
|
|
|
local->id = os_thread_get_curr_id();
|
|
local->handle = os_thread_get_curr();
|
|
local->magic_n = THR_LOCAL_MAGIC_N;
|
|
|
|
local->in_ibuf = FALSE;
|
|
|
|
mutex_enter(&thr_local_mutex);
|
|
|
|
HASH_INSERT(thr_local_t, hash, thr_local_hash,
|
|
os_thread_pf(os_thread_get_curr_id()),
|
|
local);
|
|
|
|
mutex_exit(&thr_local_mutex);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Frees the local storage struct for the specified thread. */
|
|
|
|
void
|
|
thr_local_free(
|
|
/*===========*/
|
|
os_thread_id_t id) /* in: thread id */
|
|
{
|
|
thr_local_t* local;
|
|
|
|
mutex_enter(&thr_local_mutex);
|
|
|
|
/* Look for the local struct in the hash table */
|
|
|
|
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
|
|
local, os_thread_eq(local->id, id));
|
|
if (local == NULL) {
|
|
mutex_exit(&thr_local_mutex);
|
|
|
|
return;
|
|
}
|
|
|
|
HASH_DELETE(thr_local_t, hash, thr_local_hash,
|
|
os_thread_pf(id), local);
|
|
|
|
mutex_exit(&thr_local_mutex);
|
|
|
|
ut_a(local->magic_n == THR_LOCAL_MAGIC_N);
|
|
|
|
mem_free(local);
|
|
}
|
|
|
|
/********************************************************************
|
|
Initializes the thread local storage module. */
|
|
|
|
void
|
|
thr_local_init(void)
|
|
/*================*/
|
|
{
|
|
|
|
ut_a(thr_local_hash == NULL);
|
|
|
|
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
|
|
|
|
mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
|
|
}
|