summaryrefslogtreecommitdiffstats
path: root/vespamalloc/src/tests/thread/thread.cpp
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /vespamalloc/src/tests/thread/thread.cpp
Publish
Diffstat (limited to 'vespamalloc/src/tests/thread/thread.cpp')
-rw-r--r--vespamalloc/src/tests/thread/thread.cpp131
1 files changed, 131 insertions, 0 deletions
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);