Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support #29

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 38 additions & 33 deletions src/ThreadPinning.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ include("lscpu_examples.jl")
include("libs/libc.jl")
include("libs/libuv.jl")
include("libs/libpthread.jl")
include("windows/windows.jl")
import .Windows
include("omp.jl")
include("blas.jl")
include("querying.jl")
Expand Down Expand Up @@ -70,45 +72,48 @@ end
# initialization
function __init__()
forget_pin_attempts()
if AUTOUPDATE
if false
# if AUTOUPDATE
update_sysinfo!(; fromscratch = true)
end
maybe_autopin()
return nothing
end

# precompile
import SnoopPrecompile
SnoopPrecompile.@precompile_all_calls begin
ThreadPinning.lscpu2sysinfo(LSCPU_STRING)
update_sysinfo!()
lscpu_string()
sysinfo()
pinthread(0)
pinthreads(0:(nthreads() - 1))
pinthreads(collect(0:(nthreads() - 1)))
pinthreads(:compact; nthreads=1)
pinthreads(:spread; nthreads=1)
pinthreads(:random; nthreads=1)
pinthreads(:current; nthreads=1)
pinthreads(:compact; places = Cores(), nthreads=1)
pinthreads(:compact; places = CPUThreads(), nthreads=1)
pinthreads(:spread; places = NUMA(), nthreads=1)
pinthreads(:spread; places = Sockets(), nthreads=1)
getcpuid()
getcpuids()
nsockets()
nnuma()
cpuids_all()
cpuids_per_socket()
cpuids_per_numa()
ncputhreads()
ncputhreads_per_socket()
ncputhreads_per_numa()
ncores()
ncores_per_socket()
ncores_per_numa()
end
# # precompile
# import SnoopPrecompile
# SnoopPrecompile.@precompile_all_calls begin
# @static if Sys.islinux()
# ThreadPinning.lscpu2sysinfo(LSCPU_STRING)
# lscpu_string()
# end
# update_sysinfo!()
# sysinfo()
# pinthread(0)
# pinthreads(0:(nthreads() - 1))
# pinthreads(collect(0:(nthreads() - 1)))
# pinthreads(:compact; nthreads=1)
# pinthreads(:spread; nthreads=1)
# pinthreads(:random; nthreads=1)
# pinthreads(:current; nthreads=1)
# pinthreads(:compact; places = Cores(), nthreads=1)
# pinthreads(:compact; places = CPUThreads(), nthreads=1)
# pinthreads(:spread; places = NUMA(), nthreads=1)
# pinthreads(:spread; places = Sockets(), nthreads=1)
# getcpuid()
# getcpuids()
# nsockets()
# nnuma()
# cpuids_all()
# cpuids_per_socket()
# cpuids_per_numa()
# ncputhreads()
# ncputhreads_per_socket()
# ncputhreads_per_numa()
# ncores()
# ncores_per_socket()
# ncores_per_numa()
# end

# exports
export threadinfo,
Expand Down
10 changes: 7 additions & 3 deletions src/querying.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
"""
Returns the ID of the CPU on which the calling thread
is currently executing.

See `sched_getcpu` for more information.
"""
getcpuid() = Int(sched_getcpu())
function getcpuid()
@static if Sys.iswindows()
return Int(Windows.get_current_processor_number())
else
return Int(sched_getcpu())
end
end

