diff options
author | Sergei Golubchik <serg@mariadb.org> | 2017-03-30 12:48:42 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2017-03-30 12:48:42 +0200 |
commit | da4d71d10d23c1ac2d10b72baee14991ccb7a146 (patch) | |
tree | 7cdf3a8c8e72ca7c1c8105427c04123f025bd870 /mysys | |
parent | 9ec85009985d644ce7ae797bc3572d0ad0f69bb0 (diff) | |
parent | a00517ac9707ffd51c092f5af5d198c5ee789bb4 (diff) | |
download | mariadb-git-da4d71d10d23c1ac2d10b72baee14991ccb7a146.tar.gz |
Merge branch '10.1' into 10.2
Diffstat (limited to 'mysys')
49 files changed, 312 insertions, 153 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 13ea8dd9f35..b9f92124cc3 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -43,7 +43,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c my_rdtsc.c my_context.c psi_noop.c my_atomic_writes.c - file_logger.c) + file_logger.c my_dlerror.c) IF (WIN32) SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_winthread.c my_wincond.c my_winerr.c my_winfile.c my_windac.c my_conio.c) diff --git a/mysys/array.c b/mysys/array.c index 35a41f2222c..5548ca1b694 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -90,7 +90,7 @@ my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void * element) { void *buffer; if (array->elements == array->max_element) - { /* Call only when nessesary */ + { /* Call only when necessary */ if (!(buffer=alloc_dynamic(array))) return TRUE; } diff --git a/mysys/base64.c b/mysys/base64.c index 67a9a13120b..b156406474d 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -17,7 +17,6 @@ #include <my_global.h> #include <m_string.h> /* strchr() */ #include <m_ctype.h> /* my_isspace() */ -#include <base64.h> #ifndef MAIN diff --git a/mysys/file_logger.c b/mysys/file_logger.c index b94cb705d3f..078286cd7d0 100644 --- a/mysys/file_logger.c +++ b/mysys/file_logger.c @@ -11,7 +11,7 @@ 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 02111-1301 USA */ #ifndef FLOGGER_SKIP_INCLUDES diff --git a/mysys/hash.c b/mysys/hash.c index 1d6b3d5daaa..ad01afba29e 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -62,7 +62,7 @@ my_hash_value_type my_hash_sort(CHARSET_INFO *cs, const uchar *key, @param[in,out] hash The hash that is initialized @param[in[ growth_size size incrememnt for the underlying dynarray - @param[in] charset The charater set information + @param[in] charset The character set information @param[in] size The hash size @param[in] key_offest The key offset for the hash @param[in] key_length The length of the key used in @@ -115,14 +115,19 @@ my_hash_init2(HASH *hash, uint growth_size, CHARSET_INFO *charset, static inline void my_hash_free_elements(HASH *hash) { + uint records= hash->records; + /* + Set records to 0 early to guard against anyone looking at the structure + during the free process + */ + hash->records= 0; if (hash->free) { HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); - HASH_LINK *end= data + hash->records; + HASH_LINK *end= data + records; while (data < end) (*hash->free)((data++)->data); } - hash->records=0; } @@ -531,6 +536,9 @@ my_bool my_hash_insert(HASH *info, const uchar *record) The record with the same record ptr is removed. If there is a free-function it's called if record was found. + hash->free() is guarantee to be called only after the row has been + deleted from the hash and the hash can be reused by other threads. + @return @retval 0 ok @retval 1 Record not found @@ -622,7 +630,7 @@ exit: /** Update keys when record has changed. - This is much more efficent than using a delete & insert. + This is much more efficient than using a delete & insert. */ my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 932dfe0f254..6c813333d09 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -138,7 +138,7 @@ void lf_pinbox_destroy(LF_PINBOX *pinbox) Get pins from a pinbox. Usually called via lf_alloc_get_pins() or lf_hash_get_pins(). - SYNOPSYS + SYNOPSIS pinbox - DESCRIPTION @@ -442,7 +442,7 @@ static void alloc_free(uchar *first, /* initialize lock-free allocator - SYNOPSYS + SYNOPSIS allocator - size a size of an object to allocate free_ptr_offset an offset inside the object to a sizeof(void *) diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c index 98a34647844..41174a66ced 100644 --- a/mysys/lf_hash.c +++ b/mysys/lf_hash.c @@ -201,7 +201,7 @@ static LF_SLIST *l_insert(LF_SLIST * volatile *head, CHARSET_INFO *cs, lf_unpin(pins, 2); /* Note that cursor.curr is not pinned here and the pointer is unreliable, - the object may dissapear anytime. But if it points to a dummy node, the + the object may disappear anytime. But if it points to a dummy node, the pointer is safe, because dummy nodes are never freed - initialize_bucket() uses this fact. */ @@ -333,7 +333,7 @@ static void default_initializer(LF_HASH *hash, void *dst, const void *src) lf_alloc and a size of memcpy'ed block size in lf_hash_insert. Typically they are the same, indeed. But LF_HASH::element_size can be decreased after lf_hash_init, and then lf_alloc will allocate larger block that - lf_hash_insert will copy over. It is desireable if part of the element + lf_hash_insert will copy over. It is desirable if part of the element is expensive to initialize - for example if there is a mutex or DYNAMIC_ARRAY. In this case they should be initialize in the LF_ALLOCATOR::constructor, and lf_hash_insert should not overwrite them. @@ -442,7 +442,7 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) hashnr= hash->hash_function(hash->charset, (uchar *)key, keylen) & INT_MAX32; - /* hide OOM errors - if we cannot initalize a bucket, try the previous one */ + /* hide OOM errors - if we cannot initialize a bucket, try the previous one */ for (bucket= hashnr % hash->size; ;bucket= my_clear_highest_bit(bucket)) { el= lf_dynarray_lvalue(&hash->array, bucket); @@ -476,7 +476,7 @@ void *lf_hash_search_using_hash_value(LF_HASH *hash, LF_PINS *pins, LF_SLIST * volatile *el, *found; uint bucket; - /* hide OOM errors - if we cannot initalize a bucket, try the previous one */ + /* hide OOM errors - if we cannot initialize a bucket, try the previous one */ for (bucket= hashnr % hash->size; ;bucket= my_clear_highest_bit(bucket)) { el= lf_dynarray_lvalue(&hash->array, bucket); diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index c0622cd2cbf..155a4367345 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -2136,7 +2136,7 @@ find_column(DYN_HEADER *hdr, uint numkey, LEX_STRING *strkey) hdr->length= hdr_interval_length(hdr, hdr->entry + hdr->entry_size); hdr->data= hdr->dtpool + hdr->offset; /* - Check that the found data is withing the ranges. This can happen if + Check that the found data is within the ranges. This can happen if we get data with wrong offsets. */ if (hdr->length == DYNCOL_OFFSET_ERROR || @@ -3480,7 +3480,7 @@ dynamic_column_update_many_fmt(DYNAMIC_COLUMN *str, if (plan[i].val->type == DYN_COL_NULL) { - plan[i].act= PLAN_NOP; /* Mark entry to be skiped */ + plan[i].act= PLAN_NOP; /* Mark entry to be skipped */ } else { @@ -4129,7 +4129,7 @@ mariadb_dyncol_json_internal(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json, hdr_interval_length(&header, header.entry + header.entry_size); header.data= header.dtpool + header.offset; /* - Check that the found data is withing the ranges. This can happen if + Check that the found data is within the ranges. This can happen if we get data with wrong offsets. */ if (header.length == DYNCOL_OFFSET_ERROR || @@ -4269,7 +4269,7 @@ mariadb_dyncol_unpack(DYNAMIC_COLUMN *str, hdr_interval_length(&header, header.entry + header.entry_size); header.data= header.dtpool + header.offset; /* - Check that the found data is withing the ranges. This can happen if + Check that the found data is within the ranges. This can happen if we get data with wrong offsets. */ if (header.length == DYNCOL_OFFSET_ERROR || diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c index b78d73074da..debed8afed3 100644 --- a/mysys/mf_fn_ext.c +++ b/mysys/mf_fn_ext.c @@ -86,7 +86,7 @@ char *fn_ext2(const char *name) if (!(gpos= strrchr(name, FN_LIBCHAR))) gpos= name; #endif - // locate the last occurence of FN_EXTCHAR + // locate the last occurrence of FN_EXTCHAR pos= strrchr(gpos, FN_EXTCHAR); DBUG_RETURN((char*) (pos ? pos : strend(gpos))); } /* fn_ext2 */ diff --git a/mysys/mf_format.c b/mysys/mf_format.c index 91354db0b64..6672a4386e4 100644 --- a/mysys/mf_format.c +++ b/mysys/mf_format.c @@ -97,13 +97,8 @@ char * fn_format(char * to, const char *name, const char *dir, pos=strmake(strmov(to,dev),name,length); (void) strmov(pos,ext); /* Don't convert extension */ } - /* - If MY_RETURN_REAL_PATH and MY_RESOLVE_SYMLINK is given, only do - realpath if the file is a symbolic link - */ if (flag & MY_RETURN_REAL_PATH) - (void) my_realpath(to, to, MYF(flag & MY_RESOLVE_SYMLINKS ? - MY_RESOLVE_LINK: 0)); + (void) my_realpath(to, to, MYF(0)); else if (flag & MY_RESOLVE_SYMLINKS) { strmov(buff,to); diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 72385daef42..23f2d7984d3 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -82,7 +82,7 @@ int (*_my_b_encr_write)(IO_CACHE *info,const uchar *Buffer,size_t Count)= 0; info IO_CACHE handler NOTES - This is called on automaticly on init or reinit of IO_CACHE + This is called on automatically on init or reinit of IO_CACHE It must be called externally if one moves or copies an IO_CACHE object. */ @@ -166,7 +166,7 @@ init_functions(IO_CACHE* info) If == 0 then use my_default_record_cache_size type Type of cache seek_offset Where cache should start reading/writing - use_async_io Set to 1 of we should use async_io (if avaiable) + use_async_io Set to 1 of we should use async_io (if available) cache_myflags Bitmap of different flags MY_WME | MY_FAE | MY_NABP | MY_FNABP | MY_DONT_CHECK_FILESIZE @@ -446,7 +446,7 @@ static void my_aiowait(my_aio_result *result) if (errno == EINTR) continue; DBUG_PRINT("error",("No aio request, error: %d",errno)); - result->pending=0; /* Assume everythings is ok */ + result->pending=0; /* Assume everything is ok */ break; } ((my_aio_result*) tmp)->pending=0; @@ -2003,6 +2003,7 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock) It's currently safe to call this if one has called init_io_cache() on the 'info' object, even if init_io_cache() failed. This function is also safe to call twice with the same handle. + Note that info->file is not reset as the caller may still use ut for my_close() RETURN 0 ok @@ -2032,10 +2033,12 @@ int end_io_cache(IO_CACHE *info) if (info->type == SEQ_READ_APPEND) { /* Destroy allocated mutex */ - info->type= TYPE_NOT_SET; mysql_mutex_destroy(&info->append_buffer_lock); } info->share= 0; + info->type= TYPE_NOT_SET; /* Ensure that flush_io_cache() does nothing */ + info->write_end= 0; /* Ensure that my_b_write() fails */ + info->write_function= 0; /* my_b_write will crash if used */ DBUG_RETURN(error); } /* end_io_cache */ @@ -2123,7 +2126,7 @@ int main(int argc, char** argv) /* check correctness of tests */ if (total_bytes != status.st_size) { - fprintf(stderr,"Not the same number of bytes acutally in file as bytes \ + fprintf(stderr,"Not the same number of bytes actually in file as bytes \ supposedly written\n"); error=1; } diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 74eaa12f19d..34aeb569faf 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -59,11 +59,11 @@ When a new block is required it is first tried to pop one from the stack. If the stack is empty, it is tried to get a never-used block from the pool. If this is empty too, then a block is taken from the LRU ring, flushing it - to disk, if neccessary. This is handled in find_key_block(). + to disk, if necessary. This is handled in find_key_block(). With the new free list, the blocks can have three temperatures: hot, warm and cold (which is free). This is remembered in the block header by the enum BLOCK_TEMPERATURE temperature variable. Remembering the - temperature is neccessary to correctly count the number of warm blocks, + temperature is necessary to correctly count the number of warm blocks, which is required to decide when blocks are allowed to become hot. Whenever a block is inserted to another (sub-)chain, we take the old and new temperature into account to decide if we got one more or less warm block. @@ -451,7 +451,7 @@ static inline uint next_power(uint value) structure of the type SIMPLE_KEY_CACHE_CB that is used for this key cache. The parameter keycache is supposed to point to this structure. The parameter key_cache_block_size specifies the size of the blocks in - the key cache to be built. The parameters division_limit and age_threshhold + the key cache to be built. The parameters division_limit and age_threshold determine the initial values of those characteristics of the key cache that are used for midpoint insertion strategy. The parameter use_mem specifies the total amount of memory to be allocated for key cache blocks diff --git a/mysys/my_access.c b/mysys/my_access.c index 91a536d214e..75774240406 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -223,7 +223,7 @@ my_bool is_filename_allowed(const char *name __attribute__((unused)), /* - Check if a path will access a reserverd file name that may cause problems + Check if a path will access a reserved file name that may cause problems SYNOPSIS check_if_legal_filename diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 664a7380ca4..7275f602525 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -43,7 +43,7 @@ DESCRIPTION This function prepares memory root for further use, sets initial size of chunk for memory allocation and pre-allocates first block if specified. - Altough error can happen during execution of this function if + Although error can happen during execution of this function if pre_alloc_size is non-0 it won't be reported. Instead it will be reported as error in first alloc_root() on this memory root. diff --git a/mysys/my_chmod.c b/mysys/my_chmod.c index 91fd51b47d2..095ac858834 100644 --- a/mysys/my_chmod.c +++ b/mysys/my_chmod.c @@ -11,7 +11,7 @@ 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 02111-1301 USA */ #include "mysys_priv.h" #include "mysys_err.h" diff --git a/mysys/my_compare.c b/mysys/my_compare.c index 3c21d74a8a4..5ba1b409abb 100644 --- a/mysys/my_compare.c +++ b/mysys/my_compare.c @@ -98,12 +98,12 @@ static int compare_bin(const uchar *a, uint a_length, Example1: if the function is called for tuples ('aaa','bbb') and ('eee','fff'), then diff_pos[0] = 1 (as 'aaa' != 'eee') - diff_pos[1] = 0 (offset from beggining of tuple b to 'eee' keypart). + diff_pos[1] = 0 (offset from beginning of tuple b to 'eee' keypart). Example2: if the index function is called for tuples ('aaa','bbb') and ('aaa','fff'), diff_pos[0] = 2 (as 'aaa' != 'eee') - diff_pos[1] = 3 (offset from beggining of tuple b to 'fff' keypart, + diff_pos[1] = 3 (offset from beginning of tuple b to 'fff' keypart, here we assume that first key part is CHAR(3) NOT NULL) NOTES diff --git a/mysys/my_compress.c b/mysys/my_compress.c index 78d09bb5f36..0e4db5c3b17 100644 --- a/mysys/my_compress.c +++ b/mysys/my_compress.c @@ -162,7 +162,7 @@ uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen) SYNOPSIS my_uncompress() - packet Compressed data. This is is replaced with the orignal data. + packet Compressed data. This is is replaced with the original data. len Length of compressed data complen Length of the packet buffer (must be enough for the original data) diff --git a/mysys/my_context.c b/mysys/my_context.c index 1368739ac35..cf10738bdbd 100644 --- a/mysys/my_context.c +++ b/mysys/my_context.c @@ -206,7 +206,8 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) ( "movq %%rsp, (%[save])\n\t" "movq %[stack], %%rsp\n\t" -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && !defined(__INTEL_COMPILER) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __clang__) && \ + !defined(__INTEL_COMPILER) /* This emits a DWARF DW_CFA_undefined directive to make the return address undefined. This indicates that this is the top of the stack frame, and diff --git a/mysys/my_create.c b/mysys/my_create.c index 6a3bcd63557..014b65c4e14 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -36,7 +36,7 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, myf MyFlags) { - int fd, rc; + int fd; DBUG_ENTER("my_create"); DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %lu", FileName, CreateFlags, access_flags, MyFlags)); @@ -54,21 +54,7 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, fd= -1; } - rc= my_register_filename(fd, FileName, FILE_BY_CREATE, + fd= my_register_filename(fd, FileName, FILE_BY_CREATE, EE_CANTCREATEFILE, MyFlags); - /* - my_register_filename() may fail on some platforms even if the call to - *open() above succeeds. In this case, don't leave the stale file because - callers assume the file to not exist if my_create() fails, so they don't - do any cleanups. - */ - if (unlikely(fd >= 0 && rc < 0)) - { - int tmp= my_errno; - my_close(fd, MyFlags); - my_delete(FileName, MyFlags); - my_errno= tmp; - } - - DBUG_RETURN(rc); + DBUG_RETURN(fd); } /* my_create */ diff --git a/mysys/my_default.c b/mysys/my_default.c index 6324c19bdda..e7d661b33e5 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -24,7 +24,7 @@ pre- and end 'blank space' are removed from options and values. The following escape sequences are recognized in values: \b \t \n \r \\ - The following arguments are handled automaticly; If used, they must be + The following arguments are handled automatically; If used, they must be first argument on the command line! --no-defaults ; no options are read. --defaults-file=full-path-to-default-file ; Only this file will be read. @@ -62,7 +62,7 @@ check the pointer, use "----args-separator----" here to ease debug if someone misused it. - The args seprator will only be added when + The args separator will only be added when my_getopt_use_args_seprator is set to TRUE before calling load_defaults(); @@ -597,7 +597,7 @@ int my_load_defaults(const char *conf_file, const char **groups, (*argv)+= args_used; /* - Check if we wan't to see the new argument list + Check if we want to see the new argument list This options must always be the last of the default options */ if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults")) diff --git a/mysys/my_delete.c b/mysys/my_delete.c index 3dfe290dabe..0faf6079d98 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -21,6 +21,12 @@ static int my_win_unlink(const char *name); #endif +CREATE_NOSYMLINK_FUNCTION( + unlink_nosymlinks(const char *pathname), + unlinkat(dfd, filename, 0), + unlink(pathname) +); + int my_delete(const char *name, myf MyFlags) { int err; @@ -30,7 +36,10 @@ int my_delete(const char *name, myf MyFlags) #ifdef _WIN32 err = my_win_unlink(name); #else - err = unlink(name); + if (MyFlags & MY_NOSYMLINKS) + err= unlink_nosymlinks(name); + else + err= unlink(name); #endif if(err) diff --git a/mysys/my_div.c b/mysys/my_div.c index 660b87e5ab4..44eb5392421 100644 --- a/mysys/my_div.c +++ b/mysys/my_div.c @@ -27,7 +27,7 @@ char * my_filename(File fd) { DBUG_ENTER("my_filename"); - if ((uint) fd >= (uint) my_file_limit) + if ((uint) fd >= (uint) my_file_limit || !my_file_info[fd].name) DBUG_RETURN((char*) "UNKNOWN"); if (fd >= 0 && my_file_info[fd].type != UNOPEN) { diff --git a/mysys/my_dlerror.c b/mysys/my_dlerror.c new file mode 100644 index 00000000000..db21b7fc274 --- /dev/null +++ b/mysys/my_dlerror.c @@ -0,0 +1,31 @@ +/* + Copyright (c) 2017, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include <my_global.h> +#include <string.h> + +const char *my_dlerror(const char *dlpath) +{ + const char *errmsg=dlerror(); + size_t dlpathlen= strlen(dlpath); + if (!strncmp(dlpath, errmsg, dlpathlen)) + { /* if errmsg starts from dlpath, trim this prefix */ + errmsg+=dlpathlen; + if (*errmsg == ':') errmsg++; + if (*errmsg == ' ') errmsg++; + } + return errmsg; +} diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 2ac033c8264..0bb431dd560 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -69,19 +69,13 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) DBUG_RETURN(fd); /* safeguard */ } mysql_mutex_lock(&THR_LOCK_open); - if ((my_file_info[filedesc].name= (char*) - my_strdup(filename,MyFlags))) - { - my_stream_opened++; - my_file_total_opened++; - my_file_info[filedesc].type= STREAM_BY_FOPEN; - mysql_mutex_unlock(&THR_LOCK_open); - DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); - DBUG_RETURN(fd); - } + my_file_info[filedesc].name= (char*) my_strdup(filename,MyFlags); + my_stream_opened++; + my_file_total_opened++; + my_file_info[filedesc].type= STREAM_BY_FOPEN; mysql_mutex_unlock(&THR_LOCK_open); - (void) my_fclose(fd,MyFlags); - my_errno=ENOMEM; + DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); + DBUG_RETURN(fd); } else my_errno=errno; diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index fbdcef88bda..bfa28f1d372 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -37,7 +37,7 @@ MyFlags Flags NOTES - Directory is allways ended with FN_LIBCHAR + Directory is always ended with FN_LIBCHAR RESULT 0 ok diff --git a/mysys/my_init.c b/mysys/my_init.c index 32289dbed7a..7f0f7a8cc44 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -99,7 +99,7 @@ my_bool my_init(void) if (my_progname) my_progname_short= my_progname + dirname_length(my_progname); - /* Initalize our mutex handling */ + /* Initialize our mutex handling */ my_mutex_init(); if (my_thread_global_init()) @@ -227,7 +227,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", /* At very last, delete mysys key, it is used everywhere including DBUG */ pthread_key_delete(THR_KEY_mysys); - my_init_done=0; + my_init_done= my_thr_key_mysys_exists= 0; } /* my_end */ #ifndef DBUG_OFF @@ -415,7 +415,7 @@ static my_bool win32_init_tcp_ip() WORD wVersionRequested = MAKEWORD( 2, 2 ); WSADATA wsaData; /* Be a good citizen: maybe another lib has already initialised - sockets, so dont clobber them unless necessary */ + sockets, so don't clobber them unless necessary */ if (WSAStartup( wVersionRequested, &wsaData )) { /* Load failed, maybe because of previously loaded diff --git a/mysys/my_lib.c b/mysys/my_lib.c index a8f7c02ab63..abc7b8a3161 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -14,7 +14,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* TODO: check for overun of memory for names. */ +/* TODO: check for overrun of memory for names. */ #include "mysys_priv.h" #include <m_string.h> diff --git a/mysys/my_open.c b/mysys/my_open.c index b6d8f08bfc1..3999810eb2e 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -15,9 +15,14 @@ #include "mysys_priv.h" #include "mysys_err.h" -#include <my_dir.h> +#include <m_string.h> #include <errno.h> +CREATE_NOSYMLINK_FUNCTION( + open_nosymlinks(const char *pathname, int flags, int mode), + openat(dfd, filename, O_NOFOLLOW | flags, mode), + open(pathname, O_NOFOLLOW | flags, mode) +); /* Open a file @@ -45,10 +50,11 @@ File my_open(const char *FileName, int Flags, myf MyFlags) MyFlags|= my_global_flags; #if defined(_WIN32) fd= my_win_open(FileName, Flags); -#elif !defined(NO_OPEN_3) - fd = open(FileName, Flags | O_CLOEXEC, my_umask); /* Normal unix */ #else - fd = open((char *) FileName, Flags | O_CLOEXEC); + if (MyFlags & MY_NOSYMLINKS) + fd = open_nosymlinks(FileName, Flags | O_CLOEXEC, my_umask); + else + fd = open(FileName, Flags | O_CLOEXEC, my_umask); #endif fd= my_register_filename(fd, FileName, FILE_BY_OPEN, @@ -131,25 +137,16 @@ File my_register_filename(File fd, const char *FileName, enum file_type thread_safe_increment(my_file_opened,&THR_LOCK_open); DBUG_RETURN(fd); /* safeguard */ } - else - { - mysql_mutex_lock(&THR_LOCK_open); - if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) - { - my_file_opened++; - my_file_total_opened++; - my_file_info[fd].type = type_of_file; - mysql_mutex_unlock(&THR_LOCK_open); - DBUG_PRINT("exit",("fd: %d",fd)); - DBUG_RETURN(fd); - } - mysql_mutex_unlock(&THR_LOCK_open); - my_errno= ENOMEM; - } - (void) my_close(fd, MyFlags); + mysql_mutex_lock(&THR_LOCK_open); + my_file_info[fd].name = (char*) my_strdup(FileName, MyFlags); + my_file_opened++; + my_file_total_opened++; + my_file_info[fd].type = type_of_file; + mysql_mutex_unlock(&THR_LOCK_open); + DBUG_PRINT("exit",("fd: %d",fd)); + DBUG_RETURN(fd); } - else - my_errno= errno; + my_errno= errno; DBUG_PRINT("error",("Got error %d on open", my_errno)); if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) diff --git a/mysys/my_port.c b/mysys/my_port.c index 96dbe10b1bd..75a07b03efe 100644 --- a/mysys/my_port.c +++ b/mysys/my_port.c @@ -12,8 +12,8 @@ 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 */ + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02111-1301, USA */ /* Small functions to make code portable diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 745cde9ec41..d3524279ea9 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -28,7 +28,7 @@ SYNOPSIOS my_pread() - Filedes File decsriptor + Filedes File descriptor Buffer Buffer to read data into Count Number of bytes to read offset Position to read from @@ -108,7 +108,7 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, SYNOPSIOS my_pwrite() - Filedes File decsriptor + Filedes File descriptor Buffer Buffer to write data from Count Number of bytes to write offset Position to write to diff --git a/mysys/my_redel.c b/mysys/my_redel.c index 976fc5a18c3..9091c74e6b5 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -32,10 +32,10 @@ struct utimbuf { /* Rename with copy stat form old file - Copy stats from old file to new file, deletes orginal and + Copy stats from old file to new file, deletes original and changes new file name to old file name - if MY_REDEL_MAKE_COPY is given, then the orginal file + if MY_REDEL_MAKE_COPY is given, then the original file is renamed to org_name-'current_time'.BAK */ diff --git a/mysys/my_rnd.c b/mysys/my_rnd.c index ad7bda0b42b..fc38d5586ce 100644 --- a/mysys/my_rnd.c +++ b/mysys/my_rnd.c @@ -11,7 +11,7 @@ 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 02111-1301 USA */ #include "mysys_priv.h" #include <my_rnd.h> diff --git a/mysys/my_safehash.c b/mysys/my_safehash.c index 1417b8ea94e..c34f3c456cd 100644 --- a/mysys/my_safehash.c +++ b/mysys/my_safehash.c @@ -12,7 +12,7 @@ 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 02111-1301 USA */ /* Handling of multiple key caches diff --git a/mysys/my_safehash.h b/mysys/my_safehash.h index e52fee68b57..3d3aa1e6006 100644 --- a/mysys/my_safehash.h +++ b/mysys/my_safehash.h @@ -12,7 +12,7 @@ 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 02111-1301 USA */ /* Handling of multiple key caches diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index b0e910f7ba0..72648d4c9a8 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -1,5 +1,6 @@ /* Copyright (c) 2001, 2011, Oracle and/or its affiliates + Copyright (c) 2010, 2017, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,6 +24,14 @@ #include <sys/stat.h> #endif +static int always_valid(const char *filename __attribute__((unused))) +{ + return 0; +} + +int (*mysys_test_invalid_symlink)(const char *filename)= always_valid; + + /* Reads the content of a symbolic link If the file is not a symbolic link, return the original file name in to. @@ -120,6 +129,11 @@ int my_is_symlink(const char *filename __attribute__((unused))) to is guaranteed to never set to a string longer than FN_REFLEN (including the end \0) + + On error returns -1, unless error is file not found, in which case it + is 1. + + Sets my_errno to specific error number. */ int my_realpath(char *to, const char *filename, myf MyFlags) @@ -145,7 +159,10 @@ int my_realpath(char *to, const char *filename, myf MyFlags) if (MyFlags & MY_WME) my_error(EE_REALPATH, MYF(0), filename, my_errno); my_load_path(to, filename, NullS); - result= -1; + if (my_errno == ENOENT) + result= 1; + else + result= -1; } DBUG_RETURN(result); #elif defined(_WIN32) @@ -168,3 +185,78 @@ int my_realpath(char *to, const char *filename, myf MyFlags) #endif return 0; } + +#ifdef HAVE_OPEN_PARENT_DIR_NOSYMLINKS +/** opens the parent dir. walks the path, and does not resolve symlinks + + returns the pointer to the file name (basename) within the pathname + or NULL in case of an error + + stores the parent dir (dirname) file descriptor in pdfd. + It can be -1 even if there was no error! + + This is used for symlinked tables for DATA/INDEX DIRECTORY. + The paths there have been realpath()-ed. So, we can assume here that + + * `pathname` is an absolute path + * no '.', '..', and '//' in the path + * file exists +*/ + +const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd) +{ + char buf[PATH_MAX+1]; + char *s= buf, *e= buf+1, *end= strnmov(buf, pathname, sizeof(buf)); + int fd, dfd= -1; + + if (*end) + { + errno= ENAMETOOLONG; + return NULL; + } + + if (*s != '/') /* not an absolute path */ + { + errno= ENOENT; + return NULL; + } + + for (;;) + { + if (*e == '/') /* '//' in the path */ + { + errno= ENOENT; + goto err; + } + while (*e && *e != '/') + e++; + *e= 0; + + if (!memcmp(s, ".", 2) || !memcmp(s, "..", 3)) + { + errno= ENOENT; + goto err; + } + + if (++e >= end) + { + *pdfd= dfd; + return pathname + (s - buf); + } + + fd = openat(dfd, s, O_NOFOLLOW | O_PATH); + if (fd < 0) + goto err; + + if (dfd >= 0) + close(dfd); + + dfd= fd; + s= e; + } +err: + if (dfd >= 0) + close(dfd); + return NULL; +} +#endif diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index fcaf78ccff6..f1ace5dcd77 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -17,7 +17,7 @@ /* Advanced symlink handling. This is used in MyISAM to let users symlinks tables to different disk. - The main idea with these functions is to automaticly create, delete and + The main idea with these functions is to automatically create, delete and rename files and symlinks like they would be one unit. */ @@ -92,27 +92,6 @@ File my_create_with_symlink(const char *linkname, const char *filename, } /* - If the file was a symlink, delete both symlink and the file which the - symlink pointed to. -*/ - -int my_delete_with_symlink(const char *name, myf MyFlags) -{ - char link_name[FN_REFLEN]; - int was_symlink= (!my_disable_symlinks && - !my_readlink(link_name, name, MYF(0))); - int result; - DBUG_ENTER("my_delete_with_symlink"); - - if (!(result=my_delete(name, MyFlags))) - { - if (was_symlink) - result=my_delete(link_name, MyFlags); - } - DBUG_RETURN(result); -} - -/* If the file is a normal file, just rename it. If the file is a symlink: - Create a new file with the name 'to' that points at @@ -182,3 +161,29 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) DBUG_RETURN(result); #endif /* HAVE_READLINK */ } + +/** delete a - possibly symlinked - table file + + This is used to delete a file that is part of a table (e.g. MYI or MYD + file of MyISAM) when dropping a table. A file might be a symlink - + if the table was created with DATA DIRECTORY or INDEX DIRECTORY - + in this case both the symlink and the symlinked file are deleted, + but only if the symlinked file is not in the datadir. +*/ +int my_handler_delete_with_symlink(const char *filename, myf sync_dir) +{ + char real[FN_REFLEN]; + int res= 0; + DBUG_ENTER("my_handler_delete_with_symlink"); + + if (my_is_symlink(filename)) + { + /* + Delete the symlinked file only if the symlink is not + pointing into datadir. + */ + if (!(my_realpath(real, filename, MYF(0)) || mysys_test_invalid_symlink(real))) + res= my_delete(real, MYF(MY_NOSYMLINKS | sync_dir)); + } + DBUG_RETURN(my_delete(filename, MYF(sync_dir)) || res); +} diff --git a/mysys/my_sync.c b/mysys/my_sync.c index c0afd587ada..d1e239692f1 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -196,7 +196,7 @@ int my_sync_dir_by_file(const char *file_name __attribute__((unused)), char dir_name[FN_REFLEN]; size_t dir_name_length; dirname_part(dir_name, file_name, &dir_name_length); - return my_sync_dir(dir_name, my_flags); + return my_sync_dir(dir_name, my_flags & ~MY_NOSYMLINKS); #else return 0; #endif diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 60a46997901..678bfc459c7 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -44,6 +44,8 @@ static uint get_thread_lib(void); /** True if @c my_thread_global_init() has been called. */ static my_bool my_thread_global_init_done= 0; +/* True if THR_KEY_mysys is created */ +my_bool my_thr_key_mysys_exists= 0; /* @@ -167,11 +169,20 @@ my_bool my_thread_global_init(void) return 0; my_thread_global_init_done= 1; - if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) + /* + THR_KEY_mysys is deleted in my_end() as DBUG libraries are using it even + after my_thread_global_end() is called. + my_thr_key_mysys_exist is used to protect against application like QT + that calls my_thread_global_init() + my_thread_global_end() multiple times + without calling my_init() + my_end(). + */ + if (!my_thr_key_mysys_exists && + (pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) { fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret); return 1; } + my_thr_key_mysys_exists= 1; /* Mutex used by my_thread_init() and after my_thread_destroy_mutex() */ my_thread_init_internal_mutex(); @@ -262,7 +273,7 @@ my_bool my_thread_init(void) my_bool error=0; if (!my_thread_global_init_done) - return 1; /* cannot proceed with unintialized library */ + return 1; /* cannot proceed with uninitialized library */ #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_init(): pthread_self: %p\n", pthread_self()); diff --git a/mysys/my_uuid.c b/mysys/my_uuid.c index a8614afef2c..f167ebe1d6e 100644 --- a/mysys/my_uuid.c +++ b/mysys/my_uuid.c @@ -11,7 +11,7 @@ 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 02111-1301 USA */ /* implements Universal Unique Identifiers (UUIDs), as in diff --git a/mysys/my_windac.c b/mysys/my_windac.c index 51fe22e8f59..9b489759625 100644 --- a/mysys/my_windac.c +++ b/mysys/my_windac.c @@ -33,7 +33,7 @@ static my_bool is_nt() } /* - Auxilary structure to store pointers to the data which we need to keep + Auxiliary structure to store pointers to the data which we need to keep around while SECURITY_ATTRIBUTES is in use. */ diff --git a/mysys/my_winerr.c b/mysys/my_winerr.c index 15f52dd7f37..92e1fa83d78 100644 --- a/mysys/my_winerr.c +++ b/mysys/my_winerr.c @@ -117,7 +117,7 @@ static int get_errno_from_oserr(unsigned long oserrno) return EINVAL; } -/* Set errno corresponsing to GetLastError() value */ +/* Set errno corresponding to GetLastError() value */ void my_osmaperr ( unsigned long oserrno) { errno= get_errno_from_oserr(oserrno); diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index d080aca7404..471862a6d0b 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -108,6 +108,34 @@ size_t sf_malloc_usable_size(void *ptr, my_bool *is_thread_specific); void my_error_unregister_all(void); +#if !defined(O_PATH) && defined(O_EXEC) /* FreeBSD */ +#define O_PATH O_EXEC +#endif + +#ifdef O_PATH +#define HAVE_OPEN_PARENT_DIR_NOSYMLINKS +const char *my_open_parent_dir_nosymlinks(const char *pathname, int *pdfd); +#define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \ + int dfd, res; \ + const char *filename= my_open_parent_dir_nosymlinks(pathname, &dfd); \ + if (filename == NULL) return -1; \ + res= AT; \ + if (dfd >= 0) close(dfd); \ + return res; +#elif defined(HAVE_REALPATH) +#define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \ + char buf[PATH_MAX+1]; \ + if (realpath(pathname, buf) == NULL) return -1; \ + if (strcmp(pathname, buf)) { errno= ENOTDIR; return -1; } \ + return NOAT; +#else +#define NOSYMLINK_FUNCTION_BODY(AT,NOAT) \ + return NOAT; +#endif + +#define CREATE_NOSYMLINK_FUNCTION(PROTO,AT,NOAT) \ +static int PROTO { NOSYMLINK_FUNCTION_BODY(AT,NOAT) } + #ifdef _WIN32 #include <sys/stat.h> /* my_winfile.c exports, should not be used outside mysys */ diff --git a/mysys/queues.c b/mysys/queues.c index 418163d7c58..5d09ce2063f 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -27,7 +27,7 @@ This code originates from the Unireg project. Code for generell handling of priority Queues. - Implemention of queues from "Algoritms in C" by Robert Sedgewick. + Implementation of queues from "Algorithms in C" by Robert Sedgewick. The queue can optionally store the position in queue in the element that is in the queue. This allows one to remove any element from the queue diff --git a/mysys/test_thr_mutex.c b/mysys/test_thr_mutex.c index 0bd14a0d31b..fa5b6f74ba3 100644 --- a/mysys/test_thr_mutex.c +++ b/mysys/test_thr_mutex.c @@ -11,7 +11,7 @@ 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 02111-1301 USA */ /* Testing of deadlock detector */ diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index a77db04acef..c168957097f 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -517,8 +517,8 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, One can use this to signal when a thread is going to wait for a lock. See debug_sync.cc. - Beware of waiting for a signal here. The lock has aquired its mutex. - While waiting on a signal here, the locking thread could not aquire + Beware of waiting for a signal here. The lock has acquired its mutex. + While waiting on a signal here, the locking thread could not acquire the mutex to release the lock. One could lock up the table completely. @@ -788,8 +788,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) \ = READ - + = Request can be satisified. - - = Request cannot be satisified. + + = Request can be satisfied. + - = Request cannot be satisfied. READ_NO_INSERT and WRITE_ALLOW_WRITE should in principle be incompatible. However this will cause starvation of @@ -1248,7 +1248,7 @@ end: /* Get all locks in a specific order to avoid dead-locks - Sort acording to lock position and put write_locks before read_locks if + Sort according to lock position and put write_locks before read_locks if lock on same lock. Locks on MERGE tables has lower priority than other locks of the same type. See comment for lock_priority. */ diff --git a/mysys/tree.c b/mysys/tree.c index ab810c64c67..5eaeb30037d 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -30,8 +30,8 @@ 3) if key_size is given to init_tree then each node will continue the key and calls to insert_key may increase length of key. if key_size > sizeof(pointer) and key_size is a multiple of 8 (double - allign) then key will be put on a 8 alligned adress. Else - the key will be on adress (element+1). This is transparent for user + align) then key will be put on a 8 aligned address. Else + the key will be on address (element+1). This is transparent for user compare and search functions uses a pointer to given key-argument. - If you use a free function for tree-elements and you are freeing diff --git a/mysys/typelib.c b/mysys/typelib.c index 75744a65ec8..96842b1a3ad 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -182,7 +182,7 @@ const char *get_type(TYPELIB *typelib, uint nr) /** - Create an integer value to represent the supplied comma-seperated + Create an integer value to represent the supplied comma-separated string where each string in the TYPELIB denotes a bit position. @param x string to decompose diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index ae0ffe7f7eb..7d8aae032ea 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -12,7 +12,7 @@ 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 02111-1301 USA */ /** @file @@ -136,7 +136,7 @@ Status ^^^^^^ - We calculate the number of successfull waits (WT_OK returned from + We calculate the number of successful waits (WT_OK returned from wt_thd_cond_timedwait()), a number of timeouts, a deadlock cycle length distribution - number of deadlocks with every length from 1 to WT_CYCLE_STATS, and a wait time distribution - number diff --git a/mysys/wqueue.c b/mysys/wqueue.c index 2fcced14f77..1dafc03b935 100644 --- a/mysys/wqueue.c +++ b/mysys/wqueue.c @@ -13,7 +13,7 @@ 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 02111-1301 USA */ #include <wqueue.h> @@ -211,7 +211,7 @@ void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue) /* Add thread and wait - SYNOPSYS + SYNOPSIS wqueue_add_and_wait() wqueue queue to add to thread thread which is waiting |