diff options
Diffstat (limited to 'mysys')
110 files changed, 4240 insertions, 5310 deletions
diff --git a/mysys/.cvsignore b/mysys/.cvsignore deleted file mode 100644 index 056ecc2691c..00000000000 --- a/mysys/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -st35l1t6 -test_charset -test_thr_alarm -test_thr_lock -test_vsnprintf -testhash diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 87f40af2fe8..ca338369dad 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2006 MySQL AB +# 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 @@ -11,41 +11,66 @@ # # 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 +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys) -# Only the server link with this library, the client libraries and the client -# executables all link with recompiles of source found in the "mysys" directory. -# So we only need to create one version of this library, with the "static" -# Thread Local Storage model. -# -# Exception is the embedded server that needs this library compiled with -# dynamic TLS, i.e. define USE_TLS - -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys) - -SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_modify.c - errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c - mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c my_safehash.c +SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c + errors.c hash.c list.c md5.c mf_cache.c mf_dirname.c mf_fn_ext.c + mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_arr_appstr.c mf_tempdir.c - mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c - my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chmod.c my_chsize.c - my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c + mf_tempfile.c mf_unixpath.c mf_wcomp.c mulalloc.c my_access.c + my_aes.c my_alloc.c my_bit.c my_bitmap.c my_chsize.c + my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_file.c my_fopen.c my_fstream.c my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_compare.c my_init.c - my_lib.c my_lock.c my_lockmem.c my_malloc.c my_messnc.c - my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c - my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c - my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c - my_winerr.c my_winfile.c my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.c - rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c - thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c ma_dyncol.c - lf_alloc-pin.c lf_dynarray.c lf_hash.c - my_atomic.c my_getncpus.c my_rnd.c - my_uuid.c wqueue.c waiting_threads.c -) - -IF(NOT SOURCE_SUBLIBS) - ADD_LIBRARY(mysys ${MYSYS_SOURCES}) -ENDIF(NOT SOURCE_SUBLIBS) + my_lib.c my_lock.c my_malloc.c my_mess.c + my_mkdir.c my_mmap.c my_once.c my_open.c my_pread.c my_pthread.c + my_quick.c my_read.c my_redel.c my_rename.c my_seek.c my_sleep.c + my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c + my_write.c ptr_cmp.c queues.c stacktrace.c + rijndael.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c + thr_rwlock.c tree.c typelib.c base64.c my_memmem.c my_getpagesize.c + lf_alloc-pin.c lf_dynarray.c lf_hash.c + my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c + my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c + my_rdtsc.c) + +IF (WIN32) + SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_winthread.c my_wincond.c my_winerr.c my_winfile.c my_windac.c my_conio.c) +ENDIF() + +IF(HAVE_ALARM) + SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_alarm.c) +ENDIF() + +IF(NOT HAVE_CXX_NEW) + # gcc as C++ compiler does not have new/delete + SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_new.cc) + ADD_DEFINITIONS( -DUSE_MYSYS_NEW) +ENDIF() + +IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_C_COMPILER_ID MATCHES "SunPro") + # Inline assembly template for rdtsc + SET_SOURCE_FILES_PROPERTIES(my_rdtsc.c + PROPERTIES COMPILE_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/my_timer_cycles.il") +ENDIF() + +IF(HAVE_LARGE_PAGES) + SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_largepage.c) +ENDIF() + +IF(HAVE_MLOCK) + SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_lockmem.c) +ENDIF() + +ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES}) +TARGET_LINK_LIBRARIES(mysys ${DBUG_LIBRARY} strings ${ZLIB_LIBRARY} + ${LIBNSL} ${LIBM} ${LIBRT}) +DTRACE_INSTRUMENT(mysys) + +ADD_EXECUTABLE(thr_lock thr_lock.c) +TARGET_LINK_LIBRARIES(thr_lock mysys) +SET_TARGET_PROPERTIES(thr_lock PROPERTIES COMPILE_FLAGS "-DMAIN") + diff --git a/mysys/Makefile.am b/mysys/Makefile.am deleted file mode 100644 index e479134df8e..00000000000 --- a/mysys/Makefile.am +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright (C) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -MYSQLDATAdir = $(localstatedir) -MYSQLSHAREdir = $(pkgdatadir) -MYSQLBASEdir= $(prefix) -INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ - -I$(top_srcdir)/include -I$(srcdir) -pkglib_LIBRARIES = libmysys.a -noinst_LTLIBRARIES = libmysys.la -LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a $(top_builddir)/dbug/libdbug.a -noinst_HEADERS = mysys_priv.h my_static.h my_handler_errors.h \ - my_safehash.h -libmysys_la_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ - mf_path.c mf_loadpath.c my_file.c \ - my_open.c my_create.c my_dup.c my_seek.c my_read.c \ - my_pread.c my_write.c my_getpagesize.c \ - my_crc32.c ma_dyncol.c \ - mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \ - mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ - my_malloc.c my_realloc.c my_once.c mulalloc.c \ - my_alloc.c safemalloc.c my_new.cc \ - my_vle.c my_atomic.c \ - my_safehash.c lf_hash.c lf_dynarray.c lf_alloc-pin.c \ - my_rnd.c my_uuid.c my_chmod.c \ - my_fopen.c my_fstream.c my_getsystime.c \ - my_error.c errors.c my_div.c my_messnc.c \ - mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ - my_symlink.c my_symlink2.c \ - mf_pack.c mf_unixpath.c mf_arr_appstr.c \ - mf_wcomp.c mf_wfile.c my_gethwaddr.c \ - mf_qsort.c mf_qsort2.c mf_sort.c \ - ptr_cmp.c mf_radix.c queues.c my_getncpus.c \ - tree.c trie.c list.c hash.c array.c string.c \ - typelib.c \ - my_copy.c my_append.c my_lib.c \ - my_delete.c my_rename.c my_redel.c \ - my_chsize.c my_clock.c \ - my_quick.c my_lockmem.c my_static.c \ - my_sync.c my_getopt.c my_mkdir.c \ - default_modify.c default.c \ - my_compress.c checksum.c \ - my_net.c my_port.c my_sleep.c \ - charset.c charset-def.c my_bitmap.c my_bit.c md5.c \ - rijndael.c my_aes.c sha1.c \ - my_compare.c my_netware.c my_largepage.c \ - my_memmem.c stacktrace.c \ - my_windac.c my_access.c base64.c my_libwrap.c \ - wqueue.c -libmysys_la_LDFLAGS = $(AM_LDFLAGS) @WRAPLIBS@ -libmysys_la_LIBADD = $(ZLIB_LIBS) - -if NEED_THREAD -# mf_keycache is used only in the server, so it is safe to leave the file -# out of the non-threaded library. -# In fact, it will currently not compile without thread support. -libmysys_la_SOURCES += thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c \ - my_pthread.c my_thr_init.c waiting_threads.c \ - mf_keycache.c mf_keycaches.c -endif - -EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ - thr_mutex.c thr_rwlock.c waiting_threads.c \ - CMakeLists.txt mf_soundex.c \ - my_conio.c my_wincond.c my_winthread.c my_winfile.c my_winerr.c -# test_dir_DEPENDENCIES= $(LIBRARIES) -# testhash_DEPENDENCIES= $(LIBRARIES) -# test_charset_DEPENDENCIES= $(LIBRARIES) -# charset2html_DEPENDENCIES= $(LIBRARIES) -DEFS = -DDEFAULT_BASEDIR='"$(prefix)"' \ - -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \ - -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \ - -DSHAREDIR'="$(MYSQLSHAREdir)"' \ - -DDEFAULT_HOME_ENV=MYSQL_HOME \ - -DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \ - -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \ - @DEFS@ - -# I hope this always does the right thing. Otherwise this is only test programs -FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@ - -CLEANFILES = test_bitmap$(EXEEXT) test_priority_queue$(EXEEXT) \ - test_thr_alarm$(EXEEXT) test_thr_lock$(EXEEXT) \ - test_vsnprintf$(EXEEXT) test_io_cache$(EXEEXT) \ - test_dir$(EXEEXT) test_charset$(EXEEXT) \ - testhash$(EXEEXT) test_gethwaddr$(EXEEXT) \ - test_base64$(EXEEXT) test_thr_mutex$(EXEEXT) - -libmysys_a_SOURCES= -libmysys.a: libmysys.la - $(CP) .libs/libmysys.a $@ - -# -# The CP .. RM stuff is to avoid problems with some compilers (like alpha ccc) -# which automaticly removes the object files you use to compile a final program -# - -test_bitmap$(EXEEXT): my_bitmap.c $(LIBRARIES) - $(LINK) $(FLAGS) -DMAIN ./my_bitmap.c $(LDADD) $(LIBS) - -test_priority_queue$(EXEEXT): queues.c $(LIBRARIES) - $(LINK) $(FLAGS) -DMAIN ./queues.c $(LDADD) $(LIBS) - -test_thr_alarm$(EXEEXT): thr_alarm.c $(LIBRARIES) - $(CP) $(srcdir)/thr_alarm.c ./test_thr_alarm.c - $(LINK) $(FLAGS) -DMAIN ./test_thr_alarm.c $(LDADD) $(LIBS) - $(RM) -f ./test_thr_alarm.c - -test_thr_lock$(EXEEXT): thr_lock.c $(LIBRARIES) - $(CP) $(srcdir)/thr_lock.c test_thr_lock.c - $(LINK) $(FLAGS) -DMAIN ./test_thr_lock.c $(LDADD) $(LIBS) - $(RM) -f ./test_thr_lock.c - -test_vsnprintf$(EXEEXT): my_vsnprintf.c $(LIBRARIES) - $(CP) $(srcdir)/my_vsnprintf.c test_vsnprintf.c - $(LINK) $(FLAGS) -DMAIN ./test_vsnprintf.c $(LDADD) $(LIBS) - $(RM) -f test_vsnprintf.c - -test_io_cache$(EXEEXT): mf_iocache.c $(LIBRARIES) - $(CP) $(srcdir)/mf_iocache.c test_io_cache.c - $(LINK) $(FLAGS) -DMAIN ./test_io_cache.c $(LDADD) $(LIBS) - $(RM) -f test_io_cache.c - -test_dir$(EXEEXT): test_dir.c $(LIBRARIES) - $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_dir.c $(LDADD) $(LIBS) - -test_charset$(EXEEXT): test_charset.c $(LIBRARIES) - $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS) - -testhash$(EXEEXT): testhash.c $(LIBRARIES) - $(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS) - -test_gethwaddr$(EXEEXT): my_gethwaddr.c $(LIBRARIES) - $(CP) $(srcdir)/my_gethwaddr.c ./test_gethwaddr.c - $(LINK) $(FLAGS) -DMAIN ./test_gethwaddr.c $(LDADD) $(LIBS) - $(RM) -f ./test_gethwaddr.c - -test_base64$(EXEEXT): base64.c $(LIBRARIES) - $(CP) $(srcdir)/base64.c ./test_base64.c - $(LINK) $(FLAGS) -DMAIN ./test_base64.c $(LDADD) $(LIBS) - $(RM) -f ./test_base64.c - -test_thr_mutex$(EXEEXT): test_thr_mutex.c $(LIBRARIES) - $(LINK) $(FLAGS) $(srcdir)/test_thr_mutex.c $(LDADD) $(LIBS) diff --git a/mysys/array.c b/mysys/array.c index a18223e9cae..d5a4a6fa284 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -41,10 +41,10 @@ */ my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, - void *init_buffer, uint init_alloc, - uint alloc_increment CALLER_INFO_PROTO) + void *init_buffer, uint init_alloc, + uint alloc_increment) { - DBUG_ENTER("init_dynamic_array"); + DBUG_ENTER("init_dynamic_array2"); if (!alloc_increment) { alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16); @@ -61,14 +61,14 @@ my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, Since the dynamic array is usable even if allocation fails here malloc should not throw an error */ - if (!(array->buffer= (uchar*) my_malloc_ci(element_size*init_alloc, MYF(0)))) + if (init_alloc && + !(array->buffer= (uchar*) my_malloc(element_size*init_alloc, MYF(0)))) array->max_element=0; DBUG_RETURN(FALSE); } my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, - uint init_alloc, - uint alloc_increment CALLER_INFO_PROTO) + uint init_alloc, uint alloc_increment) { /* placeholder to preserve ABI */ return my_init_dynamic_array_ci(array, element_size, init_alloc, @@ -300,7 +300,7 @@ void delete_dynamic(DYNAMIC_ARRAY *array) else if (array->buffer) { - my_free(array->buffer,MYF(MY_WME)); + my_free(array->buffer); array->buffer=0; array->elements=array->max_element=0; } diff --git a/mysys/charset-def.c b/mysys/charset-def.c index db10000e174..703cd8568e0 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -42,9 +42,59 @@ extern struct charset_info_st my_charset_ucs2_roman_uca_ci; extern struct charset_info_st my_charset_ucs2_persian_uca_ci; extern struct charset_info_st my_charset_ucs2_esperanto_uca_ci; extern struct charset_info_st my_charset_ucs2_hungarian_uca_ci; +extern struct charset_info_st my_charset_ucs2_sinhala_uca_ci; extern struct charset_info_st my_charset_ucs2_croatian_uca_ci; #endif + +#ifdef HAVE_CHARSET_utf32 +extern struct charset_info_st my_charset_utf32_icelandic_uca_ci; +extern struct charset_info_st my_charset_utf32_latvian_uca_ci; +extern struct charset_info_st my_charset_utf32_romanian_uca_ci; +extern struct charset_info_st my_charset_utf32_slovenian_uca_ci; +extern struct charset_info_st my_charset_utf32_polish_uca_ci; +extern struct charset_info_st my_charset_utf32_estonian_uca_ci; +extern struct charset_info_st my_charset_utf32_spanish_uca_ci; +extern struct charset_info_st my_charset_utf32_swedish_uca_ci; +extern struct charset_info_st my_charset_utf32_turkish_uca_ci; +extern struct charset_info_st my_charset_utf32_czech_uca_ci; +extern struct charset_info_st my_charset_utf32_danish_uca_ci; +extern struct charset_info_st my_charset_utf32_lithuanian_uca_ci; +extern struct charset_info_st my_charset_utf32_slovak_uca_ci; +extern struct charset_info_st my_charset_utf32_spanish2_uca_ci; +extern struct charset_info_st my_charset_utf32_roman_uca_ci; +extern struct charset_info_st my_charset_utf32_persian_uca_ci; +extern struct charset_info_st my_charset_utf32_esperanto_uca_ci; +extern struct charset_info_st my_charset_utf32_hungarian_uca_ci; +extern struct charset_info_st my_charset_utf32_sinhala_uca_ci; +extern struct charset_info_st my_charset_utf32_croatian_uca_ci; +#endif /* HAVE_CHARSET_utf32 */ + + +#ifdef HAVE_CHARSET_utf16 +extern struct charset_info_st my_charset_utf16_icelandic_uca_ci; +extern struct charset_info_st my_charset_utf16_latvian_uca_ci; +extern struct charset_info_st my_charset_utf16_romanian_uca_ci; +extern struct charset_info_st my_charset_utf16_slovenian_uca_ci; +extern struct charset_info_st my_charset_utf16_polish_uca_ci; +extern struct charset_info_st my_charset_utf16_estonian_uca_ci; +extern struct charset_info_st my_charset_utf16_spanish_uca_ci; +extern struct charset_info_st my_charset_utf16_swedish_uca_ci; +extern struct charset_info_st my_charset_utf16_turkish_uca_ci; +extern struct charset_info_st my_charset_utf16_czech_uca_ci; +extern struct charset_info_st my_charset_utf16_danish_uca_ci; +extern struct charset_info_st my_charset_utf16_lithuanian_uca_ci; +extern struct charset_info_st my_charset_utf16_slovak_uca_ci; +extern struct charset_info_st my_charset_utf16_spanish2_uca_ci; +extern struct charset_info_st my_charset_utf16_roman_uca_ci; +extern struct charset_info_st my_charset_utf16_persian_uca_ci; +extern struct charset_info_st my_charset_utf16_esperanto_uca_ci; +extern struct charset_info_st my_charset_utf16_hungarian_uca_ci; +extern struct charset_info_st my_charset_utf16_sinhala_uca_ci; +extern struct charset_info_st my_charset_utf16_croatian_uca_ci; +#endif /* HAVE_CHARSET_utf16 */ + + #ifdef HAVE_CHARSET_utf8 extern struct charset_info_st my_charset_utf8_icelandic_uca_ci; extern struct charset_info_st my_charset_utf8_latvian_uca_ci; @@ -64,12 +114,36 @@ extern struct charset_info_st my_charset_utf8_roman_uca_ci; extern struct charset_info_st my_charset_utf8_persian_uca_ci; extern struct charset_info_st my_charset_utf8_esperanto_uca_ci; extern struct charset_info_st my_charset_utf8_hungarian_uca_ci; +extern struct charset_info_st my_charset_utf8_sinhala_uca_ci; extern struct charset_info_st my_charset_utf8_croatian_uca_ci; #ifdef HAVE_UTF8_GENERAL_CS extern struct charset_info_st my_charset_utf8_general_cs; #endif #endif +#ifdef HAVE_CHARSET_utf8mb4 +extern struct charset_info_st my_charset_utf8mb4_icelandic_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_latvian_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_romanian_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_slovenian_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_polish_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_estonian_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_spanish_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_swedish_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_turkish_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_czech_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_danish_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_lithuanian_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_slovak_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_spanish2_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_roman_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_persian_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_esperanto_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_hungarian_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_sinhala_uca_ci; +extern struct charset_info_st my_charset_utf8mb4_croatian_uca_ci; +#endif /* HAVE_CHARSET_utf8mb4 */ + #endif /* HAVE_UCA_COLLATIONS */ my_bool init_compiled_charsets(myf flags __attribute__((unused))) @@ -154,6 +228,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ucs2_persian_uca_ci); add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci); add_compiled_collation(&my_charset_ucs2_hungarian_uca_ci); + add_compiled_collation(&my_charset_ucs2_sinhala_uca_ci); add_compiled_collation(&my_charset_ucs2_croatian_uca_ci); #endif #endif @@ -189,9 +264,97 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf8_persian_uca_ci); add_compiled_collation(&my_charset_utf8_esperanto_uca_ci); add_compiled_collation(&my_charset_utf8_hungarian_uca_ci); + add_compiled_collation(&my_charset_utf8_sinhala_uca_ci); add_compiled_collation(&my_charset_utf8_croatian_uca_ci); #endif -#endif +#endif /* HAVE_CHARSET_utf8 */ + + +#ifdef HAVE_CHARSET_utf8mb4 + add_compiled_collation(&my_charset_utf8mb4_general_ci); + add_compiled_collation(&my_charset_utf8mb4_bin); +#ifdef HAVE_UCA_COLLATIONS + add_compiled_collation(&my_charset_utf8mb4_unicode_ci); + add_compiled_collation(&my_charset_utf8mb4_icelandic_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_latvian_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_romanian_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_slovenian_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_polish_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_estonian_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_spanish_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_swedish_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_turkish_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_czech_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_danish_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_lithuanian_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_slovak_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_spanish2_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_roman_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_persian_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_esperanto_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_hungarian_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_sinhala_uca_ci); + add_compiled_collation(&my_charset_utf8mb4_croatian_uca_ci); +#endif /* HAVE_UCA_COLLATIONS */ +#endif /* HAVE_CHARSET_utf8mb4 */ + + +#ifdef HAVE_CHARSET_utf16 + add_compiled_collation(&my_charset_utf16_general_ci); + add_compiled_collation(&my_charset_utf16_bin); +#ifdef HAVE_UCA_COLLATIONS + add_compiled_collation(&my_charset_utf16_unicode_ci); + add_compiled_collation(&my_charset_utf16_icelandic_uca_ci); + add_compiled_collation(&my_charset_utf16_latvian_uca_ci); + add_compiled_collation(&my_charset_utf16_romanian_uca_ci); + add_compiled_collation(&my_charset_utf16_slovenian_uca_ci); + add_compiled_collation(&my_charset_utf16_polish_uca_ci); + add_compiled_collation(&my_charset_utf16_estonian_uca_ci); + add_compiled_collation(&my_charset_utf16_spanish_uca_ci); + add_compiled_collation(&my_charset_utf16_swedish_uca_ci); + add_compiled_collation(&my_charset_utf16_turkish_uca_ci); + add_compiled_collation(&my_charset_utf16_czech_uca_ci); + add_compiled_collation(&my_charset_utf16_danish_uca_ci); + add_compiled_collation(&my_charset_utf16_lithuanian_uca_ci); + add_compiled_collation(&my_charset_utf16_slovak_uca_ci); + add_compiled_collation(&my_charset_utf16_spanish2_uca_ci); + add_compiled_collation(&my_charset_utf16_roman_uca_ci); + add_compiled_collation(&my_charset_utf16_persian_uca_ci); + add_compiled_collation(&my_charset_utf16_esperanto_uca_ci); + add_compiled_collation(&my_charset_utf16_hungarian_uca_ci); + add_compiled_collation(&my_charset_utf16_sinhala_uca_ci); + add_compiled_collation(&my_charset_utf16_croatian_uca_ci); +#endif /* HAVE_UCA_COLLATIOINS */ +#endif /* HAVE_CHARSET_utf16 */ + + +#ifdef HAVE_CHARSET_utf32 + add_compiled_collation(&my_charset_utf32_general_ci); + add_compiled_collation(&my_charset_utf32_bin); +#ifdef HAVE_UCA_COLLATIONS + add_compiled_collation(&my_charset_utf32_unicode_ci); + add_compiled_collation(&my_charset_utf32_icelandic_uca_ci); + add_compiled_collation(&my_charset_utf32_latvian_uca_ci); + add_compiled_collation(&my_charset_utf32_romanian_uca_ci); + add_compiled_collation(&my_charset_utf32_slovenian_uca_ci); + add_compiled_collation(&my_charset_utf32_polish_uca_ci); + add_compiled_collation(&my_charset_utf32_estonian_uca_ci); + add_compiled_collation(&my_charset_utf32_spanish_uca_ci); + add_compiled_collation(&my_charset_utf32_swedish_uca_ci); + add_compiled_collation(&my_charset_utf32_turkish_uca_ci); + add_compiled_collation(&my_charset_utf32_czech_uca_ci); + add_compiled_collation(&my_charset_utf32_danish_uca_ci); + add_compiled_collation(&my_charset_utf32_lithuanian_uca_ci); + add_compiled_collation(&my_charset_utf32_slovak_uca_ci); + add_compiled_collation(&my_charset_utf32_spanish2_uca_ci); + add_compiled_collation(&my_charset_utf32_roman_uca_ci); + add_compiled_collation(&my_charset_utf32_persian_uca_ci); + add_compiled_collation(&my_charset_utf32_esperanto_uca_ci); + add_compiled_collation(&my_charset_utf32_hungarian_uca_ci); + add_compiled_collation(&my_charset_utf32_sinhala_uca_ci); + add_compiled_collation(&my_charset_utf32_croatian_uca_ci); +#endif /* HAVE_UCA_COLLATIONS */ +#endif /* HAVE_CHARSET_utf32 */ /* Copy compiled charsets */ for (cs=compiled_charsets; cs->name; cs++) diff --git a/mysys/charset.c b/mysys/charset.c index c7756583b19..98b87ba9feb 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -42,7 +42,7 @@ get_collation_number_internal(const char *name) { CHARSET_INFO **cs; for (cs= all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; + cs < all_charsets + array_elements(all_charsets); cs++) { if ( cs[0] && cs[0]->name && @@ -253,13 +253,38 @@ static int add_collation(struct charset_info_st *cs) { #if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci); - newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } - else if (!strcmp(cs->csname, "utf8")) + else if (!strcmp(cs->csname, "utf8") || !strcmp(cs->csname, "utf8mb3")) { #if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, &my_charset_utf8_unicode_ci); + newcs->ctype= my_charset_utf8_unicode_ci.ctype; + if (init_state_maps(newcs)) + return MY_XML_ERROR; +#endif + } + else if (!strcmp(cs->csname, "utf8mb4")) + { +#if defined (HAVE_CHARSET_utf8mb4) && defined(HAVE_UCA_COLLATIONS) + copy_uca_collation(newcs, &my_charset_utf8mb4_unicode_ci); + newcs->ctype= my_charset_utf8mb4_unicode_ci.ctype; + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED; +#endif + } + else if (!strcmp(cs->csname, "utf16")) + { +#if defined (HAVE_CHARSET_utf16) && defined(HAVE_UCA_COLLATIONS) + copy_uca_collation(newcs, &my_charset_utf16_unicode_ci); + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; +#endif + } + else if (!strcmp(cs->csname, "utf32")) + { +#if defined (HAVE_CHARSET_utf32) && defined(HAVE_UCA_COLLATIONS) + copy_uca_collation(newcs, &my_charset_utf32_unicode_ci); + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } else @@ -342,10 +367,10 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) !(buf= (uchar*) my_malloc(len,myflags))) return TRUE; - if ((fd=my_open(filename,O_RDONLY,myflags)) < 0) + if ((fd= mysql_file_open(key_file_charset, filename, O_RDONLY, myflags)) < 0) goto error; - tmp_len=my_read(fd, buf, len, myflags); - my_close(fd,myflags); + tmp_len= mysql_file_read(fd, buf, len, myflags); + mysql_file_close(fd, myflags); if (tmp_len != len) goto error; @@ -359,11 +384,11 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) #endif } - my_free(buf, myflags); + my_free(buf); return FALSE; error: - my_free(buf, myflags); + my_free(buf); return TRUE; } @@ -390,11 +415,12 @@ char *get_charsets_dir(char *buf) DBUG_RETURN(res); } -CHARSET_INFO *all_charsets[256]={NULL}; +CHARSET_INFO *all_charsets[MY_ALL_CHARSETS_SIZE]={NULL}; CHARSET_INFO *default_charset_info = &my_charset_latin1; void add_compiled_collation(struct charset_info_st *cs) { + DBUG_ASSERT(cs->number < array_elements(all_charsets)); all_charsets[cs->number]= cs; cs->state|= MY_CS_AVAILABLE; } @@ -415,7 +441,7 @@ static void init_available_charsets(void) bzero((char*) &all_charsets,sizeof(all_charsets)); init_compiled_charsets(MYF(0)); - + /* Copy compiled charsets */ for (cs= (struct charset_info_st**) all_charsets; cs < (struct charset_info_st**) all_charsets + @@ -429,7 +455,7 @@ static void init_available_charsets(void) *cs= NULL; } } - + strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); my_read_charset_file(fname, MYF(0)); } @@ -440,20 +466,39 @@ void free_charsets(void) charsets_initialized= charsets_template; } + +static const char* +get_collation_name_alias(const char *name, char *buf, size_t bufsize) +{ + if (!strncasecmp(name, "utf8mb3_", 8)) + { + my_snprintf(buf, bufsize, "utf8_%s", name + 8); + return buf; + } + return NULL; +} + + uint get_collation_number(const char *name) { + uint id; + char alias[64]; my_pthread_once(&charsets_initialized, init_available_charsets); - return get_collation_number_internal(name); + if ((id= get_collation_number_internal(name))) + return id; + if ((name= get_collation_name_alias(name, alias, sizeof(alias)))) + return get_collation_number_internal(name); + return 0; } -uint get_charset_number(const char *charset_name, uint cs_flags) +static uint +get_charset_number_internal(const char *charset_name, uint cs_flags) { CHARSET_INFO **cs; - my_pthread_once(&charsets_initialized, init_available_charsets); for (cs= all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; + cs < all_charsets + array_elements(all_charsets); cs++) { if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) && @@ -464,16 +509,40 @@ uint get_charset_number(const char *charset_name, uint cs_flags) } +static const char* +get_charset_name_alias(const char *name) +{ + if (!my_strcasecmp(&my_charset_latin1, name, "utf8mb3")) + return "utf8"; + return NULL; +} + + +uint get_charset_number(const char *charset_name, uint cs_flags) +{ + uint id; + my_pthread_once(&charsets_initialized, init_available_charsets); + if ((id= get_charset_number_internal(charset_name, cs_flags))) + return id; + if ((charset_name= get_charset_name_alias(charset_name))) + return get_charset_number_internal(charset_name, cs_flags); + return 0; +} + + const char *get_charset_name(uint charset_number) { - CHARSET_INFO *cs; my_pthread_once(&charsets_initialized, init_available_charsets); - cs=all_charsets[charset_number]; - if (cs && (cs->number == charset_number) && cs->name ) - return (char*) cs->name; + if (charset_number < array_elements(all_charsets)) + { + CHARSET_INFO *cs= all_charsets[charset_number]; + + if (cs && (cs->number == charset_number) && cs->name) + return (char*) cs->name; + } - return (char*) "?"; /* this mimics find_type() */ + return "?"; /* this mimics find_type() */ } @@ -482,6 +551,8 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) char buf[FN_REFLEN]; struct charset_info_st *cs; + DBUG_ASSERT(cs_number < array_elements(all_charsets)); + if ((cs= (struct charset_info_st*) all_charsets[cs_number])) { if (cs->state & MY_CS_READY) /* if CS is already initialized */ @@ -491,7 +562,7 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) To make things thread safe we are not allowing other threads to interfere while we may changing the cs_info_table */ - pthread_mutex_lock(&THR_LOCK_charset); + mysql_mutex_lock(&THR_LOCK_charset); if (!(cs->state & (MY_CS_COMPILED|MY_CS_LOADED))) /* if CS is not in memory */ { @@ -513,7 +584,7 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) else cs= NULL; - pthread_mutex_unlock(&THR_LOCK_charset); + mysql_mutex_unlock(&THR_LOCK_charset); } return cs; } @@ -526,8 +597,8 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) return default_charset_info; my_pthread_once(&charsets_initialized, init_available_charsets); - - if (!cs_number || cs_number >= array_elements(all_charsets)-1) + + if (cs_number >= array_elements(all_charsets)) return NULL; cs=get_internal_charset(cs_number, flags); diff --git a/mysys/checksum.c b/mysys/checksum.c index 1d264b54321..c8d3c1a038d 100644 --- a/mysys/checksum.c +++ b/mysys/checksum.c @@ -18,7 +18,7 @@ #include <my_sys.h> #include <zlib.h> -ha_checksum my_crc_dbug_check= 1; /* Unlikely number */ +ulong my_crc_dbug_check= ~0; /* Cannot happen */ /* Calculate a long checksum for a memoryblock. @@ -32,9 +32,9 @@ ha_checksum my_crc_dbug_check= 1; /* Unlikely number */ ha_checksum my_checksum(ha_checksum crc, const uchar *pos, size_t length) { - crc= (ha_checksum) crc32((uint)crc, pos, length); + crc= (ha_checksum) crc32((uint)crc, pos, (uint) length); DBUG_PRINT("info", ("crc: %lu", (ulong) crc)); - if (crc == my_crc_dbug_check) + if ((ulong)crc == my_crc_dbug_check) my_debug_put_break_here(); return crc; } diff --git a/mysys/default.c b/mysys/default.c index 63f9445dbdc..c7ac0d89462 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (c) 2000, 2011, 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 @@ -41,9 +41,51 @@ #include <winbase.h> #endif +/** + arguments separator + + load_defaults() loads arguments from config file and put them + before the arguments from command line, this separator is used to + separate the arguments loaded from config file and arguments user + provided on command line. + + Options with value loaded from config file are always in the form + '--option=value', while for command line options, the value can be + given as the next argument. Thus we used a separator so that + handle_options() can distinguish them. + + Note: any other places that does not need to distinguish them + should skip the separator. + + The content of arguments separator does not matter, one should only + check the pointer, use "----args-separator----" here to ease debug + if someone misused it. + + The args seprator will only be added when + my_getopt_use_args_seprator is set to TRUE before calling + load_defaults(); + + See BUG#25192 +*/ +static const char *args_separator= "----args-separator----"; +inline static void set_args_separator(char** arg) +{ + DBUG_ASSERT(my_getopt_use_args_separator); + *arg= (char*)args_separator; +} +my_bool my_getopt_use_args_separator= FALSE; +my_bool my_getopt_is_args_separator(const char* arg) +{ + return (arg == args_separator); +} const char *my_defaults_file=0; const char *my_defaults_group_suffix=0; -char *my_defaults_extra_file=0; +const char *my_defaults_extra_file=0; + +static char my_defaults_file_buffer[FN_REFLEN]; +static char my_defaults_extra_file_buffer[FN_REFLEN]; + +static my_bool defaults_already_read= FALSE; /* Which directories are searched for options (and in which order) */ @@ -95,11 +137,10 @@ static int search_default_file_with_ext(Process_option_func func, - Windows: GetWindowsDirectory() - Windows: C:/ - Windows: Directory above where the executable is located - - Netware: sys:/etc/ - Unix: /etc/ - Unix: /etc/mysql/ - Unix: --sysconfdir=<path> (compile-time option) - - ALL: getenv(DEFAULT_HOME_ENV) + - ALL: getenv("MYSQL_HOME") - ALL: --defaults-extra-file=<path> (run-time option) - Unix: ~/ @@ -118,6 +159,33 @@ static char *remove_end_comment(char *ptr); /* + Expand a file name so that the current working directory is added if + the name is relative. + + RETURNS + 0 All OK + 2 Out of memory or path to long + 3 Not able to get working directory + */ + +static int +fn_expand(const char *filename, char *result_buf) +{ + char dir[FN_REFLEN]; + const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH; + DBUG_ENTER("fn_expand"); + DBUG_PRINT("enter", ("filename: %s, result_buf: 0x%lx", + filename, (unsigned long) result_buf)); + if (my_getwd(dir, sizeof(dir), MYF(0))) + DBUG_RETURN(3); + DBUG_PRINT("debug", ("dir: %s", dir)); + if (fn_format(result_buf, filename, dir, "", flags) == NULL) + DBUG_RETURN(2); + DBUG_PRINT("return", ("result: %s", result_buf)); + DBUG_RETURN(0); +} + +/* Process config files in default directories. SYNOPSIS @@ -145,6 +213,7 @@ static char *remove_end_comment(char *ptr); 0 ok 1 given cinf_file doesn't exist 2 out of memory + 3 Can't get current working directory The global variable 'my_defaults_group_suffix' is updated with value for --defaults_group_suffix @@ -167,11 +236,23 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, if (! my_defaults_group_suffix) my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV)); - if (forced_extra_defaults) - my_defaults_extra_file= (char *) forced_extra_defaults; - - if (forced_default_file) - my_defaults_file= forced_default_file; + if (forced_extra_defaults && !defaults_already_read) + { + int error= fn_expand(forced_extra_defaults, my_defaults_extra_file_buffer); + if (error) + DBUG_RETURN(error); + my_defaults_extra_file= my_defaults_extra_file_buffer; + } + + if (forced_default_file && !defaults_already_read) + { + int error= fn_expand(forced_default_file, my_defaults_file_buffer); + if (error) + DBUG_RETURN(error); + my_defaults_file= my_defaults_file_buffer; + } + + defaults_already_read= TRUE; /* We can only handle 'defaults-group-suffix' if we are called from @@ -214,15 +295,15 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, group->type_names[group->count]= 0; } - if (forced_default_file) + if (my_defaults_file) { if ((error= search_default_file_with_ext(func, func_ctx, "", "", - forced_default_file, 0)) < 0) + my_defaults_file, 0)) < 0) goto err; if (error > 0) { fprintf(stderr, "Could not open required defaults file: %s\n", - forced_default_file); + my_defaults_file); goto err; } } @@ -295,7 +376,7 @@ static int handle_default_option(void *in_ctx, const char *group_name, if (!option) return 0; - if (find_type((char *)group_name, ctx->group, 3)) + if (find_type((char *)group_name, ctx->group, FIND_TYPE_NO_PREFIX)) { if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1))) return 1; @@ -436,6 +517,7 @@ int my_load_defaults(const char *conf_file, const char **groups, char *ptr,**res; struct handle_option_ctx ctx; const char **dirs; + uint args_sep= my_getopt_use_args_separator ? 1 : 0; DBUG_ENTER("load_defaults"); init_alloc_root(&alloc,512,0); @@ -448,16 +530,28 @@ int my_load_defaults(const char *conf_file, const char **groups, if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults")) { /* remove the --no-defaults argument and return only the other arguments */ - uint i; + uint i, j; if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ (*argc + 1)*sizeof(char*)))) goto err; res= (char**) (ptr+sizeof(alloc)); res[0]= **argv; /* Copy program name */ - for (i=2 ; i < (uint) *argc ; i++) - res[i-1]=argv[0][i]; - res[i-1]=0; /* End pointer */ - (*argc)--; + j= 1; /* Start from 1 for the reset result args */ + if (my_getopt_use_args_separator) + { + /* set arguments separator */ + set_args_separator(&res[1]); + j++; + } + for (i=2 ; i < (uint) *argc ; i++, j++) + res[j]=argv[0][i]; + res[j]=0; /* End pointer */ + /* + Update the argc, if have not added args separator, then we have + to decrease argc because we have removed the "--no-defaults". + */ + if (!my_getopt_use_args_separator) + (*argc)--; *argv=res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ if (default_directories) @@ -479,15 +573,19 @@ int my_load_defaults(const char *conf_file, const char **groups, ctx.args= &args; ctx.group= &group; - error= my_search_option_files(conf_file, argc, argv, &args_used, - handle_default_option, (void *) &ctx, - dirs); + if ((error= my_search_option_files(conf_file, argc, argv, &args_used, + handle_default_option, (void *) &ctx, + dirs))) + { + free_root(&alloc,MYF(0)); + DBUG_RETURN(error); + } /* Here error contains <> 0 only if we have a fully specified conf_file or a forced default file */ if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ - (args.elements + *argc +1) *sizeof(char*)))) + (args.elements + *argc + 1 + args_sep) *sizeof(char*)))) goto err; res= (char**) (ptr+sizeof(alloc)); @@ -508,12 +606,19 @@ int my_load_defaults(const char *conf_file, const char **groups, --*argc; ++*argv; /* skip argument */ } + if (my_getopt_use_args_separator) + { + /* set arguments separator for arguments from config file and + command line */ + set_args_separator(&res[args.elements+1]); + } + if (*argc) - memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1), + memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1), (*argc-1)*sizeof(char*)); - res[args.elements+ *argc]=0; /* last null */ + res[args.elements+ *argc+args_sep]=0; /* last null */ - (*argc)+=args.elements; + (*argc)+=args.elements+args_sep; *argv= (char**) res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ delete_dynamic(&args); @@ -523,15 +628,16 @@ int my_load_defaults(const char *conf_file, const char **groups, printf("%s would have been started with the following arguments:\n", **argv); for (i=1 ; i < *argc ; i++) - printf("%s ", (*argv)[i]); + if (!my_getopt_is_args_separator((*argv)[i])) /* skip arguments separator */ + printf("%s ", (*argv)[i]); puts(""); exit(0); } - if (error == 0 && default_directories) + if (default_directories) *default_directories= dirs; - DBUG_RETURN(error); + DBUG_RETURN(0); err: fprintf(stderr,"Fatal error in defaults handling. Program aborted\n"); @@ -543,7 +649,7 @@ int my_load_defaults(const char *conf_file, const char **groups, void free_defaults(char **argv) { MEM_ROOT ptr; - memcpy_fixed((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr)); + memcpy(&ptr, ((char *) argv) - sizeof(ptr), sizeof(ptr)); free_root(&ptr,MYF(0)); } @@ -654,7 +760,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, static const char includedir_keyword[]= "includedir"; static const char include_keyword[]= "include"; const int max_recursion_level= 10; - FILE *fp; + MYSQL_FILE *fp; uint line=0; my_bool found_group=0; uint i; @@ -675,7 +781,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, strmov(name,config_file); } fn_format(name,name,"","",4); -#if !defined(__WIN__) && !defined(__NETWARE__) +#if !defined(__WIN__) { MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(0))) @@ -694,10 +800,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler, } } #endif - if (!(fp= my_fopen(name, O_RDONLY, MYF(0)))) + if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0)))) return 1; /* Ignore wrong files */ - while (fgets(buff, sizeof(buff) - 1, fp)) + while (mysql_file_fgets(buff, sizeof(buff) - 1, fp)) { line++; /* Ignore comment and empty lines */ @@ -887,11 +993,11 @@ static int search_default_file_with_ext(Process_option_func opt_handler, goto err; } } - my_fclose(fp,MYF(0)); + mysql_file_fclose(fp, MYF(0)); return(0); err: - my_fclose(fp,MYF(0)); + mysql_file_fclose(fp, MYF(0)); return -1; /* Fatal error */ } @@ -921,7 +1027,6 @@ static char *remove_end_comment(char *ptr) return ptr; } -#include <help_start.h> void my_print_default_files(const char *conf_file) { @@ -1001,8 +1106,6 @@ void print_defaults(const char *conf_file, const char **groups) --defaults-extra-file=# Read this file after the global files are read."); } -#include <help_end.h> - static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs) { @@ -1095,10 +1198,11 @@ static const char **init_default_directories(MEM_ROOT *alloc) const char **dirs; char *env; int errors= 0; + DBUG_ENTER("init_default_directories"); dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *)); if (dirs == NULL) - return NULL; + DBUG_RETURN(NULL); bzero((char *) dirs, DEFAULT_DIRS_SIZE * sizeof(char *)); #ifdef __WIN__ @@ -1117,10 +1221,6 @@ static const char **init_default_directories(MEM_ROOT *alloc) errors += add_directory(alloc, fname_buffer, dirs); } -#elif defined(__NETWARE__) - - errors += add_directory(alloc, "sys:/etc/", dirs); - #else errors += add_directory(alloc, "/etc/", dirs); @@ -1133,15 +1233,15 @@ static const char **init_default_directories(MEM_ROOT *alloc) #endif - if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) + if ((env= getenv("MYSQL_HOME"))) errors += add_directory(alloc, env, dirs); /* Placeholder for --defaults-extra-file=<path> */ errors += add_directory(alloc, "", dirs); -#if !defined(__WIN__) && !defined(__NETWARE__) +#if !defined(__WIN__) errors += add_directory(alloc, "~/", dirs); #endif - return (errors > 0 ? NULL : dirs); + DBUG_RETURN(errors > 0 ? NULL : dirs); } diff --git a/mysys/default_modify.c b/mysys/default_modify.c deleted file mode 100644 index ccbf47176a6..00000000000 --- a/mysys/default_modify.c +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright (C) 2005 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "my_global.h" -#include "mysys_priv.h" -#include "m_string.h" -#include <my_dir.h> - -#define BUFF_SIZE 1024 -#define RESERVE 1024 /* Extend buffer with this extent */ - -#ifdef _WIN32 -#define NEWLINE "\r\n" -#define NEWLINE_LEN 2 -#else -#define NEWLINE "\n" -#define NEWLINE_LEN 1 -#endif - -static char *add_option(char *dst, const char *option_value, - const char *option, int remove_option); - - -/* - Add/remove option to the option file section. - - SYNOPSYS - modify_defaults_file() - file_location The location of configuration file to edit - option The name of the option to look for (can be NULL) - option value The value of the option we would like to set (can be NULL) - section_name The name of the section (must be NOT NULL) - remove_option This defines what we want to remove: - - MY_REMOVE_NONE -- nothing to remove; - - MY_REMOVE_OPTION -- remove the specified option; - - MY_REMOVE_SECTION -- remove the specified section; - IMPLEMENTATION - We open the option file first, then read the file line-by-line, - looking for the section we need. At the same time we put these lines - into a buffer. Then we look for the option within this section and - change/remove it. In the end we get a buffer with modified version of the - file. Then we write it to the file, truncate it if needed and close it. - Note that there is a small time gap, when the file is incomplete, - and this theoretically might introduce a problem. - - RETURN - 0 - ok - 1 - some error has occured. Probably due to the lack of resourses - 2 - cannot open the file -*/ - -int modify_defaults_file(const char *file_location, const char *option, - const char *option_value, - const char *section_name, int remove_option) -{ - FILE *cnf_file; - MY_STAT file_stat; - char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; - size_t opt_len= 0, optval_len= 0, sect_len, new_opt_len, reserve_extended; - uint nr_newlines= 0, buffer_size; - my_bool in_section= FALSE, opt_applied= 0; - int reserve_occupied= 0; - DBUG_ENTER("modify_defaults_file"); - - if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0)))) - DBUG_RETURN(2); - - /* my_fstat doesn't use the flag parameter */ - if (my_fstat(my_fileno(cnf_file), &file_stat, MYF(0))) - goto malloc_err; - - if (option && option_value) - { - opt_len= strlen(option); - optval_len= strlen(option_value); - } - - new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; - - /* calculate the size of the buffer we need */ - reserve_extended= (opt_len + - 1 + /* For '=' char */ - optval_len + /* Option value len */ - NEWLINE_LEN + /* Space for newline */ - RESERVE); /* Some additional space */ - - buffer_size= (uint)(file_stat.st_size + - 1); /* The ending zero */ - - /* - Reserve space to read the contents of the file and some more - for the option we want to add. - */ - if (!(file_buffer= (char*) my_malloc(buffer_size + reserve_extended, - MYF(MY_WME)))) - goto malloc_err; - - sect_len= strlen(section_name); - - for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); ) - { - /* Skip over whitespaces */ - for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr); - src_ptr++) - {} - - if (!*src_ptr) /* Empty line */ - { - nr_newlines++; - continue; - } - - /* correct the option (if requested) */ - if (option && in_section && !strncmp(src_ptr, option, opt_len) && - (*(src_ptr + opt_len) == '=' || - my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) || - *(src_ptr + opt_len) == '\0')) - { - char *old_src_ptr= src_ptr; - src_ptr= strend(src_ptr+ opt_len); /* Find the end of the line */ - - /* could be negative */ - reserve_occupied+= (int) new_opt_len - (int) (src_ptr - old_src_ptr); - if (reserve_occupied >= (int) reserve_extended) - { - reserve_extended= (uint) reserve_occupied + RESERVE; - if (!(file_buffer= (char*) my_realloc(file_buffer, buffer_size + - reserve_extended, - MYF(MY_WME|MY_FREE_ON_ERROR)))) - goto malloc_err; - } - opt_applied= 1; - dst_ptr= add_option(dst_ptr, option_value, option, remove_option); - } - else - { - /* - If we are going to the new group and have an option to apply, do - it now. If we are removing a single option or the whole section - this will only trigger opt_applied flag. - */ - - if (in_section && !opt_applied && *src_ptr == '[') - { - dst_ptr= add_option(dst_ptr, option_value, option, remove_option); - opt_applied= 1; /* set the flag to do write() later */ - reserve_occupied= new_opt_len+ opt_len + 1 + NEWLINE_LEN; - } - - for (; nr_newlines; nr_newlines--) - dst_ptr= strmov(dst_ptr, NEWLINE); - - /* Skip the section if MY_REMOVE_SECTION was given */ - if (!in_section || remove_option != MY_REMOVE_SECTION) - dst_ptr= strmov(dst_ptr, linebuff); - } - /* Look for a section */ - if (*src_ptr == '[') - { - /* Copy the line to the buffer */ - if (!strncmp(++src_ptr, section_name, sect_len)) - { - src_ptr+= sect_len; - /* Skip over whitespaces. They are allowed after section name */ - for (; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++) - {} - - if (*src_ptr != ']') - { - in_section= FALSE; - continue; /* Missing closing parenthesis. Assume this was no group */ - } - - if (remove_option == MY_REMOVE_SECTION) - dst_ptr= dst_ptr - strlen(linebuff); - - in_section= TRUE; - } - else - in_section= FALSE; /* mark that this section is of no interest to us */ - } - } - - /* - File ended. Apply an option or set opt_applied flag (in case of - MY_REMOVE_SECTION) so that the changes are saved. Do not do anything - if we are removing non-existent option. - */ - - if (!opt_applied && in_section && (remove_option != MY_REMOVE_OPTION)) - { - /* New option still remains to apply at the end */ - if (!remove_option && *(dst_ptr - 1) != '\n') - dst_ptr= strmov(dst_ptr, NEWLINE); - dst_ptr= add_option(dst_ptr, option_value, option, remove_option); - opt_applied= 1; - } - for (; nr_newlines; nr_newlines--) - dst_ptr= strmov(dst_ptr, NEWLINE); - - if (opt_applied) - { - /* Don't write the file if there are no changes to be made */ - if (my_chsize(my_fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0, - MYF(MY_WME)) || - my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) || - my_fwrite(cnf_file, (uchar*) file_buffer, (size_t) (dst_ptr - file_buffer), - MYF(MY_NABP))) - goto err; - } - if (my_fclose(cnf_file, MYF(MY_WME))) - DBUG_RETURN(1); - - my_free(file_buffer, MYF(0)); - DBUG_RETURN(0); - -err: - my_free(file_buffer, MYF(0)); -malloc_err: - my_fclose(cnf_file, MYF(0)); - DBUG_RETURN(1); /* out of resources */ -} - - -static char *add_option(char *dst, const char *option_value, - const char *option, int remove_option) -{ - if (!remove_option) - { - dst= strmov(dst, option); - if (*option_value) - { - *dst++= '='; - dst= strmov(dst, option_value); - } - /* add a newline */ - dst= strmov(dst, NEWLINE); - } - return dst; -} diff --git a/mysys/errors.c b/mysys/errors.c index 33fb9ff7acd..2a9b3e770d2 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -18,7 +18,7 @@ #ifndef SHARED_LIBRARY -const char * NEAR globerrs[GLOBERRS]= +const char *globerrs[GLOBERRS]= { "Can't create/write to file '%s' (Errcode: %d)", "Error reading file '%s' (Errcode: %d)", @@ -97,9 +97,9 @@ void init_glob_errs() EE(EE_FILE_NOT_CLOSED) = "File '%s' (fileno: %d) was not closed"; EE(EE_CHANGE_OWNERSHIP) = "Can't change ownership of the file '%s' (Errcode: %d)"; EE(EE_CHANGE_PERMISSIONS) = "Can't change permissions of the file '%s' (Errcode: %d)"; + EE(EE_CANT_SEEK) = "Can't seek in file '%s' (Errcode: %d)"; EE(EE_CANT_CHMOD) = "Can't change mode for file '%s' to 0x%lx (Error: %d)"; EE(EE_CANT_COPY_OWNERSHIP)= "Warning: Can't copy ownership for file '%s' (Error: %d)"; - EE(EE_CANT_SEEK) = "Can't seek in file '%s' (Errcode: %d)"; } #endif @@ -114,5 +114,10 @@ void wait_for_free_space(const char *filename, int errors) MYF(ME_BELL | ME_NOREFRESH), MY_WAIT_FOR_USER_TO_FIX_PANIC, MY_WAIT_GIVE_USER_A_MESSAGE * MY_WAIT_FOR_USER_TO_FIX_PANIC ); - VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC)); + (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); +} + +const char **get_global_errmsgs() +{ + return globerrs; } diff --git a/mysys/hash.c b/mysys/hash.c index 5ff3c2e99ce..38914d5f350 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -33,16 +33,18 @@ typedef struct st_hash_info { uchar *data; /* data for current entry */ } HASH_LINK; -static uint my_hash_mask(size_t hashnr, size_t buffmax, size_t maxlength); +static uint my_hash_mask(my_hash_value_type hashnr, + size_t buffmax, size_t maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, size_t length); -static uint calc_hash(const HASH *hash, const uchar *key, size_t length) +static my_hash_value_type calc_hash(const HASH *hash, + const uchar *key, size_t length) { ulong nr1=1, nr2=4; hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); - return nr1; + return (my_hash_value_type)nr1; } /** @@ -65,8 +67,6 @@ static uint calc_hash(const HASH *hash, const uchar *key, size_t length) @param[in] get_key get the key for the hash @param[in] free_element pointer to the function that does cleanup - @param[in] CALLER_INFO_PROTO flag that define the behaviour - of the hash @return inidicates success or failure of initialization @retval 0 success @retval 1 failure @@ -75,8 +75,9 @@ my_bool _my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset, ulong size, size_t key_offset, size_t key_length, my_hash_get_key get_key, - void (*free_element)(void*), uint flags CALLER_INFO_PROTO) + void (*free_element)(void*), uint flags) { + my_bool res; DBUG_ENTER("my_hash_init"); DBUG_PRINT("enter",("hash: 0x%lx size: %u", (long) hash, (uint) size)); @@ -88,8 +89,9 @@ _my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset, hash->free=free_element; hash->flags=flags; hash->charset=charset; - DBUG_RETURN(my_init_dynamic_array_ci(&hash->array, - sizeof(HASH_LINK), size, growth_size)); + res= my_init_dynamic_array_ci(&hash->array, + sizeof(HASH_LINK), size, growth_size); + DBUG_RETURN(res); } @@ -180,7 +182,8 @@ my_hash_key(const HASH *hash, const uchar *record, size_t *length, /* Calculate pos according to keys */ -static uint my_hash_mask(size_t hashnr, size_t buffmax, size_t maxlength) +static uint my_hash_mask(my_hash_value_type hashnr, size_t buffmax, + size_t maxlength) { if ((hashnr & (buffmax-1)) < maxlength) return (uint) (hashnr & (buffmax-1)); @@ -202,7 +205,7 @@ static #if !defined(__USLC__) && !defined(__sgi) inline #endif -unsigned int rec_hashnr(HASH *hash,const uchar *record) +my_hash_value_type rec_hashnr(HASH *hash,const uchar *record) { size_t length; uchar *key= (uchar*) my_hash_key(hash, record, &length, 0); @@ -216,6 +219,23 @@ uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) return my_hash_first(hash, key, length, &state); } +uchar* my_hash_search_using_hash_value(const HASH *hash, + my_hash_value_type hash_value, + const uchar *key, + size_t length) +{ + HASH_SEARCH_STATE state; + return my_hash_first_from_hash_value(hash, hash_value, + key, length, &state); +} + +my_hash_value_type my_calc_hash(const HASH *hash, + const uchar *key, size_t length) +{ + return calc_hash(hash, key, length ? length : hash->key_length); +} + + /* Search after a record based on a key @@ -226,14 +246,31 @@ uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, HASH_SEARCH_STATE *current_record) { + uchar *res; + if (my_hash_inited(hash)) + res= my_hash_first_from_hash_value(hash, + calc_hash(hash, key, length ? length : hash->key_length), + key, length, current_record); + else + res= 0; + return res; +} + + +uchar* my_hash_first_from_hash_value(const HASH *hash, + my_hash_value_type hash_value, + const uchar *key, + size_t length, + HASH_SEARCH_STATE *current_record) +{ HASH_LINK *pos; uint flag,idx; - DBUG_ENTER("my_hash_first"); + DBUG_ENTER("my_hash_first_from_hash_value"); flag=1; if (hash->records) { - idx= my_hash_mask(calc_hash(hash, key, length ? length : hash->key_length), + idx= my_hash_mask(hash_value, hash->blength, hash->records); do { @@ -339,7 +376,8 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, my_bool my_hash_insert(HASH *info, const uchar *record) { int flag; - size_t idx,halfbuff,hash_nr,first_index; + size_t idx,halfbuff,first_index; + my_hash_value_type hash_nr; uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; @@ -485,7 +523,8 @@ my_bool my_hash_insert(HASH *info, const uchar *record) my_bool my_hash_delete(HASH *hash, uchar *record) { - uint pos2,pos_hashnr,lastpos_hashnr,idx,empty_index; + uint pos2,idx,empty_index; + my_hash_value_type pos_hashnr, lastpos_hashnr; size_t blength; HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty; DBUG_ENTER("my_hash_delete"); @@ -560,7 +599,7 @@ my_bool my_hash_delete(HASH *hash, uchar *record) pos->next=empty_index; exit: - VOID(pop_dynamic(&hash->array)); + (void) pop_dynamic(&hash->array); if (hash->free) (*hash->free)((uchar*) record); DBUG_RETURN(0); diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 0293bfc6faf..ab88828d2f6 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -3,8 +3,7 @@ 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; either version 2 of the License, or - (at your option) any later version. + 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 @@ -147,6 +146,7 @@ void lf_pinbox_destroy(LF_PINBOX *pinbox) */ LF_PINS *_lf_pinbox_get_pins(LF_PINBOX *pinbox) { + struct st_my_thread_var *var; uint32 pins, next, top_ver; LF_PINS *el; /* @@ -189,7 +189,12 @@ LF_PINS *_lf_pinbox_get_pins(LF_PINBOX *pinbox) el->link= pins; el->purgatory_count= 0; el->pinbox= pinbox; - el->stack_ends_here= & my_thread_var->stack_ends_here; + var= my_thread_var; + /* + Threads that do not call my_thread_init() should still be + able to use the LF_HASH. + */ + el->stack_ends_here= (var ? & var->stack_ends_here : NULL); return el; } @@ -328,35 +333,36 @@ static int match_pins(LF_PINS *el, void *addr) */ static void _lf_pinbox_real_free(LF_PINS *pins) { - int npins, alloca_size; - void *list, **addr; - void *first, *last= NULL; + int npins; + void *list; + void **addr= NULL; + void *first= NULL, *last= NULL; LF_PINBOX *pinbox= pins->pinbox; - LINT_INIT(first); npins= pinbox->pins_in_array+1; #ifdef HAVE_ALLOCA - alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; - /* create a sorted list of pinned addresses, to speed up searches */ - if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size) + if (pins->stack_ends_here != NULL) { - struct st_harvester hv; - addr= (void **) alloca(alloca_size); - hv.granary= addr; - hv.npins= npins; - /* scan the dynarray and accumulate all pinned addresses */ - _lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)harvest_pins, &hv); - - npins= hv.granary-addr; - /* and sort them */ - if (npins) - qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); + int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; + /* create a sorted list of pinned addresses, to speed up searches */ + if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size) + { + struct st_harvester hv; + addr= (void **) alloca(alloca_size); + hv.granary= addr; + hv.npins= npins; + /* scan the dynarray and accumulate all pinned addresses */ + _lf_dynarray_iterate(&pinbox->pinarray, + (lf_dynarray_func)harvest_pins, &hv); + + npins= hv.granary-addr; + /* and sort them */ + if (npins) + qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); + } } - else #endif - addr= 0; list= pins->purgatory; pins->purgatory= 0; @@ -474,7 +480,7 @@ void lf_alloc_destroy(LF_ALLOCATOR *allocator) uchar *tmp= anext_node(node); if (allocator->destructor) allocator->destructor(node); - my_free((void *)node, MYF(0)); + my_free(node); node= tmp; } lf_pinbox_destroy(&allocator->pinbox); diff --git a/mysys/lf_dynarray.c b/mysys/lf_dynarray.c index 7c8f54f07cf..0941c8762bb 100644 --- a/mysys/lf_dynarray.c +++ b/mysys/lf_dynarray.c @@ -2,8 +2,7 @@ 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; either version 2 of the License, or - (at your option) any later version. + 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 @@ -58,10 +57,10 @@ static void recursive_free(void **alloc, int level) int i; for (i= 0; i < LF_DYNARRAY_LEVEL_LENGTH; i++) recursive_free(alloc[i], level-1); - my_free((void *)alloc, MYF(0)); + my_free(alloc); } else - my_free(alloc[-1], MYF(0)); + my_free(alloc[-1]); } void lf_dynarray_destroy(LF_DYNARRAY *array) @@ -116,7 +115,7 @@ void *_lf_dynarray_lvalue(LF_DYNARRAY *array, uint idx) if (my_atomic_casptr(ptr_ptr, &ptr, alloc)) ptr= alloc; else - my_free(alloc, MYF(0)); + my_free(alloc); } ptr_ptr= ((void **)ptr) + idx / dynarray_idxes_in_prev_level[i]; idx%= dynarray_idxes_in_prev_level[i]; @@ -140,7 +139,7 @@ void *_lf_dynarray_lvalue(LF_DYNARRAY *array, uint idx) if (my_atomic_casptr(ptr_ptr, &ptr, data)) ptr= data; else - my_free(alloc, MYF(0)); + my_free(alloc); } return ((uchar*)ptr) + array->size_of_element * idx; } diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c index 6569bafc00d..2c89f5ca7ca 100644 --- a/mysys/lf_hash.c +++ b/mysys/lf_hash.c @@ -2,8 +2,7 @@ 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; either version 2 of the License, or - (at your option) any later version. + 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 @@ -315,7 +314,7 @@ static int initialize_bucket(LF_HASH *, LF_SLIST * volatile*, uint, LF_PINS *); See wt_init() for example. */ void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, - uint key_offset, uint key_length, hash_get_key get_key, + uint key_offset, uint key_length, my_hash_get_key get_key, CHARSET_INFO *charset) { lf_alloc_init(&hash->alloc, sizeof(LF_SLIST)+element_size, @@ -346,7 +345,7 @@ void lf_hash_destroy(LF_HASH *hash) if (el->hashnr & 1) lf_alloc_direct_free(&hash->alloc, el); /* normal node */ else - my_free((void *)el, MYF(0)); /* dummy node */ + my_free(el); /* dummy node */ el= (LF_SLIST *)next; } lf_alloc_destroy(&hash->alloc); @@ -491,7 +490,7 @@ static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node, dummy->keylen= 0; if ((cur= linsert(el, hash->charset, dummy, pins, LF_HASH_UNIQUE))) { - my_free((void *)dummy, MYF(0)); + my_free(dummy); dummy= cur; } my_atomic_casptr((void **)node, (void **)(char*) &tmp, dummy); diff --git a/mysys/list.c b/mysys/list.c index aaadd686365..e68fbf519d1 100644 --- a/mysys/list.c +++ b/mysys/list.c @@ -61,8 +61,8 @@ void list_free(LIST *root, uint free_data) { next=root->next; if (free_data) - my_free((uchar*) root->data,MYF(0)); - my_free((uchar*) root,MYF(0)); + my_free(root->data); + my_free(root); root=next; } } diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index dcb03d7f073..0116cdd2c20 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -1625,8 +1625,7 @@ dynamic_column_list(DYNAMIC_COLUMN *str, DYNAMIC_ARRAY *array_of_uint) if (entry_size * column_count + FIXED_HEADER_SIZE > str->length) return ER_DYNCOL_FORMAT; - if (init_dynamic_array(array_of_uint, sizeof(uint), - column_count, 0 CALLER_INFO)) + if (init_dynamic_array(array_of_uint, sizeof(uint), column_count, 0)) return ER_DYNCOL_RESOURCE; for (i= 0, read= (uchar *)str->str + FIXED_HEADER_SIZE; @@ -2080,7 +2079,7 @@ dynamic_column_update_many(DYNAMIC_COLUMN *str, rc= ER_DYNCOL_OK; end: - my_free(plan, MYF(0)); + my_free(plan); return rc; create_new_string: diff --git a/mysys/make-ccc b/mysys/make-ccc deleted file mode 100755 index b34bd80e1d1..00000000000 --- a/mysys/make-ccc +++ /dev/null @@ -1,4 +0,0 @@ -rm -f .deps/* raid.o mf_iocache.o libmysys.a -ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_malloc.c my_messnc.c my_mkdir.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c -make raid.o mf_iocache.o my_lock.o -ar -cr libmysys.a array.o raid.o mf_iocache.o my_lock.o diff --git a/mysys/make-conf.c b/mysys/make-conf.c deleted file mode 100644 index 0dacde4dee0..00000000000 --- a/mysys/make-conf.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* make-conf.c - * make a charset .conf file out of a ctype-charset.c file. - */ - -#ifndef CHARSET -#error You must define the charset, e.g.: -DCHARSET=latin1 -#endif - -/* some pre-processor tricks to get us going */ -#define _STRINGIZE_HELPER(x) #x -#define STRINGIZE(x) _STRINGIZE_HELPER(x) - -#define _JOIN_WORDS_HELPER(a, b) a ## b -#define JOIN_WORDS(a, b) _JOIN_WORDS_HELPER(a, b) - -#define CH_SRC ctype- ## CHARSET ## .c -#define CH_INCLUDE STRINGIZE(CH_SRC) - -/* aaaah, that's better */ -#include <my_my_global.h> -#include CH_INCLUDE - -#include <stdio.h> -#include <stdlib.h> - -#define ROW_LEN 16 - -void print_array(const char *name, const uchar *array, uint size); - -int main(void) -{ - printf("# Configuration file for the " - STRINGIZE(CHARSET) - " character set.\n"); - - print_array("ctype", JOIN_WORDS(ctype_, CHARSET), 257); - print_array("to_lower", JOIN_WORDS(to_lower_, CHARSET), 256); - print_array("to_upper", JOIN_WORDS(to_upper_, CHARSET), 256); - print_array("sort_order", JOIN_WORDS(sort_order_, CHARSET), 256); - - exit(EXIT_SUCCESS); -} - -void print_array(const char *name, const uchar *array, uint size) -{ - uint i; - - printf("\n# The %s array must have %d elements.\n", name, size); - - for (i = 0; i < size; ++i) { - printf(" %02X", array[i]); - - if ((i+1) % ROW_LEN == size % ROW_LEN) - printf("\n"); - } -} diff --git a/mysys/mf_brkhant.c b/mysys/mf_brkhant.c deleted file mode 100644 index 3573b9973b2..00000000000 --- a/mysys/mf_brkhant.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* Dont let the user break when you are doing something important */ -/* Remembers if it got 'SIGINT' and executes it on allow_break */ -/* A static buffer is used; don't call dont_break() twice in a row */ - -#include "mysys_priv.h" -#include "my_static.h" - - /* Set variable that we can't break */ - -#if !defined(THREAD) -void dont_break(void) -{ - my_dont_interrupt=1; - return; -} /* dont_break */ - -void allow_break(void) -{ - { - reg1 int index; - - my_dont_interrupt=0; - if (_my_signals) - { - if (_my_signals > MAX_SIGNALS) - _my_signals=MAX_SIGNALS; - for (index=0 ; index < _my_signals ; index++) - { - if (_my_sig_remember[index].func) /* Safequard */ - { - (*_my_sig_remember[index].func)(_my_sig_remember[index].number); - _my_sig_remember[index].func=0; - } - } - _my_signals=0; - } - } -} /* dont_break */ -#endif - - /* Set old status */ - -#if !defined(THREAD) -void my_remember_signal(int signal_number, sig_handler (*func) (int)) -{ -#ifndef __WIN__ - reg1 int index; - - index=_my_signals++; /* Nobody can break a ++ ? */ - if (index < MAX_SIGNALS) - { - _my_sig_remember[index].number=signal_number; - _my_sig_remember[index].func=func; - } -#endif /* __WIN__ */ -} /* my_remember_signal */ -#endif /* THREAD */ diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c index f0df0f3fa77..691532c0d80 100644 --- a/mysys/mf_cache.c +++ b/mysys/mf_cache.c @@ -71,8 +71,8 @@ my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix, { DBUG_RETURN(0); } - my_free(cache->dir, MYF(MY_ALLOW_ZERO_PTR)); - my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR)); + my_free(cache->dir); + my_free(cache->prefix); DBUG_RETURN(1); } @@ -110,12 +110,12 @@ void close_cached_file(IO_CACHE *cache) if (cache->file_name) { (void) my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)); - my_free(cache->file_name,MYF(0)); + my_free(cache->file_name); } #endif } - my_free(cache->dir,MYF(MY_ALLOW_ZERO_PTR)); - my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR)); + my_free(cache->dir); + my_free(cache->prefix); } DBUG_VOID_RETURN; } diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c index 1b428ded751..5a9440483e4 100644 --- a/mysys/mf_dirname.c +++ b/mysys/mf_dirname.c @@ -40,11 +40,7 @@ size_t dirname_length(const char *name) continue; } #endif - if (*pos == FN_LIBCHAR || *pos == '/' -#ifdef FN_C_AFTER_DIR - || *pos == FN_C_AFTER_DIR || *pos == FN_C_AFTER_DIR_2 -#endif - ) + if (*pos == FN_LIBCHAR || *pos == '/') gpos=pos; } return (size_t) (gpos+1-(char*) name); @@ -88,8 +84,7 @@ size_t dirname_part(char *to, const char *name, size_t *to_res_length) from_end Pointer at end of filename (normally end \0) IMPLEMENTATION - If MSDOS converts '/' to '\' - If VMS converts '<' to '[' and '>' to ']' + If Windows converts '/' to '\' Adds a FN_LIBCHAR to end if the result string if there isn't one and the last isn't dev_char. Copies data from 'from' until ASCII(0) for until from == from_end @@ -118,18 +113,12 @@ char *convert_dirname(char *to, const char *from, const char *from_end) if (!from_end || (from_end - from) > FN_REFLEN-2) from_end=from+FN_REFLEN -2; -#if FN_LIBCHAR != '/' || defined(FN_C_BEFORE_DIR_2) +#if FN_LIBCHAR != '/' { for (; from != from_end && *from ; from++) { if (*from == '/') *to++= FN_LIBCHAR; -#ifdef FN_C_BEFORE_DIR_2 - else if (*from == FN_C_BEFORE_DIR_2) - *to++= FN_C_BEFORE_DIR; - else if (*from == FN_C_AFTER_DIR_2) - *to++= FN_C_AFTER_DIR; -#endif else { #ifdef BACKSLASH_MBTAIL diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c index da7fac3de73..c872f2993c4 100644 --- a/mysys/mf_fn_ext.c +++ b/mysys/mf_fn_ext.c @@ -39,7 +39,7 @@ char *fn_ext(const char *name) DBUG_ENTER("fn_ext"); DBUG_PRINT("mfunkt",("name: '%s'",name)); -#if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR) || defined(BASKSLASH_MBTAIL) +#if defined(FN_DEVCHAR) || defined(BASKSLASH_MBTAIL) { char buff[FN_REFLEN]; size_t res_length; diff --git a/mysys/mf_format.c b/mysys/mf_format.c index 6afa2938fa3..74f114a966f 100644 --- a/mysys/mf_format.c +++ b/mysys/mf_format.c @@ -31,6 +31,8 @@ char * fn_format(char * to, const char *name, const char *dir, reg1 size_t length; size_t dev_length; DBUG_ENTER("fn_format"); + DBUG_ASSERT(name != NULL); + DBUG_ASSERT(extension != NULL); DBUG_PRINT("enter",("name: %s dir: %s extension: %s flag: %d", name,dir,extension,flag)); diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 1905437cc0a..cde11f3cae5 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -47,7 +47,6 @@ TODO: write buffer to the read buffer before we start to reuse it. */ -#define MAP_TO_USE_RAID #include "mysys_priv.h" #include <m_string.h> #ifdef HAVE_AIOWAIT @@ -56,15 +55,10 @@ static void my_aiowait(my_aio_result *result); #endif #include <errno.h> -#ifdef THREAD #define lock_append_buffer(info) \ - pthread_mutex_lock(&(info)->append_buffer_lock) + mysql_mutex_lock(&(info)->append_buffer_lock) #define unlock_append_buffer(info) \ - pthread_mutex_unlock(&(info)->append_buffer_lock) -#else -#define lock_append_buffer(info) -#define unlock_append_buffer(info) -#endif + mysql_mutex_unlock(&(info)->append_buffer_lock) #define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1)) #define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1)) @@ -117,11 +111,7 @@ init_functions(IO_CACHE* info) info->write_function = 0; /* Force a core if used */ break; default: - info->read_function = -#ifdef THREAD - info->share ? _my_b_read_r : -#endif - _my_b_read; + info->read_function = info->share ? _my_b_read_r : _my_b_read; info->write_function = _my_b_write; } @@ -174,7 +164,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, if (file >= 0) { - pos= my_tell(file, MYF(0)); + pos= mysql_file_tell(file, MYF(0)); if ((pos == (my_off_t) -1) && (my_errno == ESPIPE)) { /* @@ -194,9 +184,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, } info->disk_writes= 0; -#ifdef THREAD info->share=0; -#endif if (!cachesize && !(cachesize= my_default_record_cache_size)) DBUG_RETURN(1); /* No cache requested */ @@ -206,7 +194,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, if (!(cache_myflags & MY_DONT_CHECK_FILESIZE)) { /* Calculate end of file to avoid allocating oversized buffers */ - end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); + end_of_file= mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0)); /* Need to reset seek_not_done now that we just did a seek. */ info->seek_not_done= end_of_file == seek_offset ? 0 : 1; if (end_of_file < seek_offset) @@ -264,11 +252,10 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, { info->append_read_pos = info->write_pos = info->write_buffer; info->write_end = info->write_buffer + info->buffer_length; -#ifdef THREAD - pthread_mutex_init(&info->append_buffer_lock,MY_MUTEX_INIT_FAST); -#endif + mysql_mutex_init(key_IO_CACHE_append_buffer_lock, + &info->append_buffer_lock, MY_MUTEX_INIT_FAST); } -#if defined(SAFE_MUTEX) && defined(THREAD) +#if defined(SAFE_MUTEX) else { /* Clear mutex so that safe_mutex will notice that it's not initialized */ @@ -454,7 +441,9 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, RETURN 0 we succeeded in reading all data - 1 Error: can't read requested characters + 1 Error: couldn't read requested characters. In this case: + If info->error == -1, we got a read error. + Otherwise info->error contains the number of bytes in Buffer. */ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) @@ -463,6 +452,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) my_off_t pos_in_file; DBUG_ENTER("_my_b_read"); + /* If the buffer is not empty yet, copy what is available. */ if ((left_length= (size_t) (info->read_end-info->read_pos))) { DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */ @@ -474,7 +464,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) /* pos_in_file always point on where info->buffer was read */ pos_in_file=info->pos_in_file+ (size_t) (info->read_end - info->buffer); - /* + /* Whenever a function which operates on IO_CACHE flushes/writes some part of the IO_CACHE to disk it will set the property "seek_not_done" to indicate this to other functions operating @@ -482,7 +472,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) */ if (info->seek_not_done) { - if ((my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) + if ((mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) != MY_FILEPOS_ERROR)) { /* No error, reset seek_not_done flag. */ @@ -501,19 +491,38 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) } } + /* + Calculate, how much we are within a IO_SIZE block. Ideally this + should be zero. + */ diff_length= (size_t) (pos_in_file & (IO_SIZE-1)); + + /* + If more than a block plus the rest of the current block is wanted, + we do read directly, without filling the buffer. + */ if (Count >= (size_t) (IO_SIZE+(IO_SIZE-diff_length))) { /* Fill first intern buffer */ size_t read_length; if (info->end_of_file <= pos_in_file) - { /* End of file */ + { + /* End of file. Return, what we did copy from the buffer. */ info->error= (int) left_length; DBUG_RETURN(1); } + /* + Crop the wanted count to a multiple of IO_SIZE and subtract, + what we did already read from a block. That way, the read will + end aligned with a block. + */ length=(Count & (size_t) ~(IO_SIZE-1))-diff_length; - if ((read_length= my_read(info->file,Buffer, length, info->myflags)) + if ((read_length= mysql_file_read(info->file,Buffer, length, info->myflags)) != length) { + /* + If we didn't get, what we wanted, we either return -1 for a read + error, or (it's end of file), how much we got in total. + */ info->error= (read_length == (size_t) -1 ? -1 : (int) (read_length+left_length)); DBUG_RETURN(1); @@ -525,30 +534,52 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) diff_length=0; } + /* + At this point, we want less than one and a partial block. + We will read a full cache, minus the number of bytes, we are + within a block already. So we will reach new alignment. + */ max_length= info->read_length-diff_length; + /* We will not read past end of file. */ if (info->type != READ_FIFO && max_length > (info->end_of_file - pos_in_file)) max_length= (size_t) (info->end_of_file - pos_in_file); + /* + If there is nothing left to read, + we either are done, or we failed to fulfill the request. + Otherwise, we read max_length into the cache. + */ if (!max_length) { if (Count) { - info->error= (int) left_length; /* We only got this many char */ + /* We couldn't fulfil the request. Return, how much we got. */ + info->error= (int) left_length; DBUG_RETURN(1); } length=0; /* Didn't read any chars */ } - else if ((length= my_read(info->file,info->buffer, max_length, + else if ((length= mysql_file_read(info->file,info->buffer, max_length, info->myflags)) < Count || length == (size_t) -1) { + /* + We got an read error, or less than requested (end of file). + If not a read error, copy, what we got. + */ if (length != (size_t) -1) memcpy(Buffer, info->buffer, length); info->pos_in_file= pos_in_file; + /* For a read error, return -1, otherwise, what we got in total. */ info->error= length == (size_t) -1 ? -1 : (int) (length+left_length); info->read_pos=info->read_end=info->buffer; DBUG_RETURN(1); } + /* + Count is the remaining number of bytes requested. + length is the amount of data in the cache. + Read Count bytes from the cache. + */ info->read_pos=info->buffer+Count; info->read_end=info->buffer+length; info->pos_in_file=pos_in_file; @@ -557,7 +588,6 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) } -#ifdef THREAD /* Prepare IO_CACHE for shared use. @@ -639,9 +669,10 @@ void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, DBUG_ASSERT(read_cache->type == READ_CACHE); DBUG_ASSERT(!write_cache || (write_cache->type == WRITE_CACHE)); - pthread_mutex_init(&cshare->mutex, MY_MUTEX_INIT_FAST); - pthread_cond_init(&cshare->cond, 0); - pthread_cond_init(&cshare->cond_writer, 0); + mysql_mutex_init(key_IO_CACHE_SHARE_mutex, + &cshare->mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_IO_CACHE_SHARE_cond, &cshare->cond, 0); + mysql_cond_init(key_IO_CACHE_SHARE_cond_writer, &cshare->cond_writer, 0); cshare->running_threads= num_threads; cshare->total_threads= num_threads; @@ -692,7 +723,7 @@ void remove_io_thread(IO_CACHE *cache) if (cache == cshare->source_cache) flush_io_cache(cache); - pthread_mutex_lock(&cshare->mutex); + mysql_mutex_lock(&cshare->mutex); DBUG_PRINT("io_cache_share", ("%s: 0x%lx", (cache == cshare->source_cache) ? "writer" : "reader", (long) cache)); @@ -715,18 +746,18 @@ void remove_io_thread(IO_CACHE *cache) if (!--cshare->running_threads) { DBUG_PRINT("io_cache_share", ("the last running thread leaves, wake all")); - pthread_cond_signal(&cshare->cond_writer); - pthread_cond_broadcast(&cshare->cond); + mysql_cond_signal(&cshare->cond_writer); + mysql_cond_broadcast(&cshare->cond); } - pthread_mutex_unlock(&cshare->mutex); + mysql_mutex_unlock(&cshare->mutex); if (!total) { DBUG_PRINT("io_cache_share", ("last thread removed, destroy share")); - pthread_cond_destroy (&cshare->cond_writer); - pthread_cond_destroy (&cshare->cond); - pthread_mutex_destroy(&cshare->mutex); + mysql_cond_destroy (&cshare->cond_writer); + mysql_cond_destroy (&cshare->cond); + mysql_mutex_destroy(&cshare->mutex); } DBUG_VOID_RETURN; @@ -767,7 +798,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) DBUG_ENTER("lock_io_cache"); /* Enter the lock. */ - pthread_mutex_lock(&cshare->mutex); + mysql_mutex_lock(&cshare->mutex); cshare->running_threads--; DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", (cache == cshare->source_cache) ? @@ -784,7 +815,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) while (cshare->running_threads) { DBUG_PRINT("io_cache_share", ("writer waits in lock")); - pthread_cond_wait(&cshare->cond_writer, &cshare->mutex); + mysql_cond_wait(&cshare->cond_writer, &cshare->mutex); } DBUG_PRINT("io_cache_share", ("writer awoke, going to copy")); @@ -796,7 +827,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) if (!cshare->running_threads) { DBUG_PRINT("io_cache_share", ("waking writer")); - pthread_cond_signal(&cshare->cond_writer); + mysql_cond_signal(&cshare->cond_writer); } /* @@ -808,7 +839,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) cshare->source_cache) { DBUG_PRINT("io_cache_share", ("reader waits in lock")); - pthread_cond_wait(&cshare->cond, &cshare->mutex); + mysql_cond_wait(&cshare->cond, &cshare->mutex); } /* @@ -850,7 +881,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) cshare->running_threads) { DBUG_PRINT("io_cache_share", ("reader waits in lock")); - pthread_cond_wait(&cshare->cond, &cshare->mutex); + mysql_cond_wait(&cshare->cond, &cshare->mutex); } /* If the block is not yet read, continue with a locked cache and read. */ @@ -872,7 +903,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) Leave the lock. Do not call unlock_io_cache() later. The thread that filled the buffer did this and marked all threads as running. */ - pthread_mutex_unlock(&cshare->mutex); + mysql_mutex_unlock(&cshare->mutex); DBUG_RETURN(0); } @@ -915,8 +946,8 @@ static void unlock_io_cache(IO_CACHE *cache) cshare->total_threads)); cshare->running_threads= cshare->total_threads; - pthread_cond_broadcast(&cshare->cond); - pthread_mutex_unlock(&cshare->mutex); + mysql_cond_broadcast(&cshare->cond); + mysql_mutex_unlock(&cshare->mutex); DBUG_VOID_RETURN; } @@ -1011,7 +1042,7 @@ int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count) */ if (cache->seek_not_done) { - if (my_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0)) + if (mysql_file_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) { cache->error= -1; @@ -1019,7 +1050,7 @@ int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count) DBUG_RETURN(1); } } - len= my_read(cache->file, cache->buffer, length, cache->myflags); + len= mysql_file_read(cache->file, cache->buffer, length, cache->myflags); } DBUG_PRINT("io_cache_share", ("read %lu bytes", (ulong) len)); @@ -1117,7 +1148,6 @@ static void copy_to_read_buffer(IO_CACHE *write_cache, write_length-= copy_length; } } -#endif /*THREAD*/ /* @@ -1158,7 +1188,7 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count) With read-append cache we must always do a seek before we read, because the write could have moved the file pointer astray */ - if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) == MY_FILEPOS_ERROR) + if (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) { info->error= -1; unlock_append_buffer(info); @@ -1175,8 +1205,8 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count) size_t read_length; length=(Count & (size_t) ~(IO_SIZE-1))-diff_length; - if ((read_length= my_read(info->file,Buffer, length, - info->myflags)) == (size_t) -1) + if ((read_length= mysql_file_read(info->file,Buffer, length, + info->myflags)) == (size_t) -1) { info->error= -1; unlock_append_buffer(info); @@ -1209,7 +1239,7 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count) } else { - length= my_read(info->file,info->buffer, max_length, info->myflags); + length= mysql_file_read(info->file,info->buffer, max_length, info->myflags); if (length == (size_t) -1) { info->error= -1; @@ -1386,7 +1416,7 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count) return 1; } - if (my_seek(info->file,next_pos_in_file,MY_SEEK_SET,MYF(0)) + if (mysql_file_seek(info->file, next_pos_in_file, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) { info->error= -1; @@ -1396,8 +1426,8 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count) read_length=IO_SIZE*2- (size_t) (next_pos_in_file & (IO_SIZE-1)); if (Count < read_length) { /* Small block, read to cache */ - if ((read_length=my_read(info->file,info->request_pos, - read_length, info->myflags)) == (size_t) -1) + if ((read_length=mysql_file_read(info->file,info->request_pos, + read_length, info->myflags)) == (size_t) -1) return info->error= -1; use_length=min(Count,read_length); memcpy(Buffer,info->request_pos,(size_t) use_length); @@ -1417,7 +1447,7 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count) } else { /* Big block, don't cache it */ - if ((read_length= my_read(info->file,Buffer, Count,info->myflags)) + if ((read_length= mysql_file_read(info->file, Buffer, Count,info->myflags)) != Count) { info->error= read_length == (size_t) -1 ? -1 : read_length+left_length; @@ -1524,17 +1554,16 @@ int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count) "seek_not_done" to indicate this to other functions operating on the IO_CACHE. */ - if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0))) + if (mysql_file_seek(info->file, info->pos_in_file, MY_SEEK_SET, MYF(0))) { info->error= -1; return (1); } info->seek_not_done=0; } - if (my_write(info->file, Buffer, length, info->myflags | MY_NABP)) + if (mysql_file_write(info->file, Buffer, length, info->myflags | MY_NABP)) return info->error= -1; -#ifdef THREAD /* In case of a shared I/O cache with a writer we normally do direct write cache to read cache copy. Simulate this here by direct @@ -1548,7 +1577,6 @@ int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count) */ if (info->share) copy_to_read_buffer(info, Buffer, length); -#endif Count-=length; Buffer+=length; @@ -1570,13 +1598,11 @@ int my_b_append(register IO_CACHE *info, const uchar *Buffer, size_t Count) { size_t rest_length,length; -#ifdef THREAD /* Assert that we cannot come here with a shared cache. If we do one day, we might need to add a call to copy_to_read_buffer(). */ DBUG_ASSERT(!info->share); -#endif lock_append_buffer(info); rest_length= (size_t) (info->write_end - info->write_pos); @@ -1594,7 +1620,7 @@ int my_b_append(register IO_CACHE *info, const uchar *Buffer, size_t Count) if (Count >= IO_SIZE) { /* Fill first intern buffer */ length=Count & (size_t) ~(IO_SIZE-1); - if (my_write(info->file,Buffer, length, info->myflags | MY_NABP)) + if (mysql_file_write(info->file,Buffer, length, info->myflags | MY_NABP)) { unlock_append_buffer(info); return info->error= -1; @@ -1638,23 +1664,21 @@ int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count, size_t length; int error=0; -#ifdef THREAD /* Assert that we cannot come here with a shared cache. If we do one day, we might need to add a call to copy_to_read_buffer(). */ DBUG_ASSERT(!info->share); -#endif if (pos < info->pos_in_file) { /* Of no overlap, write everything without buffering */ if (pos + Count <= info->pos_in_file) - return (int) my_pwrite(info->file, Buffer, Count, pos, - info->myflags | MY_NABP); + return (int)mysql_file_pwrite(info->file, Buffer, Count, pos, + info->myflags | MY_NABP); /* Write the part of the block that is before buffer */ length= (uint) (info->pos_in_file - pos); - if (my_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP)) + if (mysql_file_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP)) info->error= error= -1; Buffer+=length; pos+= length; @@ -1687,16 +1711,10 @@ int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count, /* Flush write cache */ -#ifdef THREAD #define LOCK_APPEND_BUFFER if (need_append_buffer_lock) \ lock_append_buffer(info); #define UNLOCK_APPEND_BUFFER if (need_append_buffer_lock) \ unlock_append_buffer(info); -#else -#define LOCK_APPEND_BUFFER -#define UNLOCK_APPEND_BUFFER -#endif - int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock __attribute__((unused))) @@ -1707,10 +1725,8 @@ int my_b_flush_io_cache(IO_CACHE *info, DBUG_ENTER("my_b_flush_io_cache"); DBUG_PRINT("enter", ("cache: 0x%lx", (long) info)); -#ifdef THREAD if (!append_cache) need_append_buffer_lock= 0; -#endif if (info->type == WRITE_CACHE || append_cache) { @@ -1723,7 +1739,6 @@ int my_b_flush_io_cache(IO_CACHE *info, if ((length=(size_t) (info->write_pos - info->write_buffer))) { -#ifdef THREAD /* In case of a shared I/O cache with a writer we do direct write cache to read cache copy. Do it before the write here so that @@ -1732,7 +1747,6 @@ int my_b_flush_io_cache(IO_CACHE *info, */ if (info->share) copy_to_read_buffer(info, info->write_buffer, length); -#endif pos_in_file=info->pos_in_file; /* @@ -1741,7 +1755,7 @@ int my_b_flush_io_cache(IO_CACHE *info, */ if (!append_cache && info->seek_not_done) { /* File touched, do seek */ - if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) == + if (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) { UNLOCK_APPEND_BUFFER; @@ -1755,7 +1769,7 @@ int my_b_flush_io_cache(IO_CACHE *info, info->write_end= (info->write_buffer+info->buffer_length- ((pos_in_file+length) & (IO_SIZE-1))); - if (my_write(info->file,info->write_buffer,length, + if (mysql_file_write(info->file,info->write_buffer,length, info->myflags | MY_NABP)) info->error= -1; else @@ -1767,7 +1781,7 @@ int my_b_flush_io_cache(IO_CACHE *info, else { info->end_of_file+=(info->write_pos-info->append_read_pos); - DBUG_ASSERT(info->end_of_file == my_tell(info->file,MYF(0))); + DBUG_ASSERT(info->end_of_file == mysql_file_tell(info->file, MYF(0))); } info->append_read_pos=info->write_pos=info->write_buffer; @@ -1811,13 +1825,11 @@ int end_io_cache(IO_CACHE *info) DBUG_ENTER("end_io_cache"); DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info)); -#ifdef THREAD /* Every thread must call remove_io_thread(). The last one destroys the share elements. */ DBUG_ASSERT(!info->share || !info->share->total_threads); -#endif if ((pre_close=info->pre_close)) { @@ -1829,20 +1841,16 @@ int end_io_cache(IO_CACHE *info) info->alloced_buffer=0; if (info->file != -1) /* File doesn't exist */ error= my_b_flush_io_cache(info,1); - my_free((uchar*) info->buffer,MYF(MY_WME)); + my_free(info->buffer); info->buffer=info->read_pos=(uchar*) 0; } if (info->type == SEQ_READ_APPEND) { /* Destroy allocated mutex */ info->type= TYPE_NOT_SET; -#ifdef THREAD - pthread_mutex_destroy(&info->append_buffer_lock); -#endif + mysql_mutex_destroy(&info->append_buffer_lock); } -#ifdef THREAD info->share= 0; -#endif DBUG_RETURN(error); } /* end_io_cache */ @@ -1918,7 +1926,7 @@ int main(int argc, char** argv) total_bytes += 4+block_size; } close_file(&sra_cache); - my_free(block,MYF(MY_WME)); + my_free(block); if (!my_stat(fname,&status,MYF(MY_WME))) die("%s failed to stat, but I had just closed it,\ wonder how that happened"); diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index e83ba7b82fb..85631e9741b 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -17,7 +17,6 @@ More functions to be used with IO_CACHE files */ -#define MAP_TO_USE_RAID #include "mysys_priv.h" #include <m_string.h> #include <stdarg.h> @@ -71,6 +70,16 @@ my_b_copy_to_file(IO_CACHE *cache, FILE *file) my_off_t my_b_append_tell(IO_CACHE* info) { /* + Sometimes we want to make sure that the variable is not put into + a register in debugging mode so we can see its value in the core + */ +#ifndef DBUG_OFF +# define dbug_volatile volatile +#else +# define dbug_volatile +#endif + + /* Prevent optimizer from putting res in a register when debugging we need this to be able to see the value of res when the assert fails */ @@ -81,9 +90,8 @@ my_off_t my_b_append_tell(IO_CACHE* info) from messing with the variables that we need in order to provide the answer to the question. */ -#ifdef THREAD - pthread_mutex_lock(&info->append_buffer_lock); -#endif + mysql_mutex_lock(&info->append_buffer_lock); + #ifndef DBUG_OFF /* Make sure EOF is where we think it is. Note that we cannot just use @@ -103,9 +111,7 @@ my_off_t my_b_append_tell(IO_CACHE* info) } #endif res = info->end_of_file + (info->write_pos-info->append_read_pos); -#ifdef THREAD - pthread_mutex_unlock(&info->append_buffer_lock); -#endif + mysql_mutex_unlock(&info->append_buffer_lock); return res; } @@ -135,7 +141,7 @@ void my_b_seek(IO_CACHE *info,my_off_t pos) b) see if there is a better way to make it work */ if (info->type == SEQ_READ_APPEND) - VOID(flush_io_cache(info)); + (void) flush_io_cache(info); offset=(pos - info->pos_in_file); @@ -163,7 +169,7 @@ void my_b_seek(IO_CACHE *info,my_off_t pos) info->write_pos = info->write_buffer + offset; DBUG_VOID_RETURN; } - VOID(flush_io_cache(info)); + (void) flush_io_cache(info); /* Correct buffer end so that we write in increments of IO_SIZE */ info->write_end=(info->write_buffer+info->buffer_length- (pos & (IO_SIZE-1))); @@ -465,52 +471,3 @@ err: return (size_t) -1; } - -int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, - const char *default_val) -{ - uint length; - DBUG_ENTER("init_strvar_from_file"); - - if ((length=my_b_gets(f,var, max_size))) - { - char* last_p = var + length -1; - if (*last_p == '\n') - *last_p = 0; /* if we stopped on newline, kill it */ - else - { - /* - If we truncated a line or stopped on last char, remove all chars - up to and including newline. - */ - int c; - while (((c=my_b_get(f)) != '\n' && c != my_b_EOF)) - ; - } - DBUG_RETURN(0); - } - else if (default_val) - { - strmake(var, default_val, max_size-1); - DBUG_RETURN(0); - } - DBUG_RETURN(1); -} - -int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) -{ - char buf[32]; - DBUG_ENTER("init_intvar_from_file"); - - if (my_b_gets(f, buf, sizeof(buf))) - { - *var = atoi(buf); - DBUG_RETURN(0); - } - else if (default_val) - { - *var = default_val; - DBUG_RETURN(0); - } - DBUG_RETURN(1); -} diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 00e5f0874a2..80111b3245d 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -35,6 +35,7 @@ #include <my_bit.h> #include <errno.h> #include <stdarg.h> +#include "probes_mysql.h" /****************************************************************************** Simple Key Cache Module @@ -88,13 +89,13 @@ time only. Before starting to wait on its condition variable with - pthread_cond_wait(), the thread enters itself to a specific wait queue + mysql_cond_wait(), the thread enters itself to a specific wait queue with link_into_queue() (double linked with '*next' + '**prev') or wait_on_queue() (single linked with '*next'). Another thread, when releasing a resource, looks up the waiting thread in the related wait queue. It sends a signal with - pthread_cond_signal() to the waiting thread. + mysql_cond_signal() to the waiting thread. NOTE: Depending on the particular wait situation, either the sending thread removes the waiting thread from the wait queue with @@ -154,11 +155,11 @@ typedef struct st_keycache_wqueue typedef struct st_simple_key_cache_cb { - my_bool key_cache_inited; /* <=> control block is allocated */ + my_bool key_cache_inited; /* <=> control block is allocated */ my_bool in_resize; /* true during resize operation */ my_bool resize_in_flush; /* true during flush of resize operation */ my_bool can_be_used; /* usage of cache for read/write is allowed */ - size_t key_cache_mem_size; /* specified size of the cache memory */ + size_t key_cache_mem_size; /* specified size of the cache memory */ uint key_cache_block_size; /* size of the page buffer of a cache block */ ulong min_warm_blocks; /* min number of warm blocks; */ ulong age_threshold; /* age threshold for hot blocks */ @@ -176,12 +177,12 @@ typedef struct st_simple_key_cache_cb HASH_LINK **hash_root; /* arr. of entries into hash table buckets */ HASH_LINK *hash_link_root; /* memory for hash table links */ HASH_LINK *free_hash_list; /* list of free hash links */ - BLOCK_LINK *free_block_list; /* list of free blocks */ + BLOCK_LINK *free_block_list; /* list of free blocks */ BLOCK_LINK *block_root; /* memory for block links */ - uchar HUGE_PTR *block_mem; /* memory for block buffers */ + uchar *block_mem; /* memory for block buffers */ BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */ BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */ - pthread_mutex_t cache_lock; /* to lock access to the cache structure */ + mysql_mutex_t cache_lock; /* to lock access to the cache structure */ KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */ /* Waiting for a zero resize count. Using a queue for symmetry though @@ -194,7 +195,7 @@ typedef struct st_simple_key_cache_cb BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/ /* Statistics variables. These are reset in reset_key_cache_counters(). */ - ulong global_blocks_changed; /* number of currently dirty blocks */ + ulong global_blocks_changed; /* number of currently dirty blocks */ ulonglong global_cache_w_requests;/* number of write requests (write hits) */ ulonglong global_cache_write; /* number of writes from cache to files */ ulonglong global_cache_r_requests;/* number of read requests (read hits) */ @@ -219,8 +220,8 @@ typedef struct st_simple_key_cache_cb accessing it; to set this number equal to <N> add #define MAX_THREADS <N> - - to substitute calls of pthread_cond_wait for calls of - pthread_cond_timedwait (wait with timeout set up); + - to substitute calls of mysql_cond_wait for calls of + mysql_cond_timedwait (wait with timeout set up); this setting should be used only when you want to trap a deadlock situation, which theoretically should not happen; to set timeout equal to <T> seconds add @@ -251,7 +252,7 @@ typedef struct st_simple_key_cache_cb #define COND_FOR_SAVED 1 #define COND_FOR_READERS 2 -typedef pthread_cond_t KEYCACHE_CONDVAR; +typedef mysql_cond_t KEYCACHE_CONDVAR; /* descriptor of the page in the key cache block buffer */ struct st_keycache_page @@ -317,16 +318,11 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cache_var; static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache); static void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup); -#ifdef THREAD static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, - pthread_mutex_t *mutex); + mysql_mutex_t *mutex); static void release_whole_queue(KEYCACHE_WQUEUE *wqueue); -#else -#define wait_on_queue(wqueue, mutex) do {} while (0) -#define release_whole_queue(wqueue) do {} while (0) -#endif static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block); -#if !defined(DBUG_OFF) +#ifndef DBUG_OFF static void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache, const char *where, my_bool lock); #endif @@ -345,7 +341,7 @@ static void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache, #if defined(KEYCACHE_DEBUG_LOG) static FILE *keycache_debug_log=NULL; -static void keycache_debug_print _VARARGS((const char *fmt,...)); +static void keycache_debug_print(const char *fmt,...); #define KEYCACHE_DEBUG_OPEN \ if (!keycache_debug_log) \ { \ @@ -378,7 +374,6 @@ static void keycache_debug_print _VARARGS((const char *fmt,...)); #endif /* defined(KEYCACHE_DEBUG_LOG) && defined(KEYCACHE_DEBUG) */ #if defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF) -#ifdef THREAD static long keycache_thread_id; #define KEYCACHE_THREAD_TRACE(l) \ KEYCACHE_DBUG_PRINT(l,("|thread %ld",keycache_thread_id)) @@ -390,11 +385,6 @@ static long keycache_thread_id; #define KEYCACHE_THREAD_TRACE_END(l) \ KEYCACHE_DBUG_PRINT(l,("]thread %ld",keycache_thread_id)) -#else /* THREAD */ -#define KEYCACHE_THREAD_TRACE(l) KEYCACHE_DBUG_PRINT(l,("")) -#define KEYCACHE_THREAD_TRACE_BEGIN(l) KEYCACHE_DBUG_PRINT(l,("")) -#define KEYCACHE_THREAD_TRACE_END(l) KEYCACHE_DBUG_PRINT(l,("")) -#endif /* THREAD */ #else #define KEYCACHE_THREAD_TRACE_BEGIN(l) #define KEYCACHE_THREAD_TRACE_END(l) @@ -407,20 +397,20 @@ static long keycache_thread_id; ((uint) (((char*)(h)-(char *) keycache->hash_link_root)/sizeof(HASH_LINK))) #if (defined(KEYCACHE_TIMEOUT) && !defined(__WIN__)) || defined(KEYCACHE_DEBUG) -static int keycache_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex); +static int keycache_pthread_cond_wait(mysql_cond_t *cond, + mysql_mutex_t *mutex); #else -#define keycache_pthread_cond_wait pthread_cond_wait +#define keycache_pthread_cond_wait(C, M) mysql_cond_wait(C, M) #endif #if defined(KEYCACHE_DEBUG) -static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex); -static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex); -static int keycache_pthread_cond_signal(pthread_cond_t *cond); +static int keycache_pthread_mutex_lock(mysql_mutex_t *mutex); +static void keycache_pthread_mutex_unlock(mysql_mutex_t *mutex); +static int keycache_pthread_cond_signal(mysql_cond_t *cond); #else -#define keycache_pthread_mutex_lock pthread_mutex_lock -#define keycache_pthread_mutex_unlock pthread_mutex_unlock -#define keycache_pthread_cond_signal pthread_cond_signal +#define keycache_pthread_mutex_lock(M) mysql_mutex_lock(M) +#define keycache_pthread_mutex_unlock(M) mysql_mutex_unlock(M) +#define keycache_pthread_cond_signal(C) mysql_cond_signal(C) #endif /* defined(KEYCACHE_DEBUG) */ #if !defined(DBUG_OFF) @@ -513,7 +503,8 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_si keycache->cnt_for_resize_op= 0; keycache->waiting_for_resize_cnt.last_thread= NULL; keycache->in_init= 0; - pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_KEY_CACHE_cache_lock, + &keycache->cache_lock, MY_MUTEX_INIT_FAST); keycache->resize_queue.last_thread= NULL; } @@ -555,7 +546,7 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_si if ((keycache->block_root= (BLOCK_LINK*) my_malloc(length, MYF(0)))) break; - my_large_free(keycache->block_mem, MYF(0)); + my_large_free(keycache->block_mem); keycache->block_mem= 0; } if (blocks < 8) @@ -630,12 +621,12 @@ err: keycache->blocks= 0; if (keycache->block_mem) { - my_large_free((uchar*) keycache->block_mem, MYF(0)); + my_large_free((uchar*) keycache->block_mem); keycache->block_mem= NULL; } if (keycache->block_root) { - my_free((uchar*) keycache->block_root, MYF(0)); + my_free(keycache->block_root); keycache->block_root= NULL; } my_errno= error; @@ -683,7 +674,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, keycache_pthread_mutex_lock(&keycache->cache_lock); -#ifdef THREAD /* We may need to wait for another thread which is doing a resize already. This cannot happen in the MySQL server though. It allows @@ -696,7 +686,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); /* purecov: end */ } -#endif /* Mark the operation in progress. This blocks other threads from doing @@ -725,7 +714,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, keycache->resize_in_flush= 0; } -#ifdef THREAD /* Some direct read/write operations (bypassing the cache) may still be unfinished. Wait until they are done. If the key cache can be used, @@ -739,9 +727,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, */ while (keycache->cnt_for_resize_op) wait_on_queue(&keycache->waiting_for_resize_cnt, &keycache->cache_lock); -#else - KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0); -#endif end_simple_key_cache(keycache, 0); @@ -791,7 +776,7 @@ void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, if (acquire_lock) keycache_pthread_mutex_lock(&keycache->cache_lock); - safe_mutex_assert_owner(&keycache->cache_lock); + mysql_mutex_assert_owner(&keycache->cache_lock); /* Mark the resize finished. This allows other threads to start a @@ -985,9 +970,9 @@ void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup) { if (keycache->block_mem) { - my_large_free((uchar*) keycache->block_mem, MYF(0)); + my_large_free((uchar*) keycache->block_mem); keycache->block_mem= NULL; - my_free((uchar*) keycache->block_root, MYF(0)); + my_free(keycache->block_root); keycache->block_root= NULL; } keycache->disk_blocks= -1; @@ -1012,7 +997,7 @@ void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup) if (cleanup) { - pthread_mutex_destroy(&keycache->cache_lock); + mysql_mutex_destroy(&keycache->cache_lock); keycache->key_cache_inited= keycache->can_be_used= 0; KEYCACHE_DEBUG_CLOSE; } @@ -1020,8 +1005,6 @@ void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup) } /* end_key_cache */ -#ifdef THREAD - /* Link a thread into double-linked queue of waiting threads. @@ -1127,7 +1110,7 @@ static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, */ static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, - pthread_mutex_t *mutex) + mysql_mutex_t *mutex) { struct st_my_thread_var *last; struct st_my_thread_var *thread= my_thread_var; @@ -1201,8 +1184,6 @@ static void release_whole_queue(KEYCACHE_WQUEUE *wqueue) wqueue->last_thread= NULL; } -#endif /* THREAD */ - /* Unlink a block from the chain of dirty/clean blocks @@ -1374,7 +1355,6 @@ static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block, DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); DBUG_ASSERT(!block->next_used); DBUG_ASSERT(!block->prev_used); -#ifdef THREAD if (!hot && keycache->waiting_for_block.last_thread) { /* Signal that in the LRU warm sub-chain an available block has appeared */ @@ -1434,10 +1414,6 @@ static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block, #endif return; } -#else /* THREAD */ - KEYCACHE_DBUG_ASSERT(! (!hot && keycache->waiting_for_block.last_thread)); - /* Condition not transformed using DeMorgan, to keep the text identical */ -#endif /* THREAD */ pins= hot ? &keycache->used_ins : &keycache->used_last; ins= *pins; if (ins) @@ -1660,12 +1636,8 @@ static void remove_reader(BLOCK_LINK *block) DBUG_ASSERT(!block->next_used); DBUG_ASSERT(!block->prev_used); DBUG_ASSERT(block->hash_link->requests); -#ifdef THREAD if (! --block->hash_link->requests && block->condvar) keycache_pthread_cond_signal(block->condvar); -#else - --block->hash_link->requests; -#endif } @@ -1677,7 +1649,6 @@ static void remove_reader(BLOCK_LINK *block) static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block) { -#ifdef THREAD struct st_my_thread_var *thread= my_thread_var; DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); DBUG_ASSERT(!(block->status & (BLOCK_IN_FLUSH | BLOCK_CHANGED))); @@ -1699,9 +1670,6 @@ static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache, keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); block->condvar= NULL; } -#else - KEYCACHE_DBUG_ASSERT(block->hash_link->requests == 0); -#endif } @@ -1731,7 +1699,6 @@ static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link) if ((*hash_link->prev= hash_link->next)) hash_link->next->prev= hash_link->prev; hash_link->block= NULL; -#ifdef THREAD if (keycache->waiting_for_hash_link.last_thread) { /* Signal that a free hash link has appeared */ @@ -1767,9 +1734,6 @@ static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link) hash_link); return; } -#else /* THREAD */ - KEYCACHE_DBUG_ASSERT(! (keycache->waiting_for_hash_link.last_thread)); -#endif /* THREAD */ hash_link->next= keycache->free_hash_list; keycache->free_hash_list= hash_link; } @@ -1834,7 +1798,6 @@ restart: } else { -#ifdef THREAD /* Wait for a free hash link */ struct st_my_thread_var *thread= my_thread_var; KEYCACHE_PAGE page; @@ -1848,9 +1811,6 @@ restart: keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); thread->opt_info= NULL; -#else - KEYCACHE_DBUG_ASSERT(0); -#endif goto restart; } hash_link->file= file; @@ -1970,7 +1930,6 @@ restart: - block assigned but not yet read from file (invalid data). */ -#ifdef THREAD if (keycache->in_resize) { /* This is a request during a resize operation */ @@ -2212,9 +2171,6 @@ restart: } DBUG_RETURN(0); } -#else /* THREAD */ - DBUG_ASSERT(!keycache->in_resize); -#endif if (page_status == PAGE_READ && (block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | @@ -2344,7 +2300,6 @@ restart: from the LRU ring. */ -#ifdef THREAD if (! keycache->used_last) { /* @@ -2377,9 +2332,6 @@ restart: DBUG_ASSERT(!hash_link->block->next_used); DBUG_ASSERT(!hash_link->block->prev_used); } -#else - KEYCACHE_DBUG_ASSERT(keycache->used_last); -#endif /* If we waited above, hash_link->block has been assigned by link_block(). Otherwise it is still NULL. In the latter case @@ -2813,6 +2765,15 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, uint offset; int page_st; + if (MYSQL_KEYCACHE_READ_START_ENABLED()) + { + MYSQL_KEYCACHE_READ_START(my_filename(file), length, + (ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } + /* When the key cache is once initialized, we use the cache_lock to reliably distinguish the cases of normal operation, resizing, and @@ -2857,13 +2818,11 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, set_if_smaller(read_length, keycache->key_cache_block_size-offset); KEYCACHE_DBUG_ASSERT(read_length > 0); -#ifndef THREAD - if (block_length > keycache->key_cache_block_size || offset) - return_buffer=0; -#endif - /* Request the cache block that matches file/pos. */ keycache->global_cache_r_requests++; + + MYSQL_KEYCACHE_READ_BLOCK(keycache->key_cache_block_size); + block=find_key_block(keycache, file, filepos, level, 0, &page_st); if (!block) { @@ -2883,6 +2842,7 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, { if (page_st != PAGE_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, @@ -2907,14 +2867,15 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, my_errno= -1; block->status|= BLOCK_ERROR; } + else + { + MYSQL_KEYCACHE_READ_HIT(); + } } /* block status may have added BLOCK_ERROR in the above 'if'. */ if (!(block->status & BLOCK_ERROR)) { -#ifndef THREAD - if (! return_buffer) -#endif { DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); #if !defined(SERIALIZED_READ_FROM_CACHE) @@ -2922,10 +2883,7 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, #endif /* Copy data from the cache buffer */ - if (!(read_length & 511)) - bmove512(buff, block->buffer+offset, read_length); - else - memcpy(buff, block->buffer+offset, (size_t) read_length); + memcpy(buff, block->buffer+offset, (size_t) read_length); #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -2956,17 +2914,19 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, break; } -#ifndef THREAD - /* This is only true if we where able to read everything in one block */ - if (return_buffer) - DBUG_RETURN(block->buffer); -#endif next_block: buff+= read_length; filepos+= read_length+offset; offset= 0; } while ((length-= read_length)); + if (MYSQL_KEYCACHE_READ_DONE_ENABLED()) + { + MYSQL_KEYCACHE_READ_DONE((ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } goto end; } KEYCACHE_DBUG_PRINT("key_cache_read", ("keycache not initialized")); @@ -3162,10 +3122,7 @@ int simple_key_cache_insert(SIMPLE_KEY_CACHE_CB *keycache, #endif /* Copy data from buff */ - if (!(read_length & 511)) - bmove512(block->buffer+offset, buff, read_length); - else - memcpy(block->buffer+offset, buff, (size_t) read_length); + memcpy(block->buffer+offset, buff, (size_t) read_length); #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -3345,6 +3302,15 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache, uint offset; int page_st; + if (MYSQL_KEYCACHE_WRITE_START_ENABLED()) + { + MYSQL_KEYCACHE_WRITE_START(my_filename(file), length, + (ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } + /* When the key cache is once initialized, we use the cache_lock to reliably distinguish the cases of normal operation, resizing, and @@ -3380,6 +3346,8 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache, /* Cache could be disabled in a later iteration. */ if (!keycache->can_be_used) goto no_key_cache; + + MYSQL_KEYCACHE_WRITE_BLOCK(keycache->key_cache_block_size); /* Start writing at the beginning of the cache block. */ filepos-= offset; /* Do not write beyond the end of the cache block. */ @@ -3498,10 +3466,7 @@ int simple_key_cache_write(SIMPLE_KEY_CACHE_CB *keycache, #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_unlock(&keycache->cache_lock); #endif - if (!(read_length & 511)) - bmove512(block->buffer+offset, buff, read_length); - else - memcpy(block->buffer+offset, buff, (size_t) read_length); + memcpy(block->buffer+offset, buff, (size_t) read_length); #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -3593,6 +3558,15 @@ end: dec_counter_for_resize_op(keycache); keycache_pthread_mutex_unlock(&keycache->cache_lock); } + + if (MYSQL_KEYCACHE_WRITE_DONE_ENABLED()) + { + MYSQL_KEYCACHE_WRITE_DONE((ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } + #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("exec", test_key_cache(keycache, "end of key_cache_write", 1);); @@ -4216,17 +4190,11 @@ restart: if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | BLOCK_REASSIGNED))) { - struct st_hash_link *next_hash_link; - my_off_t next_diskpos; - File next_file; - uint next_status; - uint hash_requests; - - LINT_INIT(next_hash_link); - LINT_INIT(next_diskpos); - LINT_INIT(next_file); - LINT_INIT(next_status); - LINT_INIT(hash_requests); + struct st_hash_link *UNINIT_VAR(next_hash_link); + my_off_t UNINIT_VAR(next_diskpos); + File UNINIT_VAR(next_file); + uint UNINIT_VAR(next_status); + uint UNINIT_VAR(hash_requests); total_found++; found++; @@ -4330,7 +4298,7 @@ restart: #endif err: if (cache != cache_buff) - my_free((uchar*) cache, MYF(0)); + my_free(cache); if (last_errno) errno=last_errno; /* Return first error */ DBUG_RETURN(last_errno != 0); @@ -4441,7 +4409,7 @@ static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache) do { - safe_mutex_assert_owner(&keycache->cache_lock); + mysql_mutex_assert_owner(&keycache->cache_lock); total_found= 0; /* @@ -4689,8 +4657,8 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) #if defined(KEYCACHE_TIMEOUT) && !defined(__WIN__) -static int keycache_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex) +static int keycache_pthread_cond_wait(mysql_cond_t *cond, + mysql_mutex_t *mutex) { int rc; struct timeval now; /* time when we started waiting */ @@ -4717,7 +4685,7 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, fprintf(keycache_debug_log, "waiting...\n"); fflush(keycache_debug_log); #endif - rc= pthread_cond_timedwait(cond, mutex, &timeout); + rc= mysql_cond_timedwait(cond, mutex, &timeout); KEYCACHE_THREAD_TRACE_BEGIN("finished waiting"); if (rc == ETIMEDOUT || rc == ETIME) { @@ -4738,12 +4706,12 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, } #else #if defined(KEYCACHE_DEBUG) -static int keycache_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex) +static int keycache_pthread_cond_wait(mysql_cond_t *cond, + mysql_mutex_t *mutex) { int rc; KEYCACHE_THREAD_TRACE_END("started waiting"); - rc= pthread_cond_wait(cond, mutex); + rc= mysql_cond_wait(cond, mutex); KEYCACHE_THREAD_TRACE_BEGIN("finished waiting"); return rc; } @@ -4753,27 +4721,27 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, #if defined(KEYCACHE_DEBUG) -static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex) +static int keycache_pthread_mutex_lock(mysql_mutex_t *mutex) { int rc; - rc= pthread_mutex_lock(mutex); + rc= mysql_mutex_lock(mutex); KEYCACHE_THREAD_TRACE_BEGIN(""); return rc; } -static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex) +static void keycache_pthread_mutex_unlock(mysql_mutex_t *mutex) { KEYCACHE_THREAD_TRACE_END(""); - pthread_mutex_unlock(mutex); + mysql_mutex_unlock(mutex); } -static int keycache_pthread_cond_signal(pthread_cond_t *cond) +static int keycache_pthread_cond_signal(mysql_cond_t *cond) { int rc; KEYCACHE_THREAD_TRACE("signal"); - rc= pthread_cond_signal(cond); + rc= mysql_cond_signal(cond); return rc; } @@ -5149,7 +5117,7 @@ int init_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, end_simple_key_cache(partition, 1); if (!key_cache_inited) { - my_free(partition, MYF(0)); + my_free(partition); partition= 0; } if ((i == 0 && cnt < 0) || i > 0) @@ -5168,7 +5136,7 @@ int init_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, */ if (key_cache_inited) { - my_free(partition, MYF(0)); + my_free(partition); partition= 0; if(key_cache_inited) memmove(partition_ptr, partition_ptr+1, @@ -5377,8 +5345,8 @@ void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, if (cleanup) { for (i= 0; i < partitions; i++) - my_free((uchar*) keycache->partition_array[i], MYF(0)); - my_free((uchar*) keycache->partition_array, MYF(0)); + my_free(keycache->partition_array[i]); + my_free(keycache->partition_array); keycache->key_cache_inited= 0; } DBUG_VOID_RETURN; @@ -5442,10 +5410,6 @@ uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache, DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u", (uint) file, (ulong) filepos, length)); -#ifndef THREAD - if (block_length > keycache->key_cache_block_size || offset) - return_buffer=0; -#endif /* Read data in key_cache_block_size increments */ do @@ -5461,11 +5425,6 @@ uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache, block_length, return_buffer); if (ret_buff == 0) DBUG_RETURN(0); -#ifndef THREAD - /* This is only true if we were able to read everything in one block */ - if (return_buffer) - DBUG_RETURN(ret_buff); -#endif filepos+= r_length; buff+= r_length; offset= 0; @@ -6075,7 +6034,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) { if (keycache->keycache_cb) { - my_free((uchar *) keycache->keycache_cb, MYF(0)); + my_free(keycache->keycache_cb); keycache->keycache_cb= 0; } keycache->key_cache_inited= 0; @@ -6317,7 +6276,8 @@ int flush_key_blocks(KEY_CACHE *keycache, */ int reset_key_cache_counters(const char *name __attribute__((unused)), - KEY_CACHE *keycache) + KEY_CACHE *keycache, + void *unused __attribute__((unused))) { if (keycache->key_cache_inited) { diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 86fd61537e7..790936461a4 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 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 @@ -18,13 +18,8 @@ #ifdef HAVE_PWD_H #include <pwd.h> #endif -#ifdef VMS -#include <rms.h> -#include <iodef.h> -#include <descrip.h> -#endif /* VMS */ -static char * NEAR_F expand_tilde(char * *path); +static char * expand_tilde(char **path); /* Pack a dirname ; Changes HOME to ~/ and current dev to ./ */ /* from is a dirname (from dirname() ?) ending with FN_LIBCHAR */ @@ -197,7 +192,8 @@ size_t cleanup_dirname(register char *to, const char *from) end_parentdir=pos; while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */ pos--; - if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0) + if (pos[1] == FN_HOMELIB || + (pos >= start && memcmp(pos, parent, length) == 0)) { /* Don't remove ~user/ */ pos=strmov(end_parentdir+1,parent); *pos=FN_LIBCHAR; @@ -300,8 +296,7 @@ size_t normalize_dirname(char *to, const char *from) /* Despite the name, this actually converts the name to the system's - format (TODO: rip out the non-working VMS stuff and name this - properly). + format (TODO: name this properly). */ (void) intern_filename(buff, from); length= strlen(buff); /* Fix that '/' is last */ @@ -377,7 +372,7 @@ size_t unpack_dirname(char * to, const char *from) /* Expand tilde to home or user-directory */ /* Path is reset to point at FN_LIBCHAR after ~xxx */ -static char * NEAR_F expand_tilde(char * *path) +static char * expand_tilde(char **path) { if (path[0][0] == FN_LIBCHAR) return home_dir; /* ~/ expanded to home */ @@ -443,73 +438,10 @@ size_t unpack_filename(char * to, const char *from) /* Used before system command's like open(), create() .. */ /* Returns used length of to; total length should be FN_REFLEN */ -size_t system_filename(char * to, const char *from) +size_t system_filename(char *to, const char *from) { -#ifndef FN_C_BEFORE_DIR return (size_t) (strmake(to,from,FN_REFLEN-1)-to); -#else /* VMS */ - - /* change 'dev:lib/xxx' to 'dev:[lib]xxx' */ - /* change 'dev:xxx' to 'dev:xxx' */ - /* change './xxx' to 'xxx' */ - /* change './lib/' or lib/ to '[.lib]' */ - /* change '/x/y/z to '[x.y]x' */ - /* change 'dev:/x' to 'dev:[000000]x' */ - - int libchar_found; - size_t length; - char * to_pos,from_pos,pos; - char buff[FN_REFLEN]; - DBUG_ENTER("system_filename"); - - libchar_found=0; - (void) strmov(buff,from); /* If to == from */ - from_pos= buff; - if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skip device part */ - { - pos++; - to_pos=strnmov(to,from_pos,(size_t) (pos-from_pos)); - from_pos=pos; - } - else - to_pos=to; - - if (from_pos[0] == FN_CURLIB && from_pos[1] == FN_LIBCHAR) - from_pos+=2; /* Skip './' */ - if (strchr(from_pos,FN_LIBCHAR)) - { - *(to_pos++) = FN_C_BEFORE_DIR; - if (strinstr(from_pos,FN_ROOTDIR) == 1) - { - from_pos+=strlen(FN_ROOTDIR); /* Actually +1 but... */ - if (! strchr(from_pos,FN_LIBCHAR)) - { /* No dir, use [000000] */ - to_pos=strmov(to_pos,FN_C_ROOT_DIR); - libchar_found++; - } - } - else - *(to_pos++)=FN_C_DIR_SEP; /* '.' gives current dir */ - - while ((pos=strchr(from_pos,FN_LIBCHAR))) - { - if (libchar_found++) - *(to_pos++)=FN_C_DIR_SEP; /* Add '.' between dirs */ - if (strinstr(from_pos,FN_PARENTDIR) == 1 && - from_pos+strlen(FN_PARENTDIR) == pos) - to_pos=strmov(to_pos,FN_C_PARENT_DIR); /* Found '../' */ - else - to_pos=strnmov(to_pos,from_pos,(size_t) (pos-from_pos)); - from_pos=pos+1; - } - *(to_pos++)=FN_C_AFTER_DIR; - } - length= (size_t) (strmov(to_pos,from_pos)-to); - DBUG_PRINT("exit",("name: '%s'",to)); - DBUG_RETURN(length); -#endif -} /* system_filename */ - +} /* Fix a filename to intern (UNIX format) */ diff --git a/mysys/mf_path.c b/mysys/mf_path.c index 73e73cb7f76..92cb62e6827 100644 --- a/mysys/mf_path.c +++ b/mysys/mf_path.c @@ -42,7 +42,7 @@ char * my_path(char * to, const char *progname, ((prog=getenv("_")) != 0 && dirname_part(to, prog, &to_length)))) { - VOID(intern_filename(to,to)); + (void) intern_filename(to,to); if (!test_if_hard_path(to)) { if (!my_getwd(curr_dir,FN_REFLEN,MYF(0))) @@ -60,11 +60,11 @@ char * my_path(char * to, const char *progname, end= (char*) "/my/"; #endif } - VOID(intern_filename(to,end)); + (void) intern_filename(to,end); to=strend(to); if (to != start && to[-1] != FN_LIBCHAR) *to++ = FN_LIBCHAR; - VOID(strmov(to,own_pathname_part)); + (void) strmov(to,own_pathname_part); } DBUG_PRINT("exit",("to: '%s'",start)); DBUG_RETURN(start); @@ -78,9 +78,6 @@ char * my_path(char * to, const char *progname, #define F_OK 0 #define PATH_SEP ';' #define PROGRAM_EXTENSION ".exe" -#elif defined(__NETWARE__) -#define PATH_SEP ';' -#define PROGRAM_EXTENSION ".nlm" #else #define PATH_SEP ':' #endif diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c index 686ebbc1d14..a3e7465ead0 100644 --- a/mysys/mf_sort.c +++ b/mysys/mf_sort.c @@ -27,7 +27,7 @@ void my_string_ptr_sort(uchar *base, uint items, size_t size) (ptr= (uchar**) my_malloc(items*sizeof(char*),MYF(0)))) { radixsort_for_str_ptr((uchar**) base,items,size,ptr); - my_free((uchar*) ptr,MYF(0)); + my_free(ptr); } else #endif diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c index f41bbab946f..c84987cfc96 100644 --- a/mysys/mf_tempdir.c +++ b/mysys/mf_tempdir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -16,7 +16,7 @@ #include "mysys_priv.h" #include <m_string.h> -#if defined( __WIN__) || defined(__NETWARE__) +#if defined(__WIN__) #define DELIM ';' #else #define DELIM ':' @@ -29,14 +29,14 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) DBUG_ENTER("init_tmpdir"); DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL")); - pthread_mutex_init(&tmpdir->mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_TMPDIR_mutex, &tmpdir->mutex, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&tmpdir->full_list, sizeof(char*), 1, 5)) goto err; if (!pathlist || !pathlist[0]) { /* Get default temporary directory */ pathlist=getenv("TMPDIR"); /* Use this if possible */ -#if defined( __WIN__) || defined(__NETWARE__) +#if defined(__WIN__) if (!pathlist) pathlist=getenv("TEMP"); if (!pathlist) @@ -65,7 +65,7 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) err: delete_dynamic(&tmpdir->full_list); /* Safe to free */ - pthread_mutex_destroy(&tmpdir->mutex); + mysql_mutex_destroy(&tmpdir->mutex); DBUG_RETURN(TRUE); } @@ -75,10 +75,10 @@ char *my_tmpdir(MY_TMPDIR *tmpdir) char *dir; if (!tmpdir->max) return tmpdir->list[0]; - pthread_mutex_lock(&tmpdir->mutex); + mysql_mutex_lock(&tmpdir->mutex); dir=tmpdir->list[tmpdir->cur]; tmpdir->cur= (tmpdir->cur == tmpdir->max) ? 0 : tmpdir->cur+1; - pthread_mutex_unlock(&tmpdir->mutex); + mysql_mutex_unlock(&tmpdir->mutex); return dir; } @@ -88,8 +88,8 @@ void free_tmpdir(MY_TMPDIR *tmpdir) if (!tmpdir->full_list.elements) return; for (i=0; i<=tmpdir->max; i++) - my_free(tmpdir->list[i], MYF(0)); + my_free(tmpdir->list[i]); delete_dynamic(&tmpdir->full_list); - pthread_mutex_destroy(&tmpdir->mutex); + mysql_mutex_destroy(&tmpdir->mutex); } diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c index 40016210de4..e85124fb4c3 100644 --- a/mysys/mf_tempfile.c +++ b/mysys/mf_tempfile.c @@ -100,16 +100,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, my_errno= tmp; } -#elif defined(_ZTC__) - if (!dir) - dir=getenv("TMPDIR"); - if ((res=tempnam((char*) dir,(char *) prefix))) - { - strmake(to,res,FN_REFLEN-1); - (*free)(res); - file=my_create(to, 0, mode | O_EXCL | O_NOFOLLOW, MyFlags); - } -#elif defined(HAVE_MKSTEMP) && !defined(__NETWARE__) +#elif defined(HAVE_MKSTEMP) { char prefix_buff[30]; uint pfx_len; @@ -143,9 +134,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, } #elif defined(HAVE_TEMPNAM) { -#if !defined(__NETWARE__) extern char **environ; -#endif char *res,**old_env,*temp_env[1]; if (dir && !dir[0]) @@ -154,14 +143,14 @@ File create_temp_file(char *to, const char *dir, const char *prefix, to[1]= 0; dir=to; } -#if !defined(__NETWARE__) + old_env= (char**) environ; if (dir) { /* Don't use TMPDIR if dir is given */ environ=(const char**) temp_env; temp_env[0]=0; } -#endif + if ((res=tempnam((char*) dir, (char*) prefix))) { strmake(to,res,FN_REFLEN-1); @@ -176,9 +165,8 @@ File create_temp_file(char *to, const char *dir, const char *prefix, { DBUG_PRINT("error",("Got error: %d from tempnam",errno)); } -#if !defined(__NETWARE__) + environ=(const char**) old_env; -#endif } #else #error No implementation found for create_temp_file diff --git a/mysys/mf_unixpath.c b/mysys/mf_unixpath.c index 75f8de14879..ee81aae4584 100644 --- a/mysys/mf_unixpath.c +++ b/mysys/mf_unixpath.c @@ -16,10 +16,15 @@ #include "mysys_priv.h" #include <m_string.h> - /* convert filename to unix style filename */ - /* If MSDOS converts '\' to '/' */ +/** + Convert filename to unix style filename. -void to_unix_path(char * to __attribute__((unused))) + @remark On Windows, converts '\' to '/'. + + @param to A pathname. +*/ + +void to_unix_path(char *to __attribute__((unused))) { #if FN_LIBCHAR != '/' { diff --git a/mysys/mf_util.c b/mysys/mf_util.c deleted file mode 100644 index 248b72b8748..00000000000 --- a/mysys/mf_util.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* Utilities with are missing on some systems */ - -#include "mysys_priv.h" -#ifdef __ZTC__ -#include <dos.h> -#endif - -#ifdef __ZTC__ - - /* On ZORTECH C we don't have a getpid() call */ - -int getpid(void) -{ - return (int) _psp; -} - -#ifndef M_IC80386 - - /* Define halloc and hfree in as in MSC */ - -void * __CDECL halloc(long count,size_t length) -{ - return (void*) MK_FP(dos_alloc((uint) ((count*length+15) >> 4)),0); -} - -void __CDECL hfree(void *ptr) -{ - dos_free(FP_SEG(ptr)); -} - -#endif /* M_IC80386 */ -#endif /* __ZTC__ */ diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c deleted file mode 100644 index 4a4fb466600..00000000000 --- a/mysys/mf_wfile.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* Functions for finding files with wildcards */ - -/* - The following file-name-test is supported: - - "name [[,] name...] ; Matches any of used filenames. - Each name can have "*" and/or "?" - wild-cards. - - [wildspec [,]] !wildspec2 ; File that matches wildspec and not - wildspec2. -*/ - -#include "mysys_priv.h" -#include <m_string.h> - - /* Store wildcard-string in a easyer format */ - -WF_PACK *wf_comp(char * str) -{ - uint ant; - int not_pos; - register char * pos; - char * buffer; - WF_PACK *ret; - DBUG_ENTER("wf_comp"); - - not_pos= -1; /* Skip space and '!' in front */ - while (*str == ' ') - str++; - if (*str == '!') - { - not_pos=0; - while (*++str == ' ') {}; - } - if (*str == 0) /* Empty == everything */ - DBUG_RETURN((WF_PACK *) NULL); - - ant=1; /* Count filespecs */ - for (pos=str ; *pos ; pos++) - ant+= test(*pos == ' ' || *pos == ','); - - if ((ret= (WF_PACK*) my_malloc((uint) ant*(sizeof(char **)+2)+ - sizeof(WF_PACK)+ (uint) strlen(str)+1, - MYF(MY_WME))) - == 0) - DBUG_RETURN((WF_PACK *) NULL); - ret->wild= (char **) (ret+1); - buffer= (char *) (ret->wild+ant); - - ant=0; - for (pos=str ; *pos ; str= pos) - { - ret->wild[ant++]=buffer; - while (*pos != ' ' && *pos != ',' && *pos != '!' && *pos) - *buffer++ = *pos++; - - *buffer++ = '\0'; - while (*pos == ' ' || *pos == ',' || *pos == '!' ) - if (*pos++ == '!' && not_pos <0) - not_pos=(int) ant; - } - - ret->wilds=ant; - if (not_pos <0) - ret->not_pos=ant; - else - ret->not_pos=(uint) not_pos; - - DBUG_PRINT("exit",("antal: %d not_pos: %d",ret->wilds,ret->not_pos)); - DBUG_RETURN(ret); -} /* wf_comp */ - - - /* Test if a given filename is matched */ - -int wf_test(register WF_PACK *wf_pack, register const char *name) -{ - reg2 uint i; - reg3 uint not_pos; - DBUG_ENTER("wf_test"); - - if (! wf_pack || wf_pack->wilds == 0) - DBUG_RETURN(0); /* Everything goes */ - - not_pos=wf_pack->not_pos; - for (i=0 ; i < not_pos; i++) - if (wild_compare(name,wf_pack->wild[i],0) == 0) - goto found; - if (i) - DBUG_RETURN(1); /* No-match */ - -found: -/* Test that it isn't in not-list */ - - for (i=not_pos ; i < wf_pack->wilds; i++) - if (wild_compare(name,wf_pack->wild[i],0) == 0) - DBUG_RETURN(1); - DBUG_RETURN(0); -} /* wf_test */ - - - /* We need this because program don't know with malloc we used */ - -void wf_end(WF_PACK *buffer) -{ - DBUG_ENTER("wf_end"); - if (buffer) - my_free(buffer, MYF(0)); - DBUG_VOID_RETURN; -} /* wf_end */ diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 948d3a8476d..923e00d2182 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -119,7 +119,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, { /* remove block from the list and free it */ *prev= mem->next; - my_free(mem, MYF(0)); + my_free(mem); } else prev= &mem->next; @@ -162,7 +162,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) }); length+=ALIGN_SIZE(sizeof(USED_MEM)); - if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME)))) + if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR)))) { if (mem_root->error_handler) (*mem_root->error_handler)(); @@ -213,7 +213,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) get_size= length+ALIGN_SIZE(sizeof(USED_MEM)); get_size= max(get_size, block_size); - if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME)))) + if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR)))) { if (mem_root->error_handler) (*mem_root->error_handler)(); @@ -235,6 +235,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) mem_root->used= next; mem_root->first_block_usage= 0; } + TRASH_ALLOC(point, length); DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point)); DBUG_RETURN((void*) point); #endif @@ -361,13 +362,13 @@ void free_root(MEM_ROOT *root, myf MyFlags) { old=next; next= next->next ; if (old != root->pre_alloc) - my_free(old,MYF(0)); + my_free(old); } for (next=root->free ; next ;) { old=next; next= next->next; if (old != root->pre_alloc) - my_free(old,MYF(0)); + my_free(old); } root->used=root->free=0; if (root->pre_alloc) diff --git a/mysys/my_append.c b/mysys/my_append.c deleted file mode 100644 index d8789f95d95..00000000000 --- a/mysys/my_append.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "mysys_priv.h" -#include <sys/stat.h> -#include <m_string.h> -#if defined(HAVE_UTIME_H) -#include <utime.h> -#elif defined(HAVE_SYS_UTIME_H) -#include <sys/utime.h> -#elif !defined(HPUX10) -struct utimbuf { - time_t actime; - time_t modtime; -}; -#endif - -/* - Append a file to another - - NOTES - Don't set MY_FNABP or MY_NABP bits on when calling this function -*/ - -int my_append(const char *from, const char *to, myf MyFlags) -{ - size_t Count; - File from_file,to_file; - uchar buff[IO_SIZE]; - DBUG_ENTER("my_append"); - DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); - - from_file= to_file= -1; - - if ((from_file=my_open(from,O_RDONLY,MyFlags)) >= 0) - { - if ((to_file=my_open(to,O_APPEND | O_WRONLY,MyFlags)) >= 0) - { - while ((Count=my_read(from_file,buff,IO_SIZE,MyFlags)) != 0) - if (Count == (uint) -1 || - my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP))) - goto err; - if (my_close(from_file,MyFlags) | my_close(to_file,MyFlags)) - DBUG_RETURN(-1); /* Error on close */ - DBUG_RETURN(0); - } - } -err: - if (from_file >= 0) VOID(my_close(from_file,MyFlags)); - if (to_file >= 0) VOID(my_close(to_file,MyFlags)); - DBUG_RETURN(-1); -} diff --git a/mysys/my_atomic.c b/mysys/my_atomic.c index aa04d55f624..7cbe15cfb74 100644 --- a/mysys/my_atomic.c +++ b/mysys/my_atomic.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright (C) 2006 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -14,14 +14,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <my_global.h> -#include <my_pthread.h> - -#ifndef HAVE_INLINE -/* the following will cause all inline functions to be instantiated */ -#define HAVE_INLINE -#undef STATIC_INLINE -#define STATIC_INLINE extern -#endif +#include <my_sys.h> #include <my_atomic.h> @@ -43,3 +36,32 @@ int my_atomic_initialize() #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_bit.c b/mysys/my_bit.c index 2881eb1ebd2..f072f243765 100644 --- a/mysys/my_bit.c +++ b/mysys/my_bit.c @@ -15,13 +15,6 @@ #include <my_global.h> -#ifndef HAVE_INLINE -/* the following will cause all inline functions to be instantiated */ -#define HAVE_INLINE -#undef STATIC_INLINE -#define STATIC_INLINE extern -#endif - #include <my_bit.h> const char _my_bits_nbits[256] = { diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 0e5421ec484..8f86e5832f6 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -23,17 +23,13 @@ * the internal size is a set of 32 bit words * the number of bits specified in creation can be any number > 0 - * there are THREAD safe versions of most calls called bitmap_lock_* - many of those are not used and not compiled normally but the code - already exist for them in an #ifdef:ed part. These can only be used - if THREAD was specified in bitmap_init TODO: - Make assembler THREAD safe versions of these using test-and-set instructions + Make assembler thread safe versions of these using test-and-set instructions Original version created by Sergei Golubchik 2001 - 2004. New version written and test program added and some changes to the interface - was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats + was made by Mikael Ronstrom 2005, with assistance of Tomas Ulin and Mats Kindahl. */ @@ -102,19 +98,14 @@ void create_last_word_mask(MY_BITMAP *map) static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused))) { -#ifdef THREAD if (map->mutex) - pthread_mutex_lock(map->mutex); -#endif + mysql_mutex_lock(map->mutex); } - static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) { -#ifdef THREAD if (map->mutex) - pthread_mutex_unlock(map->mutex); -#endif + mysql_mutex_unlock(map->mutex); } @@ -126,30 +117,24 @@ my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, { uint size_in_bytes= bitmap_buffer_size(n_bits); uint extra= 0; -#ifdef THREAD if (thread_safe) { size_in_bytes= ALIGN_SIZE(size_in_bytes); - extra= sizeof(pthread_mutex_t); + extra= sizeof(mysql_mutex_t); } map->mutex= 0; -#endif if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME)))) DBUG_RETURN(1); -#ifdef THREAD if (thread_safe) { - map->mutex= (pthread_mutex_t *) ((char*) buf + size_in_bytes); - pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST); + map->mutex= (mysql_mutex_t *) ((char*) buf + size_in_bytes); + mysql_mutex_init(key_BITMAP_mutex, map->mutex, MY_MUTEX_INIT_FAST); } -#endif } -#ifdef THREAD else { DBUG_ASSERT(thread_safe == 0); } -#endif map->bitmap= buf; map->n_bits= n_bits; @@ -164,11 +149,9 @@ void bitmap_free(MY_BITMAP *map) DBUG_ENTER("bitmap_free"); if (map->bitmap) { -#ifdef THREAD if (map->mutex) - pthread_mutex_destroy(map->mutex); -#endif - my_free((char*) map->bitmap, MYF(0)); + mysql_mutex_destroy(map->mutex); + my_free(map->bitmap); map->bitmap=0; } DBUG_VOID_RETURN; @@ -288,43 +271,31 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_bits= prefix_size % 32; - my_bitmap_map *word_ptr= map->bitmap, last_word; - my_bitmap_map *end_prefix= word_ptr + prefix_size / 32; - DBUG_ASSERT(word_ptr && prefix_size <= map->n_bits); - - /* 1: Words that should be filled with 1 */ - for (; word_ptr < end_prefix; word_ptr++) - if (*word_ptr != 0xFFFFFFFF) - return FALSE; + uint prefix_mask= last_byte_mask(prefix_size); + uchar *m= (uchar*) map->bitmap; + uchar *end_prefix= m+(prefix_size-1)/8; + uchar *end; + DBUG_ASSERT(m && prefix_size <= map->n_bits); - last_word= *map->last_word_ptr & ~map->last_word_mask; + /* Empty prefix is always true */ + if (!prefix_size) + return 1; - /* 2: Word which contains the end of the prefix (if any) */ - if (prefix_bits) - { - if (word_ptr == map->last_word_ptr) - return uint4korr((uchar*)&last_word) == (uint32)((1 << prefix_bits) - 1); - if (uint4korr((uchar*)word_ptr) != (uint32)((1 << prefix_bits) - 1)) - return FALSE; - word_ptr++; - } + while (m < end_prefix) + if (*m++ != 0xff) + return 0; - /* 3: Words that should be filled with 0 */ - for (; word_ptr < map->last_word_ptr; word_ptr++) - if (*word_ptr != 0) - return FALSE; + end= ((uchar*) map->bitmap) + no_bytes_in_map(map) - 1; + if (m == end) + return ((*m & last_byte_mask(map->n_bits)) == prefix_mask); - /* - We can end up here in two situations: - 1) We went through the whole bitmap in step 1. This will happen if the - whole bitmap is filled with 1 and prefix_size is a multiple of 32 - (i.e. the prefix does not end in the middle of a word). - In this case word_ptr will be larger than map->last_word_ptr. - 2) We have gone through steps 1-3 and just need to check that also - the last word is 0. - */ - return word_ptr > map->last_word_ptr || last_word == 0; + if (*m != prefix_mask) + return 0; + + while (++m < end) + if (*m != 0) + return 0; + return ((*m & last_byte_mask(map->n_bits)) == 0); } @@ -332,7 +303,6 @@ my_bool bitmap_is_set_all(const MY_BITMAP *map) { my_bitmap_map *data_ptr= map->bitmap; my_bitmap_map *end= map->last_word_ptr; - for (; data_ptr < end; data_ptr++) if (*data_ptr != 0xFFFFFFFF) return FALSE; @@ -522,10 +492,10 @@ uint bitmap_bits_set(const MY_BITMAP *map) return res; } - void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + DBUG_ASSERT(map->bitmap && map2->bitmap && map->n_bits==map2->n_bits); end= map->last_word_ptr; @@ -624,189 +594,3 @@ void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) bitmap_unlock(map); } - -#ifdef NOT_USED -my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size) -{ - my_bool res; - bitmap_lock((MY_BITMAP *)map); - res= bitmap_is_prefix(map, prefix_size); - bitmap_unlock((MY_BITMAP *)map); - return res; -} - - -void bitmap_lock_set_all(MY_BITMAP *map) -{ - bitmap_lock(map); - bitmap_set_all(map); - bitmap_unlock(map); -} - - -void bitmap_lock_clear_all(MY_BITMAP *map) -{ - bitmap_lock(map); - bitmap_clear_all(map); - bitmap_unlock(map); -} - - -void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size) -{ - bitmap_lock(map); - bitmap_set_prefix(map, prefix_size); - bitmap_unlock(map); -} - - -my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map) -{ - uint res; - bitmap_lock((MY_BITMAP *)map); - res= bitmap_is_clear_all(map); - bitmap_unlock((MY_BITMAP *)map); - return res; -} - - -my_bool bitmap_lock_is_set_all(const MY_BITMAP *map) -{ - uint res; - bitmap_lock((MY_BITMAP *)map); - res= bitmap_is_set_all(map); - bitmap_unlock((MY_BITMAP *)map); - return res; -} - - -my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit) -{ - my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); - bitmap_lock((MY_BITMAP *)map); - res= bitmap_is_set(map, bitmap_bit); - bitmap_unlock((MY_BITMAP *)map); - return res; -} - - -my_bool bitmap_lock_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) -{ - uint res; - bitmap_lock((MY_BITMAP *)map1); - bitmap_lock((MY_BITMAP *)map2); - res= bitmap_is_subset(map1, map2); - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock((MY_BITMAP *)map1); - return res; -} - - -my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) -{ - uint res; - - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); - bitmap_lock((MY_BITMAP *)map1); - bitmap_lock((MY_BITMAP *)map2); - res= bitmap_cmp(map1, map2); - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock((MY_BITMAP *)map1); - return res; -} - - -void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2) -{ - bitmap_lock(map); - bitmap_lock((MY_BITMAP *)map2); - bitmap_intersect(map, map2); - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock(map); -} - - -void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2) -{ - bitmap_lock(map); - bitmap_lock((MY_BITMAP *)map2); - bitmap_subtract(map, map2); - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock(map); -} - - -void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2) -{ - bitmap_lock(map); - bitmap_lock((MY_BITMAP *)map2); - bitmap_union(map, map2); - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock(map); -} - - -/* - SYNOPSIS - bitmap_bits_set() - map - RETURN - Number of set bits in the bitmap. -*/ -uint bitmap_lock_bits_set(const MY_BITMAP *map) -{ - uint res; - bitmap_lock((MY_BITMAP *)map); - DBUG_ASSERT(map->bitmap); - res= bitmap_bits_set(map); - bitmap_unlock((MY_BITMAP *)map); - return res; -} - - -/* - SYNOPSIS - bitmap_get_first() - map - RETURN - Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set. -*/ -uint bitmap_lock_get_first(const MY_BITMAP *map) -{ - uint res; - bitmap_lock((MY_BITMAP*)map); - res= bitmap_get_first(map); - bitmap_unlock((MY_BITMAP*)map); - return res; -} - - -uint bitmap_lock_get_first_set(const MY_BITMAP *map) -{ - uint res; - bitmap_lock((MY_BITMAP*)map); - res= bitmap_get_first_set(map); - bitmap_unlock((MY_BITMAP*)map); - return res; -} - - -void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit) -{ - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); - bitmap_lock(map); - bitmap_set_bit(map, bitmap_bit); - bitmap_unlock(map); -} - - -void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit) -{ - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); - bitmap_lock(map); - bitmap_flip_bit(map, bitmap_bit); - bitmap_unlock(map); -} -#endif /* NOT_USED */ diff --git a/mysys/my_clock.c b/mysys/my_clock.c deleted file mode 100644 index adc755028d5..00000000000 --- a/mysys/my_clock.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "my_global.h" - -#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__NETWARE__) -#include "mysys_priv.h" -#include <sys/times.h> -#endif - -long my_clock(void) -{ -#if !defined(__WIN__) && !defined(__NETWARE__) - struct tms tmsbuf; - VOID(times(&tmsbuf)); - return (tmsbuf.tms_utime + tmsbuf.tms_stime); -#else - return clock(); -#endif -} diff --git a/mysys/my_compare.c b/mysys/my_compare.c index 19a76593f42..9e192e52fb7 100644 --- a/mysys/my_compare.c +++ b/mysys/my_compare.c @@ -1,6 +1,5 @@ -/* Copyright (C) 2002-2006 MySQL AB +/* Copyright (c) 2011, Oracle and/or its affiliates. Copyright (C) 2009-2011 Monty Program Ab - Copyright (c) 2011 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 @@ -14,10 +13,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "mysys_priv.h" + +#include <my_global.h> +#include <m_ctype.h> #include <my_base.h> -#include "my_compare.h" +#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, @@ -25,8 +26,7 @@ int ha_compare_text(CHARSET_INFO *charset_info, const uchar *a, uint a_length, { if (!part_key) return charset_info->coll->strnncollsp(charset_info, a, a_length, - b, b_length, - (my_bool)!skip_end_space); + b, b_length, (my_bool)!skip_end_space); return charset_info->coll->strnncoll(charset_info, a, a_length, b, b_length, part_key); } @@ -118,8 +118,8 @@ static int compare_bin(const uchar *a, uint a_length, #define FCMP(A,B) ((int) (A) - (int) (B)) -int ha_key_cmp(register HA_KEYSEG *keyseg, register const uchar *a, - register const uchar *b, uint key_length, uint32 nextflag, +int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, + const uchar *b, uint key_length, uint32 nextflag, uint *diff_pos) { int flag; @@ -552,7 +552,6 @@ found: return 0; } /* ha_key_cmp */ - /* Find the first NULL value in index-suffix values tuple @@ -642,34 +641,3 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, const uchar *a) return keyseg; } - -/* - Register handler error messages for usage with my_error() - - NOTES - This is safe to call multiple times as my_error_register() - will ignore calls to register already registered error numbers. -*/ - -#include "my_handler_errors.h" - -void my_handler_error_register(void) -{ - /* - If you got compilation error here about compile_time_assert array, check - that every HA_ERR_xxx constant has a corresponding error message in - handler_error_messages[] list (check mysys/my_handler_errors.h and - include/my_base.h). - */ - compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) == - HA_ERR_LAST + 1); - my_error_register(handler_error_messages, HA_ERR_FIRST, - HA_ERR_FIRST+ array_elements(handler_error_messages)-1); -} - - -void my_handler_error_unregister(void) -{ - my_error_unregister(HA_ERR_FIRST, - HA_ERR_FIRST+ array_elements(handler_error_messages)-1); -} diff --git a/mysys/my_compress.c b/mysys/my_compress.c index ade2742c4fc..98f96f6b2b6 100644 --- a/mysys/my_compress.c +++ b/mysys/my_compress.c @@ -51,7 +51,7 @@ my_bool my_compress(uchar *packet, size_t *len, size_t *complen) if (!compbuf) DBUG_RETURN(*complen ? 0 : 1); memcpy(packet,compbuf,*len); - my_free(compbuf,MYF(MY_WME)); + my_free(compbuf); } DBUG_RETURN(0); } @@ -89,7 +89,7 @@ void *my_az_allocator(void *dummy __attribute__((unused)), unsigned int items, void my_az_free(void *dummy __attribute__((unused)), void *address) { - my_free(address, MYF(MY_ALLOW_ZERO_PTR)); + my_free(address); } /* @@ -140,14 +140,14 @@ uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen) if (res != Z_OK) { - my_free(compbuf, MYF(MY_WME)); + my_free(compbuf); return 0; } if (*complen >= *len) { *complen= 0; - my_free(compbuf, MYF(MY_WME)); + my_free(compbuf); DBUG_PRINT("note",("Packet got longer on compression; Not compressed")); return 0; } @@ -192,11 +192,11 @@ my_bool my_uncompress(uchar *packet, size_t len, size_t *complen) if (error != Z_OK) { /* Probably wrong packet */ DBUG_PRINT("error",("Can't uncompress packet, error: %d",error)); - my_free(compbuf, MYF(MY_WME)); + my_free(compbuf); DBUG_RETURN(1); } memcpy(packet, compbuf, *complen); - my_free(compbuf, MYF(MY_WME)); + my_free(compbuf); } else *complen= len; @@ -317,7 +317,7 @@ int unpackfrm(uchar **unpack_data, size_t *unpack_len, if (my_uncompress(data, complen, &orglen)) { - my_free(data, MYF(0)); + my_free(data); DBUG_RETURN(3); } diff --git a/mysys/my_copy.c b/mysys/my_copy.c index e1c549f4676..c2f4f53a780 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -116,36 +116,36 @@ int my_copy(const char *from, const char *to, myf MyFlags) if (MyFlags & MY_FAE) goto err; } -#if !defined(__WIN__) && !defined(__NETWARE__) +#if !defined(__WIN__) /* Copy ownership */ - if (chown(to, stat_buff.st_uid,stat_buff.st_gid)) + if (chown(to, stat_buff.st_uid, stat_buff.st_gid)) { my_errno= errno; if (MyFlags & MY_WME) - my_error(EE_CANT_COPY_OWNERSHIP, MYF(ME_JUST_WARNING), to, errno); + my_error(EE_CANT_COPY_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), to, errno); if (MyFlags & MY_FAE) goto err; } #endif -#if !defined(VMS) && !defined(__ZTC__) + if (MyFlags & MY_COPYTIME) { struct utimbuf timep; timep.actime = stat_buff.st_atime; timep.modtime = stat_buff.st_mtime; - VOID(utime((char*) to, &timep)); /* last accessed and modified times */ + (void) utime((char*) to, &timep); /* last accessed and modified times */ } -#endif + DBUG_RETURN(0); } err: - if (from_file >= 0) VOID(my_close(from_file,MyFlags)); - if (to_file >= 0) VOID(my_close(to_file, MyFlags)); + if (from_file >= 0) (void) my_close(from_file,MyFlags); + if (to_file >= 0) (void) my_close(to_file, MyFlags); /* attempt to delete the to-file we've partially written */ if (file_created) - VOID(my_delete(to, MyFlags)); + (void) my_delete(to, MyFlags); DBUG_RETURN(-1); } /* my_copy */ diff --git a/mysys/my_create.c b/mysys/my_create.c index d0436276d03..49529f9b7b5 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -39,14 +39,11 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, DBUG_ENTER("my_create"); DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", FileName, CreateFlags, access_flags, MyFlags)); - -#if !defined(NO_OPEN_3) - fd= open((char *) FileName, access_flags | O_CREAT, - CreateFlags ? CreateFlags : my_umask); -#elif defined(_WIN32) +#if defined(_WIN32) fd= my_win_open(FileName, access_flags | O_CREAT); #else - fd= open(FileName, access_flags); + fd= open((char *) FileName, access_flags | O_CREAT, + CreateFlags ? CreateFlags : my_umask); #endif if ((MyFlags & MY_SYNC_DIR) && (fd >=0) && diff --git a/mysys/my_delete.c b/mysys/my_delete.c index 22425ed95fd..4a23fedb5ab 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -36,8 +36,8 @@ int my_delete(const char *name, myf MyFlags) DBUG_RETURN(err); } /* my_delete */ -#if defined(__WIN__) && defined(__NT__) -/* +#if defined(__WIN__) +/** Delete file which is possibly not closed. This function is intended to be used exclusively as a temporal solution @@ -53,6 +53,20 @@ int my_delete(const char *name, myf MyFlags) renamed to <name>.<num>.deleted where <name> - the initial name of the file, <num> - a hexadecimal number chosen to make the temporal name to be unique. + + @param the name of the being deleted file + @param the flags instructing how to react on an error internally in + the function + + @note The per-thread @c my_errno holds additional info for a caller to + decide how critical the error can be. + + @retval + 0 ok + @retval + 1 error + + */ int nt_share_delete(const char *name, myf MyFlags) { @@ -63,6 +77,7 @@ int nt_share_delete(const char *name, myf MyFlags) for (cnt= GetTickCount(); cnt; cnt--) { + errno= 0; sprintf(buf, "%s.%08X.deleted", name, cnt); if (MoveFile(name, buf)) break; @@ -79,14 +94,32 @@ int nt_share_delete(const char *name, myf MyFlags) break; } - if (DeleteFile(buf)) - DBUG_RETURN(0); + if (errno == ERROR_FILE_NOT_FOUND) + { + my_errno= ENOENT; // marking, that `name' doesn't exist + } + else if (errno == 0) + { + if (DeleteFile(buf)) + DBUG_RETURN(0); + /* + The below is more complicated than necessary. For some reason, the + assignment to my_errno clears the error number, which is retrieved + by GetLastError() (VC2005EE). Assigning to errno first, allows to + retrieve the correct value. + */ + errno= GetLastError(); + if (errno == 0) + my_errno= ENOENT; // marking, that `buf' doesn't exist + else + my_errno= errno; + } + else + my_errno= errno; - my_errno= GetLastError(); if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_DELETE, MYF(ME_BELL + ME_WAITTANG + (MyFlags & ME_NOINPUT)), - name, my_errno); - + name, my_errno); DBUG_RETURN(-1); } #endif diff --git a/mysys/my_dup.c b/mysys/my_dup.c deleted file mode 100644 index 5fdd6e9f364..00000000000 --- a/mysys/my_dup.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "mysys_priv.h" -#include "mysys_err.h" -#include <my_dir.h> -#include <errno.h> -#if defined(__WIN__) -#include <share.h> -#endif - - /* Open a file */ - -File my_dup(File file, myf MyFlags) -{ - File fd; - const char *filename; - DBUG_ENTER("my_dup"); - DBUG_PRINT("my",("file: %d MyFlags: %d", file, MyFlags)); -#ifdef _WIN32 - fd= my_win_dup(file); -#else - fd= dup(file); -#endif - filename= (((uint) file < my_file_limit) ? - my_file_info[(int) file].name : "Unknown"); - DBUG_RETURN(my_register_filename(fd, filename, FILE_BY_DUP, - EE_FILENOTFOUND, MyFlags)); -} /* my_open */ diff --git a/mysys/my_error.c b/mysys/my_error.c index 4e04d4fadc2..48b907d48cb 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -22,7 +22,6 @@ /* Max length of a error message. Should be kept in sync with MYSQL_ERRMSG_SIZE. */ #define ERRMSGSIZE (512) - /* Define some external variables for error handling */ /* @@ -49,11 +48,11 @@ */ static struct my_err_head { - struct my_err_head *meh_next; /* chain link */ - const char **meh_errmsgs; /* error messages array */ - int meh_first; /* error number matching array slot 0 */ - int meh_last; /* error number matching last slot */ -} my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST}; + struct my_err_head *meh_next; /* chain link */ + const char** (*get_errmsgs) (); /* returns error message format */ + int meh_first; /* error number matching array slot 0 */ + int meh_last; /* error number matching last slot */ +} my_errmsgs_globerrs = {NULL, get_global_errmsgs, EE_ERROR_FIRST, EE_ERROR_LAST}; static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; @@ -67,12 +66,9 @@ static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; MyFlags Flags ... variable list - RETURN - What (*error_handler_hook)() returns: - 0 OK */ -int my_error(int nr, myf MyFlags, ...) +void my_error(int nr, myf MyFlags, ...) { const char *format; struct my_err_head *meh_p; @@ -88,15 +84,17 @@ int my_error(int nr, myf MyFlags, ...) /* get the error message string. Default, if NULL or empty string (""). */ if (! (format= (meh_p && (nr >= meh_p->meh_first)) ? - meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format) - (void) my_snprintf(ebuff, sizeof(ebuff), "Unknown error %d", nr); + meh_p->get_errmsgs()[nr - meh_p->meh_first] : NULL) || ! *format) + (void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr); else { va_start(args,MyFlags); - (void) my_vsnprintf(ebuff, sizeof(ebuff), format, args); + (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, + sizeof(ebuff), format, args); va_end(args); } - DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags)); + (*error_handler_hook)(nr, ebuff, MyFlags); + DBUG_VOID_RETURN; } @@ -111,7 +109,7 @@ int my_error(int nr, myf MyFlags, ...) ... variable list */ -int my_printf_error(uint error, const char *format, myf MyFlags, ...) +void my_printf_error(uint error, const char *format, myf MyFlags, ...) { va_list args; char ebuff[ERRMSGSIZE]; @@ -120,12 +118,13 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...) error, MyFlags, errno, format)); va_start(args,MyFlags); - (void) my_vsnprintf(ebuff, sizeof(ebuff), format, args); + (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, + sizeof(ebuff), format, args); va_end(args); - DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags)); + (*error_handler_hook)(error, ebuff, MyFlags); + DBUG_VOID_RETURN; } - /* Error with va_list @@ -137,15 +136,16 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...) ... variable list */ -int my_printv_error(uint error, const char *format, myf MyFlags, va_list ap) +void my_printv_error(uint error, const char *format, myf MyFlags, va_list ap) { - char ebuff[ERRMSGSIZE+20]; + char ebuff[ERRMSGSIZE]; DBUG_ENTER("my_printv_error"); DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s", error, MyFlags, errno, format)); (void) my_vsnprintf(ebuff, sizeof(ebuff), format, ap); - DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags)); + (*error_handler_hook)(error, ebuff, MyFlags); + DBUG_VOID_RETURN; } @@ -159,9 +159,9 @@ int my_printv_error(uint error, const char *format, myf MyFlags, va_list ap) MyFlags Flags */ -int my_message(uint error, const char *str, register myf MyFlags) +void my_message(uint error, const char *str, register myf MyFlags) { - return (*error_handler_hook)(error, str, MyFlags); + (*error_handler_hook)(error, str, MyFlags); } @@ -187,7 +187,7 @@ int my_message(uint error, const char *str, register myf MyFlags) != 0 Error */ -int my_error_register(const char **errmsgs, int first, int last) +int my_error_register(const char** (*get_errmsgs) (), int first, int last) { struct my_err_head *meh_p; struct my_err_head **search_meh_pp; @@ -196,7 +196,7 @@ int my_error_register(const char **errmsgs, int first, int last) if (! (meh_p= (struct my_err_head*) my_malloc(sizeof(struct my_err_head), MYF(MY_WME)))) return 1; - meh_p->meh_errmsgs= errmsgs; + meh_p->get_errmsgs= get_errmsgs; meh_p->meh_first= first; meh_p->meh_last= last; @@ -212,7 +212,7 @@ int my_error_register(const char **errmsgs, int first, int last) /* Error numbers must be unique. No overlapping is allowed. */ if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last)) { - my_free((uchar*)meh_p, MYF(0)); + my_free(meh_p); return 1; } @@ -267,8 +267,8 @@ const char **my_error_unregister(int first, int last) *search_meh_pp= meh_p->meh_next; /* Save the return value and free the header. */ - errmsgs= meh_p->meh_errmsgs; - my_free((uchar*) meh_p, MYF(0)); + errmsgs= meh_p->get_errmsgs(); + my_free(meh_p); return errmsgs; } @@ -283,7 +283,7 @@ void my_error_unregister_all(void) /* We need this ptr, but we're about to free its container, so save it. */ saved_next= cursor->meh_next; - my_free((uchar*) cursor, MYF(0)); + my_free(cursor); } my_errmsgs_globerrs.meh_next= NULL; /* Freed in first iteration above. */ diff --git a/mysys/my_file.c b/mysys/my_file.c index d8d51b91ab2..a6a4244a772 100644 --- a/mysys/my_file.c +++ b/mysys/my_file.c @@ -127,7 +127,7 @@ void my_free_open_file_info() /* Copy data back for my_print_open_files */ memcpy((char*) my_file_info_default, my_file_info, sizeof(*my_file_info_default)* MY_NFILE); - my_free((char*) my_file_info, MYF(0)); + my_free(my_file_info); my_file_info= my_file_info_default; my_file_limit= MY_NFILE; } diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index ae631a59353..54469d2c05a 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -68,18 +68,18 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) thread_safe_increment(my_stream_opened,&THR_LOCK_open); DBUG_RETURN(fd); /* safeguard */ } - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); if ((my_file_info[filedesc].name= (char*) my_strdup(filename,MyFlags))) { my_stream_opened++; my_file_total_opened++; my_file_info[filedesc].type= STREAM_BY_FOPEN; - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); DBUG_RETURN(fd); } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); (void) my_fclose(fd,MyFlags); my_errno=ENOMEM; } @@ -231,7 +231,7 @@ int my_fclose(FILE *fd, myf MyFlags) DBUG_ENTER("my_fclose"); DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags)); - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); file= my_fileno(fd); #ifndef _WIN32 err= fclose(fd); @@ -250,9 +250,9 @@ int my_fclose(FILE *fd, myf MyFlags) if ((uint) file < my_file_limit && my_file_info[file].type != UNOPEN) { my_file_info[file].type = UNOPEN; - my_free(my_file_info[file].name, MYF(MY_ALLOW_ZERO_PTR)); + my_free(my_file_info[file].name); } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(err); } /* my_fclose */ @@ -282,7 +282,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) } else { - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); my_stream_opened++; if ((uint) Filedes < (uint) my_file_limit) { @@ -296,7 +296,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) } my_file_info[Filedes].type = STREAM_BY_FDOPEN; } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); } DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index 2059e1a9f18..83cb0d261c0 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -119,21 +119,20 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags) #ifdef EINTR if (errno == EINTR) { - VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0))); + (void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0)); continue; } #endif #if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) -#ifdef THREAD if (my_thread_var->abort) MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ -#endif + if ((errno == ENOSPC || errno == EDQUOT) && (MyFlags & MY_WAIT_IF_FULL)) { wait_for_free_space("[stream]", errors); errors++; - VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0))); + (void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0)); continue; } #endif diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index 90908bd1c0d..ab44bac43d3 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -95,7 +95,107 @@ err: return res; } -#else /* FreeBSD elif linux */ +#elif defined(__WIN__) + +/* + Workaround for BUG#32082 (Definition of VOID in my_global.h conflicts with + windows headers) +*/ +#ifdef VOID +#undef VOID +#define VOID void +#endif + +#include <iphlpapi.h> + +/* + The following typedef is for dynamically loading iphlpapi.dll / + GetAdaptersAddresses. Dynamic loading is used because + GetAdaptersAddresses is not available on Windows 2000 which MySQL + still supports. Static linking would cause an unresolved export. +*/ +typedef DWORD (WINAPI *pfnGetAdaptersAddresses)(IN ULONG Family, + IN DWORD Flags,IN PVOID Reserved, + OUT PIP_ADAPTER_ADDRESSES pAdapterAddresses, + IN OUT PULONG pOutBufLen); + +/* + my_gethwaddr - Windows version + + @brief Retrieve MAC address from network hardware + + @param[out] to MAC address exactly six bytes + + @return Operation status + @retval 0 OK + @retval <>0 FAILED +*/ +my_bool my_gethwaddr(uchar *to) +{ + PIP_ADAPTER_ADDRESSES pAdapterAddresses; + PIP_ADAPTER_ADDRESSES pCurrAddresses; + IP_ADAPTER_ADDRESSES adapterAddresses; + ULONG address_len; + my_bool return_val= 1; + static pfnGetAdaptersAddresses fnGetAdaptersAddresses= + (pfnGetAdaptersAddresses)-1; + + if(fnGetAdaptersAddresses == (pfnGetAdaptersAddresses)-1) + { + /* Get the function from the DLL */ + fnGetAdaptersAddresses= (pfnGetAdaptersAddresses) + GetProcAddress(LoadLibrary("iphlpapi.dll"), + "GetAdaptersAddresses"); + } + if (!fnGetAdaptersAddresses) + return 1; /* failed to get function */ + address_len= sizeof (IP_ADAPTER_ADDRESSES); + + /* Get the required size for the address data. */ + if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, &adapterAddresses, &address_len) + == ERROR_BUFFER_OVERFLOW) + { + pAdapterAddresses= my_malloc(address_len, 0); + if (!pAdapterAddresses) + return 1; /* error, alloc failed */ + } + else + pAdapterAddresses= &adapterAddresses; /* one is enough don't alloc */ + + /* Get the hardware info. */ + if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &address_len) + == NO_ERROR) + { + pCurrAddresses= pAdapterAddresses; + + while (pCurrAddresses) + { + /* Look for ethernet cards. */ + if (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD) + { + /* check for a good address */ + if (pCurrAddresses->PhysicalAddressLength < 6) + continue; /* bad address */ + + /* save 6 bytes of the address in the 'to' parameter */ + memcpy(to, pCurrAddresses->PhysicalAddress, 6); + + /* Network card found, we're done. */ + return_val= 0; + break; + } + pCurrAddresses= pCurrAddresses->Next; + } + } + + /* Clean up memory allocation. */ + if (pAdapterAddresses != &adapterAddresses) + my_free(pAdapterAddresses); + + return return_val; +} + +#else /* __FreeBSD__ || __linux__ || __WIN__ */ /* just fail */ my_bool my_gethwaddr(uchar *to __attribute__((unused))) { diff --git a/mysys/my_getncpus.c b/mysys/my_getncpus.c index de176803b4d..a7631e15966 100644 --- a/mysys/my_getncpus.c +++ b/mysys/my_getncpus.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright (C) 2006 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -30,7 +30,15 @@ int my_getncpus() ncpus= sysconf(_SC_NPROCESSORS_ONLN); #elif defined(__WIN__) SYSTEM_INFO sysinfo; + + /* + * We are not calling GetNativeSystemInfo here because (1) we + * don't believe that they return different values for number + * of processors and (2) if WOW64 limits processors for Win32 + * then we don't want to try to override that. + */ GetSystemInfo(&sysinfo); + ncpus= sysinfo.dwNumberOfProcessors; #else /* unknown so play safe: assume SMP and forbid uniprocessor build */ diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 5d0703f09a8..d9e34cbece6 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002-2006 MySQL AB +/* Copyright (c) 2002, 2011, 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 @@ -28,24 +28,15 @@ typedef void (*init_func_p)(const struct my_option *option, void *variable, static void default_reporter(enum loglevel level, const char *format, ...); my_error_reporter my_getopt_error_reporter= &default_reporter; -static int findopt(char *optpat, uint length, - const struct my_option **opt_res, - const char **ffname); -my_bool getopt_compare_strings(const char *s, - const char *t, - uint length); +static int findopt(char *, uint, const struct my_option **, const char **); +my_bool getopt_compare_strings(const char *, const char *, uint); static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); -static ulonglong getopt_ull(char *arg, const struct my_option *optp, - int *err); +static ulonglong getopt_ull(char *, const struct my_option *, int *); static double getopt_double(char *arg, const struct my_option *optp, int *err); -static void init_variables(const struct my_option *options, - init_func_p init_one_value); -static void init_one_value(const struct my_option *option, void *variable, - longlong value); -static void fini_one_value(const struct my_option *option, void *variable, - longlong value); -static int setval(const struct my_option *opts, void *value, char *argument, - my_bool set_maximum_value); +static void init_variables(const struct my_option *, init_func_p); +static void init_one_value(const struct my_option *, void *, longlong); +static void fini_one_value(const struct my_option *, void *, longlong); +static int setval(const struct my_option *, void *, char *, my_bool); static char *check_struct_option(char *cur_arg, char *key_name); /* @@ -60,6 +51,7 @@ enum enum_special_opt { OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE}; char *disabled_my_option= (char*) "0"; +char *enabled_my_option= (char*) "1"; /* This is a flag that can be set in client programs. 0 means that @@ -80,6 +72,8 @@ static void default_reporter(enum loglevel level, const char *format, ...) { va_list args; + DBUG_ENTER("default_reporter"); + va_start(args, format); if (level == WARNING_LEVEL) fprintf(stderr, "%s", "Warning: "); @@ -89,18 +83,9 @@ static void default_reporter(enum loglevel level, va_end(args); fputc('\n', stderr); fflush(stderr); + DBUG_VOID_RETURN; } -/* - function: handle_options - - Sort options; put options first, until special end of options (--), or - until end of argv. Parse options; check that the given option matches with - one of the options in struct 'my_option', return error in case of ambiguous - or unknown option. Check that option was given an argument if it requires - one. Call function 'get_one_option()' once for each option. -*/ - static my_getopt_value getopt_get_addr; void my_getopt_register_get_addr(my_getopt_value func_addr) @@ -108,6 +93,65 @@ void my_getopt_register_get_addr(my_getopt_value func_addr) getopt_get_addr= func_addr; } +/** + Handle command line options. + Sort options. + Put options first, until special end of options (--), + or until the end of argv. Parse options, check that the given option + matches with one of the options in struct 'my_option'. + Check that option was given an argument if it requires one + Call the optional 'get_one_option()' function once for each option. + + Note that handle_options() can be invoked multiple times to + parse a command line in several steps. + In this case, use the global flag @c my_getopt_skip_unknown to indicate + that options unknown in the current step should be preserved in the + command line for later parsing in subsequent steps. + + For 'long' options (--a_long_option), @c my_getopt_skip_unknown is + fully supported. Command line parameters such as: + - "--a_long_option" + - "--a_long_option=value" + - "--a_long_option value" + will be preserved as is when the option is not known. + + For 'short' options (-S), support for @c my_getopt_skip_unknown + comes with some limitation, because several short options + can also be specified together in the same command line argument, + as in "-XYZ". + + The first use case supported is: all short options are declared. + handle_options() will be able to interpret "-XYZ" as one of: + - an unknown X option + - "-X -Y -Z", three short options with no arguments + - "-X -YZ", where Y is a short option with argument Z + - "-XYZ", where X is a short option with argument YZ + based on the full short options specifications. + + The second use case supported is: no short option is declared. + handle_options() will reject "-XYZ" as unknown, to be parsed later. + + The use case that is explicitly not supported is to provide + only a partial list of short options to handle_options(). + This function can not be expected to extract some option Y + in the middle of the string "-XYZ" in these conditions, + without knowing if X will be declared an option later. + + Note that this limitation only impacts parsing of several + short options from the same command line argument, + as in "mysqld -anW5". + When each short option is properly separated out in the command line + argument, for example in "mysqld -a -n -w5", the code would actually + work even with partial options specs given at each stage. + + @param [in, out] argc command line options (count) + @param [in, out] argv command line options (values) + @param [in] longopts descriptor of all valid options + @param [in] get_one_option optional callback function to process each option, + can be NULL. + @return error in case of ambiguous or unknown options, + 0 on success. +*/ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_get_one_option get_one_option) @@ -116,10 +160,12 @@ int handle_options(int *argc, char ***argv, my_bool end_of_options= 0, must_be_var, set_maximum_value, option_is_loose; char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN]; - const char *prev_found; + const char *UNINIT_VAR(prev_found); const struct my_option *optp; void *value; int error, i; + my_bool is_cmdline_arg= 1; + DBUG_ENTER("handle_options"); /* handle_options() assumes arg0 (program name) always exists */ DBUG_ASSERT(argc && *argc >= 1); @@ -128,10 +174,35 @@ int handle_options(int *argc, char ***argv, (*argv)++; /* --- || ---- */ init_variables(longopts, init_one_value); + /* + Search for args_separator, if found, then the first part of the + arguments are loaded from configs + */ + for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) + { + if (my_getopt_is_args_separator(*pos)) + { + is_cmdline_arg= 0; + break; + } + } + for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { char **first= pos; char *cur_arg= *pos; + opt_found= 0; + if (!is_cmdline_arg && (my_getopt_is_args_separator(cur_arg))) + { + is_cmdline_arg= 1; + + /* save the separator too if skip unkown options */ + if (my_getopt_skip_unknown) + (*argv)[argvpos++]= cur_arg; + else + (*argc)--; + continue; + } if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ { char *argument= 0; @@ -140,78 +211,15 @@ int handle_options(int *argc, char ***argv, option_is_loose= 0; cur_arg++; /* skip '-' */ - if (*cur_arg == '-' || *cur_arg == 'O') /* check for long option, */ - { /* --set-variable, or -O */ - if (*cur_arg == 'O') - { - my_getopt_error_reporter(WARNING_LEVEL, - "%s: Option '-O' is deprecated. " - "Use --variable-name=value instead.", - my_progname); - must_be_var= 1; - - if (!(*++cur_arg)) /* If not -Ovar=# */ - { - /* the argument must be in next argv */ - if (!*++pos) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Option '-O' requires an argument", - my_progname); - return EXIT_ARGUMENT_REQUIRED; - } - cur_arg= *pos; - (*argc)--; - } - } - else if (!getopt_compare_strings(cur_arg, "-set-variable", 13)) - { - my_getopt_error_reporter(WARNING_LEVEL, - "%s: Option '--set-variable' is deprecated. " - "Use --variable-name=value instead.", - my_progname); - - must_be_var= 1; - if (cur_arg[13] == '=') - { - cur_arg+= 14; - if (!*cur_arg) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Option '--set-variable' requires an argument", - my_progname); - return EXIT_ARGUMENT_REQUIRED; - } - } - else if (cur_arg[14]) /* garbage, or another option. break out */ - must_be_var= 0; - else - { - /* the argument must be in next argv */ - if (!*++pos) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Option '--set-variable' requires an argument", - my_progname); - return EXIT_ARGUMENT_REQUIRED; - } - cur_arg= *pos; - (*argc)--; - } - } - else if (!must_be_var) - { - if (!*++cur_arg) /* skip the double dash */ - { - /* '--' means end of options, look no further */ - end_of_options= 1; - (*argc)--; - continue; - } - } + if (*cur_arg == '-') /* check for long option, */ + { + if (!*++cur_arg) /* skip the double dash */ + { + /* '--' means end of options, look no further */ + end_of_options= 1; + (*argc)--; + continue; + } opt_str= check_struct_option(cur_arg, key_name); optend= strcend(opt_str, '='); length= (uint) (optend - opt_str); @@ -224,7 +232,6 @@ int handle_options(int *argc, char ***argv, Find first the right option. Return error in case of an ambiguous, or unknown option */ - LINT_INIT(prev_found); optp= longopts; if (!(opt_found= findopt(opt_str, length, &optp, &prev_found))) { @@ -258,9 +265,9 @@ int handle_options(int *argc, char ***argv, my_getopt_error_reporter(ERROR_LEVEL, "%s: ambiguous option '--%s-%s' (--%s-%s)", my_progname, special_opt_prefix[i], - cur_arg, special_opt_prefix[i], + opt_str, special_opt_prefix[i], prev_found); - return EXIT_AMBIGUOUS_OPTION; + DBUG_RETURN(EXIT_AMBIGUOUS_OPTION); } switch (i) { case OPT_SKIP: @@ -270,11 +277,11 @@ int handle_options(int *argc, char ***argv, for example: --skip-option=0 -> option = TRUE */ optend= (optend && *optend == '0' && !(*(optend + 1))) ? - (char*) "1" : disabled_my_option; + enabled_my_option : disabled_my_option; break; case OPT_ENABLE: optend= (optend && *optend == '0' && !(*(optend + 1))) ? - disabled_my_option : (char*) "1"; + disabled_my_option : enabled_my_option; break; case OPT_MAXIMUM: set_maximum_value= 1; @@ -291,12 +298,7 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_skip_unknown) { - /* - preserve all the components of this unknown option, this may - occurr when the user provides options like: "-O foo" or - "--set-variable foo" (note that theres a space in there) - Generally, these kind of options are to be avoided - */ + /* Preserve all the components of this unknown option. */ do { (*argv)[argvpos++]= *first++; } while (first <= pos); @@ -310,7 +312,7 @@ int handle_options(int *argc, char ***argv, "%s: unknown variable '%s'", my_progname, cur_arg); if (!option_is_loose) - return EXIT_UNKNOWN_VARIABLE; + DBUG_RETURN(EXIT_UNKNOWN_VARIABLE); } else { @@ -320,7 +322,7 @@ int handle_options(int *argc, char ***argv, "%s: unknown option '--%s'", my_progname, cur_arg); if (!option_is_loose) - return EXIT_UNKNOWN_OPTION; + DBUG_RETURN(EXIT_UNKNOWN_OPTION); } if (option_is_loose) { @@ -337,7 +339,7 @@ int handle_options(int *argc, char ***argv, my_getopt_error_reporter(ERROR_LEVEL, "%s: variable prefix '%s' is not unique", my_progname, opt_str); - return EXIT_VAR_PREFIX_NOT_UNIQUE; + DBUG_RETURN(EXIT_VAR_PREFIX_NOT_UNIQUE); } else { @@ -346,7 +348,7 @@ int handle_options(int *argc, char ***argv, "%s: ambiguous option '--%s' (%s, %s)", my_progname, opt_str, prev_found, optp->name); - return EXIT_AMBIGUOUS_OPTION; + DBUG_RETURN(EXIT_AMBIGUOUS_OPTION); } } if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) @@ -360,32 +362,29 @@ int handle_options(int *argc, char ***argv, (*argc)--; continue; } - return EXIT_OPTION_DISABLED; - } - if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: option '%s' cannot take an argument", - my_progname, optp->name); - return EXIT_NO_ARGUMENT_ALLOWED; + DBUG_RETURN(EXIT_OPTION_DISABLED); } error= 0; value= optp->var_type & GET_ASK_ADDR ? (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) : optp->value; if (error) - return error; + DBUG_RETURN(error); if (optp->arg_type == NO_ARG) { + /* + Due to historical reasons GET_BOOL var_types still accepts arguments + despite the NO_ARG arg_type attribute. This can seems a bit unintuitive + and care should be taken when refactoring this code. + */ if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL) { if (my_getopt_print_errors) my_getopt_error_reporter(ERROR_LEVEL, "%s: option '--%s' cannot take an argument", my_progname, optp->name); - return EXIT_NO_ARGUMENT_ALLOWED; + DBUG_RETURN(EXIT_NO_ARGUMENT_ALLOWED); } if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) { @@ -393,7 +392,7 @@ int handle_options(int *argc, char ***argv, Set bool to 1 if no argument or if the user has used --enable-'option-name'. *optend was set to '0' if one used --disable-option - */ + */ (*argc)--; if (!optend || *optend == '1' || !my_strcasecmp(&my_charset_latin1, optend, "true")) @@ -404,43 +403,32 @@ int handle_options(int *argc, char ***argv, else { my_getopt_error_reporter(WARNING_LEVEL, - "%s: ignoring option '--%s' due to " - "invalid value '%s'", + "%s: ignoring option '--%s' " + "due to invalid value '%s'", my_progname, optp->name, optend); continue; } - if (get_one_option(optp->id, optp, + if (get_one_option && get_one_option(optp->id, optp, *((my_bool*) value) ? - (char*) "1" : disabled_my_option)) - return EXIT_ARGUMENT_INVALID; + enabled_my_option : disabled_my_option)) + DBUG_RETURN(EXIT_ARGUMENT_INVALID); continue; } argument= optend; } - else if (optp->arg_type == OPT_ARG && - (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) || - (optp->var_type & GET_TYPE_MASK) == GET_ENUM)) - { - if (optend == disabled_my_option) - init_one_value(optp, value, 0); - else - { - if (!optend) /* No argument -> enable option */ - init_one_value(optp, value, 1); - else - argument= optend; - } - } else if (optp->arg_type == REQUIRED_ARG && !optend) { - /* Check if there are more arguments after this one */ - if (!*++pos) + /* Check if there are more arguments after this one, + Note: options loaded from config file that requires value + should always be in the form '--option=value'. + */ + if (!is_cmdline_arg || !*++pos) { if (my_getopt_print_errors) my_getopt_error_reporter(ERROR_LEVEL, "%s: option '--%s' requires an argument", my_progname, optp->name); - return EXIT_ARGUMENT_REQUIRED; + DBUG_RETURN(EXIT_ARGUMENT_REQUIRED); } argument= *pos; (*argc)--; @@ -453,9 +441,9 @@ int handle_options(int *argc, char ***argv, for (optend= cur_arg; *optend; optend++) { opt_found= 0; - for (optp= longopts; optp->id; optp++) + for (optp= longopts; optp->name; optp++) { - if (optp->id == (int) (uchar) *optend) + if (optp->id && optp->id == (int) (uchar) *optend) { /* Option recognized. Find next what to do with it */ opt_found= 1; @@ -465,14 +453,14 @@ int handle_options(int *argc, char ***argv, fprintf(stderr, "%s: ERROR: Option '-%c' used, but is disabled\n", my_progname, optp->id); - return EXIT_OPTION_DISABLED; + DBUG_RETURN(EXIT_OPTION_DISABLED); } if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL && optp->arg_type == NO_ARG) { *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; + if (get_one_option && get_one_option(optp->id, optp, argument)) + DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); continue; } else if (optp->arg_type == REQUIRED_ARG || @@ -491,8 +479,8 @@ int handle_options(int *argc, char ***argv, { if (optp->var_type == GET_BOOL) *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; + if (get_one_option && get_one_option(optp->id, optp, argument)) + DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); continue; } /* Check if there are more arguments after this one */ @@ -502,7 +490,7 @@ int handle_options(int *argc, char ***argv, my_getopt_error_reporter(ERROR_LEVEL, "%s: option '-%c' requires an argument", my_progname, optp->id); - return EXIT_ARGUMENT_REQUIRED; + DBUG_RETURN(EXIT_ARGUMENT_REQUIRED); } argument= *++pos; (*argc)--; @@ -511,40 +499,57 @@ int handle_options(int *argc, char ***argv, } if ((error= setval(optp, optp->value, argument, set_maximum_value))) - { - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Error while setting value '%s' to '%s'", - my_progname, argument, optp->name); - return error; - } - if (get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; + DBUG_RETURN(error); + if (get_one_option && get_one_option(optp->id, optp, argument)) + DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); break; } } if (!opt_found) { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: unknown option '-%c'", - my_progname, *optend); - return EXIT_UNKNOWN_OPTION; + if (my_getopt_skip_unknown) + { + /* + We are currently parsing a single argv[] argument + of the form "-XYZ". + One or the argument found (say Y) is not an option. + Hack the string "-XYZ" to make a "-YZ" substring in it, + and push that to the output as an unrecognized parameter. + */ + DBUG_ASSERT(optend > *pos); + DBUG_ASSERT(optend >= cur_arg); + DBUG_ASSERT(optend <= *pos + strlen(*pos)); + DBUG_ASSERT(*optend); + optend--; + optend[0]= '-'; /* replace 'X' or '-' by '-' */ + (*argv)[argvpos++]= optend; + /* + Do not continue to parse at the current "-XYZ" argument, + skip to the next argv[] argument instead. + */ + optend= (char*) " "; + } + else + { + if (my_getopt_print_errors) + my_getopt_error_reporter(ERROR_LEVEL, + "%s: unknown option '-%c'", + my_progname, *optend); + DBUG_RETURN(EXIT_UNKNOWN_OPTION); + } } } - (*argc)--; /* option handled (short), decrease argument count */ + if (opt_found) + (*argc)--; /* option handled (short), decrease argument count */ continue; } - if ((error= setval(optp, value, argument, set_maximum_value))) - { - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Error while setting value '%s' to '%s'", - my_progname, argument, optp->name); - return error; - } - if (get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; + if (((error= setval(optp, value, argument, set_maximum_value))) && + !option_is_loose) + DBUG_RETURN(error); + if (get_one_option && get_one_option(optp->id, optp, argument)) + DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); - (*argc)--; /* option handled (short or long), decrease argument count */ + (*argc)--; /* option handled (long), decrease argument count */ } else /* non-option found */ (*argv)[argvpos++]= cur_arg; @@ -556,7 +561,7 @@ int handle_options(int *argc, char ***argv, to the program, yet to be (possibly) handled. */ (*argv)[argvpos]= 0; - return 0; + DBUG_RETURN(0); } @@ -577,6 +582,7 @@ int handle_options(int *argc, char ***argv, static char *check_struct_option(char *cur_arg, char *key_name) { char *ptr, *end; + DBUG_ENTER("check_struct_option"); ptr= strcend(cur_arg + 1, '.'); /* Skip the first character */ end= strcend(cur_arg, '='); @@ -593,15 +599,43 @@ static char *check_struct_option(char *cur_arg, char *key_name) uint len= (uint) (ptr - cur_arg); set_if_smaller(len, FN_REFLEN-1); strmake(key_name, cur_arg, len); - return ++ptr; + DBUG_RETURN(++ptr); } else { key_name[0]= 0; - return cur_arg; + DBUG_RETURN(cur_arg); } } +/** + Parse a boolean command line argument + + "ON", "TRUE" and "1" will return true, + other values will return false. + + @param[in] argument The value argument + @return boolean value +*/ +static my_bool get_bool_argument(const struct my_option *opts, + const char *argument) +{ + DBUG_ENTER("get_bool_argument"); + + if (!my_strcasecmp(&my_charset_latin1, argument, "true") || + !my_strcasecmp(&my_charset_latin1, argument, "on") || + !my_strcasecmp(&my_charset_latin1, argument, "1")) + DBUG_RETURN(1); + else if (!my_strcasecmp(&my_charset_latin1, argument, "false") || + !my_strcasecmp(&my_charset_latin1, argument, "off") || + !my_strcasecmp(&my_charset_latin1, argument, "0")) + DBUG_RETURN(0); + my_getopt_error_reporter(WARNING_LEVEL, + "option '%s': boolean value '%s' wasn't recognized. Set to OFF.", + opts->name, argument); + DBUG_RETURN(0); +} + /* function: setval @@ -612,53 +646,66 @@ static char *check_struct_option(char *cur_arg, char *key_name) static int setval(const struct my_option *opts, void *value, char *argument, my_bool set_maximum_value) { - int err= 0; + int err= 0, res= 0; + DBUG_ENTER("setval"); - if (value && argument) - { - void *result_pos= ((set_maximum_value) ? opts->u_max_value : value); + if (!argument) + argument= enabled_my_option; - if (!result_pos) - return EXIT_NO_PTR_TO_VARIABLE; + if (value) + { + if (set_maximum_value && !(value= opts->u_max_value)) + { + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Maximum value of '%s' cannot be set", + my_progname, opts->name); + DBUG_RETURN(EXIT_NO_PTR_TO_VARIABLE); + } switch ((opts->var_type & GET_TYPE_MASK)) { case GET_BOOL: /* If argument differs from 0, enable option, else disable */ - *((my_bool*) result_pos)= (my_bool) atoi(argument) != 0; + *((my_bool*) value)= get_bool_argument(opts, argument); break; case GET_INT: - *((int*) result_pos)= (int) getopt_ll(argument, opts, &err); + *((int*) value)= (int) getopt_ll(argument, opts, &err); break; case GET_UINT: - *((uint*) result_pos)= (uint) getopt_ull(argument, opts, &err); + *((uint*) value)= (uint) getopt_ull(argument, opts, &err); break; case GET_LONG: - *((long*) result_pos)= (long) getopt_ll(argument, opts, &err); + *((long*) value)= (long) getopt_ll(argument, opts, &err); break; case GET_ULONG: - *((long*) result_pos)= (long) getopt_ull(argument, opts, &err); + *((long*) value)= (long) getopt_ull(argument, opts, &err); break; case GET_LL: - *((longlong*) result_pos)= getopt_ll(argument, opts, &err); + *((longlong*) value)= getopt_ll(argument, opts, &err); break; case GET_ULL: - *((ulonglong*) result_pos)= getopt_ull(argument, opts, &err); + *((ulonglong*) value)= getopt_ull(argument, opts, &err); break; case GET_DOUBLE: - *((double*) result_pos)= getopt_double(argument, opts, &err); + *((double*) value)= getopt_double(argument, opts, &err); break; case GET_STR: - *((char**) result_pos)= argument; + if (argument == enabled_my_option) + break; /* string options don't use this default of "1" */ + *((char**) value)= argument; break; case GET_STR_ALLOC: - if ((*((char**) result_pos))) - my_free((*(char**) result_pos), MYF(MY_WME | MY_FAE)); - if (!(*((char**) result_pos)= my_strdup(argument, MYF(MY_WME)))) - return EXIT_OUT_OF_MEMORY; + if (argument == enabled_my_option) + break; /* string options don't use this default of "1" */ + my_free(*((char**) value)); + if (!(*((char**) value)= my_strdup(argument, MYF(MY_WME)))) + { + res= EXIT_OUT_OF_MEMORY; + goto ret; + }; break; case GET_ENUM: { - int type= find_type(argument, opts->typelib, 2); - if (type < 1) + int type= find_type(argument, opts->typelib, FIND_TYPE_BASIC); + if (type == 0) { /* Accept an integer representation of the enumerated item. @@ -666,25 +713,66 @@ static int setval(const struct my_option *opts, void *value, char *argument, char *endptr; ulong arg= strtoul(argument, &endptr, 10); if (*endptr || arg >= opts->typelib->count) - return EXIT_ARGUMENT_INVALID; - *((ulong*) result_pos)= arg; + { + res= EXIT_ARGUMENT_INVALID; + goto ret; + } + *(ulong*)value= arg; } else - *((ulong*) result_pos)= type - 1; + *(ulong*)value= type - 1; } break; case GET_SET: - *((ulonglong*)result_pos)= find_typeset(argument, opts->typelib, &err); + *((ulonglong*)value)= find_typeset(argument, opts->typelib, &err); if (err) - return EXIT_ARGUMENT_INVALID; + { + /* Accept an integer representation of the set */ + char *endptr; + ulonglong arg= (ulonglong) strtol(argument, &endptr, 10); + if (*endptr || (arg >> 1) >= (1ULL << (opts->typelib->count-1))) + { + res= EXIT_ARGUMENT_INVALID; + goto ret; + }; + *(ulonglong*)value= arg; + err= 0; + } break; - default: /* dummy default to avoid compiler warnings */ + case GET_FLAGSET: + { + char *error; + uint error_len; + + *((ulonglong*)value)= + find_set_from_flags(opts->typelib, opts->typelib->count, + *(ulonglong *)value, opts->def_value, + argument, strlen(argument), + &error, &error_len); + if (error) + { + res= EXIT_ARGUMENT_INVALID; + goto ret; + }; + } + break; + case GET_NO_ARG: /* get_one_option has taken care of the value already */ + default: /* dummy default to avoid compiler warnings */ break; } if (err) - return EXIT_UNKNOWN_SUFFIX; + { + res= EXIT_UNKNOWN_SUFFIX; + goto ret; + }; } - return 0; + DBUG_RETURN(0); + +ret: + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Error while setting value '%s' to '%s'", + my_progname, argument, opts->name); + DBUG_RETURN(res); } @@ -716,6 +804,7 @@ static int findopt(char *optpat, uint length, { uint count; const struct my_option *opt= *opt_res; + DBUG_ENTER("findopt"); for (count= 0; opt->name; opt++) { @@ -723,7 +812,7 @@ static int findopt(char *optpat, uint length, { (*opt_res)= opt; if (!opt->name[length]) /* Exact match */ - return 1; + DBUG_RETURN(1); if (!count) { /* We only need to know one prev */ @@ -740,7 +829,7 @@ static int findopt(char *optpat, uint length, } } } - return count; + DBUG_RETURN(count); } @@ -755,12 +844,14 @@ my_bool getopt_compare_strings(register const char *s, register const char *t, uint length) { char const *end= s + length; + DBUG_ENTER("getopt_compare_strings"); + for (;s != end ; s++, t++) { if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_')) - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } /* @@ -774,6 +865,8 @@ static longlong eval_num_suffix(char *argument, int *error, char *option_name) { char *endchar; longlong num; + DBUG_ENTER("eval_num_suffix"); + *error= 0; errno= 0; @@ -783,7 +876,7 @@ static longlong eval_num_suffix(char *argument, int *error, char *option_name) my_getopt_error_reporter(ERROR_LEVEL, "Incorrect integer value: '%s'", argument); *error= 1; - return 0; + DBUG_RETURN(0); } if (*endchar == 'k' || *endchar == 'K') num*= 1024L; @@ -797,9 +890,9 @@ static longlong eval_num_suffix(char *argument, int *error, char *option_name) "Unknown suffix '%c' used for variable '%s' (value '%s')\n", *endchar, option_name, argument); *error= 1; - return 0; + DBUG_RETURN(0); } - return num; + DBUG_RETURN(num); } /* @@ -833,6 +926,7 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, my_bool adjusted= FALSE; char buf1[255], buf2[255]; ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L); + DBUG_ENTER("getopt_ll_limit_value"); if (num > 0 && ((ulonglong) num > (ulonglong) optp->max_value) && optp->max_value) /* if max value is not set -> no upper limit */ @@ -863,7 +957,7 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, break; } - num= ((num - optp->sub_size) / block_size); + num= (num / block_size); num= (longlong) (num * block_size); if (num < optp->min_value) @@ -874,12 +968,12 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, } if (fix) - *fix= adjusted; + *fix= old != num; else if (adjusted) my_getopt_error_reporter(WARNING_LEVEL, "option '%s': signed value %s adjusted to %s", optp->name, llstr(old, buf1), llstr(num, buf2)); - return num; + DBUG_RETURN(num); } /* @@ -902,6 +996,7 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, my_bool adjusted= FALSE; ulonglong old= num; char buf1[255], buf2[255]; + DBUG_ENTER("getopt_ull_limit_value"); if ((ulonglong) num > (ulonglong) optp->max_value && optp->max_value) /* if max value is not set -> no upper limit */ @@ -946,14 +1041,40 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, } if (fix) - *fix= adjusted; + *fix= old != num; else if (adjusted) my_getopt_error_reporter(WARNING_LEVEL, "option '%s': unsigned value %s adjusted to %s", optp->name, ullstr(old, buf1), ullstr(num, buf2)); - return num; + + DBUG_RETURN(num); } +double getopt_double_limit_value(double num, const struct my_option *optp, + my_bool *fix) +{ + my_bool adjusted= FALSE; + double old= num; + DBUG_ENTER("getopt_double_limit_value"); + + if (optp->max_value && num > (double) optp->max_value) + { + num= (double) optp->max_value; + adjusted= TRUE; + } + if (num < (double) optp->min_value) + { + num= (double) optp->min_value; + adjusted= TRUE; + } + if (fix) + *fix= adjusted; + else if (adjusted) + my_getopt_error_reporter(WARNING_LEVEL, + "option '%s': value %g adjusted to %g", + optp->name, old, num); + DBUG_RETURN(num); +} /* Get double value withing ranges @@ -975,15 +1096,12 @@ static double getopt_double(char *arg, const struct my_option *optp, int *err) num= my_strtod(arg, &end, &error); if (end[0] != 0 || error) { - fprintf(stderr, - "%s: ERROR: Invalid decimal value for option '%s'\n", - my_progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "Invalid decimal value for option '%s'\n", optp->name); *err= EXIT_ARGUMENT_INVALID; return 0.0; } - if (optp->max_value && num > (double) optp->max_value) - num= (double) optp->max_value; - return max(num, (double) optp->min_value); + return getopt_double_limit_value(num, optp, NULL); } /* @@ -1025,10 +1143,11 @@ static void init_one_value(const struct my_option *option, void *variable, *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL); break; case GET_SET: + case GET_FLAGSET: *((ulonglong*) variable)= (ulonglong) value; break; case GET_DOUBLE: - *((double*) variable)= (double) value; + *((double*) variable)= ulonglong2double(value); break; case GET_STR: /* @@ -1049,8 +1168,9 @@ static void init_one_value(const struct my_option *option, void *variable, */ if ((char*) (intptr) value) { - my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR)); - *((char**) variable)= my_strdup((char*) (intptr) value, MYF(MY_WME)); + char **pstr= (char **) variable; + my_free(*pstr); + *pstr= my_strdup((char*) (intptr) value, MYF(MY_WME)); } break; default: /* dummy default to avoid compiler warnings */ @@ -1075,7 +1195,7 @@ static void fini_one_value(const struct my_option *option, void *variable, DBUG_ENTER("fini_one_value"); switch ((option->var_type & GET_TYPE_MASK)) { case GET_STR_ALLOC: - my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR)); + my_free(*((char**) variable)); *((char**) variable)= NULL; break; default: /* dummy default to avoid compiler warnings */ @@ -1087,7 +1207,9 @@ static void fini_one_value(const struct my_option *option, void *variable, void my_cleanup_options(const struct my_option *options) { + DBUG_ENTER("my_cleanup_options"); init_variables(options, fini_one_value); + DBUG_VOID_RETURN; } @@ -1100,7 +1222,7 @@ void my_cleanup_options(const struct my_option *options) NOTES We will initialize the value that is pointed to by options->value. - If the value is of type GET_ASK_ADDR, we will also ask for the address + If the value is of type GET_ASK_ADDR, we will ask for the address for a value and initialize. */ @@ -1110,7 +1232,7 @@ static void init_variables(const struct my_option *options, DBUG_ENTER("init_variables"); for (; options->name; options++) { - void *variable; + void *value; DBUG_PRINT("options", ("name: '%s'", options->name)); /* We must set u_max_value first as for some variables @@ -1119,15 +1241,23 @@ static void init_variables(const struct my_option *options, */ if (options->u_max_value) init_one_value(options, options->u_max_value, options->max_value); - if (options->value) - init_one_value(options, options->value, options->def_value); - if (options->var_type & GET_ASK_ADDR && - (variable= (*getopt_get_addr)("", 0, options, 0))) - init_one_value(options, variable, options->def_value); + value= (options->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, options, 0) : options->value); + if (value) + init_one_value(options, value, options->def_value); } DBUG_VOID_RETURN; } +/** Prints variable or option name, replacing _ with - */ +static uint print_name(const struct my_option *optp) +{ + const char *s= optp->name; + + for (;*s;s++) + putchar(*s == '_' ? '-' : *s); + return s - optp->name; +} /* function: my_print_options @@ -1135,17 +1265,16 @@ static void init_variables(const struct my_option *options, Print help for all options and variables. */ -#include <help_start.h> - void my_print_help(const struct my_option *options) { uint col, name_space= 22, comment_space= 57; const char *line_end; const struct my_option *optp; + DBUG_ENTER("my_print_help"); - for (optp= options; optp->id; optp++) + for (optp= options; optp->name; optp++) { - if (optp->id < 256) + if (optp->id && optp->id < 256) { printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " "); col= 6; @@ -1157,21 +1286,24 @@ void my_print_help(const struct my_option *options) } if (strlen(optp->name)) { - printf("--%s", optp->name); - col+= 2 + (uint) strlen(optp->name); - if ((optp->var_type & GET_TYPE_MASK) == GET_STR || - (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC) + printf("--"); + col+= 2 + print_name(optp); + if (optp->arg_type == NO_ARG || + (optp->var_type & GET_TYPE_MASK) == GET_BOOL) + { + putchar(' '); + col++; + } + else if ((optp->var_type & GET_TYPE_MASK) == GET_STR || + (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC || + (optp->var_type & GET_TYPE_MASK) == GET_ENUM || + (optp->var_type & GET_TYPE_MASK) == GET_SET || + (optp->var_type & GET_TYPE_MASK) == GET_FLAGSET ) { printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "", optp->arg_type == OPT_ARG ? "]" : ""); col+= (optp->arg_type == OPT_ARG) ? 8 : 6; } - else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG || - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) - { - putchar(' '); - col++; - } else { printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "", @@ -1203,7 +1335,17 @@ void my_print_help(const struct my_option *options) printf("%s", comment); } putchar('\n'); + if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) + { + if (optp->def_value != 0) + { + printf("%*s(Defaults to on; use --skip-", name_space, ""); + print_name(optp); + printf(" to disable.)\n"); + } + } } + DBUG_VOID_RETURN; } @@ -1216,35 +1358,53 @@ void my_print_help(const struct my_option *options) void my_print_variables(const struct my_option *options) { uint name_space= 34, length, nr; - ulonglong bit, llvalue; + ulonglong llvalue; char buff[255]; const struct my_option *optp; + DBUG_ENTER("my_print_variables"); + + for (optp= options; optp->name; optp++) + { + length= strlen(optp->name)+1; + if (length > name_space) + name_space= length; + } printf("\nVariables (--variable-name=value)\n"); - printf("and boolean options {FALSE|TRUE} Value (after reading options)\n"); - printf("--------------------------------- -----------------------------\n"); - for (optp= options; optp->id; optp++) + printf("%-*s%s", name_space, "and boolean options {FALSE|TRUE}", + "Value (after reading options)\n"); + for (length=1; length < 75; length++) + putchar(length == name_space ? ' ' : '-'); + putchar('\n'); + + for (optp= options; optp->name; optp++) { void *value= (optp->var_type & GET_ASK_ADDR ? (*getopt_get_addr)("", 0, optp, 0) : optp->value); if (value) { - printf("%s ", optp->name); - length= (uint) strlen(optp->name)+1; + length= print_name(optp); for (; length < name_space; length++) putchar(' '); switch ((optp->var_type & GET_TYPE_MASK)) { case GET_SET: if (!(llvalue= *(ulonglong*) value)) - printf("%s\n", "(No default value)"); + printf("%s\n", ""); else - for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1) + for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1) { - if (!(bit & llvalue)) - continue; - llvalue&= ~bit; - printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr)); + if (llvalue & 1) + printf( llvalue > 1 ? "%s," : "%s\n", get_type(optp->typelib, nr)); + } + break; + case GET_FLAGSET: + llvalue= *(ulonglong*) value; + for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1) + { + printf("%s%s=", (nr ? "," : ""), get_type(optp->typelib, nr)); + printf(llvalue & 1 ? "on" : "off"); } + printf("\n"); break; case GET_ENUM: printf("%s\n", get_type(optp->typelib, *(ulong*) value)); @@ -1279,12 +1439,14 @@ void my_print_variables(const struct my_option *options) case GET_DOUBLE: printf("%g\n", *(double*) value); break; + case GET_NO_ARG: + printf("(No default value)\n"); + break; default: printf("(Disabled)\n"); break; } } } + DBUG_VOID_RETURN; } - -#include <help_end.h> diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index cb063e27c1f..bc21b07e24d 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -18,9 +18,7 @@ #include "mysys_priv.h" #include "my_static.h" -#ifdef __NETWARE__ -#include <nks/time.h> -#elif defined(__WIN__) +#ifdef __WIN__ #define OFFSET_TO_EPOC 116444736000000000LL static ulonglong query_performance_frequency; #endif @@ -65,10 +63,6 @@ ulonglong my_interval_timer() GetSystemTimeAsFileTime((FILETIME*)&newtime); return newtime*100ULL; } -#elif defined(__NETWARE__) - NXTime_t tm; - NXGetTime(NX_SINCE_1970, NX_NSECONDS, &tm); - return (ulonglong)tm; #else /* TODO: check for other possibilities for hi-res timestamping */ struct timeval tv; diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index a18c296a7e1..ace14c8a3c9 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -54,7 +54,7 @@ int my_getwd(char * buf, size_t size, myf MyFlags) DBUG_RETURN(-1); if (curr_dir[0]) /* Current pos is saved here */ - VOID(strmake(buf,&curr_dir[0],size-1)); + (void) strmake(buf,&curr_dir[0],size-1); else { #if defined(HAVE_GETCWD) @@ -72,16 +72,6 @@ int my_getwd(char * buf, size_t size, myf MyFlags) getwd(pathname); strmake(buf,pathname,size-1); } -#elif defined(VMS) - if (size < 2) - DBUG_RETURN(-1); - if (!getcwd(buf,size-2,1) && MyFlags & MY_WME) - { - my_errno=errno; - my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); - DBUG_RETURN(-1); - } - intern_filename(buf,buf); #else #error "No way to get current directory" #endif @@ -103,27 +93,12 @@ int my_setwd(const char *dir, myf MyFlags) int res; size_t length; char *start, *pos; -#if defined(VMS) - char buff[FN_REFLEN]; -#endif DBUG_ENTER("my_setwd"); DBUG_PRINT("my",("dir: '%s' MyFlags %d", dir, MyFlags)); start=(char *) dir; if (! dir[0] || (dir[0] == FN_LIBCHAR && dir[1] == 0)) dir=FN_ROOTDIR; -#ifdef VMS - { - pos=strmov(buff,dir); - if (pos[-1] != FN_LIBCHAR) - { - pos[0]=FN_LIBCHAR; /* Mark as directory */ - pos[1]=0; - } - system_filename(buff,buff); /* Change to VMS format */ - dir=buff; - } -#endif /* VMS */ if ((res=chdir((char*) dir)) != 0) { my_errno=errno; diff --git a/mysys/my_handler_errors.h b/mysys/my_handler_errors.h index 6213ab188cc..8f2a8b750bd 100644 --- a/mysys/my_handler_errors.h +++ b/mysys/my_handler_errors.h @@ -1,3 +1,6 @@ +#ifndef MYSYS_MY_HANDLER_ERRORS_INCLUDED +#define MYSYS_MY_HANDLER_ERRORS_INCLUDED + /* Errors a handler can give you */ @@ -47,8 +50,7 @@ static const char *handler_error_messages[]= "There's no partition in table for the given value", "Row-based binary logging of row failed", "Index needed in foreign key constraint", - "Upholding foreign key constraints would lead to a duplicate key error in " - "some other table", + "Upholding foreign key constraints would lead to a duplicate key error in some other table", "Table needs to be upgraded before it can be used", "Table is read only", "Failed to get next auto increment value", @@ -63,7 +65,13 @@ static const char *handler_error_messages[]= "File too short; Expected more data in file", "Read page with wrong checksum", "Too many active concurrent transactions", + "Index column length exceeds limit", "Row is not visible by the current transaction", "Operation was interrupted by end user (probably kill command?)", "Disk full" }; + +extern void my_handler_error_register(void); +extern void my_handler_error_unregister(void); + +#endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */ diff --git a/mysys/my_init.c b/mysys/my_init.c index 863b636d9d3..580e29c381a 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (c) 2000, 2011 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 @@ -19,14 +19,12 @@ #include <m_string.h> #include <m_ctype.h> #include <signal.h> -#ifdef VMS -#include <my_static.c> -#include <m_ctype.h> -#endif #ifdef __WIN__ #ifdef _MSC_VER #include <locale.h> #include <crtdbg.h> +/* WSAStartup needs winsock library*/
+#pragma comment(lib, "ws2_32") #endif my_bool have_tcpip=0; static void my_win_init(void); @@ -34,11 +32,9 @@ static my_bool win32_init_tcp_ip(); #else #define my_win_init() #endif -#ifdef __NETWARE__ -static void netware_init(); -#else -#define netware_init() -#endif + +#define SCALE_SEC 100 +#define SCALE_USEC 10000 my_bool my_init_done= 0; uint mysys_usage_id= 0; /* Incremented for each my_init() */ @@ -56,69 +52,67 @@ static ulong atoi_octal(const char *str) return (ulong) tmp; } +MYSQL_FILE *mysql_stdin= NULL; +static MYSQL_FILE instrumented_stdin; -/* - Init my_sys functions and my_sys variabels - SYNOPSIS - my_init() +/** + Initialize my_sys functions, resources and variables - RETURN - 0 ok - 1 Couldn't initialize environment + @return Initialization result + @retval 0 Success + @retval 1 Error. Couldn't initialize environment */ - my_bool my_init(void) { - char * str; + char *str; + if (my_init_done) return 0; - my_init_done=1; + + my_init_done= 1; + mysys_usage_id++; my_umask= 0660; /* Default umask for new files */ my_umask_dir= 0700; /* Default umask for new directories */ + + /* Default creation of new files */ + if ((str= getenv("UMASK")) != 0) + my_umask= (int) (atoi_octal(str) | 0600); + /* Default creation of new dir's */ + if ((str= getenv("UMASK_DIR")) != 0) + my_umask_dir= (int) (atoi_octal(str) | 0700); + init_glob_errs(); + + instrumented_stdin.m_file= stdin; + instrumented_stdin.m_psi= NULL; /* not yet instrumented */ + mysql_stdin= & instrumented_stdin; + my_progname_short= "unknown"; if (my_progname) my_progname_short= my_progname + dirname_length(my_progname); - /* first initialize systems and global libraries */ - netware_init(); -#ifdef THREAD -#if defined(HAVE_PTHREAD_INIT) - pthread_init(); /* Must be called before DBUG_ENTER */ -#endif /* Initalize our mutex handling */ my_mutex_init(); - /* Initialize mysys global variables and global mutex */ + if (my_thread_global_init()) return 1; -#if !defined( __WIN__) && !defined(__NETWARE__) - sigfillset(&my_signals); /* signals blocked by mf_brkhant */ + +#if defined(HAVE_PTHREAD_INIT) + pthread_init(); /* Must be called before DBUG_ENTER */ #endif -#endif /* THREAD */ + + /* $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); + { DBUG_ENTER("my_init"); DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown")); - if (!home_dir) - { /* Don't initialize twice */ - my_time_init(); - my_win_init(); - if ((home_dir=getenv("HOME")) != 0) - home_dir=intern_filename(home_dir_buff,home_dir); -#ifndef VMS - /* Default creation of new files */ - if ((str=getenv("UMASK")) != 0) - my_umask=(int) (atoi_octal(str) | 0600); - /* Default creation of new dir's */ - if ((str=getenv("UMASK_DIR")) != 0) - my_umask_dir=(int) (atoi_octal(str) | 0700); -#endif -#ifdef VMS - init_ctype(); /* Stupid linker don't link _ctype.c */ -#endif - DBUG_PRINT("exit",("home: '%s'",home_dir)); - } + my_time_init(); + my_win_init(); + DBUG_PRINT("exit", ("home: '%s'", home_dir)); #ifdef __WIN__ win32_init_tcp_ip(); #endif @@ -162,7 +156,7 @@ void my_end(int infoflag) char ebuff[512]; my_snprintf(ebuff, sizeof(ebuff), EE(EE_OPEN_WARNING), my_file_opened, my_stream_opened); - my_message_no_curses(EE_OPEN_WARNING, ebuff, ME_BELL); + my_message_stderr(EE_OPEN_WARNING, ebuff, ME_BELL); DBUG_PRINT("error", ("%s", ebuff)); my_print_open_files(); } @@ -170,9 +164,6 @@ void my_end(int infoflag) free_charsets(); my_error_unregister_all(); my_once_free(); -#ifdef THREAD - my_thread_destroy_mutex(); -#endif if ((infoflag & MY_GIVE_INFO) || print_info) { @@ -199,16 +190,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #endif -#if defined(__NETWARE__) && !defined(__WIN__) - fprintf(info_file,"\nRun time: %.1f\n",(double) clock()/CLOCKS_PER_SEC); -#endif -#if defined(SAFEMALLOC) - /* Wait for other threads to free mysys_var */ -#ifdef THREAD - (void) my_wait_for_other_threads_to_die(1); -#endif - TERMINATE(stderr, (infoflag & MY_GIVE_INFO) != 0); -#elif defined(__WIN__) && defined(_MSC_VER) +#if defined(__WIN__) && defined(_MSC_VER) _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); @@ -219,16 +201,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", _CrtDumpMemoryLeaks(); #endif } - else if (infoflag & MY_CHECK_ERROR) - { - TERMINATE(stderr, 0); /* Print memory leaks on screen */ - } - if (!(infoflag & MY_DONT_FREE_DBUG)) - { - DBUG_END(); /* Must be done before my_thread_end */ - } -#ifdef THREAD my_thread_end(); my_thread_global_end(); my_mutex_end(); @@ -240,12 +213,15 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", safe_mutex_end((infoflag & (MY_GIVE_INFO | MY_CHECK_ERROR)) ? stderr : (FILE *) 0); #endif /* defined(SAFE_MUTEX) */ -#endif /* THREAD */ #ifdef __WIN__ if (have_tcpip) WSACleanup(); #endif /* __WIN__ */ + + if (!(infoflag & MY_DONT_FREE_DBUG)) + DBUG_END(); /* Must be done as late as possible */ + my_init_done=0; } /* my_end */ @@ -259,6 +235,7 @@ void my_debug_put_break_here(void) #ifdef __WIN__ + /* my_parameter_handler @@ -300,11 +277,66 @@ int handle_rtc_failure(int err_type, const char *file, int line, va_end(args); (void) fflush(stderr); __debugbreak(); + return 0; /* Error is handled */ } #pragma runtime_checks("", restore) #endif +/* + Open HKEY_LOCAL_MACHINE\SOFTWARE\MySQL and set any strings found + there as environment variables +*/ +static void win_init_registry(void) +{ + HKEY key_handle; + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)"SOFTWARE\\MySQL", + 0, KEY_READ, &key_handle) == ERROR_SUCCESS) + { + LONG ret; + DWORD index= 0; + DWORD type; + char key_name[256], key_data[1024]; + DWORD key_name_len= sizeof(key_name) - 1; + DWORD key_data_len= sizeof(key_data) - 1; + + while ((ret= RegEnumValue(key_handle, index++, + key_name, &key_name_len, + NULL, &type, (LPBYTE)&key_data, + &key_data_len)) != ERROR_NO_MORE_ITEMS) + { + char env_string[sizeof(key_name) + sizeof(key_data) + 2]; + + if (ret == ERROR_MORE_DATA) + { + /* Registry value larger than 'key_data', skip it */ + DBUG_PRINT("error", ("Skipped registry value that was too large")); + } + else if (ret == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + strxmov(env_string, key_name, "=", key_data, NullS); + + /* variable for putenv must be allocated ! */ + putenv(strdup(env_string)) ; + } + } + else + { + /* Unhandled error, break out of loop */ + break; + } + + key_name_len= sizeof(key_name) - 1; + key_data_len= sizeof(key_data) - 1; + } + + RegCloseKey(key_handle); + } +} + static void my_win_init(void) { @@ -312,17 +344,18 @@ static void my_win_init(void) #if defined(_MSC_VER) #if _MSC_VER < 1300 - /* + /* Clear the OS system variable TZ and avoid the 100% CPU usage Only for old versions of Visual C++ */ - _putenv( "TZ=" ); -#endif + _putenv("TZ="); +#endif #if _MSC_VER >= 1400 /* this is required to make crt functions return -1 appropriately */ _set_invalid_parameter_handler(my_parameter_handler); #endif -#endif +#endif + #ifdef __MSVC_RUNTIME_CHECKS /* Install handler to send RTC (Runtime Error Check) warnings @@ -333,58 +366,9 @@ static void my_win_init(void) _tzset(); - { - /* - Open HKEY_LOCAL_MACHINE\SOFTWARE\MySQL and set any strings found - there as environment variables - */ - HKEY key_handle; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)"SOFTWARE\\MySQL", - 0, KEY_READ, &key_handle) == ERROR_SUCCESS) - { - LONG ret; - DWORD index= 0; - DWORD type; - char key_name[256], key_data[1024]; - DWORD key_name_len= sizeof(key_name) - 1; - DWORD key_data_len= sizeof(key_data) - 1; - - while ((ret= RegEnumValue(key_handle, index++, - key_name, &key_name_len, - NULL, &type, (LPBYTE)&key_data, - &key_data_len)) != ERROR_NO_MORE_ITEMS) - { - char env_string[sizeof(key_name) + sizeof(key_data) + 2]; + win_init_registry(); - if (ret == ERROR_MORE_DATA) - { - /* Registry value larger than 'key_data', skip it */ - DBUG_PRINT("error", ("Skipped registry value that was too large")); - } - else if (ret == ERROR_SUCCESS) - { - if (type == REG_SZ) - { - strxmov(env_string, key_name, "=", key_data, NullS); - - /* variable for putenv must be allocated ! */ - putenv(strdup(env_string)) ; - } - } - else - { - /* Unhandled error, break out of loop */ - break; - } - - key_name_len= sizeof(key_name) - 1; - key_data_len= sizeof(key_data) - 1; - } - - RegCloseKey(key_handle) ; - } - } - DBUG_VOID_RETURN ; + DBUG_VOID_RETURN; } @@ -423,7 +407,7 @@ static my_bool win32_init_tcp_ip() { if (win32_have_tcpip()) { - WORD wVersionRequested = MAKEWORD( 2, 0 ); + WORD wVersionRequested = MAKEWORD( 2, 2 ); WSADATA wsaData; /* Be a good citizen: maybe another lib has already initialised sockets, so dont clobber them unless necessary */ @@ -452,56 +436,121 @@ static my_bool win32_init_tcp_ip() } #endif /* __WIN__ */ +#ifdef HAVE_PSI_INTERFACE -#ifdef __NETWARE__ -/* - Basic initialisation for netware -*/ +#if !defined(HAVE_PREAD) && !defined(_WIN32) +PSI_mutex_key key_my_file_info_mutex; +#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ + +#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) +PSI_mutex_key key_LOCK_localtime_r; +#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ -static void netware_init() +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_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, + key_THR_LOCK_isam, 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_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_uuid_generator; + +static PSI_mutex_info all_mysys_mutexes[]= +{ +#if !defined(HAVE_PREAD) && !defined(_WIN32) + { &key_my_file_info_mutex, "st_my_file_info:mutex", 0}, +#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ +#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) + { &key_LOCK_localtime_r, "LOCK_localtime_r", PSI_FLAG_GLOBAL}, +#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ + { &key_BITMAP_mutex, "BITMAP::mutex", 0}, + { &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_my_thread_var_mutex, "my_thread_var::mutex", 0}, + { &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_heap, "THR_LOCK_heap", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_isam, "THR_LOCK_isam", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_lock, "THR_LOCK_lock", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_malloc, "THR_LOCK_malloc", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_mutex, "THR_LOCK::mutex", 0}, + { &key_THR_LOCK_myisam, "THR_LOCK_myisam", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_net, "THR_LOCK_net", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_open, "THR_LOCK_open", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_threads, "THR_LOCK_threads", PSI_FLAG_GLOBAL}, + { &key_TMPDIR_mutex, "TMPDIR_mutex", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_myisam_mmap, "THR_LOCK_myisam_mmap", PSI_FLAG_GLOBAL}, + { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL } +}; + +PSI_cond_key key_COND_alarm, 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[]= { - char cwd[PATH_MAX], *name; + { &key_COND_alarm, "COND_alarm", 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}, + { &key_my_thread_var_suspend, "my_thread_var::suspend", 0}, + { &key_THR_COND_threads, "THR_COND_threads", PSI_FLAG_GLOBAL}, + { &key_WT_RESOURCE_cond, "WT_RESOURCE::cond", 0} +}; - DBUG_ENTER("netware_init"); +PSI_rwlock_key key_SAFEHASH_mutex; - /* init only if we are not a client library */ - if (my_progname) - { -#if SUPPORTED_BY_LIBC /* Removed until supported in Libc */ - struct termios tp; - /* Disable control characters */ - tcgetattr(STDIN_FILENO, &tp); - tp.c_cc[VINTR] = _POSIX_VDISABLE; - tp.c_cc[VEOF] = _POSIX_VDISABLE; - tp.c_cc[VSUSP] = _POSIX_VDISABLE; - tcsetattr(STDIN_FILENO, TCSANOW, &tp); -#endif /* SUPPORTED_BY_LIBC */ - - /* With stdout redirection */ - if (!isatty(STDOUT_FILENO)) - { - setscreenmode(SCR_AUTOCLOSE_ON_EXIT); /* auto close the screen */ - } - else - { - setscreenmode(SCR_NO_MODE); /* keep the screen up */ - } +static PSI_rwlock_info all_mysys_rwlocks[]= +{ + { &key_SAFEHASH_mutex, "SAFE_HASH::mutex", 0} +}; - /* Parse program name and change to base format */ - name= (char*) my_progname; - for (; *name; name++) - { - if (*name == '\\') - { - *name = '/'; - } - else - { - *name = tolower(*name); - } - } - } +#ifdef USE_ALARM_THREAD +PSI_thread_key key_thread_alarm; - DBUG_VOID_RETURN; +static PSI_thread_info all_mysys_threads[]= +{ + { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL} +}; +#endif /* USE_ALARM_THREAD */ + +#ifdef HUGETLB_USE_PROC_MEMINFO +PSI_file_key key_file_proc_meminfo; +#endif /* HUGETLB_USE_PROC_MEMINFO */ +PSI_file_key key_file_charset, key_file_cnf; + +static PSI_file_info all_mysys_files[]= +{ +#ifdef HUGETLB_USE_PROC_MEMINFO + { &key_file_proc_meminfo, "proc_meminfo", 0}, +#endif /* HUGETLB_USE_PROC_MEMINFO */ + { &key_file_charset, "charset", 0}, + { &key_file_cnf, "cnf", 0} +}; + +void my_init_mysys_psi_keys() +{ + const char* category= "mysys"; + int count; + + if (PSI_server == NULL) + return; + + count= sizeof(all_mysys_mutexes)/sizeof(all_mysys_mutexes[0]); + PSI_server->register_mutex(category, all_mysys_mutexes, count); + + count= sizeof(all_mysys_conds)/sizeof(all_mysys_conds[0]); + PSI_server->register_cond(category, all_mysys_conds, count); + + count= sizeof(all_mysys_rwlocks)/sizeof(all_mysys_rwlocks[0]); + PSI_server->register_rwlock(category, all_mysys_rwlocks, count); + +#ifdef USE_ALARM_THREAD + count= sizeof(all_mysys_threads)/sizeof(all_mysys_threads[0]); + PSI_server->register_thread(category, all_mysys_threads, count); +#endif /* USE_ALARM_THREAD */ + + count= sizeof(all_mysys_files)/sizeof(all_mysys_files[0]); + PSI_server->register_file(category, all_mysys_files, count); } -#endif /* __NETWARE__ */ +#endif /* HAVE_PSI_INTERFACE */ + diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index b50a606c8d8..9f5ab01a2b7 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -27,7 +27,7 @@ static uint my_get_large_page_size_int(void); static uchar* my_large_malloc_int(size_t size, myf my_flags); -static my_bool my_large_free_int(uchar* ptr, myf my_flags); +static my_bool my_large_free_int(uchar* ptr); /* Gets the size of large pages from the OS */ @@ -70,7 +70,7 @@ uchar* my_large_malloc(size_t size, myf my_flags) to my_free_lock() in case of failure */ -void my_large_free(uchar* ptr, myf my_flags __attribute__((unused))) +void my_large_free(uchar* ptr) { DBUG_ENTER("my_large_free"); @@ -79,9 +79,8 @@ void my_large_free(uchar* ptr, myf my_flags __attribute__((unused))) my_large_malloc_int(), i.e. my_malloc_lock() was used so we should free it with my_free_lock() */ - if (!my_use_large_pages || !my_large_page_size || - !my_large_free_int(ptr, my_flags)) - my_free_lock(ptr, my_flags); + if (!my_use_large_pages || !my_large_page_size || !my_large_free_int(ptr)) + my_free_lock(ptr); DBUG_VOID_RETURN; } @@ -91,19 +90,20 @@ void my_large_free(uchar* ptr, myf my_flags __attribute__((unused))) uint my_get_large_page_size_int(void) { - FILE *f; + MYSQL_FILE *f; uint size = 0; char buf[256]; DBUG_ENTER("my_get_large_page_size_int"); - if (!(f = my_fopen("/proc/meminfo", O_RDONLY, MYF(MY_WME)))) + if (!(f= mysql_file_fopen(key_file_proc_meminfo, "/proc/meminfo", + O_RDONLY, MYF(MY_WME)))) goto finish; - while (fgets(buf, sizeof(buf), f)) + while (mysql_file_fgets(buf, sizeof(buf), f)) if (sscanf(buf, "Hugepagesize: %u kB", &size)) break; - my_fclose(f, MYF(MY_WME)); + mysql_file_fclose(f, MYF(MY_WME)); finish: DBUG_RETURN(size * 1024); @@ -128,7 +128,7 @@ uchar* my_large_malloc_int(size_t size, myf my_flags) { if (my_flags & MY_WME) fprintf(stderr, - "Warning: Failed to allocate %lu bytesx from HugeTLB memory." + "Warning: Failed to allocate %lu bytes from HugeTLB memory." " errno %d\n", (ulong) size, errno); DBUG_RETURN(NULL); @@ -156,7 +156,7 @@ uchar* my_large_malloc_int(size_t size, myf my_flags) /* Linux-specific large pages deallocator */ -my_bool my_large_free_int(uchar *ptr, myf my_flags __attribute__((unused))) +my_bool my_large_free_int(uchar *ptr) { DBUG_ENTER("my_large_free_int"); DBUG_RETURN(shmdt(ptr) == 0); diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 033f8789b49..06f9521a664 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -14,7 +14,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* TODO: check for overun of memory for names. */ -/* Convert MSDOS-TIME to standar time_t (still needed?) */ #include "mysys_priv.h" #include <m_string.h> @@ -41,13 +40,8 @@ # endif # endif #endif -#ifdef VMS -#include <rms.h> -#include <iodef.h> -#include <descrip.h> -#endif -#if defined(THREAD) && defined(HAVE_READDIR_R) +#if defined(HAVE_READDIR_R) #define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C) #else #define READDIR(A,B,C) (!(C=readdir(A))) @@ -77,7 +71,7 @@ void my_dirend(MY_DIR *buffer) ALIGN_SIZE(sizeof(MY_DIR)))); free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0)); - my_free((uchar*) buffer,MYF(0)); + my_free(buffer); } DBUG_VOID_RETURN; } /* my_dirend */ @@ -103,14 +97,13 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DIR *dirp; struct dirent *dp; char tmp_path[FN_REFLEN+1],*tmp_file; -#ifdef THREAD char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1]; -#endif + DBUG_ENTER("my_dir"); DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags)); -#if defined(THREAD) && !defined(HAVE_READDIR_R) - pthread_mutex_lock(&THR_LOCK_open); +#if !defined(HAVE_READDIR_R) + mysql_mutex_lock(&THR_LOCK_open); #endif dirp = opendir(directory_file_name(tmp_path,(char *) path)); @@ -131,7 +124,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), ENTRIES_START_SIZE, ENTRIES_INCREMENT)) { - my_free((uchar*) buffer,MYF(0)); + my_free(buffer); goto error; } init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); @@ -141,11 +134,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) tmp_file=strend(tmp_path); -#ifdef THREAD dp= (struct dirent*) dirent_tmp; -#else - dp=0; -#endif while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp))) { @@ -159,8 +148,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags) goto error; bzero(finfo.mystat, sizeof(MY_STAT)); - VOID(strmov(tmp_file,dp->d_name)); - VOID(my_stat(tmp_path, finfo.mystat, MyFlags)); + (void) strmov(tmp_file,dp->d_name); + (void) my_stat(tmp_path, finfo.mystat, MyFlags); if (!(finfo.mystat->st_mode & MY_S_IREAD)) continue; } @@ -172,8 +161,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags) } (void) closedir(dirp); -#if defined(THREAD) && !defined(HAVE_READDIR_R) - pthread_mutex_unlock(&THR_LOCK_open); +#if !defined(HAVE_READDIR_R) + mysql_mutex_unlock(&THR_LOCK_open); #endif result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; result->number_off_files= dir_entries_storage->elements; @@ -184,8 +173,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_RETURN(result); error: -#if defined(THREAD) && !defined(HAVE_READDIR_R) - pthread_mutex_unlock(&THR_LOCK_open); +#if !defined(HAVE_READDIR_R) + mysql_mutex_unlock(&THR_LOCK_open); #endif my_errno=errno; if (dirp) @@ -199,9 +188,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) /* * Convert from directory name to filename. - * On VMS: - * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1 - * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1 * On UNIX, it's simple: just make sure there is a terminating / * Returns pointer to dst; @@ -209,11 +195,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags) char * directory_file_name (char * dst, const char *src) { -#ifndef VMS - /* Process as Unix format: just remove test the final slash. */ - - char * end; + char *end; if (src[0] == 0) src= (char*) "."; /* Use empty as current */ @@ -224,125 +207,7 @@ char * directory_file_name (char * dst, const char *src) end[1]='\0'; } return dst; - -#else /* VMS */ - - long slen; - long rlen; - char * ptr, rptr; - char bracket; - struct FAB fab = cc$rms_fab; - struct NAM nam = cc$rms_nam; - char esa[NAM$C_MAXRSS]; - - if (! src[0]) - src="[.]"; /* Empty is == current dir */ - - slen = strlen (src) - 1; - if (src[slen] == FN_C_AFTER_DIR || src[slen] == FN_C_AFTER_DIR_2 || - src[slen] == FN_DEVCHAR) - { - /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */ - fab.fab$l_fna = src; - fab.fab$b_fns = slen + 1; - fab.fab$l_nam = &nam; - fab.fab$l_fop = FAB$M_NAM; - - nam.nam$l_esa = esa; - nam.nam$b_ess = sizeof esa; - nam.nam$b_nop |= NAM$M_SYNCHK; - - /* We call SYS$PARSE to handle such things as [--] for us. */ - if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL) - { - slen = nam.nam$b_esl - 1; - if (esa[slen] == ';' && esa[slen - 1] == '.') - slen -= 2; - esa[slen + 1] = '\0'; - src = esa; - } - if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2) - { - /* what about when we have logical_name:???? */ - if (src[slen] == FN_DEVCHAR) - { /* Xlate logical name and see what we get */ - VOID(strmov(dst,src)); - dst[slen] = 0; /* remove colon */ - if (!(src = getenv (dst))) - return dst; /* Can't translate */ - - /* should we jump to the beginning of this procedure? - Good points: allows us to use logical names that xlate - to Unix names, - Bad points: can be a problem if we just translated to a device - name... - For now, I'll punt and always expect VMS names, and hope for - the best! */ - - slen = strlen (src) - 1; - if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2) - { /* no recursion here! */ - VOID(strmov(dst, src)); - return(dst); - } - } - else - { /* not a directory spec */ - VOID(strmov(dst, src)); - return(dst); - } - } - - bracket = src[slen]; /* End char */ - if (!(ptr = strchr (src, bracket - 2))) - { /* no opening bracket */ - VOID(strmov (dst, src)); - return dst; - } - if (!(rptr = strrchr (src, '.'))) - rptr = ptr; - slen = rptr - src; - VOID(strmake (dst, src, slen)); - - if (*rptr == '.') - { /* Put bracket and add */ - dst[slen++] = bracket; /* (rptr+1) after this */ - } - else - { - /* If we have the top-level of a rooted directory (i.e. xx:[000000]), - then translate the device and recurse. */ - - if (dst[slen - 1] == ':' - && dst[slen - 2] != ':' /* skip decnet nodes */ - && strcmp(src + slen, "[000000]") == 0) - { - dst[slen - 1] = '\0'; - if ((ptr = getenv (dst)) - && (rlen = strlen (ptr) - 1) > 0 - && (ptr[rlen] == FN_C_AFTER_DIR || ptr[rlen] == FN_C_AFTER_DIR_2) - && ptr[rlen - 1] == '.') - { - VOID(strmov(esa,ptr)); - esa[rlen - 1] = FN_C_AFTER_DIR; - esa[rlen] = '\0'; - return (directory_file_name (dst, esa)); - } - else - dst[slen - 1] = ':'; - } - VOID(strmov(dst+slen,"[000000]")); - slen += 8; - } - VOID(strmov(strmov(dst+slen,rptr+1)-1,".DIR.1")); - return dst; - } - VOID(strmov(dst, src)); - if (dst[slen] == '/' && slen > 1) - dst[slen] = 0; - return dst; -#endif /* VMS */ -} /* directory_file_name */ +} #else @@ -400,7 +265,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), ENTRIES_START_SIZE, ENTRIES_INCREMENT)) { - my_free((uchar*) buffer,MYF(0)); + my_free(buffer); goto error; } init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); @@ -547,7 +412,7 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) DBUG_PRINT("error",("Got errno: %d from stat", errno)); my_errno= errno; if (m_used) /* Free if new area */ - my_free((uchar*) stat_area,MYF(0)); + my_free(stat_area); error: if (my_flags & (MY_FAE+MY_WME)) diff --git a/mysys/my_lock.c b/mysys/my_lock.c index 6bbb177e4b6..96abded4cc3 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -22,9 +22,6 @@ #undef NO_ALARM_LOOP #endif #include <my_alarm.h> -#ifdef __NETWARE__ -#include <nks/fsio.h> -#endif #ifdef _WIN32 #define WIN_LOCK_INFINITE -1 @@ -145,59 +142,14 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, int value; ALARM_VARIABLES; #endif -#ifdef __NETWARE__ - int nxErrno; -#endif + DBUG_ENTER("my_lock"); DBUG_PRINT("my",("fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", fd,locktype,(long) start,(long) length,MyFlags)); -#ifdef VMS - DBUG_RETURN(0); -#else if (my_disable_locking && ! (MyFlags & MY_FORCE_LOCK)) DBUG_RETURN(0); -#if defined(__NETWARE__) - { - NXSOffset_t nxLength = length; - unsigned long nxLockFlags = 0; - - if (length == F_TO_EOF) - { - /* EOF is interpreted as a very large length. */ - nxLength = 0x7FFFFFFFFFFFFFFF; - } - - if (locktype == F_UNLCK) - { - /* The lock flags are currently ignored by NKS. */ - if (!(nxErrno= NXFileRangeUnlock(fd, 0L, start, nxLength))) - DBUG_RETURN(0); - } - else - { - if (locktype == F_RDLCK) - { - /* A read lock is mapped to a shared lock. */ - nxLockFlags = NX_RANGE_LOCK_SHARED; - } - else - { - /* A write lock is mapped to an exclusive lock. */ - nxLockFlags = NX_RANGE_LOCK_EXCL; - } - - if (MyFlags & MY_NO_WAIT) - { - /* Don't block on the lock. */ - nxLockFlags |= NX_RANGE_LOCK_TRYLOCK; - } - - if (!(nxErrno= NXFileRangeLock(fd, nxLockFlags, start, nxLength))) - DBUG_RETURN(0); - } - } -#elif defined(_WIN32) +#if defined(_WIN32) { int timeout_sec; if (MyFlags & MY_NO_WAIT) @@ -205,8 +157,8 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, else timeout_sec= WIN_LOCK_INFINITE; - if(win_lock(fd, locktype, start, length, timeout_sec) == 0) - DBUG_RETURN(0); + if (win_lock(fd, locktype, start, length, timeout_sec) == 0) + DBUG_RETURN(0); } #else #if defined(HAVE_FCNTL) @@ -262,12 +214,9 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, #endif /* HAVE_FCNTL */ #endif /* HAVE_LOCKING */ -#ifdef __NETWARE__ - my_errno = nxErrno; -#else - /* We got an error. We don't want EACCES errors */ + /* We got an error. We don't want EACCES errors */ my_errno=(errno == EACCES) ? EAGAIN : errno ? errno : -1; -#endif + if (MyFlags & MY_WME) { if (locktype == F_UNLCK) @@ -277,5 +226,4 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, } DBUG_PRINT("error",("my_errno: %d (%d)",my_errno,errno)); DBUG_RETURN(-1); -#endif /* ! VMS */ } /* my_lock */ diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c index b96331cd3cf..a37db6b2089 100644 --- a/mysys/my_lockmem.c +++ b/mysys/my_lockmem.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -59,40 +59,39 @@ uchar *my_malloc_lock(uint size,myf MyFlags) /* Add block in a list for munlock */ if (!(element=(struct st_mem_list*) my_malloc(sizeof(*element),MyFlags))) { - VOID(munlock((uchar*) ptr,size)); + (void) munlock((uchar*) ptr,size); free(ptr); DBUG_RETURN(0); } element->list.data=(uchar*) element; element->page=ptr; element->size=size; - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); mem_list=list_add(mem_list,&element->list); - pthread_mutex_unlock(&THR_LOCK_malloc); + mysql_mutex_unlock(&THR_LOCK_malloc); } DBUG_RETURN(ptr); } -void my_free_lock(uchar *ptr,myf Myflags __attribute__((unused))) +void my_free_lock(uchar *ptr) { LIST *list; struct st_mem_list *element=0; - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); for (list=mem_list ; list ; list=list->next) { element=(struct st_mem_list*) list->data; if (ptr == element->page) { /* Found locked mem */ - VOID(munlock((uchar*) ptr,element->size)); + (void) munlock((uchar*) ptr,element->size); mem_list=list_delete(mem_list,list); break; } } - pthread_mutex_unlock(&THR_LOCK_malloc); - if (element) - my_free((uchar*) element,MYF(0)); + mysql_mutex_unlock(&THR_LOCK_malloc); + my_free(element); free(ptr); /* Free even if not locked */ } diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index 330ef07ed30..2555c052fc3 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 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 @@ -11,34 +11,34 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* my_global.h may define SAFEMALLOC (through my_config.h). */ -#include <my_global.h> - -#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */ -#undef SAFEMALLOC -#endif + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mysys_priv.h" #include "mysys_err.h" #include <m_string.h> - /* My memory allocator */ +/** + Allocate a sized block of memory. + + @param size The size of the memory block in bytes. + @param flags Failure action modifiers (bitmasks). + @return A pointer to the allocated memory block, or NULL on failure. +*/ void *my_malloc(size_t size, myf my_flags) { void* point; DBUG_ENTER("my_malloc"); DBUG_PRINT("my",("size: %lu my_flags: %d", (ulong) size, my_flags)); + /* Safety */ if (!size) - size=1; /* Safety */ + size=1; - point= (char *) malloc(size); + point= DBUG_MALLOC(size); DBUG_EXECUTE_IF("simulate_out_of_memory", { - free(point); + my_free(point); point= NULL; }); @@ -55,33 +55,71 @@ void *my_malloc(size_t size, myf my_flags) exit(1); } else if (my_flags & MY_ZEROFILL) - bzero(point,size); - DBUG_PRINT("exit",("ptr: 0x%lx", (long) point)); - DBUG_RETURN((void*) point); -} /* my_malloc */ + bzero(point, size); + DBUG_PRINT("exit",("ptr: %p", point)); + DBUG_RETURN(point); +} + +/** + @brief wrapper around realloc() - /* Free memory allocated with my_malloc */ - /*ARGSUSED*/ + @param oldpoint pointer to currently allocated area + @param size new size requested, must be >0 + @param my_flags flags -void my_no_flags_free(void* ptr) + @note if size==0 realloc() may return NULL; my_realloc() treats this as an + error which is not the intention of realloc() +*/ +void *my_realloc(void *oldpoint, size_t size, myf my_flags) +{ + void *point; + DBUG_ENTER("my_realloc"); + DBUG_PRINT("my",("ptr: %p size: %lu my_flags: %d", oldpoint, + (ulong) size, my_flags)); + + DBUG_ASSERT(size > 0); + if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR)) + DBUG_RETURN(my_malloc(size, my_flags)); + if ((point= DBUG_REALLOC(oldpoint, size)) == NULL) + { + if (my_flags & MY_FREE_ON_ERROR) + my_free(oldpoint); + if (my_flags & MY_HOLD_ON_ERROR) + DBUG_RETURN(oldpoint); + my_errno=errno; + if (my_flags & (MY_FAE+MY_WME)) + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size); + } + DBUG_PRINT("exit",("ptr: %p", point)); + DBUG_RETURN(point); +} + + +/** + 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) { DBUG_ENTER("my_free"); - DBUG_PRINT("my",("ptr: 0x%lx", (long) ptr)); - if (ptr) - free(ptr); + DBUG_PRINT("my",("ptr: %p", ptr)); + DBUG_FREE(ptr); DBUG_VOID_RETURN; -} /* my_free */ - +} - /* malloc and copy */ -void* my_memdup(const void *from, size_t length, myf my_flags) +void *my_memdup(const void *from, size_t length, myf my_flags) { void *ptr; + DBUG_ENTER("my_memdup"); + if ((ptr= my_malloc(length,my_flags)) != 0) memcpy(ptr, from, length); - return(ptr); + DBUG_RETURN(ptr); } @@ -89,19 +127,24 @@ char *my_strdup(const char *from, myf my_flags) { char *ptr; size_t length= strlen(from)+1; + DBUG_ENTER("my_strdup"); + if ((ptr= (char*) my_malloc(length, my_flags))) - memcpy((uchar*) ptr, (uchar*) from,(size_t) length); - return(ptr); + memcpy(ptr, from, length); + DBUG_RETURN(ptr); } char *my_strndup(const char *from, size_t length, myf my_flags) { char *ptr; - if ((ptr= (char*) my_malloc(length+1,my_flags)) != 0) + DBUG_ENTER("my_strndup"); + + if ((ptr= (char*) my_malloc(length+1, my_flags))) { - memcpy((uchar*) ptr, (uchar*) from, length); - ptr[length]=0; + memcpy(ptr, from, length); + ptr[length]= 0; } - return((char*) ptr); + DBUG_RETURN(ptr); } + diff --git a/mysys/my_messnc.c b/mysys/my_mess.c index e2431959b7a..513afe39054 100644 --- a/mysys/my_messnc.c +++ b/mysys/my_mess.c @@ -15,18 +15,14 @@ #include "mysys_priv.h" -int my_message_no_curses(uint error __attribute__((unused)), - const char *str, myf MyFlags) +void my_message_stderr(uint error __attribute__((unused)), + const char *str, myf MyFlags) { - DBUG_ENTER("my_message_no_curses"); + DBUG_ENTER("my_message_stderr"); DBUG_PRINT("enter",("message: %s",str)); (void) fflush(stdout); if (MyFlags & ME_BELL) -#ifdef __NETWARE__ - ringbell(); /* Bell */ -#else - (void) fputc('\007',stderr); /* Bell */ -#endif /* __NETWARE__ */ + (void) fputc('\007', stderr); if (my_progname) { (void)fputs(my_progname,stderr); (void)fputs(": ",stderr); @@ -34,5 +30,5 @@ int my_message_no_curses(uint error __attribute__((unused)), (void)fputs(str,stderr); (void)fputc('\n',stderr); (void)fflush(stderr); - DBUG_RETURN(0); + DBUG_VOID_RETURN; } diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 303d8efaf30..82ee1562bc2 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -38,13 +38,16 @@ void *my_mmap(void *addr, size_t len, int prot, HANDLE hFileMap; LPVOID ptr; HANDLE hFile= (HANDLE)my_get_osfhandle(fd); + DBUG_ENTER("my_mmap"); + DBUG_PRINT("mysys", ("map fd: %d", fd)); + if (hFile == INVALID_HANDLE_VALUE) - return MAP_FAILED; + DBUG_RETURN(MAP_FAILED); hFileMap=CreateFileMapping(hFile, &mmap_security_attributes, PAGE_READWRITE, 0, (DWORD) len, NULL); if (hFileMap == 0) - return MAP_FAILED; + DBUG_RETURN(MAP_FAILED); ptr=MapViewOfFile(hFileMap, prot & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ, @@ -59,14 +62,19 @@ void *my_mmap(void *addr, size_t len, int prot, CloseHandle(hFileMap); if (ptr) - return ptr; + { + DBUG_PRINT("mysys", ("mapped addr: %p", ptr)); + DBUG_RETURN(ptr); + } - return MAP_FAILED; + DBUG_RETURN(MAP_FAILED); } int my_munmap(void *addr, size_t len) { - return UnmapViewOfFile(addr) ? 0 : -1; + DBUG_ENTER("my_munmap"); + DBUG_PRINT("mysys", ("unmap addr: %p", addr)); + DBUG_RETURN(UnmapViewOfFile(addr) ? 0 : -1); } int my_msync(int fd, void *addr, size_t len, int flags) diff --git a/mysys/my_net.c b/mysys/my_net.c deleted file mode 100644 index 820abf32386..00000000000 --- a/mysys/my_net.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* thread safe version of some common functions */ - -#include "mysys_priv.h" -#include <m_string.h> - -/* for thread safe my_inet_ntoa */ -#if !defined(__WIN__) -#include <netdb.h> -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#endif /* !defined(__WIN__) */ -#include "my_net.h" - - -void my_inet_ntoa(struct in_addr in, char *buf) -{ - char *ptr; - pthread_mutex_lock(&THR_LOCK_net); - ptr=inet_ntoa(in); - strmov(buf,ptr); - pthread_mutex_unlock(&THR_LOCK_net); -} - -/* This code is not needed if my_gethostbyname_r is a macro */ -#if !defined(my_gethostbyname_r) - -/* - Emulate SOLARIS style calls, not because it's better, but just to make the - usage of getbostbyname_r simpler. -*/ - -#if defined(HAVE_GETHOSTBYNAME_R) - -#if defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) - -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) -{ - struct hostent *hp; - DBUG_ASSERT((size_t) buflen >= sizeof(*result)); - if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop)) - return 0; - return hp; -} - -#elif defined(HAVE_GETHOSTBYNAME_R_RETURN_INT) - -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) -{ - if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1) - { - *h_errnop= errno; - return 0; - } - return result; -} - -#else - -/* gethostbyname_r with similar interface as gethostbyname() */ - -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) -{ - struct hostent *hp; - DBUG_ASSERT(buflen >= sizeof(struct hostent_data)); - hp= gethostbyname_r(name,result,(struct hostent_data *) buffer); - *h_errnop= errno; - return hp; -} -#endif /* GLIBC2_STYLE_GETHOSTBYNAME_R */ - -#else /* !HAVE_GETHOSTBYNAME_R */ - -#ifdef THREAD -extern pthread_mutex_t LOCK_gethostbyname_r; -#endif - -/* - No gethostbyname_r() function exists. - In this case we have to keep a mutex over the call to ensure that no - other thread is going to reuse the internal memory. - - The user is responsible to call my_gethostbyname_r_free() when he - is finished with the structure. -*/ - -struct hostent * -my_gethostbyname_r(const char *name, - struct hostent *result __attribute__((unused)), - char *buffer __attribute__((unused)), - int buflen __attribute__((unused)), - int *h_errnop) -{ - struct hostent *hp; - pthread_mutex_lock(&LOCK_gethostbyname_r); - hp= gethostbyname(name); - *h_errnop= h_errno; - return hp; -} - -void my_gethostbyname_r_free() -{ - pthread_mutex_unlock(&LOCK_gethostbyname_r); -} - -#endif /* !HAVE_GETHOSTBYNAME_R */ -#endif /* !my_gethostbyname_r */ diff --git a/mysys/my_netware.c b/mysys/my_netware.c deleted file mode 100644 index 5b5c39c0ac0..00000000000 --- a/mysys/my_netware.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (C) 2003 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - Functions specific to netware -*/ - -#include <mysys_priv.h> -#ifdef __NETWARE__ - #include <string.h> - #include <library.h> - -/* - PMUserLicenseRequest is an API exported by the polimgr.nlm - (loaded by the NetWare OS when it comes up) for use by other - NLM-based NetWare products/services. - PMUserLicenseRequest provides a couple of functions: - 1) it will optionally request a User license or ensure that - one already exists for the specified User in userInfo - 2) it utilizes the NetWare usage metering service to - record usage information about your product/service. -*/ - -long PMMeteredUsageRequest -( - /* - NDS distinguished name or IP address or ??. asciiz string, e.g. - ".CN=Admin.O=this.T=MYTREE." - */ - char *userInfo, - long infoType, /* see defined values */ - /* - string used to identify the calling service, used to index the - metered info e.g. "iPrint" - */ - char *serviceID, - char tranAddrType, /* type of address that follows */ - char *tranAddr, /* ptr to a 10-byte array */ - long flags, /* see defined values */ - /* NLS error code, if any. NULL input is okay */ - long *licRequestErrCode, - /* meter service error code, if any. NULL input is okay */ - long *storeMeterInfoErrCode, - /* - error code from NLSMeter if - storeMeterInfoErrCode == PM_LICREQ_NLSMETERERROR. - NULL input is okay - */ - long *NLSMeterErrCode -); - -typedef long(*PMUR)(const char*, long, const char*, char, - const char*, long, long*, long*, long*); - -/* infoType */ -/* indicates that the info in the userInfo param is an NDS user */ -#define PM_USERINFO_TYPE_NDS 1 -/* indicates that the info in the userInfo param is NOT an NDS user */ -#define PM_USERINFO_TYPE_ADDRESS 2 - -/* Flags */ - -/* - Tells the service that it should not check to see if the NDS user - contained in the userInfo param has a NetWare User License - just - record metering information; this is ignored if infoType != - PM_USERINFO_TYPE_NDS -*/ - -#define PM_FLAGS_METER_ONLY 0x0000001 - -/* - Indicates that the values in the userInfo and serviceID parameters - are unicode strings, so that the metering service bypasses - converting these to unicode (again) -*/ -#define PM_LICREQ_ALREADY_UNICODE 0x0000002 -/* - Useful only if infoType is PM_USERINFO_TYPE_NDS - indicates a "no - stop" policy of the calling service -*/ -#define PM_LICREQ_ALWAYS_METER 0x0000004 - - -/* - net Address Types - system-defined types of net addresses that can - be used in the tranAddrType field -*/ - -#define NLS_TRAN_TYPE_IPX 0x00000001 /* An IPX address */ -#define NLS_TRAN_TYPE_IP 0x00000008 /* An IP address */ -#define NLS_ADDR_TYPE_MAC 0x000000F1 /* a MAC address */ - -/* - Net Address Sizes - lengths that correspond to the tranAddrType - field (just fyi) -*/ -#define NLS_IPX_ADDR_SIZE 10 /* the size of an IPX address */ -#define NLS_IP_ADDR_SIZE 4 /* the size of an IP address */ -#define NLS_MAC_ADDR_SIZE 6 /* the size of a MAC address */ - - -void netware_reg_user(const char *ip, const char *user, - const char *application) -{ - PMUR usage_request; - long licRequestErrCode = 0; - long storeMeterInfoErrCode = 0; - long nlsMeterErrCode = 0; - - /* import the symbol */ - usage_request= ((PMUR)ImportPublicObject(getnlmhandle(), - "PMMeteredUsageRequest")); - if (usage_request != NULL) - { - unsigned long iaddr; - char addr[NLS_IPX_ADDR_SIZE]; - - /* create address */ - iaddr = htonl(inet_addr(ip)); - bzero(addr, NLS_IPX_ADDR_SIZE); - memcpy(addr, &iaddr, NLS_IP_ADDR_SIZE); - - /* call to NLS */ - usage_request(user, - PM_USERINFO_TYPE_ADDRESS, - application, - NLS_TRAN_TYPE_IP, - addr, - PM_FLAGS_METER_ONLY, - &licRequestErrCode, - &storeMeterInfoErrCode, - &nlsMeterErrCode); - /* release symbol */ - UnImportPublicObject(getnlmhandle(), "PMMeteredUsageRequest"); - } -} -#endif /* __NETWARE__ */ diff --git a/mysys/my_once.c b/mysys/my_once.c index 73bdd0166e6..32d07802028 100644 --- a/mysys/my_once.c +++ b/mysys/my_once.c @@ -15,20 +15,14 @@ /* Not MT-SAFE */ -/* my_global.h may define SAFEMALLOC (through my_config.h). */ -#include <my_global.h> - -#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */ -#undef SAFEMALLOC -#endif - #include "mysys_priv.h" #include "my_static.h" #include "mysys_err.h" #include <m_string.h> /* - Alloc for things we don't nead to free + Alloc for things we don't nend to free run-time (that only + should be free'd on exit) SYNOPSIS my_once_alloc() @@ -103,7 +97,7 @@ void *my_once_memdup(const void *src, size_t len, myf myflags) /* - Deallocate everything used by my_once_alloc + Deallocate everything that was allocated with my_once_alloc SYNOPSIS my_once_free() diff --git a/mysys/my_open.c b/mysys/my_open.c index b1788506832..bac0be46766 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -49,8 +49,9 @@ File my_open(const char *FileName, int Flags, myf MyFlags) fd = open((char *) FileName, Flags); #endif - DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_OPEN, - EE_FILENOTFOUND, MyFlags)); + fd= my_register_filename(fd, FileName, FILE_BY_OPEN, + EE_FILENOTFOUND, MyFlags); + DBUG_RETURN(fd); } /* my_open */ @@ -70,7 +71,7 @@ int my_close(File fd, myf MyFlags) DBUG_ENTER("my_close"); DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); #ifndef _WIN32 do { @@ -88,11 +89,11 @@ int my_close(File fd, myf MyFlags) } if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN) { - my_free(my_file_info[fd].name, MYF(0)); + my_free(my_file_info[fd].name); my_file_info[fd].type = UNOPEN; } my_file_opened--; - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(err); } /* my_close */ @@ -127,17 +128,17 @@ File my_register_filename(File fd, const char *FileName, enum file_type } else { - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) { my_file_opened++; my_file_total_opened++; my_file_info[fd].type = type_of_file; - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_PRINT("exit",("fd: %d",fd)); DBUG_RETURN(fd); } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); my_errno= ENOMEM; } (void) my_close(fd, MyFlags); diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 6421a2da601..9d513a08418 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -49,13 +49,9 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, size_t readbytes; int error= 0; -#ifndef DBUG_OFF - char llbuf[22]; DBUG_ENTER("my_pread"); - DBUG_PRINT("my",("fd: %d Seek: %s Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, ullstr(offset, llbuf), (long) Buffer, - (ulong)Count, MyFlags)); -#endif + DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d", + Filedes, (ulonglong)offset, Buffer, (ulong)Count, MyFlags)); for (;;) { errno= 0; /* Linux, Windows don't reset this on EOF/success */ @@ -74,14 +70,12 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, my_errno= HA_ERR_FILE_TOO_SHORT; DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", (int) readbytes, (uint) Count,Filedes,my_errno)); -#ifdef THREAD if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR) { DBUG_PRINT("debug", ("my_pread() was interrupted and returned %d", (int) readbytes)); continue; /* Interrupted */ } -#endif if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { if (readbytes == (size_t) -1) @@ -127,13 +121,9 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, { size_t writtenbytes, written; uint errors; -#ifndef DBUG_OFF - char llbuf[22]; DBUG_ENTER("my_pwrite"); - DBUG_PRINT("my",("fd: %d Seek: %s Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, ullstr(offset, llbuf), (long) Buffer, - (ulong)Count, MyFlags)); -#endif + DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d", + Filedes, (ulonglong)offset, Buffer, (ulong)Count, MyFlags)); errors= 0; written= 0; @@ -156,10 +146,8 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, } DBUG_PRINT("error",("Write only %u bytes", (uint) writtenbytes)); #ifndef NO_BACKGROUND -#ifdef THREAD if (my_thread_var->abort) MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ -#endif if ((my_errno == ENOSPC || my_errno == EDQUOT) && (MyFlags & MY_WAIT_IF_FULL)) { diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index e97bbe89be0..f0b3b1e8aef 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -18,7 +18,6 @@ #define DONT_REMAP_PTHREAD_FUNCTIONS #include "mysys_priv.h" -#ifdef THREAD #include <signal.h> #include <m_string.h> #include <thr_alarm.h> @@ -31,46 +30,6 @@ uint thd_lib_detected= 0; -#ifndef my_pthread_setprio -void my_pthread_setprio(pthread_t thread_id,int prior) -{ -#ifdef HAVE_PTHREAD_SETSCHEDPARAM - struct sched_param tmp_sched_param; - bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param)); - tmp_sched_param.sched_priority=prior; - VOID(pthread_setschedparam(thread_id,SCHED_POLICY,&tmp_sched_param)); -#endif -} -#endif - -#ifndef my_pthread_getprio -int my_pthread_getprio(pthread_t thread_id) -{ -#ifdef HAVE_PTHREAD_SETSCHEDPARAM - struct sched_param tmp_sched_param; - int policy; - if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param)) - { - return tmp_sched_param.sched_priority; - } -#endif - return -1; -} -#endif - -#ifndef my_pthread_attr_setprio -void my_pthread_attr_setprio(pthread_attr_t *attr, int priority) -{ -#ifdef HAVE_PTHREAD_SETSCHEDPARAM - struct sched_param tmp_sched_param; - bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param)); - tmp_sched_param.sched_priority=priority; - VOID(pthread_attr_setschedparam(attr,&tmp_sched_param)); -#endif -} -#endif - - /* To allow use of pthread_getspecific with two arguments */ #ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC @@ -85,34 +44,6 @@ void *my_pthread_getspecific_imp(pthread_key_t key) } #endif -#ifdef __NETWARE__ -/* - Don't kill the LibC Reaper thread or the main thread -*/ -#include <nks/thread.h> -#undef pthread_exit -void my_pthread_exit(void *status) -{ - NXThreadId_t tid; - NXContext_t ctx; - char name[NX_MAX_OBJECT_NAME_LEN+1] = ""; - - tid= NXThreadGetId(); - if (tid == NX_INVALID_THREAD_ID || !tid) - return; - if (NXThreadGetContext(tid, &ctx) || - NXContextGetName(ctx, name, sizeof(name)-1)) - return; - - /* - "MYSQLD.NLM's LibC Reaper" or "MYSQLD.NLM's main thread" - with a debug build of LibC the reaper can have different names - */ - if (!strindex(name, "\'s")) - pthread_exit(status); -} -#endif - /* Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7 (and DEC OSF/1 3.2 too) @@ -136,7 +67,7 @@ int my_sigwait(const sigset_t *set,int *sig) #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) -extern pthread_mutex_t LOCK_localtime_r; +extern mysql_mutex_t LOCK_localtime_r; #endif @@ -144,10 +75,10 @@ extern pthread_mutex_t LOCK_localtime_r; struct tm *localtime_r(const time_t *clock, struct tm *res) { struct tm *tmp; - pthread_mutex_lock(&LOCK_localtime_r); + mysql_mutex_lock(&LOCK_localtime_r); tmp=localtime(clock); *res= *tmp; - pthread_mutex_unlock(&LOCK_localtime_r); + mysql_mutex_unlock(&LOCK_localtime_r); return res; } #endif @@ -161,10 +92,10 @@ struct tm *localtime_r(const time_t *clock, struct tm *res) struct tm *gmtime_r(const time_t *clock, struct tm *res) { struct tm *tmp; - pthread_mutex_lock(&LOCK_localtime_r); + mysql_mutex_lock(&LOCK_localtime_r); tmp= gmtime(clock); *res= *tmp; - pthread_mutex_unlock(&LOCK_localtime_r); + mysql_mutex_unlock(&LOCK_localtime_r); return res; } #endif @@ -206,7 +137,7 @@ void sigwait_setup(sigset_t *set) sact.sa_flags = 0; sact.sa_handler = px_handle_sig; - memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */ + memcpy(&sact.sa_mask, set, sizeof(*set)); /* handler isn't thread_safe */ sigemptyset(&unblock_mask); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) 0,&rev_sigwait_set); @@ -232,7 +163,7 @@ void sigwait_setup(sigset_t *set) } } } - memcpy_fixed(&sigwait_set,set,sizeof(*set)); + memcpy(&sigwait_set, set, sizeof(*set)); pthread_sigmask(SIG_BLOCK,(sigset_t*) set,(sigset_t*) 0); pthread_sigmask(SIG_UNBLOCK,&unblock_mask,(sigset_t*) 0); } @@ -308,7 +239,7 @@ void sigwait_handle_sig(int sig) { pthread_mutex_lock(&LOCK_sigwait); sigaddset(&pending_set, sig); - VOID(pthread_cond_signal(&COND_sigwait)); /* inform sigwait() about signal */ + pthread_cond_signal(&COND_sigwait); /* inform sigwait() about signal */ pthread_mutex_unlock(&LOCK_sigwait); } @@ -320,7 +251,7 @@ void *sigwait_thread(void *set_arg) struct sigaction sact; sact.sa_flags = 0; sact.sa_handler = sigwait_handle_sig; - memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */ + memcpy(&sact.sa_mask, set, sizeof(*set)); /* handler isn't thread_safe */ sigemptyset(&pending_set); for (i = 1; i <= sizeof(pending_set)*8; i++) @@ -357,16 +288,15 @@ int sigwait(sigset_t *setp, int *sigp) pthread_t sigwait_thread_id; inited=1; sigemptyset(&pending_set); - pthread_mutex_init(&LOCK_sigwait,MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_sigwait,NULL); + pthread_mutex_init(&LOCK_sigwait, MY_MUTEX_INIT_FAST); + pthread_cond_init(&COND_sigwait, 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,8196); - my_pthread_attr_setprio(&thr_attr,100); /* Very high priority */ - VOID(pthread_create(&sigwait_thread_id,&thr_attr,sigwait_thread,setp)); - VOID(pthread_attr_destroy(&thr_attr)); + pthread_create(&sigwait_thread_id, &thr_attr, sigwait_thread, setp); + pthread_attr_destroy(&thr_attr); } pthread_mutex_lock(&LOCK_sigwait); @@ -392,7 +322,7 @@ int sigwait(sigset_t *setp, int *sigp) return 0; } } - VOID(pthread_cond_wait(&COND_sigwait,&LOCK_sigwait)); + pthread_cond_wait(&COND_sigwait, &LOCK_sigwait); } return 0; } @@ -535,13 +465,7 @@ int my_pthread_mutex_trylock(pthread_mutex_t *mutex) /* Some help functions */ -int pthread_no_free(void *not_used __attribute__((unused))) -{ - return 0; -} - int pthread_dummy(int ret) { return ret; } -#endif /* THREAD */ diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c new file mode 100644 index 00000000000..2afe3ec31dd --- /dev/null +++ b/mysys/my_rdtsc.c @@ -0,0 +1,962 @@ +/* Copyright (C) 2008-2010 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + rdtsc3 -- multi-platform timer code + pgulutzan@mysql.com, 2005-08-29 + modified 2008-11-02 + + Functions: + + my_timer_cycles ulonglong cycles + my_timer_nanoseconds ulonglong nanoseconds + my_timer_microseconds ulonglong "microseconds" + my_timer_milliseconds ulonglong milliseconds + my_timer_ticks ulonglong ticks + my_timer_init initialization / test + + We'll call the first 5 functions (the ones that return + a ulonglong) "my_timer_xxx" functions. + Each my_timer_xxx function returns a 64-bit timing value + since an arbitrary 'epoch' start. Since the only purpose + is to determine elapsed times, wall-clock time-of-day + is not known and not relevant. + + The my_timer_init function is necessary for initializing. + It returns information (underlying routine name, + frequency, resolution, overhead) about all my_timer_xxx + functions. A program should call my_timer_init once, + use the information to decide what my_timer_xxx function + to use, and subsequently call that function by function + pointer. + + A typical use would be: + my_timer_init() ... once, at program start + ... + time1= my_timer_xxx() ... time before start + [code that's timed] + time2= my_timer_xxx() ... time after end + elapsed_time= (time2 - time1) - overhead +*/ + +#include "my_global.h" +#include "my_rdtsc.h" + +#if defined(_WIN32) +#include <stdio.h> +#include "windows.h" +#else +#include <stdio.h> +#endif + +#if !defined(_WIN32) +#if TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> /* for clock_gettime */ +#else +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#elif defined(HAVE_TIME_H) +#include <time.h> +#endif +#endif +#endif + +#if defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL) +#include <asm/msr.h> /* for rdtscll */ +#endif + +#if defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME) +#include <sys/timeb.h> /* for ftime */ +#endif + +#if defined(HAVE_SYS_TIMES_H) && defined(HAVE_TIMES) +#include <sys/times.h> /* for times */ +#endif + +#if defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) +#include <ia64intrin.h> /* for __GetReg */ +#endif + +#if defined(__APPLE__) && defined(__MACH__) +#include <mach/mach_time.h> +#endif + +#if defined(__SUNPRO_CC) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) +extern "C" ulonglong my_timer_cycles_il_sparc64(); +#elif defined(__SUNPRO_CC) && defined(_ILP32) && !defined(__SunOS_5_7) +extern "C" ulonglong my_timer_cycles_il_sparc32(); +#elif defined(__SUNPRO_CC) && defined(__i386) && defined(_ILP32) +extern "C" ulonglong my_timer_cycles_il_i386(); +#elif defined(__SUNPRO_CC) && defined(__x86_64) && defined(_LP64) +extern "C" ulonglong my_timer_cycles_il_x86_64(); +#elif defined(__SUNPRO_C) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) +ulonglong my_timer_cycles_il_sparc64(); +#elif defined(__SUNPRO_C) && defined(_ILP32) && !defined(__SunOS_5_7) +ulonglong my_timer_cycles_il_sparc32(); +#elif defined(__SUNPRO_C) && defined(__i386) && defined(_ILP32) +ulonglong my_timer_cycles_il_i386(); +#elif defined(__SUNPRO_C) && defined(__x86_64) && defined(_LP64) +ulonglong my_timer_cycles_il_x86_64(); +#endif + +#if defined(__INTEL_COMPILER) +/* + icc warning #1011 is: + missing return statement at end of non-void function +*/ +#pragma warning (disable:1011) +#endif + +/* + For cycles, we depend on RDTSC for x86 platforms, + or on time buffer (which is not really a cycle count + but a separate counter with less than nanosecond + resolution) for most PowerPC platforms, or on + gethrtime which is okay for hpux and solaris, or on + clock_gettime(CLOCK_SGI_CYCLE) for Irix platforms, + or on read_real_time for aix platforms. There is + nothing for Alpha platforms, they would be tricky. +*/ + +ulonglong my_timer_cycles(void) +{ +#if defined(__GNUC__) && defined(__i386__) + /* This works much better if compiled with "gcc -O3". */ + ulonglong result; + __asm__ __volatile__ ("rdtsc" : "=A" (result)); + return result; +#elif defined(__SUNPRO_C) && defined(__i386) + __asm("rdtsc"); +#elif defined(__GNUC__) && defined(__x86_64__) + ulonglong result; + __asm__ __volatile__ ("rdtsc\n\t" \ + "shlq $32,%%rdx\n\t" \ + "orq %%rdx,%%rax" + : "=a" (result) :: "%edx"); + return result; +#elif defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL) + { + ulonglong result; + rdtscll(result); + return result; + } +#elif defined(_WIN32) && defined(_M_IX86) + __asm {rdtsc}; +#elif defined(_WIN64) && defined(_M_X64) + /* For 64-bit Windows: unsigned __int64 __rdtsc(); */ + return __rdtsc(); +#elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) + return (ulonglong) __getReg(_IA64_REG_AR_ITC); /* (3116) */ +#elif defined(__GNUC__) && defined(__ia64__) + { + ulonglong result; + __asm __volatile__ ("mov %0=ar.itc" : "=r" (result)); + return result; + } +#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (defined(__64BIT__) || defined(_ARCH_PPC64)) + { + ulonglong result; + __asm __volatile__ ("mftb %0" : "=r" (result)); + return result; + } +#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (!defined(__64BIT__) && !defined(_ARCH_PPC64)) + { + /* + mftbu means "move from time-buffer-upper to result". + The loop is saying: x1=upper, x2=lower, x3=upper, + if x1!=x3 there was an overflow so repeat. + */ + unsigned int x1, x2, x3; + ulonglong result; + for (;;) + { + __asm __volatile__ ( "mftbu %0" : "=r"(x1) ); + __asm __volatile__ ( "mftb %0" : "=r"(x2) ); + __asm __volatile__ ( "mftbu %0" : "=r"(x3) ); + if (x1 == x3) break; + } + result = x1; + return ( result << 32 ) | x2; + } +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) + return (my_timer_cycles_il_sparc64()); +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(_ILP32) && !defined(__SunOS_5_7) + return (my_timer_cycles_il_sparc32()); +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__i386) && defined(_ILP32) + /* This is probably redundant for __SUNPRO_C. */ + return (my_timer_cycles_il_i386()); +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__x86_64) && defined(_LP64) + return (my_timer_cycles_il_x86_64()); +#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) && (__GNUC__>2) + { + ulonglong result; + __asm __volatile__ ("rd %%tick,%0" : "=r" (result)); + return result; + } +#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) && (__GNUC__>2) + { + union { + ulonglong wholeresult; + struct { + ulong high; + ulong low; + } splitresult; + } result; + __asm __volatile__ ("rd %%tick,%1; srlx %1,32,%0" : "=r" (result.splitresult.high), "=r" (result.splitresult.low)); + return result.wholeresult; + } +#elif defined(__sgi) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_SGI_CYCLE) + { + struct timespec tp; + clock_gettime(CLOCK_SGI_CYCLE, &tp); + return (ulonglong) tp.tv_sec * 1000000000 + (ulonglong) tp.tv_nsec; + } +#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) + /* gethrtime may appear as either cycle or nanosecond counter */ + return (ulonglong) gethrtime(); +#else + return 0; +#endif +} + +#if defined(__INTEL_COMPILER) +/* re-enable warning#1011 which was only for my_timer_cycles() */ +/* There may be an icc bug which means we must leave disabled. */ +#pragma warning (default:1011) +#endif + +/* + For nanoseconds, most platforms have nothing available that + (a) doesn't require bringing in a 40-kb librt.so library + (b) really has nanosecond resolution. +*/ + +ulonglong my_timer_nanoseconds(void) +{ +#if defined(HAVE_READ_REAL_TIME) + { + timebasestruct_t tr; + read_real_time(&tr, TIMEBASE_SZ); + return (ulonglong) tr.tb_high * 1000000000 + (ulonglong) tr.tb_low; + } +#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) + /* SunOS 5.10+, Solaris, HP-UX: hrtime_t gethrtime(void) */ + return (ulonglong) gethrtime(); +#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + { + struct timespec tp; + clock_gettime(CLOCK_REALTIME, &tp); + return (ulonglong) tp.tv_sec * 1000000000 + (ulonglong) tp.tv_nsec; + } +#elif defined(__APPLE__) && defined(__MACH__) + { + ulonglong tm; + static mach_timebase_info_data_t timebase_info= {0,0}; + if (timebase_info.denom == 0) + (void) mach_timebase_info(&timebase_info); + tm= mach_absolute_time(); + return (tm * timebase_info.numer) / timebase_info.denom; + } +#else + return 0; +#endif +} + +/* + For microseconds, gettimeofday() is available on + almost all platforms. On Windows we use + QueryPerformanceCounter which will usually tick over + 3.5 million times per second, and we don't throw + away the extra precision. (On Windows Server 2003 + the frequency is same as the cycle frequency.) +*/ + +ulonglong my_timer_microseconds(void) +{ +#if defined(HAVE_GETTIMEOFDAY) + { + static ulonglong last_value= 0; + struct timeval tv; + if (gettimeofday(&tv, NULL) == 0) + last_value= (ulonglong) tv.tv_sec * 1000000 + (ulonglong) tv.tv_usec; + else + { + /* + There are reports that gettimeofday(2) can have intermittent failures + on some platform, see for example Bug#36819. + We are not trying again or looping, just returning the best value possible + under the circumstances ... + */ + last_value++; + } + return last_value; + } +#elif defined(_WIN32) + { + /* QueryPerformanceCounter usually works with about 1/3 microsecond. */ + LARGE_INTEGER t_cnt; + + QueryPerformanceCounter(&t_cnt); + return (ulonglong) t_cnt.QuadPart; + } +#else + return 0; +#endif +} + +/* + For milliseconds, we use ftime() if it's supported + or time()*1000 if it's not. With modern versions of + Windows and with HP Itanium, resolution is 10-15 + milliseconds. +*/ + +ulonglong my_timer_milliseconds(void) +{ +#if defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME) + /* ftime() is obsolete but maybe the platform is old */ + struct timeb ft; + ftime(&ft); + return (ulonglong)ft.time * 1000 + (ulonglong)ft.millitm; +#elif defined(HAVE_TIME) + return (ulonglong) time(NULL) * 1000; +#elif defined(_WIN32) + FILETIME ft; + GetSystemTimeAsFileTime( &ft ); + return ((ulonglong)ft.dwLowDateTime + + (((ulonglong)ft.dwHighDateTime) << 32))/10000; +#else + return 0; +#endif +} + +/* + For ticks, which we handle with times(), the frequency + is usually 100/second and the overhead is surprisingly + bad, sometimes even worse than gettimeofday's overhead. +*/ + +ulonglong my_timer_ticks(void) +{ +#if defined(HAVE_SYS_TIMES_H) && defined(HAVE_TIMES) + { + struct tms times_buf; + return (ulonglong) times(×_buf); + } +#elif defined(_WIN32) + return (ulonglong) GetTickCount(); +#else + return 0; +#endif +} + +/* + The my_timer_init() function and its sub-functions + have several loops which call timers. If there's + something wrong with a timer -- which has never + happened in tests -- we want the loop to end after + an arbitrary number of iterations, and my_timer_info + will show a discouraging result. The arbitrary + number is 1,000,000. +*/ +#define MY_TIMER_ITERATIONS 1000000 + +/* + Calculate overhead. Called from my_timer_init(). + Usually best_timer_overhead = cycles.overhead or + nanoseconds.overhead, so returned amount is in + cycles or nanoseconds. We repeat the calculation + ten times, so that we can disregard effects of + caching or interrupts. Result is quite consistent + for cycles, at least. But remember it's a minimum. +*/ + +static void my_timer_init_overhead(ulonglong *overhead, + ulonglong (*cycle_timer)(void), + ulonglong (*this_timer)(void), + ulonglong best_timer_overhead) +{ + ulonglong time1, time2; + int i; + + /* *overhead, least of 20 calculations - cycles.overhead */ + for (i= 0, *overhead= 1000000000; i < 20; ++i) + { + time1= cycle_timer(); + this_timer(); /* rather than 'time_tmp= timer();' */ + time2= cycle_timer() - time1; + if (*overhead > time2) + *overhead= time2; + } + *overhead-= best_timer_overhead; +} + +/* + Calculate Resolution. Called from my_timer_init(). + If a timer goes up by jumps, e.g. 1050, 1075, 1100, ... + then the best resolution is the minimum jump, e.g. 25. + If it's always divisible by 1000 then it's just a + result of multiplication of a lower-precision timer + result, e.g. nanoseconds are often microseconds * 1000. + If the minimum jump is less than an arbitrary passed + figure (a guess based on maximum overhead * 2), ignore. + Usually we end up with nanoseconds = 1 because it's too + hard to detect anything <= 100 nanoseconds. + Often GetTickCount() has resolution = 15. + We don't check with ticks because they take too long. +*/ +static ulonglong my_timer_init_resolution(ulonglong (*this_timer)(void), + ulonglong overhead_times_2) +{ + ulonglong time1, time2; + ulonglong best_jump; + int i, jumps, divisible_by_1000, divisible_by_1000000; + + divisible_by_1000= divisible_by_1000000= 0; + best_jump= 1000000; + for (i= jumps= 0; jumps < 3 && i < MY_TIMER_ITERATIONS * 10; ++i) + { + time1= this_timer(); + time2= this_timer(); + time2-= time1; + if (time2) + { + ++jumps; + if (!(time2 % 1000)) + { + ++divisible_by_1000; + if (!(time2 % 1000000)) + ++divisible_by_1000000; + } + if (best_jump > time2) + best_jump= time2; + /* For milliseconds, one jump is enough. */ + if (overhead_times_2 == 0) + break; + } + } + if (jumps == 3) + { + if (jumps == divisible_by_1000000) + return 1000000; + if (jumps == divisible_by_1000) + return 1000; + } + if (best_jump > overhead_times_2) + return best_jump; + return 1; +} + +/* + Calculate cycle frequency by seeing how many cycles pass + in a 200-microsecond period. I tried with 10-microsecond + periods originally, and the result was often very wrong. +*/ + +static ulonglong my_timer_init_frequency(MY_TIMER_INFO *mti) +{ + int i; + ulonglong time1, time2, time3, time4; + time1= my_timer_cycles(); + time2= my_timer_microseconds(); + time3= time2; /* Avoids a Microsoft/IBM compiler warning */ + for (i= 0; i < MY_TIMER_ITERATIONS; ++i) + { + time3= my_timer_microseconds(); + if (time3 - time2 > 200) break; + } + time4= my_timer_cycles() - mti->cycles.overhead; + time4-= mti->microseconds.overhead; + return (mti->microseconds.frequency * (time4 - time1)) / (time3 - time2); +} + +/* + Call my_timer_init before the first call to my_timer_xxx(). + If something must be initialized, it happens here. + Set: what routine is being used e.g. "asm_x86" + Set: function, overhead, actual frequency, resolution. +*/ + +void my_timer_init(MY_TIMER_INFO *mti) +{ + ulonglong (*best_timer)(void); + ulonglong best_timer_overhead; + ulonglong time1, time2; + int i; + + /* cycles */ + mti->cycles.frequency= 1000000000; +#if defined(__GNUC__) && defined(__i386__) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86; +#elif defined(__SUNPRO_C) && defined(__i386) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86; +#elif defined(__GNUC__) && defined(__x86_64__) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86_64; +#elif defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL) + mti->cycles.routine= MY_TIMER_ROUTINE_RDTSCLL; +#elif defined(_WIN32) && defined(_M_IX86) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86_WIN; +#elif defined(_WIN64) && defined(_M_X64) + mti->cycles.routine= MY_TIMER_ROUTINE_RDTSC; +#elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_IA64; +#elif defined(__GNUC__) && defined(__ia64__) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_IA64; +#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (defined(__64BIT__) || defined(_ARCH_PPC64)) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_PPC64; +#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (!defined(__64BIT__) && !defined(_ARCH_PPC64)) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_PPC; +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC64; +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(_ILP32) && !defined(__SunOS_5_7) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC32; +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__i386) && defined(_ILP32) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_I386; +#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__x86_64) && defined(_LP64) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_X86_64; +#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) && (__GNUC__>2) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_GCC_SPARC64; +#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) && (__GNUC__>2) + mti->cycles.routine= MY_TIMER_ROUTINE_ASM_GCC_SPARC32; +#elif defined(__sgi) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_SGI_CYCLE) + mti->cycles.routine= MY_TIMER_ROUTINE_SGI_CYCLE; +#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) + mti->cycles.routine= MY_TIMER_ROUTINE_GETHRTIME; +#else + mti->cycles.routine= 0; +#endif + + if (!mti->cycles.routine || !my_timer_cycles()) + { + mti->cycles.routine= 0; + mti->cycles.resolution= 0; + mti->cycles.frequency= 0; + mti->cycles.overhead= 0; + } + + /* nanoseconds */ + mti->nanoseconds.frequency= 1000000000; /* initial assumption */ +#if defined(HAVE_READ_REAL_TIME) + mti->nanoseconds.routine= MY_TIMER_ROUTINE_READ_REAL_TIME; +#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) + mti->nanoseconds.routine= MY_TIMER_ROUTINE_GETHRTIME; +#elif defined(HAVE_CLOCK_GETTIME) + mti->nanoseconds.routine= MY_TIMER_ROUTINE_CLOCK_GETTIME; +#elif defined(__APPLE__) && defined(__MACH__) + mti->nanoseconds.routine= MY_TIMER_ROUTINE_MACH_ABSOLUTE_TIME; +#else + mti->nanoseconds.routine= 0; +#endif + if (!mti->nanoseconds.routine || !my_timer_nanoseconds()) + { + mti->nanoseconds.routine= 0; + mti->nanoseconds.resolution= 0; + mti->nanoseconds.frequency= 0; + mti->nanoseconds.overhead= 0; + } + + /* microseconds */ + mti->microseconds.frequency= 1000000; /* initial assumption */ +#if defined(HAVE_GETTIMEOFDAY) + mti->microseconds.routine= MY_TIMER_ROUTINE_GETTIMEOFDAY; +#elif defined(_WIN32) + { + LARGE_INTEGER li; + /* Windows: typical frequency = 3579545, actually 1/3 microsecond. */ + if (!QueryPerformanceFrequency(&li)) + mti->microseconds.routine= 0; + else + { + mti->microseconds.frequency= li.QuadPart; + mti->microseconds.routine= MY_TIMER_ROUTINE_QUERYPERFORMANCECOUNTER; + } + } +#else + mti->microseconds.routine= 0; +#endif + if (!mti->microseconds.routine || !my_timer_microseconds()) + { + mti->microseconds.routine= 0; + mti->microseconds.resolution= 0; + mti->microseconds.frequency= 0; + mti->microseconds.overhead= 0; + } + + /* milliseconds */ + mti->milliseconds.frequency= 1000; /* initial assumption */ +#if defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME) + mti->milliseconds.routine= MY_TIMER_ROUTINE_FTIME; +#elif defined(_WIN32) + mti->milliseconds.routine= MY_TIMER_ROUTINE_GETSYSTEMTIMEASFILETIME; +#elif defined(HAVE_TIME) + mti->milliseconds.routine= MY_TIMER_ROUTINE_TIME; +#else + mti->milliseconds.routine= 0; +#endif + if (!mti->milliseconds.routine || !my_timer_milliseconds()) + { + mti->milliseconds.routine= 0; + mti->milliseconds.resolution= 0; + mti->milliseconds.frequency= 0; + mti->milliseconds.overhead= 0; + } + + /* ticks */ + mti->ticks.frequency= 100; /* permanent assumption */ +#if defined(HAVE_SYS_TIMES_H) && defined(HAVE_TIMES) + mti->ticks.routine= MY_TIMER_ROUTINE_TIMES; +#elif defined(_WIN32) + mti->ticks.routine= MY_TIMER_ROUTINE_GETTICKCOUNT; +#else + mti->ticks.routine= 0; +#endif + if (!mti->ticks.routine || !my_timer_ticks()) + { + mti->ticks.routine= 0; + mti->ticks.resolution= 0; + mti->ticks.frequency= 0; + mti->ticks.overhead= 0; + } + + /* + Calculate overhead in terms of the timer that + gives the best resolution: cycles or nanoseconds. + I doubt it ever will be as bad as microseconds. + */ + if (mti->cycles.routine) + best_timer= &my_timer_cycles; + else + { + if (mti->nanoseconds.routine) + { + best_timer= &my_timer_nanoseconds; + } + else + best_timer= &my_timer_microseconds; + } + + /* best_timer_overhead = least of 20 calculations */ + for (i= 0, best_timer_overhead= 1000000000; i < 20; ++i) + { + time1= best_timer(); + time2= best_timer() - time1; + if (best_timer_overhead > time2) + best_timer_overhead= time2; + } + if (mti->cycles.routine) + my_timer_init_overhead(&mti->cycles.overhead, + best_timer, + &my_timer_cycles, + best_timer_overhead); + if (mti->nanoseconds.routine) + my_timer_init_overhead(&mti->nanoseconds.overhead, + best_timer, + &my_timer_nanoseconds, + best_timer_overhead); + if (mti->microseconds.routine) + my_timer_init_overhead(&mti->microseconds.overhead, + best_timer, + &my_timer_microseconds, + best_timer_overhead); + if (mti->milliseconds.routine) + my_timer_init_overhead(&mti->milliseconds.overhead, + best_timer, + &my_timer_milliseconds, + best_timer_overhead); + if (mti->ticks.routine) + my_timer_init_overhead(&mti->ticks.overhead, + best_timer, + &my_timer_ticks, + best_timer_overhead); + +/* + Calculate resolution for nanoseconds or microseconds + or milliseconds, by seeing if it's always divisible + by 1000, and by noticing how much jumping occurs. + For ticks, just assume the resolution is 1. +*/ + if (mti->cycles.routine) + mti->cycles.resolution= 1; + if (mti->nanoseconds.routine) + mti->nanoseconds.resolution= + my_timer_init_resolution(&my_timer_nanoseconds, 20000); + if (mti->microseconds.routine) + mti->microseconds.resolution= + my_timer_init_resolution(&my_timer_microseconds, 20); + if (mti->milliseconds.routine) + { + if (mti->milliseconds.routine == MY_TIMER_ROUTINE_TIME) + mti->milliseconds.resolution= 1000; + else + mti->milliseconds.resolution= + my_timer_init_resolution(&my_timer_milliseconds, 0); + } + if (mti->ticks.routine) + mti->ticks.resolution= 1; + +/* + Calculate cycles frequency, + if we have both a cycles routine and a microseconds routine. + In tests, this usually results in a figure within 2% of + what "cat /proc/cpuinfo" says. + If the microseconds routine is QueryPerformanceCounter + (i.e. it's Windows), and the microseconds frequency is > + 500,000,000 (i.e. it's Windows Server so it uses RDTSC) + and the microseconds resolution is > 100 (i.e. dreadful), + then calculate cycles frequency = microseconds frequency. +*/ + if (mti->cycles.routine + && mti->microseconds.routine) + { + if (mti->microseconds.routine == + MY_TIMER_ROUTINE_QUERYPERFORMANCECOUNTER + && mti->microseconds.frequency > 500000000 + && mti->microseconds.resolution > 100) + mti->cycles.frequency= mti->microseconds.frequency; + else + { + ulonglong time1, time2; + time1= my_timer_init_frequency(mti); + /* Repeat once in case there was an interruption. */ + time2= my_timer_init_frequency(mti); + if (time1 < time2) mti->cycles.frequency= time1; + else mti->cycles.frequency= time2; + } + } + +/* + Calculate milliseconds frequency = + (cycles-frequency/#-of-cycles) * #-of-milliseconds, + if we have both a milliseconds routine and a cycles + routine. + This will be inaccurate if milliseconds resolution > 1. + This is probably only useful when testing new platforms. +*/ + if (mti->milliseconds.routine + && mti->milliseconds.resolution < 1000 + && mti->microseconds.routine + && mti->cycles.routine) + { + int i; + ulonglong time1, time2, time3, time4; + time1= my_timer_cycles(); + time2= my_timer_milliseconds(); + time3= time2; /* Avoids a Microsoft/IBM compiler warning */ + for (i= 0; i < MY_TIMER_ITERATIONS * 1000; ++i) + { + time3= my_timer_milliseconds(); + if (time3 - time2 > 10) break; + } + time4= my_timer_cycles(); + mti->milliseconds.frequency= + (mti->cycles.frequency * (time3 - time2)) / (time4 - time1); + } + +/* + Calculate ticks.frequency = + (cycles-frequency/#-of-cycles * #-of-ticks, + if we have both a ticks routine and a cycles + routine, + This is probably only useful when testing new platforms. +*/ + if (mti->ticks.routine + && mti->microseconds.routine + && mti->cycles.routine) + { + int i; + ulonglong time1, time2, time3, time4; + time1= my_timer_cycles(); + time2= my_timer_ticks(); + time3= time2; /* Avoids a Microsoft/IBM compiler warning */ + for (i= 0; i < MY_TIMER_ITERATIONS * 1000; ++i) + { + time3= my_timer_ticks(); + if (time3 - time2 > 10) break; + } + time4= my_timer_cycles(); + mti->ticks.frequency= + (mti->cycles.frequency * (time3 - time2)) / (time4 - time1); + } +} + +/* + Additional Comments + ------------------- + + This is for timing, i.e. finding out how long a piece of code + takes. If you want time of day matching a wall clock, the + my_timer_xxx functions won't help you. + + The best timer is the one with highest frequency, lowest + overhead, and resolution=1. The my_timer_info() routine will tell + you at runtime which timer that is. Usually it will be + my_timer_cycles() but be aware that, although it's best, + it has possible flaws and dangers. Depending on platform: + - The frequency might change. We don't test for this. It + happens on laptops for power saving, and on blade servers + for avoiding overheating. + - The overhead that my_timer_init() returns is the minimum. + In fact it could be slightly greater because of caching or + because you call the routine by address, as recommended. + It could be hugely greater if there's an interrupt. + - The x86 cycle counter, RDTSC doesn't "serialize". That is, + if there is out-of-order execution, rdtsc might be processed + after an instruction that logically follows it. + (We could force serialization, but that would be slower.) + - It is possible to set a flag which renders RDTSC + inoperative. Somebody responsible for the kernel + of the operating system would have to make this + decision. For the platforms we've tested with, there's + no such problem. + - With a multi-processor arrangement, it's possible + to get the cycle count from one processor in + thread X, and the cycle count from another processor + in thread Y. They may not always be in synch. + - You can't depend on a cycle counter being available for + all platforms. On Alphas, the + cycle counter is only 32-bit, so it would overflow quickly, + so we don't bother with it. On platforms that we haven't + tested, there might be some if/endif combination that we + didn't expect, or some assembler routine that we didn't + supply. + + The recommended way to use the timer routines is: + 1. Somewhere near the beginning of the program, call + my_timer_init(). This should only be necessary once, + although you can call it again if you think that the + frequency has changed. + 2. Determine the best timer based on frequency, resolution, + overhead -- all things that my_timer_init() returns. + Preserve the address of the timer and the my_timer_into + results in an easily-accessible place. + 3. Instrument the code section that you're monitoring, thus: + time1= my_timer_xxx(); + Instrumented code; + time2= my_timer_xxx(); + elapsed_time= (time2 - time1) - overhead; + If the timer is always on, then overhead is always there, + so don't subtract it. + 4. Save the elapsed time, or add it to a totaller. + 5. When all timing processes are complete, transfer the + saved / totalled elapsed time to permanent storage. + Optionally you can convert cycles to microseconds at + this point. (Don't do so every time you calculate + elapsed_time! That would waste time and lose precision!) + For converting cycles to microseconds, use the frequency + that my_timer_init() returns. You'll also need to convert + if the my_timer_microseconds() function is the Windows + function QueryPerformanceCounter(), since that's sometimes + a counter with precision slightly better than microseconds. + + Since we recommend calls by function pointer, we supply + no inline functions. + + Some comments on the many candidate routines for timing ... + + clock() -- We don't use because it would overflow frequently. + + clock_gettime() -- In tests, clock_gettime often had + resolution = 1000. + + ftime() -- A "man ftime" says: "This function is obsolete. + Don't use it." On every platform that we tested, if ftime() + was available, then so was gettimeofday(), and gettimeofday() + overhead was always at least as good as ftime() overhead. + + gettimeofday() -- available on most platforms, though not + on Windows. There is a hardware timer (sometimes a Programmable + Interrupt Timer or "PIT") (sometimes a "HPET") used for + interrupt generation. When it interrupts (a "tick" or "jiffy", + typically 1 centisecond) it sets xtime. For gettimeofday, a + Linux kernel routine usually gets xtime and then gets rdtsc + to get elapsed nanoseconds since the last tick. On Red Hat + Enterprise Linux 3, there was once a bug which caused the + resolution to be 1000, i.e. one centisecond. We never check + for time-zone change. + + getnstimeofday() -- something to watch for in future Linux + + do_gettimeofday() -- exists on Linux but not for "userland" + + get_cycles() -- a multi-platform function, worth watching + in future Linux versions. But we found platform-specific + functions which were better documented in operating-system + manuals. And get_cycles() can fail or return a useless + 32-bit number. It might be available on some platforms, + such as arm, which we didn't test. Using + "include <linux/timex.h>" or "include <asm/timex.h>" + can lead to autoconf or compile errors, depending on system. + + rdtsc, __rdtsc, rdtscll: available for x86 with Linux BSD, + Solaris, Windows. See "possible flaws and dangers" comments. + + times(): what we use for ticks. Should just read the last + (xtime) tick count, therefore should be fast, but usually + isn't. + + GetTickCount(): we use this for my_timer_ticks() on + Windows. Actually it really is a tick counter, so resolution + >= 10 milliseconds unless you have a very old Windows version. + With Windows 95 or 98 or ME, timeGetTime() has better resolution than + GetTickCount (1ms rather than 55ms). But with Windows NT or XP or 2000, + they're both getting from a variable in the Process Environment Block + (PEB), and the variable is set by the programmable interrupt timer, so + the resolution is the same (usually 10-15 milliseconds). Also timeGetTime + is slower on old machines: + http://www.doumo.jp/aon-java/jsp/postgretips/tips.jsp?tips=74. + Also timeGetTime requires linking winmm.lib, + Therefore we use GetTickCount. + It will overflow every 49 days because the return is 32-bit. + There is also a GetTickCount64 but it requires Vista or Windows Server 2008. + (As for GetSystemTimeAsFileTime, its precision is spurious, it + just reads the tick variable like the other functions do. + However, we don't expect it to overflow every 49 days, so we + will prefer it for my_timer_milliseconds().) + + QueryPerformanceCounter() we use this for my_timer_microseconds() + on Windows. 1-PIT-tick (often 1/3-microsecond). Usually reads + the PIT so it's slow. On some Windows variants, uses RDTSC. + + GetLocalTime() this is available on Windows but we don't use it. + + getclock(): documented for Alpha, but not found during tests. + + mach_absolute_time() and UpTime() are recommended for Apple. + Inititally they weren't tried, because asm_ppc seems to do the job. + But now we use mach_absolute_time for nanoseconds. + + Any clock-based timer can be affected by NPT (ntpd program), + which means: + - full-second correction can occur for leap second + - tiny corrections can occcur approimately every 11 minutes + (but I think they only affect the RTC which isn't the PIT). + + We define "precision" as "frequency" and "high precision" is + "frequency better than 1 microsecond". We define "resolution" + as a synonym for "granularity". We define "accuracy" as + "closeness to the truth" as established by some authoritative + clock, but we can't measure accuracy. + + Do not expect any of our timers to be monotonic; we + won't guarantee that they return constantly-increasing + unique numbers. + + We tested with AIX, Solaris (x86 + Sparc), Linux (x86 + + Itanium), Windows, 64-bit Windows, QNX, FreeBSD, HPUX, + Irix, Mac. We didn't test with SCO. + +*/ + diff --git a/mysys/my_read.c b/mysys/my_read.c index 5fef4455f62..dbe9006a1d3 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -37,8 +37,8 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) { size_t readbytes, save_count; DBUG_ENTER("my_read"); - DBUG_PRINT("my",("fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); + DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", + Filedes, Buffer, (ulong) Count, MyFlags)); save_count= Count; for (;;) @@ -49,6 +49,7 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) #else readbytes= read(Filedes, Buffer, Count); #endif + if (readbytes != Count) { my_errno= errno; @@ -58,14 +59,14 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d", (int) readbytes, (ulong) Count, Filedes, my_errno)); -#ifdef THREAD + if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) { DBUG_PRINT("debug", ("my_read() was interrupted and returned %ld", (long) readbytes)); continue; /* Interrupted */ } -#endif + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { if (readbytes == (size_t) -1) diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c deleted file mode 100644 index 7e49a482884..00000000000 --- a/mysys/my_realloc.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* my_global.h may define SAFEMALLOC (through my_config.h). */ -#include <my_global.h> - -#ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */ -#undef SAFEMALLOC -#endif - -#include "mysys_priv.h" -#include "mysys_err.h" - - /* My memory re allocator */ - -/** - @brief wrapper around realloc() - - @param oldpoint pointer to currently allocated area - @param size new size requested, must be >0 - @param my_flags flags - - @note if size==0 realloc() may return NULL; my_realloc() treats this as an - error which is not the intention of realloc() -*/ - -void* my_realloc(void* oldpoint, size_t size, myf my_flags) -{ - void *point; - DBUG_ENTER("my_realloc"); - DBUG_PRINT("my",("ptr: 0x%lx size: %lu my_flags: %d", (long) oldpoint, - (ulong) size, my_flags)); - - DBUG_ASSERT(size > 0); - if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR)) - DBUG_RETURN(my_malloc(size,my_flags)); -#ifdef USE_HALLOC - if (!(point = malloc(size))) - { - if (my_flags & MY_FREE_ON_ERROR) - my_free(oldpoint,my_flags); - if (my_flags & MY_HOLD_ON_ERROR) - DBUG_RETURN(oldpoint); - my_errno=errno; - if (my_flags & MY_FAE+MY_WME) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size); - } - else - { - memcpy(point,oldpoint,size); - free(oldpoint); - } -#else - if ((point= (uchar*) realloc(oldpoint,size)) == NULL) - { - if (my_flags & MY_FREE_ON_ERROR) - my_free(oldpoint, my_flags); - if (my_flags & MY_HOLD_ON_ERROR) - DBUG_RETURN(oldpoint); - my_errno=errno; - if (my_flags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size); - } -#endif - DBUG_PRINT("exit",("ptr: 0x%lx", (long) point)); - DBUG_RETURN(point); -} /* my_realloc */ diff --git a/mysys/my_redel.c b/mysys/my_redel.c index 2de989a2854..1b200568a47 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -108,7 +108,7 @@ int my_copystat(const char *from, const char *to, int MyFlags) return -1; } -#if !defined(__WIN__) && !defined(__NETWARE__) +#if !defined(__WIN__) if (statbuf.st_nlink > 1 && MyFlags & MY_LINK_WARNING) { if (MyFlags & MY_LINK_WARNING) @@ -123,27 +123,16 @@ int my_copystat(const char *from, const char *to, int MyFlags) if (MyFlags & MY_FAE) return -1; } -#endif /* !__WIN__ && !__NETWARE__ */ +#endif /* !__WIN__ */ -#ifndef VMS -#ifndef __ZTC__ if (MyFlags & MY_COPYTIME) { struct utimbuf timep; timep.actime = statbuf.st_atime; timep.modtime = statbuf.st_mtime; - VOID(utime((char*) to, &timep));/* Update last accessed and modified times */ + (void) utime((char*) to, &timep);/* Update last accessed and modified times */ } -#else - if (MyFlags & MY_COPYTIME) - { - time_t time[2]; - time[0]= statbuf.st_atime; - time[1]= statbuf.st_mtime; - VOID(utime((char*) to, time));/* Update last accessed and modified times */ - } -#endif -#endif + return 0; } /* my_copystat */ diff --git a/mysys/my_rename.c b/mysys/my_rename.c index 39e6056a9e4..1a4e7b2b409 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -44,7 +44,7 @@ int my_rename(const char *from, const char *to, myf MyFlags) } #endif #if defined(HAVE_RENAME) -#if defined(__WIN__) || defined(__NETWARE__) +#if defined(__WIN__) /* On windows we can't rename over an existing file: Remove any conflicting files: diff --git a/mysys/my_safehash.c b/mysys/my_safehash.c index b3d6439793c..1417b8ea94e 100644 --- a/mysys/my_safehash.c +++ b/mysys/my_safehash.c @@ -53,7 +53,7 @@ static void safe_hash_entry_free(SAFE_HASH_ENTRY *entry) { DBUG_ENTER("safe_hash_entry_free"); - my_free((uchar*) entry, MYF(0)); + my_free(entry); DBUG_VOID_RETURN; } @@ -100,14 +100,14 @@ my_bool safe_hash_init(SAFE_HASH *hash, uint elements, uchar *default_value) { DBUG_ENTER("safe_hash_init"); - if (hash_init(&hash->hash, &my_charset_bin, elements, - 0, 0, (hash_get_key) safe_hash_entry_get, - (void (*)(void*)) safe_hash_entry_free, 0)) + if (my_hash_init(&hash->hash, &my_charset_bin, elements, + 0, 0, (my_hash_get_key) safe_hash_entry_get, + (void (*)(void*)) safe_hash_entry_free, 0)) { hash->default_value= 0; DBUG_RETURN(1); } - my_rwlock_init(&hash->mutex, 0); + mysql_rwlock_init(key_SAFEHASH_mutex, &hash->mutex); hash->default_value= default_value; hash->root= 0; DBUG_RETURN(0); @@ -133,8 +133,8 @@ void safe_hash_free(SAFE_HASH *hash) */ if (hash->default_value) { - hash_free(&hash->hash); - rwlock_destroy(&hash->mutex); + my_hash_free(&hash->hash); + mysql_rwlock_destroy(&hash->mutex); hash->default_value=0; } } @@ -159,9 +159,9 @@ uchar *safe_hash_search(SAFE_HASH *hash, const uchar *key, uint length, { uchar *result; DBUG_ENTER("safe_hash_search"); - rw_rdlock(&hash->mutex); - result= hash_search(&hash->hash, key, length); - rw_unlock(&hash->mutex); + mysql_rwlock_rdlock(&hash->mutex); + result= my_hash_search(&hash->hash, key, length); + mysql_rwlock_unlock(&hash->mutex); if (!result) result= def; else @@ -199,8 +199,8 @@ my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, DBUG_ENTER("safe_hash_set"); DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data)); - rw_wrlock(&hash->mutex); - entry= (SAFE_HASH_ENTRY*) hash_search(&hash->hash, key, length); + mysql_rwlock_wrlock(&hash->mutex); + entry= (SAFE_HASH_ENTRY*) my_hash_search(&hash->hash, key, length); if (data == hash->default_value) { @@ -214,7 +214,7 @@ my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, /* unlink entry from list */ if ((*entry->prev= entry->next)) entry->next->prev= entry->prev; - hash_delete(&hash->hash, (uchar*) entry); + my_hash_delete(&hash->hash, (uchar*) entry); goto end; } if (entry) @@ -242,14 +242,14 @@ my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, if (my_hash_insert(&hash->hash, (uchar*) entry)) { /* This can only happen if hash got out of memory */ - my_free((char*) entry, MYF(0)); + my_free(entry); error= 1; goto end; } } end: - rw_unlock(&hash->mutex); + mysql_rwlock_unlock(&hash->mutex); DBUG_RETURN(error); } @@ -274,7 +274,7 @@ void safe_hash_change(SAFE_HASH *hash, uchar *old_data, uchar *new_data) SAFE_HASH_ENTRY *entry, *next; DBUG_ENTER("safe_hash_change"); - rw_wrlock(&hash->mutex); + mysql_rwlock_wrlock(&hash->mutex); for (entry= hash->root ; entry ; entry= next) { @@ -285,13 +285,13 @@ void safe_hash_change(SAFE_HASH *hash, uchar *old_data, uchar *new_data) { if ((*entry->prev= entry->next)) entry->next->prev= entry->prev; - hash_delete(&hash->hash, (uchar*) entry); + my_hash_delete(&hash->hash, (uchar*) entry); } else entry->data= new_data; } } - rw_unlock(&hash->mutex); + mysql_rwlock_unlock(&hash->mutex); DBUG_VOID_RETURN; } diff --git a/mysys/my_safehash.h b/mysys/my_safehash.h index 8a5856b6763..e52fee68b57 100644 --- a/mysys/my_safehash.h +++ b/mysys/my_safehash.h @@ -39,9 +39,7 @@ typedef struct st_safe_hash_entry typedef struct st_safe_hash_with_default { -#ifdef THREAD - rw_lock_t mutex; -#endif + mysql_rwlock_t mutex; HASH hash; uchar *default_value; SAFE_HASH_ENTRY *root; diff --git a/mysys/my_seek.c b/mysys/my_seek.c index 24941517487..efe0416c49a 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -45,11 +45,10 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags) { - reg1 os_off_t newpos= -1; + os_off_t newpos= -1; DBUG_ENTER("my_seek"); - DBUG_PRINT("my",("fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d", - fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos, - whence, MyFlags)); + DBUG_PRINT("my",("fd: %d Pos: %llu Whence: %d MyFlags: %d", + fd, (ulonglong) pos, whence, MyFlags)); DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */ /* @@ -66,12 +65,12 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags) my_errno= errno; if (MyFlags & MY_WME) my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno); - DBUG_PRINT("error",("lseek: %lu errno: %d", (ulong) newpos,errno)); + DBUG_PRINT("error", ("lseek: %llu errno: %d", (ulonglong) newpos, errno)); DBUG_RETURN(MY_FILEPOS_ERROR); } if ((my_off_t) newpos != pos) { - DBUG_PRINT("exit",("pos: %lu", (ulong) newpos)); + DBUG_PRINT("exit",("pos: %llu", (ulonglong) newpos)); } DBUG_RETURN((my_off_t) newpos); } /* my_seek */ @@ -86,20 +85,18 @@ my_off_t my_tell(File fd, myf MyFlags) DBUG_ENTER("my_tell"); DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); DBUG_ASSERT(fd >= 0); -#ifdef _WIN32 - pos= my_seek(fd, 0, MY_SEEK_CUR,0); -#elif defined(HAVE_TELL) - pos=tell(fd); +#if defined (HAVE_TELL) && !defined (_WIN32) + pos= tell(fd); #else - pos=lseek(fd, 0L, MY_SEEK_CUR); + pos= my_seek(fd, 0L, MY_SEEK_CUR,0); #endif if (pos == (os_off_t) -1) { my_errno= errno; if (MyFlags & MY_WME) my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno); - DBUG_PRINT("error", ("tell: %lu errno: %d", (ulong) pos, my_errno)); + DBUG_PRINT("error", ("tell: %llu errno: %d", (ulonglong) pos, my_errno)); } - DBUG_PRINT("exit",("pos: %lu", (ulong) pos)); + DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos)); DBUG_RETURN((my_off_t) pos); } /* my_tell */ diff --git a/mysys/my_sleep.c b/mysys/my_sleep.c index cb21c15a925..5a18a2854d6 100644 --- a/mysys/my_sleep.c +++ b/mysys/my_sleep.c @@ -20,9 +20,7 @@ void my_sleep(ulong m_seconds) { -#ifdef __NETWARE__ - delay(m_seconds/1000+1); -#elif defined(__WIN__) +#if defined(__WIN__) Sleep(m_seconds/1000+1); /* Sleep() has millisecond arg */ #elif defined(HAVE_SELECT) struct timeval t; diff --git a/mysys/my_static.c b/mysys/my_static.c index d6b2f9f110c..60e23e8dfa9 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -27,25 +27,20 @@ my_bool timed_mutexes= 0; /* from my_init */ char * home_dir=0; const char *my_progname= NULL, *my_progname_short= NULL; -char NEAR curr_dir[FN_REFLEN]= {0}, - NEAR home_dir_buff[FN_REFLEN]= {0}; +char curr_dir[FN_REFLEN]= {0}, + home_dir_buff[FN_REFLEN]= {0}; ulong my_stream_opened=0,my_file_opened=0, my_tmp_file_created=0; ulong my_file_total_opened= 0; -int NEAR my_umask=0664, NEAR my_umask_dir=0777; -#ifndef THREAD -int NEAR my_errno=0; -#endif +int my_umask=0664, my_umask_dir=0777; + struct st_my_file_info my_file_info_default[MY_NFILE]; uint my_file_limit= MY_NFILE; struct st_my_file_info *my_file_info= my_file_info_default; /* From mf_brkhant */ -int NEAR my_dont_interrupt=0; +int my_dont_interrupt=0; volatile int _my_signals=0; struct st_remember _my_sig_remember[MAX_SIGNALS]={{0,0}}; -#ifdef THREAD -sigset_t my_signals; /* signals blocked by mf_brkhant */ -#endif /* from mf_reccache.c */ ulong my_default_record_cache_size=RECORD_CACHE_SIZE; @@ -65,32 +60,19 @@ my_bool my_use_large_pages= 0; uint my_large_page_size= 0; #endif - /* from safe_malloc */ -uint sf_malloc_prehunc=0, /* If you have problem with core- */ - sf_malloc_endhunc=0, /* dump when malloc-message.... */ - /* set theese to 64 or 128 */ - sf_malloc_quick=0; /* set if no calls to sanity */ -size_t sf_malloc_cur_memory= 0L; /* Current memory usage */ -size_t sf_malloc_max_memory= 0L; /* Maximum memory usage */ -uint sf_malloc_count= 0; /* Number of times NEW() was called */ -uchar *sf_min_adress= (uchar*) ~(unsigned long) 0L, - *sf_max_adress= (uchar*) 0L; -/* Root of the linked list of struct st_irem */ -struct st_irem *sf_malloc_root = NULL; - /* 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 -char * NEAR globerrs[GLOBERRS]; /* my_error_messages is here */ +const char *globerrs[GLOBERRS]; /* my_error_messages is here */ #endif void (*my_abort_hook)(int) = (void(*)(int)) exit; -int (*error_handler_hook)(uint error,const char *str,myf MyFlags)= - my_message_no_curses; -int (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)= - my_message_no_curses; +void (*error_handler_hook)(uint error, const char *str, myf MyFlags)= + my_message_stderr; +void (*fatal_error_handler_hook)(uint error, const char *str, myf MyFlags)= + my_message_stderr; static const char *proc_info_dummy(void *a __attribute__((unused)), const char *b __attribute__((unused)), @@ -113,9 +95,36 @@ void (*debug_sync_C_callback_ptr)(const char *, size_t); #endif /* defined(ENABLED_DEBUG_SYNC) */ /* How to disable options */ -my_bool NEAR my_disable_locking=0; -my_bool NEAR my_disable_sync=0; -my_bool NEAR my_disable_async_io=0; -my_bool NEAR my_disable_flush_key_blocks=0; -my_bool NEAR my_disable_symlinks=0; -my_bool NEAR mysys_uses_curses=0; +my_bool my_disable_locking=0; +my_bool my_disable_sync=0; +my_bool my_disable_async_io=0; +my_bool my_disable_flush_key_blocks=0; +my_bool my_disable_symlinks=0; + +/* + Note that PSI_hook and PSI_server are unconditionally + (no ifdef HAVE_PSI_INTERFACE) defined. + This is to ensure binary compatibility between the server and plugins, + in the case when: + - the server is not compiled with HAVE_PSI_INTERFACE + - a plugin is compiled with HAVE_PSI_INTERFACE + See the doxygen documentation for the performance schema. +*/ + +/** + Hook for the instrumentation interface. + Code implementing the instrumentation interface should register here. +*/ +struct PSI_bootstrap *PSI_hook= NULL; + +/** + Instance of the instrumentation interface for the MySQL server. + @todo This is currently a global variable, which is handy when + compiling instrumented code that is bundled with the server. + When dynamic plugin are truly supported, this variable will need + to be replaced by a macro, so that each XYZ plugin can have it's own + xyz_psi_server variable, obtained from PSI_bootstrap::get_interface() + with the version used at compile time for plugin XYZ. +*/ +PSI *PSI_server= NULL; + diff --git a/mysys/my_static.h b/mysys/my_static.h index 5e853c2a559..0f1cd34a04e 100644 --- a/mysys/my_static.h +++ b/mysys/my_static.h @@ -1,3 +1,6 @@ +#ifndef MYSYS_MY_STATIC_INCLUDED +#define MYSYS_MY_STATIC_INCLUDED + /* Copyright (C) 2000 MySQL AB This program is free software; you can redistribute it and/or modify @@ -22,35 +25,13 @@ C_MODE_START #include <signal.h> #define MAX_SIGNALS 10 /* Max signals under a dont-allow */ -#define MIN_KEYBLOCK (min(IO_SIZE,1024)) -#define MAX_KEYBLOCK 8192 /* Max keyblocklength == 8*IO_SIZE */ -#define MAX_BLOCK_TYPES MAX_KEYBLOCK/MIN_KEYBLOCK struct st_remember { int number; sig_handler (*func)(int number); }; -/* - Structure that stores information of a allocated memory block - The data is at &struct_adr+sizeof(ALIGN_SIZE(sizeof(struct irem))) - The lspecialvalue is at the previous 4 bytes from this, which may not - necessarily be in the struct if the struct size isn't aligned at a 8 byte - boundary. -*/ - -struct st_irem -{ - struct st_irem *next; /* Linked list of structures */ - struct st_irem *prev; /* Other link */ - char *filename; /* File in which memory was new'ed */ - size_t datasize; /* Size requested */ - uint32 linenum; /* Line number in above file */ - uint32 SpecialValue; /* Underrun marker value */ -}; - - -extern char NEAR curr_dir[FN_REFLEN],NEAR home_dir_buff[FN_REFLEN]; +extern char curr_dir[FN_REFLEN], home_dir_buff[FN_REFLEN]; extern volatile int _my_signals; extern struct st_remember _my_sig_remember[MAX_SIGNALS]; @@ -60,13 +41,8 @@ extern const char *soundex_map; extern USED_MEM* my_once_root_block; extern uint my_once_extra; -extern uchar *sf_min_adress,*sf_max_adress; -extern uint sf_malloc_count; -extern struct st_irem *sf_malloc_root; - extern struct st_my_file_info my_file_info_default[MY_NFILE]; -#if defined(THREAD) && !defined(__WIN__) -extern sigset_t my_signals; /* signals blocked by mf_brkhant */ -#endif C_MODE_END + +#endif /* MYSYS_MY_STATIC_INCLUDED */ diff --git a/mysys/my_sync.c b/mysys/my_sync.c index 9c5fbce7ab7..4d187631786 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -17,8 +17,19 @@ #include "mysys_err.h" #include <errno.h> + ulong my_sync_count; /* Count number of sync calls */ +static void (*before_sync_wait)(void)= 0; +static void (*after_sync_wait)(void)= 0; + +void thr_set_sync_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)) +{ + before_sync_wait= before_wait; + after_sync_wait= after_wait; +} + /* Sync data in file to disk @@ -46,12 +57,19 @@ int my_sync(File fd, myf my_flags) { int res; DBUG_ENTER("my_sync"); + DBUG_PRINT("my",("fd: %d my_flags: %d", fd, my_flags)); if (my_disable_sync) DBUG_RETURN(0); statistic_increment(my_sync_count,&THR_LOCK_open); + + DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags)); + + if (before_sync_wait) + (*before_sync_wait)(); + do { #if defined(F_FULLFSYNC) @@ -70,7 +88,7 @@ int my_sync(File fd, myf my_flags) res= fsync(fd); if (res == -1 && errno == ENOLCK) res= 0; /* Result Bug in Old FreeBSD */ -#elif defined(__WIN__) +#elif defined(_WIN32) res= my_win_fsync(fd); #else #error Cannot find a way to sync a file, durability in danger @@ -83,6 +101,8 @@ int my_sync(File fd, myf my_flags) int er= errno; if (!(my_errno= er)) my_errno= -1; /* Unknown error */ + if (after_sync_wait) + (*after_sync_wait)(); if ((my_flags & MY_IGNORE_BADFD) && (er == EBADF || er == EINVAL || er == EROFS)) { @@ -92,6 +112,11 @@ int my_sync(File fd, myf my_flags) else if (my_flags & MY_WME) my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno); } + else + { + if (after_sync_wait) + (*after_sync_wait)(); + } DBUG_RETURN(res); } /* my_sync */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index cd11618c444..121392be8c3 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +/* Copyright (c) 2000, 2011 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 @@ -22,27 +22,21 @@ #include <m_string.h> #include <signal.h> -#ifdef THREAD -#ifdef USE_TLS pthread_key(struct st_my_thread_var*, THR_KEY_mysys); -#else -pthread_key(struct st_my_thread_var, THR_KEY_mysys); -#endif /* USE_TLS */ -pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open, - THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap, - THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time, - THR_LOCK_myisam_mmap; - -pthread_cond_t THR_COND_threads; +mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, + THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_myisam, THR_LOCK_heap, + THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, + THR_LOCK_myisam_mmap; + +mysql_cond_t THR_COND_threads; uint THR_thread_count= 0; uint my_thread_end_wait_time= 5; #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) -pthread_mutex_t LOCK_localtime_r; +mysql_mutex_t LOCK_localtime_r; #endif -#ifndef HAVE_GETHOSTBYNAME_R -pthread_mutex_t LOCK_gethostbyname_r; +#ifdef _MSC_VER +static void install_sigabrt_handler(); #endif - #ifdef TARGET_OS_LINUX /* @@ -61,39 +55,66 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused))) #endif /* TARGET_OS_LINUX */ +static uint get_thread_lib(void); + +/** True if @c my_thread_global_init() has been called. */ +static my_bool my_thread_global_init_done= 0; + /** - Initialize thread attributes. + Re-initialize components initialized early with @c my_thread_global_init. + Some mutexes were initialized before the instrumentation. + Destroy + create them again, now that the instrumentation + is in place. + This is safe, since this function() is called before creating new threads, + so the mutexes are not in use. */ - -void my_threadattr_global_init(void) +void my_thread_global_reinit(void) { -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP - /* - Set mutex type to "fast" a.k.a "adaptive" + struct st_my_thread_var *tmp; - In this case the thread may steal the mutex from some other thread - that is waiting for the same mutex. This will save us some - context switches but may cause a thread to 'starve forever' while - waiting for the mutex (not likely if the code within the mutex is - short). - */ - pthread_mutexattr_init(&my_fast_mutexattr); /* ?= MY_MUTEX_INIT_FAST */ - pthread_mutexattr_settype(&my_fast_mutexattr, - PTHREAD_MUTEX_ADAPTIVE_NP); -#endif -#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP - /* - Set mutex type to "errorcheck" - */ - pthread_mutexattr_init(&my_errorcheck_mutexattr); - pthread_mutexattr_settype(&my_errorcheck_mutexattr, - PTHREAD_MUTEX_ERRORCHECK); + DBUG_ASSERT(my_thread_global_init_done); + +#ifdef HAVE_PSI_INTERFACE + my_init_mysys_psi_keys(); #endif -} + mysql_mutex_destroy(&THR_LOCK_isam); + mysql_mutex_init(key_THR_LOCK_isam, &THR_LOCK_isam, MY_MUTEX_INIT_SLOW); -static uint get_thread_lib(void); + mysql_mutex_destroy(&THR_LOCK_heap); + mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_net); + mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_myisam); + mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); + + mysql_mutex_destroy(&THR_LOCK_malloc); + mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_open); + mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_charset); + mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_threads); + mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); + + mysql_cond_destroy(&THR_COND_threads); + mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL); + + tmp= my_pthread_getspecific(struct st_my_thread_var*, THR_KEY_mysys); + DBUG_ASSERT(tmp); + + mysql_mutex_destroy(&tmp->mutex); + mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); + + mysql_cond_destroy(&tmp->suspend); + mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); +} /* initialize thread environment @@ -109,14 +130,27 @@ static uint get_thread_lib(void); my_bool my_thread_global_init(void) { int pth_ret; - thd_lib_detected= get_thread_lib(); + + if (my_thread_global_init_done) + return 0; + my_thread_global_init_done= 1; if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) { - fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret); + fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret); return 1; } + mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); + + if (my_thread_init()) + return 1; + + thd_lib_detected= get_thread_lib(); + #ifdef TARGET_OS_LINUX /* BUG#24507: Race conditions inside current NPTL pthread_exit() @@ -144,129 +178,76 @@ my_bool my_thread_global_init(void) } #endif /* TARGET_OS_LINUX */ - /* Mutex used by my_thread_init() and after my_thread_destroy_mutex() */ - my_pthread_mutex_init(&THR_LOCK_threads, MY_MUTEX_INIT_FAST, - "THR_LOCK_threads", MYF_NO_DEADLOCK_DETECTION); - my_pthread_mutex_init(&THR_LOCK_malloc, MY_MUTEX_INIT_FAST, - "THR_LOCK_malloc", MYF_NO_DEADLOCK_DETECTION); - - if (my_thread_init()) - return 1; + mysql_mutex_init(key_THR_LOCK_lock, &THR_LOCK_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_isam, &THR_LOCK_isam, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_THR_LOCK_myisam_mmap, &THR_LOCK_myisam_mmap, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL); - /* Mutex uses by mysys */ - pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW); - pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW); - pthread_mutex_init(&THR_LOCK_myisam_mmap,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST); - pthread_cond_init(&THR_COND_threads, NULL); -#if defined( __WIN__) || defined(OS2) - win_pthread_init(); -#endif #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_localtime_r, &LOCK_localtime_r, MY_MUTEX_INIT_SLOW); #endif -#ifndef HAVE_GETHOSTBYNAME_R - pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW); + +#ifdef _MSC_VER + install_sigabrt_handler(); #endif + return 0; } -/** - Wait for all threads in system to die - @fn my_wait_for_other_threads_to_die() - @param number_of_threads Wait until this number of threads - - @retval 0 Less or equal to number_of_threads left - @retval 1 Wait failed -*/ - -my_bool my_wait_for_other_threads_to_die(uint number_of_threads) +void my_thread_global_end(void) { struct timespec abstime; my_bool all_threads_killed= 1; set_timespec(abstime, my_thread_end_wait_time); - pthread_mutex_lock(&THR_LOCK_threads); - while (THR_thread_count > number_of_threads) + mysql_mutex_lock(&THR_LOCK_threads); + while (THR_thread_count > 0) { - int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads, - &abstime); + int error= mysql_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads, + &abstime); if (error == ETIMEDOUT || error == ETIME) { +#ifdef HAVE_PTHREAD_KILL + /* + We shouldn't give an error here, because if we don't have + pthread_kill(), programs like mysqld can't ensure that all threads + are killed when we enter here. + */ + if (THR_thread_count) + fprintf(stderr, + "Error in my_thread_global_end(): %d threads didn't exit\n", + THR_thread_count); +#endif all_threads_killed= 0; break; } } - pthread_mutex_unlock(&THR_LOCK_threads); - return all_threads_killed; -} - - -/** - End the mysys thread system. Called when ending the last thread -*/ - - -void my_thread_global_end(void) -{ - my_bool all_threads_killed; - - if (!(all_threads_killed= my_wait_for_other_threads_to_die(0))) - { -#ifdef HAVE_PTHREAD_KILL - /* - We shouldn't give an error here, because if we don't have - pthread_kill(), programs like mysqld can't ensure that all threads - are killed when we enter here. - */ - if (THR_thread_count) - fprintf(stderr, - "Error in my_thread_global_end(): %d threads didn't exit\n", - THR_thread_count); -#endif - } + mysql_mutex_unlock(&THR_LOCK_threads); pthread_key_delete(THR_KEY_mysys); + mysql_mutex_destroy(&THR_LOCK_malloc); + mysql_mutex_destroy(&THR_LOCK_open); + mysql_mutex_destroy(&THR_LOCK_lock); + mysql_mutex_destroy(&THR_LOCK_isam); + mysql_mutex_destroy(&THR_LOCK_myisam); + mysql_mutex_destroy(&THR_LOCK_myisam_mmap); + mysql_mutex_destroy(&THR_LOCK_heap); + mysql_mutex_destroy(&THR_LOCK_net); + mysql_mutex_destroy(&THR_LOCK_charset); if (all_threads_killed) { - pthread_mutex_destroy(&THR_LOCK_threads); - pthread_cond_destroy(&THR_COND_threads); - pthread_mutex_destroy(&THR_LOCK_malloc); + mysql_mutex_destroy(&THR_LOCK_threads); + mysql_cond_destroy(&THR_COND_threads); } -} - -/* Free all mutex used by mysys */ - -void my_thread_destroy_mutex(void) -{ - struct st_my_thread_var *tmp; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); - if (tmp) - { - safe_mutex_free_deadlock_data(&tmp->mutex); - } - - pthread_mutex_destroy(&THR_LOCK_open); - pthread_mutex_destroy(&THR_LOCK_lock); - pthread_mutex_destroy(&THR_LOCK_isam); - pthread_mutex_destroy(&THR_LOCK_myisam); - pthread_mutex_destroy(&THR_LOCK_myisam_mmap); - pthread_mutex_destroy(&THR_LOCK_heap); - pthread_mutex_destroy(&THR_LOCK_net); - pthread_mutex_destroy(&THR_LOCK_time); - pthread_mutex_destroy(&THR_LOCK_charset); #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - pthread_mutex_destroy(&LOCK_localtime_r); -#endif -#ifndef HAVE_GETHOSTBYNAME_R - pthread_mutex_destroy(&LOCK_gethostbyname_r); + mysql_mutex_destroy(&LOCK_localtime_r); #endif + + my_thread_global_init_done= 0; } static my_thread_id thread_id= 0; @@ -297,50 +278,40 @@ my_bool my_thread_init(void) my_bool error=0; #ifdef EXTRA_DEBUG_THREADS - fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n", + fprintf(stderr,"my_thread_init(): pthread_self: 0x%lx\n", (ulong) pthread_self()); -#endif +#endif -#if !defined(__WIN__) || defined(USE_TLS) if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) { #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n", (long) pthread_self()); -#endif +#endif goto end; } + +#ifdef _MSC_VER + install_sigabrt_handler(); +#endif + if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp)))) { error= 1; goto end; } pthread_setspecific(THR_KEY_mysys,tmp); - -#else /* defined(__WIN__) && !(defined(USE_TLS) */ - /* - Skip initialization if the thread specific variable is already initialized - */ - if (THR_KEY_mysys.init) - goto end; - tmp= &THR_KEY_mysys; -#endif -#if defined(__WIN__) && defined(EMBEDDED_LIBRARY) - tmp->pthread_self= (pthread_t) getpid(); -#else tmp->pthread_self= pthread_self(); -#endif - my_pthread_mutex_init(&tmp->mutex, MY_MUTEX_INIT_FAST, "mysys_var->mutex", - 0); - pthread_cond_init(&tmp->suspend, NULL); + mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); tmp->stack_ends_here= (char*)&tmp + STACK_DIRECTION * (long)my_thread_stack_size; - pthread_mutex_lock(&THR_LOCK_threads); + mysql_mutex_lock(&THR_LOCK_threads); tmp->id= ++thread_id; ++THR_thread_count; - pthread_mutex_unlock(&THR_LOCK_threads); + mysql_mutex_unlock(&THR_LOCK_threads); tmp->init= 1; #ifndef DBUG_OFF /* Generate unique name for thread */ @@ -372,16 +343,20 @@ void my_thread_end(void) #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_end(): tmp: 0x%lx pthread_self: 0x%lx thread_id: %ld\n", (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L); -#endif - if (tmp && tmp->init) - { +#endif -#if !defined(__bsdi__) && !defined(__OpenBSD__) - /* bsdi and openbsd 3.5 dumps core here */ - pthread_cond_destroy(&tmp->suspend); +#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. + */ + if (PSI_server) + PSI_server->delete_current_thread(); #endif - pthread_mutex_destroy(&tmp->mutex); + if (tmp && tmp->init) + { #if !defined(DBUG_OFF) /* tmp->dbug is allocated inside DBUG library */ if (tmp->dbug) @@ -391,37 +366,25 @@ void my_thread_end(void) tmp->dbug=0; } #endif -#if !defined(__WIN__) || defined(USE_TLS) -#ifndef DBUG_OFF - /* To find bugs when accessing unallocated data */ - bfill(tmp, sizeof(tmp), 0x8F); -#endif - free(tmp); -#else - tmp->init= 0; -#endif + mysql_cond_destroy(&tmp->suspend); + mysql_mutex_destroy(&tmp->mutex); -#if !defined(__WIN__) || defined(USE_TLS) - pthread_setspecific(THR_KEY_mysys,0); -#endif /* Decrement counter for number of running threads. We are using this in my_thread_global_end() to wait until all threads have called my_thread_end and thus freed all memory they have allocated in my_thread_init() and DBUG_xxxx */ - pthread_mutex_lock(&THR_LOCK_threads); + mysql_mutex_lock(&THR_LOCK_threads); DBUG_ASSERT(THR_thread_count != 0); if (--THR_thread_count == 0) - pthread_cond_signal(&THR_COND_threads); - pthread_mutex_unlock(&THR_LOCK_threads); - } - else - { -#if !defined(__WIN__) || defined(USE_TLS) - pthread_setspecific(THR_KEY_mysys,0); -#endif + mysql_cond_signal(&THR_COND_threads); + mysql_mutex_unlock(&THR_LOCK_threads); + + TRASH(tmp, sizeof(*tmp)); + free(tmp); } + pthread_setspecific(THR_KEY_mysys,0); } struct st_my_thread_var *_my_thread_var(void) @@ -429,25 +392,6 @@ struct st_my_thread_var *_my_thread_var(void) return my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); } -#ifndef DBUG_OFF -/* Return pointer to DBUG for holding current state */ - -extern void **my_thread_var_dbug() -{ - struct st_my_thread_var *tmp= - my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); - return tmp && tmp->init ? &tmp->dbug : 0; -} -#endif - -/* Return pointer to mutex_in_use */ - -safe_mutex_t **my_thread_var_mutex_in_use() -{ - struct st_my_thread_var *tmp= - my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); - return tmp ? &tmp->mutex_in_use : 0; -} /**************************************************************************** Get name of current thread. @@ -478,8 +422,25 @@ const char *my_thread_name(void) } return tmp->name; } + +/* Return pointer to DBUG for holding current state */ + +extern void **my_thread_var_dbug() +{ + struct st_my_thread_var *tmp= + my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + return tmp && tmp->init ? &tmp->dbug : 0; +} #endif /* DBUG_OFF */ +/* Return pointer to mutex_in_use */ + +safe_mutex_t **my_thread_var_mutex_in_use() +{ + struct st_my_thread_var *tmp= + my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + return tmp ? &tmp->mutex_in_use : 0; +} static uint get_thread_lib(void) { @@ -496,4 +457,29 @@ static uint get_thread_lib(void) return THD_LIB_OTHER; } -#endif /* THREAD */ +#ifdef _WIN32 +/* + In Visual Studio 2005 and later, default SIGABRT handler will overwrite + any unhandled exception filter set by the application and will try to + call JIT debugger. This is not what we want, this we calling __debugbreak + to stop in debugger, if process is being debugged or to generate + EXCEPTION_BREAKPOINT and then handle_segfault will do its magic. +*/ + +#if (_MSC_VER >= 1400) +static void my_sigabrt_handler(int sig) +{ + __debugbreak(); +} +#endif /*_MSC_VER >=1400 */ + +static void install_sigabrt_handler(void) +{ +#if (_MSC_VER >=1400) + /*abort() should not override our exception filter*/ + _set_abort_behavior(0,_CALL_REPORTFAULT); + signal(SIGABRT,my_sigabrt_handler); +#endif /* _MSC_VER >=1400 */ +} +#endif + diff --git a/mysys/my_timer_cycles.il b/mysys/my_timer_cycles.il new file mode 100644 index 00000000000..2f3f776530b --- /dev/null +++ b/mysys/my_timer_cycles.il @@ -0,0 +1,38 @@ +/* Copyright (C) 2008 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Sun Studio SPARC inline templates for cycle timer */ +/* Sun Studio i386 and x86_64 inline templates for cycle timer */ +/* I didn't say ".volatile" or ".nonvolatile". */ + +.inline my_timer_cycles_il_sparc64,0 +rd %tick,%o0 +.end + +.inline my_timer_cycles_il_sparc32,0 +rd %tick,%o2 +srlx %o2,32,%o0 +sra %o2,0,%o1 +.end + +.inline my_timer_cycles_il_i386,0 +rdtsc +.end + +.inline my_timer_cycles_il_x86_64,0 +rdtsc +shlq $32,%rdx +orq %rdx,%rax +.end diff --git a/mysys/my_uuid.c b/mysys/my_uuid.c index 3df2dda2af5..ab1b259ae0f 100644 --- a/mysys/my_uuid.c +++ b/mysys/my_uuid.c @@ -50,9 +50,7 @@ static ulonglong uuid_time= 0; static longlong interval_timer_offset; static uchar uuid_suffix[2+6]; /* clock_seq and node */ -#ifdef THREAD -static pthread_mutex_t LOCK_uuid_generator; -#endif +static mysql_mutex_t LOCK_uuid_generator; /* Number of 100-nanosecond intervals between @@ -117,7 +115,7 @@ void my_uuid_init(ulong seed1, ulong seed2) } my_rnd_init(&uuid_rand, (ulong) (seed1 + now), (ulong) (now/2+ getpid())); set_clock_seq(); - pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_uuid_generator, &LOCK_uuid_generator, MY_MUTEX_INIT_FAST); } @@ -136,7 +134,7 @@ void my_uuid(uchar *to) DBUG_ASSERT(my_uuid_inited); - pthread_mutex_lock(&LOCK_uuid_generator); + mysql_mutex_lock(&LOCK_uuid_generator); tv= my_interval_timer()/100 + interval_timer_offset + nanoseq; if (likely(tv > uuid_time)) @@ -197,7 +195,7 @@ void my_uuid(uchar *to) } uuid_time=tv; - pthread_mutex_unlock(&LOCK_uuid_generator); + mysql_mutex_unlock(&LOCK_uuid_generator); time_low= (uint32) (tv & 0xFFFFFFFF); time_mid= (uint16) ((tv >> 32) & 0xFFFF); @@ -242,6 +240,6 @@ void my_uuid_end() if (my_uuid_inited) { my_uuid_inited= 0; - pthread_mutex_destroy(&LOCK_uuid_generator); + mysql_mutex_destroy(&LOCK_uuid_generator); } } diff --git a/mysys/my_vle.c b/mysys/my_vle.c deleted file mode 100644 index 09f297eb553..00000000000 --- a/mysys/my_vle.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 2005 MySQL AB - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - Variable length encoding. - - A method to store an arbitrary-size non-negative integer. We let the - most significant bit of the number indicate that the next byte - should be contatenated to form the real number. -*/ - -#include "my_vle.h" - -/* - Function to encode an unsigned long as VLE. The bytes for the VLE - will be written to the location pointed to by 'out'. The maximum - number of bytes written will be 'max'. - - PARAMETERS - - out Pointer to beginning of where to store VLE bytes. - max Maximum number of bytes to write. - n Number to encode. - - RETURN VALUE - On success, one past the end of the array containing the VLE - bytes. On failure, the 'out' pointer is returned. -*/ - -uchar* -my_vle_encode(uchar* out, size_t max, ulong n) -{ - uchar buf[my_vle_sizeof(n)]; - uchar *ptr= buf; - size_t len; - - do - { - *ptr++= (uchar) (n & 0x7F); - n>>= 7; - } - while (n > 0); - - len= ptr - buf; - - if (len <= max) - { - /* - The bytes are stored in reverse order in 'buf'. Let's write them - in correct order to the output buffer and set the MSB at the - same time. - */ - while (ptr-- > buf) - { - uchar v= *ptr; - if (ptr > buf) - v|= 0x80; - *out++= v; - } - } - - return out; -} - -/* - Function to decode a VLE representation of an integral value. - - - PARAMETERS - - result_ptr Pointer to an unsigned long where the value will be written. - vle Pointer to the VLE bytes. - - RETURN VALUE - - One-past the end of the VLE bytes. The routine will never read - more than sizeof(*result_ptr) + 1 bytes. -*/ - -uchar const* -my_vle_decode(ulong *result_ptr, uchar const *vle) -{ - ulong result= 0; - size_t cnt= 1; - - do - { - result<<= 7; - result|= (*vle & 0x7F); - } - while ((*vle++ & 0x80) && ++cnt <= sizeof(*result_ptr) + 1); - - if (cnt <= sizeof(*result_ptr) + 1) - *result_ptr= result; - - return vle; -} diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index a6483ae61a3..bed64230aea 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -16,13 +16,11 @@ /***************************************************************************** ** The following is a simple implementation of posix conditions *****************************************************************************/ +#if defined(_WIN32) -#include <my_global.h> #undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ #include "mysys_priv.h" -#if defined(THREAD) && defined(__WIN__) #include <m_string.h> -#undef getpid #include <process.h> #include <sys/timeb.h> @@ -157,29 +155,9 @@ static int legacy_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime) { int result; - DWORD timeout; - long long timeout_us; - my_hrtime_t now; - my_hrtime_t then; - if( abstime != NULL ) - { - now= my_hrtime(); - then.val= 1000000ULL*abstime->tv_sec + abstime->tv_nsec/1000; - timeout_us= then.val - now.val; - - if (timeout_us < 0) - timeout= 0; - else if (timeout_us > 1000ULL*INFINITE) - timeout= INFINITE; - else - timeout= (DWORD)(timeout_us/1000); - } - else - { - /* No time specified; don't expire */ - timeout= INFINITE; - } + DWORD timeout; + timeout= get_milliseconds(abstime); /* Block access if previous broadcast hasn't finished. This is just for safety and should normally not @@ -335,7 +313,6 @@ int pthread_attr_init(pthread_attr_t *connect_att) { connect_att->dwStackSize = 0; connect_att->dwCreatingFlag = 0; - connect_att->priority = 0; return 0; } @@ -345,12 +322,6 @@ int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack) return 0; } -int pthread_attr_setprio(pthread_attr_t *connect_att,int priority) -{ - connect_att->priority=priority; - return 0; -} - int pthread_attr_destroy(pthread_attr_t *connect_att) { bzero((uchar*) connect_att,sizeof(*connect_att)); diff --git a/mysys/my_windac.c b/mysys/my_windac.c index f846853f7be..0c924188623 100644 --- a/mysys/my_windac.c +++ b/mysys/my_windac.c @@ -194,8 +194,8 @@ error: FreeSid(everyone_sid); if (htoken) CloseHandle(htoken); - my_free((uchar*) sa, MYF(MY_ALLOW_ZERO_PTR)); - my_free((uchar*) dacl, MYF(MY_ALLOW_ZERO_PTR)); + my_free(sa); + my_free(dacl); *psa= 0; return 1; } @@ -215,8 +215,8 @@ void my_security_attr_free(SECURITY_ATTRIBUTES *sa) My_security_attr *attr= (My_security_attr*) (((char*)sa) + ALIGN_SIZE(sizeof(*sa))); FreeSid(attr->everyone_sid); - my_free((uchar*) attr->dacl, MYF(0)); - my_free((uchar*) sa, MYF(0)); + my_free(attr->dacl); + my_free(sa); } } diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c index f63c35ba47b..4d80d774dad 100644 --- a/mysys/my_winfile.c +++ b/mysys/my_winfile.c @@ -57,7 +57,7 @@ File my_open_osfhandle(HANDLE handle, int oflag) uint i; DBUG_ENTER("my_open_osfhandle"); - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); for(i= MY_FILE_MIN; i < my_file_limit;i++) { if(my_file_info[i].fhandle == 0) @@ -70,7 +70,7 @@ File my_open_osfhandle(HANDLE handle, int oflag) break; } } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); if(offset == -1) errno= EMFILE; /* to many file handles open */ DBUG_RETURN(offset); diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index 5fbad39597c..54b8463fe0b 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -14,34 +14,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /***************************************************************************** -** Simulation of posix threads calls for WIN95 and NT +** Simulation of posix threads calls for Windows *****************************************************************************/ - +#if defined (_WIN32) /* SAFE_MUTEX will not work until the thread structure is up to date */ -#include <my_global.h> -#undef SAFE_MUTEX +#undef SAFE_MUTEX #include "mysys_priv.h" -#if defined(THREAD) && defined(__WIN__) -#include <m_string.h> -#undef getpid #include <process.h> +#include <signal.h> -static pthread_mutex_t THR_LOCK_thread; +static void install_sigabrt_handler(void); -struct pthread_map +struct thread_start_parameter { - HANDLE pthreadself; pthread_handler func; - void *param; + void *arg; }; -void win_pthread_init(void) -{ - pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST); -} - - /** Adapter to @c pthread_mutex_trylock() @@ -63,91 +53,101 @@ win_pthread_mutex_trylock(pthread_mutex_t *mutex) return EBUSY; } - -/* -** We have tried to use '_beginthreadex' instead of '_beginthread' here -** but in this case the program leaks about 512 characters for each -** created thread ! -** As we want to save the created thread handler for other threads to -** use and to be returned by pthread_self() (instead of the Win32 pseudo -** handler), we have to go trough pthread_start() to catch the returned handler -** in the new thread. -*/ - -pthread_handler_t pthread_start(void *param) +static unsigned int __stdcall pthread_start(void *p) { - pthread_handler func=((struct pthread_map *) param)->func; - void *func_param=((struct pthread_map *) param)->param; - void *result; - my_thread_init(); /* Will always succeed in windows */ - pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beginthread to return */ - win_pthread_self=((struct pthread_map *) param)->pthreadself; - pthread_mutex_unlock(&THR_LOCK_thread); - free((char*) param); /* Free param from create */ - result= (void*) (*func)(func_param); - my_thread_end(); - pthread_exit(result); - return 0; /* Safety */ + struct thread_start_parameter *par= (struct thread_start_parameter *)p; + pthread_handler func= par->func; + void *arg= par->arg; + free(p); + (*func)(arg); + return 0; } -int pthread_create(pthread_t *thread_id, pthread_attr_t *attr, - pthread_handler func, void *param) +int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr, + pthread_handler func, void *param) { - HANDLE hThread; - struct pthread_map *map; - DWORD StackSize= 0; - int priority= 0; + uintptr_t handle; + struct thread_start_parameter *par; + unsigned int stack_size; DBUG_ENTER("pthread_create"); - if (!(map=malloc(sizeof(*map)))) - DBUG_RETURN(-1); - map->func=func; - map->param=param; - if (attr != NULL) - { - StackSize= attr->dwStackSize; - priority= attr->priority; - } - if (StackSize == 0) - StackSize= PTHREAD_STACK_MIN; - pthread_mutex_lock(&THR_LOCK_thread); -#ifdef __BORLANDC__ - hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start, - StackSize, (void*) map); -#else - hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start, - StackSize, (void*) map); -#endif - DBUG_PRINT("info", ("hThread=%lu",(long) hThread)); - *thread_id=map->pthreadself=hThread; - pthread_mutex_unlock(&THR_LOCK_thread); + par= (struct thread_start_parameter *)malloc(sizeof(*par)); + if (!par) + goto error_return; - if (hThread == (HANDLE) -1) - { - int error=errno; - DBUG_PRINT("error", - ("Can't create thread to handle request (error %d)",error)); - DBUG_RETURN(error ? error : -1); - } - VOID(SetThreadPriority(hThread, priority)) ; + par->func= func; + par->arg= param; + stack_size= attr?attr->dwStackSize:0; + + handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id); + if (!handle) + goto error_return; + DBUG_PRINT("info", ("thread id=%u",*thread_id)); + + /* Do not need thread handle, close it */ + CloseHandle((HANDLE)handle); DBUG_RETURN(0); + +error_return: + DBUG_PRINT("error", + ("Can't create thread to handle request (error %d)",errno)); + DBUG_RETURN(-1); } void pthread_exit(void *a) { - _endthread(); + _endthreadex(0); } -/* This is neaded to get the macro pthread_setspecific to work */ - -int win_pthread_setspecific(void *a,void *b,uint length) +int pthread_join(pthread_t thread, void **value_ptr) { - memcpy(a,b,length); + DWORD ret; + HANDLE handle; + + handle= OpenThread(SYNCHRONIZE, FALSE, thread); + if (!handle) + { + errno= EINVAL; + goto error_return; + } + + ret= WaitForSingleObject(handle, INFINITE); + + if(ret != WAIT_OBJECT_0) + { + errno= EINVAL; + goto error_return; + } + + CloseHandle(handle); return 0; + +error_return: + if(handle) + CloseHandle(handle); + return -1; } +int pthread_cancel(pthread_t thread) +{ + + HANDLE handle= 0; + BOOL ok= FALSE; + + handle= OpenThread(THREAD_TERMINATE, FALSE, thread); + if (handle) + { + ok= TerminateThread(handle,0); + CloseHandle(handle); + } + if (ok) + return 0; + + errno= EINVAL; + return -1; +} /* One time initialization. For simplicity, we assume initializer thread @@ -190,5 +190,4 @@ int my_pthread_once(my_pthread_once_t *once_control, } return 0; } - #endif diff --git a/mysys/my_write.c b/mysys/my_write.c index be493049d5c..46b0d749944 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -20,14 +20,14 @@ /* Write a chunk of bytes to a file */ -size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) +size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { size_t writtenbytes, written; uint errors; DBUG_ENTER("my_write"); - DBUG_PRINT("my",("fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); - errors=0; written=0; + DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", + Filedes, Buffer, (ulong) Count, MyFlags)); + errors= 0; written= 0; /* The behavior of write(fd, buf, 0) is not portable */ if (unlikely(!Count)) @@ -57,10 +57,9 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) DBUG_PRINT("error",("Write only %ld bytes, error: %d", (long) writtenbytes, my_errno)); #ifndef NO_BACKGROUND -#ifdef THREAD if (my_thread_var->abort) MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ -#endif + if ((my_errno == ENOSPC || my_errno == EDQUOT) && (MyFlags & MY_WAIT_IF_FULL)) { diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 6d39999aa86..2f669878f49 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -24,14 +24,50 @@ #include <sys/resource.h> #endif -#ifdef THREAD #include <my_pthread.h> -extern pthread_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache; -extern pthread_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net; -extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time; -#else -#include <my_no_pthread.h> -#endif + +#ifdef HAVE_PSI_INTERFACE + +#if !defined(HAVE_PREAD) && !defined(_WIN32) +extern PSI_mutex_key key_my_file_info_mutex; +#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ + +#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) +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_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, + key_THR_LOCK_isam, 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; + +extern PSI_cond_key key_COND_alarm, 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_rwlock_key key_SAFEHASH_mutex; + +#endif /* HAVE_PSI_INTERFACE */ + +extern mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache; +extern mysql_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net; +extern mysql_mutex_t THR_LOCK_charset; + +#include <mysql/psi/mysql_file.h> + +#ifdef HAVE_PSI_INTERFACE +#ifdef HUGETLB_USE_PROC_MEMINFO +extern PSI_file_key key_file_proc_meminfo; +#endif /* HUGETLB_USE_PROC_MEMINFO */ +extern PSI_file_key key_file_charset, key_file_cnf; +#endif /* HAVE_PSI_INTERFACE */ /* @@ -43,29 +79,28 @@ extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time; #endif void my_error_unregister_all(void); -void my_thread_destroy_mutex(void); -my_bool my_wait_for_other_threads_to_die(uint number_of_threads); -
-#ifdef _WIN32
-/* my_winfile.c exports, should not be used outside mysys */
-extern File my_win_open(const char *path, int oflag);
-extern int my_win_close(File fd);
-extern size_t my_win_read(File fd, uchar *buffer, size_t count);
-extern size_t my_win_write(File fd, const uchar *buffer, size_t count);
-extern size_t my_win_pread(File fd, uchar *buffer, size_t count,
- my_off_t offset);
-extern size_t my_win_pwrite(File fd, const uchar *buffer, size_t count,
- my_off_t offset);
-extern my_off_t my_win_lseek(File fd, my_off_t pos, int whence);
-extern int my_win_chsize(File fd, my_off_t newlength);
-extern FILE* my_win_fopen(const char *filename, const char *type);
-extern File my_win_fclose(FILE *file);
-extern File my_win_fileno(FILE *file);
-extern FILE* my_win_fdopen(File Filedes, const char *type);
-extern int my_win_stat(const char *path, struct _stat64 *buf);
-extern int my_win_fstat(File fd, struct _stat64 *buf);
-extern int my_win_fsync(File fd);
-extern File my_win_dup(File fd);
-extern File my_win_sopen(const char *path, int oflag, int shflag, int perm);
-extern File my_open_osfhandle(HANDLE handle, int oflag);
+ +#ifdef _WIN32 +#include <sys/stat.h> +/* my_winfile.c exports, should not be used outside mysys */ +extern File my_win_open(const char *path, int oflag); +extern int my_win_close(File fd); +extern size_t my_win_read(File fd, uchar *buffer, size_t count); +extern size_t my_win_write(File fd, const uchar *buffer, size_t count); +extern size_t my_win_pread(File fd, uchar *buffer, size_t count, + my_off_t offset); +extern size_t my_win_pwrite(File fd, const uchar *buffer, size_t count, + my_off_t offset); +extern my_off_t my_win_lseek(File fd, my_off_t pos, int whence); +extern int my_win_chsize(File fd, my_off_t newlength); +extern FILE* my_win_fopen(const char *filename, const char *type); +extern File my_win_fclose(FILE *file); +extern File my_win_fileno(FILE *file); +extern FILE* my_win_fdopen(File Filedes, const char *type); +extern int my_win_stat(const char *path, struct _stati64 *buf); +extern int my_win_fstat(File fd, struct _stati64 *buf); +extern int my_win_fsync(File fd); +extern File my_win_dup(File fd); +extern File my_win_sopen(const char *path, int oflag, int shflag, int perm); +extern File my_open_osfhandle(HANDLE handle, int oflag); #endif diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c index 24ab6a1ea9c..dcafe13291d 100644 --- a/mysys/ptr_cmp.c +++ b/mysys/ptr_cmp.c @@ -22,14 +22,40 @@ #include "mysys_priv.h" #include <myisampack.h> +#ifdef __sun +/* + * On Solaris, memcmp() is normally faster than the unrolled ptr_compare_N + * functions, as memcmp() is usually a platform-specific implementation + * written in assembler, provided in /usr/lib/libc/libc_hwcap*.so.1. + * This 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. + */ + +#include <string.h> + +static int native_compare(size_t *length, unsigned char **a, unsigned char **b) +{ + return memcmp(*a, *b, *length); +} + +#else /* __sun */ + 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 __sun +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) @@ -42,6 +68,7 @@ qsort2_cmp get_ptr_compare (size_t size) } return 0; /* Impossible */ } +#endif /* __sun */ /* @@ -51,6 +78,8 @@ qsort2_cmp get_ptr_compare (size_t size) #define cmp(N) if (first[N] != last[N]) return (int) first[N] - (int) last[N] +#ifndef __sun + static int ptr_compare(size_t *compare_length, uchar **a, uchar **b) { reg3 int length= *compare_length; @@ -153,6 +182,8 @@ static int ptr_compare_3(size_t *compare_length,uchar **a, uchar **b) return (0); } +#endif /* !__sun */ + void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos) { switch (pack_length) { diff --git a/mysys/queues.c b/mysys/queues.c index d1f2dab18bc..418163d7c58 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -176,11 +176,8 @@ int resize_queue(QUEUE *queue, uint max_elements) void delete_queue(QUEUE *queue) { DBUG_ENTER("delete_queue"); - if (queue->root) - { - my_free((uchar*) queue->root,MYF(0)); - queue->root=0; /* Allow multiple calls */ - } + my_free(queue->root); + queue->root=0; /* Allow multiple calls */ DBUG_VOID_RETURN; } diff --git a/mysys/rijndael.c b/mysys/rijndael.c index 2b12753c4e5..2d622efad82 100644 --- a/mysys/rijndael.c +++ b/mysys/rijndael.c @@ -32,22 +32,6 @@ #define FULL_UNROLL */ - -#ifdef NOT_USED -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -#endif - - static const uint32 Te0[256]= { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c deleted file mode 100644 index deb6c73327e..00000000000 --- a/mysys/safemalloc.c +++ /dev/null @@ -1,584 +0,0 @@ -/* Copyright (C) 2000-2003 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - * Memory sub-system, written by Bjorn Benson - Fixed to use my_sys scheme by Michael Widenius - - [This posting refers to an article entitled "oops, corrupted memory - again!" in net.lang.c. I am posting it here because it is source.] - - My tool for approaching this problem is to build another level of data - abstraction on top of malloc() and free() that implements some checking. - This does a number of things for you: - - Checks for overruns and underruns on allocated data - - Keeps track of where in the program the memory was malloc'ed - - Reports on pieces of memory that were not free'ed - - Records some statistics such as maximum memory used - - Marks newly malloc'ed and newly free'ed memory with special values - You can use this scheme to: - - Find bugs such as overrun, underrun, etc because you know where - a piece of data was malloc'ed and where it was free'ed - - Find bugs where memory was not free'ed - - Find bugs where newly malloc'ed memory is used without initializing - - Find bugs where newly free'ed memory is still used - - Determine how much memory your program really uses - - and other things - - To implement my scheme you must have a C compiler that has __LINE__ and - __FILE__ macros. If your compiler doesn't have these then (a) buy another: - compilers that do are available on UNIX 4.2bsd based systems and the PC, - and probably on other machines; or (b) change my scheme somehow. I have - recomendations on both these points if you would like them (e-mail please). - - There are 4 functions in my package: - char *NEW( uSize ) Allocate memory of uSize bytes - (equivalent to malloc()) - char *REA( pPtr, uSize) Allocate memory of uSize bytes, move data and - free pPtr. - (equivalent to realloc()) - FREE( pPtr ) Free memory allocated by NEW - (equivalent to free()) - TERMINATE(file,flag) End system, report errors and stats on file - I personally use two more functions, but have not included them here: - char *STRSAVE( sPtr ) Save a copy of the string in dynamic memory - char *RENEW( pPtr, uSize ) - (equivalent to realloc()) - -*/ - -#ifndef SAFEMALLOC -#define SAFEMALLOC 1 /* Get protos from my_sys */ -#endif - -#include "mysys_priv.h" -#include <m_string.h> -#include "my_static.h" -#include "mysys_err.h" - -ulonglong sf_malloc_mem_limit= ~(ulonglong)0; - -#ifndef PEDANTIC_SAFEMALLOC -/* - Set to 1 after TERMINATE() if we had to fiddle with sf_malloc_count and - the linked list of blocks so that _sanity() will not fuss when it - is not supposed to -*/ -static int sf_malloc_tampered= 0; -#endif - - - /* Static functions prototypes */ - -static int check_ptr(const char *where, uchar *ptr, const char *sFile, - uint uLine); -static int _checkchunk(struct st_irem *pRec, const char *sFile, uint uLine); - -/* - Note: We only fill up the allocated block. This do not include - malloc() roundoff or the extra space required by the irem - structures. -*/ - -/* - NEW'ed memory is filled with this value so that references to it will - end up being very strange. -*/ -#define ALLOC_VAL (uchar) 0xA5 -/* - FEEE'ed memory is filled with this value so that references to it will - end up being very strange. -*/ -#define FREE_VAL (uchar) 0x8F -#define MAGICKEY 0x14235296 /* A magic value for underrun key */ - -/* - Warning: do not change the MAGICEND? values to something with the - high bit set. Various C compilers (like the 4.2bsd one) do not do - the sign extension right later on in this code and you will get - erroneous errors. -*/ - -#define MAGICEND0 0x68 /* Magic values for overrun keys */ -#define MAGICEND1 0x34 /* " */ -#define MAGICEND2 0x7A /* " */ -#define MAGICEND3 0x15 /* " */ - - -/* Allocate some memory. */ - -void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) -{ - struct st_irem *irem; - uchar *data; - DBUG_ENTER("_mymalloc"); - DBUG_PRINT("enter",("Size: %lu Total alloc: %lu", (ulong) size, - (ulong) sf_malloc_cur_memory)); - - if (!sf_malloc_quick) - (void) _sanity (filename, lineno); - - if (size + sf_malloc_cur_memory > sf_malloc_mem_limit) - irem= 0; - else - { - /* Allocate the physical memory */ - irem= (struct st_irem *) malloc (ALIGN_SIZE(sizeof(struct st_irem)) + - sf_malloc_prehunc + - size + /* size requested */ - 4 + /* overrun mark */ - sf_malloc_endhunc); - DBUG_EXECUTE_IF("simulate_out_of_memory", - { - free(irem); - irem= NULL; - }); - } - /* Check if there isn't anymore memory avaiable */ - if (!irem) - { - if (MyFlags & MY_FAE) - error_handler_hook=fatal_error_handler_hook; - if (MyFlags & (MY_FAE+MY_WME)) - { - char buff[256]; - my_errno=errno; - sprintf(buff,"Out of memory at line %d, '%s'", lineno, filename); - my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH)); - sprintf(buff,"needed %lu byte (%luk), memory in use: %lu bytes (%luk)", - (ulong) size, (ulong) (size + 1023L) / 1024L, - (ulong) sf_malloc_max_memory, - (ulong) (sf_malloc_max_memory + 1023L) / 1024L); - my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH)); - } - DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'", - (ulong) sf_malloc_max_memory,lineno, filename)); - DBUG_EXECUTE_IF("simulate_out_of_memory", - DBUG_SET("-d,simulate_out_of_memory");); - if (MyFlags & MY_FAE) - exit(1); - DBUG_RETURN ((void*) 0); - } - - /* Fill up the structure */ - data= (((uchar*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + - sf_malloc_prehunc); - *((uint32*) (data-sizeof(uint32)))= MAGICKEY; - data[size + 0]= MAGICEND0; - data[size + 1]= MAGICEND1; - data[size + 2]= MAGICEND2; - data[size + 3]= MAGICEND3; - irem->filename= (char *) filename; - irem->linenum= lineno; - irem->datasize= size; - irem->prev= NULL; - - /* Add this remember structure to the linked list */ - pthread_mutex_lock(&THR_LOCK_malloc); - if ((irem->next= sf_malloc_root)) - sf_malloc_root->prev= irem; - sf_malloc_root= irem; - - /* Keep the statistics */ - sf_malloc_cur_memory+= size; - if (sf_malloc_cur_memory > sf_malloc_max_memory) - sf_malloc_max_memory= sf_malloc_cur_memory; - sf_malloc_count++; - pthread_mutex_unlock(&THR_LOCK_malloc); - - MEM_CHECK_ADDRESSABLE(data, size); - /* Set the memory to the aribtrary wierd value */ - if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick) - bfill(data, size, (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL)); - if (!(MyFlags & MY_ZEROFILL)) - MEM_UNDEFINED(data, size); - /* Return a pointer to the real data */ - DBUG_PRINT("exit",("ptr: %p", data)); - if (sf_min_adress > data) - sf_min_adress= data; - if (sf_max_adress < data) - sf_max_adress= data; - DBUG_RETURN((void*) data); -} - - -/* - Allocate some new memory and move old memoryblock there. - Free then old memoryblock -*/ - -void *_myrealloc(register void *ptr, register size_t size, - const char *filename, uint lineno, myf MyFlags) -{ - struct st_irem *irem; - char *data; - DBUG_ENTER("_myrealloc"); - DBUG_PRINT("my",("ptr: 0x%lx size: %lu my_flags: %d", (long) ptr, - (ulong) size, MyFlags)); - - if (!ptr && (MyFlags & MY_ALLOW_ZERO_PTR)) - DBUG_RETURN(_mymalloc(size, filename, lineno, MyFlags)); - - if (!sf_malloc_quick) - (void) _sanity (filename, lineno); - - if (check_ptr("Reallocating", (uchar*) ptr, filename, lineno)) - DBUG_RETURN((uchar*) NULL); - - irem= (struct st_irem *) (((char*) ptr) - ALIGN_SIZE(sizeof(struct st_irem))- - sf_malloc_prehunc); - if (*((uint32*) (((char*) ptr)- sizeof(uint32))) != MAGICKEY) - { - fprintf(stderr, "Error: Reallocating unallocated data at line %d, '%s'\n", - lineno, filename); - DBUG_PRINT("safe",("Reallocating unallocated data at line %d, '%s'", - lineno, filename)); - (void) fflush(stderr); - DBUG_RETURN((uchar*) NULL); - } - DBUG_PRINT("my", ("old_size: %lu -> new_size: %lu", - (ulong) irem->datasize, (ulong) size)); - - if ((data= _mymalloc(size,filename,lineno,MyFlags))) /* Allocate new area */ - { - size=min(size, irem->datasize); /* Move as much as possibly */ - memcpy((uchar*) data, ptr, (size_t) size); /* Copy old data */ - _myfree(ptr, filename, lineno, 0); /* Free not needed area */ - } - else - { - if (MyFlags & MY_HOLD_ON_ERROR) - DBUG_RETURN(ptr); - if (MyFlags & MY_FREE_ON_ERROR) - _myfree(ptr, filename, lineno, 0); - } - DBUG_RETURN(data); -} /* _myrealloc */ - - -/* Deallocate some memory. */ - -void _myfree(void *ptr, const char *filename, uint lineno, myf myflags) -{ - struct st_irem *irem; - DBUG_ENTER("_myfree"); - DBUG_PRINT("enter",("ptr: %p", ptr)); - - if (!sf_malloc_quick) - (void) _sanity (filename, lineno); - - if ((!ptr && (myflags & MY_ALLOW_ZERO_PTR)) || - check_ptr("Freeing",(uchar*) ptr,filename,lineno)) - DBUG_VOID_RETURN; - - /* Calculate the address of the remember structure */ - irem= (struct st_irem *) ((char*) ptr- ALIGN_SIZE(sizeof(struct st_irem))- - sf_malloc_prehunc); - - if (sf_malloc_quick) - (void) _checkchunk(irem, filename, lineno); - - /* - Check to make sure that we have a real remember structure. - Note: this test could fail for four reasons: - (1) The memory was already free'ed - (2) The memory was never new'ed - (3) There was an underrun - (4) A stray pointer hit this location - */ - - if (*((uint32*) ((char*) ptr- sizeof(uint32))) != MAGICKEY) - { - fprintf(stderr, "Error: Freeing unallocated data at line %d, '%s'\n", - lineno, filename); - DBUG_PRINT("safe",("Unallocated data at line %d, '%s'",lineno,filename)); - (void) fflush(stderr); - DBUG_VOID_RETURN; - } - - /* Remove this structure from the linked list */ - pthread_mutex_lock(&THR_LOCK_malloc); - if (irem->prev) - irem->prev->next= irem->next; - else - sf_malloc_root= irem->next; - - if (irem->next) - irem->next->prev= irem->prev; - /* Handle the statistics */ - sf_malloc_cur_memory-= irem->datasize; - sf_malloc_count--; - pthread_mutex_unlock(&THR_LOCK_malloc); - DBUG_PRINT("info", ("bytes freed: %ld", (ulong) irem->datasize)); - -#ifndef HAVE_valgrind - /* Mark this data as free'ed */ - if (!sf_malloc_quick) - bfill(ptr, irem->datasize, (pchar) FREE_VAL); -#endif - MEM_NOACCESS(ptr, irem->datasize); - *((uint32*) ((char*) ptr- sizeof(uint32)))= ~MAGICKEY; - MEM_NOACCESS((char*) ptr - sizeof(uint32), sizeof(uint32)); - /* Actually free the memory */ - free((char*) irem); - DBUG_VOID_RETURN; -} - - /* Check if we have a wrong pointer */ - -static int check_ptr(const char *where, uchar *ptr, const char *filename, - uint lineno) -{ - if (!ptr) - { - fprintf(stderr, "Error: %s NULL pointer at line %d, '%s'\n", - where,lineno, filename); - DBUG_PRINT("safe",("Null pointer at line %d '%s'", lineno, filename)); - (void) fflush(stderr); - return 1; - } -#ifndef _MSC_VER - if ((long) ptr & (ALIGN_SIZE(1)-1)) - { - fprintf(stderr, "Error: %s wrong aligned pointer at line %d, '%s'\n", - where,lineno, filename); - DBUG_PRINT("safe",("Wrong aligned pointer at line %d, '%s'", - lineno,filename)); - (void) fflush(stderr); - return 1; - } -#endif - if (ptr < sf_min_adress || ptr > sf_max_adress) - { - fprintf(stderr, "Error: %s pointer out of range at line %d, '%s'\n", - where,lineno, filename); - DBUG_PRINT("safe",("Pointer out of range at line %d '%s'", - lineno,filename)); - (void) fflush(stderr); - return 1; - } - return 0; -} - - -/* - Report on all the memory pieces that have not been free'ed - - SYNOPSIS - TERMINATE() - file Write output to this file - flag If <> 0, also write statistics - */ - -void TERMINATE(FILE *file, uint flag) -{ - struct st_irem *irem; - DBUG_ENTER("TERMINATE"); - pthread_mutex_lock(&THR_LOCK_malloc); - - /* - Report the difference between number of calls to - NEW and the number of calls to FREE. >0 means more - NEWs than FREEs. <0, etc. - */ - - if (sf_malloc_count) - { - if (file) - { - fprintf(file, "Warning: Not freed memory segments: %u\n", sf_malloc_count); - (void) fflush(file); - } - DBUG_PRINT("safe",("sf_malloc_count: %u", sf_malloc_count)); - } - - /* - Report on all the memory that was allocated with NEW - but not free'ed with FREE. - */ - - if ((irem= sf_malloc_root)) - { - if (file) - { - fprintf(file, "Warning: Memory that was not free'ed (%lu bytes):\n", - (ulong) sf_malloc_cur_memory); - (void) fflush(file); - } - DBUG_PRINT("safe",("Memory that was not free'ed (%lu bytes):", - (ulong) sf_malloc_cur_memory)); - while (irem) - { - char *data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + - sf_malloc_prehunc); - if (file) - { - fprintf(file, - "\t%6lu bytes at %p, allocated at line %4u in '%s'", - (ulong) irem->datasize, data, irem->linenum, irem->filename); - fprintf(file, "\n"); - (void) fflush(file); - } - DBUG_PRINT("safe", - ("%6lu bytes at %p, allocated at line %4d in '%s'", - (ulong) irem->datasize, - data, irem->linenum, irem->filename)); - irem= irem->next; - } - } - /* Report the memory usage statistics */ - if (file && flag) - { - fprintf(file, "Maximum memory usage: %lu bytes (%luk)\n", - (ulong) sf_malloc_max_memory, - (ulong) (sf_malloc_max_memory + 1023L) / 1024L); - (void) fflush(file); - } - DBUG_PRINT("safe",("Maximum memory usage: %lu bytes (%luk)", - (ulong) sf_malloc_max_memory, - (ulong) (sf_malloc_max_memory + 1023L) /1024L)); - pthread_mutex_unlock(&THR_LOCK_malloc); - DBUG_VOID_RETURN; -} - - -/* - Report where a piece of memory was allocated - - This is useful to call from withing a debugger -*/ - -void sf_malloc_report_allocated(void *memory) -{ - struct st_irem *irem; - for (irem= sf_malloc_root ; irem ; irem=irem->next) - { - char *data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + - sf_malloc_prehunc); - if (data <= (char*) memory && (char*) memory <= data + irem->datasize) - { - printf("%lu bytes at %p, allocated at line %u in '%s'\n", - (ulong) irem->datasize, data, irem->linenum, irem->filename); - break; - } - } -} - - /* Returns 0 if chunk is ok */ - -static int _checkchunk(register struct st_irem *irem, const char *filename, - uint lineno) -{ - int flag=0; - char *magicp, *data; - - data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + - sf_malloc_prehunc); - /* Check for a possible underrun */ - if (*((uint32*) (data- sizeof(uint32))) != MAGICKEY) - { - fprintf(stderr, "Error: Memory allocated at %s:%d was underrun,", - irem->filename, irem->linenum); - fprintf(stderr, " discovered at %s:%d\n", filename, lineno); - (void) fflush(stderr); - DBUG_PRINT("safe",("Underrun at %p, allocated at %s:%d", - data, irem->filename, irem->linenum)); - flag=1; - } - - /* Check for a possible overrun */ - magicp= data + irem->datasize; - if (*magicp++ != MAGICEND0 || - *magicp++ != MAGICEND1 || - *magicp++ != MAGICEND2 || - *magicp++ != MAGICEND3) - { - fprintf(stderr, "Error: Memory allocated at %s:%d was overrun,", - irem->filename, irem->linenum); - fprintf(stderr, " discovered at '%s:%d'\n", filename, lineno); - (void) fflush(stderr); - DBUG_PRINT("safe",("Overrun at %p, allocated at %s:%d", - data, irem->filename, irem->linenum)); - flag=1; - } - return(flag); -} - - - /* Returns how many wrong chunks */ - -int _sanity(const char *filename, uint lineno) -{ - reg1 struct st_irem *irem; - reg2 int flag=0; - uint count=0; - - pthread_mutex_lock(&THR_LOCK_malloc); -#ifndef PEDANTIC_SAFEMALLOC - if (sf_malloc_tampered && (int) sf_malloc_count < 0) - sf_malloc_count=0; -#endif - count=sf_malloc_count; - for (irem= sf_malloc_root; irem != NULL && count-- ; irem= irem->next) - flag+= _checkchunk (irem, filename, lineno); - pthread_mutex_unlock(&THR_LOCK_malloc); - if (count || irem) - { - const char *format="Error: Safemalloc link list destroyed, discovered at '%s:%d'"; - fprintf(stderr, format, filename, lineno); fputc('\n',stderr); - fprintf(stderr, "root=%p,count=%d,irem=%p\n", sf_malloc_root,count,irem); - (void) fflush(stderr); - DBUG_PRINT("safe",(format, filename, lineno)); - flag=1; - } - return flag; -} /* _sanity */ - - - /* malloc and copy */ - -void *_my_memdup(const void *from, size_t length, const char *filename, - uint lineno, myf MyFlags) -{ - void *ptr; - if ((ptr= _mymalloc(length,filename,lineno,MyFlags)) != 0) - memcpy(ptr, from, length); - return(ptr); -} /*_my_memdup */ - - -char *_my_strdup(const char *from, const char *filename, uint lineno, - myf MyFlags) -{ - char *ptr; - size_t length= strlen(from)+1; - if ((ptr= (char*) _mymalloc(length,filename,lineno,MyFlags)) != 0) - memcpy((uchar*) ptr, (uchar*) from, (size_t) length); - return(ptr); -} /* _my_strdup */ - - -char *_my_strndup(const char *from, size_t length, - const char *filename, uint lineno, - myf MyFlags) -{ - char *ptr; - if ((ptr= (char*) _mymalloc(length+1,filename,lineno,MyFlags)) != 0) - { - memcpy((uchar*) ptr, (uchar*) from, (size_t) length); - ptr[length]=0; - } - return(ptr); -} diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 93e8ae6b508..c2e930d76e2 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -13,9 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/ -#define DONT_DEFINE_VOID 1 - #include <my_global.h> #include <my_stacktrace.h> @@ -120,12 +117,8 @@ static int safe_print_str(const char *addr, int max_len) break; } - /* Output a new line if something was printed. */ - if (total != (size_t) max_len) - fputc('\n', stderr); - if (nbytes == -1) - fprintf(stderr, "Can't read from address %p: %m.\n", addr); + fprintf(stderr, "Can't read from address %p: %m.", addr); close(fd); @@ -147,13 +140,12 @@ void my_safe_print_str(const char* val, int max_len) if (!PTR_SANE(val)) { - fprintf(stderr, "is an invalid pointer\n"); + fprintf(stderr, "is an invalid pointer"); return; } for (; max_len && PTR_SANE(val) && *val; --max_len) fputc(*val++, stderr); - fputc('\n', stderr); } #if defined(HAVE_PRINTSTACK) @@ -434,44 +426,9 @@ void my_write_core(int sig) #include <dbghelp.h> #include <tlhelp32.h> - -/* - Stack tracing on Windows is implemented using Debug Helper library(dbghelp.dll) - We do not redistribute dbghelp and the one comes with older OS (up to Windows 2000) - is missing some important functions like functions StackWalk64 or MinidumpWriteDump. - Hence, we have to load functions at runtime using LoadLibrary/GetProcAddress. -*/ - -typedef DWORD (WINAPI *SymSetOptions_FctType)(DWORD dwOptions); -typedef BOOL (WINAPI *SymGetModuleInfo64_FctType) - (HANDLE,DWORD64,PIMAGEHLP_MODULE64) ; -typedef BOOL (WINAPI *SymGetSymFromAddr64_FctType) - (HANDLE,DWORD64,PDWORD64,PIMAGEHLP_SYMBOL64) ; -typedef BOOL (WINAPI *SymGetLineFromAddr64_FctType) - (HANDLE,DWORD64,PDWORD,PIMAGEHLP_LINE64); -typedef BOOL (WINAPI *SymInitialize_FctType) - (HANDLE,PSTR,BOOL); -typedef BOOL (WINAPI *StackWalk64_FctType) - (DWORD,HANDLE,HANDLE,LPSTACKFRAME64,PVOID,PREAD_PROCESS_MEMORY_ROUTINE64, - PFUNCTION_TABLE_ACCESS_ROUTINE64,PGET_MODULE_BASE_ROUTINE64 , - PTRANSLATE_ADDRESS_ROUTINE64); -typedef BOOL (WINAPI *MiniDumpWriteDump_FctType)( - IN HANDLE hProcess, - IN DWORD ProcessId, - IN HANDLE hFile, - IN MINIDUMP_TYPE DumpType, - IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL - IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL - IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL - ); - -static SymSetOptions_FctType pSymSetOptions; -static SymGetModuleInfo64_FctType pSymGetModuleInfo64; -static SymGetSymFromAddr64_FctType pSymGetSymFromAddr64; -static SymInitialize_FctType pSymInitialize; -static StackWalk64_FctType pStackWalk64; -static SymGetLineFromAddr64_FctType pSymGetLineFromAddr64; -static MiniDumpWriteDump_FctType pMiniDumpWriteDump; +#if _MSC_VER +#pragma comment(lib, "dbghelp") +#endif static EXCEPTION_POINTERS *exception_ptrs; @@ -482,50 +439,24 @@ void my_init_stacktrace() { } -/* - Dynamically load dbghelp functions -*/ -BOOL init_dbghelp_functions() -{ - static BOOL first_time= TRUE; - static BOOL rc; - HMODULE hDbghlp; - - if(first_time) - { - first_time= FALSE; - hDbghlp= LoadLibrary("dbghelp"); - if(!hDbghlp) - { - rc= FALSE; - return rc; - } - pSymSetOptions= (SymSetOptions_FctType) - GetProcAddress(hDbghlp,"SymSetOptions"); - pSymInitialize= (SymInitialize_FctType) - GetProcAddress(hDbghlp,"SymInitialize"); - pSymGetModuleInfo64= (SymGetModuleInfo64_FctType) - GetProcAddress(hDbghlp,"SymGetModuleInfo64"); - pSymGetLineFromAddr64= (SymGetLineFromAddr64_FctType) - GetProcAddress(hDbghlp,"SymGetLineFromAddr64"); - pSymGetSymFromAddr64=(SymGetSymFromAddr64_FctType) - GetProcAddress(hDbghlp,"SymGetSymFromAddr64"); - pStackWalk64= (StackWalk64_FctType) - GetProcAddress(hDbghlp,"StackWalk64"); - pMiniDumpWriteDump = (MiniDumpWriteDump_FctType) - GetProcAddress(hDbghlp,"MiniDumpWriteDump"); - - rc = (BOOL)(pSymSetOptions && pSymInitialize && pSymGetModuleInfo64 - && pSymGetLineFromAddr64 && pSymGetSymFromAddr64 && pStackWalk64); - } - return rc; -} void my_set_exception_pointers(EXCEPTION_POINTERS *ep) { exception_ptrs = ep; } +/* + Appends directory to symbol path. +*/ +static void add_to_symbol_path(char *path, size_t path_buffer_size, + char *dir, size_t dir_buffer_size) +{ + strcat_s(dir, dir_buffer_size, ";"); + if (!strstr(path, dir)) + { + strcat_s(path, path_buffer_size, dir); + } +} /* Get symbol path - semicolon-separated list of directories to search for debug @@ -537,8 +468,28 @@ static void get_symbol_path(char *path, size_t size) { HANDLE hSnap; char *envvar; + char *p; +#ifndef DBUG_OFF + static char pdb_debug_dir[MAX_PATH + 7]; +#endif path[0]= '\0'; + +#ifndef DBUG_OFF + /* + Add "debug" subdirectory of the application directory, sometimes PDB will + placed here by installation. + */ + GetModuleFileName(NULL, pdb_debug_dir, MAX_PATH); + p= strrchr(pdb_debug_dir, '\\'); + if(p) + { + *p= 0; + strcat_s(pdb_debug_dir, sizeof(pdb_debug_dir), "\\debug;"); + add_to_symbol_path(path, size, pdb_debug_dir, sizeof(pdb_debug_dir)); + } +#endif + /* Enumerate all modules, and add their directories to the path. Avoid duplicate entries. @@ -552,7 +503,7 @@ static void get_symbol_path(char *path, size_t size) for (ret= Module32First(hSnap, &mod); ret; ret= Module32Next(hSnap, &mod)) { char *module_dir= mod.szExePath; - char *p= strrchr(module_dir,'\\'); + p= strrchr(module_dir,'\\'); if (!p) { /* @@ -560,29 +511,23 @@ static void get_symbol_path(char *path, size_t size) will indicate current directory. */ module_dir[0]= '.'; - p= module_dir + 1; + module_dir[1]= '\0'; } - *p++= ';'; - *p= '\0'; - - if (!strstr(path, module_dir)) + else { - size_t dir_len = strlen(module_dir); - if (size > dir_len) - { - strncat(path, module_dir, size-1); - size -= dir_len; - } + *p= '\0'; } + add_to_symbol_path(path, size, module_dir,sizeof(mod.szExePath)); } CloseHandle(hSnap); } + /* Add _NT_SYMBOL_PATH, if present. */ envvar= getenv("_NT_SYMBOL_PATH"); - if(envvar && size) + if(envvar) { - strncat(path, envvar, size-1); + strcat_s(path, size, envvar); } } @@ -606,15 +551,15 @@ void my_print_stacktrace(uchar* unused1, ulong unused2) STACKFRAME64 frame={0}; static char symbol_path[MAX_SYMBOL_PATH]; - if(!exception_ptrs || !init_dbghelp_functions()) + if(!exception_ptrs) return; /* Copy context, as stackwalking on original will unwind the stack */ context = *(exception_ptrs->ContextRecord); /*Initialize symbols.*/ - pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); + SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); get_symbol_path(symbol_path, sizeof(symbol_path)); - pSymInitialize(hProcess, symbol_path, TRUE); + SymInitialize(hProcess, symbol_path, TRUE); /*Prepare stackframe for the first StackWalk64 call*/ frame.AddrFrame.Mode= frame.AddrPC.Mode= frame.AddrStack.Mode= AddrModeFlat; @@ -646,11 +591,11 @@ void my_print_stacktrace(uchar* unused1, ulong unused2) BOOL have_symbol= FALSE; BOOL have_source= FALSE; - if(!pStackWalk64(machine, hProcess, hThread, &frame, &context, 0, 0, 0 ,0)) + if(!StackWalk64(machine, hProcess, hThread, &frame, &context, 0, 0, 0 ,0)) break; addr= frame.AddrPC.Offset; - have_module= pSymGetModuleInfo64(hProcess,addr,&module); + have_module= SymGetModuleInfo64(hProcess,addr,&module); #ifdef _M_IX86 if(!have_module) { @@ -660,13 +605,13 @@ void my_print_stacktrace(uchar* unused1, ulong unused2) happy, pretend passing the old structure. */ module.SizeOfStruct= MODULE64_SIZE_WINXP; - have_module= pSymGetModuleInfo64(hProcess, addr, &module); + have_module= SymGetModuleInfo64(hProcess, addr, &module); } #endif - have_symbol= pSymGetSymFromAddr64(hProcess, addr, &function_offset, + have_symbol= SymGetSymFromAddr64(hProcess, addr, &function_offset, &(package.sym)); - have_source= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line); + have_source= SymGetLineFromAddr64(hProcess, addr, &line_offset, &line); fprintf(stderr, "%p ", addr); if(have_module) @@ -710,7 +655,7 @@ void my_write_core(int unused) MINIDUMP_EXCEPTION_INFORMATION info; HANDLE hFile; - if(!exception_ptrs || !init_dbghelp_functions() || !pMiniDumpWriteDump) + if(!exception_ptrs) return; info.ExceptionPointers= exception_ptrs; @@ -728,7 +673,7 @@ void my_write_core(int unused) if(hFile) { /* Create minidump */ - if(pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), + if(MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &info, 0, 0)) { fprintf(stderr, "Minidump written to %s\n", @@ -754,11 +699,11 @@ void my_safe_print_str(const char *val, int len) { __try { - fprintf(stderr,"=%.*s\n", len, val); + fprintf(stderr, "%.*s", len, val); } __except(EXCEPTION_EXECUTE_HANDLER) { - fprintf(stderr,"is an invalid string pointer\n"); + fprintf(stderr, "is an invalid string pointer"); } } #endif /*__WIN__*/ diff --git a/mysys/string.c b/mysys/string.c index 030178c6667..fa669ceda3a 100644 --- a/mysys/string.c +++ b/mysys/string.c @@ -98,20 +98,21 @@ my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, size_t length) { char *new_ptr; + DBUG_ENTER("dynstr_append_mem"); if (str->length+length >= str->max_length) { size_t new_length=(str->length+length+str->alloc_increment)/ str->alloc_increment; new_length*=str->alloc_increment; if (!(new_ptr=(char*) my_realloc(str->str,new_length,MYF(MY_WME)))) - return TRUE; + DBUG_RETURN(TRUE); str->str=new_ptr; str->max_length=new_length; } memcpy(str->str + str->length,append,length); str->length+=length; str->str[str->length]=0; /* Safety for C programs */ - return FALSE; + DBUG_RETURN(FALSE); } @@ -177,11 +178,8 @@ my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) void dynstr_free(DYNAMIC_STRING *str) { - if (str->str) - { - my_free(str->str,MYF(MY_WME)); - str->str=0; - } + my_free(str->str); + str->str= NULL; } diff --git a/mysys/test_charset.c b/mysys/test_charset.c index d867b49304e..39df1b02d7b 100644 --- a/mysys/test_charset.c +++ b/mysys/test_charset.c @@ -77,15 +77,5 @@ int main(int argc, char **argv) { _print_csinfo(cs); fflush(stdout); -#ifdef NOT_USED_ANYMORE - cs_list = list_charsets(MYF(MY_CS_COMPILED | MY_CS_CONFIG)); - printf("LIST OF CHARSETS (compiled + *.conf):\n%s\n", cs_list); - my_free(cs_list,MYF(0)); - - cs_list = list_charsets(MYF(MY_CS_INDEX | MY_CS_LOADED)); - printf("LIST OF CHARSETS (index + loaded):\n%s\n", cs_list); - my_free(cs_list,MYF(0)); -#endif - return 0; } diff --git a/mysys/test_fn.c b/mysys/test_fn.c deleted file mode 100644 index 249cc878390..00000000000 --- a/mysys/test_fn.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "mysys_priv.h" - -const char *test_names[]= -{ - "/usr/my/include/srclib/myfunc/dbug/test", - "test", - "dbug/test", - "/usr/my/srclib/myfunc/dbug/test", - "/usr/monty/oldcopy/jazz/setupp.frm", - "~/monty.tst", - "~/dbug/monty.tst", - "./hejsan", - "./dbug/test", - "../dbug/test", - "../myfunc/test", - "../../monty/rutedit", - "/usr/monty//usr/monty/rutedit", - "/usr/./monty/rutedit", - "/usr/my/../monty/rutedit", - "/usr/my/~/rutedit", - "~/../my", - "~/../my/srclib/myfunc/test", - "~/../my/srclib/myfunc/./dbug/test", - "/../usr/my/srclib/dbug", - "c/../my", - "/c/../my", - NullS, -}; - -int main(int argc __attribute__((unused)), char **argv) -{ - const char **pos; - char buff[FN_REFLEN],buff2[FN_REFLEN]; - DBUG_ENTER ("main"); - DBUG_PROCESS (argv[0]); - MY_INIT(argv[0]); - - if (argv[1] && argv[1][1] == '#') - DBUG_PUSH(argv[1]+2); - - for (pos=test_names; *pos ; pos++) - { - printf("org : '%s'\n",*pos); - printf("pack: '%s'\n",fn_format(buff,*pos,"","",8)); - printf("unpack: '%s'\n",fn_format(buff2,*pos,"","",4)); - unpack_filename(buff,buff); - if (strcmp(buff,buff2) != 0) - { - printf("error on cmp: '%s' != '%s'\n",buff,buff2); - } - puts(""); - } - DBUG_RETURN(0); -} diff --git a/mysys/testhash.c b/mysys/testhash.c index 2add2ebd2d7..376303f29be 100644 --- a/mysys/testhash.c +++ b/mysys/testhash.c @@ -286,5 +286,5 @@ static int rnd(int max_value) void free_record(void *record) { - my_free(record,MYF(0)); + my_free(record); } diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 98c746af8ca..f902057a71b 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -15,9 +15,10 @@ /* 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(THREAD) && !defined(DONT_USE_THR_ALARM) +#if !defined(DONT_USE_THR_ALARM) #include <errno.h> #include <my_pthread.h> #include <signal.h> @@ -56,8 +57,8 @@ static sig_handler process_alarm_part2(int sig); #if !defined(__WIN__) -static pthread_mutex_t LOCK_alarm; -static pthread_cond_t COND_alarm; +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; @@ -65,7 +66,7 @@ pthread_t alarm_thread; #ifdef USE_ALARM_THREAD static void *alarm_handler(void *arg); -#define reschedule_alarms() pthread_cond_signal(&COND_alarm) +#define reschedule_alarms() mysql_cond_signal(&COND_alarm) #else #define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) #endif @@ -88,8 +89,8 @@ void init_thr_alarm(uint max_alarms) init_queue(&alarm_queue, max_alarms+1, offsetof(ALARM,expire_time), 0, compare_ulong, NullS, offsetof(ALARM, index_in_queue)+1, 0); sigfillset(&full_signal_set); /* Neaded to block signals */ - pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_alarm,NULL); + mysql_mutex_init(key_LOCK_alarm, &LOCK_alarm, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_alarm, &COND_alarm, NULL); if (thd_lib_detected == THD_LIB_LT) thr_client_alarm= SIGALRM; else @@ -110,10 +111,9 @@ void init_thr_alarm(uint max_alarms) pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&thr_attr,8196); - - my_pthread_attr_setprio(&thr_attr,100); /* Very high priority */ - VOID(pthread_create(&alarm_thread,&thr_attr,alarm_handler,NULL)); - VOID(pthread_attr_destroy(&thr_attr)); + 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() */ @@ -132,14 +132,14 @@ void init_thr_alarm(uint max_alarms) void resize_thr_alarm(uint max_alarms) { - pthread_mutex_lock(&LOCK_alarm); + 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); - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); } @@ -204,7 +204,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) alarm_data->thread_id= current_my_thread_var->id; one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); - pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ + mysql_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ if (alarm_queue.elements >= max_used_alarms) { if (alarm_queue.elements == alarm_queue.max_elements) @@ -231,15 +231,15 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) else reschedule_alarms(); /* Reschedule alarms */ } - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); (*alrm)= &alarm_data->alarmed; DBUG_RETURN(0); abort: if (alarm_data->malloced) - my_free(alarm_data, MYF(0)); - pthread_mutex_unlock(&LOCK_alarm); + my_free(alarm_data); + mysql_mutex_unlock(&LOCK_alarm); one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); abort_no_unlock: *alrm= 0; /* No alarm */ @@ -263,12 +263,12 @@ void thr_end_alarm(thr_alarm_t *alarmed) DBUG_VOID_RETURN; one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed)); - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); DBUG_ASSERT(alarm_data->index_in_queue != 0); DBUG_ASSERT(queue_element(&alarm_queue, alarm_data->index_in_queue) == alarm_data); queue_remove(&alarm_queue, alarm_data->index_in_queue); - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL); reset_index_in_queue(alarm_data); DBUG_VOID_RETURN; @@ -310,14 +310,14 @@ sig_handler process_alarm(int sig __attribute__((unused))) #ifndef USE_ALARM_THREAD pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask); - pthread_mutex_lock(&LOCK_alarm); + 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 - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); #endif return; @@ -428,7 +428,7 @@ void end_thr_alarm(my_bool free_structures) DBUG_ENTER("end_thr_alarm"); if (alarm_aborted != 1) /* If memory not freed */ { - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); alarm_aborted= -1; /* mark aborted */ if (alarm_queue.elements || (alarm_thread_running && free_structures)) @@ -448,21 +448,21 @@ void end_thr_alarm(my_bool free_structures) set_timespec(abstime, 10); /* Wait up to 10 seconds */ while (alarm_thread_running) { - int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime); + 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; - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); if (!alarm_thread_running) /* Safety */ { - pthread_mutex_destroy(&LOCK_alarm); - pthread_cond_destroy(&COND_alarm); + mysql_mutex_destroy(&LOCK_alarm); + mysql_cond_destroy(&COND_alarm); } } else - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); } DBUG_VOID_RETURN; } @@ -479,7 +479,7 @@ void thr_alarm_kill(my_thread_id thread_id) if (alarm_aborted) return; - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); for (i= queue_first_element(&alarm_queue) ; i <= queue_last_element(&alarm_queue); i++) @@ -494,14 +494,14 @@ void thr_alarm_kill(my_thread_id thread_id) break; } } - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); DBUG_VOID_RETURN; } void thr_alarm_info(ALARM_INFO *info) { - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); info->next_alarm_time= 0; info->max_used_alarms= max_used_alarms; if ((info->active_alarms= alarm_queue.elements)) @@ -512,7 +512,7 @@ void thr_alarm_info(ALARM_INFO *info) time_diff= (long) (alarm_data->expire_time - now); info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff); } - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); } /* @@ -549,7 +549,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) #endif my_thread_init(); alarm_thread_running= 1; - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); for (;;) { if (alarm_queue.elements) @@ -564,7 +564,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) abstime.tv_sec=sleep_time; abstime.tv_nsec=0; next_alarm_expire_time= sleep_time; - if ((error=pthread_cond_timedwait(&COND_alarm,&LOCK_alarm,&abstime)) && + if ((error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime)) && error != ETIME && error != ETIMEDOUT) { #ifdef MAIN @@ -579,7 +579,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) else { next_alarm_expire_time= ~ (time_t) 0; - if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm))) + if ((error= mysql_cond_wait(&COND_alarm, &LOCK_alarm))) { #ifdef MAIN printf("Got error: %d from ptread_cond_wait (errno: %d)\n", @@ -591,8 +591,8 @@ static void *alarm_handler(void *arg __attribute__((unused))) } bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */ alarm_thread_running= 0; - pthread_cond_signal(&COND_alarm); - pthread_mutex_unlock(&LOCK_alarm); + mysql_cond_signal(&COND_alarm); + mysql_mutex_unlock(&LOCK_alarm); pthread_exit(0); return 0; /* Impossible */ } @@ -684,18 +684,17 @@ void resize_thr_alarm(uint max_alarms) #endif /* __WIN__ */ -#endif /* THREAD */ - +#endif /**************************************************************************** Handling of test case (when compiled with -DMAIN) ***************************************************************************/ #ifdef MAIN -#if defined(THREAD) && !defined(DONT_USE_THR_ALARM) +#if !defined(DONT_USE_THR_ALARM) -static pthread_cond_t COND_thread_count; -static pthread_mutex_t LOCK_thread_count; +static mysql_cond_t COND_thread_count; +static mysql_mutex_t LOCK_thread_count; static uint thread_count; #ifdef HPUX10 @@ -772,7 +771,7 @@ static void *test_thread(void *arg) break; continue; } - VOID(getchar()); /* Somebody was playing */ + (void) getchar(); /* Somebody was playing */ } } } @@ -782,10 +781,10 @@ static void *test_thread(void *arg) thr_end_alarm(&got_alarm); fflush(stdout); } - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; - VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ + mysql_mutex_unlock(&LOCK_thread_count); free((uchar*) arg); return 0; } @@ -799,9 +798,9 @@ static void *signal_hand(void *arg __attribute__((unused))) my_thread_init(); pthread_detach_this_thread(); init_thr_alarm(10); /* Setup alarm handler */ - pthread_mutex_lock(&LOCK_thread_count); /* Required by bsdi */ - VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ - pthread_mutex_unlock(&LOCK_thread_count); + 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); @@ -872,8 +871,8 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) { DBUG_PUSH(argv[1]+2); } - pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_thread_count,NULL); + 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); @@ -888,11 +887,6 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) sigaddset(&set,THR_SERVER_ALARM); sigdelset(&set, thr_client_alarm); (void) pthread_sigmask(SIG_SETMASK,&set,NULL); -#ifdef NOT_USED - sigemptyset(&set); - sigaddset(&set, thr_client_alarm); - VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); -#endif pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); @@ -900,10 +894,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) pthread_attr_setstacksize(&thr_attr,65536L); /* Start signal thread and wait for it to start */ - VOID(pthread_mutex_lock(&LOCK_thread_count)); - pthread_create(&tid,&thr_attr,signal_hand,NULL); - VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + 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")); thr_setconcurrency(3); @@ -913,32 +908,34 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) { param=(int*) malloc(sizeof(int)); *param= i; - pthread_mutex_lock(&LOCK_thread_count); - if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param))) + mysql_mutex_lock(&LOCK_thread_count); + if ((error= mysql_thread_create(0, + &tid, &thr_attr, test_thread, + (void*) param))) { printf("Can't create thread %d, error: %d\n",i,error); exit(1); } thread_count++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } pthread_attr_destroy(&thr_attr); - pthread_mutex_lock(&LOCK_thread_count); + 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) { - VOID(pthread_cond_wait(&COND_thread_count,&LOCK_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); } } - pthread_mutex_unlock(&LOCK_thread_count); + 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", @@ -948,17 +945,13 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) return 0; } -#else /* THREAD */ +#else /* !defined(DONT_USE_ALARM_THREAD) */ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) { -#ifndef THREAD - printf("thr_alarm disabled because we are not using threads\n"); -#else printf("thr_alarm disabled with DONT_USE_THR_ALARM\n"); -#endif exit(1); } -#endif /* THREAD */ +#endif /* !defined(DONT_USE_ALARM_THREAD) */ #endif /* MAIN */ diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index ac70282c050..b2e51cde260 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -29,7 +29,6 @@ TL_READ_WITH_SHARED_LOCKS TL_READ_HIGH_PRIORITY # High priority read TL_READ_NO_INSERT # Read without concurrent inserts TL_WRITE_ALLOW_WRITE # Write lock that allows other writers -TL_WRITE_ALLOW_READ # Write lock, but allow reading TL_WRITE_CONCURRENT_INSERT # Insert that can be mixed when selects TL_WRITE_DELAYED # Used by delayed insert @@ -41,7 +40,7 @@ TL_WRITE_ONLY # High priority write Locks are prioritized according to: -WRITE_ALLOW_WRITE, WRITE_ALLOW_READ, WRITE_CONCURRENT_INSERT, WRITE_DELAYED, +WRITE_ALLOW_WRITE, WRITE_CONCURRENT_INSERT, WRITE_DELAYED, WRITE_LOW_PRIORITY, READ, WRITE, READ_HIGH_PRIORITY and WRITE_ONLY Locks in the same privilege level are scheduled in first-in-first-out order. @@ -73,9 +72,8 @@ get_status: In MyISAM this stores the number of rows and size of the datafile for concurrent reads. -The lock algorithm allows one to have one TL_WRITE_ALLOW_READ, -TL_WRITE_CONCURRENT_INSERT or one TL_WRITE_DELAYED lock at the same -time as multiple read locks. +The lock algorithm allows one to have one TL_WRITE_CONCURRENT_INSERT or +one TL_WRITE_DELAYED lock at the same time as multiple read locks. In addition, if lock->allow_multiple_concurrent_insert is set then there can be any number of TL_WRITE_CONCURRENT_INSERT locks aktive at the same time. @@ -87,14 +85,12 @@ be any number of TL_WRITE_CONCURRENT_INSERT locks aktive at the same time. #include "mysys_priv.h" -#ifdef THREAD #include "thr_lock.h" #include <m_string.h> #include <errno.h> my_bool thr_lock_inited=0; ulong locks_immediate = 0L, locks_waited = 0L; -ulong table_lock_wait_timeout; enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE; /* The following constants are only for debug output */ @@ -105,7 +101,17 @@ enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE; LIST *thr_lock_thread_list; /* List of threads in use */ ulong max_write_lock_count= ~(ulong) 0L; -static inline pthread_cond_t *get_cond(void) +static void (*before_lock_wait)(void)= 0; +static void (*after_lock_wait)(void)= 0; + +void thr_set_lock_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)) +{ + before_lock_wait= before_wait; + after_lock_wait= after_wait; +} + +static inline mysql_cond_t *get_cond(void) { return &my_thread_var->suspend; } @@ -135,15 +141,18 @@ static inline pthread_cond_t *get_cond(void) */ -inline int LOCK_CMP(THR_LOCK_DATA *A, THR_LOCK_DATA *B) +static inline int LOCK_CMP(THR_LOCK_DATA *a, THR_LOCK_DATA *b) { - if (A->lock != B->lock) - return A->lock < B->lock; - if (A->type != B->type) - return A->type > B->type; /* Prioritize read */ - return A->priority < B->priority; + if (a->lock != b->lock) + return a->lock < b->lock; + + if (a->type != b->type) + return a->type > b->type; + + return a->priority < b->priority; } + /* For the future (now the thread specific cond is alloced by my_pthread.c) */ @@ -155,7 +164,7 @@ my_bool init_thr_lock() } static inline my_bool -thr_lock_owner_equal(THR_LOCK_OWNER *rhs, THR_LOCK_OWNER *lhs) +thr_lock_owner_equal(THR_LOCK_INFO *rhs, THR_LOCK_INFO *lhs) { return rhs == lhs; } @@ -175,7 +184,7 @@ static int check_lock(struct st_lock_list *list, const char* lock_type, if (list->data) { enum thr_lock_type last_lock_type= list->data->type; - THR_LOCK_OWNER *first_owner= list->data->owner; + THR_LOCK_INFO *first_owner= list->data->owner; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { @@ -287,7 +296,6 @@ static void check_locks(THR_LOCK *lock, const char *where, (((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT || lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) && !lock->read_no_write_count) || - lock->write_wait.data->type == TL_WRITE_ALLOW_READ || (lock->write_wait.data->type == TL_WRITE_DELAYED && !lock->read.data))) { @@ -393,16 +401,16 @@ void thr_lock_init(THR_LOCK *lock) { DBUG_ENTER("thr_lock_init"); bzero((char*) lock,sizeof(*lock)); - VOID(pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST)); + mysql_mutex_init(key_THR_LOCK_mutex, &lock->mutex, MY_MUTEX_INIT_FAST); lock->read.last= &lock->read.data; lock->read_wait.last= &lock->read_wait.data; lock->write_wait.last= &lock->write_wait.data; lock->write.last= &lock->write.data; - pthread_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */ + mysql_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */ lock->list.data=(void*) lock; thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list); - pthread_mutex_unlock(&THR_LOCK_lock); + mysql_mutex_unlock(&THR_LOCK_lock); DBUG_VOID_RETURN; } @@ -410,10 +418,10 @@ void thr_lock_init(THR_LOCK *lock) void thr_lock_delete(THR_LOCK *lock) { DBUG_ENTER("thr_lock_delete"); - pthread_mutex_lock(&THR_LOCK_lock); + mysql_mutex_lock(&THR_LOCK_lock); thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list); - pthread_mutex_unlock(&THR_LOCK_lock); - pthread_mutex_destroy(&lock->mutex); + mysql_mutex_unlock(&THR_LOCK_lock); + mysql_mutex_destroy(&lock->mutex); DBUG_VOID_RETURN; } @@ -423,7 +431,6 @@ void thr_lock_info_init(THR_LOCK_INFO *info) struct st_my_thread_var *tmp= my_thread_var; info->thread= tmp->pthread_self; info->thread_id= tmp->id; - info->n_cursors= 0; } /* Initialize a lock instance */ @@ -441,7 +448,7 @@ void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *param) static inline my_bool -have_old_read_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner) +has_old_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner) { for ( ; data ; data=data->next) { @@ -468,13 +475,13 @@ static void wake_up_waiters(THR_LOCK *lock); static enum enum_thr_lock_result wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, - my_bool in_wait_list) + my_bool in_wait_list, ulong lock_wait_timeout) { struct st_my_thread_var *thread_var= my_thread_var; - pthread_cond_t *cond= &thread_var->suspend; + mysql_cond_t *cond= &thread_var->suspend; struct timespec wait_timeout; enum enum_thr_lock_result result= THR_LOCK_ABORTED; - my_bool can_deadlock= test(data->owner->info->n_cursors); + const char *old_proc_info; DBUG_ENTER("wait_for_lock"); /* @@ -513,14 +520,26 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, thread_var->current_cond= cond; data->cond= cond; - if (can_deadlock) - set_timespec(wait_timeout, table_lock_wait_timeout); + old_proc_info= proc_info_hook(NULL, "Waiting for table level lock", + __func__, __FILE__, __LINE__); + + /* + Since before_lock_wait potentially can create more threads to + scheduler work for, we don't want to call the before_lock_wait + callback unless it will really start to wait. + + For similar reasons, we do not want to call before_lock_wait and + after_lock_wait for each lap around the loop, so we restrict + ourselves to call it before_lock_wait once before starting to wait + and once after the thread has exited the wait loop. + */ + if ((!thread_var->abort || in_wait_list) && before_lock_wait) + (*before_lock_wait)(); + + set_timespec(wait_timeout, lock_wait_timeout); while (!thread_var->abort || in_wait_list) { - int rc= (can_deadlock ? - pthread_cond_timedwait(cond, &data->lock->mutex, - &wait_timeout) : - pthread_cond_wait(cond, &data->lock->mutex)); + int rc= mysql_cond_timedwait(cond, &data->lock->mutex, &wait_timeout); /* We must break the wait if one of the following occurs: - the connection has been aborted (!thread_var->abort), but @@ -548,6 +567,14 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, /* purecov: end */ } } + + /* + We call the after_lock_wait callback once the wait loop has + finished. + */ + if (after_lock_wait) + (*after_lock_wait)(); + DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d", thread_var->abort, in_wait_list)); @@ -578,25 +605,27 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, data->type == TL_WRITE_CONCURRENT_INSERT); check_locks(data->lock,"got wait_for_lock", data->type, 0); } - pthread_mutex_unlock(&data->lock->mutex); + mysql_mutex_unlock(&data->lock->mutex); /* The following must be done after unlock of lock->mutex */ - pthread_mutex_lock(&thread_var->mutex); + mysql_mutex_lock(&thread_var->mutex); thread_var->current_mutex= 0; thread_var->current_cond= 0; - pthread_mutex_unlock(&thread_var->mutex); + mysql_mutex_unlock(&thread_var->mutex); + + proc_info_hook(NULL, old_proc_info, __func__, __FILE__, __LINE__); + DBUG_RETURN(result); } static enum enum_thr_lock_result -thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, - enum thr_lock_type lock_type) +thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, + enum thr_lock_type lock_type, ulong lock_wait_timeout) { THR_LOCK *lock=data->lock; enum enum_thr_lock_result result= THR_LOCK_SUCCESS; struct st_lock_list *wait_queue; - THR_LOCK_DATA *lock_owner; DBUG_ENTER("thr_lock"); data->next=0; @@ -604,9 +633,9 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, data->type=lock_type; data->owner= owner; /* Must be reset ! */ data->priority&= ~THR_LOCK_LATE_PRIV; - VOID(pthread_mutex_lock(&lock->mutex)); + mysql_mutex_lock(&lock->mutex); DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", - (long) data, data->owner->info->thread_id, + (long) data, data->owner->thread_id, (long) lock, (int) lock_type)); check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? "enter read_lock" : "enter write_lock", lock_type, 0); @@ -616,22 +645,38 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, if (lock->write.data) { /* - We can allow a read lock even if there is already a write lock - on the table in one the following cases: - - This thread alread have a write lock on the table - - The write lock is TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED - and the read lock is TL_READ_HIGH_PRIORITY or TL_READ - - The write lock is TL_WRITE_CONCURRENT_INSERT or TL_WRITE_ALLOW_WRITE - and the read lock is not TL_READ_NO_INSERT + We can allow a read lock even if there is already a + write lock on the table if they are owned by the same + thread or if they satisfy the following lock + compatibility matrix: + + Request + /------- + H|++++ WRITE_ALLOW_WRITE + e|+++- WRITE_CONCURRENT_INSERT + l|++++ WRITE_DELAYED + d |||| + |||\= READ_NO_INSERT + ||\ = READ_HIGH_PRIORITY + |\ = READ_WITH_SHARED_LOCKS + \ = READ + + + + = Request can be satisified. + - = Request cannot be satisified. + + READ_NO_INSERT and WRITE_ALLOW_WRITE should in principle + be incompatible. However this will cause starvation of + LOCK TABLE READ in InnoDB under high write load. + See Bug#42147 for more information. */ DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx", - lock->write.data->owner->info->thread_id)); + lock->write.data->owner->thread_id)); if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || (lock->write.data->type <= TL_WRITE_DELAYED && (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) || - (lock->write.data->type != TL_WRITE_CONCURRENT_INSERT && - lock->write.data->type != TL_WRITE_ALLOW_READ)))) + (lock->write.data->type != TL_WRITE_CONCURRENT_INSERT)))) { /* Already got a write lock */ (*lock->read.last)=data; /* Add to running FIFO */ data->prev=lock->read.last; @@ -655,7 +700,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, else if (!lock->write_wait.data || lock->write_wait.data->type <= TL_WRITE_LOW_PRIORITY || lock_type == TL_READ_HIGH_PRIORITY || - have_old_read_lock(lock->read.data, data->owner)) + has_old_lock(lock->read.data, data->owner)) /* Has old read lock */ { /* No important write-locks */ (*lock->read.last)=data; /* Add to running FIFO */ data->prev=lock->read.last; @@ -685,14 +730,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, result= THR_LOCK_ABORTED; /* Can't wait for this one */ goto end; } - /* - if there is a TL_WRITE_ALLOW_READ lock, we have to wait for a lock - (TL_WRITE_ALLOW_READ is used for ALTER TABLE in MySQL) - */ - if ((!lock->write.data || - lock->write.data->type != TL_WRITE_ALLOW_READ) && - !have_specific_lock(lock->write_wait.data,TL_WRITE_ALLOW_READ) && - (lock->write.data || lock->read.data)) + if (lock->write.data || lock->read.data) { /* Add delayed write lock to write_wait queue, and return at once */ (*lock->write_wait.last)=data; @@ -714,6 +752,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, { if (lock->write.data->type == TL_WRITE_ONLY) { + /* purecov: begin tested */ /* Allow lock owner to bypass TL_WRITE_ONLY. */ if (!thr_lock_owner_equal(data->owner, lock->write.data->owner)) { @@ -722,23 +761,50 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, result= THR_LOCK_ABORTED; /* Can't wait for this one */ goto end; } + /* purecov: end */ } /* - The following test will not work if the old lock was a - TL_WRITE_ALLOW_WRITE, TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED in - the same thread, but this will never happen within MySQL. - The idea is to allow us to get a lock at once if we already have a write lock or if there is no pending write locks and if all write locks are of the same type and are either TL_WRITE_ALLOW_WRITE or TL_WRITE_CONCURRENT_INSERT + + Note that, since lock requests for the same table are sorted in + such way that requests with higher thr_lock_type value come first + (with one exception (*)), lock being requested usually (**) has + equal or "weaker" type than one which thread might have already + acquired. + *) The only exception to this rule is case when type of old lock + is TL_WRITE_LOW_PRIORITY and type of new lock is changed inside + of thr_lock() from TL_WRITE_CONCURRENT_INSERT to TL_WRITE since + engine turns out to be not supporting concurrent inserts. + Note that since TL_WRITE has the same compatibility rules as + TL_WRITE_LOW_PRIORITY (their only difference is priority), + it is OK to grant new lock without additional checks in such + situation. + **) The exceptions are situations when: + - when old lock type is TL_WRITE_DELAYED + But these should never happen within MySQL. + Therefore it is OK to allow acquiring write lock on the table if + this thread already holds some write lock on it. + + (INSERT INTO t1 VALUES (f1()), where f1() is stored function which + tries to update t1, is an example of statement which requests two + different types of write lock on the same table). */ - if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || - (!lock->write_wait.data && lock_type == lock->write.data->type && - (lock_type == TL_WRITE_ALLOW_WRITE || - (lock_type == TL_WRITE_CONCURRENT_INSERT && - lock->allow_multiple_concurrent_insert)))) + DBUG_ASSERT(! has_old_lock(lock->write.data, data->owner) || + ((lock_type <= lock->write.data->type || + (lock_type == TL_WRITE && + lock->write.data->type == TL_WRITE_LOW_PRIORITY)) && + lock->write.data->type != TL_WRITE_DELAYED)); + + if (((lock_type == TL_WRITE_ALLOW_WRITE || + (lock_type == TL_WRITE_CONCURRENT_INSERT && + lock->allow_multiple_concurrent_insert)) && + ! lock->write_wait.data && + lock->write.data->type == lock_type) || + has_old_lock(lock->write.data, data->owner)) { DBUG_PRINT("info", ("write_wait.data: 0x%lx old_type: %d", (ulong) lock->write_wait.data, @@ -755,7 +821,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, goto end; } DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx", - lock->write.data->owner->info->thread_id)); + lock->write.data->owner->thread_id)); } else { @@ -791,27 +857,14 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, } } DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d", - lock->read.data->owner->info->thread_id, data->type)); + lock->read.data->owner->thread_id, data->type)); } wait_queue= &lock->write_wait; } - /* - Try to detect a trivial deadlock when using cursors: attempt to - lock a table that is already locked by an open cursor within the - same connection. lock_owner can be zero if we succumbed to a high - priority writer in the write_wait queue. - */ - lock_owner= lock->read.data ? lock->read.data : lock->write.data; - if (lock_owner && lock_owner->owner->info == owner->info) - { - DBUG_PRINT("lock",("deadlock")); - result= THR_LOCK_DEADLOCK; - goto end; - } /* Can't get lock yet; Wait for it */ - DBUG_RETURN(wait_for_lock(wait_queue, data, 0)); + DBUG_RETURN(wait_for_lock(wait_queue, data, 0, lock_wait_timeout)); end: - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(result); } @@ -833,7 +886,7 @@ static inline void free_all_read_locks(THR_LOCK *lock, do { - pthread_cond_t *cond=data->cond; + mysql_cond_t *cond= data->cond; if ((int) data->type == (int) TL_READ_NO_INSERT) { if (using_concurrent_insert) @@ -855,10 +908,10 @@ static inline void free_all_read_locks(THR_LOCK *lock, } /* purecov: begin inspected */ DBUG_PRINT("lock",("giving read lock to thread: 0x%lx", - data->owner->info->thread_id)); + data->owner->thread_id)); /* purecov: end */ data->cond=0; /* Mark thread free */ - VOID(pthread_cond_signal(cond)); + mysql_cond_signal(cond); } while ((data=data->next)); *lock->read_wait.last=0; if (!lock->read_wait.data) @@ -874,8 +927,8 @@ void thr_unlock(THR_LOCK_DATA *data, uint unlock_flags) enum thr_lock_type lock_type=data->type; DBUG_ENTER("thr_unlock"); DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) data, data->owner->info->thread_id, (long) lock)); - pthread_mutex_lock(&lock->mutex); + (long) data, data->owner->thread_id, (long) lock)); + mysql_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock", lock_type, 0); if (((*data->prev)=data->next)) /* remove from lock-list */ @@ -913,7 +966,7 @@ void thr_unlock(THR_LOCK_DATA *data, uint unlock_flags) check_locks(lock,"after releasing lock", lock_type, 1); wake_up_waiters(lock); check_locks(lock,"end of thr_unlock", lock_type, 1); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; } @@ -968,12 +1021,12 @@ static void wake_up_waiters(THR_LOCK *lock) data->type=TL_WRITE; /* Upgrade lock */ /* purecov: begin inspected */ DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx", - data->type, data->owner->info->thread_id)); + data->type, data->owner->thread_id)); /* purecov: end */ { - pthread_cond_t *cond=data->cond; + mysql_cond_t *cond= data->cond; data->cond=0; /* Mark thread free */ - VOID(pthread_cond_signal(cond)); /* Start waiting thread */ + mysql_cond_signal(cond); /* Start waiting thread */ } if (data->type != TL_WRITE_ALLOW_WRITE || !lock->write_wait.data || @@ -1014,7 +1067,7 @@ static void wake_up_waiters(THR_LOCK *lock) goto end; } do { - pthread_cond_t *cond=data->cond; + mysql_cond_t *cond= data->cond; if (((*data->prev)=data->next)) /* remove from wait-list */ data->next->prev= data->prev; else @@ -1024,7 +1077,7 @@ static void wake_up_waiters(THR_LOCK *lock) lock->write.last= &data->next; data->next=0; /* Only one write lock */ data->cond=0; /* Mark thread free */ - VOID(pthread_cond_signal(cond)); /* Start waiting thread */ + mysql_cond_signal(cond); /* Start waiting thread */ } while (lock_type == TL_WRITE_ALLOW_WRITE && (data=lock->write_wait.data) && data->type == TL_WRITE_ALLOW_WRITE); @@ -1071,7 +1124,8 @@ static void sort_locks(THR_LOCK_DATA **data,uint count) enum enum_thr_lock_result -thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner) +thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, + ulong lock_wait_timeout) { THR_LOCK_DATA **pos, **end, **first_lock; DBUG_ENTER("thr_multi_lock"); @@ -1085,12 +1139,14 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner) /* lock everything */ for (pos=data,end=data+count; pos < end ; pos++) { - enum enum_thr_lock_result result= thr_lock(*pos, owner, (*pos)->type); + enum enum_thr_lock_result result= thr_lock(*pos, owner, (*pos)->type, + lock_wait_timeout); if (result != THR_LOCK_SUCCESS) { /* Aborted */ thr_multi_unlock(data,(uint) (pos-data), 0); DBUG_RETURN(result); } + DEBUG_SYNC_C("thr_multi_lock_after_thr_lock"); #ifdef MAIN printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(), (long) pos[0]->lock, pos[0]->type); fflush(stdout); @@ -1206,7 +1262,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count, uint unlock_flags) else { DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) *pos, (*pos)->owner->info->thread_id, + (long) *pos, (*pos)->owner->thread_id, (long) (*pos)->lock)); } } @@ -1222,19 +1278,19 @@ void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock) { THR_LOCK_DATA *data; DBUG_ENTER("thr_abort_locks"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); for (data=lock->read_wait.data; data ; data=data->next) { data->type=TL_UNLOCK; /* Mark killed */ /* It's safe to signal the cond first: we're still holding the mutex. */ - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond=0; /* Removed from list */ } for (data=lock->write_wait.data; data ; data=data->next) { data->type=TL_UNLOCK; - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond=0; } lock->read_wait.last= &lock->read_wait.data; @@ -1242,7 +1298,7 @@ void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock) lock->read_wait.data=lock->write_wait.data=0; if (upgrade_lock && lock->write.data) lock->write.data->type=TL_WRITE_ONLY; - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; } @@ -1259,16 +1315,16 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) my_bool found= FALSE; DBUG_ENTER("thr_abort_locks_for_thread"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); for (data= lock->read_wait.data; data ; data= data->next) { - if (data->owner->info->thread_id == thread_id) /* purecov: tested */ + if (data->owner->thread_id == thread_id) /* purecov: tested */ { DBUG_PRINT("info",("Aborting read-wait lock")); data->type= TL_UNLOCK; /* Mark killed */ /* It's safe to signal the cond first: we're still holding the mutex. */ found= TRUE; - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond= 0; /* Removed from list */ if (((*data->prev)= data->next)) @@ -1279,12 +1335,12 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) } for (data= lock->write_wait.data; data ; data= data->next) { - if (data->owner->info->thread_id == thread_id) /* purecov: tested */ + if (data->owner->thread_id == thread_id) /* purecov: tested */ { DBUG_PRINT("info",("Aborting write-wait lock")); data->type= TL_UNLOCK; found= TRUE; - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond= 0; if (((*data->prev)= data->next)) @@ -1294,7 +1350,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) } } wake_up_waiters(lock); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(found); } @@ -1312,10 +1368,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) 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 and TL_WRITE_ALLOW_READ. The normal downgrade variants are - TL_WRITE_ONLY => TL_WRITE_ALLOW_READ After a short exclusive lock - TL_WRITE_ALLOW_READ => TL_WRITE_ALLOW_WRITE After discovering that the - operation didn't need such a high lock. + 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 @@ -1336,198 +1389,32 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, #ifndef DBUG_OFF enum thr_lock_type old_lock_type= in_data->type; #endif -#ifdef TO_BE_REMOVED - THR_LOCK_DATA *data, *next; - bool start_writers= FALSE; - bool start_readers= FALSE; -#endif DBUG_ENTER("thr_downgrade_write_only_lock"); - pthread_mutex_lock(&lock->mutex); + 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); -#if TO_BE_REMOVED - switch (old_lock_type) - { - case TL_WRITE_ONLY: - case TL_WRITE: - case TL_WRITE_LOW_PRIORITY: - /* - Previous lock was exclusive we are now ready to start up most waiting - threads. - */ - switch (new_lock_type) - { - case TL_WRITE_ALLOW_READ: - /* Still cannot start WRITE operations. Can only start readers. */ - start_readers= TRUE; - break; - case TL_WRITE: - case TL_WRITE_LOW_PRIORITY: - /* - Still cannot start anything, but new requests are no longer - aborted. - */ - break; - case TL_WRITE_ALLOW_WRITE: - /* - We can start both writers and readers. - */ - start_writers= TRUE; - start_readers= TRUE; - break; - case TL_WRITE_CONCURRENT_INSERT: - case TL_WRITE_DELAYED: - /* - This routine is not designed for those. Lock will be downgraded - but no start of waiters will occur. This is not the optimal but - should be a correct behaviour. - */ - break; - default: - DBUG_ASSERT(0); - } - break; - case TL_WRITE_DELAYED: - case TL_WRITE_CONCURRENT_INSERT: - /* - This routine is not designed for those. Lock will be downgraded - but no start of waiters will occur. This is not the optimal but - should be a correct behaviour. - */ - break; - case TL_WRITE_ALLOW_READ: - DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); - /* - Previously writers were not allowed to start, now it is ok to - start them again. Readers are already allowed so no reason to - handle them. - */ - start_writers= TRUE; - break; - default: - DBUG_ASSERT(0); - break; - } - if (start_writers) - { - /* - At this time the only active writer can be ourselves. Thus we need - not worry about that there are other concurrent write operations - active on the table. Thus we only need to worry about starting - waiting operations. - We also only come here with TL_WRITE_ALLOW_WRITE as the new - lock type, thus we can start other writers also of the same type. - If we find a lock at exclusive level >= TL_WRITE_LOW_PRIORITY we - don't start any more operations that would be mean those operations - will have to wait for things started afterwards. - */ - DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); - for (data=lock->write_wait.data; data ; data= next) - { - /* - All WRITE requests compatible with new lock type are also - started - */ - next= data->next; - if (start_writers && data->type == new_lock_type) - { - pthread_cond_t *cond= data->cond; - /* - It is ok to start this waiter. - Move from being first in wait queue to be last in write queue. - */ - if (((*data->prev)= data->next)) - data->next->prev= data->prev; - else - lock->write_wait.last= data->prev; - data->prev= lock->write.last; - lock->write.last= &data->next; - data->next= 0; - check_locks(lock, "Started write lock after downgrade", new_lock_type, - 0); - data->cond= 0; - pthread_cond_signal(cond); - } - else - { - /* - We found an incompatible lock, we won't start any more write - requests to avoid letting writers pass other writers in the - queue. - */ - start_writers= FALSE; - if (data->type >= TL_WRITE_LOW_PRIORITY) - { - /* - We have an exclusive writer in the queue so we won't start - readers either. - */ - start_readers= FALSE; - } - } - } - } - if (start_readers) - { - DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE || - new_lock_type == TL_WRITE_ALLOW_READ); - /* - When we come here we know that the write locks are - TL_WRITE_ALLOW_WRITE or TL_WRITE_ALLOW_READ. This means that reads - are ok - */ - for (data=lock->read_wait.data; data ; data=next) - { - next= data->next; - /* - All reads are ok to start now except TL_READ_NO_INSERT when - write lock is TL_WRITE_ALLOW_READ. - */ - if (new_lock_type != TL_WRITE_ALLOW_READ || - data->type != TL_READ_NO_INSERT) - { - pthread_cond_t *cond= data->cond; - if (((*data->prev)= data->next)) - data->next->prev= data->prev; - else - lock->read_wait.last= data->prev; - data->prev= lock->read.last; - lock->read.last= &data->next; - data->next= 0; - - if (data->type == TL_READ_NO_INSERT) - lock->read_no_write_count++; - check_locks(lock, "Started read lock after downgrade", new_lock_type, - 0); - data->cond= 0; - pthread_cond_signal(cond); - } - } - } - check_locks(lock,"after starting waiters after downgrading lock", - new_lock_type, 0); -#endif - pthread_mutex_unlock(&lock->mutex); + 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, - enum thr_lock_type new_lock_type) + enum thr_lock_type new_lock_type, + ulong lock_wait_timeout) { THR_LOCK *lock=data->lock; enum enum_thr_lock_result res; DBUG_ENTER("thr_upgrade_write_delay_lock"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY) { - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(data->type == TL_UNLOCK); /* Test if Aborted */ } check_locks(lock,"before upgrading lock", data->type, 0); @@ -1539,9 +1426,9 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, { if (!lock->read.data) /* No read locks */ { /* We have the lock */ - if (lock->get_status) - (*lock->get_status)(data->status_param, 0); - pthread_mutex_unlock(&lock->mutex); + if (data->lock->get_status) + (*data->lock->get_status)(data->status_param, 0); + mysql_mutex_unlock(&lock->mutex); if (lock->start_trans) (*lock->start_trans)(data->status_param); DBUG_RETURN(0); @@ -1564,7 +1451,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, { check_locks(lock,"waiting for lock", new_lock_type, 0); } - res= wait_for_lock(&lock->write_wait,data,1); + res= wait_for_lock(&lock->write_wait, data, 1, lock_wait_timeout); if (res == THR_LOCK_SUCCESS && lock->start_trans) DBUG_RETURN((*lock->start_trans)(data->status_param)); DBUG_RETURN(0); @@ -1573,16 +1460,17 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, /* downgrade a WRITE lock to a WRITE_DELAY lock if there is pending locks */ -my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) +my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data, + ulong lock_wait_timeout) { THR_LOCK *lock=data->lock; enum thr_lock_type write_lock_type; DBUG_ENTER("thr_reschedule_write_lock"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); if (!lock->read_wait.data) /* No waiting read locks */ { - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(0); } @@ -1604,8 +1492,9 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) lock->write_wait.data=data; free_all_read_locks(lock,0); - pthread_mutex_unlock(&lock->mutex); - DBUG_RETURN(thr_upgrade_write_delay_lock(data, write_lock_type)); + mysql_mutex_unlock(&lock->mutex); + DBUG_RETURN(thr_upgrade_write_delay_lock(data, write_lock_type, + lock_wait_timeout)); } @@ -1622,7 +1511,7 @@ static void thr_print_lock(const char* name,struct st_lock_list *list) prev= &list->data; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { - printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->info->thread_id, + printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->thread_id, (int) data->type); if (data->prev != prev) printf("\nWarning: prev didn't point at previous lock\n"); @@ -1639,13 +1528,13 @@ void thr_print_locks(void) LIST *list; uint count=0; - pthread_mutex_lock(&THR_LOCK_lock); + mysql_mutex_lock(&THR_LOCK_lock); puts("Current locks:"); for (list= thr_lock_thread_list; list && count++ < MAX_THREADS; list= list_rest(list)) { THR_LOCK *lock=(THR_LOCK*) list->data; - VOID(pthread_mutex_lock(&lock->mutex)); + mysql_mutex_lock(&lock->mutex); printf("lock: 0x%lx:",(ulong) lock); if ((lock->write_wait.data || lock->read_wait.data) && (! lock->read.data && ! lock->write.data)) @@ -1663,14 +1552,13 @@ void thr_print_locks(void) thr_print_lock("write_wait",&lock->write_wait); thr_print_lock("read",&lock->read); thr_print_lock("read_wait",&lock->read_wait); - VOID(pthread_mutex_unlock(&lock->mutex)); + mysql_mutex_unlock(&lock->mutex); puts(""); } fflush(stdout); - pthread_mutex_unlock(&THR_LOCK_lock); + mysql_mutex_unlock(&THR_LOCK_lock); } -#endif /* THREAD */ /***************************************************************************** ** Test of thread locks @@ -1678,8 +1566,6 @@ void thr_print_locks(void) #ifdef MAIN -#ifdef THREAD - struct st_test { uint lock_nr; enum thr_lock_type lock_type; @@ -1699,26 +1585,14 @@ struct st_test test_8[] = {{1,TL_READ_NO_INSERT},{2,TL_READ_NO_INSERT},{3,TL_REA struct st_test test_9[] = {{4,TL_READ_HIGH_PRIORITY}}; struct st_test test_10[] ={{4,TL_WRITE}}; struct st_test test_11[] = {{0,TL_WRITE_LOW_PRIORITY},{1,TL_WRITE_LOW_PRIORITY},{2,TL_WRITE_LOW_PRIORITY},{3,TL_WRITE_LOW_PRIORITY}}; /* Many writes */ -struct st_test test_12[] = {{0,TL_WRITE_ALLOW_READ},{1,TL_WRITE_ALLOW_READ},{2,TL_WRITE_ALLOW_READ},{3,TL_WRITE_ALLOW_READ}}; /* Many writes */ -struct st_test test_13[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_WRITE_CONCURRENT_INSERT},{2,TL_WRITE_CONCURRENT_INSERT},{3,TL_WRITE_CONCURRENT_INSERT}}; -struct st_test test_14[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}}; -struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}}; -struct st_test test_16[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}}; - -struct st_test test_17[] = {{5,TL_WRITE_CONCURRENT_INSERT}}; -struct st_test test_18[] = {{5,TL_WRITE_CONCURRENT_INSERT}}; -struct st_test test_19[] = {{5,TL_READ}}; -struct st_test test_20[] = {{5,TL_READ_NO_INSERT}}; -struct st_test test_21[] = {{5,TL_WRITE}}; - - -struct st_test *tests[]= -{ - test_0, test_1, test_2, test_3, test_4, test_5, test_6, test_7, test_8, - test_9, test_10, test_11, test_12, test_13, test_14, test_15, test_16, - test_17, test_18, test_19, test_20, test_21 -}; - +struct st_test test_12[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_WRITE_CONCURRENT_INSERT},{2,TL_WRITE_CONCURRENT_INSERT},{3,TL_WRITE_CONCURRENT_INSERT}}; +struct st_test test_13[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}}; +struct st_test test_14[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}}; +struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}}; + +struct st_test *tests[] = {test_0,test_1,test_2,test_3,test_4,test_5,test_6, + test_7,test_8,test_9,test_10,test_11,test_12, + test_13,test_14,test_15}; int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test), sizeof(test_1)/sizeof(struct st_test), sizeof(test_2)/sizeof(struct st_test), @@ -1734,27 +1608,22 @@ int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test), sizeof(test_12)/sizeof(struct st_test), sizeof(test_13)/sizeof(struct st_test), sizeof(test_14)/sizeof(struct st_test), - sizeof(test_15)/sizeof(struct st_test), - sizeof(test_16)/sizeof(struct st_test), - sizeof(test_17)/sizeof(struct st_test), - sizeof(test_18)/sizeof(struct st_test), - sizeof(test_19)/sizeof(struct st_test), - sizeof(test_20)/sizeof(struct st_test), - sizeof(test_21)/sizeof(struct st_test) + sizeof(test_15)/sizeof(struct st_test) }; -static pthread_cond_t COND_thread_count; -static pthread_mutex_t LOCK_thread_count; +static mysql_cond_t COND_thread_count; +static mysql_mutex_t LOCK_thread_count; static uint thread_count; static ulong sum=0; #define MAX_LOCK_COUNT 8 +#define TEST_TIMEOUT 100000 /* The following functions is for WRITE_CONCURRENT_INSERT */ static void test_get_status(void* param __attribute__((unused)), - int concurrent_insert __attribute__((unused))) + my_bool concurrent_insert __attribute__((unused))) { } @@ -1777,7 +1646,6 @@ static void *test_thread(void *arg) { int i,j,param=*((int*) arg); THR_LOCK_DATA data[MAX_LOCK_COUNT]; - THR_LOCK_OWNER owner; THR_LOCK_INFO lock_info; THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT]; my_thread_init(); @@ -1785,7 +1653,6 @@ static void *test_thread(void *arg) printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout); thr_lock_info_init(&lock_info); - thr_lock_owner_init(&owner, &lock_info); for (i=0; i < lock_counts[param] ; i++) thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL); for (j=1 ; j < 10 ; j++) /* try locking 10 times */ @@ -1795,8 +1662,8 @@ static void *test_thread(void *arg) multi_locks[i]= &data[i]; data[i].type= tests[param][i].lock_type; } - thr_multi_lock(multi_locks, lock_counts[param], &owner); - pthread_mutex_lock(&LOCK_thread_count); + thr_multi_lock(multi_locks, lock_counts[param], &lock_info, TEST_TIMEOUT); + mysql_mutex_lock(&LOCK_thread_count); { int tmp=rand() & 7; /* Do something from 0-2 sec */ if (tmp == 0) @@ -1810,16 +1677,16 @@ static void *test_thread(void *arg) sum+=k; } } - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); thr_multi_unlock(multi_locks,lock_counts[param], THR_UNLOCK_UPDATE_STATUS); } printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout); thr_print_locks(); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; - VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ + mysql_mutex_unlock(&LOCK_thread_count); free((uchar*) arg); return 0; } @@ -1837,15 +1704,15 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) printf("Main thread: %s\n",my_thread_name()); - if ((error=pthread_cond_init(&COND_thread_count,NULL))) + if ((error= mysql_cond_init(0, &COND_thread_count, NULL))) { - fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)", + fprintf(stderr, "Got error: %d from mysql_cond_init (errno: %d)", error,errno); exit(1); } - if ((error=pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST))) + if ((error= mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST))) { - fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)", + fprintf(stderr, "Got error: %d from mysql_cond_init (errno: %d)", error,errno); exit(1); } @@ -1881,40 +1748,42 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) } #endif #ifdef HAVE_THR_SETCONCURRENCY - VOID(thr_setconcurrency(2)); + (void) thr_setconcurrency(2); #endif for (i=0 ; i < array_elements(lock_counts) ; i++) { param=(int*) malloc(sizeof(int)); *param=i; - if ((error=pthread_mutex_lock(&LOCK_thread_count))) + if ((error= mysql_mutex_lock(&LOCK_thread_count))) { - fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)", - error,errno); + fprintf(stderr, "Got error: %d from mysql_mutex_lock (errno: %d)", + error, errno); exit(1); } - if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param))) + if ((error= mysql_thread_create(0, + &tid, &thr_attr, test_thread, + (void*) param))) { - fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n", - error,errno); - pthread_mutex_unlock(&LOCK_thread_count); + fprintf(stderr, "Got error: %d from mysql_thread_create (errno: %d)\n", + error, errno); + mysql_mutex_unlock(&LOCK_thread_count); exit(1); } thread_count++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } pthread_attr_destroy(&thr_attr); - if ((error=pthread_mutex_lock(&LOCK_thread_count))) - fprintf(stderr,"Got error: %d from pthread_mutex_lock\n",error); + if ((error= mysql_mutex_lock(&LOCK_thread_count))) + fprintf(stderr, "Got error: %d from mysql_mutex_lock\n", error); while (thread_count) { - if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count))) - fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error); + if ((error= mysql_cond_wait(&COND_thread_count, &LOCK_thread_count))) + fprintf(stderr, "Got error: %d from mysql_cond_wait\n", error); } - if ((error=pthread_mutex_unlock(&LOCK_thread_count))) - fprintf(stderr,"Got error: %d from pthread_mutex_unlock\n",error); + if ((error= mysql_mutex_unlock(&LOCK_thread_count))) + fprintf(stderr, "Got error: %d from mysql_mutex_unlock\n", error); for (i=0 ; i < array_elements(locks) ; i++) thr_lock_delete(locks+i); #ifdef EXTRA_DEBUG @@ -1926,13 +1795,4 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) return 0; } -#else /* THREAD */ - -int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) -{ - printf("thr_lock disabled because we are not using threads\n"); - exit(1); -} - -#endif /* THREAD */ #endif /* MAIN */ diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 9421a3b2d98..86a7ce9684b 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc +/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -19,12 +19,12 @@ #if defined(TARGET_OS_LINUX) && !defined (__USE_UNIX98) #define __USE_UNIX98 /* To get rw locks under Linux */ #endif + #ifdef SAFE_MUTEX #define SAFE_MUTEX_DEFINED +#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ #endif -#if defined(THREAD) -#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ #include "mysys_priv.h" #include "my_static.h" #include <m_string.h> @@ -52,6 +52,7 @@ pthread_mutexattr_t my_fast_mutexattr; #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP pthread_mutexattr_t my_errorcheck_mutexattr; #endif + #ifdef SAFE_MUTEX_DEFINED static pthread_mutex_t THR_LOCK_mutex; static ulong safe_mutex_count= 0; /* Number of mutexes created */ @@ -170,12 +171,12 @@ static int safe_mutex_lazy_init_deadlock_detection(safe_mutex_t *mp) pthread_mutex_lock(&THR_LOCK_mutex); mp->id= ++safe_mutex_id; pthread_mutex_unlock(&THR_LOCK_mutex); - hash_init2(mp->locked_mutex, 64, &my_charset_bin, + my_hash_init2(mp->locked_mutex, 64, &my_charset_bin, 128, offsetof(safe_mutex_deadlock_t, id), sizeof(mp->id), 0, 0, HASH_UNIQUE); - hash_init2(mp->used_mutex, 64, &my_charset_bin, + my_hash_init2(mp->used_mutex, 64, &my_charset_bin, 128, offsetof(safe_mutex_t, id), sizeof(mp->id), @@ -185,10 +186,7 @@ static int safe_mutex_lazy_init_deadlock_detection(safe_mutex_t *mp) int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr __attribute__((unused)), - const char *name, - myf my_flags, - const char *file, - uint line) + const char *name, const char *file, uint line) { DBUG_ENTER("safe_mutex_init"); DBUG_PRINT("enter",("mutex: 0x%lx name: %s", (ulong) mp, name)); @@ -201,11 +199,9 @@ int safe_mutex_init(safe_mutex_t *mp, /* Skip the very common '&' prefix from the autogenerated name */ mp->name= name[0] == '&' ? name + 1 : name; - if (!safe_mutex_deadlock_detector) - my_flags|= MYF_NO_DEADLOCK_DETECTION; /* Deadlock detection is initialised only lazily, on first use. */ - mp->create_flags= my_flags; + mp->create_flags= safe_mutex_deadlock_detector ? MYF_NO_DEADLOCK_DETECTION : 0; #ifdef SAFE_MUTEX_DETECT_DESTROY /* @@ -229,7 +225,9 @@ int safe_mutex_init(safe_mutex_t *mp, pthread_mutex_unlock(&THR_LOCK_mutex); } #else - thread_safe_increment(safe_mutex_count, &THR_LOCK_mutex); + pthread_mutex_lock(&THR_LOCK_mutex); + safe_mutex_count++; + pthread_mutex_unlock(&THR_LOCK_mutex); #endif /* SAFE_MUTEX_DETECT_DESTROY */ DBUG_RETURN(0); } @@ -339,7 +337,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, */ pthread_mutex_lock(&THR_LOCK_mutex); - if (!hash_search(mutex_root->locked_mutex, (uchar*) &mp->id, 0)) + if (!my_hash_search(mutex_root->locked_mutex, (uchar*) &mp->id, 0)) { safe_mutex_deadlock_t *deadlock; safe_mutex_t *mutex; @@ -359,7 +357,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, mutex= mutex_root; do { - if (hash_search(mp->locked_mutex, (uchar*) &mutex->id, 0)) + if (my_hash_search(mp->locked_mutex, (uchar*) &mutex->id, 0)) { print_deadlock_warning(mp, mutex); /* Mark wrong usage to avoid future warnings for same error */ @@ -527,8 +525,8 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, - const struct timespec *abstime, - const char *file, uint line) + const struct timespec *abstime, + const char *file, uint line) { int error; safe_mutex_t save_state; @@ -637,7 +635,9 @@ int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line) mp->info= NULL; /* Get crash if double free */ } #else - thread_safe_sub(safe_mutex_count, 1, &THR_LOCK_mutex); + pthread_mutex_lock(&THR_LOCK_mutex); + safe_mutex_count--; + pthread_mutex_unlock(&THR_LOCK_mutex); #endif /* SAFE_MUTEX_DETECT_DESTROY */ DBUG_RETURN(error); } @@ -664,9 +664,9 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp) mp); pthread_mutex_unlock(&THR_LOCK_mutex); - hash_free(mp->used_mutex); - hash_free(mp->locked_mutex); - my_free(mp->locked_mutex, 0); + my_hash_free(mp->used_mutex); + my_hash_free(mp->locked_mutex); + my_free(mp->locked_mutex); mp->create_flags|= MYF_NO_DEADLOCK_DETECTION; } } @@ -711,7 +711,6 @@ void safe_mutex_end(FILE *file __attribute__((unused))) #endif /* SAFE_MUTEX_DETECT_DESTROY */ } - static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, safe_mutex_deadlock_t *locked_mutex) { @@ -774,17 +773,17 @@ static my_bool remove_from_locked_mutex(safe_mutex_t *mp, (ulong) delete_mutex, (ulong) mp, delete_mutex->id, mp->id)); - found= (safe_mutex_deadlock_t *) hash_search(mp->locked_mutex, + found= (safe_mutex_deadlock_t *) my_hash_search(mp->locked_mutex, (uchar*) &delete_mutex->id, 0); DBUG_ASSERT(found); if (found) { - if (hash_delete(mp->locked_mutex, (uchar*) found)) + if (my_hash_delete(mp->locked_mutex, (uchar*) found)) { DBUG_ASSERT(0); } if (!--found->count) - my_free(found, MYF(0)); + my_free(found); } DBUG_RETURN(0); } @@ -796,12 +795,12 @@ static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex, DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)", (ulong) mutex, (ulong) locked_mutex, mutex->id, locked_mutex->id)); - if (hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex)) + if (my_hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex)) { DBUG_ASSERT(0); } if (!--locked_mutex->count) - my_free(locked_mutex, MYF(0)); + my_free(locked_mutex); DBUG_RETURN(0); } @@ -924,4 +923,3 @@ void fastmutex_global_init(void) } #endif /* defined(MY_PTHREAD_FASTMUTEX) */ -#endif /* THREAD */ diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c index 2978d91090d..a6eb16a4b1b 100644 --- a/mysys/thr_rwlock.c +++ b/mysys/thr_rwlock.c @@ -16,7 +16,7 @@ /* Synchronization - readers / writer thread locks */ #include "mysys_priv.h" -#if defined(THREAD) && !defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && !defined(HAVE_RWLOCK_INIT) +#if defined(NEED_MY_RW_LOCK) #include <errno.h> #ifdef _WIN32 @@ -171,7 +171,7 @@ static int srw_unlock(my_rw_lock_t *rwp) * Mountain View, California 94043 */ -int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused))) +int my_rw_init(my_rw_lock_t *rwp) { pthread_condattr_t cond_attr; @@ -199,17 +199,21 @@ int my_rwlock_init(rw_lock_t *rwp, void *arg __attribute__((unused))) rwp->state = 0; rwp->waiters = 0; +#ifdef SAFE_MUTEX + rwp->write_thread = 0; +#endif return(0); } -int my_rwlock_destroy(rw_lock_t *rwp) +int my_rw_destroy(my_rw_lock_t *rwp) { #ifdef _WIN32 if (have_srwlock) return 0; /* no destroy function */ #endif + DBUG_ASSERT(rwp->state == 0); pthread_mutex_destroy( &rwp->lock ); pthread_cond_destroy( &rwp->readers ); pthread_cond_destroy( &rwp->writers ); @@ -217,7 +221,7 @@ int my_rwlock_destroy(rw_lock_t *rwp) } -int my_rw_rdlock(rw_lock_t *rwp) +int my_rw_rdlock(my_rw_lock_t *rwp) { #ifdef _WIN32 if (have_srwlock) @@ -227,7 +231,7 @@ int my_rw_rdlock(rw_lock_t *rwp) pthread_mutex_lock(&rwp->lock); /* active or queued writers */ - while ((rwp->state < 0 ) || rwp->waiters) + while (( rwp->state < 0 ) || rwp->waiters) pthread_cond_wait( &rwp->readers, &rwp->lock); rwp->state++; @@ -235,7 +239,7 @@ int my_rw_rdlock(rw_lock_t *rwp) return(0); } -int my_rw_tryrdlock(rw_lock_t *rwp) +int my_rw_tryrdlock(my_rw_lock_t *rwp) { int res; @@ -257,7 +261,7 @@ int my_rw_tryrdlock(rw_lock_t *rwp) } -int my_rw_wrlock(rw_lock_t *rwp) +int my_rw_wrlock(my_rw_lock_t *rwp) { #ifdef _WIN32 if (have_srwlock) @@ -267,16 +271,21 @@ int my_rw_wrlock(rw_lock_t *rwp) pthread_mutex_lock(&rwp->lock); rwp->waiters++; /* another writer queued */ + my_rw_lock_assert_not_write_owner(rwp); + while (rwp->state) pthread_cond_wait(&rwp->writers, &rwp->lock); rwp->state = -1; rwp->waiters--; +#ifdef SAFE_MUTEX + rwp->write_thread= pthread_self(); +#endif pthread_mutex_unlock(&rwp->lock); return(0); } -int my_rw_trywrlock(rw_lock_t *rwp) +int my_rw_trywrlock(my_rw_lock_t *rwp) { int res; @@ -292,13 +301,16 @@ int my_rw_trywrlock(rw_lock_t *rwp) { res=0; rwp->state = -1; +#ifdef SAFE_MUTEX + rwp->write_thread= pthread_self(); +#endif } pthread_mutex_unlock(&rwp->lock); return(res); } -int my_rw_unlock(rw_lock_t *rwp) +int my_rw_unlock(my_rw_lock_t *rwp) { #ifdef _WIN32 if (have_srwlock) @@ -309,9 +321,15 @@ int my_rw_unlock(rw_lock_t *rwp) ("state: %d waiters: %d", rwp->state, rwp->waiters)); pthread_mutex_lock(&rwp->lock); + DBUG_ASSERT(rwp->state != 0); + if (rwp->state == -1) /* writer releasing */ { + my_rw_lock_assert_write_owner(rwp); rwp->state= 0; /* mark as available */ +#ifdef SAFE_MUTEX + rwp->write_thread= 0; +#endif if ( rwp->waiters ) /* writers queued */ pthread_cond_signal( &rwp->writers ); @@ -320,7 +338,8 @@ int my_rw_unlock(rw_lock_t *rwp) } else { - if ( --rwp->state == 0 ) /* no more readers */ + if ( --rwp->state == 0 && /* no more readers */ + rwp->waiters) pthread_cond_signal( &rwp->writers ); } @@ -328,4 +347,126 @@ int my_rw_unlock(rw_lock_t *rwp) return(0); } +#endif /* defined(NEED_MY_RW_LOCK) */ + + +int rw_pr_init(rw_pr_lock_t *rwlock) +{ + pthread_mutex_init(&rwlock->lock, NULL); + pthread_cond_init(&rwlock->no_active_readers, NULL); + rwlock->active_readers= 0; + rwlock->writers_waiting_readers= 0; + rwlock->active_writer= FALSE; +#ifdef SAFE_MUTEX + rwlock->writer_thread= 0; +#endif + return 0; +} + + +int rw_pr_destroy(rw_pr_lock_t *rwlock) +{ + pthread_cond_destroy(&rwlock->no_active_readers); + pthread_mutex_destroy(&rwlock->lock); + return 0; +} + + +int rw_pr_rdlock(rw_pr_lock_t *rwlock) +{ + pthread_mutex_lock(&rwlock->lock); + /* + The fact that we were able to acquire 'lock' mutex means + that there are no active writers and we can acquire rd-lock. + Increment active readers counter to prevent requests for + wr-lock from succeeding and unlock mutex. + */ + rwlock->active_readers++; + pthread_mutex_unlock(&rwlock->lock); + return 0; +} + + +int rw_pr_wrlock(rw_pr_lock_t *rwlock) +{ + pthread_mutex_lock(&rwlock->lock); + + if (rwlock->active_readers != 0) + { + /* There are active readers. We have to wait until they are gone. */ + rwlock->writers_waiting_readers++; + + while (rwlock->active_readers != 0) + pthread_cond_wait(&rwlock->no_active_readers, &rwlock->lock); + + rwlock->writers_waiting_readers--; + } + + /* + We own 'lock' mutex so there is no active writers. + Also there are no active readers. + This means that we can grant wr-lock. + Not releasing 'lock' mutex until unlock will block + both requests for rd and wr-locks. + Set 'active_writer' flag to simplify unlock. + + Thanks to the fact wr-lock/unlock in the absence of + contention from readers is essentially mutex lock/unlock + with a few simple checks make this rwlock implementation + wr-lock optimized. + */ + rwlock->active_writer= TRUE; +#ifdef SAFE_MUTEX + rwlock->writer_thread= pthread_self(); #endif + return 0; +} + + +int rw_pr_unlock(rw_pr_lock_t *rwlock) +{ + if (rwlock->active_writer) + { + /* We are unlocking wr-lock. */ +#ifdef SAFE_MUTEX + rwlock->writer_thread= 0; +#endif + rwlock->active_writer= FALSE; + if (rwlock->writers_waiting_readers) + { + /* + Avoid expensive cond signal in case when there is no contention + or it is wr-only. + + Note that from view point of performance it would be better to + signal on the condition variable after unlocking mutex (as it + reduces number of contex switches). + + Unfortunately this would mean that such rwlock can't be safely + used by MDL subsystem, which relies on the fact that it is OK + to destroy rwlock once it is in unlocked state. + */ + pthread_cond_signal(&rwlock->no_active_readers); + } + pthread_mutex_unlock(&rwlock->lock); + } + else + { + /* We are unlocking rd-lock. */ + pthread_mutex_lock(&rwlock->lock); + rwlock->active_readers--; + if (rwlock->active_readers == 0 && + rwlock->writers_waiting_readers) + { + /* + If we are last reader and there are waiting + writers wake them up. + */ + pthread_cond_signal(&rwlock->no_active_readers); + } + pthread_mutex_unlock(&rwlock->lock); + } + return 0; +} + + diff --git a/mysys/tree.c b/mysys/tree.c index eba058b22f8..03c4ac5b36b 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -183,7 +183,7 @@ static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); delete_tree_element(tree,element->right); if (tree->with_delete) - my_free((char*) element,MYF(0)); + my_free(element); } } @@ -329,7 +329,7 @@ int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg) if (tree->free) (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size; - my_free((uchar*) element,MYF(0)); + my_free(element); tree->elements_in_tree--; return 0; } diff --git a/mysys/trie.c b/mysys/trie.c deleted file mode 100644 index 5738b9b866b..00000000000 --- a/mysys/trie.c +++ /dev/null @@ -1,236 +0,0 @@ -/* Copyright (C) 2005 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - Implementation of trie and Aho-Corasick automaton. - Supports only charsets that can be compared byte-wise. - - TODO: - Add character frequencies. Can increase lookup speed - up to 30%. - Implement character-wise comparision. -*/ - - -#include "mysys_priv.h" -#include <m_string.h> -#include <my_trie.h> -#include <my_base.h> - - -/* - SYNOPSIS - TRIE *trie_init (TRIE *trie, CHARSET_INFO *charset); - - DESCRIPTION - Allocates or initializes a `TRIE' object. If `trie' is a `NULL' - pointer, the function allocates, initializes, and returns a new - object. Otherwise, the object is initialized and the address of - the object is returned. If `trie_init()' allocates a new object, - it will be freed when `trie_free()' is called. - - RETURN VALUE - An initialized `TRIE*' object. `NULL' if there was insufficient - memory to allocate a new object. -*/ - -TRIE *trie_init (TRIE *trie, CHARSET_INFO *charset) -{ - MEM_ROOT mem_root; - DBUG_ENTER("trie_init"); - DBUG_ASSERT(charset); - init_alloc_root(&mem_root, - (sizeof(TRIE_NODE) * 128) + ALLOC_ROOT_MIN_BLOCK_SIZE, - sizeof(TRIE_NODE) * 128); - if (! trie) - { - if (! (trie= (TRIE *)alloc_root(&mem_root, sizeof(TRIE)))) - { - free_root(&mem_root, MYF(0)); - DBUG_RETURN(NULL); - } - } - - memcpy(&trie->mem_root, &mem_root, sizeof(MEM_ROOT)); - trie->root.leaf= 0; - trie->root.c= 0; - trie->root.next= NULL; - trie->root.links= NULL; - trie->root.fail= NULL; - trie->charset= charset; - trie->nnodes= 0; - trie->nwords= 0; - DBUG_RETURN(trie); -} - - -/* - SYNOPSIS - void trie_free (TRIE *trie); - trie - valid pointer to `TRIE' - - DESCRIPTION - Frees the memory allocated for a `trie'. - - RETURN VALUE - None. -*/ - -void trie_free (TRIE *trie) -{ - MEM_ROOT mem_root; - DBUG_ENTER("trie_free"); - DBUG_ASSERT(trie); - memcpy(&mem_root, &trie->mem_root, sizeof(MEM_ROOT)); - free_root(&mem_root, MYF(0)); - DBUG_VOID_RETURN; -} - - -/* - SYNOPSIS - my_bool trie_insert (TRIE *trie, const uchar *key, uint keylen); - trie - valid pointer to `TRIE' - key - valid pointer to key to insert - keylen - non-0 key length - - DESCRIPTION - Inserts new key into trie. - - RETURN VALUE - Upon successful completion, `trie_insert' returns `FALSE'. Otherwise - `TRUE' is returned. - - NOTES - If this function fails you must assume `trie' is broken. - However it can be freed with trie_free(). -*/ - -my_bool trie_insert (TRIE *trie, const uchar *key, uint keylen) -{ - TRIE_NODE *node; - TRIE_NODE *next; - uchar p; - uint k; - DBUG_ENTER("trie_insert"); - DBUG_ASSERT(trie && key && keylen); - node= &trie->root; - trie->root.fail= NULL; - for (k= 0; k < keylen; k++) - { - p= key[k]; - for (next= node->links; next; next= next->next) - if (next->c == p) - break; - - if (! next) - { - TRIE_NODE *tmp= (TRIE_NODE *)alloc_root(&trie->mem_root, - sizeof(TRIE_NODE)); - if (! tmp) - DBUG_RETURN(TRUE); - tmp->leaf= 0; - tmp->c= p; - tmp->links= tmp->fail= tmp->next= NULL; - trie->nnodes++; - if (! node->links) - { - node->links= tmp; - } - else - { - for (next= node->links; next->next; next= next->next) /* no-op */; - next->next= tmp; - } - node= tmp; - } - else - { - node= next; - } - } - node->leaf= keylen; - trie->nwords++; - DBUG_RETURN(FALSE); -} - - -/* - SYNOPSIS - my_bool trie_prepare (TRIE *trie); - trie - valid pointer to `TRIE' - - DESCRIPTION - Constructs Aho-Corasick automaton. - - RETURN VALUE - Upon successful completion, `trie_prepare' returns `FALSE'. Otherwise - `TRUE' is returned. -*/ - -my_bool ac_trie_prepare (TRIE *trie) -{ - TRIE_NODE **tmp_nodes; - TRIE_NODE *node; - uint32 fnode= 0; - uint32 lnode= 0; - DBUG_ENTER("trie_prepare"); - DBUG_ASSERT(trie); - - tmp_nodes= (TRIE_NODE **)my_malloc(trie->nnodes * sizeof(TRIE_NODE *), MYF(0)); - if (! tmp_nodes) - DBUG_RETURN(TRUE); - - trie->root.fail= &trie->root; - for (node= trie->root.links; node; node= node->next) - { - node->fail= &trie->root; - tmp_nodes[lnode++]= node; - } - - while (fnode < lnode) - { - TRIE_NODE *current= (TRIE_NODE *)tmp_nodes[fnode++]; - for (node= current->links; node; node= node->next) - { - TRIE_NODE *fail= current->fail; - tmp_nodes[lnode++]= node; - while (! (node->fail= trie_goto(&trie->root, fail, node->c))) - fail= fail->fail; - } - } - my_free((uchar*)tmp_nodes, MYF(0)); - DBUG_RETURN(FALSE); -} - - -/* - SYNOPSIS - void ac_trie_init (TRIE *trie, AC_TRIE_STATE *state); - trie - valid pointer to `TRIE' - state - value pointer to `AC_TRIE_STATE' - - DESCRIPTION - Initializes `AC_TRIE_STATE' object. -*/ - -void ac_trie_init (TRIE *trie, AC_TRIE_STATE *state) -{ - DBUG_ENTER("ac_trie_init"); - DBUG_ASSERT(trie && state); - state->trie= trie; - state->node= &trie->root; - DBUG_VOID_RETURN; -} diff --git a/mysys/typelib.c b/mysys/typelib.c index 97acd476c20..f724e5b27a2 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2011, 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 @@ -20,14 +20,14 @@ #include <m_ctype.h> -static const char field_separator=','; +#define is_field_separator(X) ((X) == ',' || (X) == '=') int find_type_with_warning(const char *x, TYPELIB *typelib, const char *option) { int res; const char **ptr; - if ((res= find_type((char *) x, typelib, 2)) <= 0) + if ((res= find_type((char *) x, typelib, FIND_TYPE_BASIC)) <= 0) { ptr= typelib->type_names; if (!*x) @@ -43,48 +43,47 @@ int find_type_with_warning(const char *x, TYPELIB *typelib, const char *option) } -uint find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) +int find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) { int res; if ((res= find_type_with_warning(x, typelib, option)) <= 0) exit(1); - return (uint) res; + return res; } -/* +/** Search after a string in a list of strings. Endspace in x is not compared. - SYNOPSIS - find_type() - x String to find - lib TYPELIB (struct of pointer to values + count) - full_name bitmap of what to do - If & 1 accept only whole names - If & 2 don't expand if half field - If & 4 allow #number# as type - If & 8 use ',' as string terminator - - NOTES - If part, uniq field is found and full_name == 0 then x is expanded - to full field. - - RETURN - -1 Too many matching values - 0 No matching value + @param x String to find + @param typelib TYPELIB (struct of pointer to values + count) + @param flags flags to tune behaviour: a combination of + FIND_TYPE_NO_PREFIX + FIND_TYPE_ALLOW_NUMBER + FIND_TYPE_COMMA_TERM. + FIND_TYPE_NO_OVERWRITE can be passed but is + superfluous (is always implicitely on). + + @retval + -1 Too many matching values + @retval + 0 No matching value + @retval >0 Offset+1 in typelib for matched string */ -int find_type(char *x, const TYPELIB *typelib, uint full_name) +int find_type(const char *x, const TYPELIB *typelib, uint flags) { int find,pos; int UNINIT_VAR(findpos); /* guarded by find */ - reg1 char * i; - reg2 const char *j; + const char *i; + const char *j; DBUG_ENTER("find_type"); DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) typelib)); + DBUG_ASSERT(!(flags & ~(FIND_TYPE_NO_PREFIX | FIND_TYPE_ALLOW_NUMBER | + FIND_TYPE_NO_OVERWRITE | FIND_TYPE_COMMA_TERM))); if (!typelib->count) { DBUG_PRINT("exit",("no count")); @@ -94,24 +93,26 @@ int find_type(char *x, const TYPELIB *typelib, uint full_name) for (pos=0 ; (j=typelib->type_names[pos]) ; pos++) { for (i=x ; - *i && (!(full_name & 8) || *i != field_separator) && + *i && (!(flags & FIND_TYPE_COMMA_TERM) || !is_field_separator(*i)) && my_toupper(&my_charset_latin1,*i) == my_toupper(&my_charset_latin1,*j) ; i++, j++) ; if (! *j) { while (*i == ' ') i++; /* skip_end_space */ - if (! *i || ((full_name & 8) && *i == field_separator)) + if (! *i || ((flags & FIND_TYPE_COMMA_TERM) && is_field_separator(*i))) DBUG_RETURN(pos+1); } - if ((!*i && (!(full_name & 8) || *i != field_separator)) && - (!*j || !(full_name & 1))) + if ((!*i && + (!(flags & FIND_TYPE_COMMA_TERM) || !is_field_separator(*i))) && + (!*j || !(flags & FIND_TYPE_NO_PREFIX))) { find++; findpos=pos; } } - if (find == 0 && (full_name & 4) && x[0] == '#' && strend(x)[-1] == '#' && + if (find == 0 && (flags & FIND_TYPE_ALLOW_NUMBER) && x[0] == '#' && + strend(x)[-1] == '#' && (findpos=atoi(x+1)-1) >= 0 && (uint) findpos < typelib->count) find=1; else if (find == 0 || ! x[0]) @@ -119,19 +120,21 @@ int find_type(char *x, const TYPELIB *typelib, uint full_name) DBUG_PRINT("exit",("Couldn't find type")); DBUG_RETURN(0); } - else if (find != 1 || (full_name & 1)) + else if (find != 1 || (flags & FIND_TYPE_NO_PREFIX)) { DBUG_PRINT("exit",("Too many possybilities")); DBUG_RETURN(-1); } - if (!(full_name & 2)) - (void) strmov(x,typelib->type_names[findpos]); DBUG_RETURN(findpos+1); } /* find_type */ - /* Get name of type nr 'nr' */ - /* Warning first type is 1, 0 = empty field */ +/** + Get name of type nr + + @note + first type is 1, 0 = empty field +*/ void make_type(register char * to, register uint nr, register TYPELIB *typelib) @@ -145,8 +148,12 @@ void make_type(register char * to, register uint nr, } /* make_type */ - /* Get type */ - /* Warning first type is 0 */ +/** + Get type + + @note + first type is 0 +*/ const char *get_type(TYPELIB *typelib, uint nr) { @@ -156,18 +163,16 @@ const char *get_type(TYPELIB *typelib, uint nr) } -/* +/** Create an integer value to represent the supplied comma-seperated string where each string in the TYPELIB denotes a bit position. - SYNOPSIS - find_typeset() - x string to decompose - lib TYPELIB (struct of pointer to values + count) - err index (not char position) of string element which was not + @param x string to decompose + @param lib TYPELIB (struct of pointer to values + count) + @param err index (not char position) of string element which was not found or 0 if there was no error - RETURN + @retval a integer representation of the supplied string */ @@ -190,11 +195,11 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) { (*err)++; i= x; - while (*x && *x != field_separator) + while (*x && !is_field_separator(*x)) x++; - if (x[0] && x[1]) /* skip separator if found */ + if (x[0] && x[1]) /* skip separator if found */ x++; - if ((find= find_type(i, lib, 2 | 8) - 1) < 0) + if ((find= find_type(i, lib, FIND_TYPE_COMMA_TERM) - 1) < 0) DBUG_RETURN(0); result|= (ULL(1) << find); } @@ -203,16 +208,15 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) } /* find_set */ -/* +/** Create a copy of a specified TYPELIB structure. - SYNOPSIS - copy_typelib() - root pointer to a MEM_ROOT object for allocations - from pointer to a source TYPELIB structure + @param root pointer to a MEM_ROOT object for allocations + @param from pointer to a source TYPELIB structure - RETURN - pointer to the new TYPELIB structure on successful copy, or + @retval + pointer to the new TYPELIB structure on successful copy + @retval NULL otherwise */ @@ -252,3 +256,140 @@ TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from) return to; } + + +static const char *on_off_default_names[]= { "off","on","default", 0}; +static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1, + "", on_off_default_names, 0}; + +/** + Parse a TYPELIB name from the buffer + + @param lib Set of names to scan for. + @param strpos INOUT Start of the buffer (updated to point to the next + character after the name) + @param end End of the buffer + + @note + The buffer is assumed to contain one of the names specified in the TYPELIB, + followed by comma, '=', or end of the buffer. + + @retval + 0 No matching name + @retval + >0 Offset+1 in typelib for matched name +*/ + +static uint parse_name(const TYPELIB *lib, const char **strpos, const char *end) +{ + const char *pos= *strpos; + uint find= find_type(pos, lib, FIND_TYPE_COMMA_TERM); + for (; pos != end && *pos != '=' && *pos !=',' ; pos++); + *strpos= pos; + return find; +} + +/** + Parse and apply a set of flag assingments + + @param lib Flag names + @param default_name Number of "default" in the typelib + @param cur_set Current set of flags (start from this state) + @param default_set Default set of flags (use this for assign-default + keyword and flag=default assignments) + @param str String to be parsed + @param length Length of the string + @param err_pos OUT If error, set to point to start of wrong set string + NULL on success + @param err_len OUT If error, set to the length of wrong set string + + @details + Parse a set of flag assignments, that is, parse a string in form: + + param_name1=value1,param_name2=value2,... + + where the names are specified in the TYPELIB, and each value can be + either 'on','off', or 'default'. Setting the same name twice is not + allowed. + + Besides param=val assignments, we support the "default" keyword (keyword + #default_name in the typelib). It can be used one time, if specified it + causes us to build the new set over the default_set rather than cur_set + value. + + @note + it's not charset aware + + @retval + Parsed set value if (*errpos == NULL), otherwise undefined +*/ + +my_ulonglong find_set_from_flags(const TYPELIB *lib, uint default_name, + my_ulonglong cur_set, my_ulonglong default_set, + const char *str, uint length, + char **err_pos, uint *err_len) +{ + const char *end= str + length; + my_ulonglong flags_to_set= 0, flags_to_clear= 0, res; + my_bool set_defaults= 0; + + *err_pos= 0; /* No error yet */ + if (str != end) + { + const char *start= str; + for (;;) + { + const char *pos= start; + uint flag_no, value; + + if (!(flag_no= parse_name(lib, &pos, end))) + goto err; + + if (flag_no == default_name) + { + /* Using 'default' twice isn't allowed. */ + if (set_defaults) + goto err; + set_defaults= TRUE; + } + else + { + my_ulonglong bit= (1ULL << (flag_no - 1)); + /* parse the '=on|off|default' */ + if ((flags_to_clear | flags_to_set) & bit || + pos >= end || *pos++ != '=' || + !(value= parse_name(&on_off_default_typelib, &pos, end))) + goto err; + + if (value == 1) /* this is '=off' */ + flags_to_clear|= bit; + else if (value == 2) /* this is '=on' */ + flags_to_set|= bit; + else /* this is '=default' */ + { + if (default_set & bit) + flags_to_set|= bit; + else + flags_to_clear|= bit; + } + } + if (pos >= end) + break; + + if (*pos++ != ',') + goto err; + + start=pos; + continue; + err: + *err_pos= (char*)start; + *err_len= end - start; + break; + } + } + res= set_defaults? default_set : cur_set; + res|= flags_to_set; + res&= ~flags_to_clear; + return res; +} + diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index 6ee79cb8e87..ddc06a3ae5e 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -193,6 +193,8 @@ uint32 wt_success_stats; static my_atomic_rwlock_t cycle_stats_lock, wait_stats_lock, success_stats_lock; +extern PSI_cond_key key_WT_RESOURCE_cond; + #ifdef SAFE_STATISTICS #define incr(VAR, LOCK) \ do { \ @@ -253,7 +255,7 @@ struct st_wt_resource { uint waiter_count; enum { ACTIVE, FREE } state; #ifndef DBUG_OFF - pthread_mutex_t *cond_mutex; /* a mutex for the 'cond' below */ + mysql_mutex_t *cond_mutex; /* a mutex for the 'cond' below */ #endif /* before the 'lock' all elements are mutable, after (and including) - @@ -301,7 +303,7 @@ struct st_wt_resource { #else rw_lock_t lock; #endif - pthread_cond_t cond; /* the corresponding mutex is provided by the caller */ + mysql_cond_t cond; /* the corresponding mutex is provided by the caller */ DYNAMIC_ARRAY owners; }; @@ -398,7 +400,7 @@ static void wt_resource_init(uchar *arg) bzero(rc, sizeof(*rc)); rc_rwlock_init(rc); - pthread_cond_init(&rc->cond, 0); + mysql_cond_init(key_WT_RESOURCE_cond, &rc->cond, 0); my_init_dynamic_array(&rc->owners, sizeof(WT_THD *), 0, 5); DBUG_VOID_RETURN; } @@ -416,7 +418,7 @@ static void wt_resource_destroy(uchar *arg) DBUG_ASSERT(rc->owners.elements == 0); rc_rwlock_destroy(rc); - pthread_cond_destroy(&rc->cond); + mysql_cond_destroy(&rc->cond); delete_dynamic(&rc->owners); DBUG_VOID_RETURN; } @@ -795,7 +797,7 @@ static int deadlock(WT_THD *thd, WT_THD *blocker, uint depth, { DBUG_PRINT("wt", ("killing %s", arg.victim->name)); arg.victim->killed= 1; - pthread_cond_broadcast(&arg.victim->waiting_for->cond); + mysql_cond_broadcast(&arg.victim->waiting_for->cond); rc_unlock(arg.victim->waiting_for); ret= WT_OK; } @@ -1029,11 +1031,11 @@ retry: called by a *waiter* (thd) to start waiting It's supposed to be a drop-in replacement for - pthread_cond_timedwait(), and it takes mutex as an argument. + mysql_cond_timedwait(), and it takes mutex as an argument. @return one of WT_TIMEOUT, WT_DEADLOCK, WT_OK */ -int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) +int wt_thd_cond_timedwait(WT_THD *thd, mysql_mutex_t *mutex) { int ret= WT_TIMEOUT; struct timespec timeout; @@ -1048,7 +1050,7 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) DBUG_ASSERT(rc->cond_mutex == mutex); else rc->cond_mutex= mutex; - safe_mutex_assert_owner(mutex); + mysql_mutex_assert_owner(mutex); #endif before= starttime= my_hrtime(); @@ -1061,7 +1063,7 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) end_wait_time= starttime.val *1000 + (*thd->timeout_short)*ULL(1000000); set_timespec_time_nsec(timeout, end_wait_time); if (ret == WT_TIMEOUT && !thd->killed) - ret= pthread_cond_timedwait(&rc->cond, mutex, &timeout); + ret= mysql_cond_timedwait(&rc->cond, mutex, &timeout); if (ret == WT_TIMEOUT && !thd->killed) { int r= deadlock(thd, thd, 0, *thd->deadlock_search_depth_long); @@ -1074,7 +1076,7 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) end_wait_time= starttime.val *1000 + (*thd->timeout_long)*ULL(1000000); set_timespec_time_nsec(timeout, end_wait_time); if (!thd->killed) - ret= pthread_cond_timedwait(&rc->cond, mutex, &timeout); + ret= mysql_cond_timedwait(&rc->cond, mutex, &timeout); } } after= my_hrtime(); @@ -1120,10 +1122,10 @@ void wt_thd_release(WT_THD *thd, const WT_RESOURCE_ID *resid) delete_dynamic_element(&rc->owners, j); if (rc->owners.elements == 0) { - pthread_cond_broadcast(&rc->cond); + mysql_cond_broadcast(&rc->cond); #ifndef DBUG_OFF if (rc->cond_mutex) - safe_mutex_assert_owner(rc->cond_mutex); + mysql_mutex_assert_owner(rc->cond_mutex); #endif } unlock_lock_and_free_resource(thd, rc); diff --git a/mysys/wqueue.c b/mysys/wqueue.c index fcc0a39725d..b6f52ba5c31 100644 --- a/mysys/wqueue.c +++ b/mysys/wqueue.c @@ -130,7 +130,7 @@ void wqueue_release_queue(WQUEUE *wqueue) do { thread= next; - pthread_cond_signal(&thread->suspend); + mysql_cond_signal(&thread->suspend); next= thread->next; thread->next= NULL; } @@ -158,7 +158,7 @@ void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue) if (first_type == MY_PTHREAD_LOCK_WRITE) { /* release first waiting for write lock */ - pthread_cond_signal(&next->suspend); + mysql_cond_signal(&next->suspend); if (next == last) wqueue->last_thread= NULL; else @@ -184,7 +184,7 @@ void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue) else { /* release waiting for read lock */ - pthread_cond_signal(&thread->suspend); + mysql_cond_signal(&thread->suspend); thread->next= NULL; } } while (thread != last); @@ -204,7 +204,7 @@ void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue) void wqueue_add_and_wait(WQUEUE *wqueue, struct st_my_thread_var *thread, - pthread_mutex_t *lock) + mysql_mutex_t *lock) { DBUG_ENTER("wqueue_add_and_wait"); DBUG_PRINT("enter", @@ -215,7 +215,7 @@ void wqueue_add_and_wait(WQUEUE *wqueue, { DBUG_PRINT("info", ("wait... cond: 0x%lx mutex: 0x%lx", (ulong) &thread->suspend, (ulong) lock)); - pthread_cond_wait(&thread->suspend, lock); + mysql_cond_wait(&thread->suspend, lock); DBUG_PRINT("info", ("wait done cond: 0x%lx mutex: 0x%lx next: 0x%lx", (ulong) &thread->suspend, (ulong) lock, (ulong) thread->next)); |