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
];