diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f69a017..7b5b8c04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,6 @@ IF(COMMAND CMAKE_POLICY) ENDIF() -PROJECT(mariadb-connector-c C) - # Is C/C built as subproject? get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY) @@ -25,11 +23,29 @@ get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY) SET_PROPERTY(DIRECTORY PROPERTY INCLUDE_DIRECTORIES) FOREACH(V WITH_MYSQLCOMPAT WITH_MSI WITH_SIGNCODE WITH_RTC WITH_UNIT_TESTS WITH_DYNCOL WITH_EXTERNAL_ZLIB WITH_CURL WITH_SQLITE WITH_SSL WITH_ICONV - DEFAULT_CHARSET INSTALL_LAYOUT WITH_TEST_SRCPKG + DEFAULT_CHARSET INSTALL_LAYOUT WITH_TEST_SRCPKG WITH_BOOST_CONTEXT DEFAULT_SSL_VERIFY_SERVER_CERT) SET(${V} ${${OPT}${V}}) ENDFOREACH() +MACRO(ADD_OPTION _name _text _default) + IF(NOT DEFINED ${_name}) + OPTION(${OPT}${_name} "${_text}" "${_default}") + ELSE() + OPTION(${OPT}${_name} "${_text}" "${${_name}}") + ENDIF() +ENDMACRO() + +ADD_OPTION(WITH_BOOST_CONTEXT + "Use Boost::Context for the non-blocking API on platforms without native implementation" + OFF) + +IF(WITH_BOOST_CONTEXT) + PROJECT(mariadb-connector-c LANGUAGES C CXX) +ELSE() + PROJECT(mariadb-connector-c C) +ENDIF() + SET(CC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) SET(CC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) @@ -41,14 +57,6 @@ MATH(EXPR MARIADB_PACKAGE_VERSION_ID "${CPACK_PACKAGE_VERSION_MAJOR} * 10000 + ${CPACK_PACKAGE_VERSION_MINOR} * 100 + ${CPACK_PACKAGE_VERSION_PATCH}") -MACRO(ADD_OPTION _name _text _default) - IF(NOT DEFINED ${_name}) - OPTION(${OPT}${_name} "${_text}" "${_default}") - ELSE() - OPTION(${OPT}${_name} "${_text}" "${${_name}}") - ENDIF() -ENDMACRO() - ### Options ### IF(NOT WIN32) ADD_OPTION(WITH_MYSQLCOMPAT "creates libmysql* symbolic links" OFF) @@ -367,6 +375,11 @@ IF(NOT WITH_SSL STREQUAL "OFF") MARK_AS_ADVANCED(SSL_SOURCES) ENDIF() +IF(WITH_BOOST_CONTEXT) + FIND_PACKAGE(Boost 1.40 COMPONENTS context REQUIRED) + SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${Boost_LIBRARIES}) +ENDIF() + SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)") MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE) IF (ENABLED_LOCAL_INFILE MATCHES "^(0|FALSE)$") diff --git a/cmake/check_include_files.cmake b/cmake/check_include_files.cmake index d8bbffcd..50e289fa 100644 --- a/cmake/check_include_files.cmake +++ b/cmake/check_include_files.cmake @@ -43,6 +43,9 @@ CHECK_INCLUDE_FILES (sys/types.h HAVE_SYS_TYPES_H) CHECK_INCLUDE_FILES (sys/stat.h HAVE_SYS_STAT_H) CHECK_INCLUDE_FILES (sys/un.h HAVE_SYS_UN_H) CHECK_INCLUDE_FILES (unistd.h HAVE_UNISTD_H) +IF(WITH_BOOST_CONTEXT) + CHECK_INCLUDE_FILE_CXX (boost/fiber/context.hpp HAVE_BOOST_CONTEXT_H) +ENDIF() IF(APPLE) SET(CMAKE_REQUIRED_DEFINITIONS -D_XOPEN_SOURCE=600) diff --git a/cmake/plugins.cmake b/cmake/plugins.cmake index de5c12c1..5de75750 100644 --- a/cmake/plugins.cmake +++ b/cmake/plugins.cmake @@ -50,7 +50,7 @@ FUNCTION(REGISTER_PLUGIN) endif() if(NOT ${CC_PLUGIN_DEFAULT} STREQUAL "OFF") - set(PLUGIN_${CC_PLUGIN_TARGET}_TYPE ${CC_PLUGIN_TYPE}) + set(PLUGIN_${CC_PLUGIN_TARGET}_TYPE ${CC_PLUGIN_TYPE} PARENT_SCOPE) if(${CC_PLUGIN_DEFAULT} MATCHES "DYNAMIC") diff --git a/include/ma_config.h.in b/include/ma_config.h.in index b2b6bfab..8af0a5aa 100644 --- a/include/ma_config.h.in +++ b/include/ma_config.h.in @@ -29,6 +29,7 @@ #cmakedefine HAVE_SYS_UN_H 1 #cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_UCONTEXT_H 1 +#cmakedefine HAVE_BOOST_CONTEXT_H 1 /* * function definitions - processed in LibmysqlFunctions.txt diff --git a/include/ma_context.h b/include/ma_context.h index 0ad7f68b..4c3f0d8d 100644 --- a/include/ma_context.h +++ b/include/ma_context.h @@ -32,12 +32,20 @@ #define MY_CONTEXT_USE_X86_64_GCC_ASM #elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__) #define MY_CONTEXT_USE_I386_GCC_ASM +#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__aarch64__) +#define MY_CONTEXT_USE_AARCH64_GCC_ASM +#elif defined(HAVE_BOOST_CONTEXT_H) +#define MY_CONTEXT_USE_BOOST_CONTEXT #elif defined(HAVE_UCONTEXT_H) #define MY_CONTEXT_USE_UCONTEXT #else #define MY_CONTEXT_DISABLE #endif +#ifdef __cplusplus +extern "C" { +#endif + #ifdef MY_CONTEXT_USE_WIN32_FIBERS struct my_context { void (*user_func)(void *); @@ -107,6 +115,49 @@ struct my_context { #endif +#ifdef MY_CONTEXT_USE_AARCH64_GCC_ASM +#include + +struct my_context { + uint64_t save[22]; + void *stack_top; + void *stack_bot; +#ifdef HAVE_VALGRIND + unsigned int valgrind_stack_id; +#endif +#ifndef DBUG_OFF + void *dbug_state; +#endif +}; +#endif + + +#ifdef MY_CONTEXT_USE_BOOST_CONTEXT +/* + boost::context is a C++-library that provides a portable co-routine fallback + for architectures that lack a native my_context implementation, and which is + available on some platforms where ucontext is not (ucontext has been + deprecated in Posix). + + Since boost::context is in C++, the implementation details must be put into + a separate source file ma_boost_context.cc and hidden in an opaque void *. +*/ +struct my_context { + /* Pointer to state that uses C++-types and cannot be compiled in C. */ + void *internal_context; + void *stack; + size_t stack_size; +#ifndef DBUG_OFF + void *dbug_state; +#endif + int active; +#ifdef HAVE_VALGRIND + unsigned int valgrind_stack_id; +#endif +}; +#endif /* MY_CONTEXT_USE_BOOST_CONTEXT */ + + #ifdef MY_CONTEXT_DISABLE struct my_context { int dummy; @@ -240,3 +291,7 @@ struct mysql_async_context { */ struct my_context async_context; }; + +#ifdef __cplusplus +} +#endif diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 318d3f69..29c6107c 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -298,7 +298,7 @@ MESSAGE(STATUS "SYSTEM_LIBS: ${SYSTEM_LIBS}") INCLUDE_DIRECTORIES(${LIBMARIADB_PLUGIN_INCLUDES}) ADD_DEFINITIONS(${LIBMARIADB_PLUGIN_DEFS}) FOREACH(plugin ${PLUGINS_STATIC}) - SET(EXTERNAL_PLUGINS "${EXTERNAL_PLUGINS} extern struct st_mysql_client_plugin ${plugin}_client_plugin;\n") + SET(EXTERNAL_PLUGINS "${EXTERNAL_PLUGINS} extern struct st_mysql_client_plugin_${PLUGIN_${plugin}_TYPE} ${plugin}_client_plugin;\n") SET(BUILTIN_PLUGINS "${BUILTIN_PLUGINS} (struct st_mysql_client_plugin *)&${plugin}_client_plugin,\n") ENDFOREACH() CONFIGURE_FILE(${CC_SOURCE_DIR}/libmariadb/ma_client_plugin.c.in @@ -394,6 +394,9 @@ IF(WITH_DYNCOL) ENDIF() SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} mariadb_async.c ma_context.c) +IF(WITH_BOOST_CONTEXT) + SET(LIBMARIADB_SOURCES ${LIBMARIADB_SOURCES} ma_boost_context.cc) +ENDIF() SET(MARIADB_LIB_SYMBOLS ${MARIADB_LIB_SYMBOLS} ${MARIADB_NONBLOCK_SYMBOLS}) INCLUDE(${CC_SOURCE_DIR}/cmake/export.cmake) diff --git a/libmariadb/ma_boost_context.cc b/libmariadb/ma_boost_context.cc new file mode 100644 index 00000000..cb7625d9 --- /dev/null +++ b/libmariadb/ma_boost_context.cc @@ -0,0 +1,117 @@ +#include "ma_config.h" +#include "mysql.h" +#include "ma_context.h" + +#ifdef MY_CONTEXT_USE_BOOST_CONTEXT + +#include + +namespace ctx=boost::context; + +struct my_context_intern { + ctx::fiber parent, coro; + + void *stack_top(const my_context *c) { + return (unsigned char *)(c->stack) + c->stack_size; + } + + /* A StackAlloc for ctx::fiber that reuses our stack. */ + struct my_stack_alloc { + typedef ctx::stack_traits traits_type; + my_context *c; + my_stack_alloc(my_context *c_arg) : c(c_arg) { }; + ctx::stack_context allocate() { + ctx::stack_context sctx; + sctx.size= c->stack_size; + sctx.sp= ((my_context_intern *)c->internal_context)->stack_top(c); +#if defined(BOOST_USE_VALGRIND) && defined(HAVE_VALGRIND) + sctx.valgrind_stack_id= c->valgrind_stack_id; +#endif + return sctx; + } + void deallocate(ctx::stack_context & sctx) { + /* Empty, we will re-use the stack. */ + } + }; +}; + + +extern "C" +int +my_context_spawn(struct my_context *c, void (*f)(void *), void *d) +{ + my_context_intern *ci= (my_context_intern *)c->internal_context; + ci->coro= ctx::fiber(std::allocator_arg, my_context_intern::my_stack_alloc(c), + [c, f, d](ctx::fiber && parent) { + my_context_intern *ci= (my_context_intern *)c->internal_context; + ci->parent= std::move(parent); + (*f)(d); + c->active= 0; + return std::move(ci->parent); + }); + c->active= 1; + ci->coro= std::move(ci->coro).resume(); + return c->active; +} + + +extern "C" +int +my_context_continue(struct my_context *c) +{ + if (!c->active) + return 0; + my_context_intern *ci= (my_context_intern *)c->internal_context; + ci->coro= std::move(ci->coro).resume(); + return c->active; +} + + +extern "C" +int +my_context_yield(struct my_context *c) +{ + if (!c->active) + return -1; + my_context_intern *ci= (my_context_intern *)c->internal_context; + ci->parent= std::move(ci->parent).resume(); + return 0; +} + + +extern "C" +int +my_context_init(struct my_context *c, size_t stack_size) +{ + memset(c, 0, sizeof(*c)); + if (!(c->stack= malloc(stack_size))) + return -1; /* Out of memory */ + if (!(c->internal_context= new my_context_intern)) + { + free(c->stack); + return -1; + } + c->stack_size= stack_size; +#ifdef HAVE_VALGRIND + c->valgrind_stack_id= + VALGRIND_STACK_REGISTER(c->stack, ((unsigned char *)(c->stack))+stack_size); +#endif + return 0; +} + + +extern "C" +void +my_context_destroy(struct my_context *c) +{ + delete (my_context_intern *)c->internal_context; + if (c->stack) + { +#ifdef HAVE_VALGRIND + VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); +#endif + free(c->stack); + } +} + +#endif /* MY_CONTEXT_USE_BOOST_CONTEXT */ diff --git a/libmariadb/ma_context.c b/libmariadb/ma_context.c index 222dbe28..f9431d04 100644 --- a/libmariadb/ma_context.c +++ b/libmariadb/ma_context.c @@ -21,6 +21,9 @@ swapcontext(). */ +#include +#include + #include "ma_global.h" #include "ma_string.h" #include "ma_context.h" @@ -167,9 +170,6 @@ my_context_destroy(struct my_context *c) save them as we cannot know if we will yield or not in advance). */ -#include -#include - /* Layout of saved registers etc. Since this is accessed through gcc inline assembler, it is simpler to just @@ -204,7 +204,7 @@ 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_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 @@ -408,9 +408,6 @@ my_context_destroy(struct my_context *c) save them as we cannot know if we will yield or not in advance). */ -#include -#include - /* Layout of saved registers etc. Since this is accessed through gcc inline assembler, it is simpler to just @@ -443,7 +440,7 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) ( "movl %%esp, (%[save])\n\t" "movl %[stack], %%esp\n\t" -#if __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 @@ -625,6 +622,334 @@ my_context_destroy(struct my_context *c) #endif /* MY_CONTEXT_USE_I386_GCC_ASM */ +#ifdef MY_CONTEXT_USE_AARCH64_GCC_ASM +/* + GCC-aarch64 (arm64) implementation of my_context. + + This is slightly optimized in the common case where we never yield + (eg. fetch next row and it is already fully received in buffer). In this + case we do not need to restore registers at return (though we still need to + save them as we cannot know if we will yield or not in advance). +*/ + +/* + Layout of saved registers etc. + Since this is accessed through gcc inline assembler, it is simpler to just + use numbers than to try to define nice constants or structs. + + 0 0 x19 + 1 8 x20 + 2 16 x21 + ... + 9 72 x28 + 10 80 x29 (frame pointer) + 11 88 sp + 12 96 d8 + 13 104 d9 + ... + 19 152 d15 + 20 160 pc for done + 21 168 pc for yield/continue +*/ + +int +my_context_spawn(struct my_context *c, void (*f)(void *), void *d) +{ + register int ret asm("w0"); + register void (*f_reg)(void *) asm("x1") = f; + register void *d_reg asm("x2") = d; + register void *stack asm("x13") = c->stack_top; + /* Need this in callee-save register to preserve in function call. */ + register const uint64_t *save asm("x19") = &c->save[0]; + + /* + There are a total of 20 callee-save registers (including frame pointer and + link register) we need to save and restore when suspending and continuing, + plus stack pointer sp and program counter pc. + + However, if we never suspend, the user-supplied function will in any case + restore the callee-save registers, so we can avoid restoring them in this + case. + */ + __asm__ __volatile__ + ( + "mov x10, sp\n\t" + "mov sp, %[stack]\n\t" +#if !defined(__INTEL_COMPILER) + /* + This emits a DWARF DW_CFA_undefined directive to make the return address + (UNW_AARCH64_X30) undefined. This indicates that this is the top of the + stack frame, and helps tools that use DWARF stack unwinding to obtain + stack traces. (I use numeric constant to avoid a dependency on libdwarf + includes). + */ + ".cfi_escape 0x07, 30\n\t" +#endif + "stp x19, x20, [%[save], #0]\n\t" + "stp x21, x22, [%[save], #16]\n\t" + "stp x23, x24, [%[save], #32]\n\t" + "stp x25, x26, [%[save], #48]\n\t" + "stp x27, x28, [%[save], #64]\n\t" + "stp x29, x10, [%[save], #80]\n\t" + "stp d8, d9, [%[save], #96]\n\t" + "stp d10, d11, [%[save], #112]\n\t" + "stp d12, d13, [%[save], #128]\n\t" + "stp d14, d15, [%[save], #144]\n\t" + "adr x10, 1f\n\t" + "adr x11, 2f\n\t" + "stp x10, x11, [%[save], #160]\n\t" + + /* Need this in x0 to follow calling convention. */ + "mov x0, %[d]\n\t" + "blr %[f]\n\t" + "ldr x11, [%[save], #160]\n\t" + "br x11\n" + /* + Come here when operation is done. + We do not need to restore callee-save registers, as the called function + will do this for us if needed. + */ + "1:\n\t" + "ldr x10, [%[save], #88]\n\t" + "mov sp, x10\n\t" + "mov %w[ret], #0\n\t" + "b 3f\n" + /* Come here when operation was suspended. */ + "2:\n\t" + "mov %w[ret], #1\n" + "3:\n" + : [ret] "=r" (ret), + [f] "+r" (f_reg), + [d] "+r" (d_reg), + [stack] "+r" (stack) + : [save] "r" (save) + : "x3", "x4", "x5", "x6", "x7", + "x9", "x10", "x11", "x14", "x15", "x18", "x30", + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", + "memory", "cc" + ); + + return ret; +} + +int +my_context_continue(struct my_context *c) +{ + register int ret asm("w0"); + /* Need this in callee-save register to preserve in function call. */ + register const uint64_t *save asm("x19") = &c->save[0]; + + __asm__ __volatile__ + ( + "ldp x13, x11, [%[save], #0]\n\t" + "stp x19, x20, [%[save], #0]\n\t" + /* x19 is %[save], delay restoring it until %[save] is no longer needed. */ + "mov x20, x11\n\t" + + "ldp x10, x11, [%[save], #16]\n\t" + "stp x21, x22, [%[save], #16]\n\t" + "mov x21, x10\n\t" + "mov x22, x11\n\t" + + "ldp x10, x11, [%[save], #32]\n\t" + "stp x23, x24, [%[save], #32]\n\t" + "mov x23, x10\n\t" + "mov x24, x11\n\t" + + "ldp x10, x11, [%[save], #48]\n\t" + "stp x25, x26, [%[save], #48]\n\t" + "mov x25, x10\n\t" + "mov x26, x11\n\t" + + "ldp x10, x11, [%[save], #64]\n\t" + "stp x27, x28, [%[save], #64]\n\t" + "mov x27, x10\n\t" + "mov x28, x11\n\t" + + "ldp x10, x11, [%[save], #80]\n\t" + "mov x14, sp\n\t" + "stp x29, x14, [%[save], #80]\n\t" + "mov x29, x10\n\t" + "mov sp, x11\n\t" + + "ldp d0, d1, [%[save], #96]\n\t" + "stp d8, d9, [%[save], #96]\n\t" + "fmov d8, d0\n\t" + "fmov d9, d1\n\t" + + "ldp d0, d1, [%[save], #112]\n\t" + "stp d10, d11, [%[save], #112]\n\t" + "fmov d10, d0\n\t" + "fmov d11, d1\n\t" + + "ldp d0, d1, [%[save], #128]\n\t" + "stp d12, d13, [%[save], #128]\n\t" + "fmov d12, d0\n\t" + "fmov d13, d1\n\t" + + "ldp d0, d1, [%[save], #144]\n\t" + "stp d14, d15, [%[save], #144]\n\t" + "fmov d14, d0\n\t" + "fmov d15, d1\n\t" + + "adr x10, 1f\n\t" + "adr x11, 2f\n\t" + "ldr x15, [%[save], #168]\n\t" + "stp x10, x11, [%[save], #160]\n\t" + "mov x19, x13\n\t" + "br x15\n" + /* + Come here when operation is done. + Be sure to use the same callee-save register for %[save] here and in + my_context_spawn(), so we preserve the value correctly at this point. + */ + "1:\n\t" + /* x19 (aka %[save]) is preserved from my_context_spawn() in this case. */ + "ldr x20, [%[save], #8]\n\t" + "ldp x21, x22, [%[save], #16]\n\t" + "ldp x23, x24, [%[save], #32]\n\t" + "ldp x25, x26, [%[save], #48]\n\t" + "ldp x27, x28, [%[save], #64]\n\t" + "ldp x29, x10, [%[save], #80]\n\t" + "mov sp, x10\n\t" + "ldp d8, d9, [%[save], #96]\n\t" + "ldp d10, d11, [%[save], #112]\n\t" + "ldp d12, d13, [%[save], #128]\n\t" + "ldp d14, d15, [%[save], #144]\n\t" + "mov %w[ret], #0\n\t" + "b 3f\n" + /* Come here when operation is suspended. */ + "2:\n\t" + "mov %w[ret], #1\n" + "3:\n" + : [ret] "=r" (ret) + : [save] "r" (save) + : "x1", "x2", "x3", "x4", "x5", "x6", "x7", + "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x18", "x30", + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", + "memory", "cc" + ); + + return ret; +} + +int +my_context_yield(struct my_context *c) +{ + register const uint64_t *save asm("x19") = &c->save[0]; + __asm__ __volatile__ + ( + "ldp x13, x11, [%[save], #0]\n\t" + "stp x19, x20, [%[save], #0]\n\t" + /* x19 is %[save], delay restoring it until %[save] is no longer needed. */ + "mov x20, x11\n\t" + + "ldp x10, x11, [%[save], #16]\n\t" + "stp x21, x22, [%[save], #16]\n\t" + "mov x21, x10\n\t" + "mov x22, x11\n\t" + + "ldp x10, x11, [%[save], #32]\n\t" + "stp x23, x24, [%[save], #32]\n\t" + "mov x23, x10\n\t" + "mov x24, x11\n\t" + + "ldp x10, x11, [%[save], #48]\n\t" + "stp x25, x26, [%[save], #48]\n\t" + "mov x25, x10\n\t" + "mov x26, x11\n\t" + + "ldp x10, x11, [%[save], #64]\n\t" + "stp x27, x28, [%[save], #64]\n\t" + "mov x27, x10\n\t" + "mov x28, x11\n\t" + + "ldp x10, x11, [%[save], #80]\n\t" + "mov x14, sp\n\t" + "stp x29, x14, [%[save], #80]\n\t" + "mov x29, x10\n\t" + "mov sp, x11\n\t" + + "ldp d0, d1, [%[save], #96]\n\t" + "stp d8, d9, [%[save], #96]\n\t" + "fmov d8, d0\n\t" + "fmov d9, d1\n\t" + + "ldp d0, d1, [%[save], #112]\n\t" + "stp d10, d11, [%[save], #112]\n\t" + "fmov d10, d0\n\t" + "fmov d11, d1\n\t" + + "ldp d0, d1, [%[save], #128]\n\t" + "stp d12, d13, [%[save], #128]\n\t" + "fmov d12, d0\n\t" + "fmov d13, d1\n\t" + + "ldp d0, d1, [%[save], #144]\n\t" + "stp d14, d15, [%[save], #144]\n\t" + "fmov d14, d0\n\t" + "fmov d15, d1\n\t" + + "ldr x11, [%[save], #168]\n\t" + "adr x10, 1f\n\t" + "str x10, [%[save], #168]\n\t" + "mov x19, x13\n\t" + "br x11\n" + + "1:\n" + : + : [save] "r" (save) + : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", + "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x18", "x30", + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", + "memory", "cc" + ); + return 0; +} + +int +my_context_init(struct my_context *c, size_t stack_size) +{ + memset(c, 0, sizeof(*c)); + + if (!(c->stack_bot= malloc(stack_size))) + return -1; /* Out of memory */ + /* + Align stack to 16-byte boundary. + Also put two zero words at the top of the stack. + */ + c->stack_top= (void *) + (( ((intptr)c->stack_bot + stack_size) & ~(intptr)0xf) - 16); + memset(c->stack_top, 0, 16); + +#ifdef HAVE_VALGRIND + c->valgrind_stack_id= + VALGRIND_STACK_REGISTER(c->stack_bot, c->stack_top); +#endif + return 0; +} + +void +my_context_destroy(struct my_context *c) +{ + if (c->stack_bot) + { + free(c->stack_bot); +#ifdef HAVE_VALGRIND + VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); +#endif + } +} + +#endif /* MY_CONTEXT_USE_AARCH64_GCC_ASM */ + + #ifdef MY_CONTEXT_USE_WIN32_FIBERS int my_context_yield(struct my_context *c) diff --git a/libmariadb/ma_time.c b/libmariadb/ma_time.c index 460c32d4..b2d70152 100644 --- a/libmariadb/ma_time.c +++ b/libmariadb/ma_time.c @@ -54,12 +54,9 @@ size_t mariadb_time_to_string(const MYSQL_TIME *tm, char *time_str, size_t len, return 0; break; } - if (digits && (len < length)) - { - char helper[16]; - snprintf(helper, 16, ".%%0%du", digits); - length+= snprintf(time_str + length, len - length, helper, digits); - } + if (digits && len > length + 1) + length+= snprintf(time_str + length, len - length, ".%0*lu", digits, + tm->second_part); return length; } diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 47d5c706..b423b102 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -1465,8 +1465,8 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user, reset_tls_error(mysql); - /* if host contains a semicolon, we need to parse connection string */ - if (host && strchr(host, ';')) + /* if host contains a semicolon or equal sign, we need to parse connection string */ + if (host && (strchr(host, ';') || strchr(host, '='))) { if (parse_connection_string(mysql, NULL, host, strlen(host))) return NULL; @@ -2122,7 +2122,9 @@ my_bool STDCALL mariadb_reconnect(MYSQL *mysql) my_context_install_suspend_resume_hook(ctxt, my_suspend_hook, &hook_data); } - if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, + if (!mysql_real_connect(&tmp_mysql, + mysql->options.host ? NULL : mysql->host, + mysql->user,mysql->passwd, mysql->db, mysql->port, mysql->unix_socket, mysql->client_flag | CLIENT_REMEMBER_OPTIONS) || mysql_set_character_set(&tmp_mysql, mysql->charset->csname)) diff --git a/plugins/auth/CMakeLists.txt b/plugins/auth/CMakeLists.txt index 39fecc2e..a20d38b7 100644 --- a/plugins/auth/CMakeLists.txt +++ b/plugins/auth/CMakeLists.txt @@ -27,14 +27,14 @@ ENDIF() #native password REGISTER_PLUGIN(TARGET mysql_native_password - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS STATIC DEFAULT STATIC SOURCES ${AUTH_DIR}/my_auth.c) #Dialog client authentication plugin REGISTER_PLUGIN(TARGET dialog - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS DYNAMIC STATIC OFF DEFAULT DYNAMIC SOURCES ${AUTH_DIR}/dialog.c @@ -72,7 +72,7 @@ IF(CRYPTO_PLUGIN) ENDIF() REGISTER_PLUGIN(TARGET client_ed25519 - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS DYNAMIC STATIC OFF DEFAULT DYNAMIC SOURCES ${AUTH_DIR}/ed25519.c @@ -89,7 +89,7 @@ IF(CRYPTO_PLUGIN) # SHA256 caching plugin for MySQL 8.0 connection REGISTER_PLUGIN(TARGET caching_sha2_password - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS DYNAMIC STATIC OFF DEFAULT DYNAMIC SOURCES ${AUTH_DIR}/caching_sha2_pw.c @@ -100,7 +100,7 @@ IF(CRYPTO_PLUGIN) MESSAGE1(SHA256_PASSWORD "sha256_password not supported by GnuTLS due to missing OAEP padding") ELSE() REGISTER_PLUGIN(TARGET sha256_password - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS DYNAMIC STATIC OFF DEFAULT DYNAMIC SOURCES ${AUTH_DIR}/sha256_pw.c @@ -140,7 +140,7 @@ ELSE() ENDIF() IF(GSSAPI_SOURCES) REGISTER_PLUGIN(TARGET auth_gssapi_client - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS DYNAMIC STATIC OFF DYNAMIC_AND_STATIC DEFAULT ${AUTH_GSSAPI_DEFAULT_CONFIG} SOURCES ${GSSAPI_SOURCES} @@ -156,7 +156,7 @@ ENDIF() # old_password plugin REGISTER_PLUGIN(TARGET mysql_old_password - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS STATIC DYNAMIC OFF DEFAULT STATIC DISABLED YES @@ -164,7 +164,7 @@ REGISTER_PLUGIN(TARGET mysql_old_password # Cleartext REGISTER_PLUGIN(TARGET mysql_clear_password - TYPE MARIADB_CLIENT_PLUGIN_AUTH + TYPE AUTH CONFIGURATIONS DYNAMIC STATIC OFF DEFAULT DYNAMIC SOURCES ${AUTH_DIR}/mariadb_cleartext.c) diff --git a/plugins/compress/CMakeLists.txt b/plugins/compress/CMakeLists.txt index f6dab85d..ed04a658 100644 --- a/plugins/compress/CMakeLists.txt +++ b/plugins/compress/CMakeLists.txt @@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include) #zlib compression REGISTER_PLUGIN(TARGET zlib - TYPE MARIADB_CLIENT_COMPRESSION_PLUGIN + TYPE COMPRESSION CONFIGURATIONS STATIC DEFAULT STATIC SOURCES ${COMPRESS_PLUGIN_DIR}/c_zlib.c) @@ -15,7 +15,7 @@ REGISTER_PLUGIN(TARGET zlib IF(${ZSTD_FOUND}) INCLUDE_DIRECTORIES(${ZSTD_INCLUDE_DIRS}) REGISTER_PLUGIN(TARGET zstd - TYPE MARIADB_CLIENT_COMPRESSION_PLUGIN + TYPE COMPRESSION CONFIGURATIONS DYNAMIC STATIC OFF DEFAULT DYNAMIC SOURCES ${COMPRESS_PLUGIN_DIR}/c_zstd.c diff --git a/plugins/connection/CMakeLists.txt b/plugins/connection/CMakeLists.txt index 743cf2b0..47665c6d 100644 --- a/plugins/connection/CMakeLists.txt +++ b/plugins/connection/CMakeLists.txt @@ -1,6 +1,6 @@ # Replication REGISTER_PLUGIN(TARGET replication - TYPE MARIADB_CLIENT_PLUGIN_CONNECTION + TYPE CONNECTION CONFIGURATIONS STATIC DYNAMIC OFF DEFAULT OFF SOURCES ${CC_SOURCE_DIR}/plugins/connection/replication.c) diff --git a/plugins/io/CMakeLists.txt b/plugins/io/CMakeLists.txt index 8c304c99..42a09300 100644 --- a/plugins/io/CMakeLists.txt +++ b/plugins/io/CMakeLists.txt @@ -5,7 +5,7 @@ IF (WITH_CURL) ADD_DEFINITIONS(-DHAVE_REMOTEIO=1) #remote io plugin REGISTER_PLUGIN(TARGET remote_io - TYPE MARIADB_CLIENT_PLUGIN_IO + TYPE REMOTEIO CONFIGURATIONS DYNAMIC STATIC OFF DEFAULT DYNAMIC SOURCES ${CC_SOURCE_DIR}/plugins/io/remote_io.c diff --git a/plugins/pvio/CMakeLists.txt b/plugins/pvio/CMakeLists.txt index b74407a6..c59a50f6 100644 --- a/plugins/pvio/CMakeLists.txt +++ b/plugins/pvio/CMakeLists.txt @@ -5,7 +5,7 @@ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include) #native password REGISTER_PLUGIN(TARGET pvio_socket - TYPE MARIADB_CLIENT_PLUGIN_PVIO + TYPE PVIO CONFIGURATIONS STATIC DYNAMIC DEFAULT DEFAULT STATIC SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_socket.c) @@ -13,14 +13,14 @@ REGISTER_PLUGIN(TARGET pvio_socket IF(WIN32) # named pipe REGISTER_PLUGIN(TARGET pvio_npipe - TYPE MARIADB_CLIENT_PLUGIN_PVIO + TYPE PVIO CONFIGURATIONS STATIC DYNAMIC DEFAULT DEFAULT STATIC SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_npipe.c) # shared memory REGISTER_PLUGIN(TARGET pvio_shmem - TYPE MARIADB_CLIENT_PLUGIN_PVIO + TYPE PVIO CONFIGURATIONS STATIC DYNAMIC DEFAULT DEFAULT DYNAMIC SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_shmem.c)