diff options
Diffstat (limited to 'mysys')
45 files changed, 1267 insertions, 1154 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index c3c4d6b5246..e32a722ff05 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -23,8 +23,8 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.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_gethostbyname.c - my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_handler.c my_init.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_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 @@ -65,11 +65,6 @@ IF(HAVE_MLOCK) SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_lockmem.c) ENDIF() -IF(UNIX) - # some workarounds - SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_port.c) -ENDIF() - ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES}) TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY} ${LIBNSL} ${LIBM} ${LIBRT}) diff --git a/mysys/Makefile.am b/mysys/Makefile.am deleted file mode 100644 index da5a2fa0b3b..00000000000 --- a/mysys/Makefile.am +++ /dev/null @@ -1,170 +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@ @RDTSC_SPARC_ASSEMBLY@ \ - -I$(top_builddir)/include \ - -I$(top_srcdir)/include -I$(srcdir) -pkglib_LIBRARIES = libmysys.a -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_a_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_seek.c my_read.c \ - my_pread.c my_write.c my_getpagesize.c \ - my_crc32.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_once.c mulalloc.c \ - my_alloc.c my_new.cc my_atomic.c lf_hash.c \ - lf_dynarray.c lf_alloc-pin.c \ - my_fopen.c my_fstream.c my_getsystime.c \ - my_error.c errors.c my_div.c my_mess.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 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 list.c hash.c array.c string.c typelib.c \ - my_copy.c my_lib.c \ - my_delete.c my_rename.c my_redel.c \ - my_chsize.c my_quick.c my_lockmem.c my_static.c \ - my_sync.c my_getopt.c my_mkdir.c \ - default.c my_compress.c checksum.c \ - my_port.c my_sleep.c \ - charset.c charset-def.c my_bitmap.c my_bit.c md5.c \ - my_safehash.c my_rnd.c my_uuid.c my_chmod.c wqueue.c \ - my_gethostbyname.c rijndael.c my_aes.c sha1.c \ - my_handler.c my_largepage.c \ - my_memmem.c stacktrace.c \ - my_windac.c my_access.c base64.c my_libwrap.c \ - my_rdtsc.c - -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_a_SOURCES += 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_winerr.c \ - my_winfile.c \ - my_timer_cycles.il -libmysys_a_LIBADD = @THREAD_LOBJECTS@ -# 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@ - -libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@ - -# 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) - -# -# 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) - -if HAVE_DTRACE_DASH_G -libmysys_a_LIBADD += probes_mysql.o -libmysys_a_DEPENDENCIES += probes_mysql.o dtrace_files dtrace_providers -CLEANFILES = probes_mysql.o dtrace_files dtrace_providers -DTRACEFILES = mf_keycache.o -DTRACEPROVIDER = probes_mysql.d -CLEANFILES += $(DTRACEPROVIDER) dtrace_sources - -dtrace_files: - echo $(DTRACEFILES) > $@ -dtrace_providers: probes_mysql.d - echo $(DTRACEPROVIDER) > $@ -probes_mysql.d: - -$(RM) -f probes_mysql.d - $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d - echo timestamp > dtrace_sources - -probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES) - $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@ -endif diff --git a/mysys/charset.c b/mysys/charset.c index 7f414fbad97..f859ceae394 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -415,6 +415,7 @@ 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; } @@ -526,14 +527,17 @@ uint get_charset_number(const char *charset_name, uint cs_flags) 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() */ } @@ -542,6 +546,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 */ @@ -586,8 +592,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)) + + if (cs_number >= array_elements(all_charsets)) return NULL; cs=get_internal_charset(cs_number, flags); diff --git a/mysys/default.c b/mysys/default.c index 0e0883e1fcf..fe070f42748 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 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 @@ -61,12 +61,31 @@ 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 */ -const char *args_separator= "----args-separator----"; +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) */ @@ -121,7 +140,7 @@ static int search_default_file_with_ext(Process_option_func func, - 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: ~/ @@ -140,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 @@ -167,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 @@ -189,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 @@ -236,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; } } @@ -317,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; @@ -458,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); @@ -470,17 +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 */ - /* set arguments separator */ - res[1]= (char *)args_separator; - for (i=2 ; i < (uint) *argc ; i++) - res[i]=argv[0][i]; - res[i]=0; /* End pointer */ + 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) @@ -514,7 +585,7 @@ int my_load_defaults(const char *conf_file, const char **groups, or a forced default file */ if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ - (args.elements + *argc + 1 + 1) *sizeof(char*)))) + (args.elements + *argc + 1 + args_sep) *sizeof(char*)))) goto err; res= (char**) (ptr+sizeof(alloc)); @@ -535,16 +606,19 @@ int my_load_defaults(const char *conf_file, const char **groups, --*argc; ++*argv; /* skip argument */ } - /* set arguments separator for arguments from config file and - command line */ - res[args.elements+1]= (char *)args_separator; + 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+1), (char*) ((*argv)+1), + memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1), (*argc-1)*sizeof(char*)); - res[args.elements+ *argc+1]=0; /* last null */ + res[args.elements+ *argc+args_sep]=0; /* last null */ - (*argc)+=args.elements+1; + (*argc)+=args.elements+args_sep; *argv= (char**) res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ delete_dynamic(&args); @@ -554,7 +628,7 @@ 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++) - if ((*argv)[i] != args_separator) /* skip arguments separator */ + if (!my_getopt_is_args_separator((*argv)[i])) /* skip arguments separator */ printf("%s ", (*argv)[i]); puts(""); exit(0); @@ -1158,7 +1232,7 @@ 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> */ diff --git a/mysys/errors.c b/mysys/errors.c index 5c8afff6395..2a9b3e770d2 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -52,8 +52,8 @@ const char *globerrs[GLOBERRS]= "File '%s' (fileno: %d) was not closed", "Can't change ownership of the file '%s' (Errcode: %d)", "Can't change permissions of the file '%s' (Errcode: %d)", + "Can't seek in file '%s' (Errcode: %d)" "Can't change mode for file '%s' to 0x%lx (Error: %d)", - "Can't do seek on file '%s' (Errcode: %d)", "Warning: Can't copy ownership for file '%s' (Error: %d)" }; @@ -97,8 +97,8 @@ 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_SEEK) = "Can't do seek on file '%s' (Errcode: %d)"; EE(EE_CANT_COPY_OWNERSHIP)= "Warning: Can't copy ownership for file '%s' (Error: %d)"; } #endif diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 3eec91236c5..ab88828d2f6 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -146,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; /* @@ -188,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; } @@ -327,34 +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; + int npins; + void *list; + void **addr= NULL; void *first= NULL, *last= NULL; LF_PINBOX *pinbox= pins->pinbox; 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; 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_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 aa7e4be03eb..4a548fe330f 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -55,15 +55,10 @@ static void my_aiowait(my_aio_result *result); #endif #include <errno.h> -#ifdef THREAD #define lock_append_buffer(info) \ mysql_mutex_lock(&(info)->append_buffer_lock) #define unlock_append_buffer(info) \ mysql_mutex_unlock(&(info)->append_buffer_lock) -#else -#define lock_append_buffer(info) -#define unlock_append_buffer(info) -#endif #define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1)) #define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1)) @@ -116,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; } @@ -173,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)) { /* @@ -193,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 */ @@ -205,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) @@ -263,12 +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 mysql_mutex_init(key_IO_CACHE_append_buffer_lock, &info->append_buffer_lock, MY_MUTEX_INIT_FAST); -#endif } -#if defined(SAFE_MUTEX) && defined(THREAD) +#if defined(SAFE_MUTEX) else { /* Clear mutex so that safe_mutex will notice that it's not initialized */ @@ -485,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. */ @@ -529,7 +516,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) 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) { /* @@ -572,7 +559,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) } 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) { @@ -601,7 +588,6 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) } -#ifdef THREAD /* Prepare IO_CACHE for shared use. @@ -1056,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; @@ -1064,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)); @@ -1162,7 +1148,6 @@ static void copy_to_read_buffer(IO_CACHE *write_cache, write_length-= copy_length; } } -#endif /*THREAD*/ /* @@ -1203,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); @@ -1220,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); @@ -1254,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; @@ -1431,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; @@ -1441,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); @@ -1462,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; @@ -1569,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 @@ -1593,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; @@ -1615,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); @@ -1639,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; @@ -1683,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; @@ -1735,16 +1714,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))) @@ -1755,10 +1728,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) { @@ -1771,7 +1742,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 @@ -1780,7 +1750,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; /* @@ -1789,7 +1758,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; @@ -1803,7 +1772,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 @@ -1815,7 +1784,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; @@ -1859,13 +1828,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)) { @@ -1884,9 +1851,7 @@ int end_io_cache(IO_CACHE *info) { /* Destroy allocated mutex */ info->type= TYPE_NOT_SET; -#ifdef THREAD mysql_mutex_destroy(&info->append_buffer_lock); -#endif } #ifdef THREAD info->share= 0; diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index c74504e4fa8..85631e9741b 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -90,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 mysql_mutex_lock(&info->append_buffer_lock); -#endif + #ifndef DBUG_OFF /* Make sure EOF is where we think it is. Note that we cannot just use @@ -112,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 mysql_mutex_unlock(&info->append_buffer_lock); -#endif return res; } diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 41b93517655..80111b3245d 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -318,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, 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 @@ -379,7 +374,6 @@ static void keycache_debug_print(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)) @@ -391,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) @@ -685,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 @@ -698,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 @@ -727,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, @@ -741,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); @@ -1022,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. @@ -1203,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 @@ -1376,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 */ @@ -1436,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) @@ -1662,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 } @@ -1679,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))); @@ -1701,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 } @@ -1733,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 */ @@ -1769,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; } @@ -1836,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; @@ -1850,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; @@ -1972,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 */ @@ -2214,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 | @@ -2346,7 +2300,6 @@ restart: from the LRU ring. */ -#ifdef THREAD if (! keycache->used_last) { /* @@ -2379,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 @@ -2868,11 +2818,6 @@ 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++; @@ -2931,9 +2876,6 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache, /* 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) @@ -2972,20 +2914,6 @@ 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) - { - 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)); - } - DBUG_RETURN(block->buffer); - } -#endif next_block: buff+= read_length; filepos+= read_length+offset; @@ -4262,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++; @@ -5488,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 @@ -5507,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; diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index c6e6a3a429e..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 @@ -192,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; diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 22199758112..be39ac50731 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -21,17 +21,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. */ @@ -100,18 +96,14 @@ void create_last_word_mask(MY_BITMAP *map) static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused))) { -#ifdef THREAD if (map->mutex) mysql_mutex_lock(map->mutex); -#endif } static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) { -#ifdef THREAD if (map->mutex) mysql_mutex_unlock(map->mutex); -#endif } @@ -123,30 +115,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(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= (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; @@ -161,10 +147,8 @@ void bitmap_free(MY_BITMAP *map) DBUG_ENTER("bitmap_free"); if (map->bitmap) { -#ifdef THREAD if (map->mutex) mysql_mutex_destroy(map->mutex); -#endif my_free(map->bitmap); map->bitmap=0; } diff --git a/mysys/my_handler.c b/mysys/my_compare.c index 2cbe65bebba..4629a3bae18 100644 --- a/mysys/my_handler.c +++ b/mysys/my_compare.c @@ -1,26 +1,23 @@ -/* Copyright (C) 2002-2006 MySQL AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. +/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ + 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 <m_ctype.h> #include <my_base.h> -#include <my_handler.h> +#include <my_compare.h> #include <my_sys.h> -#include "my_handler_errors.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, @@ -28,8 +25,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); } @@ -121,8 +117,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; @@ -555,7 +551,6 @@ found: return 0; } /* ha_key_cmp */ - /* Find the first NULL value in index-suffix values tuple @@ -645,37 +640,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. -*/ - -static const char **get_handler_error_messages() -{ - return handler_error_messages; -} - -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/ma_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(get_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_fopen.c b/mysys/my_fopen.c index ebe5c7ddf80..9bc740c80fd 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 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 @@ -18,6 +18,10 @@ #include <errno.h> #include "mysys_err.h" +#if defined(__FreeBSD__) +extern int getosreldate(void); +#endif + static void make_ftype(char * to,int flag); /* @@ -89,7 +93,135 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) } /* my_fopen */ - /* Close a stream */ +#if defined(_WIN32) + +static FILE *my_win_freopen(const char *path, const char *mode, FILE *stream) +{ + int handle_fd, fd= _fileno(stream); + HANDLE osfh; + + DBUG_ASSERT(path && stream); + + /* Services don't have stdout/stderr on Windows, so _fileno returns -1. */ + if (fd < 0) + { + if (!freopen(path, mode, stream)) + return NULL; + + fd= _fileno(stream); + } + + if ((osfh= CreateFile(path, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, + NULL)) == INVALID_HANDLE_VALUE) + return NULL; + + if ((handle_fd= _open_osfhandle((intptr_t)osfh, + _O_APPEND | _O_TEXT)) == -1) + { + CloseHandle(osfh); + return NULL; + } + + if (_dup2(handle_fd, fd) < 0) + { + CloseHandle(osfh); + return NULL; + } + + _close(handle_fd); + + return stream; +} + +#elif defined(__FreeBSD__) + +/* No close operation hook. */ + +static int no_close(void *cookie __attribute__((unused))) +{ + return 0; +} + +/* + A hack around a race condition in the implementation of freopen. + + The race condition steams from the fact that the current fd of + the stream is closed before its number is used to duplicate the + new file descriptor. This defeats the desired atomicity of the + close and duplicate of dup2(). + + See PR number 79887 for reference: + http://www.freebsd.org/cgi/query-pr.cgi?pr=79887 +*/ + +static FILE *my_freebsd_freopen(const char *path, const char *mode, FILE *stream) +{ + int old_fd; + FILE *result; + + flockfile(stream); + + old_fd= fileno(stream); + + /* Use a no operation close hook to avoid having the fd closed. */ + stream->_close= no_close; + + /* Relies on the implicit dup2 to close old_fd. */ + result= freopen(path, mode, stream); + + /* If successful, the _close hook was replaced. */ + + if (result == NULL) + close(old_fd); + else + funlockfile(result); + + return result; +} + +#endif + + +/** + Change the file associated with a file stream. + + @param path Path to file. + @param mode Mode of the stream. + @param stream File stream. + + @note + This function is used to redirect stdout and stderr to a file and + subsequently to close and reopen that file for log rotation. + + @retval A FILE pointer on success. Otherwise, NULL. +*/ + +FILE *my_freopen(const char *path, const char *mode, FILE *stream) +{ + FILE *result; + +#if defined(_WIN32) + result= my_win_freopen(path, mode, stream); +#elif defined(__FreeBSD__) + /* + XXX: Once the fix is ported to the stable releases, this should + be dependent upon the specific FreeBSD versions. Check at: + http://www.freebsd.org/cgi/query-pr.cgi?pr=79887 + */ + if (getosreldate() > 900027) + result= freopen(path, mode, stream); + else + result= my_freebsd_freopen(path, mode, stream); +#else + result= freopen(path, mode, stream); +#endif + + return result; +} + /* Close a stream */ int my_fclose(FILE *fd, myf MyFlags) diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index 0c7e4ef7aa3..83cb0d261c0 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -124,10 +124,9 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags) } #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)) { diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c deleted file mode 100644 index 3962de21fc0..00000000000 --- a/mysys/my_gethostbyname.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2002, 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* Thread safe version of gethostbyname_r() */ - -#include "mysys_priv.h" -#if !defined(__WIN__) -#include <netdb.h> -#endif -#include <my_net.h> - -/* This file 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 mysql_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; - mysql_mutex_lock(&LOCK_gethostbyname_r); - hp= gethostbyname(name); - *h_errnop= h_errno; - return hp; -} - -void my_gethostbyname_r_free() -{ - mysql_mutex_unlock(&LOCK_gethostbyname_r); -} - -#endif /* !HAVE_GETHOSTBYNAME_R */ -#endif /* !my_gethostbyname_r */ diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index d14087d061e..ab44bac43d3 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -21,18 +21,6 @@ #ifndef MAIN -#if defined(__FreeBSD__) || defined(__linux__) -static my_bool memcpy_and_test(uchar *to, uchar *from, uint len) -{ - uint i, res=1; - - for (i=0; i < len; i++) - if ((*to++= *from++)) - res=0; - return res; -} -#endif /* FreeBSD || linux */ - #ifdef __FreeBSD__ #include <net/ethernet.h> @@ -44,10 +32,11 @@ static my_bool memcpy_and_test(uchar *to, uchar *from, uint len) my_bool my_gethwaddr(uchar *to) { size_t len; - uchar *buf, *next, *end, *addr; + char *buf, *next, *end; struct if_msghdr *ifm; struct sockaddr_dl *sdl; int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; + char zero_array[ETHER_ADDR_LEN] = {0}; if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) goto err; @@ -63,9 +52,9 @@ my_bool my_gethwaddr(uchar *to) ifm = (struct if_msghdr *)next; if (ifm->ifm_type == RTM_IFINFO) { - sdl = (struct sockaddr_dl *)(ifm + 1); - addr=(uchar *)LLADDR(sdl); - res=memcpy_and_test(to, addr, ETHER_ADDR_LEN); + sdl= (struct sockaddr_dl *)(ifm + 1); + memcpy(to, LLADDR(sdl), ETHER_ADDR_LEN); + res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; } } @@ -81,8 +70,9 @@ err: my_bool my_gethwaddr(uchar *to) { - int fd, res=1; + int fd, res= 1; struct ifreq ifr; + char zero_array[ETHER_ADDR_LEN] = {0}; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) @@ -91,9 +81,13 @@ my_bool my_gethwaddr(uchar *to) bzero(&ifr, sizeof(ifr)); strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1); - do { + do + { if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) - res=memcpy_and_test(to, (uchar *)&ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); + { + memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); + res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; + } } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6'); close(fd); diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 74c0d6b5ba3..fff8fda581c 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc +/* 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 @@ -176,7 +176,7 @@ int handle_options(int *argc, char ***argv, */ for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { - if (*pos == args_separator) + if (my_getopt_is_args_separator(*pos)) { is_cmdline_arg= 0; break; @@ -188,7 +188,7 @@ int handle_options(int *argc, char ***argv, char **first= pos; char *cur_arg= *pos; opt_found= 0; - if (!is_cmdline_arg && (cur_arg == args_separator)) + if (!is_cmdline_arg && (my_getopt_is_args_separator(cur_arg))) { is_cmdline_arg= 1; @@ -360,14 +360,6 @@ int handle_options(int *argc, char ***argv, } return EXIT_OPTION_DISABLED; } - if (must_be_var && optp->arg_type == 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; - } error= 0; value= optp->var_type & GET_ASK_ADDR ? (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) : @@ -377,6 +369,11 @@ int handle_options(int *argc, char ***argv, 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) @@ -391,7 +388,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")) @@ -418,10 +415,9 @@ int handle_options(int *argc, char ***argv, else if (optp->arg_type == REQUIRED_ARG && !optend) { /* 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'. - */ + 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) @@ -607,6 +603,32 @@ static char *check_struct_option(char *cur_arg, char *key_name) } } +/** + 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) +{ + if (!my_strcasecmp(&my_charset_latin1, argument, "true") || + !my_strcasecmp(&my_charset_latin1, argument, "on") || + !my_strcasecmp(&my_charset_latin1, argument, "1")) + 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")) + return 0; + my_getopt_error_reporter(WARNING_LEVEL, + "option '%s': boolean value '%s' wasn't recognized. Set to OFF.", + opts->name, argument); + return 0; +} + /* function: setval @@ -634,7 +656,7 @@ static int setval(const struct my_option *opts, void *value, char *argument, switch ((opts->var_type & GET_TYPE_MASK)) { case GET_BOOL: /* If argument differs from 0, enable option, else disable */ - *((my_bool*) value)= (my_bool) atoi(argument) != 0; + *((my_bool*) value)= get_bool_argument(opts, argument); break; case GET_INT: *((int*) value)= (int) getopt_ll(argument, opts, &err); @@ -674,7 +696,7 @@ static int setval(const struct my_option *opts, void *value, char *argument, break; case GET_ENUM: { - int type= find_type(argument, opts->typelib, 2); + int type= find_type(argument, opts->typelib, FIND_TYPE_BASIC); if (type == 0) { /* diff --git a/mysys/my_handler_errors.h b/mysys/my_handler_errors.h index e5cb06fba63..97282503967 100644 --- a/mysys/my_handler_errors.h +++ b/mysys/my_handler_errors.h @@ -66,7 +66,12 @@ 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" }; +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 ae4aa5bb5b7..8cf1af2f8ee 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 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 @@ -37,8 +37,6 @@ static my_bool win32_init_tcp_ip(); #define SCALE_USEC 10000 my_bool my_init_done= 0; -/** True if @c my_basic_init() has been called. */ -my_bool my_basic_init_done= 0; uint mysys_usage_id= 0; /* Incremented for each my_init() */ ulong my_thread_stack_size= (sizeof(void*) <= 4)? 65536: ((256-16)*1024); @@ -57,23 +55,22 @@ static ulong atoi_octal(const char *str) MYSQL_FILE *mysql_stdin= NULL; static MYSQL_FILE instrumented_stdin; + /** - Perform a limited initialisation of mysys. - This initialisation is sufficient to: - - allocate memory, - - read configuration files, - - parse command lines arguments. - To complete the mysys initialisation, - call my_init(). - @return 0 on success + Initialize my_sys functions, resources and variables + + @return Initialization result + @retval 0 Success + @retval 1 Error. Couldn't initialize environment */ -my_bool my_basic_init(void) +my_bool my_init(void) { - char * str; + char *str; - if (my_basic_init_done) + if (my_init_done) return 0; - my_basic_init_done= 1; + + my_init_done= 1; mysys_usage_id++; my_umask= 0660; /* Default umask for new files */ @@ -96,52 +93,20 @@ my_bool my_basic_init(void) if (my_progname) my_progname_short= my_progname + dirname_length(my_progname); -#if defined(THREAD) /* Initalize our mutex handling */ my_mutex_init(); if (my_thread_global_init()) return 1; + #if defined(HAVE_PTHREAD_INIT) pthread_init(); /* Must be called before DBUG_ENTER */ #endif - if (my_thread_basic_global_init()) - return 1; -#endif /* $HOME is needed early to parse configuration files located in ~/ */ if ((home_dir= getenv("HOME")) != 0) home_dir= intern_filename(home_dir_buff, home_dir); - return 0; -} - - -/* - Init my_sys functions and my_sys variabels - - SYNOPSIS - my_init() - - RETURN - 0 ok - 1 Couldn't initialize environment -*/ - -my_bool my_init(void) -{ - if (my_init_done) - return 0; - - my_init_done= 1; - - if (my_basic_init()) - return 1; - -#ifdef THREAD - if (my_thread_global_init()) - return 1; -#endif /* THREAD */ { DBUG_ENTER("my_init"); DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown")); @@ -240,7 +205,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", { DBUG_END(); /* Must be done before my_thread_end */ } -#ifdef THREAD + my_thread_end(); my_thread_global_end(); my_mutex_end(); @@ -252,7 +217,6 @@ 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) @@ -260,7 +224,6 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", #endif /* __WIN__ */ my_init_done=0; - my_basic_init_done= 0; } /* my_end */ #ifndef DBUG_OFF @@ -319,6 +282,89 @@ int handle_rtc_failure(int err_type, const char *file, int line, #pragma runtime_checks("", restore) #endif +#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10) +#define MS 10000000 + +static void win_init_time(void) +{ + /* The following is used by time functions */ + FILETIME ft; + LARGE_INTEGER li, t_cnt; + + DBUG_ASSERT(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency)); + + if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0) + query_performance_frequency= 0; + else + { + GetSystemTimeAsFileTime(&ft); + li.LowPart= ft.dwLowDateTime; + li.HighPart= ft.dwHighDateTime; + query_performance_offset= li.QuadPart-OFFSET_TO_EPOC; + QueryPerformanceCounter(&t_cnt); + query_performance_offset-= (t_cnt.QuadPart / + query_performance_frequency * MS + + t_cnt.QuadPart % + query_performance_frequency * MS / + query_performance_frequency); + } +} + + +/* + 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) { @@ -326,17 +372,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 @@ -347,106 +394,10 @@ static void my_win_init(void) _tzset(); - - - - - - - - - - - - - - - - - - - - - - - - - /* The following is used by time functions */ -#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10) -#define MS 10000000 - { - FILETIME ft; - LARGE_INTEGER li, t_cnt; - DBUG_ASSERT(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency)); - if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0) - query_performance_frequency= 0; - else - { - GetSystemTimeAsFileTime(&ft); - li.LowPart= ft.dwLowDateTime; - li.HighPart= ft.dwHighDateTime; - query_performance_offset= li.QuadPart-OFFSET_TO_EPOC; - QueryPerformanceCounter(&t_cnt); - query_performance_offset-= (t_cnt.QuadPart / - query_performance_frequency * MS + - t_cnt.QuadPart % - query_performance_frequency * MS / - query_performance_frequency); - } - } - - { - /* - 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_time(); + 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; } @@ -524,29 +475,22 @@ PSI_mutex_key key_my_file_info_mutex; PSI_mutex_key key_LOCK_localtime_r; #endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ -#ifndef HAVE_GETHOSTBYNAME_R -PSI_mutex_key key_LOCK_gethostbyname_r; -#endif /* HAVE_GETHOSTBYNAME_R */ - PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm, key_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_THR_LOCK_time, + key_THR_LOCK_open, key_THR_LOCK_threads, key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap; static PSI_mutex_info all_mysys_mutexes[]= { -#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) +#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) */ -#ifndef HAVE_GETHOSTBYNAME_R - { &key_LOCK_gethostbyname_r, "LOCK_gethostbyname_r", PSI_FLAG_GLOBAL}, -#endif /* HAVE_GETHOSTBYNAME_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}, @@ -563,7 +507,6 @@ static PSI_mutex_info all_mysys_mutexes[]= { &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_THR_LOCK_time, "THR_LOCK_time", PSI_FLAG_GLOBAL}, { &key_TMPDIR_mutex, "TMPDIR_mutex", PSI_FLAG_GLOBAL}, { &key_THR_LOCK_myisam_mmap, "THR_LOCK_myisam_mmap", PSI_FLAG_GLOBAL} }; diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 890ff0b5dd1..06f9521a664 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -41,7 +41,7 @@ # endif #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))) @@ -97,13 +97,12 @@ 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) +#if !defined(HAVE_READDIR_R) mysql_mutex_lock(&THR_LOCK_open); #endif @@ -135,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))) { @@ -166,7 +161,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) } (void) closedir(dirp); -#if defined(THREAD) && !defined(HAVE_READDIR_R) +#if !defined(HAVE_READDIR_R) mysql_mutex_unlock(&THR_LOCK_open); #endif result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; @@ -178,7 +173,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_RETURN(result); error: -#if defined(THREAD) && !defined(HAVE_READDIR_R) +#if !defined(HAVE_READDIR_R) mysql_mutex_unlock(&THR_LOCK_open); #endif my_errno=errno; diff --git a/mysys/my_open.c b/mysys/my_open.c index 8f34ce1c6dc..2aef97b3e34 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -89,7 +89,7 @@ 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); -#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) +#if !defined(HAVE_PREAD) && !defined(_WIN32) mysql_mutex_destroy(&my_file_info[fd].mutex); #endif my_file_info[fd].type = UNOPEN; @@ -125,7 +125,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type { if ((uint) fd >= my_file_limit) { -#if defined(THREAD) && !defined(HAVE_PREAD) +#if !defined(HAVE_PREAD) my_errno= EMFILE; #else thread_safe_increment(my_file_opened,&THR_LOCK_open); @@ -140,7 +140,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type my_file_opened++; my_file_total_opened++; my_file_info[fd].type = type_of_file; -#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) +#if !defined(HAVE_PREAD) && !defined(_WIN32) mysql_mutex_init(key_my_file_info_mutex, &my_file_info[fd].mutex, MY_MUTEX_INIT_FAST); #endif diff --git a/mysys/my_port.c b/mysys/my_port.c deleted file mode 100644 index 9ad333421ca..00000000000 --- a/mysys/my_port.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2002 MySQL AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* - Small functions to make code portable -*/ - -#include "mysys_priv.h" - -#ifdef _AIX - -/* - On AIX, at least with gcc 3.1, the expression - '(double) (ulonglong) var' doesn't always work for big unsigned - integers like '18446744073709551615'. The end result is that the - high bit is simply dropped. (probably bug in gcc optimizations) - Handling the conversion in a sub function seems to work. -*/ - - - -double my_ulonglong2double(unsigned long long nr) -{ - return (double) nr; -} -#endif /* _AIX */ diff --git a/mysys/my_pread.c b/mysys/my_pread.c index d0a0ddaec66..e006360c11b 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -85,14 +85,14 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, 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) @@ -173,10 +173,10 @@ size_t my_pwrite(File 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 a13cd9b3545..f0b3b1e8aef 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -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> @@ -470,4 +469,3 @@ int pthread_dummy(int ret) { return ret; } -#endif /* THREAD */ diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c index c8ef38efbdc..2afe3ec31dd 100644 --- a/mysys/my_rdtsc.c +++ b/mysys/my_rdtsc.c @@ -868,14 +868,8 @@ void my_timer_init(MY_TIMER_INFO *mti) clock() -- We don't use because it would overflow frequently. - clock_gettime() -- Often we don't use this even when it exists. - In configure.in, we use AC_CHECK_FUNCS(clock_gettime). Not - AC_CHECK_LIB(rc,clock_gettime) - AC_CHECK_FUNCS(clock_gettime) - If we had the above lines in configure.in, we'd have to use - /usr/lib/librt.so or /usr/lib64/librt.so when linking, and - the size of librt.so is 40KB. In tests, clock_gettime often - had resolution = 1000. + 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() diff --git a/mysys/my_read.c b/mysys/my_read.c index 75f9dd64f1d..dbe9006a1d3 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -59,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_seek.c b/mysys/my_seek.c index 63337c636a4..ca12a2e95d1 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -65,7 +65,7 @@ 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: %llu errno: %d", (ulonglong) newpos,errno)); + DBUG_PRINT("error", ("lseek: %llu errno: %d", (ulonglong) newpos, errno)); DBUG_RETURN(MY_FILEPOS_ERROR); } if ((my_off_t) newpos != pos) @@ -95,6 +95,7 @@ my_off_t my_tell(File fd, myf MyFlags) my_errno= errno; if (MyFlags & MY_WME) my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno); + DBUG_PRINT("error", ("tell: %llu errno: %d", (ulonglong) pos, my_errno)); } DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos)); DBUG_RETURN((my_off_t) pos); diff --git a/mysys/my_static.c b/mysys/my_static.c index c6bf3c0ef0f..ac0ad2467f7 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -32,9 +32,7 @@ char curr_dir[FN_REFLEN]= {0}, ulong my_stream_opened=0,my_file_opened=0, my_tmp_file_created=0; ulong my_file_total_opened= 0; int my_umask=0664, my_umask_dir=0777; -#ifndef THREAD -int my_errno=0; -#endif + 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; diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index 33f45a882e1..9657ea6bf58 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -113,7 +113,6 @@ int my_is_symlink(const char *filename __attribute__((unused))) #endif } - /* Resolve all symbolic links in path 'to' may be equal to 'filename' @@ -122,8 +121,7 @@ int my_is_symlink(const char *filename __attribute__((unused))) (including the end \0) */ -int my_realpath(char *to, const char *filename, - myf MyFlags __attribute__((unused))) +int my_realpath(char *to, const char *filename, myf MyFlags) { #if defined(HAVE_REALPATH) && !defined(HAVE_BROKEN_REALPATH) int result=0; @@ -150,7 +148,23 @@ int my_realpath(char *to, const char *filename, } DBUG_RETURN(result); #else +#ifdef _WIN32 + int ret= GetFullPathName(filename,FN_REFLEN,
+ to,
+ NULL); + if (ret == 0 || ret > FN_REFLEN) + { + if (ret > FN_REFLEN) + my_errno= ENAMETOOLONG; + else + my_errno= EACCES; + if (MyFlags & MY_WME) + my_error(EE_REALPATH, MYF(0), filename, my_errno); + return -1; + } +#else my_load_path(to, filename, NullS); +#endif return 0; #endif } diff --git a/mysys/my_sync.c b/mysys/my_sync.c index 7dfd365326c..f39b10253dd 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) @@ -64,7 +82,7 @@ int my_sync(File fd, myf my_flags) /* Some file systems don't support F_FULLFSYNC and fail above: */ DBUG_PRINT("info",("fcntl(F_FULLFSYNC) failed, falling back")); #endif -#if defined(HAVE_FDATASYNC) +#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC res= fdatasync(fd); #elif defined(HAVE_FSYNC) res= fsync(fd); @@ -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,11 +112,18 @@ 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 */ static const char cur_dir_name[]= {FN_CURLIB, 0}; + + /* Force directory information to disk. @@ -108,7 +135,9 @@ static const char cur_dir_name[]= {FN_CURLIB, 0}; RETURN 0 if ok, !=0 if error */ + #ifdef NEED_EXPLICIT_SYNC_DIR + int my_sync_dir(const char *dir_name, myf my_flags) { File dir_fd; @@ -133,12 +162,15 @@ int my_sync_dir(const char *dir_name, myf my_flags) res= 1; DBUG_RETURN(res); } + #else /* NEED_EXPLICIT_SYNC_DIR */ + int my_sync_dir(const char *dir_name __attribute__((unused)), - myf my_flags __attribute__((unused))) + myf my_flags __attribute__((unused))) { return 0; } + #endif /* NEED_EXPLICIT_SYNC_DIR */ @@ -153,7 +185,9 @@ int my_sync_dir(const char *dir_name __attribute__((unused)), RETURN 0 if ok, !=0 if error */ + #ifdef NEED_EXPLICIT_SYNC_DIR + int my_sync_dir_by_file(const char *file_name, myf my_flags) { char dir_name[FN_REFLEN]; @@ -161,10 +195,14 @@ int my_sync_dir_by_file(const char *file_name, myf my_flags) dirname_part(dir_name, file_name, &dir_name_length); return my_sync_dir(dir_name, my_flags); } + #else /* NEED_EXPLICIT_SYNC_DIR */ + int my_sync_dir_by_file(const char *file_name __attribute__((unused)), - myf my_flags __attribute__((unused))) + myf my_flags __attribute__((unused))) { return 0; } + #endif /* NEED_EXPLICIT_SYNC_DIR */ + diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index a2d89c79b4e..146a223a9e3 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 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,11 +22,10 @@ #include <m_string.h> #include <signal.h> -#ifdef THREAD pthread_key(struct st_my_thread_var*, THR_KEY_mysys); 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_time, + THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_myisam_mmap; mysql_cond_t THR_COND_threads; @@ -35,9 +34,6 @@ uint my_thread_end_wait_time= 5; #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) mysql_mutex_t LOCK_localtime_r; #endif -#ifndef HAVE_GETHOSTBYNAME_R -mysql_mutex_t LOCK_gethostbyname_r; -#endif #ifdef _MSC_VER static void install_sigabrt_handler(); #endif @@ -61,62 +57,40 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused))) static uint get_thread_lib(void); -/** True if @c my_thread_basic_global_init() has been called. */ -static my_bool my_thread_basic_global_init_done= 0; - -/** - Perform a minimal initialisation of mysys, when compiled with threads. - The initialisation performed is sufficient to: - - allocate memory - - perform file operations - - use charsets - - use my_errno - @sa my_basic_init - @sa my_thread_basic_global_reinit -*/ -my_bool my_thread_basic_global_init(void) -{ - int pth_ret; - - if (my_thread_basic_global_init_done) - return 0; - my_thread_basic_global_init_done= 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 ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) - { - fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret); - return 1; - } - - if (my_thread_init()) - return 1; +/** True if @c my_thread_global_init() has been called. */ +static my_bool my_thread_global_init_done= 0; - return 0; -} /** - Re-initialize components initialized early with @c my_thread_basic_global_init. + 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_thread_basic_global_reinit(void) +void my_thread_global_reinit(void) { struct st_my_thread_var *tmp; - DBUG_ASSERT(my_thread_basic_global_init_done); + 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); + + 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); @@ -129,6 +103,9 @@ void my_thread_basic_global_reinit(void) 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); @@ -152,7 +129,24 @@ void my_thread_basic_global_reinit(void) my_bool my_thread_global_init(void) { - if (my_thread_basic_global_init()) + int pth_ret; + + 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); + 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(); @@ -190,26 +184,16 @@ my_bool my_thread_global_init(void) 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_mutex_init(key_THR_LOCK_time, &THR_LOCK_time, MY_MUTEX_INIT_FAST); mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL); #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) mysql_mutex_init(key_LOCK_localtime_r, &LOCK_localtime_r, MY_MUTEX_INIT_SLOW); #endif -#ifndef HAVE_GETHOSTBYNAME_R - mysql_mutex_init(key_LOCK_gethostbyname_r, - &LOCK_gethostbyname_r, MY_MUTEX_INIT_SLOW); -#endif #ifdef _MSC_VER install_sigabrt_handler(); #endif - if (my_thread_init()) - { - my_thread_global_end(); /* Clean up */ - return 1; - } return 0; } @@ -253,7 +237,6 @@ void my_thread_global_end(void) mysql_mutex_destroy(&THR_LOCK_myisam_mmap); mysql_mutex_destroy(&THR_LOCK_heap); mysql_mutex_destroy(&THR_LOCK_net); - mysql_mutex_destroy(&THR_LOCK_time); mysql_mutex_destroy(&THR_LOCK_charset); if (all_threads_killed) { @@ -263,11 +246,8 @@ void my_thread_global_end(void) #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) mysql_mutex_destroy(&LOCK_localtime_r); #endif -#ifndef HAVE_GETHOSTBYNAME_R - mysql_mutex_destroy(&LOCK_gethostbyname_r); -#endif - my_thread_basic_global_init_done= 0; + my_thread_global_init_done= 0; } static my_thread_id thread_id= 0; @@ -498,4 +478,3 @@ static void install_sigabrt_handler(void) } #endif -#endif /* THREAD */ diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index ad1636011db..58c09e332d6 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -24,7 +24,108 @@ #include <process.h> #include <sys/timeb.h> -int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) + +/* + Windows native condition variables. We use runtime loading / function + pointers, because they are not available on XP +*/ + +/* Prototypes and function pointers for condition variable functions */ +typedef VOID (WINAPI * InitializeConditionVariableProc) + (PCONDITION_VARIABLE ConditionVariable); + +typedef BOOL (WINAPI * SleepConditionVariableCSProc) + (PCONDITION_VARIABLE ConditionVariable, + PCRITICAL_SECTION CriticalSection, + DWORD dwMilliseconds); + +typedef VOID (WINAPI * WakeAllConditionVariableProc) + (PCONDITION_VARIABLE ConditionVariable); + +typedef VOID (WINAPI * WakeConditionVariableProc) + (PCONDITION_VARIABLE ConditionVariable); + +static InitializeConditionVariableProc my_InitializeConditionVariable; +static SleepConditionVariableCSProc my_SleepConditionVariableCS; +static WakeAllConditionVariableProc my_WakeAllConditionVariable; +static WakeConditionVariableProc my_WakeConditionVariable; + + +/** + Indicates if we have native condition variables, + initialized first time pthread_cond_init is called. +*/ + +static BOOL have_native_conditions= FALSE; + + +/** + Check if native conditions can be used, load function pointers +*/ + +static void check_native_cond_availability(void) +{ + HMODULE module= GetModuleHandle("kernel32"); + + my_InitializeConditionVariable= (InitializeConditionVariableProc) + GetProcAddress(module, "InitializeConditionVariable"); + my_SleepConditionVariableCS= (SleepConditionVariableCSProc) + GetProcAddress(module, "SleepConditionVariableCS"); + my_WakeAllConditionVariable= (WakeAllConditionVariableProc) + GetProcAddress(module, "WakeAllConditionVariable"); + my_WakeConditionVariable= (WakeConditionVariableProc) + GetProcAddress(module, "WakeConditionVariable"); + + if (my_InitializeConditionVariable) + have_native_conditions= TRUE; +} + + + +/** + Convert abstime to milliseconds +*/ + +static DWORD get_milliseconds(const struct timespec *abstime) +{ + long long millis; + union ft64 now; + + if (abstime == NULL) + return INFINITE; + + GetSystemTimeAsFileTime(&now.ft); + + /* + Calculate time left to abstime + - subtract start time from current time(values are in 100ns units) + - convert to millisec by dividing with 10000 + */ + millis= (abstime->tv.i64 - now.i64) / 10000; + + /* Don't allow the timeout to be negative */ + if (millis < 0) + return 0; + + /* + Make sure the calculated timeout does not exceed original timeout + value which could cause "wait for ever" if system time changes + */ + if (millis > abstime->max_timeout_msec) + millis= abstime->max_timeout_msec; + + if (millis > UINT_MAX) + millis= UINT_MAX; + + return (DWORD)millis; +} + + +/* + Old (pre-vista) implementation using events +*/ + +static int legacy_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { cond->waiting= 0; InitializeCriticalSection(&cond->lock_waiting); @@ -53,7 +154,8 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) return 0; } -int pthread_cond_destroy(pthread_cond_t *cond) + +static int legacy_cond_destroy(pthread_cond_t *cond) { DeleteCriticalSection(&cond->lock_waiting); @@ -65,48 +167,13 @@ int pthread_cond_destroy(pthread_cond_t *cond) } -int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) -{ - return pthread_cond_timedwait(cond,mutex,NULL); -} - - -int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, +static int legacy_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime) { int result; - long timeout; - union ft64 now; - - if( abstime != NULL ) - { - GetSystemTimeAsFileTime(&now.ft); - - /* - Calculate time left to abstime - - subtract start time from current time(values are in 100ns units) - - convert to millisec by dividing with 10000 - */ - timeout= (long)((abstime->tv.i64 - now.i64) / 10000); - - /* Don't allow the timeout to be negative */ - if (timeout < 0) - timeout= 0L; - - /* - Make sure the calucated timeout does not exceed original timeout - value which could cause "wait for ever" if system time changes - */ - if (timeout > abstime->max_timeout_msec) - timeout= abstime->max_timeout_msec; - - } - 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 @@ -142,7 +209,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, return result == WAIT_TIMEOUT ? ETIMEDOUT : 0; } -int pthread_cond_signal(pthread_cond_t *cond) +static int legacy_cond_signal(pthread_cond_t *cond) { EnterCriticalSection(&cond->lock_waiting); @@ -155,7 +222,7 @@ int pthread_cond_signal(pthread_cond_t *cond) } -int pthread_cond_broadcast(pthread_cond_t *cond) +static int legacy_cond_broadcast(pthread_cond_t *cond) { EnterCriticalSection(&cond->lock_waiting); /* @@ -177,6 +244,87 @@ int pthread_cond_broadcast(pthread_cond_t *cond) } +/* + Posix API functions. Just choose between native and legacy implementation. +*/ + +int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) +{ + /* + Once initialization is used here rather than in my_init(), to + 1) avoid my_init() pitfalls- undefined order in which initialization should + run + 2) be potentially useful C++ (in static constructors that run before main()) + 3) just to simplify the API. + Also, the overhead of my_pthread_once is very small. + */ + static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT; + my_pthread_once(&once_control, check_native_cond_availability); + + if (have_native_conditions) + { + my_InitializeConditionVariable(&cond->native_cond); + return 0; + } + else + return legacy_cond_init(cond, attr); +} + + +int pthread_cond_destroy(pthread_cond_t *cond) +{ + if (have_native_conditions) + return 0; /* no destroy function */ + else + return legacy_cond_destroy(cond); +} + + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + if (have_native_conditions) + { + my_WakeAllConditionVariable(&cond->native_cond); + return 0; + } + else + return legacy_cond_broadcast(cond); +} + + +int pthread_cond_signal(pthread_cond_t *cond) +{ + if (have_native_conditions) + { + my_WakeConditionVariable(&cond->native_cond); + return 0; + } + else + return legacy_cond_signal(cond); +} + + +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec *abstime) +{ + if (have_native_conditions) + { + DWORD timeout= get_milliseconds(abstime); + if (!my_SleepConditionVariableCS(&cond->native_cond, mutex, timeout)) + return ETIMEDOUT; + return 0; + } + else + return legacy_cond_timedwait(cond, mutex, abstime); +} + + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + return pthread_cond_timedwait(cond, mutex, NULL); +} + + int pthread_attr_init(pthread_attr_t *connect_att) { connect_att->dwStackSize = 0; diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c index 6c0b191ca2c..4d80d774dad 100644 --- a/mysys/my_winfile.c +++ b/mysys/my_winfile.c @@ -97,7 +97,7 @@ HANDLE my_get_osfhandle(File fd) static int my_get_open_flags(File fd) { - DBUG_ENTER("my_get_osfhandle"); + DBUG_ENTER("my_get_open_flags"); DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); DBUG_RETURN(my_file_info[fd].oflag); } @@ -321,7 +321,7 @@ size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset) if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) DBUG_RETURN(0); /*return 0 at EOF*/ my_osmaperr(lastError); - DBUG_RETURN(-1); + DBUG_RETURN((size_t)-1); } DBUG_RETURN(nBytesRead); } @@ -352,7 +352,7 @@ size_t my_win_read(File Filedes, uchar *Buffer, size_t Count) if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) DBUG_RETURN(0); /*return 0 at EOF*/ my_osmaperr(lastError); - DBUG_RETURN(-1); + DBUG_RETURN((size_t)-1); } DBUG_RETURN(nBytesRead); } @@ -386,7 +386,7 @@ size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count, if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov)) { my_osmaperr(GetLastError()); - DBUG_RETURN(-1); + DBUG_RETURN((size_t)-1); } else DBUG_RETURN(nBytesWritten); @@ -427,6 +427,15 @@ size_t my_win_write(File fd, const uchar *Buffer, size_t Count) DBUG_ENTER("my_win_write"); DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer, (ulonglong)Count)); + + if(!Count) + DBUG_RETURN(0); + +#ifdef _WIN64 + if(Count > UINT_MAX) + Count= UINT_MAX; +#endif + if(my_get_open_flags(fd) & _O_APPEND) { /* @@ -442,10 +451,10 @@ size_t my_win_write(File fd, const uchar *Buffer, size_t Count) hFile= my_get_osfhandle(fd); if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov)) { - nWritten= (size_t)-1; my_osmaperr(GetLastError()); + DBUG_RETURN((size_t)-1); } - DBUG_RETURN((size_t)nWritten); + DBUG_RETURN(nWritten); } diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index 19d4a707062..54b8463fe0b 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -156,8 +156,19 @@ int pthread_cancel(pthread_t thread) int my_pthread_once(my_pthread_once_t *once_control, void (*init_routine)(void)) { - LONG state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, - MY_PTHREAD_ONCE_INIT); + LONG state; + + /* + Do "dirty" read to find out if initialization is already done, to + save an interlocked operation in common case. Memory barriers are ensured by + Visual C++ volatile implementation. + */ + if (*once_control == MY_PTHREAD_ONCE_DONE) + return 0; + + state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, + MY_PTHREAD_ONCE_INIT); + switch(state) { case MY_PTHREAD_ONCE_INIT: diff --git a/mysys/my_write.c b/mysys/my_write.c index 3eac1364f46..64f7546620f 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -52,10 +52,9 @@ size_t my_write(File 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 772e0346016..af7939376a6 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -24,7 +24,6 @@ #include <sys/resource.h> #endif -#ifdef THREAD #include <my_pthread.h> #ifdef HAVE_PSI_INTERFACE @@ -37,16 +36,12 @@ extern PSI_mutex_key key_my_file_info_mutex; extern PSI_mutex_key key_LOCK_localtime_r; #endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ -#ifndef HAVE_GETHOSTBYNAME_R -extern PSI_mutex_key key_LOCK_gethostbyname_r; -#endif /* HAVE_GETHOSTBYNAME_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_THR_LOCK_time, + key_THR_LOCK_open, key_THR_LOCK_threads, key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap; extern PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond, @@ -61,10 +56,7 @@ extern PSI_thread_key key_thread_alarm; 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, THR_LOCK_time; -#else /* THREAD */ -#include <my_no_pthread.h> -#endif /* THREAD */ +extern mysql_mutex_t THR_LOCK_charset; #include <mysql/psi/mysql_file.h> diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c index 2005e3eb2b7..dcafe13291d 100644 --- a/mysys/ptr_cmp.c +++ b/mysys/ptr_cmp.c @@ -22,7 +22,7 @@ #include "mysys_priv.h" #include <myisampack.h> -#ifdef TARGET_OS_SOLARIS +#ifdef __sun /* * On Solaris, memcmp() is normally faster than the unrolled ptr_compare_N * functions, as memcmp() is usually a platform-specific implementation @@ -39,22 +39,25 @@ static int native_compare(size_t *length, unsigned char **a, unsigned char **b) return memcmp(*a, *b, *length); } -#else /* TARGET_OS_SOLARIS */ +#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 /* TARGET_OS_SOLARIS */ +#endif /* __sun */ /* Get a pointer to a optimal byte-compare function for a given size */ -qsort2_cmp get_ptr_compare (size_t size) +#ifdef __sun +qsort2_cmp get_ptr_compare (size_t size __attribute__((unused))) { -#ifdef TARGET_OS_SOLARIS return (qsort2_cmp) native_compare; +} #else +qsort2_cmp get_ptr_compare (size_t size) +{ if (size < 4) return (qsort2_cmp) ptr_compare; switch (size & 3) { @@ -64,8 +67,8 @@ qsort2_cmp get_ptr_compare (size_t size) case 3: return (qsort2_cmp) ptr_compare_3; } return 0; /* Impossible */ -#endif /* TARGET_OS_SOLARIS */ } +#endif /* __sun */ /* @@ -75,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; @@ -177,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/stacktrace.c b/mysys/stacktrace.c index ba62062ebc0..e4999dbbe81 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -24,6 +24,11 @@ #include <unistd.h> #include <strings.h> +#ifdef __linux__ +#include <ctype.h> /* isprint */ +#include <sys/syscall.h> /* SYS_gettid */ +#endif + #if HAVE_EXECINFO_H #include <execinfo.h> #endif @@ -43,10 +48,99 @@ void my_init_stacktrace() #endif } -void my_safe_print_str(const char* name, const char* val, int max_len) +#ifdef __linux__ + +static void print_buffer(char *buffer, size_t count) +{ + for (; count && *buffer; --count) + { + int c= (int) *buffer++; + fputc(isprint(c) ? c : ' ', stderr); + } +} + +/** + Access the pages of this process through /proc/self/task/<tid>/mem + in order to safely print the contents of a memory address range. + + @param addr The address at the start of the memory region. + @param max_len The length of the memory region. + + @return Zero on success. +*/ +static int safe_print_str(const char *addr, int max_len) { - char *heap_end= (char*) sbrk(0); - fprintf(stderr, "%s at %p ", name, val); + int fd; + pid_t tid; + off_t offset; + ssize_t nbytes= 0; + size_t total, count; + char buf[256]; + + tid= (pid_t) syscall(SYS_gettid); + + sprintf(buf, "/proc/self/task/%d/mem", tid); + + if ((fd= open(buf, O_RDONLY)) < 0) + return -1; + + /* Ensure that off_t can hold a pointer. */ + compile_time_assert(sizeof(off_t) >= sizeof(intptr)); + + total= max_len; + offset= (intptr) addr; + + /* Read up to the maximum number of bytes. */ + while (total) + { + count= min(sizeof(buf), total); + + if ((nbytes= pread(fd, buf, count, offset)) < 0) + { + /* Just in case... */ + if (errno == EINTR) + continue; + else + break; + } + + /* Advance offset into memory. */ + total-= nbytes; + offset+= nbytes; + addr+= nbytes; + + /* Output the printable characters. */ + print_buffer(buf, nbytes); + + /* Break if less than requested... */ + if ((count - nbytes)) + 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); + + close(fd); + + return 0; +} + +#endif + +void my_safe_print_str(const char* val, int max_len) +{ + char *heap_end; + +#ifdef __linux__ + if (!safe_print_str(val, max_len)) + return; +#endif + + heap_end= (char*) sbrk(0); if (!PTR_SANE(val)) { @@ -54,7 +148,6 @@ void my_safe_print_str(const char* name, const char* val, int max_len) return; } - fprintf(stderr, "= "); for (; max_len && PTR_SANE(val) && *val; --max_len) fputc(*val++, stderr); fputc('\n', stderr); @@ -315,6 +408,9 @@ end: /* Produce a core for the thread */ void my_write_core(int sig) { +#ifdef HAVE_gcov + extern void __gcov_flush(void); +#endif signal(sig, SIG_DFL); #ifdef HAVE_gcov /* @@ -322,7 +418,6 @@ void my_write_core(int sig) information from this process, causing gcov output to be incomplete. So we force the writing of coverage information here before terminating. */ - extern void __gcov_flush(void); __gcov_flush(); #endif pthread_kill(pthread_self(), sig); @@ -605,16 +700,15 @@ void my_write_core(int unused) } -void my_safe_print_str(const char *name, const char *val, int len) +void my_safe_print_str(const char *val, int len) { - fprintf(stderr,"%s at %p", name, val); - __try + __try { - fprintf(stderr,"=%.*s\n", len, val); + fprintf(stderr, "%.*s\n", len, val); } __except(EXCEPTION_EXECUTE_HANDLER) { - fprintf(stderr,"is an invalid string pointer\n"); + fprintf(stderr, "is an invalid string pointer\n"); } } #endif /*__WIN__*/ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 9742861db08..725b32fa4a6 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -18,7 +18,7 @@ #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> @@ -674,15 +674,14 @@ 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 mysql_cond_t COND_thread_count; static mysql_mutex_t LOCK_thread_count; @@ -936,17 +935,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 b22823ae33e..8034e6d30a8 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -85,7 +85,6 @@ 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> @@ -1515,7 +1514,6 @@ void thr_print_locks(void) mysql_mutex_unlock(&THR_LOCK_lock); } -#endif /* THREAD */ /***************************************************************************** ** Test of thread locks @@ -1523,8 +1521,6 @@ void thr_print_locks(void) #ifdef MAIN -#ifdef THREAD - struct st_test { uint lock_nr; enum thr_lock_type lock_type; @@ -1754,13 +1750,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 b5548662679..fdc25b67049 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -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> @@ -525,7 +525,7 @@ 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, - struct timespec *abstime, + const struct timespec *abstime, const char *file, uint line) { int error; @@ -929,4 +929,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 ecd12849822..bad80b43eef 100644 --- a/mysys/thr_rwlock.c +++ b/mysys/thr_rwlock.c @@ -16,10 +16,122 @@ /* Synchronization - readers / writer thread locks */ #include "mysys_priv.h" -#if defined(THREAD) #if defined(NEED_MY_RW_LOCK) #include <errno.h> +#ifdef _WIN32 + +static BOOL have_srwlock= FALSE; +/* Prototypes and function pointers for windows functions */ +typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock); +typedef BOOL (WINAPI* srw_bool_func) (PSRWLOCK SRWLock); + +static srw_func my_InitializeSRWLock; +static srw_func my_AcquireSRWLockExclusive; +static srw_func my_ReleaseSRWLockExclusive; +static srw_func my_AcquireSRWLockShared; +static srw_func my_ReleaseSRWLockShared; + +static srw_bool_func my_TryAcquireSRWLockExclusive; +static srw_bool_func my_TryAcquireSRWLockShared; + +/** + Check for presence of Windows slim reader writer lock function. + Load function pointers. +*/ + +static void check_srwlock_availability(void) +{ + HMODULE module= GetModuleHandle("kernel32"); + + my_InitializeSRWLock= (srw_func) GetProcAddress(module, + "InitializeSRWLock"); + my_AcquireSRWLockExclusive= (srw_func) GetProcAddress(module, + "AcquireSRWLockExclusive"); + my_AcquireSRWLockShared= (srw_func) GetProcAddress(module, + "AcquireSRWLockShared"); + my_ReleaseSRWLockExclusive= (srw_func) GetProcAddress(module, + "ReleaseSRWLockExclusive"); + my_ReleaseSRWLockShared= (srw_func) GetProcAddress(module, + "ReleaseSRWLockShared"); + my_TryAcquireSRWLockExclusive= (srw_bool_func) GetProcAddress(module, + "TryAcquireSRWLockExclusive"); + my_TryAcquireSRWLockShared= (srw_bool_func) GetProcAddress(module, + "TryAcquireSRWLockShared"); + + /* + We currently require TryAcquireSRWLockExclusive. This API is missing on + Vista, this means SRWLock are only used starting with Win7. + + If "trylock" usage for rwlocks is eliminated from server codebase (it is used + in a single place currently, in query cache), then SRWLock can be enabled on + Vista too. In this case condition below needs to be changed to e.g check + for my_InitializeSRWLock. + */ + + if (my_TryAcquireSRWLockExclusive) + have_srwlock= TRUE; + +} + + +static int srw_init(my_rw_lock_t *rwp) +{ + my_InitializeSRWLock(&rwp->srwlock); + rwp->have_exclusive_srwlock = FALSE; + return 0; +} + + +static int srw_rdlock(my_rw_lock_t *rwp) +{ + my_AcquireSRWLockShared(&rwp->srwlock); + return 0; +} + + +static int srw_tryrdlock(my_rw_lock_t *rwp) +{ + + if (!my_TryAcquireSRWLockShared(&rwp->srwlock)) + return EBUSY; + return 0; +} + + +static int srw_wrlock(my_rw_lock_t *rwp) +{ + my_AcquireSRWLockExclusive(&rwp->srwlock); + rwp->have_exclusive_srwlock= TRUE; + return 0; +} + + +static int srw_trywrlock(my_rw_lock_t *rwp) +{ + if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock)) + return EBUSY; + rwp->have_exclusive_srwlock= TRUE; + return 0; +} + + +static int srw_unlock(my_rw_lock_t *rwp) +{ + if (rwp->have_exclusive_srwlock) + { + rwp->have_exclusive_srwlock= FALSE; + my_ReleaseSRWLockExclusive(&rwp->srwlock); + } + else + { + my_ReleaseSRWLockShared(&rwp->srwlock); + } + return 0; +} + +#endif /*_WIN32 */ + /* Source base from Sun Microsystems SPILT, simplified for MySQL use -- Joshua Chamas @@ -59,10 +171,26 @@ * Mountain View, California 94043 */ -int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr) +int my_rw_init(my_rw_lock_t *rwp) { pthread_condattr_t cond_attr; +#ifdef _WIN32 + /* + Once initialization is used here rather than in my_init(), in order to + - avoid my_init() pitfalls- (undefined order in which initialization should + run) + - be potentially useful C++ (static constructors) + - just to simplify the API. + Also, the overhead is of my_pthread_once is very small. + */ + static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT; + my_pthread_once(&once_control, check_srwlock_availability); + + if (have_srwlock) + return srw_init(rwp); +#endif + pthread_mutex_init( &rwp->lock, MY_MUTEX_INIT_FAST); pthread_condattr_init( &cond_attr ); pthread_cond_init( &rwp->readers, &cond_attr ); @@ -74,8 +202,6 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr) #ifdef SAFE_MUTEX rwp->write_thread = 0; #endif - /* If attribute argument is NULL use default value - prefer writers. */ - rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE; return(0); } @@ -83,6 +209,10 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr) 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 ); @@ -93,11 +223,15 @@ int my_rw_destroy(my_rw_lock_t *rwp) int my_rw_rdlock(my_rw_lock_t *rwp) { +#ifdef _WIN32 + if (have_srwlock) + return srw_rdlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); /* active or queued writers */ - while (( rwp->state < 0 ) || - (rwp->waiters && ! rwp->prefer_readers)) + while (( rwp->state < 0 ) || rwp->waiters) pthread_cond_wait( &rwp->readers, &rwp->lock); rwp->state++; @@ -108,9 +242,14 @@ int my_rw_rdlock(my_rw_lock_t *rwp) int my_rw_tryrdlock(my_rw_lock_t *rwp) { int res; + +#ifdef _WIN32 + if (have_srwlock) + return srw_tryrdlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); - if ((rwp->state < 0 ) || - (rwp->waiters && ! rwp->prefer_readers)) + if ((rwp->state < 0 ) || rwp->waiters) res= EBUSY; /* Can't get lock */ else { @@ -124,6 +263,11 @@ int my_rw_tryrdlock(my_rw_lock_t *rwp) int my_rw_wrlock(my_rw_lock_t *rwp) { +#ifdef _WIN32 + if (have_srwlock) + return srw_wrlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); rwp->waiters++; /* another writer queued */ @@ -144,6 +288,12 @@ int my_rw_wrlock(my_rw_lock_t *rwp) int my_rw_trywrlock(my_rw_lock_t *rwp) { int res; + +#ifdef _WIN32 + if (have_srwlock) + return srw_trywrlock(rwp); +#endif + pthread_mutex_lock(&rwp->lock); if (rwp->state) res= EBUSY; /* Can't get lock */ @@ -162,6 +312,11 @@ int my_rw_trywrlock(my_rw_lock_t *rwp) int my_rw_unlock(my_rw_lock_t *rwp) { +#ifdef _WIN32 + if (have_srwlock) + return srw_unlock(rwp); +#endif + DBUG_PRINT("rw_unlock", ("state: %d waiters: %d", rwp->state, rwp->waiters)); pthread_mutex_lock(&rwp->lock); @@ -192,30 +347,126 @@ int my_rw_unlock(my_rw_lock_t *rwp) return(0); } +#endif /* defined(NEED_MY_RW_LOCK) */ + -int rw_pr_init(struct st_my_rw_lock_t *rwlock) +int rw_pr_init(rw_pr_lock_t *rwlock) { - my_bool prefer_readers_attr= TRUE; - return my_rw_init(rwlock, &prefer_readers_attr); + 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; } -#else -/* - We are on system which has native read/write locks which support - preferring of readers. -*/ +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_init(rw_pr_lock_t *rwlock) + +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_rwlockattr_t rwlock_attr; + 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); - pthread_rwlockattr_init(&rwlock_attr); - pthread_rwlockattr_setkind_np(&rwlock_attr, PTHREAD_RWLOCK_PREFER_READER_NP); - pthread_rwlock_init(rwlock, NULL); - pthread_rwlockattr_destroy(&rwlock_attr); + 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; } -#endif /* defined(NEED_MY_RW_LOCK) */ -#endif /* defined(THREAD) */ + +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/typelib.c b/mysys/typelib.c index aec203becc0..463d3ba53a5 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 @@ -27,7 +27,7 @@ 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) @@ -56,16 +56,13 @@ uint find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) Search after a string in a list of strings. Endspace in x is not compared. @param x String to find - @param lib TYPELIB (struct of pointer to values + count) - @param 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 - - @note - If part, uniq field is found and full_name == 0 then x is expanded - to full field. + @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 @@ -76,15 +73,17 @@ uint find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) */ -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) || !is_field_separator(*i)) && + *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) && is_field_separator(*i))) + if (! *i || ((flags & FIND_TYPE_COMMA_TERM) && is_field_separator(*i))) DBUG_RETURN(pos+1); } - if ((!*i && (!(full_name & 8) || !is_field_separator(*i))) && - (!*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,13 +120,11 @@ 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 */ @@ -200,7 +199,7 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) x++; 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); } @@ -284,7 +283,7 @@ static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1, static uint parse_name(const TYPELIB *lib, const char **strpos, const char *end) { const char *pos= *strpos; - uint find= find_type((char*)pos, lib, 8); + uint find= find_type(pos, lib, FIND_TYPE_COMMA_TERM); for (; pos != end && *pos != '=' && *pos !=',' ; pos++); *strpos= pos; return find; |