1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "include/compat.h"
16 #include "common/errno.h"
17 #include "systest_runnable.h"
18 #include "systest_settings.h"
28 #include <sys/syscall.h>
29 #include <sys/types.h>
35 using std::ostringstream;
38 static pid_t do_gettid(void)
40 #if defined(__linux__)
41 return static_cast < pid_t >(syscall(SYS_gettid));
43 return static_cast < pid_t >(pthread_getthreadid_np());
47 std::atomic<unsigned> m_highest_id = { 0 };
50 SysTestRunnable(int argc, const char **argv)
56 m_id = ++m_highest_id;
57 memset(&m_pthread, 0, sizeof(m_pthread));
68 const char* SysTestRunnable::
69 get_id_str(void) const
81 bool use_threads = SysTestSettings::inst().use_threads();
83 ret = pthread_create(&m_pthread, NULL, systest_runnable_pthread_helper,
84 static_cast<void*>(this));
90 ret = preforker.prefork(err_msg);
94 if (preforker.is_child()) {
96 void *retptr = systest_runnable_pthread_helper(static_cast<void*>(this));
97 preforker.exit((int)(uintptr_t)retptr);
105 std::string SysTestRunnable::
109 return "SysTestRunnable was never started.";
112 bool use_threads = SysTestSettings::inst().use_threads();
115 ret = pthread_join(m_pthread, &ptrretval);
118 oss << "pthread_join failed with error " << ret;
121 int retval = (int)(uintptr_t)ptrretval;
124 oss << "ERROR " << retval;
130 ret = preforker.parent_wait(err_msg);
135 std::string SysTestRunnable::
136 run_until_finished(std::vector < SysTestRunnable * > &runnables)
139 for (std::vector < SysTestRunnable * >::const_iterator r = runnables.begin();
140 r != runnables.end(); ++r) {
141 int ret = (*r)->start();
144 oss << "run_until_finished: got error " << ret
145 << " when starting runnable " << index;
151 for (std::vector < SysTestRunnable * >::const_iterator r = runnables.begin();
152 r != runnables.end(); ++r) {
153 std::string rstr = (*r)->join();
156 oss << "run_until_finished: runnable " << (*r)->get_id_str()
157 << ": got error: " << rstr;
161 printf("*******************************\n");
165 void *systest_runnable_pthread_helper(void *arg)
167 SysTestRunnable *st = static_cast < SysTestRunnable * >(arg);
168 st->update_id_str(true);
169 printf("%s: starting.\n", st->get_id_str());
171 printf("%s: shutting down.\n", st->get_id_str());
172 return (void*)(uintptr_t)ret;
175 void SysTestRunnable::
176 update_id_str(bool started)
178 bool use_threads = SysTestSettings::inst().use_threads();
184 snprintf(extra, sizeof(extra), "_[%d]", do_gettid());
186 snprintf(extra, sizeof(extra), "_[%d]", getpid());
189 snprintf(m_id_str, SysTestRunnable::ID_STR_SZ, "thread_%d%s", m_id, extra);
191 snprintf(m_id_str, SysTestRunnable::ID_STR_SZ, "process_%d%s", m_id, extra);
194 // Copy argv so that if some fiend decides to modify it, it's ok.
195 void SysTestRunnable::
196 set_argv(int argc, const char **argv)
198 if (m_argv_orig != NULL) {
199 for (int i = 0; i < m_argc; ++i)
200 free((void*)(m_argv_orig[i]));
201 delete[] m_argv_orig;
210 m_argv_orig = new const char*[m_argc+1];
211 for (int i = 0; i < m_argc; ++i)
212 m_argv_orig[i] = strdup(argv[i]);
213 m_argv_orig[argc] = NULL;
214 m_argv = new const char*[m_argc+1];
215 for (int i = 0; i <= m_argc; ++i)
216 m_argv[i] = m_argv_orig[i];