summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rw-r--r--mysys/CMakeLists.txt9
-rw-r--r--mysys/file_logger.c2
-rw-r--r--mysys/get_password.c1
-rw-r--r--mysys/guess_malloc_library.c65
-rw-r--r--mysys/hash.c2
-rw-r--r--mysys/lf_alloc-pin.c6
-rw-r--r--mysys/lf_hash.c10
-rw-r--r--mysys/ma_dyncol.c6
-rw-r--r--mysys/mf_cache.c37
-rw-r--r--mysys/mf_iocache.c13
-rw-r--r--mysys/mf_iocache2.c27
-rw-r--r--mysys/mf_keycache.c301
-rw-r--r--mysys/mf_tempfile.c133
-rw-r--r--mysys/my_access.c2
-rw-r--r--mysys/my_alloc.c46
-rw-r--r--mysys/my_atomic.c67
-rw-r--r--mysys/my_atomic_writes.c2
-rw-r--r--mysys/my_basename.c1
-rw-r--r--mysys/my_bitmap.c5
-rw-r--r--mysys/my_compare.c4
-rw-r--r--mysys/my_conio.c4
-rw-r--r--mysys/my_context.c2
-rw-r--r--mysys/my_default.c6
-rw-r--r--mysys/my_delete.c4
-rw-r--r--mysys/my_fopen.c100
-rw-r--r--mysys/my_getopt.c96
-rw-r--r--mysys/my_getsystime.c43
-rw-r--r--mysys/my_init.c38
-rw-r--r--mysys/my_lib.c10
-rw-r--r--mysys/my_likely.c173
-rw-r--r--mysys/my_lock.c1
-rw-r--r--mysys/my_malloc.c9
-rw-r--r--mysys/my_open.c49
-rw-r--r--mysys/my_pthread.c1
-rw-r--r--mysys/my_read.c40
-rw-r--r--mysys/my_sync.c3
-rw-r--r--mysys/my_thr_init.c4
-rw-r--r--mysys/my_wincond.c5
-rw-r--r--mysys/my_windac.c21
-rw-r--r--mysys/my_winerr.c2
-rw-r--r--mysys/my_winfile.c4
-rw-r--r--mysys/my_winthread.c4
-rw-r--r--mysys/mysys_priv.h4
-rw-r--r--mysys/psi_noop.c7
-rw-r--r--mysys/ptr_cmp.c36
-rw-r--r--mysys/safemalloc.c10
-rw-r--r--mysys/stacktrace.c28
-rw-r--r--mysys/string.c6
-rw-r--r--mysys/thr_alarm.c17
-rw-r--r--mysys/thr_lock.c47
-rw-r--r--mysys/thr_mutex.c11
-rw-r--r--mysys/tree.c68
-rw-r--r--mysys/waiting_threads.c3
-rw-r--r--mysys/wqueue.c1
54 files changed, 913 insertions, 683 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 26dbd953324..93fca192b3a 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -36,13 +36,14 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c
string.c thr_alarm.c thr_lock.c thr_mutex.c
thr_rwlock.c thr_timer.c
tree.c typelib.c base64.c my_memmem.c
- my_getpagesize.c
+ my_getpagesize.c
+ guess_malloc_library.c
lf_alloc-pin.c lf_dynarray.c lf_hash.c
safemalloc.c my_new.cc
- my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
+ my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c
my_rdtsc.c my_context.c psi_noop.c
- my_atomic_writes.c
+ my_atomic_writes.c my_likely.c
file_logger.c my_dlerror.c)
IF (WIN32)
@@ -73,7 +74,7 @@ ENDIF()
ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES})
TARGET_LINK_LIBRARIES(mysys dbug strings mysys_ssl ${ZLIB_LIBRARY}
- ${LIBNSL} ${LIBM} ${LIBRT} ${LIBDL} ${LIBSOCKET} ${LIBEXECINFO} ${CRC32_VPMSUM_LIBRARY})
+ ${LIBNSL} ${LIBM} ${LIBRT} ${LIBDL} ${LIBSOCKET} ${LIBEXECINFO} ${CRC32_LIBRARY})
DTRACE_INSTRUMENT(mysys)
IF(HAVE_BFD_H)
diff --git a/mysys/file_logger.c b/mysys/file_logger.c
index 35a077c4391..3565397c79a 100644
--- a/mysys/file_logger.c
+++ b/mysys/file_logger.c
@@ -227,7 +227,7 @@ int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
void logger_init_mutexes()
{
#ifdef HAVE_PSI_INTERFACE
- if (PSI_server)
+ if (unlikely(PSI_server))
PSI_server->register_mutex("sql_logger", mutex_list, 1);
#endif
}
diff --git a/mysys/get_password.c b/mysys/get_password.c
index 8a507d94e9b..2b63a686d07 100644
--- a/mysys/get_password.c
+++ b/mysys/get_password.c
@@ -64,7 +64,6 @@ char *get_tty_password(const char *opt_message)
{
char to[80];
char *pos=to,*end=to+sizeof(to)-1;
- int i=0;
DBUG_ENTER("get_tty_password");
_cputs(opt_message ? opt_message : "Enter password: ");
for (;;)
diff --git a/mysys/guess_malloc_library.c b/mysys/guess_malloc_library.c
new file mode 100644
index 00000000000..ed86ae0679c
--- /dev/null
+++ b/mysys/guess_malloc_library.c
@@ -0,0 +1,65 @@
+/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2012, 2017, MariaDB Corporation.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/* guess_malloc_library() deduces, to the best of its ability,
+ the currently used malloc library and its version */
+
+#include <stddef.h>
+#include "my_global.h"
+#include <m_string.h>
+
+typedef const char* (*tc_version_type)(int*, int*, const char**);
+typedef int (*mallctl_type)(const char*, void*, size_t*, void*, size_t);
+
+char *guess_malloc_library()
+{
+ tc_version_type tc_version_func;
+ mallctl_type mallctl_func;
+#ifndef HAVE_DLOPEN
+ return (char*) MALLOC_LIBRARY;
+#else
+ static char buf[128];
+
+ if (strcmp(MALLOC_LIBRARY, "system") != 0)
+ {
+ return (char*) MALLOC_LIBRARY;
+ }
+
+ /* tcmalloc */
+ tc_version_func= (tc_version_type) dlsym(RTLD_DEFAULT, "tc_version");
+ if (tc_version_func)
+ {
+ int major, minor;
+ const char* ver_str = tc_version_func(&major, &minor, NULL);
+ strxnmov(buf, sizeof(buf)-1, "tcmalloc ", ver_str, NULL);
+ return buf;
+ }
+
+ /* jemalloc */
+ mallctl_func= (mallctl_type) dlsym(RTLD_DEFAULT, "mallctl");
+ if (mallctl_func)
+ {
+ char *ver;
+ size_t len = sizeof(ver);
+ mallctl_func("version", &ver, &len, NULL, 0);
+ strxnmov(buf, sizeof(buf)-1, "jemalloc ", ver, NULL);
+ return buf;
+ }
+
+ return (char*) MALLOC_LIBRARY;
+#endif
+}
+
diff --git a/mysys/hash.c b/mysys/hash.c
index fd26a4e1881..d89f175c161 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -380,7 +380,7 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key,
my_bool my_hash_insert(HASH *info, const uchar *record)
{
int flag;
- uint idx, halfbuff, first_index;
+ size_t idx, halfbuff, first_index;
size_t length;
my_hash_value_type current_hash_nr, UNINIT_VAR(rec_hash_nr),
UNINIT_VAR(rec2_hash_nr);
diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c
index bf2b8a12846..4e4917962ab 100644
--- a/mysys/lf_alloc-pin.c
+++ b/mysys/lf_alloc-pin.c
@@ -161,7 +161,7 @@ LF_PINS *lf_pinbox_get_pins(LF_PINBOX *pinbox)
pinstack_top_ver is 32 bits; 16 low bits are the index in the
array, to the first element of the list. 16 high bits are a version
(every time the 16 low bits are updated, the 16 high bits are
- incremented). Versioniong prevents the ABA problem.
+ incremented). Versioning prevents the ABA problem.
*/
top_ver= pinbox->pinstack_top_ver;
do
@@ -430,7 +430,7 @@ static void alloc_free(uchar *first,
{
anext_node(last)= tmp.node;
} while (!my_atomic_casptr((void **)(char *)&allocator->top,
- (void **)&tmp.ptr, first) && LF_BACKOFF);
+ (void **)&tmp.ptr, first) && LF_BACKOFF());
}
/*
@@ -501,7 +501,7 @@ void *lf_alloc_new(LF_PINS *pins)
{
node= allocator->top;
lf_pin(pins, 0, node);
- } while (node != allocator->top && LF_BACKOFF);
+ } while (node != allocator->top && LF_BACKOFF());
if (!node)
{
node= (void *)my_malloc(allocator->element_size, MYF(MY_WME));
diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c
index 64e5c5e3e93..60dcfd8bed4 100644
--- a/mysys/lf_hash.c
+++ b/mysys/lf_hash.c
@@ -86,12 +86,12 @@ typedef struct {
1 - error (callbck returned 1)
*/
static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
- const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins,
+ const uchar *key, size_t keylen, CURSOR *cursor, LF_PINS *pins,
my_hash_walk_action callback)
{
uint32 cur_hashnr;
const uchar *cur_key;
- uint cur_keylen;
+ size_t cur_keylen;
intptr link;
DBUG_ASSERT(!cs || !callback); /* should not be set both */
@@ -103,7 +103,7 @@ retry:
cursor->curr= (LF_SLIST *)(*cursor->prev);
lf_pin(pins, 1, cursor->curr);
} while (my_atomic_loadptr((void**)cursor->prev) != cursor->curr &&
- LF_BACKOFF);
+ LF_BACKOFF());
for (;;)
{
if (unlikely(!cursor->curr))
@@ -117,7 +117,7 @@ retry:
link= cursor->curr->link;
cursor->next= PTR(link);
lf_pin(pins, 0, cursor->next);
- } while (link != cursor->curr->link && LF_BACKOFF);
+ } while (link != cursor->curr->link && LF_BACKOFF());
if (!DELETED(link))
{
@@ -145,7 +145,7 @@ retry:
and remove this deleted node
*/
if (my_atomic_casptr((void **) cursor->prev,
- (void **) &cursor->curr, cursor->next) && LF_BACKOFF)
+ (void **) &cursor->curr, cursor->next) && LF_BACKOFF())
lf_alloc_free(pins, cursor->curr);
else
goto retry;
diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c
index fb163899a76..0085c375aa1 100644
--- a/mysys/ma_dyncol.c
+++ b/mysys/ma_dyncol.c
@@ -3822,11 +3822,11 @@ static
my_bool dynstr_append_json_quoted(DYNAMIC_STRING *str,
const char *append, size_t len)
{
- uint additional= ((str->alloc_increment && str->alloc_increment > 6) ?
+ size_t additional= ((str->alloc_increment && str->alloc_increment > 6) ?
str->alloc_increment :
10);
- uint lim= additional;
- uint i;
+ size_t lim= additional;
+ size_t i;
if (dynstr_realloc(str, len + additional + 2))
return TRUE;
str->str[str->length++]= '"';
diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c
index a3426889a82..478900ddb2a 100644
--- a/mysys/mf_cache.c
+++ b/mysys/mf_cache.c
@@ -21,36 +21,6 @@
#include "mysys_err.h"
/**
- Remove an open tempfile so that it doesn't survive if we crash
-
- If the operating system doesn't support this, just remember
- the file name for later removal
-*/
-
-static my_bool cache_remove_open_tmp(IO_CACHE *cache __attribute__((unused)),
- const char *name)
-{
-#if O_TEMPORARY == 0
-#if !defined(CANT_DELETE_OPEN_FILES)
- /* The following should always succeed */
- (void) my_delete(name,MYF(MY_WME | ME_NOINPUT));
-#else
- int length;
- if (!(cache->file_name=
- (char*) my_malloc((length=strlen(name)+1),MYF(MY_WME))))
- {
- my_close(cache->file,MYF(0));
- cache->file = -1;
- errno=my_errno=ENOMEM;
- return 1;
- }
- memcpy(cache->file_name,name,length);
-#endif
-#endif /* O_TEMPORARY == 0 */
- return 0;
-}
-
-/**
Open tempfile cached by IO_CACHE
Should be used when no seeks are done (only reinit_io_buff)
@@ -88,14 +58,11 @@ my_bool real_open_cached_file(IO_CACHE *cache)
char name_buff[FN_REFLEN];
int error=1;
DBUG_ENTER("real_open_cached_file");
- if ((cache->file=create_temp_file(name_buff, cache->dir,
+ if ((cache->file= create_temp_file(name_buff, cache->dir,
cache->prefix[0] ? cache->prefix : 0,
- (O_RDWR | O_BINARY | O_TRUNC |
- O_TEMPORARY | O_SHORT_LIVED),
- MYF(MY_WME))) >= 0)
+ O_BINARY, MYF(MY_WME | MY_TEMPORARY))) >= 0)
{
error=0;
- cache_remove_open_tmp(cache, name_buff);
}
DBUG_RETURN(error);
}
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index aea41886f05..d63547e0936 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -115,6 +115,7 @@ init_functions(IO_CACHE* info)
DBUG_ASSERT(!(info->myflags & MY_ENCRYPT));
info->read_function = info->share ? _my_b_cache_read_r : _my_b_cache_read;
info->write_function = info->share ? _my_b_cache_write_r : _my_b_cache_write;
+ info->myflags&= ~MY_FULL_IO;
break;
case TYPE_NOT_SET:
DBUG_ASSERT(0);
@@ -455,6 +456,8 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
{
info->read_end=info->write_pos;
info->end_of_file=my_b_tell(info);
+ /* Ensure we will read all data */
+ info->myflags|= MY_FULL_IO;
/*
Trigger a new seek only if we have a valid
file handle.
@@ -469,6 +472,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
info->seek_not_done=1;
}
info->end_of_file = ~(my_off_t) 0;
+ info->myflags&= ~MY_FULL_IO;
}
pos=info->request_pos+(seek_offset-info->pos_in_file);
if (type == WRITE_CACHE)
@@ -553,7 +557,7 @@ int _my_b_read(IO_CACHE *info, uchar *Buffer, size_t Count)
}
res= info->read_function(info, Buffer, Count);
if (res && info->error >= 0)
- info->error+= left_length; /* update number or read bytes */
+ info->error+= (int)left_length; /* update number or read bytes */
return res;
}
@@ -1917,13 +1921,12 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
{
if (append_cache)
{
-
if (mysql_file_write(info->file, info->write_buffer, length,
info->myflags | MY_NABP))
+ {
info->error= -1;
- else
- info->error= 0;
-
+ DBUG_RETURN(-1);
+ }
info->end_of_file+= info->write_pos - info->append_read_pos;
info->append_read_pos= info->write_buffer;
DBUG_ASSERT(info->end_of_file == mysql_file_tell(info->file, MYF(0)));
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 2499094037d..ef163ee24d3 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -249,18 +249,16 @@ my_off_t my_b_filelength(IO_CACHE *info)
}
-size_t
+my_bool
my_b_write_backtick_quote(IO_CACHE *info, const char *str, size_t len)
{
const uchar *start;
const uchar *p= (const uchar *)str;
const uchar *end= p + len;
size_t count;
- size_t total= 0;
if (my_b_write(info, (uchar *)"`", 1))
- return (size_t)-1;
- ++total;
+ return 1;
for (;;)
{
start= p;
@@ -268,35 +266,32 @@ my_b_write_backtick_quote(IO_CACHE *info, const char *str, size_t len)
++p;
count= p - start;
if (count && my_b_write(info, start, count))
- return (size_t)-1;
- total+= count;
+ return 1;
if (p >= end)
break;
if (my_b_write(info, (uchar *)"``", 2))
- return (size_t)-1;
- total+= 2;
+ return 1;
++p;
}
- if (my_b_write(info, (uchar *)"`", 1))
- return (size_t)-1;
- ++total;
- return total;
+ return (my_b_write(info, (uchar *)"`", 1));
}
/*
Simple printf version. Supports '%s', '%d', '%u', "%ld" and "%lu"
- Used for logging in MySQL
- returns number of written character, or (size_t) -1 on error
+ Used for logging in MariaDB
+
+ @return 0 ok
+ 1 error
*/
-size_t my_b_printf(IO_CACHE *info, const char* fmt, ...)
+my_bool my_b_printf(IO_CACHE *info, const char* fmt, ...)
{
size_t result;
va_list args;
va_start(args,fmt);
result=my_b_vprintf(info, fmt, args);
va_end(args);
- return result;
+ return result == (size_t) -1;
}
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index f2dddc0bd7f..edf8cd3be8a 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -421,11 +421,12 @@ static int keycache_pthread_cond_signal(mysql_cond_t *cond);
#undef inline
#endif
#define inline /* disabled inline for easier debugging */
-static int fail_block(BLOCK_LINK *block);
static int fail_hlink(HASH_LINK *hlink);
static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache);
#endif
-
+#ifdef DBUG_ASSERT_EXISTS
+static int fail_block(BLOCK_LINK *block);
+#endif
static inline uint next_power(uint value)
{
@@ -713,7 +714,7 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
res= 1;
goto finish;
}
- DBUG_ASSERT(cache_empty(keycache));
+ DBUG_SLOW_ASSERT(cache_empty(keycache));
/* End the flush phase. */
keycache->resize_in_flush= 0;
@@ -748,7 +749,6 @@ finish:
SYNOPSIS
finish_resize_simple_key_cache()
keycache pointer to the control block of a simple key cache
- acquire_lock <=> acquire the key cache lock at start
DESCRIPTION
This function performs finalizing actions for the operation of
@@ -756,8 +756,6 @@ finish:
keycache as a pointer to the control block structure of the type
SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag
in_resize in this structure to FALSE.
- The parameter acquire_lock says whether the key cache lock must be
- acquired at the start of the function.
RETURN VALUE
none
@@ -769,14 +767,10 @@ finish:
*/
static
-void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
- my_bool acquire_lock)
+void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache)
{
DBUG_ENTER("finish_resize_simple_key_cache");
- if (acquire_lock)
- keycache_pthread_mutex_lock(&keycache->cache_lock);
-
mysql_mutex_assert_owner(&keycache->cache_lock);
/*
@@ -848,8 +842,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
int blocks= 0;
DBUG_ENTER("resize_simple_key_cache");
- if (!keycache->key_cache_inited)
- DBUG_RETURN(blocks);
+ DBUG_ASSERT(keycache->key_cache_inited);
/*
Note that the cache_lock mutex and the resize_queue are left untouched.
@@ -865,7 +858,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
changed_blocks_hash_size);
finish:
- finish_resize_simple_key_cache(keycache, 0);
+ finish_resize_simple_key_cache(keycache);
DBUG_RETURN(blocks);
}
@@ -1088,7 +1081,7 @@ static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
thread->prev);
}
thread->next= NULL;
-#if !defined(DBUG_OFF)
+#ifdef DBUG_ASSERT_EXISTS
/*
This makes it easier to see it's not in a chain during debugging.
And some DBUG_ASSERT() rely on it.
@@ -1211,7 +1204,7 @@ static inline void unlink_changed(BLOCK_LINK *block)
block->next_changed->prev_changed= block->prev_changed;
*block->prev_changed= block->next_changed;
-#if !defined(DBUG_OFF)
+#ifdef DBUG_ASSERT_EXISTS
/*
This makes it easier to see it's not in a chain during debugging.
And some DBUG_ASSERT() rely on it.
@@ -1497,7 +1490,7 @@ static void unlink_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block)
keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
}
block->next_used= NULL;
-#if !defined(DBUG_OFF)
+#ifdef DBUG_ASSERT_EXISTS
/*
This makes it easier to see it's not in a chain during debugging.
And some DBUG_ASSERT() rely on it.
@@ -2436,7 +2429,7 @@ restart:
The call is thread safe because only the current
thread might change the block->hash_link value
*/
- error= my_pwrite(block->hash_link->file,
+ error= (int)my_pwrite(block->hash_link->file,
block->buffer + block->offset,
block->length - block->offset,
block->hash_link->diskpos + block->offset,
@@ -2610,12 +2603,11 @@ restart:
SYNOPSIS
- read_block()
+ read_block_{primary|secondary}()
keycache pointer to a key cache data structure
block block to which buffer the data is to be read
read_length size of data to be read
min_length at least so much data must be read
- primary <-> the current thread will read the data
RETURN VALUE
None
@@ -2629,90 +2621,100 @@ restart:
portion is less than read_length, but not less than min_length.
*/
-static void read_block(SIMPLE_KEY_CACHE_CB *keycache,
- BLOCK_LINK *block, uint read_length,
- uint min_length, my_bool primary)
+static void read_block_primary(SIMPLE_KEY_CACHE_CB *keycache,
+ BLOCK_LINK *block, uint read_length,
+ uint min_length)
{
size_t got_length;
/* On entry cache_lock is locked */
- KEYCACHE_THREAD_TRACE("read_block");
- if (primary)
- {
- /*
- This code is executed only by threads that submitted primary
- requests. Until block->status contains BLOCK_READ, all other
- request for the block become secondary requests. For a primary
- request the block must be properly initialized.
- */
- DBUG_ASSERT(((block->status & ~BLOCK_FOR_UPDATE) == BLOCK_IN_USE) ||
- fail_block(block));
- DBUG_ASSERT((block->length == 0) || fail_block(block));
- DBUG_ASSERT((block->offset == keycache->key_cache_block_size) ||
- fail_block(block));
- DBUG_ASSERT((block->requests > 0) || fail_block(block));
-
- KEYCACHE_DBUG_PRINT("read_block",
- ("page to be read by primary request"));
-
- keycache->global_cache_read++;
- /* Page is not in buffer yet, is to be read from disk */
- keycache_pthread_mutex_unlock(&keycache->cache_lock);
- /*
- Here other threads may step in and register as secondary readers.
- They will register in block->wqueue[COND_FOR_REQUESTED].
- */
- got_length= my_pread(block->hash_link->file, block->buffer,
- read_length, block->hash_link->diskpos, MYF(0));
- keycache_pthread_mutex_lock(&keycache->cache_lock);
- /*
- The block can now have been marked for free (in case of
- FLUSH_RELEASE). Otherwise the state must be unchanged.
- */
- DBUG_ASSERT(((block->status & ~(BLOCK_REASSIGNED |
- BLOCK_FOR_UPDATE)) == BLOCK_IN_USE) ||
- fail_block(block));
- DBUG_ASSERT((block->length == 0) || fail_block(block));
- DBUG_ASSERT((block->offset == keycache->key_cache_block_size) ||
- fail_block(block));
- DBUG_ASSERT((block->requests > 0) || fail_block(block));
-
- if (got_length < min_length)
- block->status|= BLOCK_ERROR;
- else
- {
- block->status|= BLOCK_READ;
- block->length= got_length;
- /*
- Do not set block->offset here. If this block is marked
- BLOCK_CHANGED later, we want to flush only the modified part. So
- only a writer may set block->offset down from
- keycache->key_cache_block_size.
- */
- }
- KEYCACHE_DBUG_PRINT("read_block",
- ("primary request: new page in cache"));
- /* Signal that all pending requests for this page now can be processed */
- release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]);
- }
+ KEYCACHE_THREAD_TRACE("read_block_primary");
+
+ /*
+ This code is executed only by threads that submitted primary
+ requests. Until block->status contains BLOCK_READ, all other
+ request for the block become secondary requests. For a primary
+ request the block must be properly initialized.
+ */
+ DBUG_ASSERT(((block->status & ~BLOCK_FOR_UPDATE) == BLOCK_IN_USE) ||
+ fail_block(block));
+ DBUG_ASSERT((block->length == 0) || fail_block(block));
+ DBUG_ASSERT((block->offset == keycache->key_cache_block_size) ||
+ fail_block(block));
+ DBUG_ASSERT((block->requests > 0) || fail_block(block));
+
+ KEYCACHE_DBUG_PRINT("read_block_primary",
+ ("page to be read by primary request"));
+
+ keycache->global_cache_read++;
+ /* Page is not in buffer yet, is to be read from disk */
+ keycache_pthread_mutex_unlock(&keycache->cache_lock);
+ /*
+ Here other threads may step in and register as secondary readers.
+ They will register in block->wqueue[COND_FOR_REQUESTED].
+ */
+ got_length= my_pread(block->hash_link->file, block->buffer,
+ read_length, block->hash_link->diskpos, MYF(0));
+ keycache_pthread_mutex_lock(&keycache->cache_lock);
+ /*
+ The block can now have been marked for free (in case of
+ FLUSH_RELEASE). Otherwise the state must be unchanged.
+ */
+ DBUG_ASSERT(((block->status & ~(BLOCK_REASSIGNED |
+ BLOCK_FOR_UPDATE)) == BLOCK_IN_USE) ||
+ fail_block(block));
+ DBUG_ASSERT((block->length == 0) || fail_block(block));
+ DBUG_ASSERT((block->offset == keycache->key_cache_block_size) ||
+ fail_block(block));
+ DBUG_ASSERT((block->requests > 0) || fail_block(block));
+
+ if (got_length < min_length)
+ block->status|= BLOCK_ERROR;
else
{
+ block->status|= BLOCK_READ;
+ block->length= (uint)got_length;
/*
- This code is executed only by threads that submitted secondary
- requests. At this point it could happen that the cache block is
- not yet assigned to the hash_link for the requested file block.
- But at awake from the wait this should be the case. Unfortunately
- we cannot assert this here because we do not know the hash_link
- for the requested file block nor the file and position. So we have
- to assert this in the caller.
+ Do not set block->offset here. If this block is marked
+ BLOCK_CHANGED later, we want to flush only the modified part. So
+ only a writer may set block->offset down from
+ keycache->key_cache_block_size.
*/
- KEYCACHE_DBUG_PRINT("read_block",
- ("secondary request waiting for new page to be read"));
- wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock);
- KEYCACHE_DBUG_PRINT("read_block",
- ("secondary request: new page in cache"));
}
+ KEYCACHE_DBUG_PRINT("read_block_primary",
+ ("primary request: new page in cache"));
+ /* Signal that all pending requests for this page now can be processed */
+ release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]);
+
+ DBUG_ASSERT(keycache->can_be_used);
+}
+
+
+static void read_block_secondary(SIMPLE_KEY_CACHE_CB *keycache,
+ BLOCK_LINK *block)
+{
+ KEYCACHE_THREAD_TRACE("read_block_secondary");
+
+ /*
+ This code is executed only by threads that submitted secondary
+ requests. At this point it could happen that the cache block is
+ not yet assigned to the hash_link for the requested file block.
+ But at awake from the wait this should be the case. Unfortunately
+ we cannot assert this here because we do not know the hash_link
+ for the requested file block nor the file and position. So we have
+ to assert this in the caller.
+ */
+ KEYCACHE_DBUG_PRINT("read_block_secondary",
+ ("secondary request waiting for new page to be read"));
+
+ wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock);
+
+ KEYCACHE_DBUG_PRINT("read_block_secondary",
+ ("secondary request: new page in cache"));
+
+ DBUG_ASSERT(keycache->can_be_used);
+ DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
}
@@ -2857,22 +2859,24 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
}
if (!(block->status & BLOCK_ERROR))
{
- if (page_st != PAGE_READ)
+ if (page_st == PAGE_TO_BE_READ)
+ {
+ MYSQL_KEYCACHE_READ_MISS();
+ read_block_primary(keycache, block,
+ keycache->key_cache_block_size, read_length+offset);
+ }
+ else if (page_st == PAGE_WAIT_TO_BE_READ)
{
MYSQL_KEYCACHE_READ_MISS();
/* The requested page is to be read into the block buffer */
- read_block(keycache, block,
- keycache->key_cache_block_size, read_length+offset,
- (my_bool)(page_st == PAGE_TO_BE_READ));
+ read_block_secondary(keycache, block);
+
/*
A secondary request must now have the block assigned to the
- requested file block. It does not hurt to check it for
- primary requests too.
+ requested file block.
*/
- DBUG_ASSERT(keycache->can_be_used);
DBUG_ASSERT(block->hash_link->file == file);
DBUG_ASSERT(block->hash_link->diskpos == filepos);
- DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
}
else if (block->length < read_length + offset)
{
@@ -3076,23 +3080,30 @@ int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
}
if (!(block->status & BLOCK_ERROR))
{
- if ((page_st == PAGE_WAIT_TO_BE_READ) ||
- ((page_st == PAGE_TO_BE_READ) &&
- (offset || (read_length < keycache->key_cache_block_size))))
+ if (page_st == PAGE_WAIT_TO_BE_READ)
{
/*
- Either
-
this is a secondary request for a block to be read into the
cache. The block is in eviction. It is not yet assigned to
the requested file block (It does not point to the right
hash_link). So we cannot call remove_reader() on the block.
And we cannot access the hash_link directly here. We need to
- wait until the assignment is complete. read_block() executes
- the correct wait when called with primary == FALSE.
-
- Or
+ wait until the assignment is complete. read_block_secondary()
+ executes the correct wait.
+ */
+ read_block_secondary(keycache, block);
+ /*
+ A secondary request must now have the block assigned to the
+ requested file block.
+ */
+ DBUG_ASSERT(block->hash_link->file == file);
+ DBUG_ASSERT(block->hash_link->diskpos == filepos);
+ }
+ else if (page_st == PAGE_TO_BE_READ &&
+ (offset || (read_length < keycache->key_cache_block_size)))
+ {
+ /*
this is a primary request for a block to be read into the
cache and the supplied data does not fill the whole block.
@@ -3107,17 +3118,8 @@ int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache,
Though reading again what the caller did read already is an
expensive operation, we need to do this for correctness.
*/
- read_block(keycache, block, keycache->key_cache_block_size,
- read_length + offset, (page_st == PAGE_TO_BE_READ));
- /*
- A secondary request must now have the block assigned to the
- requested file block. It does not hurt to check it for
- primary requests too.
- */
- DBUG_ASSERT(keycache->can_be_used);
- DBUG_ASSERT(block->hash_link->file == file);
- DBUG_ASSERT(block->hash_link->diskpos == filepos);
- DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
+ read_block_primary(keycache, block, keycache->key_cache_block_size,
+ read_length + offset);
}
else if (page_st == PAGE_TO_BE_READ)
{
@@ -3412,25 +3414,29 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache,
reading the file block. If the read completes after us, it
overwrites our new contents with the old contents. So we have to
wait for the other thread to complete the read of this block.
- read_block() takes care for the wait.
+ read_block_primary|secondary() takes care for the wait.
*/
- if (!(block->status & BLOCK_ERROR) &&
- ((page_st == PAGE_TO_BE_READ &&
- (offset || read_length < keycache->key_cache_block_size)) ||
- (page_st == PAGE_WAIT_TO_BE_READ)))
+ if (!(block->status & BLOCK_ERROR))
{
- read_block(keycache, block,
- offset + read_length >= keycache->key_cache_block_size?
- offset : keycache->key_cache_block_size,
- offset, (page_st == PAGE_TO_BE_READ));
- DBUG_ASSERT(keycache->can_be_used);
- DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
- /*
- Prevent block from flushing and from being selected for to be
- freed. This must be set when we release the cache_lock.
- Here we set it in case we could not set it above.
- */
- block->status|= BLOCK_FOR_UPDATE;
+ if (page_st == PAGE_TO_BE_READ &&
+ (offset || read_length < keycache->key_cache_block_size))
+ {
+ read_block_primary(keycache, block,
+ offset + read_length >= keycache->key_cache_block_size?
+ offset : keycache->key_cache_block_size,
+ offset);
+ /*
+ Prevent block from flushing and from being selected for to be
+ freed. This must be set when we release the cache_lock.
+ Here we set it in case we could not set it above.
+ */
+ block->status|= BLOCK_FOR_UPDATE;
+ }
+ else if (page_st == PAGE_WAIT_TO_BE_READ)
+ {
+ read_block_secondary(keycache, block);
+ block->status|= BLOCK_FOR_UPDATE;
+ }
}
/*
The block should always be assigned to the requested file block
@@ -3803,7 +3809,7 @@ static int flush_cached_blocks(SIMPLE_KEY_CACHE_CB *keycache,
(BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE));
block->status|= BLOCK_IN_FLUSHWRITE;
keycache_pthread_mutex_unlock(&keycache->cache_lock);
- error= my_pwrite(file, block->buffer + block->offset,
+ error= (int)my_pwrite(file, block->buffer + block->offset,
block->length - block->offset,
block->hash_link->diskpos + block->offset,
MYF(MY_NABP | MY_WAIT_IF_FULL));
@@ -4309,10 +4315,8 @@ restart:
} /* if (keycache->disk_blocks > 0 */
-#ifndef DBUG_OFF
DBUG_EXECUTE("check_keycache",
test_key_cache(keycache, "end of flush_key_blocks", 0););
-#endif
err:
if (cache != cache_buff)
my_free(cache);
@@ -4790,11 +4794,12 @@ void keycache_debug_log_close(void)
#endif /* defined(KEYCACHE_DEBUG) */
-#if !defined(DBUG_OFF)
+#ifdef DBUG_ASSERT_EXISTS
#define F_B_PRT(_f_, _v_) DBUG_PRINT("assert_fail", (_f_, _v_))
-static int fail_block(BLOCK_LINK *block)
+static int fail_block(BLOCK_LINK *block __attribute__((unused)))
{
+#ifndef DBUG_OFF
F_B_PRT("block->next_used: %p\n", block->next_used);
F_B_PRT("block->prev_used: %p\n", block->prev_used);
F_B_PRT("block->next_changed: %p\n", block->next_changed);
@@ -4805,10 +4810,13 @@ static int fail_block(BLOCK_LINK *block)
F_B_PRT("block->offset: %u\n", block->offset);
F_B_PRT("block->requests: %u\n", block->requests);
F_B_PRT("block->temperature: %u\n", block->temperature);
+#endif
return 0; /* Let the assert fail. */
}
+#endif
-static int fail_hlink(HASH_LINK *hlink)
+#ifndef DBUG_OFF
+static int fail_hlink(HASH_LINK *hlink __attribute__((unused)))
{
F_B_PRT("hlink->next: %p\n", hlink->next);
F_B_PRT("hlink->prev: %p\n", hlink->prev);
@@ -5276,7 +5284,8 @@ int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
{
for (i= 0; i < partitions; i++)
{
- finish_resize_simple_key_cache(keycache->partition_array[i], 1);
+ keycache_pthread_mutex_lock(&keycache->partition_array[i]->cache_lock);
+ finish_resize_simple_key_cache(keycache->partition_array[i]);
}
}
DBUG_RETURN(blocks);
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index 62b3e09747f..0ff7066fd95 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -22,7 +22,9 @@
#include <paths.h>
#endif
-
+#ifdef HAVE_MKOSTEMP
+#define mkstemp(A) mkostemp(A, O_CLOEXEC)
+#endif
/*
@brief
@@ -45,8 +47,11 @@
implementation, it's main use is to generate a file with
a name that does not already exist.
- When passing O_TEMPORARY flag in "mode" the file should
- be automatically deleted
+ When passing MY_TEMPORARY flag in MyFlags the file is automatically deleted
+
+ "mode" bits that always must be used for newly created files with
+ unique file names (O_EXCL | O_TRUNC | O_CREAT | O_RDWR) are added
+ automatically, and shouldn't be specified by the caller.
The implementation using mkstemp should be considered the
reference implementation when adding a new or modifying an
@@ -55,51 +60,55 @@
*/
File create_temp_file(char *to, const char *dir, const char *prefix,
- int mode __attribute__((unused)),
- myf MyFlags __attribute__((unused)))
+ int mode, myf MyFlags)
{
File file= -1;
-#ifdef __WIN__
- TCHAR path_buf[MAX_PATH-14];
-#endif
DBUG_ENTER("create_temp_file");
DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix));
-#if defined (__WIN__)
-
- /*
- Use GetTempPath to determine path for temporary files.
- This is because the documentation for GetTempFileName
- has the following to say about this parameter:
- "If this parameter is NULL, the function fails."
- */
- if (!dir)
- {
- if(GetTempPath(sizeof(path_buf), path_buf) > 0)
- dir = path_buf;
- }
- /*
- Use GetTempFileName to generate a unique filename, create
- the file and release it's handle
- - uses up to the first three letters from prefix
- */
- if (GetTempFileName(dir, prefix, 0, to) == 0)
- DBUG_RETURN(-1);
-
- DBUG_PRINT("info", ("name: %s", to));
-
- /*
- Open the file without the "open only if file doesn't already exist"
- since the file has already been created by GetTempFileName
- */
- if ((file= my_open(to, (mode & ~O_EXCL), MyFlags)) < 0)
+ DBUG_ASSERT((mode & (O_EXCL | O_TRUNC | O_CREAT | O_RDWR)) == 0);
+
+ mode|= O_TRUNC | O_CREAT | O_RDWR; /* not O_EXCL, see Windows code below */
+
+#ifdef _WIN32
{
- /* Open failed, remove the file created by GetTempFileName */
- int tmp= my_errno;
- (void) my_delete(to, MYF(0));
- my_errno= tmp;
+ TCHAR path_buf[MAX_PATH-14];
+ /*
+ Use GetTempPath to determine path for temporary files.
+ This is because the documentation for GetTempFileName
+ has the following to say about this parameter:
+ "If this parameter is NULL, the function fails."
+ */
+ if (!dir)
+ {
+ if(GetTempPath(sizeof(path_buf), path_buf) > 0)
+ dir = path_buf;
+ }
+ /*
+ Use GetTempFileName to generate a unique filename, create
+ the file and release it's handle
+ - uses up to the first three letters from prefix
+ */
+ if (GetTempFileName(dir, prefix, 0, to) == 0)
+ DBUG_RETURN(-1);
+
+ DBUG_PRINT("info", ("name: %s", to));
+
+ if (MyFlags & MY_TEMPORARY)
+ mode|= O_SHORT_LIVED | O_TEMPORARY;
+
+ /*
+ Open the file without O_EXCL flag
+ since the file has already been created by GetTempFileName
+ */
+ if ((file= my_open(to, mode, MyFlags)) < 0)
+ {
+ /* Open failed, remove the file created by GetTempFileName */
+ int tmp= my_errno;
+ (void) my_delete(to, MYF(0));
+ my_errno= tmp;
+ }
}
-
#elif defined(HAVE_MKSTEMP)
{
char prefix_buff[30];
@@ -119,8 +128,8 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
}
strmov(convert_dirname(to,dir,NullS),prefix_buff);
org_file=mkstemp(to);
- if (mode & O_TEMPORARY)
- (void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
+ if (org_file >= 0 && (MyFlags & MY_TEMPORARY))
+ (void) my_delete(to, MYF(MY_WME));
file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
EE_CANTCREATEFILE, MyFlags);
/* If we didn't manage to register the name, remove the temp file */
@@ -132,46 +141,10 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
my_errno=tmp;
}
}
-#elif defined(HAVE_TEMPNAM)
- {
- extern char **environ;
-
- char *res,**old_env,*temp_env[1];
- if (dir && !dir[0])
- { /* Change empty string to current dir */
- to[0]= FN_CURLIB;
- to[1]= 0;
- dir=to;
- }
-
- old_env= (char**) environ;
- if (dir)
- { /* Don't use TMPDIR if dir is given */
- environ=(const char**) temp_env;
- temp_env[0]=0;
- }
-
- if ((res=tempnam((char*) dir, (char*) prefix)))
- {
- strmake(to,res,FN_REFLEN-1);
- (*free)(res);
- file=my_create(to,0,
- (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW |
- O_TEMPORARY | O_SHORT_LIVED),
- MYF(MY_WME));
-
- }
- else
- {
- DBUG_PRINT("error",("Got error: %d from tempnam",errno));
- }
-
- environ=(const char**) old_env;
- }
#else
#error No implementation found for create_temp_file
#endif
if (file >= 0)
- thread_safe_increment(my_tmp_file_created,&THR_LOCK_open);
+ statistic_increment(my_tmp_file_created,&THR_LOCK_open);
DBUG_RETURN(file);
}
diff --git a/mysys/my_access.c b/mysys/my_access.c
index 75774240406..0f3263a79c3 100644
--- a/mysys/my_access.c
+++ b/mysys/my_access.c
@@ -38,7 +38,7 @@ int my_access(const char *path, int amode)
attributes = GetFileAttributes(path);
if (attributes == INVALID_FILE_ATTRIBUTES ||
- (attributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK))
+ ((attributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK)))
{
my_errno= errno= EACCES;
return -1;
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index 1b0ef857afa..7139466be17 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -34,6 +34,7 @@
SYNOPSIS
init_alloc_root()
mem_root - memory root to initialize
+ name - name of memroot (for debugging)
block_size - size of chunks (blocks) used for memory allocation
(It is external size of chunk i.e. it should include
memory required for internal structures, thus it
@@ -53,13 +54,13 @@
Because of this, we store in MY_THREAD_SPECIFIC as bit 1 in block_size
*/
-void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
+void init_alloc_root(MEM_ROOT *mem_root, const char *name, size_t block_size,
size_t pre_alloc_size __attribute__((unused)),
myf my_flags)
{
DBUG_ENTER("init_alloc_root");
- DBUG_PRINT("enter",("root: %p prealloc: %zu", mem_root,
- pre_alloc_size));
+ DBUG_PRINT("enter",("root: %p name: %s prealloc: %zu", mem_root,
+ name, pre_alloc_size));
mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
mem_root->min_malloc= 32;
@@ -70,6 +71,8 @@ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
mem_root->error_handler= 0;
mem_root->block_num= 4; /* We shift this with >>2 */
mem_root->first_block_usage= 0;
+ mem_root->total_alloc= 0;
+ mem_root->name= name;
#if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG))
if (pre_alloc_size)
@@ -79,6 +82,7 @@ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
MYF(my_flags))))
{
mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM));
+ mem_root->total_alloc= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM));
mem_root->free->left= pre_alloc_size;
mem_root->free->next= 0;
TRASH_MEM(mem_root->free);
@@ -137,6 +141,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
{
/* remove block from the list and free it */
*prev= mem->next;
+ mem_root->total_alloc-= mem->size;
my_free(mem);
}
else
@@ -148,9 +153,10 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
block_size)))))
{
mem->size= size;
+ mem_root->total_alloc+= size;
mem->left= pre_alloc_size;
mem->next= *prev;
- *prev= mem_root->pre_alloc= mem;
+ *prev= mem_root->pre_alloc= mem;
TRASH_MEM(mem);
}
else
@@ -172,7 +178,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
#if defined(HAVE_valgrind) && defined(EXTRA_DEBUG)
reg1 USED_MEM *next;
DBUG_ENTER("alloc_root");
- DBUG_PRINT("enter",("root: %p", mem_root));
+ DBUG_PRINT("enter",("root: %p name: %s", mem_root, mem_root->name));
DBUG_ASSERT(alloc_root_inited(mem_root));
@@ -194,8 +200,10 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
DBUG_RETURN((uchar*) 0); /* purecov: inspected */
}
next->next= mem_root->used;
+ next->left= 0;
next->size= length;
mem_root->used= next;
+ mem_root->total_alloc+= length;
DBUG_PRINT("exit",("ptr: %p", (((char*) next)+
ALIGN_SIZE(sizeof(USED_MEM)))));
DBUG_RETURN((uchar*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
@@ -205,7 +213,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
reg1 USED_MEM *next= 0;
reg2 USED_MEM **prev;
DBUG_ENTER("alloc_root");
- DBUG_PRINT("enter",("root: %p", mem_root));
+ DBUG_PRINT("enter",("root: %p name: %s", mem_root, mem_root->name));
DBUG_ASSERT(alloc_root_inited(mem_root));
DBUG_EXECUTE_IF("simulate_out_of_memory",
@@ -248,6 +256,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
DBUG_RETURN((void*) 0); /* purecov: inspected */
}
mem_root->block_num++;
+ mem_root->total_alloc+= get_size;
next->next= *prev;
next->size= get_size;
next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
@@ -296,6 +305,10 @@ void *multi_alloc_root(MEM_ROOT *root, ...)
char **ptr, *start, *res;
size_t tot_length, length;
DBUG_ENTER("multi_alloc_root");
+ /*
+ We don't need to do DBUG_PRINT here as it will be done when alloc_root
+ is called
+ */
va_start(args, root);
tot_length= 0;
@@ -321,7 +334,9 @@ void *multi_alloc_root(MEM_ROOT *root, ...)
DBUG_RETURN((void*) start);
}
-/* Mark all data in blocks free for reusage */
+
+#if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG))
+/** Mark all data in blocks free for reusage */
static inline void mark_blocks_free(MEM_ROOT* root)
{
@@ -349,7 +364,9 @@ static inline void mark_blocks_free(MEM_ROOT* root)
/* Now everything is set; Indicate that nothing is used anymore */
root->used= 0;
root->first_block_usage= 0;
+ root->block_num= 4;
}
+#endif
/*
@@ -375,13 +392,20 @@ void free_root(MEM_ROOT *root, myf MyFlags)
{
reg1 USED_MEM *next,*old;
DBUG_ENTER("free_root");
- DBUG_PRINT("enter",("root: %p flags: %u", root, (uint) MyFlags));
+ DBUG_PRINT("enter",("root: %p name: %s flags: %u", root, root->name,
+ (uint) MyFlags));
+#if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG))
+ /*
+ There is no point in using mark_blocks_free when using valgrind as
+ it will not reclaim any memory
+ */
if (MyFlags & MY_MARK_BLOCKS_FREE)
{
mark_blocks_free(root);
DBUG_VOID_RETURN;
}
+#endif
if (!(MyFlags & MY_KEEP_PREALLOC))
root->pre_alloc=0;
@@ -389,13 +413,19 @@ void free_root(MEM_ROOT *root, myf MyFlags)
{
old=next; next= next->next ;
if (old != root->pre_alloc)
+ {
+ root->total_alloc-= old->size;
my_free(old);
+ }
}
for (next=root->free ; next ;)
{
old=next; next= next->next;
if (old != root->pre_alloc)
+ {
+ root->total_alloc-= old->size;
my_free(old);
+ }
}
root->used=root->free=0;
if (root->pre_alloc)
diff --git a/mysys/my_atomic.c b/mysys/my_atomic.c
deleted file mode 100644
index 26348b518ae..00000000000
--- a/mysys/my_atomic.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
-
- 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include <my_global.h>
-#include <my_sys.h>
-
-#include <my_atomic.h>
-
-/*
- checks that the current build of atomic ops
- can run on this machine
-
- RETURN
- ATOMIC_xxx values, see my_atomic.h
-*/
-int my_atomic_initialize()
-{
- compile_time_assert(sizeof(intptr) == sizeof(void *));
- /* currently the only thing worth checking is SMP/UP issue */
-#ifdef MY_ATOMIC_MODE_DUMMY
- return my_getncpus() == 1 ? MY_ATOMIC_OK : MY_ATOMIC_NOT_1CPU;
-#else
- return MY_ATOMIC_OK;
-#endif
-}
-
-#ifdef SAFE_MUTEX
-#undef pthread_mutex_init
-#undef pthread_mutex_destroy
-#undef pthread_mutex_lock
-#undef pthread_mutex_unlock
-
-void plain_pthread_mutex_init(safe_mutex_t *m)
-{
- pthread_mutex_init(& m->mutex, NULL);
-}
-
-void plain_pthread_mutex_destroy(safe_mutex_t *m)
-{
- pthread_mutex_destroy(& m->mutex);
-}
-
-void plain_pthread_mutex_lock(safe_mutex_t *m)
-{
- pthread_mutex_lock(& m->mutex);
-}
-
-void plain_pthread_mutex_unlock(safe_mutex_t *m)
-{
- pthread_mutex_unlock(& m->mutex);
-}
-
-#endif
-
-
diff --git a/mysys/my_atomic_writes.c b/mysys/my_atomic_writes.c
index 0b54a207713..7f1e353c121 100644
--- a/mysys/my_atomic_writes.c
+++ b/mysys/my_atomic_writes.c
@@ -259,7 +259,7 @@ static my_bool shannon_has_atomic_write(File file, int page_size)
************************************************************************/
/*
- Initalize automic write sub systems.
+ Initialize automic write sub systems.
Checks if we have any devices that supports atomic write
*/
diff --git a/mysys/my_basename.c b/mysys/my_basename.c
index 9d1eaf53efa..4a1de782863 100644
--- a/mysys/my_basename.c
+++ b/mysys/my_basename.c
@@ -13,6 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <my_global.h>
#include <my_sys.h>
/**
@brief retrieve last component of the filename.
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index a0c1a23d63c..4db6b8a44f8 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -166,11 +166,15 @@ static inline uint get_first_set(my_bitmap_map value, uint word_pos)
return MY_BIT_NONE; /* Impossible */
}
+/*
+ Initialize a bitmap object. All bits will be set to zero
+*/
my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
my_bool thread_safe)
{
DBUG_ENTER("my_bitmap_init");
+ map->mutex= 0;
if (!buf)
{
uint size_in_bytes= bitmap_buffer_size(n_bits);
@@ -180,7 +184,6 @@ my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
size_in_bytes= ALIGN_SIZE(size_in_bytes);
extra= sizeof(mysql_mutex_t);
}
- map->mutex= 0;
if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME))))
DBUG_RETURN(1);
if (thread_safe)
diff --git a/mysys/my_compare.c b/mysys/my_compare.c
index 5ba1b409abb..4d384936a55 100644
--- a/mysys/my_compare.c
+++ b/mysys/my_compare.c
@@ -20,8 +20,8 @@
#include <my_compare.h>
#include <my_sys.h>
-int ha_compare_text(CHARSET_INFO *charset_info, const uchar *a, uint a_length,
- const uchar *b, uint b_length, my_bool part_key)
+int ha_compare_text(CHARSET_INFO *charset_info, const uchar *a, size_t a_length,
+ const uchar *b, size_t b_length, my_bool part_key)
{
if (!part_key)
return charset_info->coll->strnncollsp(charset_info, a, a_length,
diff --git a/mysys/my_conio.c b/mysys/my_conio.c
index 0af5706cace..21f30bd9b67 100644
--- a/mysys/my_conio.c
+++ b/mysys/my_conio.c
@@ -47,7 +47,7 @@ static HANDLE my_coninpfh= 0; /* console input */
static
int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, int id, int time)
{
- int res;
+ DWORD res;
char tname[FN_REFLEN];
sprintf(tname, "%s-%08X", name, id);
@@ -203,7 +203,7 @@ char* my_cgets(char *buffer, size_t clen, size_t* plen)
if (*plen > 0 && buffer[*plen - 1] == '\r')
{
char tmp[3];
- int tmplen= sizeof(tmp);
+ DWORD tmplen= (DWORD)sizeof(tmp);
*plen= *plen - 1;
/* read /n left in the buffer */
diff --git a/mysys/my_context.c b/mysys/my_context.c
index cf10738bdbd..5423f59d19b 100644
--- a/mysys/my_context.c
+++ b/mysys/my_context.c
@@ -707,7 +707,7 @@ my_context_continue(struct my_context *c)
{
/*
This seems to be a common trick to run ConvertThreadToFiber() only on the
- first occurence in a thread, in a way that works on multiple Windows
+ first occurrence in a thread, in a way that works on multiple Windows
versions.
*/
void *current_fiber= GetCurrentFiber();
diff --git a/mysys/my_default.c b/mysys/my_default.c
index 78fbe57e01d..f2d5bde41d5 100644
--- a/mysys/my_default.c
+++ b/mysys/my_default.c
@@ -519,7 +519,7 @@ int my_load_defaults(const char *conf_file, const char **groups,
uint args_sep= my_getopt_use_args_separator ? 1 : 0;
DBUG_ENTER("load_defaults");
- init_alloc_root(&alloc, 512, 0, MYF(0));
+ init_alloc_root(&alloc, "my_load_defaults", 512, 0, MYF(0));
if ((dirs= init_default_directories(&alloc)) == NULL)
goto err;
/*
@@ -1042,7 +1042,7 @@ void my_print_default_files(const char *conf_file)
{
const char **dirs;
MEM_ROOT alloc;
- init_alloc_root(&alloc, 512, 0, MYF(0));
+ init_alloc_root(&alloc, "my_print_defaults", 512, 0, MYF(0));
if ((dirs= init_default_directories(&alloc)) == NULL)
{
@@ -1186,7 +1186,7 @@ static const char **init_default_directories(MEM_ROOT *alloc)
{
errors += add_directory(alloc, fname_buffer, dirs);
- strncat(fname_buffer, "/data", sizeof(fname_buffer));
+ strcat_s(fname_buffer, sizeof(fname_buffer), "/data");
errors += add_directory(alloc, fname_buffer, dirs);
}
}
diff --git a/mysys/my_delete.c b/mysys/my_delete.c
index 0faf6079d98..beece473a01 100644
--- a/mysys/my_delete.c
+++ b/mysys/my_delete.c
@@ -83,7 +83,7 @@ static int my_win_unlink(const char *name)
{
HANDLE handle= INVALID_HANDLE_VALUE;
DWORD attributes;
- DWORD last_error;
+ uint last_error;
char unique_filename[MAX_PATH + 35];
unsigned long long tsc; /* time stamp counter, for unique filename*/
@@ -148,7 +148,7 @@ static int my_win_unlink(const char *name)
name, tsc);
if (!MoveFile(name, unique_filename))
{
- DBUG_PRINT("warning", ("moving %s to unique filename failed, error %u\n",
+ DBUG_PRINT("warning", ("moving %s to unique filename failed, error %lu\n",
name,GetLastError()));
}
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index 7dde1e1b4fc..59baeaec744 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -19,10 +19,6 @@
#include <errno.h>
#include "mysys_err.h"
-#if defined(__FreeBSD__)
-extern int getosreldate(void);
-#endif
-
static void make_ftype(char * to,int flag);
/*
@@ -65,15 +61,13 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
int filedesc= my_fileno(fd);
if ((uint)filedesc >= my_file_limit)
{
- thread_safe_increment(my_stream_opened,&THR_LOCK_open);
+ statistic_increment(my_stream_opened,&THR_LOCK_open);
DBUG_RETURN(fd); /* safeguard */
}
- mysql_mutex_lock(&THR_LOCK_open);
my_file_info[filedesc].name= (char*) my_strdup(filename,MyFlags);
- my_stream_opened++;
- my_file_total_opened++;
+ statistic_increment(my_stream_opened, &THR_LOCK_open);
+ statistic_increment(my_file_total_opened, &THR_LOCK_open);
my_file_info[filedesc].type= STREAM_BY_FOPEN;
- mysql_mutex_unlock(&THR_LOCK_open);
DBUG_PRINT("exit",("stream: %p", fd));
DBUG_RETURN(fd);
}
@@ -130,52 +124,6 @@ static FILE *my_win_freopen(const char *path, const char *mode, FILE *stream)
return stream;
}
-#elif defined(__FreeBSD__)
-
-/* No close operation hook. */
-
-static int no_close(void *cookie __attribute__((unused)))
-{
- return 0;
-}
-
-/*
- A hack around a race condition in the implementation of freopen.
-
- The race condition stems from the fact that the current fd of
- the stream is closed before its number is used to duplicate the
- new file descriptor. This defeats the desired atomicity of the
- close and duplicate of dup2().
-
- See PR number 79887 for reference:
- http://www.freebsd.org/cgi/query-pr.cgi?pr=79887
-*/
-
-static FILE *my_freebsd_freopen(const char *path, const char *mode, FILE *stream)
-{
- int old_fd;
- FILE *result;
-
- flockfile(stream);
-
- old_fd= fileno(stream);
-
- /* Use a no operation close hook to avoid having the fd closed. */
- stream->_close= no_close;
-
- /* Relies on the implicit dup2 to close old_fd. */
- result= freopen(path, mode, stream);
-
- /* If successful, the _close hook was replaced. */
-
- if (result == NULL)
- close(old_fd);
- else
- funlockfile(result);
-
- return result;
-}
-
#endif
@@ -199,16 +147,6 @@ FILE *my_freopen(const char *path, const char *mode, FILE *stream)
#if defined(_WIN32)
result= my_win_freopen(path, mode, stream);
-#elif defined(__FreeBSD__)
- /*
- XXX: Once the fix is ported to the stable releases, this should
- be dependent upon the specific FreeBSD versions. Check at:
- http://www.freebsd.org/cgi/query-pr.cgi?pr=79887
- */
- if (getosreldate() > 900027)
- result= freopen(path, mode, stream);
- else
- result= my_freebsd_freopen(path, mode, stream);
#else
result= freopen(path, mode, stream);
#endif
@@ -221,13 +159,22 @@ FILE *my_freopen(const char *path, const char *mode, FILE *stream)
int my_fclose(FILE *fd, myf MyFlags)
{
int err,file;
+ char *name= NULL;
DBUG_ENTER("my_fclose");
DBUG_PRINT("my",("stream: %p MyFlags: %lu", fd, MyFlags));
- mysql_mutex_lock(&THR_LOCK_open);
file= my_fileno(fd);
+ if ((uint) file < my_file_limit && my_file_info[file].type != UNOPEN)
+ {
+ name= my_file_info[file].name;
+ my_file_info[file].name= NULL;
+ my_file_info[file].type= UNOPEN;
+ }
#ifndef _WIN32
- err= fclose(fd);
+ do
+ {
+ err= fclose(fd);
+ } while (err == -1 && errno == EINTR);
#else
err= my_win_fclose(fd);
#endif
@@ -236,16 +183,15 @@ int my_fclose(FILE *fd, myf MyFlags)
my_errno=errno;
if (MyFlags & (MY_FAE | MY_WME))
my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG),
- my_filename(file),errno);
+ name,errno);
}
else
- my_stream_opened--;
- if ((uint) file < my_file_limit && my_file_info[file].type != UNOPEN)
+ statistic_decrement(my_stream_opened, &THR_LOCK_open);
+
+ if (name)
{
- my_file_info[file].type = UNOPEN;
- my_free(my_file_info[file].name);
+ my_free(name);
}
- mysql_mutex_unlock(&THR_LOCK_open);
DBUG_RETURN(err);
} /* my_fclose */
@@ -275,13 +221,12 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
}
else
{
- mysql_mutex_lock(&THR_LOCK_open);
- my_stream_opened++;
+ statistic_increment(my_stream_opened, &THR_LOCK_open);
if ((uint) Filedes < (uint) my_file_limit)
{
if (my_file_info[Filedes].type != UNOPEN)
{
- my_file_opened--; /* File is opened with my_open ! */
+ statistic_decrement(my_file_opened, &THR_LOCK_open); /* File is opened with my_open ! */
}
else
{
@@ -289,7 +234,6 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
}
my_file_info[Filedes].type = STREAM_BY_FDOPEN;
}
- mysql_mutex_unlock(&THR_LOCK_open);
}
DBUG_PRINT("exit",("stream: %p", fd));
@@ -320,6 +264,8 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
r+ == O_RDWR
w+ == O_RDWR|O_TRUNC|O_CREAT
a+ == O_RDWR|O_APPEND|O_CREAT
+ b == FILE_BINARY
+ e == O_CLOEXEC
*/
static void make_ftype(register char * to, register int flag)
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index dd4fba5bda7..830b7f42473 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -23,7 +23,6 @@
#include <mysys_err.h>
#include <my_getopt.h>
#include <errno.h>
-#include <m_string.h>
typedef void (*init_func_p)(const struct my_option *option, void *variable,
longlong value);
@@ -237,7 +236,7 @@ int handle_options(int *argc, char ***argv,
{
is_cmdline_arg= 1;
- /* save the separator too if skip unkown options */
+ /* save the separator too if skip unknown options */
if (my_getopt_skip_unknown)
(*argv)[argvpos++]= cur_arg;
else
@@ -827,7 +826,7 @@ static int setval(const struct my_option *opts, void *value, char *argument,
*((ulonglong*)value)=
find_set_from_flags(opts->typelib, opts->typelib->count,
*(ulonglong *)value, opts->def_value,
- argument, strlen(argument),
+ argument, (uint)strlen(argument),
&error, &error_len);
if (error)
{
@@ -836,6 +835,27 @@ static int setval(const struct my_option *opts, void *value, char *argument,
};
}
break;
+ case GET_BIT:
+ {
+ uint tmp;
+ ulonglong bit= (opts->block_size >= 0 ?
+ opts->block_size :
+ -opts->block_size);
+ /*
+ This sets a bit stored in a longlong.
+ The bit to set is stored in block_size. If block_size is positive
+ then setting the bit means value is true. If block_size is negatitive,
+ then setting the bit means value is false.
+ */
+ tmp= get_bool_argument(opts, argument);
+ if (opts->block_size < 0)
+ tmp= !tmp;
+ if (tmp)
+ (*(ulonglong*)value)|= bit;
+ else
+ (*(ulonglong*)value)&= ~bit;
+ break;
+ }
case GET_NO_ARG: /* get_one_option has taken care of the value already */
default: /* dummy default to avoid compiler warnings */
break;
@@ -949,31 +969,43 @@ my_bool getopt_compare_strings(register const char *s, register const char *t,
/*
function: eval_num_suffix
- Transforms suffix like k/m/g to their real value.
+ Transforms suffix like k/m/g/t/p/e to their real value.
*/
-static inline long eval_num_suffix(char *suffix, int *error)
+static inline ulonglong eval_num_suffix(char *suffix, int *error)
{
- long num= 1;
- if (*suffix == 'k' || *suffix == 'K')
- num*= 1024L;
- else if (*suffix == 'm' || *suffix == 'M')
- num*= 1024L * 1024L;
- else if (*suffix == 'g' || *suffix == 'G')
- num*= 1024L * 1024L * 1024L;
- else if (*suffix)
- {
+ switch (*suffix) {
+ case '\0':
+ return 1ULL;
+ case 'k':
+ case 'K':
+ return 1ULL << 10;
+ case 'm':
+ case 'M':
+ return 1ULL << 20;
+ case 'g':
+ case 'G':
+ return 1ULL << 30;
+ case 't':
+ case 'T':
+ return 1ULL << 40;
+ case 'p':
+ case 'P':
+ return 1ULL << 50;
+ case 'e':
+ case 'E':
+ return 1ULL << 60;
+ default:
*error= 1;
- return 0;
+ return 0ULL;
}
- return num;
}
/*
function: eval_num_suffix_ll
Transforms a number with a suffix to real number. Suffix can
- be k|K for kilo, m|M for mega or g|G for giga.
+ be k|K for kilo, m|M for mega, etc.
*/
static longlong eval_num_suffix_ll(char *argument,
@@ -1006,7 +1038,7 @@ static longlong eval_num_suffix_ll(char *argument,
function: eval_num_suffix_ull
Transforms a number with a suffix to positive Integer. Suffix can
- be k|K for kilo, m|M for mega or g|G for giga.
+ be k|K for kilo, m|M for mega, etc.
*/
static ulonglong eval_num_suffix_ull(char *argument,
@@ -1289,6 +1321,19 @@ static void init_one_value(const struct my_option *option, void *variable,
case GET_FLAGSET:
*((ulonglong*) variable)= (ulonglong) value;
break;
+ case GET_BIT:
+ {
+ ulonglong bit= (option->block_size >= 0 ?
+ option->block_size :
+ -option->block_size);
+ if (option->block_size < 0)
+ value= !value;
+ if (value)
+ (*(ulonglong*)variable)|= bit;
+ else
+ (*(ulonglong*)variable)&= ~bit;
+ break;
+ }
case GET_DOUBLE:
*((double*) variable)= getopt_ulonglong2double(value);
break;
@@ -1477,7 +1522,8 @@ void my_print_help(const struct my_option *options)
printf("--");
col+= 2 + print_name(optp);
if (optp->arg_type == NO_ARG ||
- (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
+ (optp->var_type & GET_TYPE_MASK) == GET_BOOL ||
+ (optp->var_type & GET_TYPE_MASK) == GET_BIT)
{
putchar(' ');
col++;
@@ -1575,7 +1621,7 @@ void my_print_variables(const struct my_option *options)
for (optp= options; optp->name; optp++)
{
- length= strlen(optp->name)+1;
+ length= (uint)strlen(optp->name)+1;
if (length > name_space)
name_space= length;
}
@@ -1627,6 +1673,16 @@ void my_print_variables(const struct my_option *options)
case GET_BOOL:
printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE");
break;
+ case GET_BIT:
+ {
+ ulonglong bit= (optp->block_size >= 0 ?
+ optp->block_size :
+ -optp->block_size);
+ my_bool reverse= optp->block_size < 0;
+ printf("%s\n", ((*((ulonglong*) value) & bit) != 0) ^ reverse ?
+ "TRUE" : "FALSE");
+ break;
+ }
case GET_INT:
printf("%d\n", *((int*) value));
break;
diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c
index 1cedeb21d6e..cd9525e5ff7 100644
--- a/mysys/my_getsystime.c
+++ b/mysys/my_getsystime.c
@@ -18,9 +18,12 @@
#include "mysys_priv.h"
#include "my_static.h"
-#ifdef __WIN__
+#ifdef _WIN32
#define OFFSET_TO_EPOC 116444736000000000LL
static ulonglong query_performance_frequency;
+typedef void (WINAPI* get_system_time_as_filetime_t)(LPFILETIME);
+static get_system_time_as_filetime_t
+ my_GetSystemTimePreciseAsFileTime= GetSystemTimeAsFileTime;
#endif
#ifdef HAVE_LINUX_UNISTD_H
#include <linux/unistd.h>
@@ -53,7 +56,7 @@ ulonglong my_interval_timer()
return tp.tv_sec*1000000000ULL+tp.tv_nsec;
#elif defined(HAVE_GETHRTIME)
return gethrtime();
-#elif defined(__WIN__)
+#elif defined(_WIN32)
LARGE_INTEGER t_cnt;
if (query_performance_frequency)
{
@@ -65,7 +68,7 @@ ulonglong my_interval_timer()
else
{
ulonglong newtime;
- GetSystemTimeAsFileTime((FILETIME*)&newtime);
+ my_GetSystemTimePreciseAsFileTime((FILETIME*)&newtime);
return newtime*100ULL;
}
#else
@@ -82,11 +85,10 @@ ulonglong my_interval_timer()
my_hrtime_t my_hrtime()
{
my_hrtime_t hrtime;
-#if defined(__WIN__)
+#if defined(_WIN32)
ulonglong newtime;
- GetSystemTimeAsFileTime((FILETIME*)&newtime);
- newtime -= OFFSET_TO_EPOC;
- hrtime.val= newtime/10;
+ my_GetSystemTimePreciseAsFileTime((FILETIME*)&newtime);
+ hrtime.val= (newtime - OFFSET_TO_EPOC)/10;
#elif defined(HAVE_CLOCK_GETTIME)
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
@@ -100,14 +102,39 @@ my_hrtime_t my_hrtime()
return hrtime;
}
+#ifdef _WIN32
+
+/*
+ Low accuracy, "coarse" timer.
+ Has lower latency than my_hrtime(). Used in situations, where microsecond
+ precision is not needed, e.g in Windows pthread_cond_timedwait, where POSIX
+ interface needs nanoseconds, yet the underlying Windows function only
+ accepts millisecons.
+*/
+my_hrtime_t my_hrtime_coarse()
+{
+ my_hrtime_t hrtime;
+ ulonglong t;
+ GetSystemTimeAsFileTime((FILETIME*)&t);
+ hrtime.val= (t - OFFSET_TO_EPOC)/10;
+ return hrtime;
+}
+
+#endif
void my_time_init()
{
-#ifdef __WIN__
+#ifdef _WIN32
compile_time_assert(sizeof(LARGE_INTEGER) ==
sizeof(query_performance_frequency));
if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0)
query_performance_frequency= 0;
+
+ get_system_time_as_filetime_t f= (get_system_time_as_filetime_t)
+ GetProcAddress(GetModuleHandle("kernel32"),
+ "GetSystemTimePreciseAsFileTime");
+ if (f)
+ my_GetSystemTimePreciseAsFileTime= f;
#endif
}
diff --git a/mysys/my_init.c b/mysys/my_init.c
index 86775275f23..972750da0ff 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -105,6 +105,10 @@ my_bool my_init(void)
if (my_thread_global_init())
return 1;
+#if defined(SAFEMALLOC) && !defined(DBUG_OFF)
+ dbug_sanity= sf_sanity;
+#endif
+
/* $HOME is needed early to parse configuration files located in ~/ */
if ((home_dir= getenv("HOME")) != 0)
home_dir= intern_filename(home_dir_buff, home_dir);
@@ -118,6 +122,9 @@ my_bool my_init(void)
#ifdef __WIN__
win32_init_tcp_ip();
#endif
+#ifdef CHECK_UNLIKELY
+ init_my_likely();
+#endif
DBUG_RETURN(0);
}
} /* my_init */
@@ -151,17 +158,36 @@ void my_end(int infoflag)
}
if ((infoflag & MY_CHECK_ERROR) || print_info)
+ { /* Test if some file is left open */
+ char ebuff[512];
+ uint i, open_files, open_streams;
+
+ for (open_streams= open_files= i= 0 ; i < my_file_limit ; i++)
+ {
+ if (my_file_info[i].type == UNOPEN)
+ continue;
+ if (my_file_info[i].type == STREAM_BY_FOPEN ||
+ my_file_info[i].type == STREAM_BY_FDOPEN)
+ open_streams++;
+ else
+ open_files++;
- { /* Test if some file is left open */
- if (my_file_opened | my_stream_opened)
+#ifdef EXTRA_DEBUG
+ fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i);
+ fputc('\n', stderr);
+#endif
+ }
+ if (open_files || open_streams)
{
- char ebuff[512];
my_snprintf(ebuff, sizeof(ebuff), EE(EE_OPEN_WARNING),
- my_file_opened, my_stream_opened);
+ open_files, open_streams);
my_message_stderr(EE_OPEN_WARNING, ebuff, ME_BELL);
DBUG_PRINT("error", ("%s", ebuff));
- my_print_open_files();
}
+
+#ifdef CHECK_UNLIKELY
+ end_my_likely(info_file);
+#endif
}
free_charsets();
my_error_unregister_all();
@@ -229,7 +255,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
my_init_done= my_thr_key_mysys_exists= 0;
} /* my_end */
-#ifndef DBUG_OFF
+#ifdef DBUG_ASSERT_EXISTS
/* Dummy tag function for debugging */
void my_debug_put_break_here(void)
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 21dcdcf861f..dc6b7cfd292 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -132,7 +132,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
MYF(MyFlags)))
goto error;
- init_alloc_root(&dirh->root, NAMES_START_SIZE, NAMES_START_SIZE,
+ init_alloc_root(&dirh->root, "dir", NAMES_START_SIZE, NAMES_START_SIZE,
MYF(MyFlags));
dp= (struct dirent*) dirent_tmp;
@@ -206,12 +206,12 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
ushort mode;
char tmp_path[FN_REFLEN], *tmp_file,attrib;
#ifdef _WIN64
- __int64 handle;
+ __int64 handle= -1;
#else
- long handle;
+ long handle= -1;
#endif
DBUG_ENTER("my_dir");
- DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));
+ DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,(int)MyFlags));
/* Put LIB-CHAR as last path-character if not there */
tmp_file=tmp_path;
@@ -235,7 +235,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
MYF(MyFlags)))
goto error;
- init_alloc_root(&dirh->root, NAMES_START_SIZE, NAMES_START_SIZE,
+ init_alloc_root(&dirh->root, "dir", NAMES_START_SIZE, NAMES_START_SIZE,
MYF(MyFlags));
if ((handle=_findfirst(tmp_path,&find)) == -1L)
diff --git a/mysys/my_likely.c b/mysys/my_likely.c
new file mode 100644
index 00000000000..c6fca5b7146
--- /dev/null
+++ b/mysys/my_likely.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2018, MariaDB Corporation 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/*
+ Checks that my_likely/my_unlikely is correctly used
+
+ Note that we can't use mysql_mutex or my_malloc here as these
+ uses likely() macros and the likely_mutex would be used twice
+*/
+
+#include "mysys_priv.h"
+#include <hash.h>
+#include <m_ctype.h>
+
+#ifndef CHECK_UNLIKEY
+my_bool likely_inited= 0;
+
+typedef struct st_likely_entry
+{
+ const char *key;
+ size_t key_length;
+ uint line;
+ ulonglong ok,fail;
+} LIKELY_ENTRY;
+
+static uchar *get_likely_key(LIKELY_ENTRY *part, size_t *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length= part->key_length;
+ return (uchar*) part->key;
+}
+
+pthread_mutex_t likely_mutex;
+HASH likely_hash;
+
+void init_my_likely()
+{
+ /* Allocate big enough to avoid malloc calls */
+ my_hash_init2(&likely_hash, 10000, &my_charset_bin,
+ 1024, 0, 0,
+ (my_hash_get_key) get_likely_key, 0,
+ free, HASH_UNIQUE);
+ likely_inited= 1;
+ pthread_mutex_init(&likely_mutex, MY_MUTEX_INIT_FAST);
+}
+
+static int likely_cmp(LIKELY_ENTRY **a, LIKELY_ENTRY **b)
+{
+ int cmp;
+ if ((cmp= strcmp((*a)->key, (*b)->key)))
+ return cmp;
+ return (int) ((*a)->line - (*b)->line);
+}
+
+
+void end_my_likely(FILE *out)
+{
+ uint i;
+ FILE *likely_file;
+ my_bool do_close= 0;
+ LIKELY_ENTRY **sort_ptr= 0;
+
+ likely_inited= 0;
+
+ if (!(likely_file= out))
+ {
+ char name[80];
+ sprintf(name, "/tmp/unlikely-%lu.out", (ulong) getpid());
+ if ((likely_file= my_fopen(name, O_TRUNC | O_WRONLY, MYF(MY_WME))))
+ do_close= 1;
+ else
+ likely_file= stderr;
+ }
+ fflush(likely_file);
+ fputs("Wrong likely/unlikely usage:\n", likely_file);
+ if (!(sort_ptr= (LIKELY_ENTRY**)
+ malloc(sizeof(LIKELY_ENTRY*) *likely_hash.records)))
+ {
+ fprintf(stderr, "ERROR: Out of memory in end_my_likely\n");
+ goto err;
+ }
+
+ for (i=0 ; i < likely_hash.records ; i++)
+ sort_ptr[i]= (LIKELY_ENTRY *) my_hash_element(&likely_hash, i);
+
+ my_qsort(sort_ptr, likely_hash.records, sizeof(LIKELY_ENTRY*),
+ (qsort_cmp) likely_cmp);
+
+ for (i=0 ; i < likely_hash.records ; i++)
+ {
+ LIKELY_ENTRY *entry= sort_ptr[i];
+ if (entry->fail > entry->ok)
+ fprintf(likely_file,
+ "%50s line: %6u ok: %8lld fail: %8lld\n",
+ entry->key, entry->line, entry->ok, entry->fail);
+ }
+ fputs("\n", likely_file);
+ fflush(likely_file);
+err:
+ free((void*) sort_ptr);
+ if (do_close)
+ my_fclose(likely_file, MYF(MY_WME));
+ pthread_mutex_destroy(&likely_mutex);
+ my_hash_free(&likely_hash);
+}
+
+
+static LIKELY_ENTRY *my_likely_find(const char *file_name, uint line)
+{
+ char key[80], *pos;
+ LIKELY_ENTRY *entry;
+ size_t length;
+
+ if (!likely_inited)
+ return 0;
+
+ pos= strnmov(key, file_name, sizeof(key)-4);
+ int3store(pos+1, line);
+ length= (size_t) (pos-key)+4;
+
+ pthread_mutex_lock(&likely_mutex);
+ if (!(entry= (LIKELY_ENTRY*) my_hash_search(&likely_hash, (uchar*) key,
+ length)))
+ {
+ if (!(entry= (LIKELY_ENTRY *) malloc(sizeof(*entry) + length)))
+ return 0;
+ entry->key= (char*) (entry+1);
+ memcpy((void*) entry->key, key, length);
+ entry->key_length= length;
+ entry->line= line;
+ entry->ok= entry->fail= 0;
+
+ if (my_hash_insert(&likely_hash, (void*) entry))
+ {
+ pthread_mutex_unlock(&likely_mutex);
+ free(entry);
+ return 0;
+ }
+ }
+ pthread_mutex_unlock(&likely_mutex);
+ return entry;
+}
+
+
+int my_likely_ok(const char *file_name, uint line)
+{
+ LIKELY_ENTRY *entry= my_likely_find(file_name, line);
+ if (entry)
+ entry->ok++;
+ return 0;
+}
+
+
+int my_likely_fail(const char *file_name, uint line)
+{
+ LIKELY_ENTRY *entry= my_likely_find(file_name, line);
+ if (entry)
+ entry->fail++;
+ return 0;
+}
+#endif /* CHECK_UNLIKEY */
diff --git a/mysys/my_lock.c b/mysys/my_lock.c
index 082d8e9f5a0..34b1723e13c 100644
--- a/mysys/my_lock.c
+++ b/mysys/my_lock.c
@@ -34,7 +34,6 @@ static int win_lock(File fd, int locktype, my_off_t start, my_off_t length,
DWORD dwFlags;
OVERLAPPED ov= {0};
HANDLE hFile= (HANDLE)my_get_osfhandle(fd);
- DWORD lastError= 0;
int i;
int timeout_millis= timeout_sec * 1000;
diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c
index 719c13a040e..6a3ec8da093 100644
--- a/mysys/my_malloc.c
+++ b/mysys/my_malloc.c
@@ -200,8 +200,6 @@ void *my_realloc(void *oldpoint, size_t size, myf my_flags)
/**
Free memory allocated with my_malloc.
- @remark Relies on free being able to handle a NULL argument.
-
@param ptr Pointer to the memory allocated by my_malloc.
*/
void my_free(void *ptr)
@@ -214,6 +212,13 @@ void my_free(void *ptr)
my_bool old_flags;
old_size= MALLOC_SIZE_AND_FLAG(ptr, &old_flags);
update_malloc_size(- (longlong) old_size - MALLOC_PREFIX_SIZE, old_flags);
+#ifndef SAFEMALLOC
+ /*
+ Trash memory if not safemalloc. We don't have to do this if safemalloc
+ is used as safemalloc will also do trashing
+ */
+ TRASH_FREE(ptr, old_size);
+#endif
sf_free(MALLOC_FIX_POINTER_FOR_FREE(ptr));
}
DBUG_VOID_RETURN;
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 3999810eb2e..54e53089da9 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -76,12 +76,18 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
int my_close(File fd, myf MyFlags)
{
int err;
+ char *name= NULL;
DBUG_ENTER("my_close");
DBUG_PRINT("my",("fd: %d MyFlags: %lu",fd, MyFlags));
if (!(MyFlags & (MY_WME | MY_FAE)))
MyFlags|= my_global_flags;
- mysql_mutex_lock(&THR_LOCK_open);
+ if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN)
+ {
+ name= my_file_info[fd].name;
+ my_file_info[fd].name= NULL;
+ my_file_info[fd].type= UNOPEN;
+ }
#ifndef _WIN32
do
{
@@ -96,15 +102,13 @@ int my_close(File fd, myf MyFlags)
my_errno=errno;
if (MyFlags & (MY_FAE | MY_WME))
my_error(EE_BADCLOSE, MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
- my_filename(fd),errno);
+ name,errno);
}
- if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN)
+ if (name)
{
- my_free(my_file_info[fd].name);
- my_file_info[fd].type = UNOPEN;
+ my_free(name);
}
- my_file_opened--;
- mysql_mutex_unlock(&THR_LOCK_open);
+ statistic_decrement(my_file_opened, &THR_LOCK_open);
DBUG_RETURN(err);
} /* my_close */
@@ -134,15 +138,13 @@ File my_register_filename(File fd, const char *FileName, enum file_type
{
if ((uint) fd >= my_file_limit)
{
- thread_safe_increment(my_file_opened,&THR_LOCK_open);
+ statistic_increment(my_file_opened,&THR_LOCK_open);
DBUG_RETURN(fd); /* safeguard */
}
- mysql_mutex_lock(&THR_LOCK_open);
my_file_info[fd].name = (char*) my_strdup(FileName, MyFlags);
- my_file_opened++;
- my_file_total_opened++;
+ statistic_increment(my_file_opened,&THR_LOCK_open);
+ statistic_increment(my_file_total_opened,&THR_LOCK_open);
my_file_info[fd].type = type_of_file;
- mysql_mutex_unlock(&THR_LOCK_open);
DBUG_PRINT("exit",("fd: %d",fd));
DBUG_RETURN(fd);
}
@@ -159,26 +161,3 @@ File my_register_filename(File fd, const char *FileName, enum file_type
}
DBUG_RETURN(-1);
}
-
-
-
-
-#ifdef EXTRA_DEBUG
-
-void my_print_open_files(void)
-{
- if (my_file_opened | my_stream_opened)
- {
- uint i;
- for (i= 0 ; i < my_file_limit ; i++)
- {
- if (my_file_info[i].type != UNOPEN)
- {
- fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i);
- fputc('\n', stderr);
- }
- }
- }
-}
-
-#endif
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 20e53a23ab5..0b84ed0cd82 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -21,6 +21,7 @@
#include <signal.h>
#include <m_string.h>
#include <thr_alarm.h>
+#include <my_pthread.h>
#if (defined(__BSD__) || defined(_BSDI_VERSION))
#define SCHED_POLICY SCHED_RR
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 922da5a7e95..89b368e9800 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -35,11 +35,10 @@
size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
{
- size_t readbytes, save_count;
+ size_t readbytes, save_count= 0;
DBUG_ENTER("my_read");
DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %lu",
Filedes, Buffer, (ulong) Count, MyFlags));
- save_count= Count;
if (!(MyFlags & (MY_WME | MY_FAE | MY_FNABP)))
MyFlags|= my_global_flags;
@@ -61,47 +60,52 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
if (readbytes != Count)
{
- my_errno= errno;
- if (errno == 0 || (readbytes != (size_t) -1 &&
- (MyFlags & (MY_NABP | MY_FNABP))))
- my_errno= HA_ERR_FILE_TOO_SHORT;
+ int got_errno= my_errno= errno;
DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d",
(int) readbytes, (ulong) Count, Filedes,
- my_errno));
+ got_errno));
+
+ if (got_errno == 0 || (readbytes != (size_t) -1 &&
+ (MyFlags & (MY_NABP | MY_FNABP))))
+ my_errno= HA_ERR_FILE_TOO_SHORT;
- if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
+ if ((readbytes == 0 || (int) readbytes == -1) && got_errno == EINTR)
{
DBUG_PRINT("debug", ("my_read() was interrupted and returned %ld",
(long) readbytes));
continue; /* Interrupted */
}
+ /* Do a read retry if we didn't get enough data on first read */
+ if (readbytes != (size_t) -1 && readbytes != 0 &&
+ (MyFlags & MY_FULL_IO))
+ {
+ Buffer+= readbytes;
+ Count-= readbytes;
+ save_count+= readbytes;
+ continue;
+ }
+
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
if (readbytes == (size_t) -1)
my_error(EE_READ,
MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
- my_filename(Filedes),my_errno);
+ my_filename(Filedes), got_errno);
else if (MyFlags & (MY_NABP | MY_FNABP))
my_error(EE_EOFERR,
MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))),
- my_filename(Filedes),my_errno);
+ my_filename(Filedes), got_errno);
}
if (readbytes == (size_t) -1 ||
((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO)))
DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
- if (readbytes != (size_t) -1 && (MyFlags & MY_FULL_IO))
- {
- Buffer+= readbytes;
- Count-= readbytes;
- continue;
- }
}
if (MyFlags & (MY_NABP | MY_FNABP))
readbytes= 0; /* Ok on read */
- else if (MyFlags & MY_FULL_IO)
- readbytes= save_count;
+ else
+ readbytes+= save_count;
break;
}
DBUG_RETURN(readbytes);
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index d1e239692f1..cf8dfb6a8c8 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -133,8 +133,6 @@ int my_sync(File fd, myf my_flags)
} /* my_sync */
-static const char cur_dir_name[]= {FN_CURLIB, 0};
-
/*
Force directory information to disk.
@@ -151,6 +149,7 @@ int my_sync_dir(const char *dir_name __attribute__((unused)),
myf my_flags __attribute__((unused)))
{
#ifdef NEED_EXPLICIT_SYNC_DIR
+ static const char cur_dir_name[]= {FN_CURLIB, 0};
File dir_fd;
int res= 0;
const char *correct_dir_name;
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 3f9c8eeba10..2faa704b998 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -341,14 +341,12 @@ void my_thread_end(void)
tmp, pthread_self(), tmp ? (long) tmp->id : 0L);
#endif
-#ifdef HAVE_PSI_INTERFACE
/*
Remove the instrumentation for this thread.
This must be done before trashing st_my_thread_var,
because the LF_HASH depends on it.
*/
- PSI_THREAD_CALL(delete_current_thread)();
-#endif
+ PSI_CALL_delete_current_thread();
/*
We need to disable DBUG early for this thread to ensure that the
diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c
index 54b272d7025..514e9a92ecf 100644
--- a/mysys/my_wincond.c
+++ b/mysys/my_wincond.c
@@ -98,9 +98,10 @@ int pthread_attr_init(pthread_attr_t *connect_att)
return 0;
}
-int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack)
+int pthread_attr_setstacksize(pthread_attr_t *connect_att,size_t stack)
{
- connect_att->dwStackSize=stack;
+ DBUG_ASSERT(stack < UINT_MAX);
+ connect_att->dwStackSize=(DWORD)stack;
return 0;
}
diff --git a/mysys/my_windac.c b/mysys/my_windac.c
index 9b489759625..720bf3b4894 100644
--- a/mysys/my_windac.c
+++ b/mysys/my_windac.c
@@ -17,21 +17,6 @@
#include "m_string.h"
#ifdef __WIN__
-/* Windows NT/2000 discretionary access control utility functions. */
-
-/*
- Check if the operating system is built on NT technology.
-
- RETURN
- 0 Windows 95/98/Me
- 1 otherwise
-*/
-
-static my_bool is_nt()
-{
- return GetVersion() < 0x80000000;
-}
-
/*
Auxiliary structure to store pointers to the data which we need to keep
around while SECURITY_ATTRIBUTES is in use.
@@ -86,12 +71,6 @@ int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror,
PSID owner_sid;
My_security_attr *attr;
- if (! is_nt())
- {
- *psa= 0;
- return 0;
- }
-
/*
Get SID of Everyone group. Easier to retrieve all SIDs each time
this function is called than worry about thread safety.
diff --git a/mysys/my_winerr.c b/mysys/my_winerr.c
index a3f6229b74e..ccd94d92d80 100644
--- a/mysys/my_winerr.c
+++ b/mysys/my_winerr.c
@@ -96,7 +96,7 @@ access violations */
static int get_errno_from_oserr(unsigned long oserrno)
{
- int i;
+ size_t i;
/* check the table for the OS error code */
for (i= 0; i < ERRTABLESIZE; ++i)
diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c
index ad87bf718d2..0762a95e827 100644
--- a/mysys/my_winfile.c
+++ b/mysys/my_winfile.c
@@ -528,7 +528,7 @@ FILE *my_win_fopen(const char *filename, const char *type)
{
FILE *file;
int flags= 0;
- DBUG_ENTER("my_win_open");
+ DBUG_ENTER("my_win_fopen");
/*
If we are not creating, then we need to use my_access to make sure
@@ -585,7 +585,7 @@ int my_win_fclose(FILE *file)
{
File fd;
- DBUG_ENTER("my_win_close");
+ DBUG_ENTER("my_win_fclose");
fd= my_fileno(file);
if(fd < 0)
DBUG_RETURN(-1);
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
index f3335621c38..080eeb49f63 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -79,10 +79,10 @@ int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr,
par->arg= param;
stack_size= attr?attr->dwStackSize:0;
- handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id);
+ handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, (uint *)thread_id);
if (!handle)
goto error_return;
- DBUG_PRINT("info", ("thread id=%u",*thread_id));
+ DBUG_PRINT("info", ("thread id=%lu",*thread_id));
/* Do not need thread handle, close it */
CloseHandle((HANDLE)handle);
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 892e09148ef..38a75120303 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -146,8 +146,12 @@ const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd);
return NOAT;
#endif
+#ifndef _WIN32
#define CREATE_NOSYMLINK_FUNCTION(PROTO,AT,NOAT) \
static int PROTO { NOSYMLINK_FUNCTION_BODY(AT,NOAT) }
+#else
+#define CREATE_NOSYMLINK_FUNCTION(PROTO,AT,NOAT)
+#endif
#ifdef _WIN32
#include <sys/stat.h>
diff --git a/mysys/psi_noop.c b/mysys/psi_noop.c
index 6eecf56f797..f8fa2c92f63 100644
--- a/mysys/psi_noop.c
+++ b/mysys/psi_noop.c
@@ -763,6 +763,13 @@ struct PSI_bootstrap *PSI_hook= NULL;
PSI *PSI_server= & PSI_noop;
+/**
+ Global performance schema flag.
+ Indicate if the performance schema is enabled.
+ This flag is set at startup, and never changes.
+*/
+my_bool pfs_enabled= FALSE;
+
void set_psi_server(PSI *psi)
{
PSI_server= psi;
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 6d853a8db25..1880e60a811 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -27,14 +27,18 @@
* written in assembler. for example one in /usr/lib/libc/libc_hwcap*.so.1.
* on Solaris, or on Windows inside C runtime linrary.
*
- * On Solaris, native implementation is also usually faster than the
- * built-in memcmp supplied by GCC, so it is recommended to build
+ * On Solaris, native implementation is also usually faster than the
+ * built-in memcmp supplied by GCC, so it is recommended to build
* with "-fno-builtin-memcmp"in CFLAGS if building with GCC on Solaris.
*/
-#if defined (__sun) || defined (_WIN32)
+/*
+ Daniel Blacks tests shows that libc memcmp is generally faster than
+ ptr_cmp() at least of x86 and power8 platforms, so we use the libc
+ code as deafult for now
+*/
+
#define USE_NATIVE_MEMCMP 1
-#endif
#ifdef USE_NATIVE_MEMCMP
@@ -45,23 +49,19 @@ static int native_compare(size_t *length, unsigned char **a, unsigned char **b)
return memcmp(*a, *b, *length);
}
-#else /* USE_NATIVE_MEMCMP */
+qsort2_cmp get_ptr_compare (size_t size __attribute__((unused)))
+{
+ return (qsort2_cmp) native_compare;
+}
+
+#else /* USE_NATIVE_MEMCMP */
static int ptr_compare(size_t *compare_length, uchar **a, uchar **b);
static int ptr_compare_0(size_t *compare_length, uchar **a, uchar **b);
static int ptr_compare_1(size_t *compare_length, uchar **a, uchar **b);
static int ptr_compare_2(size_t *compare_length, uchar **a, uchar **b);
static int ptr_compare_3(size_t *compare_length, uchar **a, uchar **b);
-#endif /* __sun */
- /* Get a pointer to a optimal byte-compare function for a given size */
-
-#ifdef USE_NATIVE_MEMCMP
-qsort2_cmp get_ptr_compare (size_t size __attribute__((unused)))
-{
- return (qsort2_cmp) native_compare;
-}
-#else
qsort2_cmp get_ptr_compare (size_t size)
{
if (size < 4)
@@ -74,9 +74,6 @@ qsort2_cmp get_ptr_compare (size_t size)
}
return 0; /* Impossible */
}
-#endif /* USE_NATIVE_MEMCMP */
-
-
/*
Compare to keys to see witch is smaller.
Loop unrolled to make it quick !!
@@ -84,8 +81,6 @@ qsort2_cmp get_ptr_compare (size_t size)
#define cmp(N) if (first[N] != last[N]) return (int) first[N] - (int) last[N]
-#ifndef USE_NATIVE_MEMCMP
-
static int ptr_compare(size_t *compare_length, uchar **a, uchar **b)
{
size_t length= *compare_length;
@@ -189,7 +184,7 @@ static int ptr_compare_3(size_t *compare_length,uchar **a, uchar **b)
return (0);
}
-#endif /* !__sun */
+#endif /* USE_NATIVE_MEMCMP */
void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos)
{
@@ -227,4 +222,3 @@ my_off_t my_get_ptr(uchar *ptr, size_t pack_length)
}
return pos;
}
-
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 9916650308a..ae8993fbf00 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -293,7 +293,7 @@ static void warn(const char *format,...)
{
void *frame[SF_REMEMBER_FRAMES + SF_FRAMES_SKIP];
int frames= backtrace(frame, array_elements(frame));
- fprintf(stderr, " ");
+ fprintf(stderr, " at ");
if (frames < SF_REMEMBER_FRAMES + SF_FRAMES_SKIP)
frame[frames]= 0;
print_stack(frame + SF_FRAMES_SKIP);
@@ -318,7 +318,8 @@ static int bad_ptr(const char *where, void *ptr)
}
if (irem->marker != MAGICSTART)
{
- warn("Error: %s unallocated data or underrun buffer", where);
+ DBUG_PRINT("error",("Unallocated data or underrun buffer %p", ptr));
+ warn("Error: %s unallocated data or underrun buffer %p", ptr, where);
return 1;
}
@@ -328,7 +329,8 @@ static int bad_ptr(const char *where, void *ptr)
magicend[2] != MAGICEND2 ||
magicend[3] != MAGICEND3)
{
- warn("Error: %s overrun buffer ", where);
+ DBUG_PRINT("error",("Overrun buffer %p", ptr));
+ warn("Error: %s overrun buffer %p", where, ptr);
fprintf(stderr, "Allocated at ");
print_stack(irem->frame);
return 1;
@@ -338,7 +340,7 @@ static int bad_ptr(const char *where, void *ptr)
}
/* check all allocated memory list for consistency */
-static int sf_sanity()
+int sf_sanity()
{
struct st_irem *irem;
int flag= 0;
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index 463cfe03f1d..619172a5a6a 100644
--- a/mysys/stacktrace.c
+++ b/mysys/stacktrace.c
@@ -70,7 +70,7 @@ static void print_buffer(char *buffer, size_t count)
@return Zero on success.
*/
-static int safe_print_str(const char *addr, int max_len)
+static int safe_print_str(const char *addr, size_t max_len)
{
int fd;
pid_t tid;
@@ -147,7 +147,7 @@ static int safe_print_str(const char *addr, int max_len)
returns 1, it does not mean 100% that the pointer is corrupted.
*/
-int my_safe_print_str(const char* val, int max_len)
+int my_safe_print_str(const char* val, size_t max_len)
{
char *heap_end;
@@ -178,12 +178,13 @@ int my_safe_print_str(const char* val, int max_len)
#include <ucontext.h>
void my_print_stacktrace(uchar* stack_bottom __attribute__((unused)),
- ulong thread_stack __attribute__((unused)))
+ ulong thread_stack __attribute__((unused)),
+ my_bool silent)
{
if (printstack(fileno(stderr)) == -1)
my_safe_printf_stderr("%s",
"Error when traversing the stack, stack appears corrupt.\n");
- else
+ else if (!silent)
my_safe_printf_stderr("%s",
"Please read "
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
@@ -260,7 +261,8 @@ static int print_with_addr_resolve(void **addrs, int n)
}
#endif
-void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
+void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack,
+ my_bool silent __attribute__((unused)))
{
void *addrs[128];
char **strings __attribute__((unused)) = NULL;
@@ -334,7 +336,8 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp)
}
#endif /* defined(__alpha__) && defined(__GNUC__) */
-void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
+void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack,
+ my_bool silent)
{
uchar** UNINIT_VAR(fp);
uint frame_count = 0, sigreturn_frame_count;
@@ -449,7 +452,8 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
"Stack trace seems successful - bottom reached\n");
end:
- my_safe_printf_stderr("%s",
+ if (!silent)
+ my_safe_printf_stderr("%s",
"Please read "
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
"and follow instructions on how to resolve the stack trace.\n"
@@ -610,7 +614,7 @@ static void get_symbol_path(char *path, size_t size)
#define SYMOPT_NO_PROMPTS 0
#endif
-void my_print_stacktrace(uchar* unused1, ulong unused2)
+void my_print_stacktrace(uchar* unused1, ulong unused2, my_bool silent)
{
HANDLE hProcess= GetCurrentProcess();
HANDLE hThread= GetCurrentThread();
@@ -699,7 +703,7 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
if(have_source)
{
const char *base_file_name= my_basename(line.FileName);
- my_safe_printf_stderr("[%s:%u]",
+ my_safe_printf_stderr("[%s:%lu]",
base_file_name, line.LineNumber);
}
my_safe_printf_stderr("%s", "\n");
@@ -729,7 +733,7 @@ void my_write_core(int unused)
if(GetModuleFileName(NULL, path, sizeof(path)))
{
_splitpath(path, NULL, NULL,dump_fname,NULL);
- strncat(dump_fname, ".dmp", sizeof(dump_fname));
+ strcat_s(dump_fname, sizeof(dump_fname), ".dmp");
}
hFile= CreateFile(dump_fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
@@ -759,7 +763,7 @@ void my_write_core(int unused)
}
-int my_safe_print_str(const char *val, int len)
+int my_safe_print_str(const char *val, size_t len)
{
__try
{
@@ -776,7 +780,7 @@ int my_safe_print_str(const char *val, int len)
size_t my_write_stderr(const void *buf, size_t count)
{
- return (size_t) write(fileno(stderr), buf, count);
+ return (size_t) write(fileno(stderr), buf, (uint)count);
}
diff --git a/mysys/string.c b/mysys/string.c
index a0fa3a02e17..18c5f4ec9af 100644
--- a/mysys/string.c
+++ b/mysys/string.c
@@ -178,9 +178,9 @@ my_bool dynstr_append_quoted(DYNAMIC_STRING *str,
const char *append, size_t len,
char quote)
{
- uint additional= (str->alloc_increment ? str->alloc_increment : 10);
- uint lim= additional;
- uint i;
+ size_t additional= (str->alloc_increment ? str->alloc_increment : 10);
+ size_t lim= additional;
+ size_t i;
if (dynstr_realloc(str, len + additional + 2))
return TRUE;
str->str[str->length++]= quote;
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 61ef3657161..357923cf388 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -36,13 +36,6 @@
#define ETIME ETIMEDOUT
#endif
-uint thr_client_alarm;
-static int alarm_aborted=1; /* No alarm thread */
-my_bool thr_alarm_inited= 0, my_disable_thr_alarm= 0;
-volatile my_bool alarm_thread_running= 0;
-time_t next_alarm_expire_time= ~ (time_t) 0;
-static sig_handler process_alarm_part2(int sig);
-
#ifdef DBUG_OFF
#define reset_index_in_queue(alarm_data)
#else
@@ -55,9 +48,16 @@ static sig_handler process_alarm_part2(int sig);
#define one_signal_hand_sigmask(A,B,C)
#endif
+my_bool thr_alarm_inited= 0, my_disable_thr_alarm= 0;
#if !defined(__WIN__)
+uint thr_client_alarm;
+static int alarm_aborted=1; /* No alarm thread */
+volatile my_bool alarm_thread_running= 0;
+time_t next_alarm_expire_time= ~ (time_t) 0;
+static sig_handler process_alarm_part2(int sig);
+
static mysql_mutex_t LOCK_alarm;
static mysql_cond_t COND_alarm;
static sigset_t full_signal_set;
@@ -261,7 +261,8 @@ void thr_end_alarm(thr_alarm_t *alarmed)
alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
mysql_mutex_lock(&LOCK_alarm);
DBUG_ASSERT(alarm_data->index_in_queue != 0);
- DBUG_ASSERT(queue_element(&alarm_queue, alarm_data->index_in_queue) ==
+ DBUG_ASSERT((ALARM*) queue_element(&alarm_queue,
+ alarm_data->index_in_queue) ==
alarm_data);
queue_remove(&alarm_queue, alarm_data->index_in_queue);
mysql_mutex_unlock(&LOCK_alarm);
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index 5cf81bcc93e..3bc16d8c1db 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -357,7 +357,8 @@ static void check_locks(THR_LOCK *lock, const char *where,
data && count < MAX_LOCKS;
data=data->next)
{
- if (data->type != TL_WRITE_CONCURRENT_INSERT)
+ if (data->type != TL_WRITE_CONCURRENT_INSERT &&
+ data->type != TL_WRITE_ALLOW_WRITE)
{
fprintf(stderr,
"Warning at '%s': Found TL_WRITE_CONCURRENT_INSERT lock mixed with other write lock: %d\n",
@@ -1540,7 +1541,7 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data,
enum thr_lock_type new_lock_type)
{
THR_LOCK *lock=in_data->lock;
-#ifndef DBUG_OFF
+#ifdef DBUG_ASSERT_EXISTS
enum thr_lock_type old_lock_type= in_data->type;
#endif
DBUG_ENTER("thr_downgrade_write_only_lock");
@@ -1683,31 +1684,35 @@ void thr_print_locks(void)
uint count=0;
mysql_mutex_lock(&THR_LOCK_lock);
- puts("Current locks:");
+ puts("Current active THR (table level locks):");
for (list= thr_lock_thread_list; list && count++ < MAX_THREADS;
list= list_rest(list))
{
THR_LOCK *lock=(THR_LOCK*) list->data;
mysql_mutex_lock(&lock->mutex);
- printf("lock:%p:", lock);
- if ((lock->write_wait.data || lock->read_wait.data) &&
- (! lock->read.data && ! lock->write.data))
- printf(" WARNING: ");
- if (lock->write.data)
- printf(" write");
- if (lock->write_wait.data)
- printf(" write_wait");
- if (lock->read.data)
- printf(" read");
- if (lock->read_wait.data)
- printf(" read_wait");
- puts("");
- thr_print_lock("write",&lock->write);
- thr_print_lock("write_wait",&lock->write_wait);
- thr_print_lock("read",&lock->read);
- thr_print_lock("read_wait",&lock->read_wait);
+ if ((lock->write.data || lock->read.data ||
+ lock->write_wait.data || lock->read_wait.data))
+ {
+ printf("lock: %p:", lock);
+ if ((lock->write_wait.data || lock->read_wait.data) &&
+ (! lock->read.data && ! lock->write.data))
+ printf(" WARNING: ");
+ if (lock->write.data)
+ printf(" write");
+ if (lock->write_wait.data)
+ printf(" write_wait");
+ if (lock->read.data)
+ printf(" read");
+ if (lock->read_wait.data)
+ printf(" read_wait");
+ puts("");
+ thr_print_lock("write",&lock->write);
+ thr_print_lock("write_wait",&lock->write_wait);
+ thr_print_lock("read",&lock->read);
+ thr_print_lock("read_wait",&lock->read_wait);
+ puts("");
+ }
mysql_mutex_unlock(&lock->mutex);
- puts("");
}
fflush(stdout);
mysql_mutex_unlock(&THR_LOCK_lock);
diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c
index f1e83db2bb6..268a2b80f63 100644
--- a/mysys/thr_mutex.c
+++ b/mysys/thr_mutex.c
@@ -149,10 +149,11 @@ static inline void remove_from_active_list(safe_mutex_t *mp)
}
/*
- We initialise the hashes for deadlock detection lazily.
- This greatly helps with performance when lots of mutexes are initiased but
- only a few of them are actually used (eg. XtraDB).
+ We initialize the hashes for deadlock detection lazily.
+ This greatly helps with performance when lots of mutexes are initialized but
+ only a few of them are actually used (eg. InnoDB).
*/
+
static int safe_mutex_lazy_init_deadlock_detection(safe_mutex_t *mp)
{
if (!my_multi_malloc(MY_FAE | MY_WME,
@@ -239,7 +240,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file,
if (!mp->file)
{
fprintf(stderr,
- "safe_mutex: Trying to lock unitialized mutex at %s, line %d\n",
+ "safe_mutex: Trying to lock uninitialized mutex at %s, line %d\n",
file, line);
fflush(stderr);
abort();
@@ -584,7 +585,7 @@ int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line)
if (!mp->file)
{
fprintf(stderr,
- "safe_mutex: Trying to destroy unitialized mutex at %s, line %d\n",
+ "safe_mutex: Trying to destroy uninitialized mutex at %s, line %d\n",
file, line);
fflush(stderr);
abort();
diff --git a/mysys/tree.c b/mysys/tree.c
index c71925df7db..b07d56ec942 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -66,7 +66,7 @@
#define DEFAULT_ALLOC_SIZE 8192
#define DEFAULT_ALIGN_SIZE 8192
-static void delete_tree_element(TREE *,TREE_ELEMENT *);
+static int delete_tree_element(TREE *,TREE_ELEMENT *, my_bool abort);
static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *,
tree_walk_action,void *);
static int tree_walk_right_root_left(TREE *,TREE_ELEMENT *,
@@ -130,28 +130,37 @@ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit,
}
if (!(tree->with_delete= MY_TEST(my_flags & MY_TREE_WITH_DELETE)))
{
- init_alloc_root(&tree->mem_root, default_alloc_size, 0, MYF(my_flags));
+ init_alloc_root(&tree->mem_root, "tree", default_alloc_size, 0,
+ MYF(my_flags));
tree->mem_root.min_malloc= sizeof(TREE_ELEMENT)+tree->size_of_element;
}
DBUG_VOID_RETURN;
}
-static void free_tree(TREE *tree, myf free_flags)
+static int free_tree(TREE *tree, my_bool abort, myf free_flags)
{
+ int error, first_error= 0;
DBUG_ENTER("free_tree");
DBUG_PRINT("enter",("tree: %p", tree));
if (tree->root) /* If initialized */
{
if (tree->with_delete)
- delete_tree_element(tree,tree->root);
+ {
+ if ((error= delete_tree_element(tree, tree->root, abort)))
+ {
+ first_error= first_error ? first_error : error;
+ abort= 1;
+ }
+ }
else
{
if (tree->free)
{
if (tree->memory_limit)
(*tree->free)(NULL, free_init, tree->custom_arg);
- delete_tree_element(tree,tree->root);
+ if ((error= delete_tree_element(tree, tree->root, abort)))
+ first_error= first_error ? first_error : error;
if (tree->memory_limit)
(*tree->free)(NULL, free_end, tree->custom_arg);
}
@@ -162,32 +171,61 @@ static void free_tree(TREE *tree, myf free_flags)
tree->elements_in_tree=0;
tree->allocated=0;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(first_error);
}
-void delete_tree(TREE* tree)
+
+/**
+ Delete tree.
+
+ @param tree Tree
+ @param abort 0 if normal, 1 if tree->free should not be called.
+
+ @return 0 ok
+ <> 0 Returns first <> 0 from (tree->free)(*,free_free,*)
+
+ @Notes
+ If one (tree->free)(,free_free,) returns <> 0, no future
+ tree->free(*,free_free,*) will be called.
+ Other tree->free operations (free_init, free_end) will be called
+*/
+
+
+int delete_tree(TREE* tree, my_bool abort)
{
- free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */
+ return free_tree(tree, abort, MYF(0)); /* my_free() mem_root if applicable */
}
-void reset_tree(TREE* tree)
+int reset_tree(TREE* tree)
{
/* do not free mem_root, just mark blocks as free */
- free_tree(tree, MYF(MY_MARK_BLOCKS_FREE));
+ return free_tree(tree, 0, MYF(MY_MARK_BLOCKS_FREE));
}
-static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
+static int delete_tree_element(TREE *tree, TREE_ELEMENT *element,
+ my_bool abort)
{
+ int error, first_error= 0;
if (element != &tree->null_element)
{
- delete_tree_element(tree,element->left);
- if (tree->free)
- (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
- delete_tree_element(tree,element->right);
+ if ((first_error= delete_tree_element(tree, element->left, abort)))
+ abort= 1;
+ if (!abort && tree->free)
+ {
+ if ((error= (*tree->free)(ELEMENT_KEY(tree,element), free_free,
+ tree->custom_arg)))
+ {
+ first_error= first_error ? first_error : error;
+ abort= 1;
+ }
+ }
+ if ((error= delete_tree_element(tree, element->right, abort)))
+ first_error= first_error ? first_error : error;
if (tree->with_delete)
my_free(element);
}
+ return first_error;
}
diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c
index 2549bd8a587..8e66e0372c1 100644
--- a/mysys/waiting_threads.c
+++ b/mysys/waiting_threads.c
@@ -172,6 +172,7 @@
!! thread4 should not wait for thread2.
*/
+#include <my_global.h>
#include <waiting_threads.h>
#include <m_string.h>
@@ -617,7 +618,7 @@ retry:
{
rc= *shared_ptr;
lf_pin(arg->thd->pins, 0, rc);
- } while (rc != *shared_ptr && LF_BACKOFF);
+ } while (rc != *shared_ptr && LF_BACKOFF());
if (rc == 0)
{
diff --git a/mysys/wqueue.c b/mysys/wqueue.c
index 8bc28111655..270f1895d75 100644
--- a/mysys/wqueue.c
+++ b/mysys/wqueue.c
@@ -15,6 +15,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
+#include <my_global.h>
#include <wqueue.h>
#define STRUCT_PTR(TYPE, MEMBER, a) \