diff --git a/README-WIN.txt b/README-WIN.txt new file mode 100644 index 0000000..c4a9b48 --- /dev/null +++ b/README-WIN.txt @@ -0,0 +1,20 @@ +How to build on Windows + + +You need CMake (download from http://www.cmake.org/) and Visual Studio 2005 or +later (free Express edition should work ok) + +1.Open Visual Studio command line prompt +2.To build with MySQL support, you will need mysql.h header file and client +library libmysqld.lib +One can get them e.g by downloading and unpacking the "zip" distribution of mysql + +- Append directory where libmysql.lib is located to environment variable LIB, e.g + set LIB=%LIB%;G:\mysql-noinstall-6.0.6-alpha-win32\mysql-6.0.6-alpha-win32\lib\opt + +- Append directory where mysql.h is located to environment variable INCLUDE, e.g + set INCLUDE=%INCLUDE%;G:\mysql-noinstall-6.0.6-alpha-win32\mysql-6.0.6-alpha-win32\include +3.In the sysbench directory, execute cmake -G "Visual Studio 9 2008" +4.Open sysbench.sln in Explorer and build Relwithdebinfo target. + Alternatively, from the command line, issue + vcbuild /useenv sysbench.sln "Relwithdebinfo|Win32" diff --git a/sysbench/CMakeLists.txt b/sysbench/CMakeLists.txt new file mode 100644 index 0000000..74714d4 --- /dev/null +++ b/sysbench/CMakeLists.txt @@ -0,0 +1,109 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# 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 + +cmake_minimum_required(VERSION 2.6) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +project(sysbench) +add_executable(sysbench + sysbench.c + sysbench.h + sb_timer.c + sb_timer.h + sb_options.c + sb_options.h + sb_logger.c + sb_logger.h + sb_list.h + db_driver.h + db_driver.c + sb_win.c + sb_win.h +) +if(MSVC) + # Link C runtime statically to avoid hassle with CRT dll redistribution. + STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}) + STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO}) + STRING(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) + STRING(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG_INIT ${CMAKE_C_FLAGS_DEBUG_INIT}) + + STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) + STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) + STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG_INIT ${CMAKE_CXX_FLAGS_DEBUG_INIT}) + + #Silence "deprecated API" warnings. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996") + + #Look for mysql.h in INCLUDE paths + find_path(MYSQLH_PATH mysql.h ENV INCLUDE) + message("mysql.h directory = ${MYSQLH_PATH}") + + #Looks for libmysql.lib in LIB paths + find_file(LIBMYSQL_LIB libmysql.lib ENV LIB) + message("libmysql.lib = ${LIBMYSQL_LIB}") + + #Look for libmysql.dll + find_file(LIBMYSQL_DLL libmysql.dll ENV LIB ENV PATH) + message("libmysql.dll = ${LIBMYSQL_DLL}") + + #If mysql header file and client library are found, build with mysql + if(MYSQLH_PATH AND LIBMYSQL_LIB) + set(USE_MYSQL 1) + + #If libmysql.dll found, copy it next to sysbench.exe in the postbuild step + if(LIBMYSQL_DLL) + file(TO_NATIVE_PATH ${LIBMYSQL_DLL} LIBMYSQL_DLL) + ADD_CUSTOM_COMMAND( + TARGET sysbench + POST_BUILD + COMMAND copy /y ${LIBMYSQL_DLL} $(OutDir) + ) + endif(LIBMYSQL_DLL) + endif(MYSQLH_PATH AND LIBMYSQL_LIB) +endif(MSVC) + + +if(USE_MYSQL) + message("using mysql driver") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_MYSQL") + include_directories(${MYSQLH_PATH}) + add_subdirectory(drivers/mysql) + target_link_libraries (sysbench sbmysql) + target_link_libraries (sysbench ${LIBMYSQL_LIB}) +endif(USE_MYSQL) + +add_subdirectory(tests/cpu) +target_link_libraries (sysbench sbcpu) + +add_subdirectory(tests/fileio) +target_link_libraries (sysbench sbfileio) + +add_subdirectory(tests/mutex) +target_link_libraries (sysbench sbmutex) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_LUA -DUSE_LUA") +add_subdirectory(scripting) +target_link_libraries(sysbench sbscript lua) + + +add_subdirectory(tests/threads) +target_link_libraries (sysbench sbthreads) + +add_subdirectory(tests/memory) +target_link_libraries (sysbench sbmemory) diff --git a/sysbench/db_driver.c b/sysbench/db_driver.c index f3ced0c..5c04589 100644 --- a/sysbench/db_driver.c +++ b/sysbench/db_driver.c @@ -18,7 +18,9 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif - +#ifdef _WIN32 +#include "sb_win.h" +#endif #ifdef STDC_HEADERS # include #endif @@ -681,7 +683,7 @@ void db_free_row(db_row_t *row) int db_bulk_insert_init(db_conn_t *con, const char *query) { drv_caps_t driver_caps; - unsigned int query_len; + size_t query_len; if (con->driver == NULL) return 1; diff --git a/sysbench/drivers/mysql/CMakeLists.txt b/sysbench/drivers/mysql/CMakeLists.txt new file mode 100644 index 0000000..43f2ab3 --- /dev/null +++ b/sysbench/drivers/mysql/CMakeLists.txt @@ -0,0 +1,2 @@ +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +ADD_LIBRARY(sbmysql drv_mysql.c) diff --git a/sysbench/drivers/mysql/drv_mysql.c b/sysbench/drivers/mysql/drv_mysql.c index 70a06c0..eeeb1b9 100644 --- a/sysbench/drivers/mysql/drv_mysql.c +++ b/sysbench/drivers/mysql/drv_mysql.c @@ -21,6 +21,9 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef _WIN32 +#include +#endif #ifdef HAVE_STRING_H # include @@ -117,11 +120,11 @@ db_mysql_bind_map_t db_mysql_bind_map[] = static drv_caps_t mysql_drv_caps = { - .multi_rows_insert = 1, - .prepared_statements = 0, - .auto_increment = 1, - .serial = 0, - .unsigned_int = 1, + 1, + 0, + 1, + 0, + 1, }; @@ -157,10 +160,9 @@ static int mysql_drv_done(void); static db_driver_t mysql_driver = { - .sname = "mysql", - .lname = "MySQL driver", - .args = mysql_drv_args, - .ops = + "mysql", + "MySQL driver", + mysql_drv_args, { mysql_drv_init, mysql_drv_describe, @@ -179,7 +181,7 @@ static db_driver_t mysql_driver = mysql_drv_store_results, mysql_drv_done }, - .listitem = {NULL, NULL} + {0,0} }; @@ -232,6 +234,8 @@ int mysql_drv_init(void) use_ps = 1; #endif + mysql_library_init(-1, NULL, NULL); + return 0; } @@ -809,6 +813,8 @@ int mysql_drv_close(db_stmt_t *stmt) /* Uninitialize driver */ int mysql_drv_done(void) { + mysql_library_end(); + return 0; } diff --git a/sysbench/sb_list.h b/sysbench/sb_list.h index 00d0926..bc507e2 100644 --- a/sysbench/sb_list.h +++ b/sysbench/sb_list.h @@ -19,14 +19,16 @@ #define SB_LIST_H -typedef struct sb_list_item sb_list_t; -typedef struct sb_list_item sb_list_item_t; - -struct sb_list_item +typedef struct sb_list_item_t { - sb_list_item_t *next_p; - sb_list_item_t *prev_p; -}; +// char c; + struct sb_list_item_t *next_p; + struct sb_list_item_t *prev_p; +} +sb_list_item_t; + +typedef sb_list_item_t sb_list_item; +typedef sb_list_item_t sb_list_t ; #ifndef offsetof # define offsetof(type, member) ((size_t) &((type *)0)->member) diff --git a/sysbench/sb_logger.c b/sysbench/sb_logger.c index 06a96aa..222ec75 100644 --- a/sysbench/sb_logger.c +++ b/sysbench/sb_logger.c @@ -18,6 +18,9 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef _WIN32 +#include "sb_win.h" +#endif #ifdef STDC_HEADERS # include @@ -107,13 +110,13 @@ static sb_arg_t text_handler_args[] = static log_handler_t text_handler = { - .ops = { - .init = &text_handler_init, - .process = &text_handler_process, - .done = NULL, + { + &text_handler_init, + &text_handler_process, + NULL, }, - .args = text_handler_args, - .listitem = {NULL, NULL} + text_handler_args, + {0,0} }; /* Operation start/stop messages handler */ @@ -131,13 +134,13 @@ static sb_arg_t oper_handler_args[] = }; static log_handler_t oper_handler = { - .ops = { - .init = oper_handler_init, - .process = &oper_handler_process, - .done = oper_handler_done, + { + oper_handler_init, + &oper_handler_process, + oper_handler_done, }, - .args = oper_handler_args, - .listitem = {NULL, NULL} + oper_handler_args, + {0,0} }; @@ -310,19 +313,30 @@ void log_errno(log_msg_priority_t priority, const char *fmt, ...) int n; int old_errno; char *tmp; - + +#ifdef _WIN32 + LPVOID lpMsgBuf; + old_errno = GetLastError(); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, old_errno, + 0, (LPTSTR)&lpMsgBuf, 0, NULL); + tmp = (char *)lpMsgBuf; +#else old_errno = errno; #ifdef HAVE_STRERROR_R #ifdef STRERROR_R_CHAR_P - tmp = strerror_r(old_errno, errbuf, ERROR_BUFFER_SIZE); + tmp = strerror_r(old_errno, errbuf, sizeof(errbuf)); #else - strerror_r(old_errno, errbuf, ERROR_BUFFER_SIZE); + strerror_r(old_errno, errbuf, sizeof(errbuf)); tmp = errbuf; #endif /* STRERROR_R_CHAR_P */ #else /* !HAVE_STRERROR_P */ strncpy(errbuf, strerror(old_errno), sizeof(errbuf)); tmp = errbuf; -#endif +#endif /* HAVE_STRERROR_P */ +#endif /* WIN32 */ va_start(ap, fmt); n = vsnprintf(buf, TEXT_BUFFER_SIZE, fmt, ap); @@ -331,6 +345,10 @@ void log_errno(log_msg_priority_t priority, const char *fmt, ...) return; snprintf(buf + n, TEXT_BUFFER_SIZE - n, " errno = %d (%s)", old_errno, tmp); + +#ifdef _WIN32 + LocalFree(lpMsgBuf); +#endif log_text(priority, "%s", buf); } @@ -406,7 +424,8 @@ int text_handler_process(log_msg_t *msg) } printf("%s%s", prefix, text_msg->text); - + fflush(stdout); + return 0; } diff --git a/sysbench/sb_options.c b/sysbench/sb_options.c index bcdaa49..bff89f0 100644 --- a/sysbench/sb_options.c +++ b/sysbench/sb_options.c @@ -18,6 +18,9 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef _WIN32 +# include "sb_win.h" +#endif #ifdef STDC_HEADERS # include diff --git a/sysbench/sb_options.h b/sysbench/sb_options.h index 0ca6f7f..fcc167c 100644 --- a/sysbench/sb_options.h +++ b/sysbench/sb_options.h @@ -23,9 +23,7 @@ #include "config.h" #endif -#ifdef STDC_HEADERS #include -#endif #include "sb_list.h" diff --git a/sysbench/sb_timer.h b/sysbench/sb_timer.h index eec3e22..6977500 100644 --- a/sysbench/sb_timer.h +++ b/sysbench/sb_timer.h @@ -22,6 +22,10 @@ # include "config.h" #endif +#ifdef _WIN32 +#include "sb_win.h" +#endif + #ifdef TIME_WITH_SYS_TIME # include # include diff --git a/sysbench/sb_win.c b/sysbench/sb_win.c new file mode 100644 index 0000000..3609457 --- /dev/null +++ b/sysbench/sb_win.c @@ -0,0 +1,244 @@ +/* Copyright (C) 2008 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 +*/ + +/* + This file contains Windows port of Posix functionality used in sysbench + (partial implementation of pthreads, gettimeofday() and random() +*/ + +#define _CRT_RAND_S /* for rand_s */ +#include +#include +#include +#include "sb_win.h" + +int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) +{ + cond->waiting= 0; + InitializeCriticalSection(&cond->lock_waiting); + + cond->events[SIGNAL]= CreateEvent(NULL, FALSE, FALSE, NULL); + cond->events[BROADCAST]= CreateEvent(NULL, TRUE, FALSE, NULL); + cond->broadcast_block_event= CreateEvent(NULL, TRUE, TRUE, NULL); + + if( cond->events[SIGNAL] == NULL || + cond->events[BROADCAST] == NULL || + cond->broadcast_block_event == NULL ) + return ENOMEM; + return 0; +} + +int pthread_cond_destroy(pthread_cond_t *cond) +{ + DeleteCriticalSection(&cond->lock_waiting); + + if (CloseHandle(cond->events[SIGNAL]) == 0 || + CloseHandle(cond->events[BROADCAST]) == 0 || + CloseHandle(cond->broadcast_block_event) == 0) + return EINVAL; + return 0; +} + + +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, +struct timespec *abstime) +{ + int result; + long timeout; + union { + FILETIME ft; + long long i64; + }now; + + if( abstime != NULL ) + { + long long stoptime_nanos = (abstime->tv_sec*1000000000 + abstime->tv_nsec); + long long now_nanos; + long long timeout_nanos; + + GetSystemTimeAsFileTime(&now.ft); + now_nanos = now.i64 *100; + timeout_nanos = stoptime_nanos - now_nanos; + timeout = (long)(timeout_nanos /1000000); + } + else + { + /* No time specified; don't expire */ + timeout= INFINITE; + } + + /* + Block access if previous broadcast hasn't finished. + This is just for safety and should normally not + affect the total time spent in this function. + */ + WaitForSingleObject(cond->broadcast_block_event, INFINITE); + + EnterCriticalSection(&cond->lock_waiting); + cond->waiting++; + LeaveCriticalSection(&cond->lock_waiting); + + LeaveCriticalSection(mutex); + + result= WaitForMultipleObjects(2, cond->events, FALSE, timeout); + + EnterCriticalSection(&cond->lock_waiting); + cond->waiting--; + + if (cond->waiting == 0 && result == (WAIT_OBJECT_0+BROADCAST)) + { + /* + We're the last waiter to be notified or to stop waiting, so + reset the manual event. + */ + /* Close broadcast gate */ + ResetEvent(cond->events[BROADCAST]); + /* Open block gate */ + SetEvent(cond->broadcast_block_event); + } + LeaveCriticalSection(&cond->lock_waiting); + + EnterCriticalSection(mutex); + + return result == WAIT_TIMEOUT ? ETIMEDOUT : 0; +} + +int pthread_cond_signal(pthread_cond_t *cond) +{ + EnterCriticalSection(&cond->lock_waiting); + + if(cond->waiting > 0) + SetEvent(cond->events[SIGNAL]); + + LeaveCriticalSection(&cond->lock_waiting); + + return 0; +} + + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + EnterCriticalSection(&cond->lock_waiting); + /* + The mutex protect us from broadcasting if + there isn't any thread waiting to open the + block gate after this call has closed it. + */ + if(cond->waiting > 0) + { + /* Close block gate */ + ResetEvent(cond->broadcast_block_event); + /* Open broadcast gate */ + SetEvent(cond->events[BROADCAST]); + } + + LeaveCriticalSection(&cond->lock_waiting); + + return 0; +} + +int pthread_attr_init(pthread_attr_t *attr) +{ + attr->stacksize = 0; + return 0; +} + +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + InitializeCriticalSection(mutex); + return 0; +} +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + EnterCriticalSection(mutex); + return 0; +} +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + LeaveCriticalSection(mutex); + return 0; +} +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + DeleteCriticalSection(mutex); + return 0; +} + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg) +{ + DWORD tid; + *thread = CreateThread(NULL, attr->stacksize, + (LPTHREAD_START_ROUTINE) start_routine, arg, + STACK_SIZE_PARAM_IS_A_RESERVATION, &tid); + if (*thread != NULL) + return 0; + return -1; +} + +/* Minimal size of thread stack on Windows*/ +#define PTHREAD_STACK_MIN 65536 + +int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize) +{ + if(stacksize) + attr->stacksize = max(stacksize, PTHREAD_STACK_MIN); + return 0; +} + +int pthread_join(pthread_t pthread, void **value_ptr) +{ + if (WaitForSingleObject(pthread, INFINITE) != WAIT_OBJECT_0) + return -1; + if (value_ptr) + *value_ptr = 0; + return 0; + +} + +#include +int gettimeofday(struct timeval * tp, void * tzp) +{ + static long long qpf = 0, startup_time = 0; + long long qpc; + if(qpf == 0) + { + QueryPerformanceFrequency((LARGE_INTEGER *)&qpf); + } + if(startup_time == 0) + { + QueryPerformanceCounter((LARGE_INTEGER *)&qpc); + startup_time = time(NULL) - (qpc/qpf); + } + QueryPerformanceCounter((LARGE_INTEGER *)&qpc); + tp->tv_sec = (long)(startup_time + qpc/qpf); + tp->tv_usec = (long)((qpc%qpf)*1000000/qpf); + return 0; +} + +int random() +{ + int ret; + rand_s(&ret); + return ret; +} diff --git a/sysbench/sb_win.h b/sysbench/sb_win.h new file mode 100644 index 0000000..45a16bd --- /dev/null +++ b/sysbench/sb_win.h @@ -0,0 +1,103 @@ +#ifndef SB_WINPORT_H +#define SB_WINPORT_H +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include + +#if (_MSC_VER < 1400) +#error "need Visual Studio 2005 or higher" +#endif + +#ifndef PACKAGE +#define PACKAGE "sysbench" +#endif +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "0.5" +#endif + +#define snprintf(buffer, count, format,...) \ + _snprintf_s(buffer,count, _TRUNCATE,format, __VA_ARGS__) +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define srandom(seed) srand(seed) +typedef intptr_t ssize_t; + +#ifdef _WIN64 +#define SIZEOF_SIZE_T 8 +#else +#define SIZEOF_SIZE_T 4 +#endif + + +struct timespec +{ + time_t tv_sec; + long long tv_nsec; +}; +typedef HANDLE pthread_t; +typedef CRITICAL_SECTION pthread_mutex_t; + +#define SIGNAL 0 +#define BROADCAST 1 +#define MAX_EVENTS 2 +typedef struct _pthread_cond_t +{ + int waiting; + CRITICAL_SECTION lock_waiting; + + HANDLE events[MAX_EVENTS]; + HANDLE broadcast_block_event; +}pthread_cond_t; + + +typedef struct +{ + char unused; +}pthread_condattr_t; + +typedef struct +{ + DWORD stacksize; +}pthread_attr_t; + +typedef struct +{ + char unused; +}pthread_mutexattr_t; + +extern int pthread_attr_init(pthread_attr_t *attr); +extern int pthread_cond_destroy(pthread_cond_t *cond); +extern int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec *abstime); +extern int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int pthread_cond_signal(pthread_cond_t *cond); +extern int pthread_mutex_lock(pthread_mutex_t *mutex); +extern int pthread_mutex_unlock(pthread_mutex_t *mutex); +extern int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); +extern int pthread_mutex_destroy(pthread_mutex_t *mutex); +extern int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); +extern int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize); +extern int pthread_join(pthread_t thread, void **value_ptr); +extern int gettimeofday(struct timeval * tp, void * tzp); +extern int random(); + +#define ETIMEDOUT 2204 + +static __inline int usleep(int micros) +{ + Sleep(micros/1000); + return 0; +} + + + +#define gmtime_r(a,b) gmtime_s(b,a) + +#endif + diff --git a/sysbench/scripting/CMakeLists.txt b/sysbench/scripting/CMakeLists.txt new file mode 100644 index 0000000..7346d5c --- /dev/null +++ b/sysbench/scripting/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +include_directories(lua/src ..) +add_subdirectory(lua/src) +add_library(sbscript sb_script.c sb_script.h script_lua.c script_lua.h) + diff --git a/sysbench/scripting/lua/src/CMakeLists.txt b/sysbench/scripting/lua/src/CMakeLists.txt new file mode 100644 index 0000000..2fed0ca --- /dev/null +++ b/sysbench/scripting/lua/src/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# 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 + +if(MSVC) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLUA_WIN") +endif(MSVC) +add_library(lua lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c + lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c + lundump.c lvm.c lzio.c + lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c ltablib.c + lstrlib.c loadlib.c linit.c + lapi.h lcode.h ldo.h lgc.h llimits.h lobject.h lparser.h lstring.h ltm.h + luaconf.h lundump.h lzio.h lauxlib.h ldebug.h lfunc.h llex.h lmem.h lopcodes.h + lstate.h ltable.h lua.h lualib.h lvm.h) \ No newline at end of file diff --git a/sysbench/scripting/lua/src/luaconf.h b/sysbench/scripting/lua/src/luaconf.h index 68326f0..d09d3d1 100644 --- a/sysbench/scripting/lua/src/luaconf.h +++ b/sysbench/scripting/lua/src/luaconf.h @@ -32,7 +32,9 @@ #define LUA_ANSI #endif +#ifndef _WIN32 #define LUA_USE_DLOPEN +#endif /* @@ LUA_PATH and LUA_CPATH are the names of the environment variables that diff --git a/sysbench/scripting/script_lua.c b/sysbench/scripting/script_lua.c index a78996c..5db3264 100644 --- a/sysbench/scripting/script_lua.c +++ b/sysbench/scripting/script_lua.c @@ -94,10 +94,16 @@ static int sb_lua_op_thread_done(int); static void sb_lua_op_print_stats(void); static sb_operations_t lua_ops = { - .init = &sb_lua_init, - .get_request = &sb_lua_get_request, - .execute_request = &sb_lua_op_execute_request, - .done = &sb_lua_done + &sb_lua_init, + NULL, + NULL, + NULL, + &sb_lua_get_request, + &sb_lua_op_execute_request, + NULL, + NULL, + NULL, + &sb_lua_done }; /* Main (global) interpreter state */ @@ -240,7 +246,7 @@ int sb_lua_op_execute_request(sb_request_t *sb_req, int thread_id) { log_msg_t msg; log_msg_oper_t op_msg; - uint restart; + unsigned int restart; lua_State *L = states[thread_id]; (void)sb_req; /* unused */ diff --git a/sysbench/sysbench.c b/sysbench/sysbench.c index d4492cf..03abf2a 100644 --- a/sysbench/sysbench.c +++ b/sysbench/sysbench.c @@ -442,7 +442,9 @@ int run_test(sb_test_t *test) /* initialize attr */ pthread_attr_init(&thread_attr); +#ifdef PTHREAD_SCOPE_SYSTEM pthread_attr_setscope(&thread_attr,PTHREAD_SCOPE_SYSTEM); +#endif pthread_attr_setstacksize(&thread_attr, thread_stack_size); #ifdef HAVE_THR_SETCONCURRENCY @@ -468,7 +470,7 @@ int run_test(sb_test_t *test) } pthread_mutex_unlock(&thread_start_mutex); - log_text(LOG_INFO, "Threads started!"); + log_text(LOG_NOTICE, "Threads started!\n"); for(i = 0; i < sb_globals.num_threads; i++) { if(pthread_join(threads[i].thread, NULL)) @@ -545,7 +547,7 @@ int init(void) return 1; } - thread_stack_size = sb_get_value_int("thread-stack-size"); + thread_stack_size = sb_get_value_size("thread-stack-size"); if (thread_stack_size <= 0) { log_text(LOG_FATAL, "Invalid value for thread-stack-size: %d.\n", thread_stack_size); diff --git a/sysbench/tests/CMakeLists.txt b/sysbench/tests/CMakeLists.txt new file mode 100644 index 0000000..837fb1e --- /dev/null +++ b/sysbench/tests/CMakeLists.txt @@ -0,0 +1,2 @@ +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +ADD_LIBRARY(sbtests sb_cpu.) diff --git a/sysbench/tests/cpu/CMakeLists.txt b/sysbench/tests/cpu/CMakeLists.txt new file mode 100644 index 0000000..19ede0a --- /dev/null +++ b/sysbench/tests/cpu/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/tests) +ADD_LIBRARY(sbcpu sb_cpu.c) diff --git a/sysbench/tests/cpu/sb_cpu.c b/sysbench/tests/cpu/sb_cpu.c index ea5b1fb..f94c0f2 100644 --- a/sysbench/tests/cpu/sb_cpu.c +++ b/sysbench/tests/cpu/sb_cpu.c @@ -18,6 +18,9 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef _WIN32 +# include "sb_win.h" +#endif #ifdef HAVE_MATH_H # include @@ -42,27 +45,24 @@ static int cpu_done(void); static sb_test_t cpu_test = { - .sname = "cpu", - .lname = "CPU performance test", - .ops = { - .init = cpu_init, - .prepare = NULL, - .thread_init = NULL, - .thread_done = NULL, - .cleanup = NULL, - .print_mode = cpu_print_mode, - .get_request = cpu_get_request, - .execute_request = cpu_execute_request, - .print_stats = cpu_print_stats, - .done = cpu_done +"cpu", + "CPU performance test", + { + cpu_init, + NULL, + NULL, + cpu_print_mode, + cpu_get_request, + cpu_execute_request, + cpu_print_stats, + NULL, + NULL, + cpu_done }, - .cmds = { - .prepare = NULL, - .help = NULL, - .run = NULL, - .cleanup = NULL + { + NULL,NULL,NULL,NULL }, - .args = cpu_args, + cpu_args, {NULL, NULL} }; diff --git a/sysbench/tests/fileio/CMakeLists.txt b/sysbench/tests/fileio/CMakeLists.txt new file mode 100644 index 0000000..f5270d4 --- /dev/null +++ b/sysbench/tests/fileio/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/tests) +ADD_LIBRARY(sbfileio sb_fileio.c crc32.c) diff --git a/sysbench/tests/fileio/crc32.c b/sysbench/tests/fileio/crc32.c index b70752e..a746a92 100644 --- a/sysbench/tests/fileio/crc32.c +++ b/sysbench/tests/fileio/crc32.c @@ -26,7 +26,11 @@ #define OF(args) args #include "crc32.h" +#ifndef _WIN32 #define ptrdiff_t long +#else +#include +#endif /* Find a four-byte integer type for crc32_little() and crc32_big(). */ #ifndef NOBYFOUR diff --git a/sysbench/tests/fileio/sb_fileio.c b/sysbench/tests/fileio/sb_fileio.c index c611e60..9dbcded 100644 --- a/sysbench/tests/fileio/sb_fileio.c +++ b/sysbench/tests/fileio/sb_fileio.c @@ -19,6 +19,10 @@ # include "config.h" #endif +#ifdef _WIN32 +#include "sb_win.h" +#endif + #ifdef STDC_HEADERS # include /* Required for memalign to be declared on Solaris */ @@ -45,6 +49,14 @@ #ifdef HAVE_SYS_MMAN_H # include #endif +#ifdef _WIN32 +# include +# include +# include +# define S_IRUSR _S_IREAD +# define S_IWUSR _S_IWRITE +# define HAVE_MMAP +#endif #include "sysbench.h" #include "crc32.h" @@ -53,6 +65,24 @@ #define FILE_CHECKSUM_LENGTH sizeof(int) #define FILE_OFFSET_LENGTH sizeof(long) +#ifdef _WIN32 +typedef HANDLE FILE_DESCRIPTOR; +#define VALID_FILE(fd) (fd != INVALID_HANDLE_VALUE) +#define FD_FMT "%p" +#define MAP_SHARED 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define MAP_FAILED NULL + +void *mmap(void *addr, size_t len, int prot, int flags, + FILE_DESCRIPTOR fd, long long off); +int munmap(void *addr, size_t size); +#else +typedef int FILE_DESCRIPTOR; +#define VALID_FILE(fd) (fd >= 0) +#define FD_FMT "%d" +#endif + /* Supported operations in request */ typedef enum { @@ -102,8 +132,8 @@ static sb_aio_context_t *aio_ctxts; /* Test options */ static unsigned int num_files; -static off_t total_size; -static off_t file_size; +static long long total_size; +static long long file_size; static int file_block_size; static int file_extra_flags; static int file_fsync_freq; @@ -112,7 +142,7 @@ static int file_fsync_end; static file_fsync_mode_t file_fsync_mode; static float file_rw_ratio; static int file_merged_requests; -static off_t file_max_request_size; +static long long file_max_request_size; static file_io_mode_t file_io_mode; #ifdef HAVE_LIBAIO static unsigned int file_async_backlog; @@ -137,12 +167,12 @@ static unsigned long long bytes_written; #ifdef HAVE_MMAP /* Array of file mappings */ -static void **mmaps; +static void **mmaps; static unsigned long file_page_mask; #endif /* Array of file descriptors */ -static int *files; +static FILE_DESCRIPTOR *files; /* Buffer for all I/O operations */ static void *buffer; @@ -196,33 +226,31 @@ static void file_print_stats(void); static sb_test_t fileio_test = { - .sname = "fileio", - .lname = "File I/O test", - .ops = + "fileio", + "File I/O test", { - .init = file_init, - .thread_init = NULL, + file_init, + file_prepare, + NULL, + file_print_mode, + file_get_request, + file_execute_request, + file_print_stats, #ifdef HAVE_LIBAIO - .thread_done = file_thread_done, + file_thread_done, #else - .thread_done = NULL, + NULL, #endif - .prepare = file_prepare, - .cleanup = NULL, - .print_mode = file_print_mode, - .get_request = file_get_request, - .execute_request = file_execute_request, - .print_stats = file_print_stats, - .done = file_done + file_done }, - .cmds = { - .prepare = file_cmd_prepare, - .help = NULL, - .run = NULL, - .cleanup = file_cmd_cleanup + { + NULL, + file_cmd_prepare, + NULL, + file_cmd_cleanup }, - .args = fileio_args, - {NULL, NULL} + fileio_args, + {0,0} }; @@ -235,13 +263,13 @@ static sb_request_t file_get_rnd_request(void); static void check_seq_req(sb_file_request_t *, sb_file_request_t *); static const char *get_io_mode_str(file_io_mode_t mode); static const char *get_test_mode_str(file_test_mode_t mode); -static void file_fill_buffer(unsigned char *, unsigned int, unsigned long); -static int file_validate_buffer(unsigned char *, unsigned int, unsigned long); +static void file_fill_buffer(unsigned char *, unsigned int, size_t); +static int file_validate_buffer(unsigned char *, unsigned int, size_t); /* File operation wrappers */ static int file_fsync(unsigned int, int); -static ssize_t file_pread(unsigned int, void *, ssize_t, off_t, int); -static ssize_t file_pwrite(unsigned int, void *, ssize_t, off_t, int); +static ssize_t file_pread(unsigned int, void *, ssize_t, long long, int); +static ssize_t file_pwrite(unsigned int, void *, ssize_t, long long, int); #ifdef HAVE_LIBAIO static int file_async_init(void); static int file_async_done(void); @@ -255,7 +283,9 @@ static int file_mmap_done(void); /* Portability wrappers */ static unsigned long sb_getpagesize(void); +static unsigned long sb_get_allocation_granularity(void); static void *sb_memalign(size_t size); +static void sb_free_memaligned(void *buf); int register_test_fileio(sb_list_t *tests) { @@ -270,7 +300,7 @@ int file_init(void) if (parse_arguments()) return 1; - files = (int *)malloc(num_files * sizeof(int)); + files = (FILE_DESCRIPTOR *)malloc(num_files * sizeof(FILE_DESCRIPTOR)); if (files == NULL) { log_text(LOG_FATAL, "Memory allocation failure."); @@ -301,10 +331,15 @@ int file_prepare(void) unlink(file_name); log_text(LOG_DEBUG, "Opening file: %s",file_name); - +#ifndef _WIN32 files[i] = open(file_name, O_CREAT | O_RDWR | file_extra_flags, S_IRUSR | S_IWUSR); - if (files[i] < 0) +#else + files[i] = CreateFile(file_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, + OPEN_ALWAYS, file_extra_flags? file_extra_flags : FILE_ATTRIBUTE_NORMAL, + NULL); +#endif + if (!VALID_FILE(files[i])) { log_errno(LOG_FATAL, "Cannot open file"); return 1; @@ -327,7 +362,11 @@ int file_done(void) unsigned int i; for (i = 0; i < num_files; i++) +#ifndef _WIN32 close(files[i]); +#else + CloseHandle(files[i]); +#endif #ifdef HAVE_LIBAIO if (file_async_done()) @@ -340,7 +379,7 @@ int file_done(void) #endif if (buffer != NULL) - free(buffer); + sb_free_memaligned(buffer); pthread_mutex_destroy(&fsync_mutex); @@ -378,7 +417,7 @@ sb_request_t file_get_seq_request(void) if (position + file_max_request_size <= file_size) file_req->size = file_max_request_size; else - file_req->size = file_size - position; + file_req->size = file_size - position; file_req->file_id = current_file; file_req->pos = position; } @@ -445,7 +484,7 @@ sb_request_t file_get_rnd_request(void) { sb_request_t sb_req; sb_file_request_t *file_req = &sb_req.u.file_request; - unsigned int rand; + unsigned int randnum; unsigned long long tmppos; int real_mode = test_mode; int mode = test_mode; @@ -515,16 +554,16 @@ sb_request_t file_get_rnd_request(void) } } - rand=sb_rnd(); + randnum=sb_rnd(); if (mode==MODE_RND_WRITE) /* mode shall be WRITE or RND_WRITE only */ file_req->operation = FILE_OP_TYPE_WRITE; else file_req->operation = FILE_OP_TYPE_READ; - tmppos = (long long)((double)rand / (double)SB_MAX_RND * (double)(total_size)); + tmppos = (long long)((double)randnum / (double)SB_MAX_RND * (double)(total_size)); tmppos = tmppos - (tmppos % (long long)file_block_size); file_req->file_id = (int)(tmppos / (long long)file_size); - file_req->pos = (off_t)(tmppos % (long long)file_size); + file_req->pos = (long long)(tmppos % (long long)file_size); file_req->size = file_block_size; req_performed++; @@ -537,12 +576,11 @@ sb_request_t file_get_rnd_request(void) int file_execute_request(sb_request_t *sb_req, int thread_id) { - int fd; + FILE_DESCRIPTOR fd; sb_file_request_t *file_req = &sb_req->u.file_request; log_msg_t msg; log_msg_oper_t op_msg; - - fd = files[file_req->file_id]; + if (sb_globals.debug) { log_text(LOG_DEBUG, @@ -565,7 +603,7 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) log_text(LOG_FATAL, "Too large position discovered in request!"); return 1; } - + fd = files[file_req->file_id]; /* Prepare log message */ msg.type = LOG_MSG_TYPE_OPER; msg.data = &op_msg; @@ -585,7 +623,7 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) thread_id) != (ssize_t)file_req->size) { - log_errno(LOG_FATAL, "Failed to write file! file: %d pos: %lld", + log_errno(LOG_FATAL, "Failed to write file! file: " FD_FMT " pos: %lld", fd, (long long)file_req->pos); return 1; } @@ -595,7 +633,7 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) { if (file_fsync(file_req->file_id, thread_id)) { - log_errno(LOG_FATAL, "Failed to fsync file! file: %d", fd); + log_errno(LOG_FATAL, "Failed to fsync file! file: " FD_FMT, fd); return 1; } } @@ -617,7 +655,7 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) thread_id) != (ssize_t)file_req->size) { - log_errno(LOG_FATAL, "Failed to read file! file: %d pos: %lld", + log_errno(LOG_FATAL, "Failed to read file! file: " FD_FMT " pos: %lld", fd, (long long)file_req->pos); return 1; } @@ -628,8 +666,8 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) file_validate_buffer(buffer, file_req->size, file_req->pos)) { log_text(LOG_FATAL, - "Validation failed on file %d, block offset 0x%x, exiting...", - file_req->file_id, file_req->pos); + "Validation failed on file " FD_FMT ", block offset 0x%x, exiting...", + file_req->file_id, file_req->pos); return 1; } @@ -647,7 +685,7 @@ int file_execute_request(sb_request_t *sb_req, int thread_id) break; if(file_fsync(file_req->file_id, thread_id)) { - log_errno(LOG_FATAL, "Failed to fsync file! file: %d", fd); + log_errno(LOG_FATAL, "Failed to fsync file! file: " FD_FMT, fd); return 1; } @@ -803,7 +841,7 @@ int create_files(void) unsigned int i; int fd; char file_name[512]; - off_t offset; + long long offset; log_text(LOG_INFO, "%d files, %ldKb each, %ldMb total", num_files, (long)(file_size / 1024), @@ -812,7 +850,6 @@ int create_files(void) for (i=0; i < num_files; i++) { snprintf(file_name, sizeof(file_name), "test_file.%d",i); unlink(file_name); - fd = open(file_name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); if (fd < 0) { @@ -833,7 +870,11 @@ int create_files(void) } /* fsync files to prevent cache flush from affecting test results */ +#ifndef _WIN32 fsync(fd); +#else + _commit(fd); +#endif close(fd); } return 0; @@ -1111,18 +1152,37 @@ int file_mmap_prepare(void) if (file_io_mode != FILE_IO_MODE_MMAP) return 0; - file_page_mask = ~(sb_getpagesize() - 1); + file_page_mask = ~(sb_get_allocation_granularity() - 1); /* Extend file sizes for sequential write test */ if (test_mode == MODE_WRITE) for (i = 0; i < num_files; i++) + { +#ifdef _WIN32 + HANDLE hFile = files[i]; + LARGE_INTEGER offset; + offset.QuadPart = file_size; + if (!SetFilePointerEx(hFile ,offset ,NULL, FILE_BEGIN)) + { + log_errno(LOG_FATAL, "SetFilePointerEx() failed on file %d", i); + return 1; + } + if (!SetEndOfFile(hFile)) + { + log_errno(LOG_FATAL, "SetEndOfFile() failed on file %d", i); + return 1; + } + offset.QuadPart = 0; + SetFilePointerEx(hFile ,offset ,NULL, FILE_BEGIN); +#else if (ftruncate(files[i], file_size)) { log_errno(LOG_FATAL, "ftruncate() failed on file %d", i); return 1; } - - +#endif + } + #if SIZEOF_SIZE_T > 4 mmaps = (void **)malloc(num_files * sizeof(void *)); for (i = 0; i < num_files; i++) @@ -1168,7 +1228,7 @@ int file_mmap_done(void) int file_fsync(unsigned int file_id, int thread_id) { - int fd = files[file_id]; + FILE_DESCRIPTOR fd = files[file_id]; #ifdef HAVE_LIBAIO struct iocb iocb; #else @@ -1188,7 +1248,11 @@ int file_fsync(unsigned int file_id, int thread_id) ) { if (file_fsync_mode == FSYNC_ALL) +#ifndef _WIN32 return fsync(fd); +#else + return !FlushFileBuffers(fd); +#endif #ifdef HAVE_FDATASYNC return fdatasync(fd); @@ -1214,22 +1278,128 @@ int file_fsync(unsigned int file_id, int thread_id) /* Use msync on file on 64-bit architectures */ else if (file_io_mode == FILE_IO_MODE_MMAP) { +#ifndef _WIN32 msync(mmaps[file_id], file_size, MS_SYNC | MS_INVALIDATE); +#else + FlushViewOfFile(mmaps[file_id], (size_t)file_size); +#endif } #endif - + return 1; /* Unknown I/O mode */ } +#ifdef _WIN32 +ssize_t pread(HANDLE hFile, void *buf, ssize_t count, long long offset) +{ + DWORD nBytesRead; + OVERLAPPED ov = {0}; + LARGE_INTEGER li; + + if(!count) + return 0; +#ifdef _WIN64 + if(count > UINT_MAX) + count= UINT_MAX; +#endif + + li.QuadPart = offset; + ov.Offset = li.LowPart; + ov.OffsetHigh = li.HighPart; + + if(!ReadFile(hFile, buf, (DWORD)count, &nBytesRead, &ov)) + { + DWORD lastError = GetLastError(); + if(lastError == ERROR_HANDLE_EOF) + return 0; + return -1; + } + return nBytesRead; +} +ssize_t pwrite(HANDLE hFile, const void *buf, size_t count, + long long offset) +{ + DWORD nBytesWritten; + OVERLAPPED ov = {0}; + LARGE_INTEGER li; + + if(!count) + return 0; + +#ifdef _WIN64 + if(count > UINT_MAX) + count= UINT_MAX; +#endif + + li.QuadPart = offset; + ov.Offset = li.LowPart; + ov.OffsetHigh= li.HighPart; + + if(!WriteFile(hFile, buf, (DWORD)count, &nBytesWritten, &ov)) + { + return -1; + } + else + return nBytesWritten; +} + +#define MAP_SHARED 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define MAP_FAILED NULL + +void *mmap(void *addr, size_t len, int prot, int flags, + FILE_DESCRIPTOR fd, long long off) +{ + DWORD flProtect; + DWORD flMap; + void *retval; + LARGE_INTEGER li; + HANDLE hMap; + + switch(prot) + { + case PROT_READ: + flProtect = PAGE_READONLY; + flMap = FILE_MAP_READ; + break; + case PROT_READ|PROT_WRITE: + flProtect = PAGE_READWRITE; + flMap = FILE_MAP_ALL_ACCESS; + break; + default: + return MAP_FAILED; + } + hMap = CreateFileMapping(fd, NULL, flProtect, 0 , 0, NULL); + + if(hMap == INVALID_HANDLE_VALUE) + return MAP_FAILED; + + li.QuadPart = off; + retval = MapViewOfFileEx(hMap, flMap, li.HighPart, li.LowPart, len, NULL); + + CloseHandle(hMap); + return retval; +} + +int munmap(void *start, size_t len) +{ + (void) len; /* unused */ + if(UnmapViewOfFile(start)) + return 0; + return -1; +} +#endif + ssize_t file_pread(unsigned int file_id, void *buf, ssize_t count, - off_t offset, int thread_id) + long long offset, int thread_id) { - int fd = files[file_id]; + FILE_DESCRIPTOR fd = files[file_id]; #ifdef HAVE_MMAP void *start; - off_t page_addr; - off_t page_offset; + long long page_addr; + long long page_offset; #endif #ifdef HAVE_LIBAIO struct iocb iocb; @@ -1264,7 +1434,6 @@ ssize_t file_pread(unsigned int file_id, void *buf, ssize_t count, return 0; memcpy(buffer, (char *)start + page_offset, count); munmap(start, count + page_offset); - return count; # else (void)start; /* unused */ @@ -1284,9 +1453,9 @@ ssize_t file_pread(unsigned int file_id, void *buf, ssize_t count, ssize_t file_pwrite(unsigned int file_id, void *buf, ssize_t count, - off_t offset, int thread_id) + long long offset, int thread_id) { - int fd = files[file_id]; + FILE_DESCRIPTOR fd = files[file_id]; #ifdef HAVE_MMAP void *start; size_t page_addr; @@ -1321,6 +1490,7 @@ ssize_t file_pwrite(unsigned int file_id, void *buf, ssize_t count, page_offset = offset - page_addr; start = mmap(NULL, count + page_offset, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_addr); + if (start == MAP_FAILED) return 0; memcpy((char *)start + page_offset, buffer, count); @@ -1453,7 +1623,13 @@ int parse_arguments(void) if (mode == NULL || !strlen(mode)) file_extra_flags = 0; else if (!strcmp(mode, "sync")) + { +#ifdef _WIN32 + file_extra_flags = FILE_FLAG_WRITE_THROUGH; +#else file_extra_flags = O_SYNC; +#endif + } else if (!strcmp(mode, "dsync")) { #ifdef O_DSYNC @@ -1465,7 +1641,9 @@ int parse_arguments(void) } else if (!strcmp(mode, "direct")) { -#ifdef O_DIRECT +#ifdef _WIN32 + file_extra_flags = FILE_FLAG_NO_BUFFERING; +#elif defined(O_DIRECT) file_extra_flags = O_DIRECT; #else log_text(LOG_FATAL, "O_DIRECT is not supported on this platform."); @@ -1572,15 +1750,34 @@ unsigned long sb_getpagesize(void) { #ifdef _SC_PAGESIZE return sysconf(_SC_PAGESIZE); +#elif defined _WIN32 + SYSTEM_INFO info; + GetSystemInfo(&info); + return info.dwPageSize; #else return getpagesize(); #endif } +/* + Alignment requirement for mmap(). The same as page size, except on Windows + (on Windows it has to be 64KB, even if pagesize is only 4 or 8KB) +*/ +unsigned long sb_get_allocation_granularity(void) +{ +#ifdef _WIN32 + SYSTEM_INFO info; + GetSystemInfo(&info); + return info.dwAllocationGranularity; +#else + return sb_getpagesize(); +#endif +} -/* Allocate a buffer of a specified size and align it to the page size */ - - +/* + Allocate a buffer of a specified size and align it to the allocation + granularity +*/ void *sb_memalign(size_t size) { unsigned long page_size; @@ -1595,6 +1792,9 @@ void *sb_memalign(size_t size) #elif defined(HAVE_VALLOC) (void)page_size; /* unused */ buffer = valloc(size); +#elif defined (_WIN32) + (void)page_size; /* unused */ + buffer = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); #else (void)page_size; /* unused */ log_text(LOG_WARNING, "None of valloc(), memalign and posix_memalign() is available, doing unaligned IO!"); @@ -1604,12 +1804,20 @@ void *sb_memalign(size_t size) return buffer; } +static void sb_free_memaligned(void *buf) +{ +#ifdef _WIN32 + VirtualFree(buf,0,MEM_FREE); +#else + free(buf); +#endif +} /* Fill buffer with random values and write checksum */ void file_fill_buffer(unsigned char *buf, unsigned int len, - unsigned long offset) + size_t offset) { unsigned int i; @@ -1627,7 +1835,7 @@ void file_fill_buffer(unsigned char *buf, unsigned int len, /* Validate checksum and offset of block read from disk */ -int file_validate_buffer(unsigned char *buf, unsigned int len, unsigned long offset) +int file_validate_buffer(unsigned char *buf, unsigned int len, size_t offset) { unsigned int checksum; unsigned int cs_offset; @@ -1644,11 +1852,11 @@ int file_validate_buffer(unsigned char *buf, unsigned int len, unsigned long of return 1; } - if (offset != *(unsigned long *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)) + if (offset != *(size_t *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)) { log_text(LOG_FATAL, "Offset mismatch in block:"); log_text(LOG_FATAL, " Actual offset: %ld Stored offset: %ld", - offset, *(unsigned long *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)); + offset, *(size_t *)(buf + cs_offset + FILE_CHECKSUM_LENGTH)); return 1; } diff --git a/sysbench/tests/memory/CMakeLists.txt b/sysbench/tests/memory/CMakeLists.txt new file mode 100644 index 0000000..cbb576a --- /dev/null +++ b/sysbench/tests/memory/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/tests) +add_library(sbmemory sb_memory.c) diff --git a/sysbench/tests/memory/sb_memory.c b/sysbench/tests/memory/sb_memory.c index 3d3df14..c369698 100644 --- a/sysbench/tests/memory/sb_memory.c +++ b/sysbench/tests/memory/sb_memory.c @@ -18,6 +18,9 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef _WIN32 +#include "sb_win.h" +#endif #include "sysbench.h" @@ -58,35 +61,34 @@ static void memory_print_stats(void); static sb_test_t memory_test = { - .sname = "memory", - .lname = "Memory functions speed test", - .ops = + "memory", + "Memory functions speed test", { - .init = memory_init, - .prepare = NULL, - .thread_init = NULL, - .thread_done = NULL, - .cleanup = NULL, - .print_mode = memory_print_mode, - .get_request = memory_get_request, - .execute_request = memory_execute_request, - .print_stats = memory_print_stats, - .done = NULL + memory_init, + NULL, + NULL, + memory_print_mode, + memory_get_request, + memory_execute_request, + memory_print_stats, + NULL, + NULL, + NULL }, - .cmds = { - .help = NULL, - .prepare = NULL, - .run = NULL, - .cleanup = NULL + { + NULL, + NULL, + NULL, + NULL }, - .args = memory_args, + memory_args, {NULL, NULL} }; /* Test arguments */ static ssize_t memory_block_size; -static off_t memory_total_size; +static size_t memory_total_size; static unsigned int memory_scope; static unsigned int memory_oper; static unsigned int memory_access_rnd; @@ -96,7 +98,7 @@ static unsigned int memory_hugetlb; /* Statistics */ static unsigned int total_ops; -static off_t total_bytes; +static size_t total_bytes; /* Array of per-thread buffers */ static int **buffers; diff --git a/sysbench/tests/mutex/CMakeLists.txt b/sysbench/tests/mutex/CMakeLists.txt new file mode 100644 index 0000000..2d4b947 --- /dev/null +++ b/sysbench/tests/mutex/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/tests) +add_library(sbmutex sb_mutex.c) diff --git a/sysbench/tests/mutex/sb_mutex.c b/sysbench/tests/mutex/sb_mutex.c index 729b828..a670a19 100644 --- a/sysbench/tests/mutex/sb_mutex.c +++ b/sysbench/tests/mutex/sb_mutex.c @@ -19,6 +19,10 @@ # include "config.h" #endif +#ifdef _WIN32 +# include "sb_win.h" +#endif + #ifdef HAVE_PTHREAD_H # include #endif @@ -52,27 +56,26 @@ static int mutex_done(void); static sb_test_t mutex_test = { - .sname = "mutex", - .lname = "Mutex performance test", - .ops = { - .init = mutex_init, - .prepare = NULL, - .thread_init = NULL, - .thread_done = NULL, - .print_mode = mutex_print_mode, - .print_stats = NULL, - .get_request = mutex_get_request, - .execute_request = mutex_execute_request, - .cleanup = NULL, - .done = mutex_done + "mutex", + "Mutex performance test", + { + mutex_init, + NULL, + NULL, + mutex_print_mode, + mutex_get_request, + mutex_execute_request, + NULL, + NULL, + mutex_done }, - .cmds = { - .help = NULL, - .prepare = NULL, - .run = NULL, - .cleanup = NULL + { + NULL, + NULL, + NULL, + NULL }, - .args = mutex_args, + mutex_args, {NULL, NULL} }; @@ -141,7 +144,7 @@ sb_request_t mutex_get_request(void) int mutex_execute_request(sb_request_t *sb_req, int thread_id) { unsigned int i; - unsigned int c; + unsigned int c=0; unsigned int current_lock; sb_mutex_request_t *mutex_req = &sb_req->u.mutex_request; log_msg_t msg; diff --git a/sysbench/tests/sb_fileio.h b/sysbench/tests/sb_fileio.h index 2a69c94..c0f70ed 100644 --- a/sysbench/tests/sb_fileio.h +++ b/sysbench/tests/sb_fileio.h @@ -18,6 +18,10 @@ #ifndef SB_FILEIO_H #define SB_FILEIO_H +#ifdef _WIN32 +#include "sb_win.h" /* ssize_t defined*/ +#endif + /* File operation types */ typedef enum { @@ -32,7 +36,7 @@ typedef enum typedef struct { unsigned int file_id; - off_t pos; + long long pos; ssize_t size; sb_file_op_t operation; } sb_file_request_t; diff --git a/sysbench/tests/sb_memory.h b/sysbench/tests/sb_memory.h index 4420387..17bdedd 100644 --- a/sysbench/tests/sb_memory.h +++ b/sysbench/tests/sb_memory.h @@ -40,7 +40,7 @@ typedef enum typedef struct { sb_mem_op_t type; - unsigned long block_size; + size_t block_size; sb_mem_scope_t scope; } sb_mem_request_t; diff --git a/sysbench/tests/threads/CMakeLists.txt b/sysbench/tests/threads/CMakeLists.txt new file mode 100644 index 0000000..7143ece --- /dev/null +++ b/sysbench/tests/threads/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (C) 2008 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/tests) +add_library(sbthreads sb_threads.c) diff --git a/sysbench/tests/threads/sb_threads.c b/sysbench/tests/threads/sb_threads.c index 7a2a064..a5b9558 100644 --- a/sysbench/tests/threads/sb_threads.c +++ b/sysbench/tests/threads/sb_threads.c @@ -19,6 +19,10 @@ # include "config.h" #endif +#ifdef _WIN32 +# include "sb_win.h" +#endif + #ifdef HAVE_PTHREAD_H # include #endif @@ -28,6 +32,8 @@ /* How to test scheduler pthread_yield or sched_yield */ #ifdef HAVE_PTHREAD_YIELD #define YIELD pthread_yield +#elif defined (_WIN32) +#define YIELD SwitchToThread #else #define YIELD sched_yield #endif @@ -53,27 +59,27 @@ static int threads_cleanup(void); static sb_test_t threads_test = { - .sname = "threads", - .lname = "Threads subsystem performance test", - .ops = { - .init = threads_init, - .prepare = threads_prepare, - .thread_init = NULL, - .thread_done = NULL, - .print_mode = threads_print_mode, - .print_stats = NULL, - .get_request = threads_get_request, - .execute_request = threads_execute_request, - .cleanup = threads_cleanup, - .done = NULL + "threads", + "Threads subsystem performance test", + { + threads_init, + threads_prepare, + NULL, + threads_print_mode, + threads_get_request, + threads_execute_request, + NULL, + NULL, + NULL, + threads_cleanup, }, - .cmds = { - .help = NULL, - .prepare = NULL, - .run = NULL, - .cleanup = NULL + { + NULL, + NULL, + NULL, + NULL }, - .args = threads_args, + threads_args, {NULL, NULL} };