1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980open!Coreopen!Asyncletbitn=Int63.of_int(1lsln)letconfigurable_psb_period=bit0letkernel_tracing=bit1letkcore=bit2letsnapshot_on_exit=bit3includeFlags.Make(structletallow_intersecting=falseletshould_print_error=trueletremove_zero_flags=falseletknown=[configurable_psb_period,"configurable_psb_period";kernel_tracing,"kernel_tracing";kcore,"kcore"];;end)moduleVersion=structtypet={major:int;minor:int}[@@derivingsexp_of,compare]letcreate~major~minor={major;minor}letof_perf_version_string_exnversion_string=tryScanf.sscanfversion_string"perf version %d.%d"(funmajorminor->{major;minor})with|Scanf.Scan_failure_|End_of_file->raise_s[%message"unable to interpret perf version string"(version_string:string)];;endletsupports_configurable_psb_period()=letcyc_cap=In_channel.read_all"/sys/bus/event_source/devices/intel_pt/caps/psb_cyc"inString.(=)cyc_cap"1\n";;letsupports_tracing_kernel()=(* Only allow tracing the kernel if we are root. `perf` will start even without this,
but the generated traces will be broken, so disallow it here.
This check is technically stricter than it has to be. We could query the capability
bits of the perf binary here instead, as per
<https://perf.wiki.kernel.org/index.php/Perf_tools_support_for_Intel%C2%AE_Processor_Trace#Adding_capabilities_to_perf> *)Int.(Core_unix.geteuid()=0);;letkernel_version_at_least~major~minorversion=Int.(Version.compareversion(Version.create~major~minor)>=0);;(* Added in kernel commit eeb399b, which made it into 5.5. *)letsupports_kcore=kernel_version_at_least~major:5~minor:5(* Added in kernel commit ce7b0e4, which made it into 5.4. *)letsupports_snapshot_on_exit=kernel_version_at_least~major:5~minor:4letdetect_exn()=let%bindperf_version_proc=Process.create_exn~prog:"perf"~args:["--version"]()inlet%mapversion_string=Reader.contents(Process.stdoutperf_version_proc)inletversion=Version.of_perf_version_string_exnversion_stringinletset_ifboolflagcap=cap+ifboolthenflagelseemptyinempty|>set_if(supports_configurable_psb_period())configurable_psb_period|>set_if(supports_tracing_kernel())kernel_tracing|>set_if(supports_kcoreversion)kcore|>set_if(supports_snapshot_on_exitversion)snapshot_on_exit;;