When starting a new binary, a thread ID running app main() is returned to the caller. The param main_thread is added to related functions. Returned id is used in osv_execve to correctly implement cpu pinning for Open MPI.
In osv_execve.c long type was used instead of pid_t should be - fixed also. Signed-off-by: Justin Cinkelj <justin.cink...@xlab.si> --- core/app.cc | 18 +++++++++++------- core/osv_execve.cc | 29 ++++++++++++++++------------- core/run.cc | 10 ++++++---- include/osv/app.hh | 9 +++++---- include/osv/osv_execve.h | 4 ++-- include/osv/run.hh | 6 ++++-- 6 files changed, 44 insertions(+), 32 deletions(-) diff --git a/core/app.cc b/core/app.cc index ea00661..2337ff5 100644 --- a/core/app.cc +++ b/core/app.cc @@ -115,24 +115,25 @@ bool application::unsafe_stop_and_abandon_other_threads() return success; } -shared_app_t application::run(const std::vector<std::string>& args) +shared_app_t application::run(const std::vector<std::string>& args, pid_t *main_thread) { - return run(args[0], args); + return run(args[0], args, main_thread); } shared_app_t application::run(const std::string& command, const std::vector<std::string>& args, bool new_program, - const std::unordered_map<std::string, std::string> *env) + const std::unordered_map<std::string, std::string> *env, + pid_t *main_thread) { auto app = std::make_shared<application>(command, args, new_program, env); - app->start(); + app->start(main_thread); apps.push(app); return app; } -void run(const std::vector<std::string>& args) { - application::run(args); +void run(const std::vector<std::string>& args, pid_t *main_thread) { + application::run(args, main_thread); } application::application(const std::string& command, @@ -178,7 +179,7 @@ application::application(const std::string& command, } } -void application::start() +void application::start(pid_t *main_thread) { // FIXME: we cannot create the thread inside the constructor because // the thread would attempt to call shared_from_this() before object @@ -189,6 +190,9 @@ void application::start() return nullptr; }, this); override_current_app = nullptr; + if (main_thread) { + *main_thread = pthread_getid(_thread); + } if (err) { throw launch_error("Failed to create the main thread, err=" + std::to_string(err)); } diff --git a/core/osv_execve.cc b/core/osv_execve.cc index 5bd1d54..8a481e9 100644 --- a/core/osv_execve.cc +++ b/core/osv_execve.cc @@ -7,7 +7,7 @@ /* Record thread state changes (termination) by storing exit status into a map. * It is used to implement waitpid like functionality for threads (osv_waittid). **/ -static std::unordered_map<long, int> exited_threads; +static std::unordered_map<pid_t, int> exited_threads; static mutex exec_mutex; static condvar cond; extern "C" long gettid(); // implemented in linux.cc @@ -17,24 +17,27 @@ extern "C" long gettid(); // implemented in linux.cc static int thread_run_app_in_namespace(std::string filename, const std::vector<std::string> args, const std::unordered_map<std::string, std::string> envp, - long* thread_id, + pid_t* thread_id, int notification_fd) { int ret; const bool new_program = true; // run in new ELF namespace - long tid = gettid(); // sched::thread::current()->id(); + pid_t tid, *ptid; + /* + Make sure we always have tid for exited_threads. It doesn't work to copy + tid into *thread_id after osv::run - osv::run blocks, and assignment is + to late to be of any use. + */ + ptid = thread_id? thread_id: &tid; - debugf_execve("thread_run_app_in_namespace... tid=%ld\n", tid); - if (thread_id) { - *thread_id = tid; - } + debugf_execve("thread_run_app_in_namespace... tid=%ld\n", *ptid); // An additional new thread is created by osv::run and caller is blocked - osv::run(filename, args, &ret, new_program, &envp); - debugf_execve("thread_run_app_in_namespace ret = %d tid=%ld\n", ret, tid); + osv::run(filename, args, &ret, new_program, &envp, ptid); + debugf_execve("thread_run_app_in_namespace ret = %d tid=%ld\n", ret, *ptid); WITH_LOCK(exec_mutex) { - exited_threads[tid] = ret; + exited_threads[*ptid] = ret; cond.wake_all(); } @@ -87,7 +90,7 @@ extern "C" { * return thread_id of (first) finished thread. **/ int osv_execve(const char *path, char *const argv[], char *const envp[], - long *thread_id, int notification_fd) + pid_t *thread_id, int notification_fd) { // will start app at path in new OSv thread, without replacing current binary. debugf_execve("OSv osv_execve:%d path=%s argv=%p envp=%p thread_id=%p %d notification_fd=%d\n", @@ -133,7 +136,7 @@ int osv_execve(const char *path, char *const argv[], char *const envp[], * @options - if WNOHANG bit set, don't block. * **/ -long osv_waittid(long tid, int *status, int options) { +pid_t osv_waittid(pid_t tid, int *status, int options) { debugf_execve("osv_waittid tid=%ld options=%d (WNOHANG=%d) th_status_size=%d\n", tid, options, WNOHANG, exited_threads.size()); @@ -153,7 +156,7 @@ long osv_waittid(long tid, int *status, int options) { } // some thread terminated, we might be interested in it. int exit_code; - long tid2; + pid_t tid2; auto it = exited_threads.end(); if (tid <= 0) { it = exited_threads.begin(); diff --git a/core/run.cc b/core/run.cc index 0184462..be5ffb9 100644 --- a/core/run.cc +++ b/core/run.cc @@ -6,9 +6,10 @@ std::shared_ptr<osv::application> run(std::string path, std::vector<std::string> args, int* return_code, bool new_program, - const std::unordered_map<std::string, std::string> *env) + const std::unordered_map<std::string, std::string> *env, + pid_t* main_thread) { - auto app = osv::application::run(path, args, new_program, env); + auto app = osv::application::run(path, args, new_program, env, main_thread); app->join(); if (return_code) { *return_code = app->get_return_code(); @@ -17,13 +18,14 @@ std::shared_ptr<osv::application> run(std::string path, } std::shared_ptr<osv::application> run(std::string path, - int argc, char** argv, int *return_code) + int argc, char** argv, int *return_code, + pid_t* main_thread) { std::vector<std::string> args; for (int i = 0; i < argc; i++) { args.push_back(argv[i]); } - return run(path, args, return_code); + return run(path, args, return_code, main_thread); } } diff --git a/include/osv/app.hh b/include/osv/app.hh index 4fe261b..aad121c 100644 --- a/include/osv/app.hh +++ b/include/osv/app.hh @@ -79,7 +79,7 @@ public: * \param args Arguments passed to the program's main() function. * \throw launch_error */ - static shared_app_t run(const std::vector<std::string>& args); + static shared_app_t run(const std::vector<std::string>& args, int *main_thread = nullptr); /** * Start a new application. @@ -93,7 +93,8 @@ public: static shared_app_t run(const std::string& command, const std::vector<std::string>& args, bool new_program = false, - const std::unordered_map<std::string, std::string> *env = nullptr); + const std::unordered_map<std::string, std::string> *env = nullptr, + int *main_thread = nullptr); static void join_all() { apps.join(); @@ -167,7 +168,7 @@ private: shared_app_t get_shared() { return shared_from_this(); } - void start(); + void start(int *main_thread = nullptr); void main(); void run_main(std::string path, int argc, char** argv); void run_main(); @@ -214,7 +215,7 @@ namespace osv { * Creates a new app * args Arguments passed to the program's main() function. */ -void run(const std::vector<std::string>& args); +void run(const std::vector<std::string>& args, int *main_thread = nullptr); namespace this_application { diff --git a/include/osv/osv_execve.h b/include/osv/osv_execve.h index 790d707..d281253 100644 --- a/include/osv/osv_execve.h +++ b/include/osv/osv_execve.h @@ -12,8 +12,8 @@ extern "C" { #endif -int osv_execve(const char *path, char *const argv[], char *const envp[], long* thread_id, int notification_fd); -long osv_waittid(long tid, int *status, int options); +int osv_execve(const char *path, char *const argv[], char *const envp[], pid_t* thread_id, int notification_fd); +pid_t osv_waittid(pid_t tid, int *status, int options); #ifdef __cplusplus } diff --git a/include/osv/run.hh b/include/osv/run.hh index d27681b..54585f1 100644 --- a/include/osv/run.hh +++ b/include/osv/run.hh @@ -78,7 +78,8 @@ namespace osv { * \return \c shared pointer to the application */ std::shared_ptr<osv::application> run(std::string path, - int argc, char** argv, int *return_code); + int argc, char** argv, int *return_code, + pid_t *main_thread = nullptr); /** * Run the given executable. @@ -143,7 +144,8 @@ std::shared_ptr<osv::application> run(std::string path, std::vector<std::string> args, int* return_code, bool new_program = false, - const std::unordered_map<std::string, std::string> *env = nullptr); + const std::unordered_map<std::string, std::string> *env = nullptr, + pid_t *main_thread = nullptr); /**@}*/ -- 2.5.5 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to osv-dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.