Skip to content

Commit 68feeb4

Browse files
Refactor WakeLock.PInvoke for compatibility with the ARM CPU #2745 (#2756)
Replaced `SimpleReasonString` field from `REASON_CONTEXT` with a union, REASON_CONTEXT_UNION. The ARM CPU is more strict with unions. Within unions, strings are not allowed, thus using a pointer to a string, with updated allocation within PowerCreateRequest.
1 parent 0134497 commit 68feeb4

File tree

1 file changed

+44
-11
lines changed

1 file changed

+44
-11
lines changed

src/BenchmarkDotNet/Running/WakeLock.PInvoke.cs

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.ComponentModel;
1+
using System;
2+
using System.ComponentModel;
23
using System.Runtime.InteropServices;
34

45
namespace BenchmarkDotNet.Running;
@@ -9,15 +10,27 @@ private static class PInvoke
910
{
1011
public static SafePowerHandle PowerCreateRequest(string reason)
1112
{
12-
REASON_CONTEXT context = new REASON_CONTEXT()
13+
IntPtr reasonPtr = Marshal.StringToHGlobalAuto(reason);
14+
try
1315
{
14-
Version = POWER_REQUEST_CONTEXT_VERSION,
15-
Flags = POWER_REQUEST_CONTEXT_FLAGS.POWER_REQUEST_CONTEXT_SIMPLE_STRING,
16-
SimpleReasonString = reason
17-
};
18-
SafePowerHandle safePowerHandle = PowerCreateRequest(context);
19-
if (safePowerHandle.IsInvalid) { throw new Win32Exception(); }
20-
return safePowerHandle;
16+
REASON_CONTEXT context = new REASON_CONTEXT()
17+
{
18+
Version = POWER_REQUEST_CONTEXT_VERSION,
19+
Flags = POWER_REQUEST_CONTEXT_FLAGS.POWER_REQUEST_CONTEXT_SIMPLE_STRING,
20+
Reason = new REASON_CONTEXT.REASON_CONTEXT_UNION { SimpleReasonString = reasonPtr }
21+
22+
};
23+
SafePowerHandle safePowerHandle = PowerCreateRequest(context);
24+
if (safePowerHandle.IsInvalid) { throw new Win32Exception(); }
25+
return safePowerHandle;
26+
}
27+
finally
28+
{
29+
if (reasonPtr != IntPtr.Zero)
30+
{
31+
Marshal.FreeHGlobal(reasonPtr);
32+
}
33+
}
2134
}
2235

2336
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
@@ -48,14 +61,34 @@ public static void PowerClearRequest(SafePowerHandle safePowerHandle, POWER_REQU
4861
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
4962
public static extern bool CloseHandle(nint hObject);
5063

64+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
5165
private struct REASON_CONTEXT
5266
{
5367
public uint Version;
5468

5569
public POWER_REQUEST_CONTEXT_FLAGS Flags;
5670

57-
[MarshalAs(UnmanagedType.LPWStr)]
58-
public string SimpleReasonString;
71+
public REASON_CONTEXT_UNION Reason;
72+
73+
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
74+
public struct REASON_CONTEXT_UNION
75+
{
76+
[FieldOffset(0)]
77+
public nint SimpleReasonString;
78+
79+
// The DETAILED structure is not (yet) used, but needed for ARM CPUs, otherwise PowerCreateRequest fails, see #2745
80+
[FieldOffset(0)]
81+
public DETAILED Detailed;
82+
83+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
84+
public struct DETAILED
85+
{
86+
public nint LocalizedReasonModule;
87+
public uint LocalizedReasonId;
88+
public uint ReasonStringCount;
89+
public nint ReasonStrings;
90+
}
91+
}
5992
}
6093

6194
private const uint POWER_REQUEST_CONTEXT_VERSION = 0U;

0 commit comments

Comments
 (0)