diff options
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/CMakeLists.txt | 16 | ||||
-rw-r--r-- | mysys/array.c | 43 | ||||
-rw-r--r-- | mysys/crc32/crc32_arm64.c | 28 | ||||
-rw-r--r-- | mysys/errors.c | 2 | ||||
-rw-r--r-- | mysys/mf_iocache2.c | 35 | ||||
-rw-r--r-- | mysys/mf_radix.c | 2 | ||||
-rw-r--r-- | mysys/mf_sort.c | 2 | ||||
-rw-r--r-- | mysys/my_alarm.c | 33 | ||||
-rw-r--r-- | mysys/my_alloc.c | 13 | ||||
-rw-r--r-- | mysys/my_bitmap.c | 25 | ||||
-rw-r--r-- | mysys/my_getopt.c | 2 | ||||
-rw-r--r-- | mysys/my_init.c | 44 | ||||
-rw-r--r-- | mysys/my_lock.c | 26 | ||||
-rw-r--r-- | mysys/my_malloc.c | 1 | ||||
-rw-r--r-- | mysys/my_pthread.c | 5 | ||||
-rw-r--r-- | mysys/my_static.c | 5 | ||||
-rw-r--r-- | mysys/my_symlink.c | 4 | ||||
-rw-r--r-- | mysys/my_timezone.cc | 247 | ||||
-rw-r--r-- | mysys/my_winfile.c | 63 | ||||
-rw-r--r-- | mysys/mysys_priv.h | 7 | ||||
-rw-r--r-- | mysys/thr_alarm.c | 844 | ||||
-rw-r--r-- | mysys/thr_lock.c | 46 |
22 files changed, 456 insertions, 1037 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index ab6d9edf..646a8bae 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -34,7 +34,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c my_default.c my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_basename.c my_write.c ptr_cmp.c queues.c stacktrace.c - string.c thr_alarm.c thr_lock.c thr_mutex.c + string.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 @@ -45,7 +45,8 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c my_default.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c my_rdtsc.c psi_noop.c my_atomic_writes.c my_cpu.c my_likely.c my_largepage.c - file_logger.c my_dlerror.c crc32/crc32c.cc) + file_logger.c my_dlerror.c crc32/crc32c.cc + my_timezone.cc) IF (WIN32) SET (MYSYS_SOURCES ${MYSYS_SOURCES} @@ -63,6 +64,9 @@ IF(MSVC_INTEL) IF(CMAKE_SIZEOF_VOID_P EQUAL 8) SET (MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32c_amd64.cc) ENDIF() +ELSEIF(MSVC_ARM64) + SET (MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_arm64.c) + ADD_DEFINITIONS(-DHAVE_ARMV8_CRC -DHAVE_ARMV8_CRC_CRYPTO_INTRINSICS) ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|i386|i686") SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_x86.c crc32/crc32c_x86.cc) IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "5") @@ -146,10 +150,6 @@ IF(UNIX) SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_addr_resolve.c my_setuser.c) ENDIF() -IF(HAVE_ALARM) - SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_alarm.c) -ENDIF() - IF(HAVE_MLOCK) SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_lockmem.c) ENDIF() @@ -159,7 +159,9 @@ MAYBE_DISABLE_IPO(mysys) TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARIES} ${LIBNSL} ${LIBM} ${LIBRT} ${CMAKE_DL_LIBS} ${LIBSOCKET} ${LIBEXECINFO}) DTRACE_INSTRUMENT(mysys) - +IF(WIN32) + TARGET_LINK_LIBRARIES(mysys icuuc icuin) +ENDIF() IF (HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC) TARGET_LINK_LIBRARIES(mysys atomic) ENDIF() diff --git a/mysys/array.c b/mysys/array.c index 6e871ee6..02a54d44 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -92,7 +92,7 @@ my_bool init_dynamic_array2(PSI_memory_key psi_key, DYNAMIC_ARRAY *array, my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void * element) { void *buffer; - if (array->elements == array->max_element) + if (unlikely(array->elements == array->max_element)) { /* Call only when necessary */ if (!(buffer=alloc_dynamic(array))) return TRUE; @@ -102,7 +102,42 @@ my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void * element) buffer=array->buffer+(array->elements * array->size_of_element); array->elements++; } - memcpy(buffer,element,(size_t) array->size_of_element); + memcpy(buffer, element, array->size_of_element); + return FALSE; +} + + +/* Fast version of appending to dynamic array */ + +void init_append_dynamic(DYNAMIC_ARRAY_APPEND *append, + DYNAMIC_ARRAY *array) +{ + append->array= array; + append->pos= array->buffer + array->elements * array->size_of_element; + append->end= array->buffer + array->max_element * array->size_of_element; +} + + +my_bool append_dynamic(DYNAMIC_ARRAY_APPEND *append, + const void *element) +{ + DYNAMIC_ARRAY *array= append->array; + size_t size_of_element= array->size_of_element; + if (unlikely(append->pos == append->end)) + { + void *buffer; + if (!(buffer=alloc_dynamic(array))) + return TRUE; + append->pos= (uchar*)buffer + size_of_element; + append->end= array->buffer + array->max_element * size_of_element; + memcpy(buffer, element, size_of_element); + } + else + { + array->elements++; + memcpy(append->pos, element, size_of_element); + append->pos+= size_of_element; + } return FALSE; } @@ -281,7 +316,7 @@ my_bool allocate_dynamic(DYNAMIC_ARRAY *array, size_t max_elements) void get_dynamic(DYNAMIC_ARRAY *array, void *element, size_t idx) { - if (idx >= array->elements) + if (unlikely(idx >= array->elements)) { DBUG_PRINT("warning",("To big array idx: %d, array size is %d", idx,array->elements)); @@ -306,7 +341,7 @@ void delete_dynamic(DYNAMIC_ARRAY *array) /* Just mark as empty if we are using a static buffer */ - if (!(array->malloc_flags & MY_INIT_BUFFER_USED) && array->buffer) + if (array->buffer && !(array->malloc_flags & MY_INIT_BUFFER_USED)) my_free(array->buffer); array->buffer= 0; diff --git a/mysys/crc32/crc32_arm64.c b/mysys/crc32/crc32_arm64.c index 6588606a..df7e6936 100644 --- a/mysys/crc32/crc32_arm64.c +++ b/mysys/crc32/crc32_arm64.c @@ -7,7 +7,23 @@ typedef unsigned (*my_crc32_t)(unsigned, const void *, size_t); #ifdef HAVE_ARMV8_CRC -# ifdef HAVE_ARMV8_CRYPTO +#ifdef _WIN32 +#include <windows.h> +int crc32_aarch64_available(void) +{ + return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); +} + +const char *crc32c_aarch64_available(void) +{ + if (crc32_aarch64_available() == 0) + return NULL; + /* TODO : pmull seems supported, but does not compile*/ + return "Using ARMv8 crc32 instructions"; +} +#endif /* _WIN32 */ + +#ifdef HAVE_ARMV8_CRYPTO static unsigned crc32c_aarch64_pmull(unsigned, const void *, size_t); # endif @@ -31,7 +47,8 @@ my_crc32_t crc32c_aarch64_available(void) # endif return NULL; } -# else + +# else /* __APPLE__ */ # include <sys/auxv.h> # ifdef __FreeBSD__ static unsigned long getauxval(unsigned int key) @@ -61,7 +78,7 @@ int crc32_aarch64_available(void) unsigned long auxv= getauxval(AT_HWCAP); return (auxv & HWCAP_CRC32) != 0; } -# endif +# endif /* __APPLE__ */ # ifndef __APPLE__ static unsigned crc32c_aarch64(unsigned, const void *, size_t); @@ -78,7 +95,7 @@ my_crc32_t crc32c_aarch64_available(void) # endif return crc32c_aarch64; } -# endif +# endif /* __APPLE__ */ const char *crc32c_aarch64_impl(my_crc32_t c) { @@ -123,7 +140,10 @@ asm(".arch_extension crypto"); #else /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ /* Intrinsics header*/ +#ifndef _WIN32 #include <arm_acle.h> +#endif + #include <arm_neon.h> #define CRC32CX(crc, value) (crc) = __crc32cd((crc), (value)) diff --git a/mysys/errors.c b/mysys/errors.c index a8be37bf..76ca70fc 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -60,6 +60,7 @@ const char *globerrs[GLOBERRS]= "Lock Pages in memory access rights required", "Memcntl %s cmd %s error", "Warning: Charset id '%d' csname '%s' trying to replace existing csname '%s'", + "Deprecated program name. It will be removed in a future release, use '%s' instead" }; void init_glob_errs(void) @@ -109,6 +110,7 @@ void init_glob_errs() EE(EE_PERM_LOCK_MEMORY)= "Lock Pages in memory access rights required"; EE(EE_MEMCNTL) = "Memcntl %s cmd %s error"; EE(EE_DUPLICATE_CHARSET)= "Warning: Charset id %d trying to replace csname %s with %s"; + EE(EE_NAME_DEPRECATED) = "Notice: %s is deprecated and will be removed in a future release, use command '%s'" } #endif diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 4622b686..e134524a 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -74,6 +74,41 @@ int my_b_copy_all_to_file(IO_CACHE *cache, FILE *file) DBUG_RETURN(my_b_copy_to_file(cache, file, SIZE_T_MAX)); } +/** + Similar to above my_b_copy_to_file(), but destination is another IO_CACHE. +*/ +int +my_b_copy_to_cache(IO_CACHE *from_cache, IO_CACHE *to_cache, + size_t count) +{ + size_t curr_write, bytes_in_cache; + DBUG_ENTER("my_b_copy_to_cache"); + + bytes_in_cache= my_b_bytes_in_cache(from_cache); + do + { + curr_write= MY_MIN(bytes_in_cache, count); + if (my_b_write(to_cache, from_cache->read_pos, curr_write)) + DBUG_RETURN(1); + + from_cache->read_pos += curr_write; + count -= curr_write; + } while (count && (bytes_in_cache= my_b_fill(from_cache))); + if(from_cache->error == -1) + DBUG_RETURN(1); + DBUG_RETURN(0); +} + +int my_b_copy_all_to_cache(IO_CACHE *from_cache, IO_CACHE *to_cache) +{ + DBUG_ENTER("my_b_copy_all_to_cache"); + /* Reinit the cache to read from the beginning of the cache */ + if (reinit_io_cache(from_cache, READ_CACHE, 0L, FALSE, FALSE)) + DBUG_RETURN(1); + DBUG_RETURN(my_b_copy_to_cache(from_cache, to_cache, + from_cache->end_of_file)); +} + my_off_t my_b_append_tell(IO_CACHE* info) { /* diff --git a/mysys/mf_radix.c b/mysys/mf_radix.c index 8f044cf9..89a3c4ac 100644 --- a/mysys/mf_radix.c +++ b/mysys/mf_radix.c @@ -26,7 +26,7 @@ /* Radixsort */ -my_bool radixsort_is_appliccable(uint n_items, size_t size_of_element) +my_bool radixsort_is_applicable(uint n_items, size_t size_of_element) { return size_of_element <= 20 && n_items >= 1000 && n_items < 100000; } diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c index 24e875b8..79bdfdd2 100644 --- a/mysys/mf_sort.c +++ b/mysys/mf_sort.c @@ -23,7 +23,7 @@ void my_string_ptr_sort(uchar *base, uint items, size_t size) #if INT_MAX > 65536L uchar **ptr=0; - if (radixsort_is_appliccable(items, size) && + if (radixsort_is_applicable(items, size) && (ptr= (uchar**) my_malloc(PSI_NOT_INSTRUMENTED, items * sizeof(char*),MYF(0)))) { diff --git a/mysys/my_alarm.c b/mysys/my_alarm.c deleted file mode 100644 index ee11dc9c..00000000 --- a/mysys/my_alarm.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - Use is subject to license terms - - 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 Street, Fifth Floor, Boston, MA 02110-1335 USA */ - -/* Function to set a varible when we got a alarm */ -/* Used by my_lock samt functions in m_alarm.h */ - - -#include "mysys_priv.h" -#include "my_alarm.h" - -#ifdef HAVE_ALARM - - /* ARGSUSED */ -sig_handler my_set_alarm_variable(int signo __attribute__((unused))) -{ - my_have_got_alarm=1; /* Tell program that time expired */ - return; -} - -#endif /* HAVE_ALARM */ diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 22ec265e..39c11365 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -677,3 +677,16 @@ LEX_CSTRING safe_lexcstrdup_root(MEM_ROOT *root, const LEX_CSTRING str) res.length= str.length; return res; } + + +LEX_STRING lex_string_casedn_root(MEM_ROOT *root, CHARSET_INFO *cs, + const char *str, size_t length) +{ + size_t nbytes= length * cs->cset->casedn_multiply(cs); + LEX_STRING res= {NULL, 0}; + if (!(res.str= alloc_root(root, nbytes + 1))) + return res; + res.length= cs->cset->casedn(cs, str, length, res.str, nbytes); + res.str[res.length]= '\0'; + return res; +} diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index c9bbcc4b..af102ab0 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -544,9 +544,9 @@ uint bitmap_bits_set(const MY_BITMAP *map) /** - Copy bitmaps + Copy bitmaps (if source bigger tail is left unchanged) - @param map1 to-bitmap + @param map to-bitmap @param map2 from-bitmap @notes @@ -554,18 +554,19 @@ uint bitmap_bits_set(const MY_BITMAP *map) In this case, only up to to->n_bits will be copied. */ -void bitmap_copy(MY_BITMAP *map1, const MY_BITMAP *map2) +void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) { - my_bitmap_map *to= map1->bitmap, *from= map2->bitmap; - uint map1_length= no_words_in_map(map1)*sizeof(my_bitmap_map); - uint map2_length= no_words_in_map(map2)*sizeof(my_bitmap_map); - uint length= MY_MIN(map1_length, map2_length); - DBUG_ASSERT_DIFFERENT_BITMAPS(map1,map2); + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + uint len= no_words_in_map(map), len2 = no_words_in_map(map2); + DBUG_ASSERT_DIFFERENT_BITMAPS(map, map2); - memcpy(to, from, length); - if (length < map1_length) - bzero(to + length, map1_length - length); - *map1->last_word_ptr&= ~map1->last_bit_mask; + end= to + MY_MIN(len, len2 - 1); + while (to < end) + *to++ = *from++; + + if (len2 <= len) + *to= (*from & ~map2->last_bit_mask) | (*to & map2->last_bit_mask); + *(map->last_word_ptr)&= ~map->last_bit_mask; } diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 6b480dae..449302a9 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -907,7 +907,9 @@ static int setval(const struct my_option *opts, void *value, char *argument, goto ret; }; } + validate_value(opts->name, argument, option_file); + DBUG_RETURN(0); ret: diff --git a/mysys/my_init.c b/mysys/my_init.c index 44488e58..485ce163 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -43,6 +43,13 @@ static void setup_codepages(); #define _SC_PAGESIZE _SC_PAGE_SIZE #endif +#if defined(__linux__) +#define EXE_LINKPATH "/proc/self/exe" +#elif defined(__FreeBSD__) +/* unfortunately, not mounted by default */ +#define EXE_LINKPATH "/proc/curproc/file" +#endif + extern pthread_key(struct st_my_thread_var*, THR_KEY_mysys); #define SCALE_SEC 100 @@ -169,15 +176,34 @@ my_bool my_init(void) mysql_stdin= & instrumented_stdin; my_progname_short= "unknown"; - if (my_progname) - my_progname_short= my_progname + dirname_length(my_progname); - /* Initialize our mutex handling */ my_mutex_init(); if (my_thread_global_init()) return 1; + if (my_progname) + { + char link_name[FN_REFLEN]; + my_progname_short= my_progname + dirname_length(my_progname); + /* + if my_progname_short doesn't start from "mariadb", but it's + a symlink to an actual executable, that does - warn the user. + First try to find the actual name via /proc, but if it's unmounted + (which it usually is on FreeBSD) resort to my_progname + */ + if (strncmp(my_progname_short, "mariadb", 7)) + { + int res= 1; +#ifdef EXE_LINKPATH + res= my_readlink(link_name, EXE_LINKPATH, MYF(0)); +#endif + if ((res == 0 || my_readlink(link_name, my_progname, MYF(0)) == 0) && + strncmp(link_name + dirname_length(link_name), "mariadb", 7) == 0) + my_error(EE_NAME_DEPRECATED, MYF(MY_WME), link_name); + } + } + #if defined(SAFEMALLOC) && !defined(DBUG_OFF) dbug_sanity= sf_sanity; #endif @@ -442,7 +468,7 @@ PSI_mutex_key key_LOCK_localtime_r; PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, - key_LOCK_alarm, key_LOCK_timer, + key_LOCK_timer, key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, key_THR_LOCK_lock, key_THR_LOCK_malloc, key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, @@ -461,7 +487,6 @@ static PSI_mutex_info all_mysys_mutexes[]= { &key_IO_CACHE_append_buffer_lock, "IO_CACHE::append_buffer_lock", 0}, { &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0}, { &key_KEY_CACHE_cache_lock, "KEY_CACHE::cache_lock", 0}, - { &key_LOCK_alarm, "LOCK_alarm", PSI_FLAG_GLOBAL}, { &key_LOCK_timer, "LOCK_timer", PSI_FLAG_GLOBAL}, { &key_my_thread_var_mutex, "my_thread_var::mutex", 0}, { &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL}, @@ -478,13 +503,12 @@ static PSI_mutex_info all_mysys_mutexes[]= { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL } }; -PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond, +PSI_cond_key key_COND_timer, key_IO_CACHE_SHARE_cond, key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend, key_THR_COND_threads, key_WT_RESOURCE_cond; static PSI_cond_info all_mysys_conds[]= { - { &key_COND_alarm, "COND_alarm", PSI_FLAG_GLOBAL}, { &key_COND_timer, "COND_timer", PSI_FLAG_GLOBAL}, { &key_IO_CACHE_SHARE_cond, "IO_CACHE_SHARE::cond", 0}, { &key_IO_CACHE_SHARE_cond_writer, "IO_CACHE_SHARE::cond_writer", 0}, @@ -500,16 +524,10 @@ static PSI_rwlock_info all_mysys_rwlocks[]= { &key_SAFEHASH_mutex, "SAFE_HASH::mutex", 0} }; -#ifdef USE_ALARM_THREAD -PSI_thread_key key_thread_alarm; -#endif PSI_thread_key key_thread_timer; static PSI_thread_info all_mysys_threads[]= { -#ifdef USE_ALARM_THREAD - { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL}, -#endif { &key_thread_timer, "statement_timer", PSI_FLAG_GLOBAL} }; diff --git a/mysys/my_lock.c b/mysys/my_lock.c index 7597436f..35e159dd 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -16,12 +16,8 @@ #include "mysys_priv.h" #include "mysys_err.h" #include <errno.h> -#undef MY_HOW_OFTEN_TO_ALARM -#define MY_HOW_OFTEN_TO_ALARM ((int) my_time_to_wait_for_lock) -#ifdef NO_ALARM_LOOP -#undef NO_ALARM_LOOP -#endif -#include <my_alarm.h> +/* Wait timeout for short lock (2 seconds) */ +#define NANOSECONDS_TO_WAIT_FOR_LOCK 2000000000ULL #ifdef _WIN32 #define WIN_LOCK_INFINITE -1 @@ -139,7 +135,6 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, { #ifdef HAVE_FCNTL int value; - ALARM_VARIABLES; #endif DBUG_ENTER("my_lock"); @@ -171,6 +166,7 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, if (MyFlags & (MY_NO_WAIT | MY_SHORT_WAIT)) { + ulonglong end_time; if (fcntl(fd,F_SETLK,&lock) != -1) /* Check if we can lock */ DBUG_RETURN(0); /* Ok, file locked */ if (MyFlags & MY_NO_WAIT) @@ -179,14 +175,16 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, DBUG_RETURN(-1); } - DBUG_PRINT("info",("Was locked, trying with alarm")); - ALARM_INIT; - while ((value=fcntl(fd,F_SETLKW,&lock)) && ! ALARM_TEST && - errno == EINTR) - { /* Setup again so we don`t miss it */ - ALARM_REINIT; + DBUG_PRINT("info",("Was locked, trying with timeout")); + end_time= my_interval_timer() + NANOSECONDS_TO_WAIT_FOR_LOCK; + while ((value= fcntl(fd, F_SETLKW, &lock)) == -1) + { + if (errno != EACCES && errno != EAGAIN && errno != EINTR) + break; + if (my_interval_timer() > end_time) + break; + my_sleep(1000); } - ALARM_END; if (value != -1) DBUG_RETURN(0); if (errno == EINTR) diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index 5a5ed6c8..64c888ff 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -66,6 +66,7 @@ void set_malloc_size_cb(MALLOC_SIZE_CB func) @return A pointer to the allocated memory block, or NULL on failure. */ +ATTRIBUTE_MALLOC void *my_malloc(PSI_memory_key key, size_t size, myf my_flags) { my_memory_header *mh; diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 9bedfe36..d29bbe60 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -20,7 +20,6 @@ #include "mysys_priv.h" #include <signal.h> #include <m_string.h> -#include <thr_alarm.h> #include <my_pthread.h> #if (defined(__BSD__) || defined(_BSDI_VERSION)) @@ -234,11 +233,7 @@ void *sigwait_thread(void *set_arg) sigaction(i, &sact, (struct sigaction*) 0); } } - /* Ensure that init_thr_alarm() is called */ - DBUG_ASSERT(thr_client_alarm); - sigaddset(set, thr_client_alarm); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); - alarm_thread=pthread_self(); /* For thr_alarm */ for (;;) { /* Wait for signals */ diff --git a/mysys/my_static.c b/mysys/my_static.c index d0f20a5c..35e67693 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -21,8 +21,6 @@ #include "mysys_priv.h" #include "my_static.h" -#include "my_alarm.h" - PSI_memory_key key_memory_DYNAMIC_STRING; PSI_memory_key key_memory_IO_CACHE; @@ -95,9 +93,6 @@ const char *soundex_map= "01230120022455012623010202"; USED_MEM* my_once_root_block=0; /* pointer to first block */ uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */ - /* from my_alarm */ -int volatile my_have_got_alarm=0; /* declare variable to reset */ -ulong my_time_to_wait_for_lock=2; /* In seconds */ /* from errors.c */ #ifdef SHARED_LIBRARY diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index 8238e501..a07f67a1 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -45,7 +45,7 @@ int (*mysys_test_invalid_symlink)(const char *filename)= always_valid; int my_readlink(char *to, const char *filename, myf MyFlags) { #ifndef HAVE_READLINK - strmov(to,filename); + strnmov(to, filename, FN_REFLEN); return 1; #else int result=0; @@ -58,7 +58,7 @@ int my_readlink(char *to, const char *filename, myf MyFlags) if ((my_errno=errno) == EINVAL) { result= 1; - strmov(to,filename); + strnmov(to, filename, FN_REFLEN); } else { diff --git a/mysys/my_timezone.cc b/mysys/my_timezone.cc new file mode 100644 index 00000000..d155f014 --- /dev/null +++ b/mysys/my_timezone.cc @@ -0,0 +1,247 @@ +/* + Copyright (c) 2023 MariaDB + + 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-1335 USA */ + +#include <config.h> +#include <my_global.h> +#include <my_sys.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#ifdef _WIN32 +#include <icu.h> +#include <objbase.h> +#define MAX_TZ_ABBR 64 + +static bool use_icu_for_tzinfo; + +/* + Retrieve GMT offset and timezone abbreviation using ICU. +*/ +static void icu_get_tzinfo(time_t t, my_tz* tz) +{ + UErrorCode status= U_ZERO_ERROR; + const char *locale= nullptr; + UCalendar* cal= ucal_open(nullptr, -1, locale, UCAL_GREGORIAN, &status); + ucal_setMillis(cal, 1000.0 * t, &status); + int32_t zone_offset= ucal_get(cal, UCAL_ZONE_OFFSET, &status); + int32_t dst_offset= ucal_get(cal, UCAL_DST_OFFSET, &status); + tz->seconds_offset= (zone_offset + dst_offset) / 1000; + + UChar u_tz_abbr[MAX_TZ_ABBR]; + ucal_getTimeZoneDisplayName(cal, + dst_offset ? UCAL_SHORT_DST : UCAL_SHORT_STANDARD, + locale, u_tz_abbr, MAX_TZ_ABBR, &status); + ucal_close(cal); + size_t num; + wcstombs_s(&num, tz->abbreviation, sizeof(tz->abbreviation), + (wchar_t *) u_tz_abbr, sizeof(u_tz_abbr)); +} + +#define MAX_TIMEZONE_LEN 128 + +/* + Synchronizes C runtime timezone with ICU timezone. + + Must be called after tzset(). + + If TZ environment variable is set, tries to find ICU + timezone matching the variable value.If such timezone + is found, it is set as default timezone for ICU. + + @return 0 success + -1 otherwise +*/ +static int sync_icu_timezone() +{ + const char *tz_env= getenv("TZ"); + UErrorCode ec= U_ZERO_ERROR; + UEnumeration *en= nullptr; + int ret= -1; + + if (!tz_env) + { + /* TZ environment variable not set - use default timezone*/ + return 0; + } + + int timezone_offset_ms = -1000 * _timezone; + int dst_offset_ms = -1000 * _dstbias *(_daylight != 0); + + /* + Find ICU timezone with the same UTC and DST offsets + and name as C runtime. + */ + en= ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, nullptr, + &timezone_offset_ms, &ec); + if (U_FAILURE(ec)) + return -1; + + for (;;) + { + int32_t len; + const char *tzid= uenum_next(en, &len, &ec); + if (U_FAILURE(ec)) + break; + + if (!tzid) + break; + UChar u_tzid[MAX_TIMEZONE_LEN]; + u_uastrncpy(u_tzid, tzid, MAX_TIMEZONE_LEN); + int32_t dst_savings= ucal_getDSTSavings(u_tzid, &ec); + if (U_FAILURE(ec)) + break; + + if (dst_savings == dst_offset_ms) + { + if (tz_env && !strcmp(tzid, tz_env)) + { + /* + Found timezone ID that matches TZ env.var + exactly, e.g PST8PDT + */ + UChar u_tzid[MAX_TIMEZONE_LEN]; + u_uastrncpy(u_tzid, tzid, MAX_TIMEZONE_LEN); + ucal_setDefaultTimeZone(u_tzid, &ec); + ret= 0; + break; + } + } + } + uenum_close(en); + return ret; +} +#endif /* _WIN32 */ + +/** + Initialize time conversion information + + @param[out] sys_timezone name of the current timezone + @param[in] sys_timezone_len length of the 'sys_timezone' buffer + +*/ +extern "C" void my_tzset() +{ + tzset(); +#ifdef _WIN32 + /* + CoInitializeEx is needed by ICU on older Windows 10, until + version 1903. + */ + (void) CoInitializeEx(NULL, COINITBASE_MULTITHREADED); + use_icu_for_tzinfo= !sync_icu_timezone(); +#endif +} + +/** + Retrieve current timezone name + @param[out] sys_timezone - buffer to receive timezone name + @param[in] size - size of sys_timezone buffer +*/ +extern "C" void my_tzname(char* sys_timezone, size_t size) +{ +#ifdef _WIN32 + if (use_icu_for_tzinfo) + { + /* TZ environment variable not set - return default timezone name*/ + UChar default_tzname[MAX_TIMEZONE_LEN]; + UErrorCode ec; + int32_t len= + ucal_getDefaultTimeZone(default_tzname, MAX_TIMEZONE_LEN, &ec); + if (U_SUCCESS(ec)) + { + u_austrncpy(sys_timezone, default_tzname, (int32_t) size); + return; + } + use_icu_for_tzinfo= false; + } +#endif + struct tm tm; + time_t t; + tzset(); + t= time(NULL); + localtime_r(&t, &tm); + const char *tz_name= tzname[tm.tm_isdst != 0 ? 1 : 0]; + snprintf(sys_timezone, size, "%s", tz_name); +} + +#ifndef STRUCT_TM_HAS_TM_GMTOFF +/* + Portable timegm() + + Based on http://howardhinnant.github.io/date_algorithms.html + by Howard Hinnant, of the C++ <chrono> library fame. +*/ + +/** Returns number of days since Unix epoch. */ +static int days_from_epoch(int y, int m, int d) +{ + y-= m <= 2; + int era= y / 400; + int yoe= y - era * 400; // [0, 399] + int doy= (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365] + int doe= yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096] + return era * 146097 + doe - 719468; +} + +/** + Converts a UTC time represented by a struct tm to time_t. + + Unlike libc's timegm() or Windows' _mkgmtime(), this function + does not modify the input struct. +*/ +static time_t my_timegm(const struct tm *t) +{ + longlong days, hours, minutes, seconds; + days= (longlong) days_from_epoch(t->tm_year+1900, t->tm_mon+1, t->tm_mday); + hours= 24LL * days + t->tm_hour; + minutes= 60LL * hours + t->tm_min; + seconds= 60LL * minutes + t->tm_sec; + return (time_t) seconds; +} +#endif /* STRUCT_TM_HAS_TM_GMTOFF */ + +/** + Return timezone information (GMT offset, timezone abbreviation) + corresponding to specific timestamp. + + @param[in] t timestamp (seconds since Unix epoch) + @param[out] gmt_offset offset from GMT, in seconds + @param[out] abbr buffer to receive time zone abbreviation + @param[in] abbr_size size of the abbr buffer +*/ +void my_tzinfo(time_t t, struct my_tz* tz) +{ +#ifdef _WIN32 + if (use_icu_for_tzinfo) + { + icu_get_tzinfo(t, tz); + return; + } +#endif + + struct tm loc_time; + localtime_r(&t, &loc_time); +#ifdef STRUCT_TM_HAS_TM_GMTOFF + tz->seconds_offset= loc_time.tm_gmtoff; + snprintf(tz->abbreviation, sizeof(tz->abbreviation), "%s", loc_time.tm_zone); +#else + tz->seconds_offset= (long) (my_timegm(&loc_time) - t); + int is_dst= loc_time.tm_isdst ? 1 : 0; + snprintf(tz->abbreviation, sizeof(tz->abbreviation), "%s", tzname[is_dst]); +#endif +} diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c index 35bc6b35..7a1e3e60 100644 --- a/mysys/my_winfile.c +++ b/mysys/my_winfile.c @@ -89,17 +89,15 @@ static void invalidate_fd(File fd) /* Get Windows handle for a file descriptor */ HANDLE my_get_osfhandle(File fd) { - DBUG_ENTER("my_get_osfhandle"); DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); - DBUG_RETURN(my_file_info[fd].fhandle); + return (my_file_info[fd].fhandle); } static int my_get_open_flags(File fd) { - DBUG_ENTER("my_get_open_flags"); DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); - DBUG_RETURN(my_file_info[fd].oflag); + return (my_file_info[fd].oflag); } /* @@ -347,10 +345,8 @@ size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset) OVERLAPPED ov= {0}; LARGE_INTEGER li; - DBUG_ENTER("my_win_pread"); - if(!Count) - DBUG_RETURN(0); + return(0); #ifdef _WIN64 if(Count > UINT_MAX) Count= UINT_MAX; @@ -369,11 +365,11 @@ size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset) through e.g. a command pipe in windows : see MSDN on ReadFile. */ if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) - DBUG_RETURN(0); /*return 0 at EOF*/ + return(0); /*return 0 at EOF*/ my_osmaperr(lastError); - DBUG_RETURN((size_t)-1); + return((size_t)-1); } - DBUG_RETURN(nBytesRead); + return(nBytesRead); } @@ -382,9 +378,8 @@ size_t my_win_read(File Filedes, uchar *Buffer, size_t Count) DWORD nBytesRead; HANDLE hFile; - DBUG_ENTER("my_win_read"); if(!Count) - DBUG_RETURN(0); + return(0); #ifdef _WIN64 if(Count > UINT_MAX) Count= UINT_MAX; @@ -400,11 +395,11 @@ size_t my_win_read(File Filedes, uchar *Buffer, size_t Count) through e.g. a command pipe in windows : see MSDN on ReadFile. */ if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) - DBUG_RETURN(0); /*return 0 at EOF*/ + return(0); /*return 0 at EOF*/ my_osmaperr(lastError); - DBUG_RETURN((size_t)-1); + return((size_t)-1); } - DBUG_RETURN(nBytesRead); + return(nBytesRead); } @@ -416,12 +411,8 @@ size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count, OVERLAPPED ov= {0}; LARGE_INTEGER li; - DBUG_ENTER("my_win_pwrite"); - DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %llu, offset: %llu", - Filedes, Buffer, (ulonglong)Count, (ulonglong)offset)); - if(!Count) - DBUG_RETURN(0); + return(0); #ifdef _WIN64 if(Count > UINT_MAX) @@ -436,10 +427,10 @@ size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count, if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov)) { my_osmaperr(GetLastError()); - DBUG_RETURN((size_t)-1); + return((size_t)-1); } else - DBUG_RETURN(nBytesWritten); + return(nBytesWritten); } @@ -448,11 +439,9 @@ my_off_t my_win_lseek(File fd, my_off_t pos, int whence) LARGE_INTEGER offset; LARGE_INTEGER newpos; - DBUG_ENTER("my_win_lseek"); - /* Check compatibility of Windows and Posix seek constants */ - compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR - && FILE_END == SEEK_END); + compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR && + FILE_END == SEEK_END); offset.QuadPart= pos; if(!SetFilePointerEx(my_get_osfhandle(fd), offset, &newpos, whence)) @@ -460,7 +449,7 @@ my_off_t my_win_lseek(File fd, my_off_t pos, int whence) my_osmaperr(GetLastError()); newpos.QuadPart= -1; } - DBUG_RETURN(newpos.QuadPart); + return(newpos.QuadPart); } @@ -474,12 +463,8 @@ size_t my_win_write(File fd, const uchar *Buffer, size_t Count) OVERLAPPED *pov= NULL; HANDLE hFile; - DBUG_ENTER("my_win_write"); - DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer, - (ulonglong)Count)); - if(!Count) - DBUG_RETURN(0); + return(0); #ifdef _WIN64 if(Count > UINT_MAX) @@ -502,9 +487,9 @@ size_t my_win_write(File fd, const uchar *Buffer, size_t Count) if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov)) { my_osmaperr(GetLastError()); - DBUG_RETURN((size_t)-1); + return((size_t)-1); } - DBUG_RETURN(nWritten); + return(nWritten); } @@ -512,7 +497,6 @@ int my_win_chsize(File fd, my_off_t newlength) { HANDLE hFile; LARGE_INTEGER length; - DBUG_ENTER("my_win_chsize"); hFile= (HANDLE) my_get_osfhandle(fd); length.QuadPart= newlength; @@ -520,11 +504,11 @@ int my_win_chsize(File fd, my_off_t newlength) goto err; if (!SetEndOfFile(hFile)) goto err; - DBUG_RETURN(0); + return(0); err: my_osmaperr(GetLastError()); my_errno= errno; - DBUG_RETURN(-1); + return(-1); } @@ -555,7 +539,6 @@ File my_win_handle2File(HANDLE hFile) { int retval= -1; uint i; - DBUG_ENTER("my_win_handle2File"); for(i= MY_FILE_MIN; i < my_file_limit; i++) @@ -623,7 +606,6 @@ FILE * my_win_fdopen(File fd, const char *type) FILE *file; int crt_fd; int flags= 0; - DBUG_ENTER("my_win_fdopen"); if(strchr(type,'a') != NULL) @@ -641,8 +623,8 @@ FILE * my_win_fdopen(File fd, const char *type) int my_win_fclose(FILE *file) { File fd; - DBUG_ENTER("my_win_fclose"); + fd= my_fileno(file); if(fd < 0) DBUG_RETURN(-1); @@ -665,7 +647,6 @@ int my_win_fstat(File fd, struct _stati64 *buf) int crt_fd; int retval; HANDLE hFile, hDup; - DBUG_ENTER("my_win_fstat"); hFile= my_get_osfhandle(fd); diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index e795dbe2..efeb0c65 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -43,20 +43,17 @@ extern PSI_mutex_key key_LOCK_localtime_r; #endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, - key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm, + key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, key_THR_LOCK_lock, key_THR_LOCK_malloc, key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, key_THR_LOCK_open, key_THR_LOCK_threads, key_LOCK_uuid_generator, key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_timer; -extern PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond, +extern PSI_cond_key key_COND_timer, key_IO_CACHE_SHARE_cond, key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend, key_THR_COND_threads; -#ifdef USE_ALARM_THREAD -extern PSI_thread_key key_thread_alarm; -#endif /* USE_ALARM_THREAD */ extern PSI_thread_key key_thread_timer; extern PSI_rwlock_key key_SAFEHASH_mutex; diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c deleted file mode 100644 index 4e2db203..00000000 --- a/mysys/thr_alarm.c +++ /dev/null @@ -1,844 +0,0 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates - Copyright (c) 2012, 2014, SkySQL 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-1335 USA */ - -/* To avoid problems with alarms in debug code, we disable DBUG here */ -#define FORCE_DBUG_OFF -#include "mysys_priv.h" -#include <my_global.h> - -#if !defined(DONT_USE_THR_ALARM) -#include <errno.h> -#include <my_pthread.h> -#include <signal.h> -#include <my_sys.h> -#include <m_string.h> -#include <queues.h> -#include "thr_alarm.h" - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> /* AIX needs this for fd_set */ -#endif - -#ifndef ETIME -#define ETIME ETIMEDOUT -#endif - -#ifdef DBUG_OFF -#define reset_index_in_queue(alarm_data) -#else -#define reset_index_in_queue(alarm_data) alarm_data->index_in_queue= 0; -#endif /* DBUG_OFF */ - -#ifndef USE_ONE_SIGNAL_HAND -#define one_signal_hand_sigmask(A,B,C) pthread_sigmask((A), (B), (C)) -#else -#define one_signal_hand_sigmask(A,B,C) -#endif - -my_bool thr_alarm_inited= 0, my_disable_thr_alarm= 0; - -#if !defined(_WIN32) - -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; -static QUEUE alarm_queue; -static uint max_used_alarms=0; -pthread_t alarm_thread; - -#define MY_THR_ALARM_QUEUE_EXTENT 10 - -#ifdef USE_ALARM_THREAD -static void *alarm_handler(void *arg); -#define reschedule_alarms() mysql_cond_signal(&COND_alarm) -#else -#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) -#endif - -static sig_handler thread_alarm(int sig __attribute__((unused))); - -static int compare_ulong(void *not_used __attribute__((unused)), - uchar *a_ptr,uchar* b_ptr) -{ - ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr); - return (a < b) ? -1 : (a == b) ? 0 : 1; -} - -void init_thr_alarm(uint max_alarms) -{ - sigset_t s; - DBUG_ENTER("init_thr_alarm"); - alarm_aborted=0; - next_alarm_expire_time= ~ (time_t) 0; - init_queue(&alarm_queue, max_alarms+1, offsetof(ALARM,expire_time), 0, - compare_ulong, NullS, offsetof(ALARM, index_in_queue)+1, - MY_THR_ALARM_QUEUE_EXTENT); - sigfillset(&full_signal_set); /* Neaded to block signals */ - mysql_mutex_init(key_LOCK_alarm, &LOCK_alarm, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_alarm, &COND_alarm, NULL); - thr_client_alarm= SIGUSR1; - my_sigset(thr_client_alarm, thread_alarm); - sigemptyset(&s); - sigaddset(&s, THR_SERVER_ALARM); - alarm_thread=pthread_self(); -#if defined(USE_ALARM_THREAD) - { - pthread_attr_t thr_attr; - pthread_attr_init(&thr_attr); - pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - mysql_thread_create(key_thread_alarm, - &alarm_thread, &thr_attr, alarm_handler, NULL); - pthread_attr_destroy(&thr_attr); - } -#elif defined(USE_ONE_SIGNAL_HAND) - pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ -#else - my_sigset(THR_SERVER_ALARM, process_alarm); - pthread_sigmask(SIG_UNBLOCK, &s, NULL); -#endif - DBUG_VOID_RETURN; -} - - -void resize_thr_alarm(uint max_alarms) -{ - mysql_mutex_lock(&LOCK_alarm); - /* - It's ok not to shrink the queue as there may be more pending alarms than - than max_alarms - */ - if (alarm_queue.elements < max_alarms) - { - resize_queue(&alarm_queue,max_alarms+1); - max_used_alarms= alarm_queue.elements; - } - mysql_mutex_unlock(&LOCK_alarm); -} - - -/* - Request alarm after sec seconds. - - SYNOPSIS - thr_alarm() - alrm Pointer to alarm detection - alarm_data Structure to store in alarm queue - - NOTES - This function can't be called from the alarm-handling thread. - - RETURN VALUES - 0 ok - 1 If no more alarms are allowed (aborted by process) - - Stores in first argument a pointer to a non-zero int which is set to 0 - when the alarm has been given -*/ - -my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) -{ - time_t now, next; -#ifndef USE_ONE_SIGNAL_HAND - sigset_t old_mask; -#endif - my_bool reschedule; - struct st_my_thread_var *current_my_thread_var= my_thread_var; - DBUG_ENTER("thr_alarm"); - DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec)); - - if (my_disable_thr_alarm) - { - (*alrm)= &alarm_data->alarmed; - alarm_data->alarmed= 1; /* Abort if interrupted */ - DBUG_RETURN(0); - } - - if (unlikely(alarm_aborted)) - { /* No signal thread */ - DBUG_PRINT("info", ("alarm aborted")); - if (alarm_aborted > 0) - goto abort_no_unlock; - sec= 1; /* Abort mode */ - } - - now= my_time(0); - if (!alarm_data) - { - if (!(alarm_data=(ALARM*) my_malloc(PSI_INSTRUMENT_ME, sizeof(ALARM), - MYF(MY_WME)))) - goto abort_no_unlock; - alarm_data->malloced= 1; - } - else - alarm_data->malloced= 0; - next= now + sec; - alarm_data->expire_time= next; - alarm_data->alarmed= 0; - alarm_data->thread= current_my_thread_var->pthread_self; - alarm_data->thread_id= current_my_thread_var->id; - - one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); - mysql_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ - if (alarm_queue.elements >= max_used_alarms) - { - max_used_alarms=alarm_queue.elements+1; - } - reschedule= (ulong) next_alarm_expire_time > (ulong) next; - queue_insert_safe(&alarm_queue, (uchar*) alarm_data); - assert(alarm_data->index_in_queue > 0); - - /* Reschedule alarm if the current one has more than sec left */ - if (unlikely(reschedule)) - { - DBUG_PRINT("info", ("reschedule")); - if (pthread_equal(pthread_self(),alarm_thread)) - { - alarm(sec); /* purecov: inspected */ - next_alarm_expire_time= next; - } - else - reschedule_alarms(); /* Reschedule alarms */ - } - mysql_mutex_unlock(&LOCK_alarm); - one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); - (*alrm)= &alarm_data->alarmed; - DBUG_RETURN(0); - -abort_no_unlock: - *alrm= 0; /* No alarm */ - DBUG_RETURN(1); -} - - -/* - Remove alarm from list of alarms -*/ - -void thr_end_alarm(thr_alarm_t *alarmed) -{ - ALARM *alarm_data; -#ifndef USE_ONE_SIGNAL_HAND - sigset_t old_mask; -#endif - DBUG_ENTER("thr_end_alarm"); - - if (my_disable_thr_alarm) - DBUG_VOID_RETURN; - one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); - alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed)); - mysql_mutex_lock(&LOCK_alarm); - DBUG_ASSERT(alarm_data->index_in_queue != 0); - 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); - one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); - reset_index_in_queue(alarm_data); - DBUG_VOID_RETURN; -} - -/* - Come here when some alarm in queue is due. - Mark all alarms with are finnished in list. - Schedule alarms to be sent again after 1-10 sec (many alarms at once) - If alarm_aborted is set then all alarms are given and resent - every second. -*/ - -sig_handler process_alarm(int sig __attribute__((unused))) -{ - sigset_t old_mask; -/* - This must be first as we can't call DBUG inside an alarm for a normal thread -*/ - - /* - We have to do do the handling of the alarm in a sub function, - because otherwise we would get problems with two threads calling - DBUG_... functions at the same time (as two threads may call - process_alarm() at the same time - */ - -#ifndef USE_ALARM_THREAD - pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask); - mysql_mutex_lock(&LOCK_alarm); -#endif - process_alarm_part2(sig); -#ifndef USE_ALARM_THREAD -#if defined(SIGNAL_HANDLER_RESET_ON_DELIVERY) && !defined(USE_ONE_SIGNAL_HAND) - my_sigset(THR_SERVER_ALARM,process_alarm); -#endif - mysql_mutex_unlock(&LOCK_alarm); - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - return; -} - - -static sig_handler process_alarm_part2(int sig __attribute__((unused))) -{ - ALARM *alarm_data; - DBUG_ENTER("process_alarm"); - DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements)); - -#if defined(MAIN) && !defined(__bsdi__) - printf("process_alarm\n"); fflush(stdout); -#endif - if (likely(alarm_queue.elements)) - { - if (unlikely(alarm_aborted)) - { - uint i; - for (i= queue_first_element(&alarm_queue) ; - i <= queue_last_element(&alarm_queue) ;) - { - alarm_data=(ALARM*) queue_element(&alarm_queue,i); - alarm_data->alarmed=1; /* Info to thread */ - if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, thr_client_alarm)) - { -#ifdef MAIN - printf("Warning: pthread_kill couldn't find thread!!!\n"); -#endif - queue_remove(&alarm_queue,i); /* No thread. Remove alarm */ - reset_index_in_queue(alarm_data); - } - else - i++; /* Signal next thread */ - } -#ifndef USE_ALARM_THREAD - if (alarm_queue.elements) - alarm(1); /* Signal soon again */ -#endif - } - else - { - time_t now= my_time(0); - time_t next= now+10-(now%10); - while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now) - { - alarm_data->alarmed=1; /* Info to thread */ - DBUG_PRINT("info",("sending signal to waiting thread")); - if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, thr_client_alarm)) - { -#ifdef MAIN - printf("Warning: pthread_kill couldn't find thread!!!\n"); -#endif /* MAIN */ - queue_remove_top(&alarm_queue); /* No thread. Remove alarm */ - reset_index_in_queue(alarm_data); - if (!alarm_queue.elements) - break; - } - else - { - alarm_data->expire_time=next; - queue_replace_top(&alarm_queue); - } - } -#ifndef USE_ALARM_THREAD - if (alarm_queue.elements) - { -#ifdef __bsdi__ - alarm(0); /* Remove old alarm */ -#endif - alarm((uint) (alarm_data->expire_time-now)); - next_alarm_expire_time= alarm_data->expire_time; - } -#endif - } - } - else - { - /* - Ensure that next time we call thr_alarm(), we will schedule a new alarm - */ - next_alarm_expire_time= ~(time_t) 0; - } - DBUG_VOID_RETURN; -} - - -/* - Schedule all alarms now and optionally free all structures - - SYNPOSIS - end_thr_alarm() - free_structures Set to 1 if we should free memory used for - the alarm queue. - When we call this we should KNOW that there - is no active alarms - IMPLEMENTATION - Set alarm_abort to -1 which will change the behavior of alarms as follows: - - All old alarms will be rescheduled at once - - All new alarms will be rescheduled to one second -*/ - -void end_thr_alarm(my_bool free_structures) -{ - DBUG_ENTER("end_thr_alarm"); - if (alarm_aborted != 1) /* If memory not freed */ - { - mysql_mutex_lock(&LOCK_alarm); - DBUG_PRINT("info",("Rescheduling %d waiting alarms",alarm_queue.elements)); - alarm_aborted= -1; /* mark aborted */ - if (alarm_queue.elements || (alarm_thread_running && free_structures)) - { - if (pthread_equal(pthread_self(),alarm_thread)) - alarm(1); /* Shut down everything soon */ - else - reschedule_alarms(); - } - if (free_structures) - { - struct timespec abstime; - - DBUG_ASSERT(!alarm_queue.elements); - - /* Wait until alarm thread dies */ - set_timespec(abstime, 10); /* Wait up to 10 seconds */ - while (alarm_thread_running) - { - int error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime); - if (error == ETIME || error == ETIMEDOUT) - break; /* Don't wait forever */ - } - delete_queue(&alarm_queue); - alarm_aborted= 1; - mysql_mutex_unlock(&LOCK_alarm); - if (!alarm_thread_running) /* Safety */ - { - mysql_mutex_destroy(&LOCK_alarm); - mysql_cond_destroy(&COND_alarm); - } - } - else - mysql_mutex_unlock(&LOCK_alarm); - } - DBUG_VOID_RETURN; -} - - -/* - Remove another thread from the alarm -*/ - -void thr_alarm_kill(my_thread_id thread_id) -{ - uint i; - DBUG_ENTER("thr_alarm_kill"); - - if (alarm_aborted) - return; - mysql_mutex_lock(&LOCK_alarm); - for (i= queue_first_element(&alarm_queue) ; - i <= queue_last_element(&alarm_queue); - i++) - { - ALARM *element= (ALARM*) queue_element(&alarm_queue,i); - if (element->thread_id == thread_id) - { - DBUG_PRINT("info", ("found thread; Killing it")); - element->expire_time= 0; - queue_replace(&alarm_queue, i); - reschedule_alarms(); - break; - } - } - mysql_mutex_unlock(&LOCK_alarm); - DBUG_VOID_RETURN; -} - - -void thr_alarm_info(ALARM_INFO *info) -{ - mysql_mutex_lock(&LOCK_alarm); - info->next_alarm_time= 0; - info->max_used_alarms= max_used_alarms; - if ((info->active_alarms= alarm_queue.elements)) - { - time_t now= my_time(0); - long time_diff; - ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue); - time_diff= (long) (alarm_data->expire_time - now); - info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff); - } - mysql_mutex_unlock(&LOCK_alarm); -} - -/* - This is here for thread to get interruptet from read/write/fcntl - ARGSUSED -*/ - - -static sig_handler thread_alarm(int sig __attribute__((unused))) -{ -#ifdef MAIN - printf("thread_alarm\n"); fflush(stdout); -#endif -#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY - my_sigset(sig,thread_alarm); /* int. thread system calls */ -#endif -} - - -#ifdef HAVE_TIMESPEC_TS_SEC -#define tv_sec ts_sec -#define tv_nsec ts_nsec -#endif - -/* set up a alarm thread with uses 'sleep' to sleep between alarms */ - -#ifdef USE_ALARM_THREAD -static void *alarm_handler(void *arg __attribute__((unused))) -{ - int error; - struct timespec abstime; -#ifdef MAIN - puts("Starting alarm thread"); -#endif - my_thread_init(); - alarm_thread_running= 1; - mysql_mutex_lock(&LOCK_alarm); - for (;;) - { - if (alarm_queue.elements) - { - time_t sleep_time,now= my_time(0); - if (alarm_aborted) - sleep_time=now+1; - else - sleep_time= ((ALARM*) queue_top(&alarm_queue))->expire_time; - if (sleep_time > now) - { - abstime.tv_sec=sleep_time; - abstime.tv_nsec=0; - next_alarm_expire_time= sleep_time; - if ((error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime)) && - error != ETIME && error != ETIMEDOUT) - { -#ifdef MAIN - printf("Got error: %d from ptread_cond_timedwait (errno: %d)\n", - error,errno); -#endif - } - } - } - else if (alarm_aborted == -1) - break; - else - { - next_alarm_expire_time= ~ (time_t) 0; - if ((error= mysql_cond_wait(&COND_alarm, &LOCK_alarm))) - { -#ifdef MAIN - printf("Got error: %d from ptread_cond_wait (errno: %d)\n", - error,errno); -#endif - } - } - process_alarm(0); - } - bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */ - alarm_thread_running= 0; - mysql_cond_signal(&COND_alarm); - mysql_mutex_unlock(&LOCK_alarm); - pthread_exit(0); - return 0; /* Impossible */ -} -#endif /* USE_ALARM_THREAD */ -#endif - -/**************************************************************************** - Handling of test case (when compiled with -DMAIN) -***************************************************************************/ - -#ifdef MAIN -#if !defined(DONT_USE_THR_ALARM) - -static mysql_cond_t COND_thread_count; -static mysql_mutex_t LOCK_thread_count; -static uint thread_count; - -#ifdef HPUX10 -typedef int * fd_set_ptr; -#else -typedef fd_set * fd_set_ptr; -#endif /* HPUX10 */ - -static void *test_thread(void *arg) -{ - int i,param=*((int*) arg),wait_time,retry; - time_t start_time; - thr_alarm_t got_alarm; - fd_set fd; - FD_ZERO(&fd); - my_thread_init(); - printf("Thread %d (%s) started\n",param,my_thread_name()); fflush(stdout); - for (i=1 ; i <= 10 ; i++) - { - wait_time=param ? 11-i : i; - start_time= my_time(0); - if (thr_alarm(&got_alarm,wait_time,0)) - { - printf("Thread: %s Alarms aborted\n",my_thread_name()); - break; - } - if (wait_time == 3) - { - printf("Thread: %s Simulation of no alarm needed\n",my_thread_name()); - fflush(stdout); - } - else - { - for (retry=0 ; !thr_got_alarm(&got_alarm) && retry < 10 ; retry++) - { - printf("Thread: %s Waiting %d sec\n",my_thread_name(),wait_time); - select(0,(fd_set_ptr) &fd,0,0,0); - } - if (!thr_got_alarm(&got_alarm)) - { - printf("Thread: %s didn't get an alarm. Aborting!\n", - my_thread_name()); - break; - } - if (wait_time == 7) - { /* Simulate alarm-miss */ - fd_set readFDs; - uint max_connection=fileno(stdin); - FD_ZERO(&readFDs); - FD_SET(max_connection,&readFDs); - retry=0; - for (;;) - { - printf("Thread: %s Simulating alarm miss\n",my_thread_name()); - fflush(stdout); - if (select(max_connection+1, (fd_set_ptr) &readFDs,0,0,0) < 0) - { - if (errno == EINTR) - break; /* Got new interrupt */ - printf("Got errno: %d from select. Retrying..\n",errno); - if (retry++ >= 3) - { - printf("Warning: Interrupt of select() doesn't set errno!\n"); - break; - } - } - else /* This shouldn't happen */ - { - if (!FD_ISSET(max_connection,&readFDs)) - { - printf("Select interrupted, but errno not set\n"); - fflush(stdout); - if (retry++ >= 3) - break; - continue; - } - (void) getchar(); /* Somebody was playing */ - } - } - } - } - printf("Thread: %s Slept for %d (%d) sec\n",my_thread_name(), - (int) (my_time(0)-start_time), wait_time); fflush(stdout); - thr_end_alarm(&got_alarm); - fflush(stdout); - } - mysql_mutex_lock(&LOCK_thread_count); - thread_count--; - mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ - mysql_mutex_unlock(&LOCK_thread_count); - my_thread_end(); - return 0; -} - - -static void *signal_hand(void *arg __attribute__((unused))) -{ - sigset_t set; - int sig,error,err_count=0;; - - my_thread_init(); - pthread_detach_this_thread(); - init_thr_alarm(10); /* Setup alarm handler */ - mysql_mutex_lock(&LOCK_thread_count); /* Required by bsdi */ - mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ - mysql_mutex_unlock(&LOCK_thread_count); - - sigemptyset(&set); /* Catch all signals */ - sigaddset(&set,SIGINT); - sigaddset(&set,SIGQUIT); - sigaddset(&set,SIGTERM); - sigaddset(&set,SIGHUP); -#ifdef SIGTSTP - sigaddset(&set,SIGTSTP); -#endif -#ifdef USE_ONE_SIGNAL_HAND - sigaddset(&set,THR_SERVER_ALARM); /* For alarms */ - puts("Starting signal and alarm handling thread"); -#else - puts("Starting signal handling thread"); -#endif - printf("server alarm: %d thread alarm: %d\n", - THR_SERVER_ALARM, thr_client_alarm); - DBUG_PRINT("info",("Starting signal and alarm handling thread")); - for(;;) - { - int code; - while ((error=my_sigwait(&set,&sig,&code)) == EINTR) - printf("sigwait restarted\n"); - if (error) - { - fprintf(stderr,"Got error %d from sigwait\n",error); - if (err_count++ > 5) - exit(1); /* Too many errors in test */ - continue; - } -#ifdef USE_ONE_SIGNAL_HAND - if (sig != THR_SERVER_ALARM) -#endif - printf("Main thread: Got signal %d\n",sig); - switch (sig) { - case SIGINT: - case SIGQUIT: - case SIGTERM: - case SIGHUP: - printf("Aborting nicely\n"); - end_thr_alarm(0); - break; -#ifdef SIGTSTP - case SIGTSTP: - printf("Aborting\n"); - exit(1); - return 0; /* Keep some compilers happy */ -#endif -#ifdef USE_ONE_SIGNAL_HAND - case THR_SERVER_ALARM: - process_alarm(sig); - break; -#endif - } - } -} - - -int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) -{ - pthread_t tid; - pthread_attr_t thr_attr; - int i, param[2], error; - sigset_t set; - ALARM_INFO alarm_info; - MY_INIT(argv[0]); - - if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') - { - DBUG_PUSH(argv[1]+2); - } - mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST); - mysql_cond_init(0, &COND_thread_count, NULL); - - /* Start a alarm handling thread */ - sigemptyset(&set); - sigaddset(&set,SIGINT); - sigaddset(&set,SIGQUIT); - sigaddset(&set,SIGTERM); - sigaddset(&set,SIGHUP); - signal(SIGTERM,SIG_DFL); /* If it's blocked by parent */ -#ifdef SIGTSTP - sigaddset(&set,SIGTSTP); -#endif - sigaddset(&set,THR_SERVER_ALARM); - sigdelset(&set, thr_client_alarm); - (void) pthread_sigmask(SIG_SETMASK,&set,NULL); - - pthread_attr_init(&thr_attr); - pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&thr_attr,65536L); - - /* Start signal thread and wait for it to start */ - mysql_mutex_lock(&LOCK_thread_count); - mysql_thread_create(0, &tid, &thr_attr, signal_hand, NULL); - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - DBUG_PRINT("info",("signal thread created")); - - pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - printf("Main thread: %s\n",my_thread_name()); - for (i=0 ; i < 2 ; i++) - { - param[i]= i; - mysql_mutex_lock(&LOCK_thread_count); - if ((error= mysql_thread_create(0, - &tid, &thr_attr, test_thread, - (void*) ¶m[i]))) - { - printf("Can't create thread %d, error: %d\n",i,error); - exit(1); - } - thread_count++; - mysql_mutex_unlock(&LOCK_thread_count); - } - - pthread_attr_destroy(&thr_attr); - mysql_mutex_lock(&LOCK_thread_count); - thr_alarm_info(&alarm_info); - printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", - alarm_info.active_alarms, alarm_info.max_used_alarms, - alarm_info.next_alarm_time); - while (thread_count) - { - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - if (thread_count == 1) - { - printf("Calling end_thr_alarm. This should cancel the last thread\n"); - end_thr_alarm(0); - } - } - mysql_mutex_unlock(&LOCK_thread_count); - thr_alarm_info(&alarm_info); - end_thr_alarm(1); - printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", - alarm_info.active_alarms, alarm_info.max_used_alarms, - alarm_info.next_alarm_time); - printf("Test succeeded\n"); - mysql_cond_destroy(&COND_thread_count); - mysql_mutex_destroy(&LOCK_thread_count); - my_end(MY_CHECK_ERROR); - return 0; -} - -#else /* !defined(DONT_USE_ALARM_THREAD) */ - -int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) -{ - printf("thr_alarm disabled with DONT_USE_THR_ALARM\n"); - exit(1); -} - -#endif /* !defined(DONT_USE_ALARM_THREAD) */ -#endif /* WIN */ -#endif /* MAIN */ diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 214ff01b..de982806 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1386,52 +1386,6 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) } -/* - Downgrade a WRITE_* to a lower WRITE level - SYNOPSIS - thr_downgrade_write_lock() - in_data Lock data of thread downgrading its lock - new_lock_type New write lock type - RETURN VALUE - NONE - DESCRIPTION - This can be used to downgrade a lock already owned. When the downgrade - occurs also other waiters, both readers and writers can be allowed to - start. - The previous lock is often TL_WRITE_ONLY but can also be - TL_WRITE. The normal downgrade variants are: - TL_WRITE_ONLY => TL_WRITE after a short exclusive lock while holding a - write table lock - TL_WRITE_ONLY => TL_WRITE_ALLOW_WRITE After a short exclusive lock after - already earlier having dongraded lock to TL_WRITE_ALLOW_WRITE - The implementation is conservative and rather don't start rather than - go on unknown paths to start, the common cases are handled. - - NOTE: - In its current implementation it is only allowed to downgrade from - TL_WRITE_ONLY. In this case there are no waiters. Thus no wake up - logic is required. -*/ - -void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, - enum thr_lock_type new_lock_type) -{ - THR_LOCK *lock=in_data->lock; -#ifdef DBUG_ASSERT_EXISTS - enum thr_lock_type old_lock_type= in_data->type; -#endif - DBUG_ENTER("thr_downgrade_write_only_lock"); - - mysql_mutex_lock(&lock->mutex); - DBUG_ASSERT(old_lock_type == TL_WRITE_ONLY); - DBUG_ASSERT(old_lock_type > new_lock_type); - in_data->type= new_lock_type; - check_locks(lock,"after downgrading lock", old_lock_type, 0); - - mysql_mutex_unlock(&lock->mutex); - DBUG_VOID_RETURN; -} - /* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, |