summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/win/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/win/process.c')
-rw-r--r--Utilities/cmlibuv/src/win/process.c56
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. */