Skip to content

Instantly share code, notes, and snippets.

@andrew-kramer-inno
Created July 4, 2026 18:21
Show Gist options
  • Select an option

  • Save andrew-kramer-inno/f7e8449b521b7435e91c92ae6b3ae6d8 to your computer and use it in GitHub Desktop.

Select an option

Save andrew-kramer-inno/f7e8449b521b7435e91c92ae6b3ae6d8 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#include <errno.h>
#include <IOKit/IOKitLib.h>
#include <libproc.h>
#include <mach/mach.h>
#include <mach/task_policy.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
static const char* kRequestPath = "/tmp/power-daemon-override/request";
static const char* kLogPath = "/tmp/power-daemon-override/entitled-direct.log";
static const char* kPackageLaneSessionControlPath = "/tmp/power-daemon-override/package-lane-session-control";
static const char* kPackageLaneSessionStatusPath = "/tmp/power-daemon-override/package-lane-session-status";
#define MAX_SCALARS 16
#define MAX_STRUCT_BYTES 12288
#define MAX_LOGGED_STRUCT_BYTES MAX_STRUCT_BYTES
#define PPM_SELECTOR_GET_CLIENT_STATE 0x1d
#define PPM_SELECTOR_SET_DETAILED_THERMAL_BUDGETS 0x23
#define PPM_DETAILED_THERMAL_BUDGETS_BYTES 0x288
#define PPM_DETAILED_THERMAL_BUDGETS_COUNT_OFFSET 0x280
#define PPM_CLIENT_STATE_BYTES 0x640
#define PPM_CLIENT_STATE_DETAILED_BUDGET_COUNT_OFFSET 0x1b8
#define PPM_CLIENT_STATE_DETAILED_BUDGET_ENTRY_OFFSET 0x1c0
#define PPM_CLIENT_STATE_DETAILED_BUDGET_MAX 8
#define PPM_PACKAGE_CLIENT_ID 2
#define PPM_PACKAGE_SESSION_MIN_BUDGET 8000
#define PPM_PACKAGE_SESSION_MAX_BUDGET 255000
#define PPM_PACKAGE_SESSION_MAX_SECONDS 3600
#define PPM_PACKAGE_SESSION_MIN_POLL_MS 100
#define PPM_PACKAGE_SESSION_MAX_POLL_MS 5000
#define AGX_SELECTOR_CONSISTENT_PERF_STATE 0x109
#define AGX_SELECTOR_PERF_STATE 0x10d
#ifndef PRIO_DARWIN_PROCESS
#define PRIO_DARWIN_PROCESS 4
#endif
#ifndef PRIO_DARWIN_GPU
#define PRIO_DARWIN_GPU 5
#endif
#ifndef PRIO_DARWIN_ROLE
#define PRIO_DARWIN_ROLE 6
#endif
#ifndef PROC_PIDCOALITIONINFO
#define PROC_PIDCOALITIONINFO 20
#endif
#ifndef SYS_coalition_policy_set
#define SYS_coalition_policy_set 556
#endif
#ifndef SYS_coalition_policy_get
#define SYS_coalition_policy_get 557
#endif
#define COALITION_TYPE_RESOURCE 0
#define COALITION_TYPE_JETSAM 1
#define COALITION_NUM_TYPES 2
#define COALITION_POLICY_SUPPRESS 1
#define COALITION_POLICY_SUPPRESS_NONE 0
#define COALITION_POLICY_SUPPRESS_DARWIN_BG 1
struct ProcPidCoalitionInfoPrivate
{
uint64_t CoalitionId[COALITION_NUM_TYPES];
uint64_t Reserved1;
uint64_t Reserved2;
uint64_t Reserved3;
};
struct TaskSuppressionPolicyPrivate
{
integer_t Active;
integer_t LowPriCpu;
integer_t TimerThrottle;
integer_t DiskThrottle;
integer_t CpuLimit;
integer_t Suspend;
integer_t ThroughputQos;
integer_t SuppressedCpu;
integer_t BackgroundSockets;
integer_t Reserved[7];
};
#define TASK_SUPPRESSION_POLICY_PRIVATE_COUNT ((mach_msg_type_number_t)(sizeof(struct TaskSuppressionPolicyPrivate) / sizeof(integer_t)))
static const char* ReturnName(kern_return_t kr)
{
switch (kr)
{
case KERN_SUCCESS: return "KERN_SUCCESS";
case kIOReturnNotPrivileged: return "kIOReturnNotPrivileged";
case kIOReturnNotPermitted: return "kIOReturnNotPermitted";
case kIOReturnUnsupported: return "kIOReturnUnsupported";
case kIOReturnBadArgument: return "kIOReturnBadArgument";
case kIOReturnNoDevice: return "kIOReturnNoDevice";
case kIOReturnNoResources: return "kIOReturnNoResources";
default: return "other";
}
}
static void Logf(const char* Format, ...)
{
FILE* Log = fopen(kLogPath, "a");
if (!Log)
{
return;
}
time_t Now = time(NULL);
fprintf(Log, "%lld ", (long long)Now);
va_list Args;
va_start(Args, Format);
vfprintf(Log, Format, Args);
va_end(Args);
fprintf(Log, "\n");
fclose(Log);
}
static void ReadRequest(char* Buffer, size_t BufferSize)
{
if (BufferSize == 0)
{
return;
}
Buffer[0] = '\0';
FILE* Request = fopen(kRequestPath, "r");
if (!Request)
{
return;
}
size_t Len = fread(Buffer, 1, BufferSize - 1, Request);
Buffer[Len] = '\0';
fclose(Request);
for (size_t i = 0; Buffer[i]; ++i)
{
if (Buffer[i] == '\r' || Buffer[i] == '\n')
{
Buffer[i] = '\0';
break;
}
}
}
static size_t Tokenize(char* Buffer, char* Tokens[], size_t MaxTokens)
{
size_t Count = 0;
char* Save = NULL;
char* Token = strtok_r(Buffer, " \t", &Save);
while (Token && Count < MaxTokens)
{
Tokens[Count++] = Token;
Token = strtok_r(NULL, " \t", &Save);
}
return Count;
}
static uint64_t ParseU64(const char* Text)
{
return strtoull(Text, NULL, 0);
}
typedef struct NamedInt
{
const char* Name;
int Value;
} NamedInt;
static const NamedInt kDarwinRoles[] = {
{"default", 0},
{"ui_focal", 1},
{"uifocal", 1},
{"ui", 2},
{"non_ui", 3},
{"nonui", 3},
{"ui_non_focal", 4},
{"uinonfocal", 4},
{"tal_launch", 5},
{"bg", 6},
{"background", 6},
{"user_init", 7},
{NULL, 0},
};
static const NamedInt kGpuRoles[] = {
{"unknown", 0},
{"allow", 1},
{"deny", 2},
{"background", 3},
{"utility", 4},
{"ui_non_focal", 5},
{"nonfocal", 5},
{"non_focal", 5},
{"ui", 6},
{"ui_focal", 7},
{"uifocal", 7},
{NULL, 0},
};
static bool ParseIntToken(const char* Text, int* OutValue)
{
char* End = NULL;
errno = 0;
long Value = strtol(Text, &End, 0);
if (errno != 0 || End == Text || *End != '\0' || Value < INT32_MIN || Value > INT32_MAX)
{
return false;
}
*OutValue = (int)Value;
return true;
}
static bool ParseNamedInt(const char* Text, const NamedInt* Values, int* OutValue)
{
if (ParseIntToken(Text, OutValue))
{
return true;
}
for (size_t i = 0; Values[i].Name; ++i)
{
if (strcasecmp(Text, Values[i].Name) == 0)
{
*OutValue = Values[i].Value;
return true;
}
}
return false;
}
static const char* NamedIntName(const NamedInt* Values, int Value)
{
for (size_t i = 0; Values[i].Name; ++i)
{
if (Values[i].Value == Value)
{
return Values[i].Name;
}
}
return "unknown-value";
}
static int HexNibble(char C)
{
if (C >= '0' && C <= '9')
{
return C - '0';
}
if (C >= 'a' && C <= 'f')
{
return C - 'a' + 10;
}
if (C >= 'A' && C <= 'F')
{
return C - 'A' + 10;
}
return -1;
}
static bool ParseHexBytes(const char* Hex, unsigned char* Output, size_t MaxOutput, size_t* OutputSize)
{
*OutputSize = 0;
int High = -1;
for (size_t i = 0; Hex[i]; ++i)
{
if (Hex[i] == ':' || Hex[i] == '-' || Hex[i] == '_' || Hex[i] == ' ')
{
continue;
}
int Value = HexNibble(Hex[i]);
if (Value < 0)
{
return false;
}
if (High < 0)
{
High = Value;
continue;
}
if (*OutputSize >= MaxOutput)
{
return false;
}
Output[(*OutputSize)++] = (unsigned char)((High << 4) | Value);
High = -1;
}
return High < 0;
}
static const char* CoalitionSuppressName(int Value)
{
switch (Value)
{
case COALITION_POLICY_SUPPRESS_NONE: return "none";
case COALITION_POLICY_SUPPRESS_DARWIN_BG: return "darwin-bg";
default: return "unknown";
}
}
static bool ParseCoalitionSuppressValue(const char* Text, uint32_t* OutValue)
{
if (strcmp(Text, "none") == 0 || strcmp(Text, "NONE") == 0 || strcmp(Text, "0") == 0)
{
*OutValue = COALITION_POLICY_SUPPRESS_NONE;
return true;
}
if (strcmp(Text, "darwin-bg") == 0 || strcmp(Text, "darwin_bg") == 0 ||
strcmp(Text, "bg") == 0 || strcmp(Text, "DARWIN_BG") == 0 || strcmp(Text, "1") == 0)
{
*OutValue = COALITION_POLICY_SUPPRESS_DARWIN_BG;
return true;
}
return false;
}
static bool ReadCoalitionInfoForPid(pid_t Pid, struct ProcPidCoalitionInfoPrivate* Info)
{
memset(Info, 0, sizeof(*Info));
int Ret = proc_pidinfo(Pid, PROC_PIDCOALITIONINFO, 0, Info, sizeof(*Info));
if (Ret != (int)sizeof(*Info))
{
int SavedErrno = errno;
Logf("coalition pid=%d proc_pidinfo result=fail ret=%d errno=%d %s",
Pid,
Ret,
SavedErrno,
strerror(SavedErrno));
return false;
}
Logf("coalition pid=%d resource=%llu jetsam=%llu",
Pid,
(unsigned long long)Info->CoalitionId[COALITION_TYPE_RESOURCE],
(unsigned long long)Info->CoalitionId[COALITION_TYPE_JETSAM]);
return true;
}
static int CoalitionPolicyGet(uint64_t CoalitionId)
{
errno = 0;
int Value = (int)syscall(SYS_coalition_policy_get, CoalitionId, COALITION_POLICY_SUPPRESS);
int SavedErrno = errno;
Logf("coalition=%llu op=get-suppress flavor=%u result=%s value=%d value-name=%s errno=%d %s",
(unsigned long long)CoalitionId,
COALITION_POLICY_SUPPRESS,
Value >= 0 ? "ok" : "fail",
Value,
Value >= 0 ? CoalitionSuppressName(Value) : "none",
Value >= 0 ? 0 : SavedErrno,
Value >= 0 ? "none" : strerror(SavedErrno));
return Value;
}
static bool CoalitionPolicySet(uint64_t CoalitionId, uint32_t Value)
{
errno = 0;
int Ret = (int)syscall(SYS_coalition_policy_set, CoalitionId, COALITION_POLICY_SUPPRESS, Value);
int SavedErrno = errno;
Logf("coalition=%llu op=set-suppress flavor=%u value=%u value-name=%s result=%s errno=%d %s",
(unsigned long long)CoalitionId,
COALITION_POLICY_SUPPRESS,
Value,
CoalitionSuppressName((int)Value),
Ret == 0 ? "ok" : "fail",
Ret == 0 ? 0 : SavedErrno,
Ret == 0 ? "none" : strerror(SavedErrno));
return Ret == 0;
}
static bool ResolveJetsamCoalition(pid_t Pid, uint64_t* OutCoalition)
{
struct ProcPidCoalitionInfoPrivate Info;
if (!ReadCoalitionInfoForPid(Pid, &Info))
{
return false;
}
*OutCoalition = Info.CoalitionId[COALITION_TYPE_JETSAM];
return true;
}
static void CallCoalitionSuppressGet(pid_t Pid)
{
uint64_t Coalition = 0;
if (!ResolveJetsamCoalition(Pid, &Coalition))
{
return;
}
CoalitionPolicyGet(Coalition);
}
static void CallCoalitionSuppressSet(pid_t Pid, uint32_t Value)
{
uint64_t Coalition = 0;
if (!ResolveJetsamCoalition(Pid, &Coalition))
{
return;
}
CoalitionPolicyGet(Coalition);
CoalitionPolicySet(Coalition, Value);
CoalitionPolicyGet(Coalition);
}
static bool GetTaskPolicyPortForPid(pid_t Pid, mach_port_t* OutTask)
{
*OutTask = MACH_PORT_NULL;
kern_return_t Kr = task_name_for_pid(mach_task_self(), Pid, OutTask);
Logf("task-suppress pid=%d op=task_name_for_pid kr=0x%x %s task=0x%x",
Pid,
Kr,
ReturnName(Kr),
*OutTask);
if (Kr == KERN_SUCCESS)
{
return true;
}
Kr = task_for_pid(mach_task_self(), Pid, OutTask);
Logf("task-suppress pid=%d op=task_for_pid kr=0x%x %s task=0x%x",
Pid,
Kr,
ReturnName(Kr),
*OutTask);
return Kr == KERN_SUCCESS;
}
static void FillTaskSuppressionPolicy(struct TaskSuppressionPolicyPrivate* Policy, bool Active)
{
memset(Policy, 0, sizeof(*Policy));
if (!Active)
{
return;
}
Policy->Active = 1;
Policy->LowPriCpu = 1;
Policy->TimerThrottle = LATENCY_QOS_TIER_5;
Policy->DiskThrottle = 1;
Policy->ThroughputQos = THROUGHPUT_QOS_TIER_5;
Policy->BackgroundSockets = 1;
}
static void LogTaskSuppressionPolicy(const char* Label, const struct TaskSuppressionPolicyPrivate* Policy)
{
Logf("task-suppress %s active=%d lowpri-cpu=%d timer=0x%x disk=%d cpu-limit=%d suspend=%d throughput=0x%x suppressed-cpu=%d bg-sockets=%d",
Label,
Policy->Active,
Policy->LowPriCpu,
Policy->TimerThrottle,
Policy->DiskThrottle,
Policy->CpuLimit,
Policy->Suspend,
Policy->ThroughputQos,
Policy->SuppressedCpu,
Policy->BackgroundSockets);
}
static bool TaskSuppressionGet(pid_t Pid, struct TaskSuppressionPolicyPrivate* Policy)
{
mach_port_t Task = MACH_PORT_NULL;
if (!GetTaskPolicyPortForPid(Pid, &Task))
{
return false;
}
memset(Policy, 0, sizeof(*Policy));
mach_msg_type_number_t Count = TASK_SUPPRESSION_POLICY_PRIVATE_COUNT;
boolean_t Defaulted = FALSE;
kern_return_t Kr = task_policy_get(Task,
TASK_SUPPRESSION_POLICY,
(task_policy_t)Policy,
&Count,
&Defaulted);
Logf("task-suppress pid=%d op=get flavor=%d kr=0x%x %s count=%u defaulted=%d",
Pid,
TASK_SUPPRESSION_POLICY,
Kr,
ReturnName(Kr),
Count,
Defaulted);
if (Kr == KERN_SUCCESS)
{
LogTaskSuppressionPolicy("get", Policy);
}
mach_port_deallocate(mach_task_self(), Task);
return Kr == KERN_SUCCESS;
}
static bool TaskSuppressionSet(pid_t Pid, bool Active)
{
mach_port_t Task = MACH_PORT_NULL;
if (!GetTaskPolicyPortForPid(Pid, &Task))
{
return false;
}
struct TaskSuppressionPolicyPrivate Policy;
FillTaskSuppressionPolicy(&Policy, Active);
LogTaskSuppressionPolicy(Active ? "set-active" : "set-inactive", &Policy);
kern_return_t Kr = task_policy_set(Task,
TASK_SUPPRESSION_POLICY,
(task_policy_t)&Policy,
TASK_SUPPRESSION_POLICY_PRIVATE_COUNT);
Logf("task-suppress pid=%d op=set active=%d flavor=%d kr=0x%x %s count=%u",
Pid,
Active ? 1 : 0,
TASK_SUPPRESSION_POLICY,
Kr,
ReturnName(Kr),
TASK_SUPPRESSION_POLICY_PRIVATE_COUNT);
mach_port_deallocate(mach_task_self(), Task);
return Kr == KERN_SUCCESS;
}
static int EncodeLatencyQosTier(int Tier)
{
if (Tier <= 0)
{
return Tier == 0 ? LATENCY_QOS_TIER_0 : LATENCY_QOS_TIER_UNSPECIFIED;
}
if (Tier == 1) return LATENCY_QOS_TIER_1;
if (Tier == 2) return LATENCY_QOS_TIER_2;
if (Tier == 3) return LATENCY_QOS_TIER_3;
if (Tier == 4) return LATENCY_QOS_TIER_4;
return LATENCY_QOS_TIER_5;
}
static int EncodeThroughputQosTier(int Tier)
{
if (Tier <= 0)
{
return Tier == 0 ? THROUGHPUT_QOS_TIER_0 : THROUGHPUT_QOS_TIER_UNSPECIFIED;
}
if (Tier == 1) return THROUGHPUT_QOS_TIER_1;
if (Tier == 2) return THROUGHPUT_QOS_TIER_2;
if (Tier == 3) return THROUGHPUT_QOS_TIER_3;
if (Tier == 4) return THROUGHPUT_QOS_TIER_4;
return THROUGHPUT_QOS_TIER_5;
}
static bool ParseQosTierToken(const char* Text, int* OutTier)
{
if (strcmp(Text, "unspecified") == 0 || strcmp(Text, "none") == 0 || strcmp(Text, "clear") == 0)
{
*OutTier = -1;
return true;
}
char* End = NULL;
errno = 0;
long Value = strtol(Text, &End, 0);
if (errno != 0 || End == Text || *End != '\0' || Value < 0 || Value > 5)
{
return false;
}
*OutTier = (int)Value;
return true;
}
static bool TaskQosGet(pid_t Pid, task_policy_flavor_t Flavor, const char* Label)
{
mach_port_t Task = MACH_PORT_NULL;
if (!GetTaskPolicyPortForPid(Pid, &Task))
{
return false;
}
struct task_qos_policy Policy;
memset(&Policy, 0, sizeof(Policy));
mach_msg_type_number_t Count = TASK_QOS_POLICY_COUNT;
boolean_t Defaulted = FALSE;
kern_return_t Kr = task_policy_get(Task,
Flavor,
(task_policy_t)&Policy,
&Count,
&Defaulted);
Logf("task-qos pid=%d op=get label=%s flavor=%d kr=0x%x %s count=%u defaulted=%d latency=0x%x throughput=0x%x",
Pid,
Label,
Flavor,
Kr,
ReturnName(Kr),
Count,
Defaulted,
Policy.task_latency_qos_tier,
Policy.task_throughput_qos_tier);
mach_port_deallocate(mach_task_self(), Task);
return Kr == KERN_SUCCESS;
}
static bool TaskQosSet(pid_t Pid, task_policy_flavor_t Flavor, const char* Label, int LatencyTier, int ThroughputTier)
{
mach_port_t Task = MACH_PORT_NULL;
if (!GetTaskPolicyPortForPid(Pid, &Task))
{
return false;
}
struct task_qos_policy Policy;
Policy.task_latency_qos_tier = EncodeLatencyQosTier(LatencyTier);
Policy.task_throughput_qos_tier = EncodeThroughputQosTier(ThroughputTier);
kern_return_t Kr = task_policy_set(Task,
Flavor,
(task_policy_t)&Policy,
TASK_QOS_POLICY_COUNT);
Logf("task-qos pid=%d op=set label=%s flavor=%d latency-tier=%d latency=0x%x throughput-tier=%d throughput=0x%x kr=0x%x %s",
Pid,
Label,
Flavor,
LatencyTier,
Policy.task_latency_qos_tier,
ThroughputTier,
Policy.task_throughput_qos_tier,
Kr,
ReturnName(Kr));
mach_port_deallocate(mach_task_self(), Task);
return Kr == KERN_SUCCESS;
}
static void CallTaskQosGet(pid_t Pid)
{
TaskQosGet(Pid, TASK_BASE_QOS_POLICY, "base");
TaskQosGet(Pid, TASK_OVERRIDE_QOS_POLICY, "override");
TaskQosGet(Pid, TASK_BASE_LATENCY_QOS_POLICY, "base-latency");
TaskQosGet(Pid, TASK_BASE_THROUGHPUT_QOS_POLICY, "base-throughput");
}
static void CallTaskQosOverrideSet(pid_t Pid, int LatencyTier, int ThroughputTier)
{
TaskQosGet(Pid, TASK_OVERRIDE_QOS_POLICY, "override-before");
TaskQosSet(Pid, TASK_OVERRIDE_QOS_POLICY, "override", LatencyTier, ThroughputTier);
TaskQosGet(Pid, TASK_OVERRIDE_QOS_POLICY, "override-after");
}
static bool DarwinPriorityGet(pid_t Pid, int Which, const char* Label, const NamedInt* Names)
{
errno = 0;
int Value = getpriority(Which, (id_t)Pid);
int SavedErrno = errno;
bool Ok = SavedErrno == 0;
Logf("darwin-priority pid=%d op=get label=%s which=%d result=%s value=%d value-name=%s errno=%d %s",
Pid,
Label,
Which,
Ok ? "ok" : "fail",
Value,
Ok ? NamedIntName(Names, Value) : "unreadable",
Ok ? 0 : SavedErrno,
Ok ? "none" : strerror(SavedErrno));
return Ok;
}
static bool DarwinPrioritySet(pid_t Pid, int Which, const char* Label, const NamedInt* Names, int Value)
{
errno = 0;
int Ret = setpriority(Which, (id_t)Pid, Value);
int SavedErrno = errno;
bool Ok = Ret == 0;
Logf("darwin-priority pid=%d op=set label=%s which=%d value=%d value-name=%s result=%s errno=%d %s",
Pid,
Label,
Which,
Value,
NamedIntName(Names, Value),
Ok ? "ok" : "fail",
Ok ? 0 : SavedErrno,
Ok ? "none" : strerror(SavedErrno));
return Ok;
}
static void CallDarwinProcessClear(pid_t Pid)
{
errno = 0;
int Ret = setpriority(PRIO_DARWIN_PROCESS, (id_t)Pid, 0);
int SavedErrno = errno;
Logf("darwin-priority pid=%d op=set label=process-clear which=%d value=0 result=%s errno=%d %s",
Pid,
PRIO_DARWIN_PROCESS,
Ret == 0 ? "ok" : "fail",
Ret == 0 ? 0 : SavedErrno,
Ret == 0 ? "none" : strerror(SavedErrno));
}
static void CallDarwinRoleGet(pid_t Pid)
{
DarwinPriorityGet(Pid, PRIO_DARWIN_ROLE, "darwin-role", kDarwinRoles);
}
static void CallDarwinRoleSet(pid_t Pid, int Value)
{
DarwinPriorityGet(Pid, PRIO_DARWIN_ROLE, "darwin-role-before", kDarwinRoles);
DarwinPrioritySet(Pid, PRIO_DARWIN_ROLE, "darwin-role", kDarwinRoles, Value);
DarwinPriorityGet(Pid, PRIO_DARWIN_ROLE, "darwin-role-after", kDarwinRoles);
}
static void CallGpuRoleGet(pid_t Pid)
{
DarwinPriorityGet(Pid, PRIO_DARWIN_GPU, "gpu-role", kGpuRoles);
}
static void CallGpuRoleSet(pid_t Pid, int Value)
{
DarwinPriorityGet(Pid, PRIO_DARWIN_GPU, "gpu-role-before", kGpuRoles);
DarwinPrioritySet(Pid, PRIO_DARWIN_GPU, "gpu-role", kGpuRoles, Value);
DarwinPriorityGet(Pid, PRIO_DARWIN_GPU, "gpu-role-after", kGpuRoles);
}
static void CallTaskSuppressGet(pid_t Pid)
{
struct TaskSuppressionPolicyPrivate Policy;
TaskSuppressionGet(Pid, &Policy);
}
static void CallTaskSuppressSet(pid_t Pid, bool Active)
{
struct TaskSuppressionPolicyPrivate Policy;
TaskSuppressionGet(Pid, &Policy);
TaskSuppressionSet(Pid, Active);
TaskSuppressionGet(Pid, &Policy);
}
static io_service_t GetService(const char* ClassName)
{
io_iterator_t Iterator = IO_OBJECT_NULL;
kern_return_t kr = IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching(ClassName), &Iterator);
if (kr != KERN_SUCCESS)
{
Logf("service=%s match kr=0x%x %s", ClassName, kr, ReturnName(kr));
return IO_OBJECT_NULL;
}
io_service_t Service = IOIteratorNext(Iterator);
IOObjectRelease(Iterator);
if (Service == IO_OBJECT_NULL)
{
Logf("service=%s not_found", ClassName);
}
return Service;
}
static bool OpenServiceType(const char* ClassName, uint32_t Type, io_connect_t* OutConnect)
{
*OutConnect = IO_OBJECT_NULL;
io_service_t Service = GetService(ClassName);
if (Service == IO_OBJECT_NULL)
{
return false;
}
kern_return_t kr = IOServiceOpen(Service, mach_task_self(), Type, OutConnect);
IOObjectRelease(Service);
Logf("open service=%s type=%u kr=0x%x %s connect=0x%x", ClassName, Type, kr, ReturnName(kr), *OutConnect);
return kr == KERN_SUCCESS;
}
static void CallCLPCWorkload(double Watts, uint64_t Option)
{
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType("AppleCLPC", 0, &Connect))
{
return;
}
uint64_t Scalars[3] = {
(uint64_t)(Watts * 1000.0),
(Option == 2) ? 5 : 9,
2
};
kern_return_t kr = IOConnectCallMethod(Connect, 2, Scalars, 3, NULL, 0, NULL, NULL, NULL, NULL);
Logf("call clpc-workload selector=2 watts=%.3f option=%llu scalars=(%llu,%llu,%llu) kr=0x%x %s",
Watts,
(unsigned long long)Option,
(unsigned long long)Scalars[0],
(unsigned long long)Scalars[1],
(unsigned long long)Scalars[2],
kr,
ReturnName(kr));
IOServiceClose(Connect);
}
static void CallCLPCTarget(uint64_t Target, double Watts, uint64_t Reason)
{
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType("AppleCLPC", 0, &Connect))
{
return;
}
uint64_t Scalars[3] = {
(uint64_t)(Watts * 1000.0),
Target,
Reason
};
kern_return_t kr = IOConnectCallMethod(Connect, 8, Scalars, 3, NULL, 0, NULL, 0, NULL, 0);
Logf("call clpc-target selector=8 target=%llu watts=%.3f reason=%llu scalars=(%llu,%llu,%llu) kr=0x%x %s",
(unsigned long long)Target,
Watts,
(unsigned long long)Reason,
(unsigned long long)Scalars[0],
(unsigned long long)Scalars[1],
(unsigned long long)Scalars[2],
kr,
ReturnName(kr));
IOServiceClose(Connect);
}
static void ScanPPMOpen(void)
{
for (uint32_t Type = 0; Type < 16; ++Type)
{
io_connect_t Connect = IO_OBJECT_NULL;
bool Opened = OpenServiceType("ApplePassthroughPPM", Type, &Connect);
if (Opened && Connect != IO_OBJECT_NULL)
{
IOServiceClose(Connect);
}
}
}
static void LogScalarArray(const char* Label, uint32_t Selector, const uint64_t* Values, uint32_t Count)
{
for (uint32_t i = 0; i < Count; ++i)
{
Logf("%s selector=%u index=%u value=0x%llx",
Label,
Selector,
i,
(unsigned long long)Values[i]);
}
}
static void LogStructBytes(const char* Label, uint32_t Selector, const void* Data, size_t Size)
{
const unsigned char* Bytes = (const unsigned char*)Data;
size_t Limit = Size < MAX_LOGGED_STRUCT_BYTES ? Size : MAX_LOGGED_STRUCT_BYTES;
char Hex[(MAX_LOGGED_STRUCT_BYTES * 2) + 1];
for (size_t i = 0; i < Limit; ++i)
{
snprintf(&Hex[i * 2], sizeof(Hex) - (i * 2), "%02x", Bytes[i]);
}
Hex[Limit * 2] = '\0';
Logf("%s selector=%u bytes=%zu first%zu=%s", Label, Selector, Size, Limit, Hex);
}
static void CallGenericMethodOnConnection(const char* ServiceName,
uint32_t OpenType,
io_connect_t Connect,
uint32_t Selector,
const uint64_t* InputScalars,
uint32_t InputScalarCount,
const void* InputStruct,
size_t InputStructSize,
uint32_t RequestedOutputScalars,
size_t RequestedOutputStructSize)
{
uint64_t OutputScalars[MAX_SCALARS] = {0};
unsigned char OutputStruct[MAX_STRUCT_BYTES] = {0};
uint32_t OutputScalarCount = RequestedOutputScalars > MAX_SCALARS ? MAX_SCALARS : RequestedOutputScalars;
size_t OutputStructSize = RequestedOutputStructSize > MAX_STRUCT_BYTES ? MAX_STRUCT_BYTES : RequestedOutputStructSize;
uint64_t* OutputScalarPtr = OutputScalarCount == 0 ? NULL : OutputScalars;
uint32_t* OutputScalarCountPtr = OutputScalarCount == 0 ? NULL : &OutputScalarCount;
void* OutputStructPtr = OutputStructSize == 0 ? NULL : OutputStruct;
size_t* OutputStructSizePtr = OutputStructSize == 0 ? NULL : &OutputStructSize;
kern_return_t kr = IOConnectCallMethod(Connect,
Selector,
InputScalarCount == 0 ? NULL : InputScalars,
InputScalarCount,
InputStructSize == 0 ? NULL : InputStruct,
InputStructSize,
OutputScalarPtr,
OutputScalarCountPtr,
OutputStructPtr,
OutputStructSizePtr);
Logf("call-method service=%s type=%u selector=%u input-scalars=%u input-struct=%zu requested-output-scalars=%u requested-output-struct=%zu kr=0x%x %s output-scalars=%u output-struct=%zu",
ServiceName,
OpenType,
Selector,
InputScalarCount,
InputStructSize,
RequestedOutputScalars,
RequestedOutputStructSize,
kr,
ReturnName(kr),
OutputScalarCount,
OutputStructSize);
LogScalarArray("call-method-input-scalar", Selector, InputScalars, InputScalarCount);
if (kr == KERN_SUCCESS)
{
LogScalarArray("call-method-output-scalar", Selector, OutputScalars, OutputScalarCount);
if (OutputStructSize > 0)
{
LogStructBytes("call-method-output-struct", Selector, OutputStruct, OutputStructSize);
}
}
}
static void CallGenericMethod(const char* ServiceName,
uint32_t OpenType,
uint32_t Selector,
const uint64_t* InputScalars,
uint32_t InputScalarCount,
const void* InputStruct,
size_t InputStructSize,
uint32_t RequestedOutputScalars,
size_t RequestedOutputStructSize)
{
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType(ServiceName, OpenType, &Connect))
{
return;
}
CallGenericMethodOnConnection(ServiceName,
OpenType,
Connect,
Selector,
InputScalars,
InputScalarCount,
InputStruct,
InputStructSize,
RequestedOutputScalars,
RequestedOutputStructSize);
IOServiceClose(Connect);
}
static void CallPPMSafeCPMSBatch(const uint64_t* Clients, uint32_t ClientCount)
{
static const uint64_t DefaultClients[] = {2, 5, 6, 7, 0};
if (ClientCount == 0)
{
Clients = DefaultClients;
ClientCount = (uint32_t)(sizeof(DefaultClients) / sizeof(DefaultClients[0]));
}
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType("ApplePassthroughPPM", 0, &Connect))
{
return;
}
Logf("ppm-safe-cpms-batch begin clients=%u", ClientCount);
for (uint32_t i = 0; i < ClientCount; ++i)
{
uint64_t InputScalars[1] = {Clients[i]};
Logf("ppm-safe-cpms-batch client=%llu selector=0x1d get-client-state",
(unsigned long long)Clients[i]);
CallGenericMethodOnConnection("ApplePassthroughPPM", 0, Connect, 0x1d, InputScalars, 1, NULL, 0, 0, 0x640);
Logf("ppm-safe-cpms-batch client=%llu selector=0x27 get-default-power-profile",
(unsigned long long)Clients[i]);
CallGenericMethodOnConnection("ApplePassthroughPPM", 0, Connect, 0x27, InputScalars, 1, NULL, 0, 0, 0x24);
Logf("ppm-safe-cpms-batch client=%llu selector=0x2d get-min-max-power-policy",
(unsigned long long)Clients[i]);
CallGenericMethodOnConnection("ApplePassthroughPPM", 0, Connect, 0x2d, InputScalars, 1, NULL, 0, 0, 0x28);
}
Logf("ppm-safe-cpms-batch selector=0x1e get-cpms-control-state");
CallGenericMethodOnConnection("ApplePassthroughPPM", 0, Connect, 0x1e, NULL, 0, NULL, 0, 0, 0x28c0);
IOServiceClose(Connect);
Logf("ppm-safe-cpms-batch end");
}
static void BuildDetailedThermalBudgetPayload(unsigned char Output[PPM_DETAILED_THERMAL_BUDGETS_BYTES],
uint8_t ClientId,
uint32_t Budget,
uint64_t Details)
{
uint32_t Count = 1;
memset(Output, 0, PPM_DETAILED_THERMAL_BUDGETS_BYTES);
Output[0] = ClientId;
memcpy(Output + 4, &Budget, sizeof(Budget));
memcpy(Output + 8, &Details, sizeof(Details));
memcpy(Output + PPM_DETAILED_THERMAL_BUDGETS_COUNT_OFFSET, &Count, sizeof(Count));
}
static bool ParseClientStateDetailedBudget(const unsigned char* State,
size_t StateSize,
uint8_t ClientId,
uint64_t Details,
uint32_t* OutBudget,
uint32_t* OutCount)
{
if (StateSize < PPM_CLIENT_STATE_DETAILED_BUDGET_ENTRY_OFFSET)
{
return false;
}
uint32_t Count = 0;
memcpy(&Count, State + PPM_CLIENT_STATE_DETAILED_BUDGET_COUNT_OFFSET, sizeof(Count));
if (OutCount)
{
*OutCount = Count;
}
if (Count > PPM_CLIENT_STATE_DETAILED_BUDGET_MAX)
{
return false;
}
for (uint32_t i = 0; i < Count; ++i)
{
size_t Offset = PPM_CLIENT_STATE_DETAILED_BUDGET_ENTRY_OFFSET + ((size_t)i * 16);
if (Offset + 16 > StateSize)
{
return false;
}
uint32_t Budget = 0;
uint64_t EntryDetails = 0;
memcpy(&Budget, State + Offset + 4, sizeof(Budget));
memcpy(&EntryDetails, State + Offset + 8, sizeof(EntryDetails));
if (State[Offset] == ClientId && EntryDetails == Details)
{
if (OutBudget)
{
*OutBudget = Budget;
}
return true;
}
}
return false;
}
static bool ReadPackageLaneBudgetOnConnection(io_connect_t Connect, uint64_t Details, uint32_t* OutBudget)
{
uint64_t InputScalars[1] = {PPM_PACKAGE_CLIENT_ID};
unsigned char OutputStruct[PPM_CLIENT_STATE_BYTES] = {0};
size_t OutputStructSize = sizeof(OutputStruct);
kern_return_t kr = IOConnectCallMethod(Connect,
PPM_SELECTOR_GET_CLIENT_STATE,
InputScalars,
1,
NULL,
0,
NULL,
NULL,
OutputStruct,
&OutputStructSize);
if (kr != KERN_SUCCESS)
{
Logf("ppm-package-lane-readback selector=0x%x kr=0x%x %s output-struct=%zu",
PPM_SELECTOR_GET_CLIENT_STATE,
kr,
ReturnName(kr),
OutputStructSize);
return false;
}
uint32_t Count = 0;
uint32_t Budget = 0;
bool Found = ParseClientStateDetailedBudget(OutputStruct,
OutputStructSize,
PPM_PACKAGE_CLIENT_ID,
Details,
&Budget,
&Count);
if (Found)
{
Logf("ppm-package-lane-readback client=%u details=0x%llx budget=%u count=%u",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Budget,
Count);
if (OutBudget)
{
*OutBudget = Budget;
}
}
else
{
Logf("ppm-package-lane-readback client=%u details=0x%llx not_found count=%u output-struct=%zu",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Count,
OutputStructSize);
}
return Found;
}
static kern_return_t SetPackageLaneBudgetOnConnection(io_connect_t Connect, uint32_t Budget, uint64_t Details)
{
unsigned char InputStruct[PPM_DETAILED_THERMAL_BUDGETS_BYTES];
BuildDetailedThermalBudgetPayload(InputStruct, PPM_PACKAGE_CLIENT_ID, Budget, Details);
kern_return_t kr = IOConnectCallMethod(Connect,
PPM_SELECTOR_SET_DETAILED_THERMAL_BUDGETS,
NULL,
0,
InputStruct,
sizeof(InputStruct),
NULL,
NULL,
NULL,
NULL);
Logf("ppm-package-lane-set selector=0x%x client=%u details=0x%llx budget=%u input-struct=%zu kr=0x%x %s",
PPM_SELECTOR_SET_DETAILED_THERMAL_BUDGETS,
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Budget,
sizeof(InputStruct),
kr,
ReturnName(kr));
return kr;
}
static void CallPPMPackageLaneSetOnce(uint32_t Budget, uint64_t Details)
{
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType("ApplePassthroughPPM", 0, &Connect))
{
return;
}
Logf("ppm-package-lane-set-once begin client=%u details=0x%llx budget=%u",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Budget);
ReadPackageLaneBudgetOnConnection(Connect, Details, NULL);
SetPackageLaneBudgetOnConnection(Connect, Budget, Details);
ReadPackageLaneBudgetOnConnection(Connect, Details, NULL);
IOServiceClose(Connect);
Logf("ppm-package-lane-set-once end");
}
static void CallPPMPackageLaneCycle(uint32_t Budget, uint32_t HoldSeconds, uint64_t Details)
{
if (HoldSeconds < 1)
{
Logf("ppm-package-lane-cycle hold-seconds clamped from %u to 1", HoldSeconds);
HoldSeconds = 1;
}
if (HoldSeconds > 60)
{
Logf("ppm-package-lane-cycle hold-seconds clamped from %u to 60", HoldSeconds);
HoldSeconds = 60;
}
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType("ApplePassthroughPPM", 0, &Connect))
{
return;
}
uint32_t InitialBudget = 0;
Logf("ppm-package-lane-cycle begin client=%u details=0x%llx budget=%u hold-seconds=%u",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Budget,
HoldSeconds);
if (!ReadPackageLaneBudgetOnConnection(Connect, Details, &InitialBudget))
{
Logf("ppm-package-lane-cycle abort no-initial-readback");
IOServiceClose(Connect);
Logf("ppm-package-lane-cycle end");
return;
}
kern_return_t SetKr = SetPackageLaneBudgetOnConnection(Connect, Budget, Details);
ReadPackageLaneBudgetOnConnection(Connect, Details, NULL);
if (SetKr == KERN_SUCCESS)
{
Logf("ppm-package-lane-cycle holding seconds=%u", HoldSeconds);
sleep(HoldSeconds);
ReadPackageLaneBudgetOnConnection(Connect, Details, NULL);
}
else
{
Logf("ppm-package-lane-cycle set failed; restore still attempted");
}
Logf("ppm-package-lane-cycle restore-initial budget=%u", InitialBudget);
SetPackageLaneBudgetOnConnection(Connect, InitialBudget, Details);
ReadPackageLaneBudgetOnConnection(Connect, Details, NULL);
IOServiceClose(Connect);
Logf("ppm-package-lane-cycle end");
}
typedef struct PackageLaneSessionControl
{
bool Stop;
bool HasBudget;
uint32_t Budget;
uint32_t Seq;
} PackageLaneSessionControl;
typedef struct PackageLaneSessionArgs
{
uint32_t Budget;
uint32_t MaxSeconds;
uint32_t PollMs;
uint64_t Details;
} PackageLaneSessionArgs;
static uint32_t ClampPackageLaneSessionBudget(uint32_t Budget)
{
if (Budget < PPM_PACKAGE_SESSION_MIN_BUDGET)
{
Logf("ppm-package-lane-session budget clamped from %u to %u",
Budget,
PPM_PACKAGE_SESSION_MIN_BUDGET);
return PPM_PACKAGE_SESSION_MIN_BUDGET;
}
if (Budget > PPM_PACKAGE_SESSION_MAX_BUDGET)
{
Logf("ppm-package-lane-session budget clamped from %u to %u",
Budget,
PPM_PACKAGE_SESSION_MAX_BUDGET);
return PPM_PACKAGE_SESSION_MAX_BUDGET;
}
return Budget;
}
static void WritePackageLaneSessionStatus(const char* Phase,
bool Active,
uint32_t InitialBudget,
uint32_t TargetBudget,
uint32_t ReadbackBudget,
uint32_t ElapsedSeconds,
uint32_t MaxSeconds,
uint32_t SetCount,
kern_return_t LastKr,
const char* Reason)
{
char TmpPath[256];
snprintf(TmpPath, sizeof(TmpPath), "%s.tmp", kPackageLaneSessionStatusPath);
FILE* Status = fopen(TmpPath, "w");
if (!Status)
{
Logf("ppm-package-lane-session status-open failed path=%s", TmpPath);
return;
}
fprintf(Status,
"{"
"\"phase\":\"%s\","
"\"active\":%s,"
"\"pid\":%d,"
"\"initial_budget\":%u,"
"\"target_budget\":%u,"
"\"readback_budget\":%u,"
"\"elapsed_seconds\":%u,"
"\"max_seconds\":%u,"
"\"set_count\":%u,"
"\"last_kr\":%d,"
"\"last_kr_name\":\"%s\","
"\"reason\":\"%s\","
"\"updated_at\":%lld"
"}\n",
Phase,
Active ? "true" : "false",
getpid(),
InitialBudget,
TargetBudget,
ReadbackBudget,
ElapsedSeconds,
MaxSeconds,
SetCount,
LastKr,
ReturnName(LastKr),
Reason ? Reason : "",
(long long)time(NULL));
fclose(Status);
if (rename(TmpPath, kPackageLaneSessionStatusPath) != 0)
{
Logf("ppm-package-lane-session status-rename failed");
unlink(TmpPath);
}
}
static bool ReadPackageLaneSessionControl(PackageLaneSessionControl* OutControl)
{
memset(OutControl, 0, sizeof(*OutControl));
FILE* Control = fopen(kPackageLaneSessionControlPath, "r");
if (!Control)
{
return false;
}
char Line[128];
while (fgets(Line, sizeof(Line), Control))
{
char Key[64] = {0};
unsigned long long Value = 0;
if (sscanf(Line, "%63[^=]=%llu", Key, &Value) != 2)
{
continue;
}
if (strcmp(Key, "stop") == 0)
{
OutControl->Stop = Value != 0;
}
else if (strcmp(Key, "budget") == 0)
{
OutControl->HasBudget = true;
OutControl->Budget = (uint32_t)Value;
}
else if (strcmp(Key, "seq") == 0)
{
OutControl->Seq = (uint32_t)Value;
}
}
fclose(Control);
return true;
}
static void* PackageLaneSessionThread(void* Context)
{
PackageLaneSessionArgs* Args = (PackageLaneSessionArgs*)Context;
uint32_t TargetBudget = ClampPackageLaneSessionBudget(Args->Budget);
uint32_t MaxSeconds = Args->MaxSeconds;
uint32_t PollMs = Args->PollMs;
uint64_t Details = Args->Details;
free(Args);
unlink(kPackageLaneSessionControlPath);
if (MaxSeconds < 1)
{
Logf("ppm-package-lane-session max-seconds clamped from %u to 1", MaxSeconds);
MaxSeconds = 1;
}
if (MaxSeconds > PPM_PACKAGE_SESSION_MAX_SECONDS)
{
Logf("ppm-package-lane-session max-seconds clamped from %u to %u",
MaxSeconds,
PPM_PACKAGE_SESSION_MAX_SECONDS);
MaxSeconds = PPM_PACKAGE_SESSION_MAX_SECONDS;
}
if (PollMs < PPM_PACKAGE_SESSION_MIN_POLL_MS)
{
Logf("ppm-package-lane-session poll-ms clamped from %u to %u",
PollMs,
PPM_PACKAGE_SESSION_MIN_POLL_MS);
PollMs = PPM_PACKAGE_SESSION_MIN_POLL_MS;
}
if (PollMs > PPM_PACKAGE_SESSION_MAX_POLL_MS)
{
Logf("ppm-package-lane-session poll-ms clamped from %u to %u",
PollMs,
PPM_PACKAGE_SESSION_MAX_POLL_MS);
PollMs = PPM_PACKAGE_SESSION_MAX_POLL_MS;
}
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType("ApplePassthroughPPM", 0, &Connect))
{
Logf("ppm-package-lane-session open failed");
WritePackageLaneSessionStatus("ended", false, 0, TargetBudget, 0, 0, MaxSeconds, 0, kIOReturnNoDevice, "open-failed");
return NULL;
}
time_t Start = time(NULL);
uint32_t InitialBudget = 0;
uint32_t ReadbackBudget = 0;
uint32_t SetCount = 0;
uint32_t LastControlSeq = 0;
uint32_t LastStatusSecond = UINT32_MAX;
kern_return_t LastKr = KERN_SUCCESS;
const char* EndReason = "timeout";
Logf("ppm-package-lane-session begin client=%u details=0x%llx budget=%u max-seconds=%u poll-ms=%u",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
TargetBudget,
MaxSeconds,
PollMs);
if (!ReadPackageLaneBudgetOnConnection(Connect, Details, &InitialBudget))
{
Logf("ppm-package-lane-session abort no-initial-readback");
IOServiceClose(Connect);
WritePackageLaneSessionStatus("ended", false, 0, TargetBudget, 0, 0, MaxSeconds, SetCount, kIOReturnNoDevice, "no-initial-readback");
Logf("ppm-package-lane-session end reason=no-initial-readback set-count=%u", SetCount);
return NULL;
}
ReadbackBudget = InitialBudget;
WritePackageLaneSessionStatus("starting", true, InitialBudget, TargetBudget, ReadbackBudget, 0, MaxSeconds, SetCount, LastKr, "");
LastKr = SetPackageLaneBudgetOnConnection(Connect, TargetBudget, Details);
++SetCount;
ReadPackageLaneBudgetOnConnection(Connect, Details, &ReadbackBudget);
WritePackageLaneSessionStatus("active", true, InitialBudget, TargetBudget, ReadbackBudget, 0, MaxSeconds, SetCount, LastKr, "");
for (;;)
{
time_t Now = time(NULL);
uint32_t Elapsed = (uint32_t)(Now - Start);
if (Elapsed >= MaxSeconds)
{
EndReason = "timeout";
break;
}
PackageLaneSessionControl Control;
if (ReadPackageLaneSessionControl(&Control))
{
if (Control.Stop)
{
EndReason = "stop-requested";
break;
}
if (Control.HasBudget && (Control.Seq != 0 || Control.Budget != TargetBudget))
{
if (Control.Seq == 0 || Control.Seq != LastControlSeq)
{
TargetBudget = ClampPackageLaneSessionBudget(Control.Budget);
LastControlSeq = Control.Seq;
LastKr = SetPackageLaneBudgetOnConnection(Connect, TargetBudget, Details);
++SetCount;
ReadPackageLaneBudgetOnConnection(Connect, Details, &ReadbackBudget);
WritePackageLaneSessionStatus("active", true, InitialBudget, TargetBudget, ReadbackBudget, Elapsed, MaxSeconds, SetCount, LastKr, "");
}
}
}
if (Elapsed != LastStatusSecond)
{
LastStatusSecond = Elapsed;
ReadPackageLaneBudgetOnConnection(Connect, Details, &ReadbackBudget);
WritePackageLaneSessionStatus("active", true, InitialBudget, TargetBudget, ReadbackBudget, Elapsed, MaxSeconds, SetCount, LastKr, "");
}
usleep((useconds_t)PollMs * 1000);
}
uint32_t Elapsed = (uint32_t)(time(NULL) - Start);
Logf("ppm-package-lane-session restore-initial budget=%u reason=%s", InitialBudget, EndReason);
WritePackageLaneSessionStatus("restoring", true, InitialBudget, TargetBudget, ReadbackBudget, Elapsed, MaxSeconds, SetCount, LastKr, EndReason);
LastKr = SetPackageLaneBudgetOnConnection(Connect, InitialBudget, Details);
++SetCount;
ReadPackageLaneBudgetOnConnection(Connect, Details, &ReadbackBudget);
IOServiceClose(Connect);
WritePackageLaneSessionStatus("ended", false, InitialBudget, InitialBudget, ReadbackBudget, Elapsed, MaxSeconds, SetCount, LastKr, EndReason);
Logf("ppm-package-lane-session end reason=%s set-count=%u", EndReason, SetCount);
return NULL;
}
static void StartPPMPackageLaneSession(uint32_t Budget, uint32_t MaxSeconds, uint32_t PollMs, uint64_t Details)
{
PackageLaneSessionArgs* Args = (PackageLaneSessionArgs*)calloc(1, sizeof(*Args));
if (!Args)
{
Logf("ppm-package-lane-session allocation failed");
return;
}
Args->Budget = Budget;
Args->MaxSeconds = MaxSeconds;
Args->PollMs = PollMs;
Args->Details = Details;
pthread_t Thread;
int rc = pthread_create(&Thread, NULL, PackageLaneSessionThread, Args);
if (rc != 0)
{
Logf("ppm-package-lane-session pthread_create failed rc=%d", rc);
free(Args);
return;
}
pthread_detach(Thread);
Logf("ppm-package-lane-session thread-started client=%u details=0x%llx budget=%u max-seconds=%u poll-ms=%u",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Budget,
MaxSeconds,
PollMs);
}
typedef struct PackageLanePinArgs
{
uint32_t Budget;
uint32_t Seconds;
uint32_t IntervalMs;
uint64_t Details;
} PackageLanePinArgs;
static void* PackageLanePinThread(void* Context)
{
PackageLanePinArgs* Args = (PackageLanePinArgs*)Context;
uint32_t Budget = Args->Budget;
uint32_t Seconds = Args->Seconds;
uint32_t IntervalMs = Args->IntervalMs;
uint64_t Details = Args->Details;
free(Args);
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType("ApplePassthroughPPM", 0, &Connect))
{
Logf("ppm-package-lane-pin open failed");
return NULL;
}
time_t Start = time(NULL);
uint32_t Iteration = 0;
uint32_t InitialBudget = 0;
bool HaveInitialBudget = false;
Logf("ppm-package-lane-pin begin client=%u details=0x%llx budget=%u seconds=%u interval-ms=%u",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Budget,
Seconds,
IntervalMs);
HaveInitialBudget = ReadPackageLaneBudgetOnConnection(Connect, Details, &InitialBudget);
for (;;)
{
time_t Now = time(NULL);
uint32_t Elapsed = (uint32_t)(Now - Start);
if (Seconds != 0 && Elapsed >= Seconds)
{
break;
}
Logf("ppm-package-lane-pin iteration=%u elapsed=%u", Iteration, Elapsed);
SetPackageLaneBudgetOnConnection(Connect, Budget, Details);
ReadPackageLaneBudgetOnConnection(Connect, Details, NULL);
++Iteration;
usleep((useconds_t)IntervalMs * 1000);
}
if (Seconds != 0 && HaveInitialBudget)
{
Logf("ppm-package-lane-pin restore-initial budget=%u", InitialBudget);
SetPackageLaneBudgetOnConnection(Connect, InitialBudget, Details);
}
else if (Seconds != 0)
{
Logf("ppm-package-lane-pin restore-initial skipped; no initial readback");
}
ReadPackageLaneBudgetOnConnection(Connect, Details, NULL);
IOServiceClose(Connect);
Logf("ppm-package-lane-pin end iterations=%u", Iteration);
return NULL;
}
static void StartPPMPackageLanePin(uint32_t Budget, uint32_t Seconds, uint32_t IntervalMs, uint64_t Details)
{
if (IntervalMs < 100)
{
Logf("ppm-package-lane-pin interval-ms clamped from %u to 100", IntervalMs);
IntervalMs = 100;
}
if (IntervalMs > 60000)
{
Logf("ppm-package-lane-pin interval-ms clamped from %u to 60000", IntervalMs);
IntervalMs = 60000;
}
PackageLanePinArgs* Args = (PackageLanePinArgs*)calloc(1, sizeof(*Args));
if (!Args)
{
Logf("ppm-package-lane-pin allocation failed");
return;
}
Args->Budget = Budget;
Args->Seconds = Seconds;
Args->IntervalMs = IntervalMs;
Args->Details = Details;
pthread_t Thread;
int rc = pthread_create(&Thread, NULL, PackageLanePinThread, Args);
if (rc != 0)
{
Logf("ppm-package-lane-pin pthread_create failed rc=%d", rc);
free(Args);
return;
}
pthread_detach(Thread);
Logf("ppm-package-lane-pin thread-started client=%u details=0x%llx budget=%u seconds=%u interval-ms=%u",
PPM_PACKAGE_CLIENT_ID,
(unsigned long long)Details,
Budget,
Seconds,
IntervalMs);
}
static void CallGenericZeroStructMethod(const char* ServiceName,
uint32_t OpenType,
uint32_t Selector,
const uint64_t* InputScalars,
uint32_t InputScalarCount,
size_t RequestedInputStructSize,
uint32_t RequestedOutputScalars,
size_t RequestedOutputStructSize,
unsigned char FillByte)
{
unsigned char InputStruct[MAX_STRUCT_BYTES];
size_t InputStructSize = RequestedInputStructSize > MAX_STRUCT_BYTES ? MAX_STRUCT_BYTES : RequestedInputStructSize;
memset(InputStruct, FillByte, InputStructSize);
CallGenericMethod(ServiceName,
OpenType,
Selector,
InputScalars,
InputScalarCount,
InputStructSize == 0 ? NULL : InputStruct,
InputStructSize,
RequestedOutputScalars,
RequestedOutputStructSize);
if (InputStructSize > 0)
{
LogStructBytes("call-method-input-struct", Selector, InputStruct, InputStructSize);
}
}
static void CallStructZeroMethod(const char* ServiceName,
uint32_t OpenType,
uint32_t Selector,
size_t RequestedInputStructSize,
size_t RequestedOutputStructSize,
unsigned char FillByte)
{
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType(ServiceName, OpenType, &Connect))
{
return;
}
unsigned char InputStruct[MAX_STRUCT_BYTES];
unsigned char OutputStruct[MAX_STRUCT_BYTES] = {0};
size_t InputStructSize = RequestedInputStructSize > MAX_STRUCT_BYTES ? MAX_STRUCT_BYTES : RequestedInputStructSize;
size_t OutputStructSize = RequestedOutputStructSize > MAX_STRUCT_BYTES ? MAX_STRUCT_BYTES : RequestedOutputStructSize;
memset(InputStruct, FillByte, InputStructSize);
kern_return_t kr = IOConnectCallStructMethod(Connect,
Selector,
InputStructSize == 0 ? NULL : InputStruct,
InputStructSize,
OutputStructSize == 0 ? NULL : OutputStruct,
OutputStructSize == 0 ? NULL : &OutputStructSize);
Logf("call-struct-zero service=%s type=%u selector=%u input-struct=%zu requested-output-struct=%zu fill=0x%02x kr=0x%x %s output-struct=%zu",
ServiceName,
OpenType,
Selector,
RequestedInputStructSize,
RequestedOutputStructSize,
FillByte,
kr,
ReturnName(kr),
OutputStructSize);
if (InputStructSize > 0)
{
LogStructBytes("call-struct-zero-input", Selector, InputStruct, InputStructSize);
}
if (kr == KERN_SUCCESS && OutputStructSize > 0)
{
LogStructBytes("call-struct-zero-output", Selector, OutputStruct, OutputStructSize);
}
IOServiceClose(Connect);
}
static void ScanStructZeroMethods(const char* ServiceName,
uint32_t OpenType,
uint32_t StartSelector,
uint32_t EndSelector,
size_t InputStructSize,
size_t OutputStructSize,
unsigned char FillByte)
{
for (uint32_t Selector = StartSelector; Selector <= EndSelector; ++Selector)
{
CallStructZeroMethod(ServiceName, OpenType, Selector, InputStructSize, OutputStructSize, FillByte);
}
}
static void ScanGenericZeroStructMethods(const char* ServiceName,
uint32_t OpenType,
uint32_t StartSelector,
uint32_t EndSelector,
const uint64_t* InputScalars,
uint32_t InputScalarCount,
size_t InputStructSize,
uint32_t OutputScalarCount,
size_t OutputStructSize,
unsigned char FillByte)
{
for (uint32_t Selector = StartSelector; Selector <= EndSelector; ++Selector)
{
CallGenericZeroStructMethod(ServiceName,
OpenType,
Selector,
InputScalars,
InputScalarCount,
InputStructSize,
OutputScalarCount,
OutputStructSize,
FillByte);
}
}
static void ScanScalarShapes(const char* ServiceName,
uint32_t OpenType,
uint32_t StartSelector,
uint32_t EndSelector,
uint32_t MaxInputScalars,
uint32_t MaxOutputScalars,
size_t OutputStructSize,
uint64_t FillValue)
{
uint64_t InputScalars[MAX_SCALARS] = {0};
uint32_t InputLimit = MaxInputScalars > MAX_SCALARS ? MAX_SCALARS : MaxInputScalars;
uint32_t OutputLimit = MaxOutputScalars > MAX_SCALARS ? MAX_SCALARS : MaxOutputScalars;
for (uint32_t i = 0; i < MAX_SCALARS; ++i)
{
InputScalars[i] = FillValue;
}
for (uint32_t Selector = StartSelector; Selector <= EndSelector; ++Selector)
{
for (uint32_t InputCount = 0; InputCount <= InputLimit; ++InputCount)
{
for (uint32_t OutputCount = 0; OutputCount <= OutputLimit; ++OutputCount)
{
CallGenericMethod(ServiceName,
OpenType,
Selector,
InputScalars,
InputCount,
NULL,
0,
OutputCount,
OutputStructSize);
}
}
}
}
static void CallNoInputMethod(const char* ServiceName, uint32_t OpenType, uint32_t Selector)
{
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType(ServiceName, OpenType, &Connect))
{
return;
}
kern_return_t kr = IOConnectCallMethod(Connect, Selector, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL);
Logf("call-no-input service=%s type=%u selector=%u kr=0x%x %s",
ServiceName,
OpenType,
Selector,
kr,
ReturnName(kr));
IOServiceClose(Connect);
}
static kern_return_t CallAGXPerfRecord(io_connect_t Connect,
const char* Label,
uint32_t Selector,
const unsigned char Input[8])
{
unsigned char Output[8] = {0};
size_t OutputSize = sizeof(Output);
kern_return_t kr = IOConnectCallStructMethod(Connect, Selector, Input, 8, Output, &OutputSize);
Logf("agx-perf-record label=%s selector=0x%x kr=0x%x %s output-struct=%zu",
Label,
Selector,
kr,
ReturnName(kr),
OutputSize);
LogStructBytes("agx-perf-input", Selector, Input, 8);
if (kr == KERN_SUCCESS)
{
LogStructBytes("agx-perf-output", Selector, Output, OutputSize);
}
return kr;
}
static void CallAGXPerfAssertCycle(const char* ServiceName, uint32_t OpenType, uint32_t Level, uint32_t HoldSeconds)
{
if (Level < 1 || Level > 3)
{
Logf("agx-perf-assert-cycle invalid-level=%u", Level);
return;
}
if (HoldSeconds > 30)
{
Logf("agx-perf-assert-cycle hold clamped from %u to 30", HoldSeconds);
HoldSeconds = 30;
}
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType(ServiceName, OpenType, &Connect))
{
return;
}
unsigned char AssertRecord[8] = {1, (unsigned char)Level, 0, 0, 0, 0, 0, 0};
unsigned char ReleaseRecord[8] = {1, 4, 0, 0, 0, 0, 0, 0};
unsigned char PerfQuery[8] = {2, 0, 0, 0, 0, 0, 0, 0};
unsigned char ConsistentQuery[8] = {3, 0, 0, 0, 0, 0, 0, 0};
Logf("agx-perf-assert-cycle begin service=%s type=%u level=%u hold-seconds=%u",
ServiceName,
OpenType,
Level,
HoldSeconds);
kern_return_t SetKr = CallAGXPerfRecord(Connect, "assert", AGX_SELECTOR_PERF_STATE, AssertRecord);
if (SetKr == KERN_SUCCESS)
{
CallAGXPerfRecord(Connect, "perf-query-after-assert", AGX_SELECTOR_PERF_STATE, PerfQuery);
CallAGXPerfRecord(Connect, "consistent-query-after-assert", AGX_SELECTOR_CONSISTENT_PERF_STATE, ConsistentQuery);
Logf("agx-perf-assert-cycle holding seconds=%u", HoldSeconds);
sleep(HoldSeconds);
CallAGXPerfRecord(Connect, "release", AGX_SELECTOR_PERF_STATE, ReleaseRecord);
CallAGXPerfRecord(Connect, "perf-query-after-release", AGX_SELECTOR_PERF_STATE, PerfQuery);
CallAGXPerfRecord(Connect, "consistent-query-after-release", AGX_SELECTOR_CONSISTENT_PERF_STATE, ConsistentQuery);
}
else
{
Logf("agx-perf-assert-cycle set failed; release skipped");
}
IOServiceClose(Connect);
Logf("agx-perf-assert-cycle end");
}
static void CallAGXPerfAssertHold(const char* ServiceName, uint32_t OpenType, uint32_t Level, uint32_t HoldSeconds)
{
if (Level < 1 || Level > 3)
{
Logf("agx-perf-assert-hold invalid-level=%u", Level);
return;
}
io_connect_t Connect = IO_OBJECT_NULL;
if (!OpenServiceType(ServiceName, OpenType, &Connect))
{
return;
}
unsigned char AssertRecord[8] = {1, (unsigned char)Level, 0, 0, 0, 0, 0, 0};
unsigned char PerfQuery[8] = {2, 0, 0, 0, 0, 0, 0, 0};
unsigned char ConsistentQuery[8] = {3, 0, 0, 0, 0, 0, 0, 0};
Logf("agx-perf-assert-hold begin service=%s type=%u level=%u hold-seconds=%u pid=%d",
ServiceName,
OpenType,
Level,
HoldSeconds,
getpid());
kern_return_t SetKr = CallAGXPerfRecord(Connect, "assert", AGX_SELECTOR_PERF_STATE, AssertRecord);
if (SetKr == KERN_SUCCESS)
{
CallAGXPerfRecord(Connect, "perf-query-after-assert", AGX_SELECTOR_PERF_STATE, PerfQuery);
CallAGXPerfRecord(Connect, "consistent-query-after-assert", AGX_SELECTOR_CONSISTENT_PERF_STATE, ConsistentQuery);
Logf("agx-perf-assert-hold active; stop by terminating this launchd service");
if (HoldSeconds == 0)
{
for (;;)
{
sleep(3600);
}
}
else
{
sleep(HoldSeconds);
}
}
else
{
Logf("agx-perf-assert-hold set failed");
}
IOServiceClose(Connect);
Logf("agx-perf-assert-hold end");
}
static void ScanNoInputMethods(const char* ServiceName, uint32_t OpenType, uint32_t MaxSelector)
{
for (uint32_t Selector = 0; Selector <= MaxSelector; ++Selector)
{
CallNoInputMethod(ServiceName, OpenType, Selector);
}
}
static void ScanPPMNoInputAllTypes(uint32_t MaxType, uint32_t MaxSelector)
{
for (uint32_t Type = 0; Type <= MaxType; ++Type)
{
ScanNoInputMethods("ApplePassthroughPPM", Type, MaxSelector);
}
}
__attribute__((constructor))
static void EntitledDirectEntry(void)
{
char Request[256];
ReadRequest(Request, sizeof(Request));
if (Request[0] == '\0')
{
Logf("loaded: no request");
return;
}
Logf("loaded request=\"%s\"", Request);
char Command[64] = {0};
double Watts = 0.0;
unsigned long long A = 0;
unsigned long long B = 0;
if (sscanf(Request, "%63s", Command) != 1)
{
Logf("parse failed");
return;
}
if (strcmp(Command, "clpc-workload") == 0)
{
unsigned long long Option = 0;
if (sscanf(Request, "%*s %lf %llu", &Watts, &Option) != 2)
{
Logf("parse clpc-workload failed");
return;
}
CallCLPCWorkload(Watts, Option);
return;
}
if (strcmp(Command, "clpc-target") == 0)
{
if (sscanf(Request, "%*s %llu %lf %llu", &A, &Watts, &B) != 3)
{
Logf("parse clpc-target failed");
return;
}
CallCLPCTarget(A, Watts, B);
return;
}
if (strcmp(Command, "ppm-open-scan") == 0)
{
ScanPPMOpen();
return;
}
if (strcmp(Command, "ppm-safe-cpms-batch") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[20] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
uint64_t Clients[MAX_SCALARS] = {0};
uint32_t ClientCount = 0;
for (size_t Arg = 1; Arg < Count && ClientCount < MAX_SCALARS; ++Arg)
{
Clients[ClientCount++] = ParseU64(Tokens[Arg]);
}
CallPPMSafeCPMSBatch(Clients, ClientCount);
return;
}
if (strcmp(Command, "ppm-package-lane-set-once") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[4] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 2)
{
Logf("parse ppm-package-lane-set-once failed; expected: ppm-package-lane-set-once <budget> [details]");
return;
}
uint32_t Budget = (uint32_t)ParseU64(Tokens[1]);
uint64_t Details = Count >= 3 ? ParseU64(Tokens[2]) : 0;
CallPPMPackageLaneSetOnce(Budget, Details);
return;
}
if (strcmp(Command, "ppm-package-lane-cycle") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[5] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 3)
{
Logf("parse ppm-package-lane-cycle failed; expected: ppm-package-lane-cycle <budget> <hold-seconds> [details]");
return;
}
uint32_t Budget = (uint32_t)ParseU64(Tokens[1]);
uint32_t HoldSeconds = (uint32_t)ParseU64(Tokens[2]);
uint64_t Details = Count >= 4 ? ParseU64(Tokens[3]) : 0;
CallPPMPackageLaneCycle(Budget, HoldSeconds, Details);
return;
}
if (strcmp(Command, "ppm-package-lane-session") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[6] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 4)
{
Logf("parse ppm-package-lane-session failed; expected: ppm-package-lane-session <budget> <max-seconds> <poll-ms> [details]");
return;
}
uint32_t Budget = (uint32_t)ParseU64(Tokens[1]);
uint32_t MaxSeconds = (uint32_t)ParseU64(Tokens[2]);
uint32_t PollMs = (uint32_t)ParseU64(Tokens[3]);
uint64_t Details = Count >= 5 ? ParseU64(Tokens[4]) : 0;
StartPPMPackageLaneSession(Budget, MaxSeconds, PollMs, Details);
return;
}
if (strcmp(Command, "ppm-package-lane-pin") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[6] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 4)
{
Logf("parse ppm-package-lane-pin failed; expected: ppm-package-lane-pin <budget> <seconds> <interval-ms> [details]");
return;
}
uint32_t Budget = (uint32_t)ParseU64(Tokens[1]);
uint32_t Seconds = (uint32_t)ParseU64(Tokens[2]);
uint32_t IntervalMs = (uint32_t)ParseU64(Tokens[3]);
uint64_t Details = Count >= 5 ? ParseU64(Tokens[4]) : 0;
StartPPMPackageLanePin(Budget, Seconds, IntervalMs, Details);
return;
}
if (strcmp(Command, "coalition-suppress-get") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[3] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 2)
{
Logf("parse coalition-suppress-get failed; expected: coalition-suppress-get <pid>");
return;
}
CallCoalitionSuppressGet((pid_t)ParseU64(Tokens[1]));
return;
}
if (strcmp(Command, "coalition-suppress-set") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[4] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
uint32_t Value = 0;
if (Count < 3 || !ParseCoalitionSuppressValue(Tokens[2], &Value))
{
Logf("parse coalition-suppress-set failed; expected: coalition-suppress-set <pid> <none|darwin-bg>");
return;
}
CallCoalitionSuppressSet((pid_t)ParseU64(Tokens[1]), Value);
return;
}
if (strcmp(Command, "task-suppress-get") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[3] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 2)
{
Logf("parse task-suppress-get failed; expected: task-suppress-get <pid>");
return;
}
CallTaskSuppressGet((pid_t)ParseU64(Tokens[1]));
return;
}
if (strcmp(Command, "task-suppress-set") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[4] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 3)
{
Logf("parse task-suppress-set failed; expected: task-suppress-set <pid> <active|inactive>");
return;
}
bool Active = false;
if (strcmp(Tokens[2], "active") == 0 || strcmp(Tokens[2], "on") == 0 || strcmp(Tokens[2], "1") == 0)
{
Active = true;
}
else if (strcmp(Tokens[2], "inactive") == 0 || strcmp(Tokens[2], "off") == 0 || strcmp(Tokens[2], "0") == 0)
{
Active = false;
}
else
{
Logf("parse task-suppress-set failed; invalid state=%s", Tokens[2]);
return;
}
CallTaskSuppressSet((pid_t)ParseU64(Tokens[1]), Active);
return;
}
if (strcmp(Command, "task-qos-get") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[3] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 2)
{
Logf("parse task-qos-get failed; expected: task-qos-get <pid>");
return;
}
CallTaskQosGet((pid_t)ParseU64(Tokens[1]));
return;
}
if (strcmp(Command, "task-qos-override-set") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[5] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
int LatencyTier = -1;
int ThroughputTier = -1;
if (Count < 4 ||
!ParseQosTierToken(Tokens[2], &LatencyTier) ||
!ParseQosTierToken(Tokens[3], &ThroughputTier))
{
Logf("parse task-qos-override-set failed; expected: task-qos-override-set <pid> <latency 0..5|none> <throughput 0..5|none>");
return;
}
CallTaskQosOverrideSet((pid_t)ParseU64(Tokens[1]), LatencyTier, ThroughputTier);
return;
}
if (strcmp(Command, "darwin-process-clear") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[3] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 2)
{
Logf("parse darwin-process-clear failed; expected: darwin-process-clear <pid>");
return;
}
CallDarwinProcessClear((pid_t)ParseU64(Tokens[1]));
return;
}
if (strcmp(Command, "darwin-role-get") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[3] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 2)
{
Logf("parse darwin-role-get failed; expected: darwin-role-get <pid>");
return;
}
CallDarwinRoleGet((pid_t)ParseU64(Tokens[1]));
return;
}
if (strcmp(Command, "darwin-role-set") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[4] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
int Value = 0;
if (Count < 3 || !ParseNamedInt(Tokens[2], kDarwinRoles, &Value))
{
Logf("parse darwin-role-set failed; expected: darwin-role-set <pid> <default|ui_focal|ui|non_ui|ui_non_focal|tal_launch|bg|user_init|0..7>");
return;
}
CallDarwinRoleSet((pid_t)ParseU64(Tokens[1]), Value);
return;
}
if (strcmp(Command, "gpu-role-get") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[3] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
if (Count < 2)
{
Logf("parse gpu-role-get failed; expected: gpu-role-get <pid>");
return;
}
CallGpuRoleGet((pid_t)ParseU64(Tokens[1]));
return;
}
if (strcmp(Command, "gpu-role-set") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[4] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
int Value = 0;
if (Count < 3 || !ParseNamedInt(Tokens[2], kGpuRoles, &Value))
{
Logf("parse gpu-role-set failed; expected: gpu-role-set <pid> <unknown|allow|deny|background|utility|ui_non_focal|ui|ui_focal|0..7>");
return;
}
CallGpuRoleSet((pid_t)ParseU64(Tokens[1]), Value);
return;
}
if (strcmp(Command, "ppm-noinput") == 0)
{
if (sscanf(Request, "%*s %llu %llu", &A, &B) != 2)
{
Logf("parse ppm-noinput failed; expected: ppm-noinput <type> <selector>");
return;
}
CallNoInputMethod("ApplePassthroughPPM", (uint32_t)A, (uint32_t)B);
return;
}
if (strcmp(Command, "ppm-noinput-scan") == 0)
{
if (sscanf(Request, "%*s %llu %llu", &A, &B) != 2)
{
Logf("parse ppm-noinput-scan failed; expected: ppm-noinput-scan <type> <max-selector>");
return;
}
ScanNoInputMethods("ApplePassthroughPPM", (uint32_t)A, (uint32_t)B);
return;
}
if (strcmp(Command, "ppm-noinput-scan-all") == 0)
{
if (sscanf(Request, "%*s %llu %llu", &A, &B) != 2)
{
Logf("parse ppm-noinput-scan-all failed; expected: ppm-noinput-scan-all <max-type> <max-selector>");
return;
}
ScanPPMNoInputAllTypes((uint32_t)A, (uint32_t)B);
return;
}
if (strcmp(Command, "service-noinput") == 0)
{
char ServiceName[64] = {0};
if (sscanf(Request, "%*s %63s %llu %llu", ServiceName, &A, &B) != 3)
{
Logf("parse service-noinput failed; expected: service-noinput <service> <type> <selector>");
return;
}
CallNoInputMethod(ServiceName, (uint32_t)A, (uint32_t)B);
return;
}
if (strcmp(Command, "service-noinput-scan") == 0)
{
char ServiceName[64] = {0};
if (sscanf(Request, "%*s %63s %llu %llu", ServiceName, &A, &B) != 3)
{
Logf("parse service-noinput-scan failed; expected: service-noinput-scan <service> <type> <max-selector>");
return;
}
ScanNoInputMethods(ServiceName, (uint32_t)A, (uint32_t)B);
return;
}
if (strcmp(Command, "agx-perf-assert-cycle") == 0)
{
char ServiceName[64] = {0};
unsigned long long Type = 0;
unsigned long long Level = 0;
unsigned long long HoldSeconds = 0;
if (sscanf(Request, "%*s %63s %llu %llu %llu", ServiceName, &Type, &Level, &HoldSeconds) != 4)
{
Logf("parse agx-perf-assert-cycle failed; expected: agx-perf-assert-cycle <service> <type> <level> <hold-seconds>");
return;
}
CallAGXPerfAssertCycle(ServiceName, (uint32_t)Type, (uint32_t)Level, (uint32_t)HoldSeconds);
return;
}
if (strcmp(Command, "agx-perf-assert-hold") == 0)
{
char ServiceName[64] = {0};
unsigned long long Type = 0;
unsigned long long Level = 0;
unsigned long long HoldSeconds = 0;
if (sscanf(Request, "%*s %63s %llu %llu %llu", ServiceName, &Type, &Level, &HoldSeconds) != 4)
{
Logf("parse agx-perf-assert-hold failed; expected: agx-perf-assert-hold <service> <type> <level> <hold-seconds>");
return;
}
CallAGXPerfAssertHold(ServiceName, (uint32_t)Type, (uint32_t)Level, (uint32_t)HoldSeconds);
return;
}
if (strcmp(Command, "ppm-scalars") == 0 || strcmp(Command, "service-scalars") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[24] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
bool HasService = strcmp(Command, "service-scalars") == 0;
size_t Base = HasService ? 6 : 5;
if (Count < Base)
{
Logf("parse %s failed; expected: %s",
Command,
HasService ? "service-scalars <service> <type> <selector> <out-scalars> <out-struct-bytes> [scalar...]"
: "ppm-scalars <type> <selector> <out-scalars> <out-struct-bytes> [scalar...]");
return;
}
const char* ServiceName = HasService ? Tokens[1] : "ApplePassthroughPPM";
size_t Arg = HasService ? 2 : 1;
uint32_t OpenType = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t Selector = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t OutScalars = (uint32_t)ParseU64(Tokens[Arg++]);
size_t OutStructBytes = (size_t)ParseU64(Tokens[Arg++]);
uint64_t InputScalars[MAX_SCALARS] = {0};
uint32_t InputScalarCount = 0;
while (Arg < Count && InputScalarCount < MAX_SCALARS)
{
InputScalars[InputScalarCount++] = ParseU64(Tokens[Arg++]);
}
CallGenericMethod(ServiceName, OpenType, Selector, InputScalars, InputScalarCount, NULL, 0, OutScalars, OutStructBytes);
return;
}
if (strcmp(Command, "ppm-method-zero") == 0 || strcmp(Command, "service-method-zero") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[28] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
bool HasService = strcmp(Command, "service-method-zero") == 0;
size_t Minimum = HasService ? 8 : 7;
if (Count < Minimum)
{
Logf("parse %s failed; expected: %s",
Command,
HasService ? "service-method-zero <service> <type> <selector> <in-struct> <out-scalars> <out-struct> <fill-byte> [scalar...]"
: "ppm-method-zero <type> <selector> <in-struct> <out-scalars> <out-struct> <fill-byte> [scalar...]");
return;
}
const char* ServiceName = HasService ? Tokens[1] : "ApplePassthroughPPM";
size_t Arg = HasService ? 2 : 1;
uint32_t OpenType = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t Selector = (uint32_t)ParseU64(Tokens[Arg++]);
size_t InputBytes = (size_t)ParseU64(Tokens[Arg++]);
uint32_t OutScalars = (uint32_t)ParseU64(Tokens[Arg++]);
size_t OutStructBytes = (size_t)ParseU64(Tokens[Arg++]);
unsigned char FillByte = (unsigned char)ParseU64(Tokens[Arg++]);
uint64_t InputScalars[MAX_SCALARS] = {0};
uint32_t InputScalarCount = 0;
while (Arg < Count && InputScalarCount < MAX_SCALARS)
{
InputScalars[InputScalarCount++] = ParseU64(Tokens[Arg++]);
}
CallGenericZeroStructMethod(ServiceName,
OpenType,
Selector,
InputScalars,
InputScalarCount,
InputBytes,
OutScalars,
OutStructBytes,
FillByte);
return;
}
if (strcmp(Command, "ppm-method-hex") == 0 || strcmp(Command, "service-method-hex") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[16] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
bool HasService = strcmp(Command, "service-method-hex") == 0;
size_t Minimum = HasService ? 7 : 6;
if (Count < Minimum)
{
Logf("parse %s failed; expected: %s",
Command,
HasService ? "service-method-hex <service> <type> <selector> <out-scalars> <out-struct> <hex-struct>"
: "ppm-method-hex <type> <selector> <out-scalars> <out-struct> <hex-struct>");
return;
}
const char* ServiceName = HasService ? Tokens[1] : "ApplePassthroughPPM";
size_t Arg = HasService ? 2 : 1;
uint32_t OpenType = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t Selector = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t OutScalars = (uint32_t)ParseU64(Tokens[Arg++]);
size_t OutStructBytes = (size_t)ParseU64(Tokens[Arg++]);
unsigned char InputStruct[MAX_STRUCT_BYTES] = {0};
size_t InputStructSize = 0;
if (!ParseHexBytes(Tokens[Arg], InputStruct, sizeof(InputStruct), &InputStructSize))
{
Logf("parse %s failed; invalid hex struct", Command);
return;
}
CallGenericMethod(ServiceName,
OpenType,
Selector,
NULL,
0,
InputStructSize == 0 ? NULL : InputStruct,
InputStructSize,
OutScalars,
OutStructBytes);
if (InputStructSize > 0)
{
LogStructBytes("call-method-input-struct", Selector, InputStruct, InputStructSize);
}
return;
}
if (strcmp(Command, "ppm-method-scan-zero") == 0 || strcmp(Command, "service-method-scan-zero") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[28] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
bool HasService = strcmp(Command, "service-method-scan-zero") == 0;
size_t Minimum = HasService ? 9 : 8;
if (Count < Minimum)
{
Logf("parse %s failed; expected: %s",
Command,
HasService ? "service-method-scan-zero <service> <type> <start-selector> <end-selector> <in-struct> <out-scalars> <out-struct> <fill-byte> [scalar...]"
: "ppm-method-scan-zero <type> <start-selector> <end-selector> <in-struct> <out-scalars> <out-struct> <fill-byte> [scalar...]");
return;
}
const char* ServiceName = HasService ? Tokens[1] : "ApplePassthroughPPM";
size_t Arg = HasService ? 2 : 1;
uint32_t OpenType = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t StartSelector = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t EndSelector = (uint32_t)ParseU64(Tokens[Arg++]);
size_t InputBytes = (size_t)ParseU64(Tokens[Arg++]);
uint32_t OutScalars = (uint32_t)ParseU64(Tokens[Arg++]);
size_t OutStructBytes = (size_t)ParseU64(Tokens[Arg++]);
unsigned char FillByte = (unsigned char)ParseU64(Tokens[Arg++]);
uint64_t InputScalars[MAX_SCALARS] = {0};
uint32_t InputScalarCount = 0;
while (Arg < Count && InputScalarCount < MAX_SCALARS)
{
InputScalars[InputScalarCount++] = ParseU64(Tokens[Arg++]);
}
ScanGenericZeroStructMethods(ServiceName,
OpenType,
StartSelector,
EndSelector,
InputScalars,
InputScalarCount,
InputBytes,
OutScalars,
OutStructBytes,
FillByte);
return;
}
if (strcmp(Command, "ppm-struct-zero") == 0 || strcmp(Command, "service-struct-zero") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[16] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
bool HasService = strcmp(Command, "service-struct-zero") == 0;
size_t Minimum = HasService ? 6 : 5;
if (Count < Minimum)
{
Logf("parse %s failed; expected: %s",
Command,
HasService ? "service-struct-zero <service> <type> <selector> <in-bytes> <out-bytes> [fill-byte]"
: "ppm-struct-zero <type> <selector> <in-bytes> <out-bytes> [fill-byte]");
return;
}
const char* ServiceName = HasService ? Tokens[1] : "ApplePassthroughPPM";
size_t Arg = HasService ? 2 : 1;
uint32_t OpenType = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t Selector = (uint32_t)ParseU64(Tokens[Arg++]);
size_t InputBytes = (size_t)ParseU64(Tokens[Arg++]);
size_t OutputBytes = (size_t)ParseU64(Tokens[Arg++]);
unsigned char FillByte = Arg < Count ? (unsigned char)ParseU64(Tokens[Arg]) : 0;
CallStructZeroMethod(ServiceName, OpenType, Selector, InputBytes, OutputBytes, FillByte);
return;
}
if (strcmp(Command, "ppm-struct-scan-zero") == 0 || strcmp(Command, "service-struct-scan-zero") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[16] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
bool HasService = strcmp(Command, "service-struct-scan-zero") == 0;
size_t Minimum = HasService ? 7 : 6;
if (Count < Minimum)
{
Logf("parse %s failed; expected: %s",
Command,
HasService ? "service-struct-scan-zero <service> <type> <start-selector> <end-selector> <in-bytes> <out-bytes> [fill-byte]"
: "ppm-struct-scan-zero <type> <start-selector> <end-selector> <in-bytes> <out-bytes> [fill-byte]");
return;
}
const char* ServiceName = HasService ? Tokens[1] : "ApplePassthroughPPM";
size_t Arg = HasService ? 2 : 1;
uint32_t OpenType = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t StartSelector = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t EndSelector = (uint32_t)ParseU64(Tokens[Arg++]);
size_t InputBytes = (size_t)ParseU64(Tokens[Arg++]);
size_t OutputBytes = (size_t)ParseU64(Tokens[Arg++]);
unsigned char FillByte = Arg < Count ? (unsigned char)ParseU64(Tokens[Arg]) : 0;
ScanStructZeroMethods(ServiceName, OpenType, StartSelector, EndSelector, InputBytes, OutputBytes, FillByte);
return;
}
if (strcmp(Command, "ppm-scalar-shape-scan") == 0 || strcmp(Command, "service-scalar-shape-scan") == 0)
{
char ParseBuffer[256];
strncpy(ParseBuffer, Request, sizeof(ParseBuffer) - 1);
ParseBuffer[sizeof(ParseBuffer) - 1] = '\0';
char* Tokens[16] = {0};
size_t Count = Tokenize(ParseBuffer, Tokens, sizeof(Tokens) / sizeof(Tokens[0]));
bool HasService = strcmp(Command, "service-scalar-shape-scan") == 0;
size_t Minimum = HasService ? 8 : 7;
if (Count < Minimum)
{
Logf("parse %s failed; expected: %s",
Command,
HasService ? "service-scalar-shape-scan <service> <type> <start-selector> <end-selector> <max-in-scalars> <max-out-scalars> <out-struct-bytes> [fill]"
: "ppm-scalar-shape-scan <type> <start-selector> <end-selector> <max-in-scalars> <max-out-scalars> <out-struct-bytes> [fill]");
return;
}
const char* ServiceName = HasService ? Tokens[1] : "ApplePassthroughPPM";
size_t Arg = HasService ? 2 : 1;
uint32_t OpenType = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t StartSelector = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t EndSelector = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t MaxInputScalars = (uint32_t)ParseU64(Tokens[Arg++]);
uint32_t MaxOutputScalars = (uint32_t)ParseU64(Tokens[Arg++]);
size_t OutputBytes = (size_t)ParseU64(Tokens[Arg++]);
uint64_t FillValue = Arg < Count ? ParseU64(Tokens[Arg]) : 0;
ScanScalarShapes(ServiceName,
OpenType,
StartSelector,
EndSelector,
MaxInputScalars,
MaxOutputScalars,
OutputBytes,
FillValue);
return;
}
if (strcmp(Command, "clear") == 0)
{
Logf("clear requested: no persistent direct state to clear");
return;
}
Logf("unknown command=\"%s\"", Command);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment