diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /vespamalloc/src/tests/thread |
Publish
Diffstat (limited to 'vespamalloc/src/tests/thread')
-rw-r--r-- | vespamalloc/src/tests/thread/.gitignore | 3 | ||||
-rw-r--r-- | vespamalloc/src/tests/thread/CMakeLists.txt | 10 | ||||
-rw-r--r-- | vespamalloc/src/tests/thread/racemanythreads.cpp | 82 | ||||
-rw-r--r-- | vespamalloc/src/tests/thread/thread.cpp | 131 | ||||
-rwxr-xr-x | vespamalloc/src/tests/thread/thread_test.sh | 10 |
5 files changed, 236 insertions, 0 deletions
diff --git a/vespamalloc/src/tests/thread/.gitignore b/vespamalloc/src/tests/thread/.gitignore new file mode 100644 index 00000000000..e342e6aaea7 --- /dev/null +++ b/vespamalloc/src/tests/thread/.gitignore @@ -0,0 +1,3 @@ +/*_test +vespamalloc_racemanythreads_test_app +vespamalloc_thread_test_app diff --git a/vespamalloc/src/tests/thread/CMakeLists.txt b/vespamalloc/src/tests/thread/CMakeLists.txt new file mode 100644 index 00000000000..67539a68f77 --- /dev/null +++ b/vespamalloc/src/tests/thread/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(vespamalloc_thread_test_app + SOURCES + thread.cpp +) +vespa_add_test(NAME vespamalloc_thread_test_app NO_VALGRIND COMMAND sh thread_test.sh) +vespa_add_executable(vespamalloc_racemanythreads_test_app + SOURCES + racemanythreads.cpp +) diff --git a/vespamalloc/src/tests/thread/racemanythreads.cpp b/vespamalloc/src/tests/thread/racemanythreads.cpp new file mode 100644 index 00000000000..ba5cc8b7a1c --- /dev/null +++ b/vespamalloc/src/tests/thread/racemanythreads.cpp @@ -0,0 +1,82 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> +#include <stdint.h> +#include <errno.h> +#include <vespa/vespalib/util/atomic.h> +#include <sys/resource.h> +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/log/log.h> + +LOG_SETUP("thread_test"); + +using namespace vespalib; + +class Test : public TestApp +{ +public: + ~Test(); + int Main(); +}; + +Test::~Test() +{ +} + +void * hammer(void * arg) +{ + usleep(4000000); + long seconds = * static_cast<const long *>(arg); + long stopTime(time(NULL) + seconds); + pthread_t id = pthread_self(); + while (time(NULL) < stopTime) { + std::vector<pthread_t *> allocations; + for (size_t i(0); i < 2000; i++) { + pthread_t *t = new pthread_t[20]; + allocations.push_back(t); + for (size_t j(0); j < 20; j++) { + t[j] = id; + } + } + + for (size_t i(0); i < allocations.size(); i++) { + for (size_t j(0); j < 20; j++) { + assert(allocations[i][j] == id); + } + delete [] allocations[i]; + } + } + return arg; +} + +int Test::Main() +{ + TEST_INIT("racemanythreads_test"); + size_t threadCount(1024); + long seconds(10); + if (_argc >= 2) { + threadCount = strtoul(_argv[1], NULL, 0); + if (_argc >= 3) { + seconds = strtoul(_argv[2], NULL, 0); + } + } + + pthread_attr_t attr; + EXPECT_EQUAL(pthread_attr_init(&attr), 0); + EXPECT_EQUAL(pthread_attr_setstacksize(&attr, 64*1024), 0); + std::vector<pthread_t> threads(threadCount); + for (size_t i(0); i < threadCount; i++) { + EXPECT_EQUAL( pthread_create(&threads[i], &attr, hammer, &seconds), 0); + } + for (size_t i(0); i < threadCount; i++) { + void *retval; + EXPECT_EQUAL(pthread_join(threads[i], &retval), 0); + } + + TEST_DONE(); +} + +TEST_APPHOOK(Test); diff --git a/vespamalloc/src/tests/thread/thread.cpp b/vespamalloc/src/tests/thread/thread.cpp new file mode 100644 index 00000000000..49631c0f7e5 --- /dev/null +++ b/vespamalloc/src/tests/thread/thread.cpp @@ -0,0 +1,131 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> +#include <stdint.h> +#include <errno.h> +#include <vespa/vespalib/util/atomic.h> +#include <sys/resource.h> +#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/log/log.h> + +LOG_SETUP("thread_test"); + +using namespace vespalib; + +class Test : public TestApp +{ +public: + ~Test(); + int Main(); +private: + virtual bool useIPCHelper() const { return true; } +}; + +Test::~Test() +{ +} + +void * just_return(void * arg) +{ + return arg; +} + +void * just_exit(void * arg) +{ + pthread_exit(arg); +} + +void * just_cancel(void * arg) +{ + sleep(60); + return arg; +} + +struct wait_info { + wait_info() : + _count(0) + { + if (pthread_mutex_init(&_mutex, NULL) != 0) { abort(); } + if (pthread_cond_init(&_cond, NULL) != 0) { abort(); } + } + ~wait_info() { + if (pthread_mutex_destroy(&_mutex) != 0) { abort(); } + if (pthread_cond_destroy(&_cond) != 0) { abort(); } + } + pthread_cond_t _cond; + pthread_mutex_t _mutex; + volatile uint64_t _count; +}; + +void * just_wait(void * arg) +{ + wait_info * info = (wait_info *) arg; + pthread_mutex_lock(&info->_mutex); + vespalib::Atomic::postInc(&info->_count); + pthread_cond_wait(&info->_cond, &info->_mutex); + pthread_mutex_unlock(&info->_mutex); + pthread_cond_signal(&info->_cond); + vespalib::Atomic::postDec(&info->_count); + return arg; +} + +int Test::Main() +{ + TEST_INIT("thread_test"); + size_t threadCount(102400); + if (_argc >= 3) { + threadCount = strtoul(_argv[2], NULL, 0); + } + + const char * testType = _argv[1]; + + for (size_t i(0); i < threadCount; i++) { + pthread_t th; + void *retval; + if (strcmp(testType, "exit") == 0) { + EXPECT_EQUAL( pthread_create(&th, NULL, just_exit, NULL), 0); + } else if (strcmp(testType, "cancel") == 0) { + EXPECT_EQUAL( pthread_create(&th, NULL, just_cancel, NULL), 0); + EXPECT_EQUAL( pthread_cancel(th), 0); + } else { + EXPECT_EQUAL( pthread_create(&th, NULL, just_return, NULL), 0); + } + EXPECT_EQUAL(pthread_join(th, &retval), 0); + } + + wait_info info; + pthread_attr_t attr; + EXPECT_EQUAL(pthread_attr_init(&attr), 0); + EXPECT_EQUAL(pthread_attr_setstacksize(&attr, 64*1024), 0); + EXPECT_EQUAL(info._count, 0ul); + const size_t NUM_THREADS(16382); // +1 for main thread, +1 for testsystem = 16384 + pthread_t tl[NUM_THREADS]; + for (size_t j=0;j < NUM_THREADS;j++) { + int e = pthread_create(&tl[j], &attr, just_wait, &info); + if (e != 0) { + fprintf(stderr, "pthread_create failed at index '%ld'. with errno='%d'", j, e); + perror("pthread_create failed"); + abort(); + } + } + pthread_t th; + EXPECT_EQUAL( pthread_create(&th, &attr, just_wait, &info), EAGAIN); // Verify that you have reached upper limit of threads with vespamalloc. + while (info._count != NUM_THREADS) { + usleep(1); + } + pthread_mutex_lock(&info._mutex); + pthread_cond_signal(&info._cond); + pthread_mutex_unlock(&info._mutex); + for (size_t j=0;j < NUM_THREADS;j++) { + void *retval; + EXPECT_EQUAL(pthread_join(tl[j], &retval), 0); + } + EXPECT_EQUAL(pthread_attr_destroy(&attr), 0); + EXPECT_EQUAL(info._count, 0ul); + TEST_DONE(); +} + +TEST_APPHOOK(Test); diff --git a/vespamalloc/src/tests/thread/thread_test.sh b/vespamalloc/src/tests/thread/thread_test.sh new file mode 100755 index 00000000000..edcd7a41a17 --- /dev/null +++ b/vespamalloc/src/tests/thread/thread_test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +VESPA_MALLOC_SO=../../../src/vespamalloc/libvespamalloc.so +VESPA_MALLOC_SO_D=../../../src/vespamalloc/libvespamalloc_vespamallocd.so + +LD_PRELOAD=$VESPA_MALLOC_SO ./vespamalloc_thread_test_app return 20 +LD_PRELOAD=$VESPA_MALLOC_SO ./vespamalloc_thread_test_app exit 20 +LD_PRELOAD=$VESPA_MALLOC_SO ./vespamalloc_thread_test_app cancel 20 +#LD_PRELOAD=$VESPA_MALLOC_SO ./vespamalloc_racemanythreads_test_app 4000 20 +#LD_PRELOAD=$VESPA_MALLOC_SO_D ./vespamalloc_racemanythreads_test_app 4000 20 |