Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
8f3b5ebd
Commit
8f3b5ebd
authored
Dec 06, 2008
by
Vadim Tkachenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Sync with patches commit rev 8
parent
bf05180b
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1024 additions
and
165 deletions
+1024
-165
Makefile.am
Makefile.am
+1
-1
Makefile.in
Makefile.in
+1
-1
buf/buf0buf.c
buf/buf0buf.c
+6
-4
fil/fil0fil.c
fil/fil0fil.c
+27
-0
handler/ha_innodb.cc
handler/ha_innodb.cc
+16
-3
handler/i_s.cc
handler/i_s.cc
+183
-4
handler/i_s.h
handler/i_s.h
+1
-0
handler/innodb_patch_info.h
handler/innodb_patch_info.h
+33
-0
include/fil0fil.h
include/fil0fil.h
+10
-0
include/srv0srv.h
include/srv0srv.h
+3
-0
include/sync0rw.h
include/sync0rw.h
+32
-13
include/sync0rw.ic
include/sync0rw.ic
+247
-24
include/thr0loc.h
include/thr0loc.h
+11
-0
include/univ.i
include/univ.i
+5
-3
lock/lock0lock.c
lock/lock0lock.c
+26
-26
log/log0log.c
log/log0log.c
+2
-2
srv/srv0srv.c
srv/srv0srv.c
+115
-28
sync/sync0arr.c
sync/sync0arr.c
+27
-21
sync/sync0rw.c
sync/sync0rw.c
+249
-35
thr/thr0loc.c
thr/thr0loc.c
+29
-0
No files found.
Makefile.am
View file @
8f3b5ebd
...
...
@@ -131,7 +131,7 @@ noinst_HEADERS= include/btr0btr.h include/btr0btr.ic \
include/ut0list.ic include/ut0wqueue.h
\
include/ha_prototypes.h handler/ha_innodb.h
\
include/handler0alter.h
\
handler/i_s.h
handler/i_s.h
handler/innodb_patch_info.h
EXTRA_LIBRARIES
=
libinnobase.a
noinst_LIBRARIES
=
@plugin_innobase_static_target@
...
...
Makefile.in
View file @
8f3b5ebd
...
...
@@ -651,7 +651,7 @@ noinst_HEADERS = include/btr0btr.h include/btr0btr.ic \
include/ut0list.ic include/ut0wqueue.h
\
include/ha_prototypes.h handler/ha_innodb.h
\
include/handler0alter.h
\
handler/i_s.h
handler/i_s.h
handler/innodb_patch_info.h
EXTRA_LIBRARIES
=
libinnobase.a
noinst_LIBRARIES
=
@plugin_innobase_static_target@
...
...
buf/buf0buf.c
View file @
8f3b5ebd
...
...
@@ -3596,12 +3596,14 @@ buf_print_io(
fprintf
(
file
,
"Buffer pool size %lu
\n
"
"Buffer pool size, bytes %lu
\n
"
"Free buffers %lu
\n
"
"Database pages %lu
\n
"
"Modified db pages %lu
\n
"
"Pending reads %lu
\n
"
"Pending writes: LRU %lu, flush list %lu, single page %lu
\n
"
,
(
ulong
)
size
,
(
ulong
)
size
*
UNIV_PAGE_SIZE
,
(
ulong
)
UT_LIST_GET_LEN
(
buf_pool
->
free
),
(
ulong
)
UT_LIST_GET_LEN
(
buf_pool
->
LRU
),
(
ulong
)
UT_LIST_GET_LEN
(
buf_pool
->
flush_list
),
...
...
fil/fil0fil.c
View file @
8f3b5ebd
...
...
@@ -4816,3 +4816,30 @@ fil_page_get_type(
return
(
mach_read_from_2
(
page
+
FIL_PAGE_TYPE
));
}
/*************************************************************************
Return local hash table informations. */
ulint
fil_system_hash_cells
(
void
)
/*=======================*/
{
if
(
fil_system
)
{
return
(
fil_system
->
spaces
->
n_cells
+
fil_system
->
name_hash
->
n_cells
);
}
else
{
return
0
;
}
}
ulint
fil_system_hash_nodes
(
void
)
/*=======================*/
{
if
(
fil_system
)
{
return
(
UT_LIST_GET_LEN
(
fil_system
->
space_list
)
*
(
sizeof
(
fil_space_t
)
+
MEM_BLOCK_HEADER_SIZE
));
}
else
{
return
0
;
}
}
handler/ha_innodb.cc
View file @
8f3b5ebd
...
...
@@ -9409,6 +9409,16 @@ static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binl
"Force InnoDB to not use next-key locking, to use only row-level locking."
,
NULL
,
NULL
,
FALSE
);
static
MYSQL_SYSVAR_ULONG
(
show_verbose_locks
,
srv_show_verbose_locks
,
PLUGIN_VAR_OPCMDARG
,
"Whether to show records locked in SHOW INNODB STATUS."
,
NULL
,
NULL
,
0
,
0
,
1
,
0
);
static
MYSQL_SYSVAR_ULONG
(
show_locks_held
,
srv_show_locks_held
,
PLUGIN_VAR_RQCMDARG
,
"Number of locks held to print for each InnoDB transaction in SHOW INNODB STATUS."
,
NULL
,
NULL
,
10
,
0
,
1000
,
0
);
#ifdef UNIV_LOG_ARCHIVE
static
MYSQL_SYSVAR_STR
(
log_arch_dir
,
innobase_log_arch_dir
,
PLUGIN_VAR_RQCMDARG
|
PLUGIN_VAR_READONLY
,
...
...
@@ -9559,7 +9569,7 @@ static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
static
MYSQL_SYSVAR_STR
(
version
,
innodb_version_str
,
PLUGIN_VAR_NOCMDOPT
|
PLUGIN_VAR_READONLY
,
"
InnoDB
version"
,
NULL
,
NULL
,
INNODB_VERSION_STR
);
"
Percona-InnoDB-plugin
version"
,
NULL
,
NULL
,
INNODB_VERSION_STR
);
static
MYSQL_SYSVAR_ULONG
(
io_capacity
,
srv_io_capacity
,
PLUGIN_VAR_RQCMDARG
,
...
...
@@ -9573,7 +9583,7 @@ static MYSQL_SYSVAR_ULONG(read_ahead, srv_read_ahead,
static
MYSQL_SYSVAR_ULONG
(
adaptive_checkpoint
,
srv_adaptive_checkpoint
,
PLUGIN_VAR_RQCMDARG
,
"Enable/Di
a
sable flushing along modified age 0:disable 1:enable"
,
"Enable/Disable flushing along modified age 0:disable 1:enable"
,
NULL
,
NULL
,
0
,
0
,
1
,
0
);
static
MYSQL_SYSVAR_ULONG
(
read_io_threads
,
innobase_read_io_threads
,
...
...
@@ -9631,6 +9641,8 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR
(
thread_concurrency
),
MYSQL_SYSVAR
(
thread_sleep_delay
),
MYSQL_SYSVAR
(
autoinc_lock_mode
),
MYSQL_SYSVAR
(
show_verbose_locks
),
MYSQL_SYSVAR
(
show_locks_held
),
MYSQL_SYSVAR
(
version
),
MYSQL_SYSVAR
(
io_capacity
),
MYSQL_SYSVAR
(
read_ahead
),
...
...
@@ -9823,7 +9835,8 @@ i_s_innodb_lock_waits,
i_s_innodb_cmp
,
i_s_innodb_cmp_reset
,
i_s_innodb_cmpmem
,
i_s_innodb_cmpmem_reset
i_s_innodb_cmpmem_reset
,
i_s_innodb_patches
mysql_declare_plugin_end
;
#ifdef UNIV_COMPILE_TEST_FUNCS
...
...
handler/i_s.cc
View file @
8f3b5ebd
...
...
@@ -15,6 +15,7 @@ Created July 18, 2007 Vasil Dimov
#include <mysys_err.h>
#include <my_sys.h>
#include "i_s.h"
#include "innodb_patch_info.h"
#include <mysql/plugin.h>
extern
"C"
{
...
...
@@ -199,6 +200,188 @@ field_store_ulint(
return
(
ret
);
}
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_patches */
static
ST_FIELD_INFO
innodb_patches_fields_info
[]
=
{
#define IDX_PATCH_NAME 0
{
STRUCT_FLD
(
field_name
,
"name"
),
STRUCT_FLD
(
field_length
,
255
),
STRUCT_FLD
(
field_type
,
MYSQL_TYPE_STRING
),
STRUCT_FLD
(
value
,
0
),
STRUCT_FLD
(
field_flags
,
0
),
STRUCT_FLD
(
old_name
,
""
),
STRUCT_FLD
(
open_method
,
SKIP_OPEN_TABLE
)},
#define IDX_PATCH_DESCR 1
{
STRUCT_FLD
(
field_name
,
"description"
),
STRUCT_FLD
(
field_length
,
255
),
STRUCT_FLD
(
field_type
,
MYSQL_TYPE_STRING
),
STRUCT_FLD
(
value
,
0
),
STRUCT_FLD
(
field_flags
,
0
),
STRUCT_FLD
(
old_name
,
""
),
STRUCT_FLD
(
open_method
,
SKIP_OPEN_TABLE
)},
#define IDX_PATCH_VER 2
{
STRUCT_FLD
(
field_name
,
"version"
),
STRUCT_FLD
(
field_length
,
10
),
STRUCT_FLD
(
field_type
,
MYSQL_TYPE_STRING
),
STRUCT_FLD
(
value
,
0
),
STRUCT_FLD
(
field_flags
,
0
),
STRUCT_FLD
(
old_name
,
""
),
STRUCT_FLD
(
open_method
,
SKIP_OPEN_TABLE
)},
#define IDX_PATCH_AUTHOR 3
{
STRUCT_FLD
(
field_name
,
"author"
),
STRUCT_FLD
(
field_length
,
50
),
STRUCT_FLD
(
field_type
,
MYSQL_TYPE_STRING
),
STRUCT_FLD
(
value
,
0
),
STRUCT_FLD
(
field_flags
,
0
),
STRUCT_FLD
(
old_name
,
""
),
STRUCT_FLD
(
open_method
,
SKIP_OPEN_TABLE
)},
#define IDX_PATCH_LICENCE 4
{
STRUCT_FLD
(
field_name
,
"licence"
),
STRUCT_FLD
(
field_length
,
50
),
STRUCT_FLD
(
field_type
,
MYSQL_TYPE_STRING
),
STRUCT_FLD
(
value
,
0
),
STRUCT_FLD
(
field_flags
,
0
),
STRUCT_FLD
(
old_name
,
""
),
STRUCT_FLD
(
open_method
,
SKIP_OPEN_TABLE
)},
#define IDX_PATCH_COMMENT 5
{
STRUCT_FLD
(
field_name
,
"comment"
),
STRUCT_FLD
(
field_length
,
100
),
STRUCT_FLD
(
field_type
,
MYSQL_TYPE_STRING
),
STRUCT_FLD
(
value
,
0
),
STRUCT_FLD
(
field_flags
,
0
),
STRUCT_FLD
(
old_name
,
""
),
STRUCT_FLD
(
open_method
,
SKIP_OPEN_TABLE
)},
END_OF_ST_FIELD_INFO
};
static
struct
st_mysql_information_schema
i_s_info
=
{
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
};
/***********************************************************************
Fill the dynamic table information_schema.innodb_patches */
static
int
innodb_patches_fill
(
/*=============*/
/* out: 0 on success, 1 on failure */
THD
*
thd
,
/* in: thread */
TABLE_LIST
*
tables
,
/* in/out: tables to fill */
COND
*
cond
)
/* in: condition (ignored) */
{
TABLE
*
table
=
(
TABLE
*
)
tables
->
table
;
int
status
=
0
;
int
i
;
Field
**
fields
;
DBUG_ENTER
(
"innodb_patches_fill"
);
fields
=
table
->
field
;
/* deny access to non-superusers */
if
(
check_global_access
(
thd
,
PROCESS_ACL
))
{
DBUG_RETURN
(
0
);
}
RETURN_IF_INNODB_NOT_STARTED
(
tables
->
schema_table_name
);
for
(
i
=
0
;
innodb_patches
[
i
].
file
;
i
++
)
{
field_store_string
(
fields
[
0
],
innodb_patches
[
i
].
file
);
field_store_string
(
fields
[
1
],
innodb_patches
[
i
].
name
);
field_store_string
(
fields
[
2
],
innodb_patches
[
i
].
version
);
field_store_string
(
fields
[
3
],
innodb_patches
[
i
].
author
);
field_store_string
(
fields
[
4
],
innodb_patches
[
i
].
license
);
field_store_string
(
fields
[
5
],
innodb_patches
[
i
].
comment
);
if
(
schema_table_store_record
(
thd
,
table
))
{
status
=
1
;
break
;
}
}
DBUG_RETURN
(
status
);
}
/***********************************************************************
Bind the dynamic table information_schema.innodb_patches. */
static
int
innodb_patches_init
(
/*=========*/
/* out: 0 on success */
void
*
p
)
/* in/out: table schema object */
{
DBUG_ENTER
(
"innodb_patches_init"
);
ST_SCHEMA_TABLE
*
schema
=
(
ST_SCHEMA_TABLE
*
)
p
;
schema
->
fields_info
=
innodb_patches_fields_info
;
schema
->
fill_table
=
innodb_patches_fill
;
DBUG_RETURN
(
0
);
}
UNIV_INTERN
struct
st_mysql_plugin
i_s_innodb_patches
=
{
/* the plugin type (a MYSQL_XXX_PLUGIN value) */
/* int */
STRUCT_FLD
(
type
,
MYSQL_INFORMATION_SCHEMA_PLUGIN
),
/* pointer to type-specific plugin descriptor */
/* void* */
STRUCT_FLD
(
info
,
&
i_s_info
),
/* plugin name */
/* const char* */
STRUCT_FLD
(
name
,
"INNODB_PATCHES"
),
/* plugin author (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD
(
author
,
"Percona"
),
/* general descriptive text (for SHOW PLUGINS) */
/* const char* */
STRUCT_FLD
(
descr
,
"Patches applied to InnoDB plugin"
),
/* the plugin license (PLUGIN_LICENSE_XXX) */
/* int */
STRUCT_FLD
(
license
,
PLUGIN_LICENSE_GPL
),
/* the function to invoke when plugin is loaded */
/* int (*)(void*); */
STRUCT_FLD
(
init
,
innodb_patches_init
),
/* the function to invoke when plugin is unloaded */
/* int (*)(void*); */
STRUCT_FLD
(
deinit
,
i_s_common_deinit
),
/* plugin version (for SHOW PLUGINS) */
/* unsigned int */
STRUCT_FLD
(
version
,
INNODB_VERSION_SHORT
),
/* struct st_mysql_show_var* */
STRUCT_FLD
(
status_vars
,
NULL
),
/* struct st_mysql_sys_var** */
STRUCT_FLD
(
system_vars
,
NULL
),
/* reserved for dependency checking */
/* void* */
STRUCT_FLD
(
__reserved1
,
NULL
)
};
/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
static
ST_FIELD_INFO
innodb_trx_fields_info
[]
=
{
...
...
@@ -383,10 +566,6 @@ innodb_trx_init(
DBUG_RETURN
(
0
);
}
static
struct
st_mysql_information_schema
i_s_info
=
{
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
};
UNIV_INTERN
struct
st_mysql_plugin
i_s_innodb_trx
=
{
...
...
handler/i_s.h
View file @
8f3b5ebd
...
...
@@ -16,5 +16,6 @@ extern struct st_mysql_plugin i_s_innodb_cmp;
extern
struct
st_mysql_plugin
i_s_innodb_cmp_reset
;
extern
struct
st_mysql_plugin
i_s_innodb_cmpmem
;
extern
struct
st_mysql_plugin
i_s_innodb_cmpmem_reset
;
extern
struct
st_mysql_plugin
i_s_innodb_patches
;
#endif
/* i_s_h */
handler/innodb_patch_info.h
0 → 100644
View file @
8f3b5ebd
/* Copyright (C) 2002-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef USE_PRAGMA_INTERFACE
#pragma interface
/* gcc class implementation */
#endif
struct
innodb_patch
{
const
char
*
file
;
const
char
*
name
;
const
char
*
version
;
const
char
*
author
;
const
char
*
license
;
const
char
*
comment
;
}
innodb_patches
[]
=
{
{
"innodb_show_patches.patch"
,
"I_S.INNODB_PATCHES"
,
"1.0"
,
"Percona"
,
"GPLv2"
,
""
},
{
"innodb_show_status.patch"
,
"Fixes to SHOW INNODB STATUS"
,
"1.0"
,
"Percona"
,
"GPLv2"
,
"Memory information and lock info fixes"
},
{
"innodb_io_patches.patch"
,
"Patches to InnoDB IO"
,
"1.0"
,
"Percona"
,
"GPLv2"
,
""
},
{
"innodb_rw_lock.patch"
,
"InnoDB RW-lock fixes"
,
"1.0"
,
"Percona"
,
"GPLv2"
,
"Useful for 8+ cores SMP systems"
},
{
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
}
};
include/fil0fil.h
View file @
8f3b5ebd
...
...
@@ -696,6 +696,16 @@ fil_page_get_type(
return value not defined */
const
byte
*
page
);
/* in: file page */
/*************************************************************************
Return local hash table informations. */
ulint
fil_system_hash_cells
(
void
);
/*========================*/
ulint
fil_system_hash_nodes
(
void
);
/*========================*/
typedef
struct
fil_space_struct
fil_space_t
;
...
...
include/srv0srv.h
View file @
8f3b5ebd
...
...
@@ -90,6 +90,9 @@ extern ulint srv_log_file_size;
extern
ulint
srv_log_buffer_size
;
extern
ulong
srv_flush_log_at_trx_commit
;
extern
ulint
srv_show_locks_held
;
extern
ulint
srv_show_verbose_locks
;
/* The sort order table of the MySQL latin1_swedish_ci character set
collation */
extern
const
byte
*
srv_latin1_ordering
;
...
...
include/sync0rw.h
View file @
8f3b5ebd
...
...
@@ -328,7 +328,17 @@ rw_lock_get_x_lock_count(
Accessor functions for rw lock. */
UNIV_INLINE
ulint
rw_lock_get_waiters
(
rw_lock_get_s_waiters
(
/*==================*/
rw_lock_t
*
lock
);
UNIV_INLINE
ulint
rw_lock_get_x_waiters
(
/*==================*/
rw_lock_t
*
lock
);
UNIV_INLINE
ulint
rw_lock_get_wx_waiters
(
/*================*/
rw_lock_t
*
lock
);
UNIV_INLINE
...
...
@@ -412,6 +422,11 @@ rw_lock_debug_print(
rw_lock_debug_t
*
info
);
/* in: debug struct */
#endif
/* UNIV_SYNC_DEBUG */
#ifdef HAVE_GCC_ATOMIC_BUILTINS
/* This value means NOT_LOCKED */
#define RW_LOCK_BIAS 0x00100000
#endif
/* NOTE! The structure appears here only for the compiler to know its size.
Do not use its fields directly! The structure used in the spin lock
implementation of a read-write lock. Several threads may have a shared lock
...
...
@@ -421,9 +436,9 @@ blocked by readers, a writer may queue for the lock by setting the writer
field. Then no new readers are allowed in. */
struct
rw_lock_struct
{
os_event_t
event
;
/* Used by sync0arr.c for thread queueing */
#ifdef __WIN__
/* Used by sync0arr.c for thread queueing */
os_event_t
s_event
;
/* Used for s_lock */
os_event_t
x_event
;
/* Used for x_lock */
os_event_t
wait_ex_event
;
/* This windows specific event is
used by the thread which has set the
lock state to RW_LOCK_WAIT_EX. The
...
...
@@ -431,30 +446,34 @@ struct rw_lock_struct {
thread will be the next one to proceed
once the current the event gets
signalled. See LEMMA 2 in sync0sync.c */
#ifdef HAVE_GCC_ATOMIC_BUILTINS
volatile
lint
lock_word
;
/* Used by using atomic builtin */
#endif
ulint
reader_count
;
/* Number of readers who have locked this
volatile
ulint
reader_count
;
/* Number of readers who have locked this
lock in the shared mode */
ulint
writer
;
/* This field is set to RW_LOCK_EX if there
volatile
ulint
writer
;
/* This field is set to RW_LOCK_EX if there
is a writer owning the lock (in exclusive
mode), RW_LOCK_WAIT_EX if a writer is
queueing for the lock, and
RW_LOCK_NOT_LOCKED, otherwise. */
os_thread_id_t
writer_thread
;
volatile
os_thread_id_t
writer_thread
;
/* Thread id of a possible writer thread */
ulint
writer_count
;
/* Number of times the same thread has
volatile
ulint
writer_count
;
/* Number of times the same thread has
recursively locked the lock in the exclusive
mode */
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_t
mutex
;
/* The mutex protecting rw_lock_struct */
#endif
ulint
pass
;
/* Default value 0. This is set to some
value != 0 given by the caller of an x-lock
operation, if the x-lock is to be passed to
another thread to unlock (which happens in
asynchronous i/o). */
ulint
waiters
;
/* This ulint is set to 1 if there are
waiters (readers or writers) in the global
wait array, waiting for this rw_lock.
Otherwise, == 0. */
volatile
ulint
s_waiters
;
/* 1: there are waiters (s_lock) */
volatile
ulint
x_waiters
;
/* 1: there are waiters (x_lock) */
volatile
ulint
wait_ex_waiters
;
/* 1: there are waiters (wait_ex) */
UT_LIST_NODE_T
(
rw_lock_t
)
list
;
/* All allocated rw locks are put into a
list */
...
...
@@ -467,7 +486,7 @@ struct rw_lock_struct {
const
char
*
cfile_name
;
/* File name where lock created */
const
char
*
last_s_file_name
;
/* File name where last s-locked */
const
char
*
last_x_file_name
;
/* File name where last x-locked */
ibool
writer_is_wait_ex
;
volatile
ibool
writer_is_wait_ex
;
/* This is TRUE if the writer field is
RW_LOCK_WAIT_EX; this field is located far
from the memory update hotspot fields which
...
...
include/sync0rw.ic
View file @
8f3b5ebd
...
...
@@ -47,20 +47,52 @@ rw_lock_remove_debug_info(
Accessor functions for rw lock. */
UNIV_INLINE
ulint
rw_lock_get_waiters(
rw_lock_get_
s_
waiters(
/*================*/
rw_lock_t* lock)
{
return(lock->waiters);
return(lock->s_waiters);
}
UNIV_INLINE
ulint
rw_lock_get_x_waiters(
/*================*/
rw_lock_t* lock)
{
return(lock->x_waiters);
}
UNIV_INLINE
ulint
rw_lock_get_wx_waiters(
/*================*/
rw_lock_t* lock)
{
return(lock->wait_ex_waiters);
}
UNIV_INLINE
void
rw_lock_set_s_waiters(
rw_lock_t* lock,
ulint flag)
{
lock->s_waiters = flag;
}
UNIV_INLINE
void
rw_lock_set_waiters(
rw_lock_set_x_waiters(
rw_lock_t* lock,
ulint flag)
{
lock->x_waiters = flag;
}
UNIV_INLINE
void
rw_lock_set_wx_waiters(
/*================*/
rw_lock_t* lock,
ulint flag)
{
lock->waiters = flag;
lock->wait
_ex_wait
ers = flag;
}
UNIV_INLINE
ulint
...
...
@@ -68,7 +100,19 @@ rw_lock_get_writer(
/*===============*/
rw_lock_t* lock)
{
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if (lock->writer == RW_LOCK_NOT_LOCKED) {
return(RW_LOCK_NOT_LOCKED);
}
if (lock->writer_is_wait_ex) {
return(RW_LOCK_WAIT_EX);
} else {
return(RW_LOCK_EX);
}
#else
return(lock->writer);
#endif
}
UNIV_INLINE
void
...
...
@@ -96,6 +140,7 @@ rw_lock_set_reader_count(
{
lock->reader_count = count;
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
UNIV_INLINE
mutex_t*
rw_lock_get_mutex(
...
...
@@ -104,6 +149,7 @@ rw_lock_get_mutex(
{
return(&(lock->mutex));
}
#endif
/**********************************************************************
Returns the value of writer_count for the lock. Does not reserve the lock
...
...
@@ -133,13 +179,27 @@ rw_lock_s_lock_low(
const char* file_name, /* in: file name where lock requested */
ulint line) /* in: line where requested */
{
#ifndef HAVE_GCC_ATOMIC_BUILTINS
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
#endif
/* Check if the writer field is free */
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if (UNIV_LIKELY(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)) {
/* try s-lock */
if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
/* fail */
__sync_fetch_and_add(&(lock->lock_word),1);
return(FALSE); /* locking did not succeed */
}
/* success */
__sync_fetch_and_add(&(lock->reader_count),1);
#else
if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
/* Set the shared lock by incrementing the reader count */
lock->reader_count++;
#endif
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
...
...
@@ -166,11 +226,15 @@ rw_lock_s_lock_direct(
const char* file_name, /* in: file name where requested */
ulint line) /* in: line where lock requested */
{
ut_ad(
lock->writer
== RW_LOCK_NOT_LOCKED);
ut_ad(
rw_lock_get_writer(lock)
== RW_LOCK_NOT_LOCKED);
ut_ad(rw_lock_get_reader_count(lock) == 0);
/* Set the shared lock by incrementing the reader count */
#ifdef HAVE_GCC_ATOMIC_BUILTINS
__sync_fetch_and_add(&(lock->reader_count),1);
#else
lock->reader_count++;
#endif
lock->last_s_file_name = file_name;
lock->last_s_line = line;
...
...
@@ -198,7 +262,11 @@ rw_lock_x_lock_direct(
rw_lock_set_writer(lock, RW_LOCK_EX);
lock->writer_thread = os_thread_get_curr_id();
#ifdef HAVE_GCC_ATOMIC_BUILTINS
__sync_fetch_and_add(&(lock->writer_count),1);
#else
lock->writer_count++;
#endif
lock->pass = 0;
lock->last_x_file_name = file_name;
...
...
@@ -240,15 +308,21 @@ rw_lock_s_lock_func(
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
#endif /* UNIV_SYNC_DEBUG */
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter(rw_lock_get_mutex(lock));
#endif
if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit(rw_lock_get_mutex(lock));
#endif
return; /* Success */
} else {
/* Did not succeed, try spin wait */
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit(rw_lock_get_mutex(lock));
#endif
rw_lock_s_lock_spin(lock, pass, file_name, line);
...
...
@@ -271,11 +345,23 @@ rw_lock_s_lock_func_nowait(
{
ibool success = FALSE;
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
/* try s-lock */
if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
/* fail */
__sync_fetch_and_add(&(lock->lock_word),1);
return(FALSE); /* locking did not succeed */
}
/* success */
__sync_fetch_and_add(&(lock->reader_count),1);
#else
mutex_enter(rw_lock_get_mutex(lock));
if (lock->writer == RW_LOCK_NOT_LOCKED) {
/* Set the shared lock by incrementing the reader count */
lock->reader_count++;
#endif
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
...
...
@@ -288,7 +374,9 @@ rw_lock_s_lock_func_nowait(
success = TRUE;
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit(rw_lock_get_mutex(lock));
#endif
return(success);
}
...
...
@@ -308,6 +396,55 @@ rw_lock_x_lock_func_nowait(
{
ibool success = FALSE;
os_thread_id_t curr_thread = os_thread_get_curr_id();
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if ((lock->lock_word == RW_LOCK_BIAS)
&& rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
/* try x-lock */
if(__sync_sub_and_fetch(&(lock->lock_word),
RW_LOCK_BIAS) == 0) {
/* success */
/* try to lock writer */
if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
== RW_LOCK_NOT_LOCKED) {
/* success */
lock->writer_thread = curr_thread;
lock->pass = 0;
lock->writer_is_wait_ex = FALSE;
/* next function may work as memory barrier */
relock:
__sync_fetch_and_add(&(lock->writer_count),1);
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
lock->last_x_file_name = file_name;
lock->last_x_line = line;
ut_ad(rw_lock_validate(lock));
return(TRUE);
} else {
/* x-unlock */
__sync_fetch_and_add(&(lock->lock_word),
RW_LOCK_BIAS);
}
} else {
/* fail (x-lock) */
__sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
}
}
if (lock->pass == 0
&& os_thread_eq(lock->writer_thread, curr_thread)
&& rw_lock_get_writer(lock) == RW_LOCK_EX) {
goto relock;
}
ut_ad(rw_lock_validate(lock));
return(FALSE);
#else
mutex_enter(rw_lock_get_mutex(lock));
if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
...
...
@@ -338,6 +475,7 @@ relock:
ut_ad(rw_lock_validate(lock));
return(success);
#endif
}
/**********************************************************************
...
...
@@ -353,16 +491,33 @@ rw_lock_s_unlock_func(
#endif
)
{
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_t* mutex = &(lock->mutex);
ibool sg = FALSE;
#endif
ibool x_sg = FALSE;
ibool wx_sg = FALSE;
#ifdef HAVE_GCC_ATOMIC_BUILTINS
ibool last = FALSE;
#endif
#ifndef HAVE_GCC_ATOMIC_BUILTINS
/* Acquire the mutex protecting the rw-lock fields */
mutex_enter(mutex);
#endif
/* Reset the shared lock by decrementing the reader count */
ut_a(lock->reader_count > 0);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
/* unlock lock_word */
__sync_fetch_and_add(&(lock->lock_word),1);
if(__sync_sub_and_fetch(&(lock->reader_count),1) == 0) {
last = TRUE;
}
#else
lock->reader_count--;
#endif
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
...
...
@@ -371,20 +526,36 @@ rw_lock_s_unlock_func(
/* If there may be waiters and this was the last s-lock,
signal the object */
if (UNIV_UNLIKELY(lock->waiters)
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if (UNIV_UNLIKELY(last && lock->wait_ex_waiters)) {
#else
if (UNIV_UNLIKELY(lock->wait_ex_waiters)
&& lock->reader_count == 0) {
sg = TRUE;
#endif
wx_sg = TRUE;
rw_lock_set_waiters(lock, 0);
rw_lock_set_w
x_w
aiters(lock, 0);
}
#ifdef HAVE_GCC_ATOMIC_BUILTINS
else if (UNIV_UNLIKELY(last && lock->x_waiters)) {
#else
else if (UNIV_UNLIKELY(lock->x_waiters)
&& lock->reader_count == 0) {
#endif
x_sg = TRUE;
rw_lock_set_x_waiters(lock, 0);
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit(mutex);
#endif
if (UNIV_UNLIKELY(sg)) {
#ifdef __WIN__
if (UNIV_UNLIKELY(wx_sg)) {
os_event_set(lock->wait_ex_event);
#endif
os_event_set(lock->event);
sync_array_object_signalled(sync_primary_wait_array);
} else if (UNIV_UNLIKELY(x_sg)) {
os_event_set(lock->x_event);
sync_array_object_signalled(sync_primary_wait_array);
}
...
...
@@ -408,13 +579,19 @@ rw_lock_s_unlock_direct(
ut_ad(lock->reader_count > 0);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
__sync_sub_and_fetch(&(lock->reader_count),1);
#else
lock->reader_count--;
#endif
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
#endif
ut_ad(!lock->waiters);
ut_ad(!lock->s_waiters);
ut_ad(!lock->x_waiters);
ut_ad(!lock->wait_ex_waiters);
ut_ad(rw_lock_validate(lock));
#ifdef UNIV_SYNC_PERF_STAT
rw_s_exit_count++;
...
...
@@ -434,41 +611,81 @@ rw_lock_x_unlock_func(
#endif
)
{
ibool sg = FALSE;
#ifdef HAVE_GCC_ATOMIC_BUILTINS
ibool last = FALSE;
#endif
ibool s_sg = FALSE;
ibool x_sg = FALSE;
#ifndef HAVE_GCC_ATOMIC_BUILTINS
/* Acquire the mutex protecting the rw-lock fields */
mutex_enter(&(lock->mutex));
#endif
/* Reset the exclusive lock if this thread no longer has an x-mode
lock */
ut_ad(lock->writer_count > 0);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
last = TRUE;
}
if (last) {
/* unlock lock_word */
__sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
/* FIXME: It is a value of bad manners for pthread.
But we shouldn't keep an ID of not-owner. */
lock->writer_thread = -1;
/* atomic operation may be safer about memory order. */
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
__sync_synchronize();
}
#else
lock->writer_count--;
if (lock->writer_count == 0) {
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
}
#endif
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
#endif
/* If there may be waiters, signal the lock */
if (UNIV_UNLIKELY(lock->waiters)
&& lock->writer_count == 0) {
sg = TRUE;
rw_lock_set_waiters(lock, 0);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if (last) {
#else
if (lock->writer_count == 0) {
#endif
if(lock->s_waiters){
s_sg = TRUE;
rw_lock_set_s_waiters(lock, 0);
}
if(lock->x_waiters){
x_sg = TRUE;
rw_lock_set_x_waiters(lock, 0);
}
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit(&(lock->mutex));
#endif
if (UNIV_UNLIKELY(sg)) {
if (UNIV_UNLIKELY(s_sg)) {
os_event_set(lock->s_event);
sync_array_object_signalled(sync_primary_wait_array);
}
if (UNIV_UNLIKELY(x_sg)) {
#ifdef __WIN__
/* I doubt the necessity of it. */
os_event_set(lock->wait_ex_event);
#endif
os_event_set(lock->event);
os_event_set(lock->
x_
event);
sync_array_object_signalled(sync_primary_wait_array);
}
...
...
@@ -493,9 +710,13 @@ rw_lock_x_unlock_direct(
ut_ad(lock->writer_count > 0);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
#else
lock->writer_count--;
if (lock->writer_count == 0) {
#endif
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
}
...
...
@@ -503,7 +724,9 @@ rw_lock_x_unlock_direct(
rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
#endif
ut_ad(!lock->waiters);
ut_ad(!lock->s_waiters);
ut_ad(!lock->x_waiters);
ut_ad(!lock->wait_ex_waiters);
ut_ad(rw_lock_validate(lock));
#ifdef UNIV_SYNC_PERF_STAT
...
...
include/thr0loc.h
View file @
8f3b5ebd
...
...
@@ -60,6 +60,17 @@ thr_local_get_in_ibuf_field(void);
/*=============================*/
/* out: pointer to the in_ibuf field */
/*************************************************************************
Return local hash table informations. */
ulint
thr_local_hash_cells
(
void
);
/*=======================*/
ulint
thr_local_hash_nodes
(
void
);
/*=======================*/
#ifndef UNIV_NONINL
#include "thr0loc.ic"
#endif
...
...
include/univ.i
View file @
8f3b5ebd
...
...
@@ -12,6 +12,7 @@ Created 1/20/1994 Heikki Tuuri
#
define
INNODB_VERSION_MAJOR
1
#
define
INNODB_VERSION_MINOR
0
#
define
INNODB_VERSION_BUGFIX
2
#
define
PERCONA_INNODB_VERSION
-
1
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
...
...
@@ -23,13 +24,14 @@ component, i.e. we show M.N.P as M.N */
(
INNODB_VERSION_MAJOR
<<
8
|
INNODB_VERSION_MINOR
)
/* auxiliary macros to help creating the version as string */
#
define
__INNODB_VERSION
(
a
,
b
,
c
)
(
#
a
"."
#
b
"."
#
c
)
#
define
_INNODB_VERSION
(
a
,
b
,
c
)
__INNODB_VERSION
(
a
,
b
,
c
)
#
define
__INNODB_VERSION
(
a
,
b
,
c
,
d
)
(
#
a
"."
#
b
"."
#
c
"."
#
d
)
#
define
_INNODB_VERSION
(
a
,
b
,
c
,
d
)
__INNODB_VERSION
(
a
,
b
,
c
,
d
)
#
define
INNODB_VERSION_STR
\
_INNODB_VERSION
(
INNODB_VERSION_MAJOR
,
\
INNODB_VERSION_MINOR
,
\
INNODB_VERSION_BUGFIX
)
INNODB_VERSION_BUGFIX
,
\
PERCONA_INNODB_VERSION
)
#
ifdef
MYSQL_DYNAMIC_PLUGIN
/* In the dynamic plugin, redefine some externally visible symbols
...
...
lock/lock0lock.c
View file @
8f3b5ebd
...
...
@@ -4294,8 +4294,8 @@ lock_rec_print(
putc
(
'\n'
,
file
);
if
(
srv_show_verbose_locks
)
{
block
=
buf_page_try_get
(
space
,
page_no
,
&
mtr
);
if
(
block
)
{
for
(
i
=
0
;
i
<
lock_rec_get_n_bits
(
lock
);
i
++
)
{
...
...
@@ -4319,7 +4319,7 @@ lock_rec_print(
fprintf
(
file
,
"Record lock, heap no %lu
\n
"
,
(
ulong
)
i
);
}
}
}
mtr_commit
(
&
mtr
);
if
(
UNIV_LIKELY_NULL
(
heap
))
{
mem_heap_free
(
heap
);
...
...
@@ -4498,7 +4498,7 @@ lock_print_info_all_transactions(
}
}
if
(
!
srv_print_innodb_lock_monitor
)
{
if
(
!
srv_print_innodb_lock_monitor
&&
!
srv_show_locks_held
)
{
nth_trx
++
;
goto
loop
;
}
...
...
@@ -4557,8 +4557,8 @@ lock_print_info_all_transactions(
nth_lock
++
;
if
(
nth_lock
>=
10
)
{
fputs
(
"
10
LOCKS PRINTED FOR THIS TRX:"
if
(
nth_lock
>=
srv_show_locks_held
)
{
fputs
(
"
TOO
LOCKS PRINTED FOR THIS TRX:"
" SUPPRESSING FURTHER PRINTS
\n
"
,
file
);
...
...
log/log0log.c
View file @
8f3b5ebd
...
...
@@ -3263,9 +3263,9 @@ log_print(
"Modified age %lu
\n
"
"Checkpoint age %lu
\n
"
,
(
ulong
)
log_sys
->
max_checkpoint_age
,
(
ulong
)
ut_dulint_minus
(
log_sys
->
lsn
,
(
ulong
)
(
log_sys
->
lsn
-
log_buf_pool_get_oldest_modification
()),
(
ulong
)
ut_dulint_minus
(
log_sys
->
lsn
,
log_sys
->
last_checkpoint_lsn
));
(
ulong
)
(
log_sys
->
lsn
-
log_sys
->
last_checkpoint_lsn
));
current_time
=
time
(
NULL
);
...
...
srv/srv0srv.c
View file @
8f3b5ebd
...
...
@@ -132,6 +132,10 @@ UNIV_INTERN ulint srv_log_file_size = ULINT_MAX;
UNIV_INTERN
ulint
srv_log_buffer_size
=
ULINT_MAX
;
UNIV_INTERN
ulong
srv_flush_log_at_trx_commit
=
1
;
UNIV_INTERN
ulint
srv_show_locks_held
=
10
;
UNIV_INTERN
ulint
srv_show_verbose_locks
=
0
;
/* The sort order table of the MySQL latin1_swedish_ci character set
collation */
UNIV_INTERN
const
byte
*
srv_latin1_ordering
;
...
...
@@ -1625,6 +1629,14 @@ srv_printf_innodb_monitor(
time_t
current_time
;
ulint
n_reserved
;
ulint
btr_search_sys_subtotal
;
ulint
lock_sys_subtotal
;
ulint
recv_sys_subtotal
;
ulint
io_counter_subtotal
;
ulint
i
;
trx_t
*
trx
;
mutex_enter
(
&
srv_innodb_monitor_mutex
);
current_time
=
time
(
NULL
);
...
...
@@ -1668,24 +1680,6 @@ srv_printf_innodb_monitor(
mutex_exit
(
&
dict_foreign_err_mutex
);
lock_print_info_summary
(
file
);
if
(
trx_start
)
{
long
t
=
ftell
(
file
);
if
(
t
<
0
)
{
*
trx_start
=
ULINT_UNDEFINED
;
}
else
{
*
trx_start
=
(
ulint
)
t
;
}
}
lock_print_info_all_transactions
(
file
);
if
(
trx_end
)
{
long
t
=
ftell
(
file
);
if
(
t
<
0
)
{
*
trx_end
=
ULINT_UNDEFINED
;
}
else
{
*
trx_end
=
(
ulint
)
t
;
}
}
fputs
(
"--------
\n
"
"FILE I/O
\n
"
"--------
\n
"
,
file
);
...
...
@@ -1720,6 +1714,80 @@ srv_printf_innodb_monitor(
"; in additional pool allocated "
ULINTPF
"
\n
"
,
ut_total_allocated_memory
,
mem_pool_get_reserved
(
mem_comm_pool
));
/* Calcurate reserved memories */
if
(
btr_search_sys
&&
btr_search_sys
->
hash_index
->
heap
)
{
btr_search_sys_subtotal
=
mem_heap_get_size
(
btr_search_sys
->
hash_index
->
heap
);
}
else
{
btr_search_sys_subtotal
=
0
;
for
(
i
=
0
;
i
<
btr_search_sys
->
hash_index
->
n_mutexes
;
i
++
)
{
btr_search_sys_subtotal
+=
mem_heap_get_size
(
btr_search_sys
->
hash_index
->
heaps
[
i
]);
}
}
lock_sys_subtotal
=
0
;
if
(
trx_sys
)
{
mutex_enter
(
&
kernel_mutex
);
trx
=
UT_LIST_GET_FIRST
(
trx_sys
->
mysql_trx_list
);
while
(
trx
)
{
lock_sys_subtotal
+=
((
trx
->
lock_heap
)
?
mem_heap_get_size
(
trx
->
lock_heap
)
:
0
);
trx
=
UT_LIST_GET_NEXT
(
mysql_trx_list
,
trx
);
}
mutex_exit
(
&
kernel_mutex
);
}
recv_sys_subtotal
=
((
recv_sys
&&
recv_sys
->
addr_hash
)
?
mem_heap_get_size
(
recv_sys
->
heap
)
:
0
);
fprintf
(
file
,
"Internal hash tables (constant factor + variable factor)
\n
"
" Adaptive hash index %lu
\t
(%lu + %lu)
\n
"
" Page hash %lu
\n
"
" Dictionary cache %lu
\t
(%lu + %lu)
\n
"
" File system %lu
\t
(%lu + %lu)
\n
"
" Lock system %lu
\t
(%lu + %lu)
\n
"
" Recovery system %lu
\t
(%lu + %lu)
\n
"
" Threads %lu
\t
(%lu + %lu)
\n
"
,
(
ulong
)
(
btr_search_sys
?
(
btr_search_sys
->
hash_index
->
n_cells
*
sizeof
(
hash_cell_t
))
:
0
)
+
btr_search_sys_subtotal
,
(
ulong
)
(
btr_search_sys
?
(
btr_search_sys
->
hash_index
->
n_cells
*
sizeof
(
hash_cell_t
))
:
0
),
(
ulong
)
btr_search_sys_subtotal
,
(
ulong
)
(
buf_pool
->
page_hash
->
n_cells
*
sizeof
(
hash_cell_t
)),
(
ulong
)
(
dict_sys
?
((
dict_sys
->
table_hash
->
n_cells
+
dict_sys
->
table_id_hash
->
n_cells
)
*
sizeof
(
hash_cell_t
)
+
dict_sys
->
size
)
:
0
),
(
ulong
)
(
dict_sys
?
((
dict_sys
->
table_hash
->
n_cells
+
dict_sys
->
table_id_hash
->
n_cells
)
*
sizeof
(
hash_cell_t
))
:
0
),
(
ulong
)
(
dict_sys
?
(
dict_sys
->
size
)
:
0
),
(
ulong
)
(
fil_system_hash_cells
()
*
sizeof
(
hash_cell_t
)
+
fil_system_hash_nodes
()),
(
ulong
)
(
fil_system_hash_cells
()
*
sizeof
(
hash_cell_t
)),
(
ulong
)
fil_system_hash_nodes
(),
(
ulong
)
((
lock_sys
?
(
lock_sys
->
rec_hash
->
n_cells
*
sizeof
(
hash_cell_t
))
:
0
)
+
lock_sys_subtotal
),
(
ulong
)
(
lock_sys
?
(
lock_sys
->
rec_hash
->
n_cells
*
sizeof
(
hash_cell_t
))
:
0
),
(
ulong
)
lock_sys_subtotal
,
(
ulong
)
(((
recv_sys
&&
recv_sys
->
addr_hash
)
?
(
recv_sys
->
addr_hash
->
n_cells
*
sizeof
(
hash_cell_t
))
:
0
)
+
recv_sys_subtotal
),
(
ulong
)
((
recv_sys
&&
recv_sys
->
addr_hash
)
?
(
recv_sys
->
addr_hash
->
n_cells
*
sizeof
(
hash_cell_t
))
:
0
),
(
ulong
)
recv_sys_subtotal
,
(
ulong
)
(
thr_local_hash_cells
()
*
sizeof
(
hash_cell_t
)
+
thr_local_hash_nodes
()),
(
ulong
)
(
thr_local_hash_cells
()
*
sizeof
(
hash_cell_t
)),
(
ulong
)
thr_local_hash_nodes
());
fprintf
(
file
,
"Dictionary memory allocated "
ULINTPF
"
\n
"
,
dict_sys
->
size
);
...
...
@@ -1778,6 +1846,25 @@ srv_printf_innodb_monitor(
srv_n_rows_deleted_old
=
srv_n_rows_deleted
;
srv_n_rows_read_old
=
srv_n_rows_read
;
lock_print_info_summary
(
file
);
if
(
trx_start
)
{
long
t
=
ftell
(
file
);
if
(
t
<
0
)
{
*
trx_start
=
ULINT_UNDEFINED
;
}
else
{
*
trx_start
=
(
ulint
)
t
;
}
}
lock_print_info_all_transactions
(
file
);
if
(
trx_end
)
{
long
t
=
ftell
(
file
);
if
(
t
<
0
)
{
*
trx_end
=
ULINT_UNDEFINED
;
}
else
{
*
trx_end
=
(
ulint
)
t
;
}
}
fputs
(
"----------------------------
\n
"
"END OF INNODB MONITOR OUTPUT
\n
"
"============================
\n
"
,
file
);
...
...
@@ -2214,7 +2301,7 @@ srv_master_thread(
ibool
skip_sleep
=
FALSE
;
ulint
i
;
dulint
oldest_lsn
;
ib_uint64_t
oldest_lsn
;
#ifdef UNIV_DEBUG_THREAD_CREATION
fprintf
(
stderr
,
"Master thread starts, id %lu
\n
"
,
...
...
@@ -2336,12 +2423,12 @@ srv_master_thread(
mutex_enter
(
&
(
log_sys
->
mutex
));
oldest_lsn
=
buf_pool_get_oldest_modification
();
if
(
ut_dulint_is_zero
(
oldest_lsn
)
)
{
if
(
oldest_lsn
==
0
)
{
mutex_exit
(
&
(
log_sys
->
mutex
));
}
else
{
if
(
ut_dulint_minus
(
log_sys
->
lsn
,
oldest_lsn
)
if
(
(
log_sys
->
lsn
-
oldest_lsn
)
>
(
log_sys
->
max_checkpoint_age
)
-
((
log_sys
->
max_checkpoint_age
)
/
4
))
{
/* 2nd defence line (max_checkpoint_age * 3/4) */
...
...
@@ -2349,9 +2436,9 @@ srv_master_thread(
mutex_exit
(
&
(
log_sys
->
mutex
));
n_pages_flushed
=
buf_flush_batch
(
BUF_FLUSH_LIST
,
PCT_IO
(
100
),
ut_dulint_max
);
IB_ULONGLONG_MAX
);
skip_sleep
=
TRUE
;
}
else
if
(
ut_dulint_minus
(
log_sys
->
lsn
,
oldest_lsn
)
}
else
if
(
(
log_sys
->
lsn
-
oldest_lsn
)
>
(
log_sys
->
max_checkpoint_age
)
/
2
)
{
/* 1st defence line (max_checkpoint_age * 1/2) */
...
...
@@ -2359,7 +2446,7 @@ srv_master_thread(
mutex_exit
(
&
(
log_sys
->
mutex
));
n_pages_flushed
=
buf_flush_batch
(
BUF_FLUSH_LIST
,
PCT_IO
(
10
),
ut_dulint_max
);
IB_ULONGLONG_MAX
);
skip_sleep
=
TRUE
;
}
else
{
mutex_exit
(
&
(
log_sys
->
mutex
));
...
...
sync/sync0arr.c
View file @
8f3b5ebd
...
...
@@ -307,13 +307,13 @@ sync_cell_event_reset(
{
if
(
type
==
SYNC_MUTEX
)
{
return
(
os_event_reset
(((
mutex_t
*
)
object
)
->
event
));
#ifdef __WIN__
}
else
if
(
type
==
RW_LOCK_WAIT_EX
)
{
return
(
os_event_reset
(
((
rw_lock_t
*
)
object
)
->
wait_ex_event
));
#endif
}
else
{
return
(
os_event_reset
(((
rw_lock_t
*
)
object
)
->
event
));
}
else
if
(
type
==
RW_LOCK_SHARED
)
{
return
(
os_event_reset
(((
rw_lock_t
*
)
object
)
->
s_event
));
}
else
{
/* RW_LOCK_EX */
return
(
os_event_reset
(((
rw_lock_t
*
)
object
)
->
x_event
));
}
}
...
...
@@ -413,15 +413,12 @@ sync_array_wait_event(
if
(
cell
->
request_type
==
SYNC_MUTEX
)
{
event
=
((
mutex_t
*
)
cell
->
wait_object
)
->
event
;
#ifdef __WIN__
/* On windows if the thread about to wait is the one which
has set the state of the rw_lock to RW_LOCK_WAIT_EX, then
it waits on a special event i.e.: wait_ex_event. */
}
else
if
(
cell
->
request_type
==
RW_LOCK_WAIT_EX
)
{
event
=
((
rw_lock_t
*
)
cell
->
wait_object
)
->
wait_ex_event
;
#endif
}
else
if
(
cell
->
request_type
==
RW_LOCK_SHARED
)
{
event
=
((
rw_lock_t
*
)
cell
->
wait_object
)
->
s_event
;
}
else
{
event
=
((
rw_lock_t
*
)
cell
->
wait_object
)
->
event
;
event
=
((
rw_lock_t
*
)
cell
->
wait_object
)
->
x_
event
;
}
cell
->
waiting
=
TRUE
;
...
...
@@ -462,6 +459,7 @@ sync_array_cell_print(
mutex_t
*
mutex
;
rw_lock_t
*
rwlock
;
ulint
type
;
ulint
writer
;
type
=
cell
->
request_type
;
...
...
@@ -491,12 +489,10 @@ sync_array_cell_print(
(
ulong
)
mutex
->
waiters
);
}
else
if
(
type
==
RW_LOCK_EX
#ifdef __WIN__
||
type
==
RW_LOCK_WAIT_EX
#endif
||
type
==
RW_LOCK_SHARED
)
{
fputs
(
type
==
RW_LOCK_
EX
?
"X-lock on"
:
"S
-lock on"
,
file
);
fputs
(
type
==
RW_LOCK_
SHARED
?
"S-lock on"
:
"X
-lock on"
,
file
);
rwlock
=
cell
->
old_wait_rw_lock
;
...
...
@@ -504,22 +500,24 @@ sync_array_cell_print(
" RW-latch at %p created in file %s line %lu
\n
"
,
(
void
*
)
rwlock
,
rwlock
->
cfile_name
,
(
ulong
)
rwlock
->
cline
);
if
(
rwlock
->
writer
!=
RW_LOCK_NOT_LOCKED
)
{
writer
=
rw_lock_get_writer
(
rwlock
);
if
(
writer
!=
RW_LOCK_NOT_LOCKED
)
{
fprintf
(
file
,
"a writer (thread id %lu) has"
" reserved it in mode %s"
,
(
ulong
)
os_thread_pf
(
rwlock
->
writer_thread
),
rwlock
->
writer
==
RW_LOCK_EX
writer
==
RW_LOCK_EX
?
" exclusive
\n
"
:
" wait exclusive
\n
"
);
}
fprintf
(
file
,
"number of readers %lu, waiters flag %lu
\n
"
"number of readers %lu,
s_waiters flag %lu, x_
waiters flag %lu
\n
"
"Last time read locked in file %s line %lu
\n
"
"Last time write locked in file %s line %lu
\n
"
,
(
ulong
)
rwlock
->
reader_count
,
(
ulong
)
rwlock
->
waiters
,
(
ulong
)
rwlock
->
s_waiters
,
(
ulong
)
(
rwlock
->
x_waiters
||
rwlock
->
wait_ex_waiters
),
rwlock
->
last_s_file_name
,
(
ulong
)
rwlock
->
last_s_line
,
rwlock
->
last_x_file_name
,
...
...
@@ -844,11 +842,15 @@ sync_array_object_signalled(
/*========================*/
sync_array_t
*
arr
)
/* in: wait array */
{
#ifdef HAVE_GCC_ATOMIC_BUILTINS
__sync_fetch_and_add
(
&
(
arr
->
sg_count
),
1
);
#else
sync_array_enter
(
arr
);
arr
->
sg_count
++
;
sync_array_exit
(
arr
);
#endif
}
/**************************************************************************
...
...
@@ -889,19 +891,23 @@ sync_arr_wake_threads_if_sema_free(void)
mutex
=
cell
->
wait_object
;
os_event_set
(
mutex
->
event
);
#ifdef __WIN__
}
else
if
(
cell
->
request_type
==
RW_LOCK_WAIT_EX
)
{
rw_lock_t
*
lock
;
lock
=
cell
->
wait_object
;
os_event_set
(
lock
->
wait_ex_event
);
#endif
}
else
if
(
cell
->
request_type
==
RW_LOCK_SHARED
)
{
rw_lock_t
*
lock
;
lock
=
cell
->
wait_object
;
os_event_set
(
lock
->
s_event
);
}
else
{
rw_lock_t
*
lock
;
lock
=
cell
->
wait_object
;
os_event_set
(
lock
->
event
);
os_event_set
(
lock
->
x_
event
);
}
}
}
...
...
sync/sync0rw.c
View file @
8f3b5ebd
...
...
@@ -119,6 +119,7 @@ rw_lock_create_func(
/* If this is the very first time a synchronization object is
created, then the following call initializes the sync system. */
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_create
(
rw_lock_get_mutex
(
lock
),
SYNC_NO_ORDER_CHECK
);
lock
->
mutex
.
cfile_name
=
cfile_name
;
...
...
@@ -128,8 +129,14 @@ rw_lock_create_func(
lock
->
mutex
.
cmutex_name
=
cmutex_name
;
lock
->
mutex
.
mutex_type
=
1
;
#endif
/* UNIV_DEBUG && !UNIV_HOTBACKUP */
#endif
/* !HAVE_GCC_ATOMIC_BUILTINS */
rw_lock_set_waiters
(
lock
,
0
);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
lock
->
lock_word
=
RW_LOCK_BIAS
;
#endif
rw_lock_set_s_waiters
(
lock
,
0
);
rw_lock_set_x_waiters
(
lock
,
0
);
rw_lock_set_wx_waiters
(
lock
,
0
);
rw_lock_set_writer
(
lock
,
RW_LOCK_NOT_LOCKED
);
lock
->
writer_count
=
0
;
rw_lock_set_reader_count
(
lock
,
0
);
...
...
@@ -151,11 +158,9 @@ rw_lock_create_func(
lock
->
last_x_file_name
=
"not yet reserved"
;
lock
->
last_s_line
=
0
;
lock
->
last_x_line
=
0
;
lock
->
event
=
os_event_create
(
NULL
);
#ifdef __WIN__
lock
->
s_event
=
os_event_create
(
NULL
);
lock
->
x_event
=
os_event_create
(
NULL
);
lock
->
wait_ex_event
=
os_event_create
(
NULL
);
#endif
mutex_enter
(
&
rw_lock_list_mutex
);
...
...
@@ -181,19 +186,21 @@ rw_lock_free(
{
ut_ad
(
rw_lock_validate
(
lock
));
ut_a
(
rw_lock_get_writer
(
lock
)
==
RW_LOCK_NOT_LOCKED
);
ut_a
(
rw_lock_get_waiters
(
lock
)
==
0
);
ut_a
(
rw_lock_get_s_waiters
(
lock
)
==
0
);
ut_a
(
rw_lock_get_x_waiters
(
lock
)
==
0
);
ut_a
(
rw_lock_get_wx_waiters
(
lock
)
==
0
);
ut_a
(
rw_lock_get_reader_count
(
lock
)
==
0
);
lock
->
magic_n
=
0
;
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_free
(
rw_lock_get_mutex
(
lock
));
#endif
mutex_enter
(
&
rw_lock_list_mutex
);
os_event_free
(
lock
->
event
);
#ifdef __WIN__
os_event_free
(
lock
->
s_event
);
os_event_free
(
lock
->
x_event
);
os_event_free
(
lock
->
wait_ex_event
);
#endif
if
(
UT_LIST_GET_PREV
(
list
,
lock
))
{
ut_a
(
UT_LIST_GET_PREV
(
list
,
lock
)
->
magic_n
==
RW_LOCK_MAGIC_N
);
...
...
@@ -211,6 +218,8 @@ rw_lock_free(
/**********************************************************************
Checks that the rw-lock has been initialized and that there are no
simultaneous shared and exclusive locks. */
/* MEMO: If HAVE_GCC_ATOMIC_BUILTINS, we should use this function statically. */
UNIV_INTERN
ibool
rw_lock_validate
(
...
...
@@ -219,7 +228,9 @@ rw_lock_validate(
{
ut_a
(
lock
);
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter
(
rw_lock_get_mutex
(
lock
));
#endif
ut_a
(
lock
->
magic_n
==
RW_LOCK_MAGIC_N
);
ut_a
((
rw_lock_get_reader_count
(
lock
)
==
0
)
...
...
@@ -227,11 +238,17 @@ rw_lock_validate(
ut_a
((
rw_lock_get_writer
(
lock
)
==
RW_LOCK_EX
)
||
(
rw_lock_get_writer
(
lock
)
==
RW_LOCK_WAIT_EX
)
||
(
rw_lock_get_writer
(
lock
)
==
RW_LOCK_NOT_LOCKED
));
ut_a
((
rw_lock_get_waiters
(
lock
)
==
0
)
||
(
rw_lock_get_waiters
(
lock
)
==
1
));
ut_a
((
rw_lock_get_s_waiters
(
lock
)
==
0
)
||
(
rw_lock_get_s_waiters
(
lock
)
==
1
));
ut_a
((
rw_lock_get_x_waiters
(
lock
)
==
0
)
||
(
rw_lock_get_x_waiters
(
lock
)
==
1
));
ut_a
((
rw_lock_get_wx_waiters
(
lock
)
==
0
)
||
(
rw_lock_get_wx_waiters
(
lock
)
==
1
));
ut_a
((
lock
->
writer
!=
RW_LOCK_EX
)
||
(
lock
->
writer_count
>
0
));
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
rw_lock_get_mutex
(
lock
));
#endif
return
(
TRUE
);
}
...
...
@@ -258,13 +275,14 @@ rw_lock_s_lock_spin(
ut_ad
(
rw_lock_validate
(
lock
));
lock_loop:
i
=
0
;
spin_loop:
rw_s_spin_wait_count
++
;
/* Spin waiting for the writer field to become free */
i
=
0
;
while
(
rw_lock_get_writer
(
lock
)
!=
RW_LOCK_NOT_LOCKED
&&
i
<
SYNC_SPIN_ROUNDS
)
{
while
(
i
<
SYNC_SPIN_ROUNDS
&&
rw_lock_get_writer
(
lock
)
!=
RW_LOCK_NOT_LOCKED
)
{
if
(
srv_spin_wait_delay
)
{
ut_delay
(
ut_rnd_interval
(
0
,
srv_spin_wait_delay
));
}
...
...
@@ -285,15 +303,27 @@ rw_lock_s_lock_spin(
lock
->
cfile_name
,
(
ulong
)
lock
->
cline
,
(
ulong
)
i
);
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter
(
rw_lock_get_mutex
(
lock
));
#endif
/* We try once again to obtain the lock */
if
(
TRUE
==
rw_lock_s_lock_low
(
lock
,
pass
,
file_name
,
line
))
{
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
rw_lock_get_mutex
(
lock
));
#endif
return
;
/* Success */
}
else
{
#ifdef HAVE_GCC_ATOMIC_BUILTINS
/* like sync0sync.c doing */
i
++
;
if
(
i
<
SYNC_SPIN_ROUNDS
)
{
goto
spin_loop
;
}
#endif
/* If we get here, locking did not succeed, we may
suspend the thread to wait in the wait array */
...
...
@@ -304,9 +334,19 @@ rw_lock_s_lock_spin(
file_name
,
line
,
&
index
);
rw_lock_set_waiters
(
lock
,
1
);
rw_lock_set_
s_
waiters
(
lock
,
1
);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
/* like sync0sync.c doing */
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
(
TRUE
==
rw_lock_s_lock_low
(
lock
,
pass
,
file_name
,
line
))
{
sync_array_free_cell
(
sync_primary_wait_array
,
index
);
return
;
/* Success */
}
}
#else
mutex_exit
(
rw_lock_get_mutex
(
lock
));
#endif
if
(
srv_print_latch_waits
)
{
fprintf
(
stderr
,
...
...
@@ -343,13 +383,19 @@ rw_lock_x_lock_move_ownership(
{
ut_ad
(
rw_lock_is_locked
(
lock
,
RW_LOCK_EX
));
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter
(
&
(
lock
->
mutex
));
#endif
lock
->
writer_thread
=
os_thread_get_curr_id
();
lock
->
pass
=
0
;
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
&
(
lock
->
mutex
));
#else
__sync_synchronize
();
#endif
}
/**********************************************************************
...
...
@@ -367,6 +413,89 @@ rw_lock_x_lock_low(
const
char
*
file_name
,
/* in: file name where lock requested */
ulint
line
)
/* in: line where requested */
{
#ifdef HAVE_GCC_ATOMIC_BUILTINS
os_thread_id_t
curr_thread
=
os_thread_get_curr_id
();
/* try to lock writer */
if
(
__sync_lock_test_and_set
(
&
(
lock
->
writer
),
RW_LOCK_EX
)
==
RW_LOCK_NOT_LOCKED
)
{
/* success */
/* obtain RW_LOCK_WAIT_EX right */
lock
->
writer_thread
=
curr_thread
;
lock
->
pass
=
pass
;
lock
->
writer_is_wait_ex
=
TRUE
;
/* atomic operation may be safer about memory order. */
__sync_synchronize
();
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info
(
lock
,
pass
,
RW_LOCK_WAIT_EX
,
file_name
,
line
);
#endif
}
if
(
!
os_thread_eq
(
lock
->
writer_thread
,
curr_thread
))
{
return
(
RW_LOCK_NOT_LOCKED
);
}
switch
(
rw_lock_get_writer
(
lock
))
{
case
RW_LOCK_WAIT_EX
:
/* have right to try x-lock */
if
(
lock
->
lock_word
==
RW_LOCK_BIAS
)
{
/* try x-lock */
if
(
__sync_sub_and_fetch
(
&
(
lock
->
lock_word
),
RW_LOCK_BIAS
)
==
0
)
{
/* success */
lock
->
pass
=
pass
;
lock
->
writer_is_wait_ex
=
FALSE
;
__sync_fetch_and_add
(
&
(
lock
->
writer_count
),
1
);
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info
(
lock
,
pass
,
RW_LOCK_WAIT_EX
);
rw_lock_add_debug_info
(
lock
,
pass
,
RW_LOCK_EX
,
file_name
,
line
);
#endif
lock
->
last_x_file_name
=
file_name
;
lock
->
last_x_line
=
line
;
/* Locking succeeded, we may return */
return
(
RW_LOCK_EX
);
}
else
{
/* fail */
__sync_fetch_and_add
(
&
(
lock
->
lock_word
),
RW_LOCK_BIAS
);
}
}
/* There are readers, we have to wait */
return
(
RW_LOCK_WAIT_EX
);
break
;
case
RW_LOCK_EX
:
/* already have x-lock */
if
((
lock
->
pass
==
0
)
&&
(
pass
==
0
))
{
__sync_fetch_and_add
(
&
(
lock
->
writer_count
),
1
);
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info
(
lock
,
pass
,
RW_LOCK_EX
,
file_name
,
line
);
#endif
lock
->
last_x_file_name
=
file_name
;
lock
->
last_x_line
=
line
;
/* Locking succeeded, we may return */
return
(
RW_LOCK_EX
);
}
return
(
RW_LOCK_NOT_LOCKED
);
break
;
default:
/* ??? */
return
(
RW_LOCK_NOT_LOCKED
);
}
#else
/* HAVE_GCC_ATOMIC_BUILTINS */
ut_ad
(
mutex_own
(
rw_lock_get_mutex
(
lock
)));
if
(
rw_lock_get_writer
(
lock
)
==
RW_LOCK_NOT_LOCKED
)
{
...
...
@@ -447,6 +576,7 @@ rw_lock_x_lock_low(
/* Locking succeeded, we may return */
return
(
RW_LOCK_EX
);
}
#endif
/* HAVE_GCC_ATOMIC_BUILTINS */
/* Locking did not succeed */
return
(
RW_LOCK_NOT_LOCKED
);
...
...
@@ -472,19 +602,33 @@ rw_lock_x_lock_func(
ulint
line
)
/* in: line where requested */
{
ulint
index
;
/* index of the reserved wait cell */
ulint
state
;
/* lock state acquired */
ulint
state
=
RW_LOCK_NOT_LOCKED
;
/* lock state acquired */
#ifdef HAVE_GCC_ATOMIC_BUILTINS
ulint
prev_state
=
RW_LOCK_NOT_LOCKED
;
#endif
ulint
i
;
/* spin round count */
ut_ad
(
rw_lock_validate
(
lock
));
lock_loop:
i
=
0
;
#ifdef HAVE_GCC_ATOMIC_BUILTINS
prev_state
=
state
;
#else
/* Acquire the mutex protecting the rw-lock fields */
mutex_enter_fast
(
&
(
lock
->
mutex
));
#endif
state
=
rw_lock_x_lock_low
(
lock
,
pass
,
file_name
,
line
);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if
(
state
!=
prev_state
)
i
=
0
;
/* if progress, reset counter. */
#else
mutex_exit
(
&
(
lock
->
mutex
));
#endif
spin_loop:
if
(
state
==
RW_LOCK_EX
)
{
return
;
/* Locking succeeded */
...
...
@@ -492,10 +636,9 @@ rw_lock_x_lock_func(
}
else
if
(
state
==
RW_LOCK_NOT_LOCKED
)
{
/* Spin waiting for the writer field to become free */
i
=
0
;
while
(
rw_lock_get_writer
(
lock
)
!=
RW_LOCK_NOT_LOCKED
&&
i
<
SYNC_SPIN_ROUNDS
)
{
while
(
i
<
SYNC_SPIN_ROUNDS
&&
rw_lock_get_writer
(
lock
)
!=
RW_LOCK_NOT_LOCKED
)
{
if
(
srv_spin_wait_delay
)
{
ut_delay
(
ut_rnd_interval
(
0
,
srv_spin_wait_delay
));
...
...
@@ -509,9 +652,12 @@ rw_lock_x_lock_func(
}
else
if
(
state
==
RW_LOCK_WAIT_EX
)
{
/* Spin waiting for the reader count field to become zero */
i
=
0
;
#ifdef HAVE_GCC_ATOMIC_BUILTINS
while
(
lock
->
lock_word
!=
RW_LOCK_BIAS
#else
while
(
rw_lock_get_reader_count
(
lock
)
!=
0
#endif
&&
i
<
SYNC_SPIN_ROUNDS
)
{
if
(
srv_spin_wait_delay
)
{
ut_delay
(
ut_rnd_interval
(
0
,
...
...
@@ -524,7 +670,6 @@ rw_lock_x_lock_func(
os_thread_yield
();
}
}
else
{
i
=
0
;
/* Eliminate a compiler warning */
ut_error
;
}
...
...
@@ -541,34 +686,69 @@ rw_lock_x_lock_func(
/* We try once again to obtain the lock. Acquire the mutex protecting
the rw-lock fields */
#ifdef HAVE_GCC_ATOMIC_BUILTINS
prev_state
=
state
;
#else
mutex_enter
(
rw_lock_get_mutex
(
lock
));
#endif
state
=
rw_lock_x_lock_low
(
lock
,
pass
,
file_name
,
line
);
#ifdef HAVE_GCC_ATOMIC_BUILTINS
if
(
state
!=
prev_state
)
i
=
0
;
/* if progress, reset counter. */
#endif
if
(
state
==
RW_LOCK_EX
)
{
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
rw_lock_get_mutex
(
lock
));
#endif
return
;
/* Locking succeeded */
}
#ifdef HAVE_GCC_ATOMIC_BUILTINS
/* like sync0sync.c doing */
i
++
;
if
(
i
<
SYNC_SPIN_ROUNDS
)
{
goto
spin_loop
;
}
#endif
rw_x_system_call_count
++
;
sync_array_reserve_cell
(
sync_primary_wait_array
,
lock
,
#ifdef __WIN__
/* On windows RW_LOCK_WAIT_EX signifies
that this thread should wait on the
special wait_ex_event. */
(
state
==
RW_LOCK_WAIT_EX
)
?
RW_LOCK_WAIT_EX
:
#endif
RW_LOCK_EX
,
file_name
,
line
,
&
index
);
rw_lock_set_waiters
(
lock
,
1
);
if
(
state
==
RW_LOCK_WAIT_EX
)
{
rw_lock_set_wx_waiters
(
lock
,
1
);
}
else
{
rw_lock_set_x_waiters
(
lock
,
1
);
}
#ifdef HAVE_GCC_ATOMIC_BUILTINS
/* like sync0sync.c doing */
for
(
i
=
0
;
i
<
4
;
i
++
)
{
prev_state
=
state
;
state
=
rw_lock_x_lock_low
(
lock
,
pass
,
file_name
,
line
);
if
(
state
==
RW_LOCK_EX
)
{
sync_array_free_cell
(
sync_primary_wait_array
,
index
);
return
;
/* Locking succeeded */
}
if
(
state
!=
prev_state
)
{
/* retry! */
sync_array_free_cell
(
sync_primary_wait_array
,
index
);
goto
lock_loop
;
}
}
#else
mutex_exit
(
rw_lock_get_mutex
(
lock
));
#endif
if
(
srv_print_latch_waits
)
{
fprintf
(
stderr
,
...
...
@@ -730,7 +910,9 @@ rw_lock_own(
ut_ad
(
lock
);
ut_ad
(
rw_lock_validate
(
lock
));
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter
(
&
(
lock
->
mutex
));
#endif
info
=
UT_LIST_GET_FIRST
(
lock
->
debug_list
);
...
...
@@ -740,7 +922,9 @@ rw_lock_own(
&&
(
info
->
pass
==
0
)
&&
(
info
->
lock_type
==
lock_type
))
{
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
&
(
lock
->
mutex
));
#endif
/* Found! */
return
(
TRUE
);
...
...
@@ -748,7 +932,9 @@ rw_lock_own(
info
=
UT_LIST_GET_NEXT
(
list
,
info
);
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
&
(
lock
->
mutex
));
#endif
return
(
FALSE
);
}
...
...
@@ -770,21 +956,25 @@ rw_lock_is_locked(
ut_ad
(
lock
);
ut_ad
(
rw_lock_validate
(
lock
));
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter
(
&
(
lock
->
mutex
));
#endif
if
(
lock_type
==
RW_LOCK_SHARED
)
{
if
(
lock
->
reader_count
>
0
)
{
ret
=
TRUE
;
}
}
else
if
(
lock_type
==
RW_LOCK_EX
)
{
if
(
lock
->
writer
==
RW_LOCK_EX
)
{
if
(
rw_lock_get_writer
(
lock
)
==
RW_LOCK_EX
)
{
ret
=
TRUE
;
}
}
else
{
ut_error
;
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
&
(
lock
->
mutex
));
#endif
return
(
ret
);
}
...
...
@@ -814,16 +1004,26 @@ rw_lock_list_print_info(
count
++
;
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter
(
&
(
lock
->
mutex
));
#endif
if
((
rw_lock_get_writer
(
lock
)
!=
RW_LOCK_NOT_LOCKED
)
||
(
rw_lock_get_reader_count
(
lock
)
!=
0
)
||
(
rw_lock_get_waiters
(
lock
)
!=
0
))
{
||
(
rw_lock_get_s_waiters
(
lock
)
!=
0
)
||
(
rw_lock_get_x_waiters
(
lock
)
!=
0
)
||
(
rw_lock_get_wx_waiters
(
lock
)
!=
0
))
{
fprintf
(
file
,
"RW-LOCK: %p "
,
(
void
*
)
lock
);
if
(
rw_lock_get_waiters
(
lock
))
{
fputs
(
" Waiters for the lock exist
\n
"
,
file
);
if
(
rw_lock_get_s_waiters
(
lock
))
{
fputs
(
" s_waiters for the lock exist,"
,
file
);
}
if
(
rw_lock_get_x_waiters
(
lock
))
{
fputs
(
" x_waiters for the lock exist
\n
"
,
file
);
}
if
(
rw_lock_get_wx_waiters
(
lock
))
{
fputs
(
" wait_ex_waiters for the lock exist
\n
"
,
file
);
}
else
{
putc
(
'\n'
,
file
);
}
...
...
@@ -835,7 +1035,9 @@ rw_lock_list_print_info(
}
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
&
(
lock
->
mutex
));
#endif
lock
=
UT_LIST_GET_NEXT
(
list
,
lock
);
}
...
...
@@ -860,10 +1062,18 @@ rw_lock_print(
if
((
rw_lock_get_writer
(
lock
)
!=
RW_LOCK_NOT_LOCKED
)
||
(
rw_lock_get_reader_count
(
lock
)
!=
0
)
||
(
rw_lock_get_waiters
(
lock
)
!=
0
))
{
||
(
rw_lock_get_s_waiters
(
lock
)
!=
0
)
||
(
rw_lock_get_x_waiters
(
lock
)
!=
0
)
||
(
rw_lock_get_wx_waiters
(
lock
)
!=
0
))
{
if
(
rw_lock_get_waiters
(
lock
))
{
fputs
(
" Waiters for the lock exist
\n
"
,
stderr
);
if
(
rw_lock_get_s_waiters
(
lock
))
{
fputs
(
" s_waiters for the lock exist,"
,
stderr
);
}
if
(
rw_lock_get_x_waiters
(
lock
))
{
fputs
(
" x_waiters for the lock exist
\n
"
,
stderr
);
}
if
(
rw_lock_get_wx_waiters
(
lock
))
{
fputs
(
" wait_ex_waiters for the lock exist
\n
"
,
stderr
);
}
else
{
putc
(
'\n'
,
stderr
);
}
...
...
@@ -922,14 +1132,18 @@ rw_lock_n_locked(void)
lock
=
UT_LIST_GET_FIRST
(
rw_lock_list
);
while
(
lock
!=
NULL
)
{
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_enter
(
rw_lock_get_mutex
(
lock
));
#endif
if
((
rw_lock_get_writer
(
lock
)
!=
RW_LOCK_NOT_LOCKED
)
||
(
rw_lock_get_reader_count
(
lock
)
!=
0
))
{
count
++
;
}
#ifndef HAVE_GCC_ATOMIC_BUILTINS
mutex_exit
(
rw_lock_get_mutex
(
lock
));
#endif
lock
=
UT_LIST_GET_NEXT
(
list
,
lock
);
}
...
...
thr/thr0loc.c
View file @
8f3b5ebd
...
...
@@ -32,6 +32,7 @@ static mutex_t thr_local_mutex;
/* The hash table. The module is not yet initialized when it is NULL. */
static
hash_table_t
*
thr_local_hash
=
NULL
;
ulint
thr_local_hash_n_nodes
=
0
;
/* The private data for each thread should be put to
the structure below and the accessor functions written
...
...
@@ -177,6 +178,7 @@ thr_local_create(void)
os_thread_pf
(
os_thread_get_curr_id
()),
local
);
thr_local_hash_n_nodes
++
;
mutex_exit
(
&
thr_local_mutex
);
}
...
...
@@ -204,6 +206,7 @@ thr_local_free(
HASH_DELETE
(
thr_local_t
,
hash
,
thr_local_hash
,
os_thread_pf
(
id
),
local
);
thr_local_hash_n_nodes
--
;
mutex_exit
(
&
thr_local_mutex
);
...
...
@@ -226,3 +229,29 @@ thr_local_init(void)
mutex_create
(
&
thr_local_mutex
,
SYNC_THR_LOCAL
);
}
/*************************************************************************
Return local hash table informations. */
ulint
thr_local_hash_cells
(
void
)
/*======================*/
{
if
(
thr_local_hash
)
{
return
(
thr_local_hash
->
n_cells
);
}
else
{
return
0
;
}
}
ulint
thr_local_hash_nodes
(
void
)
/*======================*/
{
if
(
thr_local_hash
)
{
return
(
thr_local_hash_n_nodes
*
(
sizeof
(
thr_local_t
)
+
MEM_BLOCK_HEADER_SIZE
));
}
else
{
return
0
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment