diff options
author | Brad King <brad.king@kitware.com> | 2017-09-06 19:01:50 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2018-03-05 14:21:31 (GMT) |
commit | 24de561a1a7529b919215edb0322279449c5e6c0 (patch) | |
tree | 2114c6687833ed4e9b8872eced3cb1a0953ec578 /Utilities/cmlibuv/src/win/process.c | |
parent | 43d6e5a71f7cb68578c72ece1cb5046b929ebdc0 (diff) | |
download | CMake-24de561a1a7529b919215edb0322279449c5e6c0.zip CMake-24de561a1a7529b919215edb0322279449c5e6c0.tar.gz CMake-24de561a1a7529b919215edb0322279449c5e6c0.tar.bz2 |
libuv: unix,win: add uv_spawn option to set child CPU affinity mask
Implement it on Linux, FreeBSD, and Windows for now, and fail with
UV_ENOTSUP on other platforms.
Backported from upstream libuv PR 1527, scheduled for inclusion
in libuv 2.0.
Diffstat (limited to 'Utilities/cmlibuv/src/win/process.c')
-rw-r--r-- | Utilities/cmlibuv/src/win/process.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c index cc06d9e..f5f05af 100644 --- a/Utilities/cmlibuv/src/win/process.c +++ b/Utilities/cmlibuv/src/win/process.c @@ -954,6 +954,12 @@ int uv_spawn(uv_loop_t* loop, return UV_EINVAL; } + if (options->cpumask != NULL) { + if (options->cpumask_size < (size_t)uv_cpumask_size()) { + return UV_EINVAL; + } + } + assert(options->file != NULL); assert(!(options->flags & ~(UV_PROCESS_DETACHED | UV_PROCESS_SETGID | @@ -1084,6 +1090,12 @@ int uv_spawn(uv_loop_t* loop, process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; } + if (options->cpumask != NULL) { + /* Create the child in a suspended state so we have a chance to set + its process affinity before it runs. */ + process_flags |= CREATE_SUSPENDED; + } + if (!CreateProcessW(application_path, arguments, NULL, @@ -1099,6 +1111,50 @@ int uv_spawn(uv_loop_t* loop, goto done; } + if (options->cpumask != NULL) { + /* The child is currently suspended. Set its process affinity + or terminate it if we can't. */ + int i; + int cpumasksize; + DWORD_PTR sysmask; + DWORD_PTR oldmask; + DWORD_PTR newmask; + + cpumasksize = uv_cpumask_size(); + + if (!GetProcessAffinityMask(info.hProcess, &oldmask, &sysmask)) { + err = GetLastError(); + TerminateProcess(info.hProcess, 1); + goto done; + } + + newmask = 0; + for (i = 0; i < cpumasksize; i++) { + if (options->cpumask[i]) { + if (oldmask & (((DWORD_PTR)1) << i)) { + newmask |= ((DWORD_PTR)1) << i; + } else { + err = UV_EINVAL; + TerminateProcess(info.hProcess, 1); + goto done; + } + } + } + + if (!SetProcessAffinityMask(info.hProcess, newmask)) { + err = GetLastError(); + TerminateProcess(info.hProcess, 1); + goto done; + } + + /* The process affinity of the child is set. Let it run. */ + if (ResumeThread(info.hThread) == ((DWORD)-1)) { + err = GetLastError(); + TerminateProcess(info.hProcess, 1); + goto done; + } + } + /* Spawn succeeded */ /* Beyond this point, failure is reported asynchronously. */ |