summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorMikael Ronstrom <mikael@dator8>2011-01-04 18:46:01 +0100
committerMikael Ronstrom <mikael@dator8>2011-01-04 18:46:01 +0100
commitc1986098bf5e4748b416e2e4d451baa55a9f3cee (patch)
tree3099d3c6d9977c59627e466389081f2dae42b159 /mysys
parent7311054d1579462f13320a0ef12ed869bc0dc3f9 (diff)
parent7313acfef7491fbfc722f7c84744955065a6360a (diff)
downloadmariadb-git-c1986098bf5e4748b416e2e4d451baa55a9f3cee.tar.gz
merge
Diffstat (limited to 'mysys')
-rw-r--r--mysys/Makefile.am158
-rw-r--r--mysys/default.c63
-rw-r--r--mysys/errors.c2
-rw-r--r--mysys/mf_iocache.c48
-rw-r--r--mysys/mf_keycache.c10
-rw-r--r--mysys/mf_pack.c5
-rw-r--r--mysys/my_gethostbyname.c6
-rw-r--r--mysys/my_gethwaddr.c32
-rw-r--r--mysys/my_getopt.c22
-rw-r--r--mysys/my_init.c194
-rw-r--r--mysys/my_rdtsc.c10
-rw-r--r--mysys/my_seek.c15
-rw-r--r--mysys/my_symlink.c20
-rw-r--r--mysys/my_sync.c19
-rw-r--r--mysys/my_wincond.c232
-rw-r--r--mysys/my_winfile.c21
-rw-r--r--mysys/my_winthread.c15
-rw-r--r--mysys/ptr_cmp.c19
-rw-r--r--mysys/sha1.c55
-rw-r--r--mysys/stacktrace.c110
-rw-r--r--mysys/thr_mutex.c4
-rw-r--r--mysys/thr_rwlock.c297
22 files changed, 904 insertions, 453 deletions
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
deleted file mode 100644
index 357fa321da6..00000000000
--- a/mysys/Makefile.am
+++ /dev/null
@@ -1,158 +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
-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 \
- mf_keycaches.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_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
-endif
-
-EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
- thr_mutex.c thr_rwlock.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@
-
-#
-# 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
-
-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/default.c b/mysys/default.c
index 0e0883e1fcf..75eb4709e1e 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -66,7 +66,12 @@
const char *args_separator= "----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) */
@@ -140,6 +145,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, NULL, flags) == NULL)
+ DBUG_RETURN(2);
+ DBUG_PRINT("return", ("result: %s", result_buf));
+ DBUG_RETURN(0);
+}
+
+/*
Process config files in default directories.
SYNOPSIS
@@ -167,6 +199,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 +222,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 +281,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;
}
}
diff --git a/mysys/errors.c b/mysys/errors.c
index 8bc310652f1..c74ed292906 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -52,6 +52,7 @@ 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)"
};
void init_glob_errs(void)
@@ -94,6 +95,7 @@ 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)";
}
#endif
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 173b678cdd1..575581712d4 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -173,7 +173,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))
{
/*
@@ -205,7 +205,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)
@@ -485,7 +485,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 +529,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 +572,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)
{
@@ -1056,7 +1056,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 +1064,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));
@@ -1203,7 +1203,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 +1220,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 +1254,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 +1431,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 +1441,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 +1462,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,14 +1569,14 @@ 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
@@ -1639,7 +1639,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;
@@ -1695,11 +1695,11 @@ int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count,
{
/* Of no overlap, write everything without buffering */
if (pos + Count <= info->pos_in_file)
- return my_pwrite(info->file, Buffer, Count, pos,
- info->myflags | MY_NABP);
+ return 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;
@@ -1789,7 +1789,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 +1803,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 +1815,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;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index fc62d3d8a8e..9993c636fb1 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -3963,11 +3963,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;
+ 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++;
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index c6e6a3a429e..292cd8c0454 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_gethostbyname.c b/mysys/my_gethostbyname.c
index 4b7e9054d61..8a9c721c2fb 100644
--- a/mysys/my_gethostbyname.c
+++ b/mysys/my_gethostbyname.c
@@ -92,8 +92,10 @@ extern mysql_mutex_t LOCK_gethostbyname_r;
*/
struct hostent *my_gethostbyname_r(const char *name,
- struct hostent *result, char *buffer,
- int buflen, int *h_errnop)
+ struct hostent *res __attribute__((unused)),
+ char *buffer __attribute__((unused)),
+ int buflen __attribute__((unused)),
+ int *h_errnop)
{
struct hostent *hp;
mysql_mutex_lock(&LOCK_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 2ec2f8eb5c9..5e66d2fc189 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -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)
diff --git a/mysys/my_init.c b/mysys/my_init.c
index e3b189c27bb..ab6ffef7ac7 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -311,6 +311,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)
{
@@ -318,17 +401,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
@@ -339,106 +423,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);
- }
- }
+ win_init_time();
+ win_init_registry();
- {
- /*
- 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];
-
- 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;
}
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_seek.c b/mysys/my_seek.c
index 8502c259353..ca12a2e95d1 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -14,6 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
+#include "mysys_err.h"
/*
Seek to a position in a file.
@@ -42,8 +43,7 @@
actual error.
*/
-my_off_t my_seek(File fd, my_off_t pos, int whence,
- myf MyFlags __attribute__((unused)))
+my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags)
{
os_off_t newpos= -1;
DBUG_ENTER("my_seek");
@@ -63,7 +63,9 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
if (newpos == (os_off_t) -1)
{
my_errno= errno;
- DBUG_PRINT("error",("lseek: %llu errno: %d", (ulonglong) newpos,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_RETURN(MY_FILEPOS_ERROR);
}
if ((my_off_t) newpos != pos)
@@ -77,7 +79,7 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
/* Tell current position of file */
/* ARGSUSED */
-my_off_t my_tell(File fd, myf MyFlags __attribute__((unused)))
+my_off_t my_tell(File fd, myf MyFlags)
{
os_off_t pos;
DBUG_ENTER("my_tell");
@@ -89,7 +91,12 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused)))
pos= my_seek(fd, 0L, MY_SEEK_CUR,0);
#endif
if (pos == (os_off_t) -1)
+ {
my_errno= errno;
+ if (MyFlags & MY_WME)
+ my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno);
+ DBUG_PRINT("error", ("tell: %llu errno: %d", (ulonglong) pos, my_errno));
+ }
DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos));
DBUG_RETURN((my_off_t) pos);
} /* my_tell */
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index 258e227bb7b..59d929f9a61 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -113,14 +113,12 @@ int my_is_symlink(const char *filename __attribute__((unused)))
#endif
}
-
/*
Resolve all symbolic links in path
'to' may be equal to 'filename'
*/
-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;
@@ -147,7 +145,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 6a4e26a6542..3ca57055470 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -70,7 +70,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);
@@ -108,6 +108,8 @@ int my_sync(File fd, myf my_flags)
static const char cur_dir_name[]= {FN_CURLIB, 0};
+
+
/*
Force directory information to disk.
@@ -119,7 +121,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;
@@ -144,12 +148,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 */
@@ -164,7 +171,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];
@@ -172,10 +181,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_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 aecb2f7cc78..49534370a2f 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -155,8 +155,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/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/sha1.c b/mysys/sha1.c
index 3469e480c26..e5b33a9ad13 100644
--- a/mysys/sha1.c
+++ b/mysys/sha1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2004, 2006 MySQL AB
+/* Copyright (c) 2002, 2004, 2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -6,26 +6,57 @@
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
+ 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 */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
/*
Original Source from: http://www.faqs.org/rfcs/rfc3174.html
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ Acknowledgement
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
DESCRIPTION
- This file implements the Secure Hashing Algorithm 1 as
- defined in FIPS PUB 180-1 published April 17, 1995.
-
- The SHA-1, produces a 160-bit message digest for a given data
- stream. It should take about 2**n steps to find a message with the
- same digest as a given message and 2**(n/2) to find any two
- messages with the same digest, when n is the digest size in bits.
- Therefore, this algorithm can serve as a means of providing a
- "fingerprint" for a message.
+ This file implements the Secure Hashing Algorithm 1 as
+ defined in FIPS PUB 180-1 published April 17, 1995.
+
+ The SHA-1, produces a 160-bit message digest for a given data
+ stream. It should take about 2**n steps to find a message with the
+ same digest as a given message and 2**(n/2) to find any two
+ messages with the same digest, when n is the digest size in bits.
+ Therefore, this algorithm can serve as a means of providing a
+ "fingerprint" for a message.
PORTABILITY ISSUES
SHA-1 is defined in terms of 32-bit "words". This code uses
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index ba62062ebc0..48cdaaa6c91 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,10 +700,9 @@ 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);
}
diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c
index db35d5a13a6..00890bc0425 100644
--- a/mysys/thr_mutex.c
+++ b/mysys/thr_mutex.c
@@ -262,8 +262,8 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file,
int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
- struct timespec *abstime,
- const char *file, uint line)
+ const struct timespec *abstime,
+ const char *file, uint line)
{
int error;
pthread_mutex_lock(&mp->global);
diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c
index ecd12849822..13651221d37 100644
--- a/mysys/thr_rwlock.c
+++ b/mysys/thr_rwlock.c
@@ -20,6 +20,119 @@
#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 +172,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 +203,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 +210,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 +224,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 +243,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 +264,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 +289,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 +313,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 +348,127 @@ 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) */
+
+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;
+}
+
+
#endif /* defined(THREAD) */