using System;
using System.Threading;
using System.Runtime.InteropServices;
static class Program
{
[DllImport("libc.so.6")]
private static extern int sched_getcpu();
[DllImport("libc.so.6", SetLastError = true)]
private static extern int sched_setaffinity(int pid, IntPtr cpusetsize, ulong[] cpuset);
private static void SetAffinity(int processorID)
{
ulong processorMask = 1UL << processorID;
sched_setaffinity(0, new IntPtr(sizeof(ulong)), new[] { processorMask });
}
static void Main(string[] args)
{
int processorCount = Environment.ProcessorCount;
Console.WriteLine("Processor count: " + processorCount);
Random random = new Random();
Thread[] threads = new Thread[100];
for (int i = 0; i < 100; i++)
{
int target = random.Next(0, processorCount);
threads[i] = new Thread(new ThreadStart(() =>
{
Thread.BeginThreadAffinity();
try
{
SetAffinity(target);
int actual = sched_getcpu();
if (actual == target)
Console.WriteLine("* Running correctly on " + actual);
else
Console.WriteLine("* Running on " + actual + "; should be on " + target);
}
finally
{
Thread.EndThreadAffinity();
}
}));
threads[i].Start();
}
for (int i = 0; i < 100; i++)
threads[i].Join();
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGhyZWFkaW5nOwp1c2luZyBTeXN0ZW0uUnVudGltZS5JbnRlcm9wU2VydmljZXM7CgpzdGF0aWMgY2xhc3MgUHJvZ3JhbQp7CiAgICBbRGxsSW1wb3J0KCJsaWJjLnNvLjYiKV0KICAgIHByaXZhdGUgc3RhdGljIGV4dGVybiBpbnQgc2NoZWRfZ2V0Y3B1KCk7CiAgICAKICAgIFtEbGxJbXBvcnQoImxpYmMuc28uNiIsIFNldExhc3RFcnJvciA9IHRydWUpXQogICAgcHJpdmF0ZSBzdGF0aWMgZXh0ZXJuIGludCBzY2hlZF9zZXRhZmZpbml0eShpbnQgcGlkLCBJbnRQdHIgY3B1c2V0c2l6ZSwgdWxvbmdbXSBjcHVzZXQpOwogICAgCiAgICBwcml2YXRlIHN0YXRpYyB2b2lkIFNldEFmZmluaXR5KGludCBwcm9jZXNzb3JJRCkKICAgIHsKICAgICAgICB1bG9uZyBwcm9jZXNzb3JNYXNrID0gMVVMIDw8IHByb2Nlc3NvcklEOwogICAgICAgIHNjaGVkX3NldGFmZmluaXR5KDAsIG5ldyBJbnRQdHIoc2l6ZW9mKHVsb25nKSksIG5ld1tdIHsgcHJvY2Vzc29yTWFzayB9KTsKICAgIH0KICAgIAogICAgc3RhdGljIHZvaWQgTWFpbihzdHJpbmdbXSBhcmdzKQogICAgewogICAgICAgIGludCBwcm9jZXNzb3JDb3VudCA9IEVudmlyb25tZW50LlByb2Nlc3NvckNvdW50OwogICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJQcm9jZXNzb3IgY291bnQ6ICIgKyBwcm9jZXNzb3JDb3VudCk7ICAgICAgICAgICAgICAgIAogICAgICAgIFJhbmRvbSByYW5kb20gPSBuZXcgUmFuZG9tKCk7CiAgICAgICAgVGhyZWFkW10gdGhyZWFkcyA9IG5ldyBUaHJlYWRbMTAwXTsKCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCAxMDA7IGkrKykKICAgICAgICB7CiAgICAgICAgICAgIGludCB0YXJnZXQgPSByYW5kb20uTmV4dCgwLCBwcm9jZXNzb3JDb3VudCk7CgogICAgICAgICAgICB0aHJlYWRzW2ldID0gbmV3IFRocmVhZChuZXcgVGhyZWFkU3RhcnQoKCkgPT4KICAgICAgICAgICAgewogICAgICAgICAgICAgICAgVGhyZWFkLkJlZ2luVGhyZWFkQWZmaW5pdHkoKTsKICAgICAgICAgICAgICAgIHRyeQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIFNldEFmZmluaXR5KHRhcmdldCk7CiAgICAgICAgICAgICAgICAgICAgaW50IGFjdHVhbCA9IHNjaGVkX2dldGNwdSgpOwogICAgICAgICAgICAgICAgICAgIGlmIChhY3R1YWwgPT0gdGFyZ2V0KQogICAgICAgICAgICAgICAgICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiKiBSdW5uaW5nIGNvcnJlY3RseSBvbiAiICsgYWN0dWFsKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCIqIFJ1bm5pbmcgb24gIiArIGFjdHVhbCArICI7IHNob3VsZCBiZSBvbiAiICsgdGFyZ2V0KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZpbmFsbHkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBUaHJlYWQuRW5kVGhyZWFkQWZmaW5pdHkoKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwoKICAgICAgICAgICAgdGhyZWFkc1tpXS5TdGFydCgpOwogICAgICAgIH0KCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCAxMDA7IGkrKykKICAgICAgICAgICAgdGhyZWFkc1tpXS5Kb2luKCk7CiAgICB9Cn0K