"""
Returns the ID of the CPU on which the given Julia thread
Expand Down
34 changes: 21 additions & 13 deletions src/sysinfo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,25 @@ function update_sysinfo!(; fromscratch = false, lscpustr = nothing, verbose = fa
SYSINFO[] = SysInfo()
else
local sysinfo
try
if !isnothing(lscpustr)
# explicit lscpu string given
sysinfo = lscpu2sysinfo(lscpustr; verbose)
else
if !fromscratch
# use precompiled lscpu string
sysinfo = lscpu2sysinfo(LSCPU_STRING; verbose)
@static if Sys.iswindows()
sysinfo = Windows.get_sysinfo()
else
try
if !isnothing(lscpustr)
# explicit lscpu string given
sysinfo = lscpu2sysinfo(lscpustr; verbose)
else
# from scratch: query lscpu again
sysinfo = lscpu2sysinfo(lscpu_string(); verbose)
if !fromscratch
# use precompiled lscpu string
sysinfo = lscpu2sysinfo(LSCPU_STRING; verbose)
else
# from scratch: query lscpu again
sysinfo = lscpu2sysinfo(lscpu_string(); verbose)
end
end
catch err
throw(ArgumentError("Couldn't parse the given lscpu string:\n\n $lscpustr \n\n"))
end
catch err
throw(ArgumentError("Couldn't parse the given lscpu string:\n\n $lscpustr \n\n"))
end
SYSINFO[] = sysinfo
end
Expand Down Expand Up @@ -173,4 +177,8 @@ end

# global "constant"
const SYSINFO = Ref{SysInfo}(SysInfo())
const LSCPU_STRING = lscpu_string()
@static if Sys.iswindows()
const LSCPU_STRING = "windows"
else
const LSCPU_STRING = lscpu_string()
end
131 changes: 131 additions & 0 deletions src/windows/error_codes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# SOURCE: https://learn.microsoft.com/en-gb/windows/win32/debug/system-error-codes--0-499-?redirectedfrom=MSDN

### Parsing
# lines = readlines(IOBuffer(s))
# lines = filter(!isempty, lines)
#
# error_codes = Dict{Int, String}()
# for (li, l) in pairs(lines)
# if startswith(l, "ERROR") || startswith(l, "WAIT")
# code = parse(Int, strip(split(lines[li+1], "(")[1]))
# error_codes[code] = l
# end
# end
#
# write("errors.txt", string(error_codes))

### OUTPUT
const ERROR_CODES_LOOKUP = Dict(56 => "ERROR_TOO_MANY_CMDS", 60 => "ERROR_BAD_REM_ADAP",
220 => "ERROR_FILE_CHECKED_OUT", 308 => "ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT",
67 => "ERROR_BAD_NET_NAME", 215 => "ERROR_NESTING_NOT_ALLOWED",
319 => "ERROR_UNDEFINED_SCOPE", 112 => "ERROR_DISK_FULL",
333 => "ERROR_NOT_REDUNDANT_STORAGE", 86 => "ERROR_INVALID_PASSWORD",
207 => "ERROR_RING2_STACK_IN_USE", 183 => "ERROR_ALREADY_EXISTS",
224 => "ERROR_FORMS_AUTH_REQUIRED", 12 => "ERROR_INVALID_ACCESS", 23 => "ERROR_CRC",
111 => "ERROR_BUFFER_OVERFLOW", 68 => "ERROR_TOO_MANY_NAMES",
82 => "ERROR_CANNOT_MAKE", 130 => "ERROR_DIRECT_ACCESS_HANDLE",
125 => "ERROR_NO_VOLUME_LABEL", 71 => "ERROR_REQ_NOT_ACCEP",
66 => "ERROR_BAD_DEV_TYPE", 103 => "ERROR_TOO_MANY_SEM_REQUESTS",
59 => "ERROR_UNEXP_NET_ERR", 208 => "ERROR_META_EXPANSION_TOO_LONG",
336 => "ERROR_DIRECTORY_NOT_SUPPORTED", 26 => "ERROR_NOT_DOS_DISK",
127 => "ERROR_PROC_NOT_FOUND", 100 => "ERROR_TOO_MANY_SEMAPHORES",
230 => "ERROR_BAD_PIPE", 195 => "ERROR_INVALID_MINALLOCSIZE",
141 => "ERROR_SUBST_TO_JOIN", 278 => "ERROR_INVALID_EA_HANDLE",
135 => "ERROR_IS_SUBSTED", 138 => "ERROR_JOIN_TO_JOIN", 222 => "ERROR_BAD_FILE_TYPE",
107 => "ERROR_DISK_CHANGE", 276 => "ERROR_EA_FILE_CORRUPT", 57 => "ERROR_ADAP_HDW_ERR",
152 => "ERROR_TOO_MANY_MUXWAITERS", 170 => "ERROR_BUSY",
129 => "ERROR_CHILD_NOT_COMPLETE", 133 => "ERROR_IS_JOIN_TARGET",
72 => "ERROR_REDIR_PAUSED", 258 => "WAIT_TIMEOUT", 1 => "ERROR_INVALID_FUNCTION",
137 => "ERROR_NOT_SUBSTED", 22 => "ERROR_BAD_COMMAND", 154 => "ERROR_LABEL_TOO_LONG",
313 => "ERROR_NOT_ALLOWED_ON_SYSTEM_FILE", 206 => "ERROR_FILENAME_EXCED_RANGE",
288 => "ERROR_NOT_OWNER", 299 => "ERROR_PARTIAL_COPY", 33 => "ERROR_LOCK_VIOLATION",
400 => "ERROR_THREAD_MODE_ALREADY_BACKGROUND", 113 => "ERROR_NO_MORE_SEARCH_HANDLES",
231 => "ERROR_PIPE_BUSY", 254 => "ERROR_INVALID_EA_NAME",
309 => "ERROR_NOTIFICATION_GUID_ALREADY_DEFINED", 142 => "ERROR_BUSY_DRIVE",
5 => "ERROR_ACCESS_DENIED", 55 => "ERROR_DEV_NOT_EXIST",
114 => "ERROR_INVALID_TARGET_HANDLE", 136 => "ERROR_NOT_JOINED",
117 => "ERROR_INVALID_CATEGORY", 145 => "ERROR_DIR_NOT_EMPTY",
282 => "ERROR_EAS_NOT_SUPPORTED", 275 => "ERROR_EAS_DIDNT_FIT",
337 => "ERROR_NOT_READ_FROM_COPY", 351 => "ERROR_FAIL_SHUTDOWN",
158 => "ERROR_NOT_LOCKED", 218 => "ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY",
28 => "ERROR_OUT_OF_PAPER", 148 => "ERROR_PATH_BUSY",
36 => "ERROR_SHARING_BUFFER_EXCEEDED", 118 => "ERROR_INVALID_VERIFY_SWITCH",
162 => "ERROR_SIGNAL_PENDING", 84 => "ERROR_OUT_OF_STRUCTURES",
7 => "ERROR_ARENA_TRASHED", 25 => "ERROR_SEEK", 203 => "ERROR_ENVVAR_NOT_FOUND",
353 => "ERROR_MAX_SESSIONS_REACHED", 232 => "ERROR_NO_DATA",
304 => "ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING",
18 => "ERROR_NO_MORE_FILES", 240 => "ERROR_VC_DISCONNECTED",
147 => "ERROR_IS_JOIN_PATH", 157 => "ERROR_DISCARDED", 16 => "ERROR_CURRENT_DIRECTORY",
19 => "ERROR_WRITE_PROTECT", 266 => "ERROR_CANNOT_COPY", 31 => "ERROR_GEN_FAILURE",
217 => "ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY", 146 => "ERROR_IS_SUBST_PATH",
61 => "ERROR_PRINTQ_FULL", 29 => "ERROR_WRITE_FAULT", 212 => "ERROR_LOCKED",
303 => "ERROR_DELETE_PENDING", 159 => "ERROR_BAD_THREADID_ADDR",
193 => "ERROR_BAD_EXE_FORMAT", 226 => "ERROR_VIRUS_DELETED",
101 => "ERROR_EXCL_SEM_ALREADY_OWNED", 105 => "ERROR_SEM_OWNER_DIED",
223 => "ERROR_FILE_TOO_LARGE", 17 => "ERROR_NOT_SAME_DEVICE",
335 => "ERROR_COMPRESSED_FILE_NOT_SUPPORTED", 198 => "ERROR_INVALID_SEGDPL",
89 => "ERROR_NO_PROC_SLOTS", 214 => "ERROR_TOO_MANY_MODULES",
331 => "ERROR_TOO_MANY_DESCRIPTORS", 80 => "ERROR_FILE_EXISTS",
51 => "ERROR_REM_NOT_LIST", 143 => "ERROR_SAME_DRIVE", 15 => "ERROR_INVALID_DRIVE",
330 => "ERROR_BAD_DEVICE_PATH", 134 => "ERROR_IS_JOINED",
402 => "ERROR_PROCESS_MODE_ALREADY_BACKGROUND", 110 => "ERROR_OPEN_FAILED",
30 => "ERROR_READ_FAULT", 6 => "ERROR_INVALID_HANDLE", 234 => "ERROR_MORE_DATA",
182 => "ERROR_INVALID_ORDINAL", 164 => "ERROR_MAX_THRDS_REACHED",
153 => "ERROR_INVALID_LIST_FORMAT", 186 => "ERROR_INVALID_FLAG_NUMBER",
64 => "ERROR_NETNAME_DELETED", 267 => "ERROR_DIRECTORY", 139 => "ERROR_SUBST_TO_SUBST",
4 => "ERROR_TOO_MANY_OPEN_FILES", 13 => "ERROR_INVALID_DATA",
104 => "ERROR_INVALID_AT_INTERRUPT_TIME", 316 => "ERROR_DEVICE_FEATURE_NOT_SUPPORTED",
328 => "ERROR_INVALID_FIELD_IN_PARAMETER_LIST", 52 => "ERROR_DUP_NAME",
300 => "ERROR_OPLOCK_NOT_GRANTED", 171 => "ERROR_DEVICE_SUPPORT_IN_PROGRESS",
11 => "ERROR_BAD_FORMAT", 69 => "ERROR_TOO_MANY_SESS",
302 => "ERROR_DISK_TOO_FRAGMENTED", 487 => "ERROR_INVALID_ADDRESS",
85 => "ERROR_ALREADY_ASSIGNED", 119 => "ERROR_BAD_DRIVER_LEVEL",
39 => "ERROR_HANDLE_DISK_FULL", 216 => "ERROR_EXE_MACHINE_TYPE_MISMATCH",
126 => "ERROR_MOD_NOT_FOUND", 108 => "ERROR_DRIVE_LOCKED",
156 => "ERROR_SIGNAL_REFUSED", 2 => "ERROR_FILE_NOT_FOUND",
10 => "ERROR_BAD_ENVIRONMENT", 27 => "ERROR_SECTOR_NOT_FOUND",
124 => "ERROR_INVALID_LEVEL", 307 => "ERROR_INVALID_LOCK_RANGE",
144 => "ERROR_DIR_NOT_ROOT", 352 => "ERROR_FAIL_RESTART",
200 => "ERROR_RING2SEG_MUST_BE_MOVABLE", 312 => "ERROR_NO_RANGES_PROCESSED",
20 => "ERROR_BAD_UNIT", 187 => "ERROR_SEM_NOT_FOUND", 0 => "ERROR_SUCCESS",
329 => "ERROR_OPERATION_IN_PROGRESS", 9 => "ERROR_INVALID_BLOCK",
189 => "ERROR_INVALID_STACKSEG", 109 => "ERROR_BROKEN_PIPE",
161 => "ERROR_BAD_PATHNAME", 401 => "ERROR_THREAD_MODE_NOT_BACKGROUND",
88 => "ERROR_NET_WRITE_FAULT", 209 => "ERROR_INVALID_SIGNAL_NUMBER",
120 => "ERROR_CALL_NOT_IMPLEMENTED", 323 => "ERROR_DATA_CHECKSUM_ERROR",
24 => "ERROR_BAD_LENGTH", 8 => "ERROR_NOT_ENOUGH_MEMORY", 83 => "ERROR_FAIL_I24",
190 => "ERROR_INVALID_MODULETYPE", 201 => "ERROR_RELOC_CHAIN_XEEDS_SEGLIM",
121 => "ERROR_SEM_TIMEOUT", 311 => "ERROR_DUPLICATE_PRIVILEGES",
14 => "ERROR_OUTOFMEMORY", 314 => "ERROR_DISK_RESOURCES_EXHAUSTED",
334 => "ERROR_RESIDENT_FILE_NOT_SUPPORTED", 403 => "ERROR_PROCESS_MODE_NOT_BACKGROUND",
174 => "ERROR_ATOMIC_LOCKS_NOT_SUPPORTED", 322 => "ERROR_DEVICE_NO_RESOURCES",
315 => "ERROR_INVALID_TOKEN", 123 => "ERROR_INVALID_NAME",
305 => "ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME", 32 => "ERROR_SHARING_VIOLATION",
197 => "ERROR_IOPL_NOT_ENABLED", 233 => "ERROR_PIPE_NOT_CONNECTED",
196 => "ERROR_DYNLINK_FROM_INVALID_RING", 320 => "ERROR_INVALID_CAP",
324 => "ERROR_INTERMIXED_KERNEL_EA_OPERATION", 210 => "ERROR_THREAD_1_INACTIVE",
151 => "ERROR_INVALID_EVENT_COUNT", 54 => "ERROR_NETWORK_BUSY",
63 => "ERROR_PRINT_CANCELLED", 191 => "ERROR_INVALID_EXE_SIGNATURE",
62 => "ERROR_NO_SPOOL_SPACE", 205 => "ERROR_NO_SIGNAL_SENT",
327 => "ERROR_OFFSET_ALIGNMENT_VIOLATION", 150 => "ERROR_SYSTEM_TRACE",
122 => "ERROR_INSUFFICIENT_BUFFER", 58 => "ERROR_BAD_NET_RESP",
199 => "ERROR_AUTODATASEG_EXCEEDS_64k", 173 => "ERROR_CANCEL_VIOLATION",
188 => "ERROR_INVALID_STARTING_CODESEG", 277 => "ERROR_EA_TABLE_FULL",
310 => "ERROR_INVALID_EXCEPTION_HANDLER", 321 => "ERROR_DEVICE_UNREACHABLE",
34 => "ERROR_WRONG_DISK", 50 => "ERROR_NOT_SUPPORTED", 318 => "ERROR_SCOPE_NOT_FOUND",
194 => "ERROR_ITERATED_DATA_EXCEEDS_64k", 167 => "ERROR_LOCK_FAILED",
87 => "ERROR_INVALID_PARAMETER", 301 => "ERROR_INVALID_OPLOCK_PROTOCOL",
132 => "ERROR_SEEK_ON_DEVICE", 140 => "ERROR_JOIN_TO_SUBST",
202 => "ERROR_INFLOOP_IN_RELOC_CHAIN", 317 => "ERROR_MR_MID_NOT_FOUND",
180 => "ERROR_INVALID_SEGMENT_NUMBER", 255 => "ERROR_EA_LIST_INCONSISTENT",
160 => "ERROR_BAD_ARGUMENTS", 106 => "ERROR_SEM_USER_LIMIT",
225 => "ERROR_VIRUS_INFECTED", 102 => "ERROR_SEM_IS_SET",
128 => "ERROR_WAIT_NO_CHILDREN", 259 => "ERROR_NO_MORE_ITEMS",
70 => "ERROR_SHARING_PAUSED", 350 => "ERROR_FAIL_NOACTION_REBOOT",
332 => "ERROR_SCRUB_DATA_DISABLED", 21 => "ERROR_NOT_READY", 229 => "ERROR_PIPE_LOCAL",
38 => "ERROR_HANDLE_EOF", 131 => "ERROR_NEGATIVE_SEEK",
192 => "ERROR_EXE_MARKED_INVALID", 326 => "ERROR_FILE_LEVEL_TRIM_NOT_SUPPORTED",
221 => "ERROR_CHECKOUT_REQUIRED", 53 => "ERROR_BAD_NETPATH",
3 => "ERROR_PATH_NOT_FOUND", 306 => "ERROR_SECURITY_STREAM_IS_INCONSISTENT",
149 => "ERROR_IS_SUBST_TARGET", 155 => "ERROR_TOO_MANY_TCBS",
65 => "ERROR_NETWORK_ACCESS_DENIED", 298 => "ERROR_TOO_MANY_POSTS")
95 changes: 95 additions & 0 deletions src/windows/types.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# windows datatypes (https://learn.microsoft.com/de-de/windows/win32/winprog/windows-data-types)
const DWORD = Culong
const DWORD_PTR = Ptr{Culong}
const PDWORD_PTR = Ptr{DWORD_PTR}
const WORD = Cushort
const LPVOID = Ptr{Cvoid}
const BYTE = Cuchar
const ULONG_PTR = Ptr{Culong}
const THREAD_HANDLE = UInt32
# const THREAD_HANDLE = Ptr{UInt32}

const PROCESS_SET_INFORMATION = 0x0200
const PROCESS_QUERY_INFORMATION = 0x0400
const THREAD_SET_INFORMATION = 0x0020
const THREAD_QUERY_INFORMATION = 0x0040

struct SYSTEM_INFO_0_0
wProcessorArchitecture::WORD
wReserved::WORD
end

struct SYSTEM_INFO_0 # necessary?!
dwOemId::DWORD
DUMMYSTRUCTNAME::SYSTEM_INFO_0_0
end

struct SYSTEM_INFO
# Definition: https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info
DUMMYUNIONNAME::Union{DWORD, SYSTEM_INFO_0_0};
dwPageSize::DWORD
lpMinimumApplicationAddress::LPVOID
lpMaximumApplicationAddress::LPVOID
dwActiveProcessorMask::DWORD_PTR
dwNumberOfProcessors::DWORD
dwProcessorType::DWORD
dwAllocationGranularity::DWORD
wProcessorLevel::WORD
wProcessorRevision::WORD
end

struct ProcessorCore
Flags::BYTE
end

struct NumaNode
NodeNumber::DWORD
end

# const LOGICAL_PROCESSOR_RELATIONSHIP = Cint
@enum LOGICAL_PROCESSOR_RELATIONSHIP begin
RelationProcessorCore
RelationNumaNode
RelationCache
RelationProcessorPackage
RelationGroup
RelationProcessorDie
RelationNumaNodeEx
RelationProcessorModule
RelationAll = 0xffff
end

@enum PROCESSOR_CACHE_TYPE begin
CacheUnified
CacheInstruction
CacheData
CacheTrace
end
# const PROCESSOR_CACHE_TYPE = Cint

struct CACHE_DESCRIPTOR
Level::BYTE
Associativity::BYTE
LineSize::WORD
Size::DWORD
Type::PROCESSOR_CACHE_TYPE
end

struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION
ProcessorMask::ULONG_PTR
Relationship::LOGICAL_PROCESSOR_RELATIONSHIP
# DUMMYUNIONNAME::Union{ProcessorCore, NumaNode, CACHE_DESCRIPTOR, Culonglong}
DUMMYUNIONNAME::Union{Ptr{ProcessorCore}, Ptr{NumaNode}, Ptr{CACHE_DESCRIPTOR}, Ptr{Culonglong}}
# DUMMYUNIONNAME::Union{ProcessorCore, NumaNode, CACHE_DESCRIPTOR}
# DUMMYUNIONNAME::Union{ProcessorCore, NumaNode, CACHE_DESCRIPTOR, NTuple{2, Culonglong}}
# union {
# struct {
# BYTE Flags;
# } ProcessorCore;
# struct {
# DWORD NodeNumber;
# } NumaNode;
# CACHE_DESCRIPTOR Cache;
# ULONGLONG Reserved[2];
# } ;
end
Loading