Call PAPI_start() and PAPI_stop() in different functions? - c

Usally PAPI is used like this:
Initialize Lib
Add Event(s)
PAPI_start()
someCalculation()
PAPI_stop()
However, I have an application which times code like this:
start = time()
someCalculation()
t = time() - start;
I want to override this time() function, which is in another file. My code:
static int INIT=0;
int retval;
static int eventSet = PAPI_NULL;
long long res[1];
if(INIT){
// eventSet is NOT PAPI_NULL here!
if ((retval = PAPI_stop(eventSet, res)) != PAPI_OK)
handle_error(retval);
return res[0]/1e9;
}
INIT = 1;
retval = PAPI_library_init(PAPI_VER_CURRENT);
if ((retval = PAPI_create_eventset(&eventSet)) != PAPI_OK)
handle_error(retval);
if ((retval = PAPI_add_named_event(eventSet, (char *) "rapl:::PP0_ENERGY:PACKAGE0")) != PAPI_OK)
handle_error(retval);
if ((retval = PAPI_start(eventSet)) != PAPI_OK)
handle_error(retval);
return 0.0;
When running the application I get PAPI error -9: EventSet is currently not running from PAPI_stop().
I assumed that it would be sufficient to share the eventSet variable between the two runs of the function.
Unfortunately this doesn't seem to work as the event is not running when PAPI_stop() is called.
Is there any chance to fix this?

What happens when you call your timer the third time? You stopped the events already. You need to rethink your design, perhaps use PAPI_read – Anycorn

Related

UEFI - EDK2 - Hooking SetVariable results in UNEXCEPTED_KERNEL_MODE_TRAP

I'm coding a UEFI Runtime Driver for Windows which hooks gRT->SetVariable(...)
Hooking seems to work fine but whenever I startup a user-mode application and call SetFirmwareEnvironmentVariable(...) it reults in a Bluescreen saying UNEXCEPTED_KERNEL_MODE_TRAP.
I cannot find any solution for this. Here are a few things iam aware of:
I'm raising TPL
I recalculate and set CRC32
On SetVirtualAddressMap(...) i convert all my pointer
Google didn't help at all. So i really wonder what causes this Bluescreen and how i may proceed to resolve this issue.
What am i missing? Am i doing something wrong?
Here is my code:
ExchangePointerInServiceTable((VOID**)&gST->RuntimeServices->SetVariable,
(VOID*)HookedSetVariable,
(VOID**)&gOriginalSetVariable);
static
EFI_STATUS
ExchangePointerInServiceTable(
IN OUT VOID** AddressToUpdate,
IN VOID* NewPointer,
OUT VOID** OriginalPointer OPTIONAL
)
{
EFI_STATUS status;
EFI_TPL tpl;
ASSERT(*AddressToUpdate != NewPointer);
tpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);
if (OriginalPointer != NULL)
{
*OriginalPointer = *AddressToUpdate;
}
*AddressToUpdate = NewPointer;
gST->Hdr.CRC32 = 0;
status = gBS->CalculateCrc32(&gST->Hdr, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
ASSERT_EFI_ERROR(status);
gBS->RestoreTPL(tpl);
return status;
}
EFI_STATUS
EFIAPI
HookedSetVariable(
IN CHAR16* VariableName,
IN EFI_GUID* VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID* Data
) {
if (StrCmp(VariableName, gStrComVarName) == 0) {
COMMUNICATION_PROTOCOL * comVarPtr = (COMMUNICATION_PROTOCOL*)Data;
switch (comVarPtr->i8OperationId) {
case COMMUNICATION_PROTOCOL_OPERATION_PING:
comVarPtr->i8OperationId = COMMUNICATION_PROTOCOL_PONG;
}
CopyMem(Data, comVarPtr, DataSize);
}
return gOriginalSetVariable(VariableName, VendorGuid, Attributes, DataSize, Data);
}
Edit: While in UEFI, other UEFI Applications correctly call the hooked SetVariable(...) without any further problems.
This may bring it down to the problem only existing after VirtualAddressSpace has been created from the OS.

Measure wall clock time before and after a function

I am measuring wall time through the use of clock_gettime() found in . It works perfectly fine when i use it in main() but not the way i am attempting to use it.
I am familiarizing myself with the linux scheduler and i am measuring performance on different parts.
I want to be able to measure Waiting time which is defined by "the total time a thread spends in the ready queue" (how long until it starts executing the function).
Easily enough i can measure this by setting a clock_gettime() before the thread function and another right inside the function. However the problem i am having is that the time inside the thread function is lower than the one outside, giving us a negative time.
I am running this on my windows pc through ubuntu.
what could the problem be?
code:
clock_gettime(CLOCK_REALTIME,&data.before);
thread_array[i-1] = data;
if(pthread_create(&tids[i],&attr,workLoad,(void*) &data) != 0){
perror("Could not create thread");
return 1;
}
}
for(int i = 1;i < threadAmount; i++){
if(pthread_join(tids[i],NULL)!= 0){
perror("Thread could not wait");
return 1;
}
}
and here is my threadfunc:
void *workLoad(void *args)
{
threadData* data = (threadData*) args;
clock_gettime(CLOCK_REALTIME,&data->after);
int loopAmount = data->loopAmount;
int counter = 0;
for(int i = 0; i < loopAmount; i++){
counter++;
}
return NULL;
}
result of time intervall
In the following code:
clock_gettime(CLOCK_REALTIME,&data.before);
thread_array[i-1] = data;
if(pthread_create(&tids[i],&attr,workLoad,(void*) &data) != 0){
data seems to be a local variable whose address you pass to the thread. You also copy this variable into thread_array[i-1]. If you then do thread_array[i-1].after - thread_array[i-1].before then that means that the thread updates a wrong variable. You need to pass &thread_array[i-1] to that thread, e.g.:
if(pthread_create(&tids[i],&attr,workLoad,(void*)&thread_array[i-1]) != 0){

PsGetContextThread returning C0000005(ACCESS_VIOLATION)

I'm trying to use an undocumented function called PsGetContextThread to retrieve the context of a usermode thread from a driver, I know this is possible from usermode but I have my reasons to do this from the kernel and this is not negotiable so please do not sidetrack into that. Now back on topic, the code below when debugged contains a valid thread and everything looks good to me, but it returns invalid with error code C0000005 which is ACCESS_VIOLATION but I do not know how this code could trigger that and would love some help to figure this out as I have been stuck for quite a while on this.
NTSTATUS GetThreadContext(PETHREAD thread) {
KPROCESSOR_MODE mode = UserMode;
CONTEXT context;
UNICODE_STRING setContextString, getContextString;
pPsGetContextThread PsGetContextThread;
NTSTATUS status = STATUS_SUCCESS;
RtlInitUnicodeString(&getContextString, L"PsGetContextThread");
RtlZeroMemory(&context, sizeof(CONTEXT));
PsGetContextThread = (pPsGetContextThread)MmGetSystemRoutineAddress(&getContextString);
context.ContextFlags = CONTEXT_FULL;
status = PsGetContextThread(thread, &context, mode);
if (!NT_SUCCESS(status)) {
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
If anyone knows what to try next or got any suggestions please do post below.
yes, #HarryJohnston right that when we specifying UserMode PsGetContextThread check that &context is a valid user-mode pointer. so we need pass valid user mode pointer for this. we can get it by call ZwAllocateVirtualMemory - use this code - this is works
NTSTATUS GetThreadContext(PETHREAD thread, PCONTEXT ctx)
{
#if 0
typedef NTSTATUS (NTAPI* GETSETCONTEXTTHREAD)(PETHREAD, PCONTEXT,MODE);
static GETSETCONTEXTTHREAD PsGetContextThread;
static BOOLEAN bInit;
if (!bInit)
{
STATIC_UNICODE_STRING(aPsGetContextThread, "PsGetContextThread");
PsGetContextThread = (GETSETCONTEXTTHREAD)MmGetSystemRoutineAddress(&aPsGetContextThread);
bInit = TRUE;
}
if (!PsGetContextThread)
{
return STATUS_PROCEDURE_NOT_FOUND;
}
#endif
CONTEXT * BaseAddress = 0;
SIZE_T Size = sizeof(CONTEXT);
NTSTATUS status = ZwAllocateVirtualMemory(NtCurrentProcess(), (void**)&BaseAddress, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
if (0 <= status)
{
BaseAddress->ContextFlags = ctx->ContextFlags;
if (0 <= (status = PsGetContextThread(thread, BaseAddress, UserMode)))
{
memcpy(ctx, BaseAddress, sizeof(CONTEXT));
}
ZwFreeVirtualMemory(NtCurrentProcess(), (void**)&BaseAddress, &Size, MEM_RELEASE);
}
return status;
}
and think you not need use MmGetSystemRoutineAddress but static import PsGetContextThread, but if you anyway want get this pointer in runtime - not need do this every time - but only once. make pointer to function static
You confused the third parameter - it does not state whether you fetch User mode thread context or Kernel mode thread context, it only implies whether the original call was made from User or Kernel mode. As such you don't need to call the function with user mode and copy data from user to kernel. Simply call it with KernelMode and use kernel memory.
NTSTATUS GetThreadContext(PETHREAD thread, PCONTEXT ctx)
{
#if 0
typedef NTSTATUS (NTAPI* GETSETCONTEXTTHREAD)(PETHREAD, PCONTEXT,MODE);
static GETSETCONTEXTTHREAD PsGetContextThread = NULL;
if (NULL == PsGetContextThread )
{
STATIC_UNICODE_STRING(aPsGetContextThread, "PsGetContextThread");
PsGetContextThread = (GETSETCONTEXTTHREAD)MmGetSystemRoutineAddress(&aPsGetContextThread);
}
if (NULL == PsGetContextThread)
{
return STATUS_PROCEDURE_NOT_FOUND;
}
#endif
return PsGetContextThread(thread, ctx, KernelMode);
}

Global exception handler (access violations) under Windows

I'm trying to install some sort of first-chance exception handler which can resume execution after unprotecting (VirtualProtect()) the memory page.
(I'm trying to install some watchpoints; and no, the possibility of the VirtualAlloc function to set watchpoints is not what I need; there I cannot dynamically set and unset the watching state of memory regions/pages)
I've read in the last couple of days a lot about these SEH things, but actually most I can find is for setting function local exception handlers etc....
If I'm not wrong I need to set somehow something called FS[0] (which is thread-local?).
tl;dr
I'd like to know how to install a global first-chance (= possibility to resume code and retry last instruction) exception handler which can catch hardware exceptions (like access violations).
P.s.: I can use Assembly, C or C++, but no C# etc.
Note: I have the whole thing working under POSIX systems via sigaction on SIGSEGV, but there's no such thing for Windows as far as I can see…
#include <windows.h>
#include <stdio.h>
int xfilter(EXCEPTION_POINTERS *xp) {
int rc;
EXCEPTION_RECORD *xr = xp->ExceptionRecord;
CONTEXT *xc = xp->ContextRecord;
if(xr->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
++xc->Eip;//Advanced by one(Probably xc->Eip += 2)//http://msdn.microsoft.com/en-us/library/ms679284(v=vs.85).aspx
rc = EXCEPTION_CONTINUE_EXECUTION;
} else {
rc = EXCEPTION_CONTINUE_SEARCH;
}
return rc;
}
int main() {
EXCEPTION_POINTERS * xp;
char *p = NULL;
__try {
fprintf(stderr, "%s", "before\n");
*p = 'X';//Access Violation
fprintf(stderr, "%s", "after\n");
}
__except(xfilter(xp = GetExceptionInformation())) {
fprintf(stderr, "%s", "Exception occurred\n");//NO EXECUTE WHEN EXCEPTION_CONTINUE_EXECUTION
}
return 0;
}
/* result
before
after
*/

Suspend/Resume all user processes - Is that possible?

I have PC's with a lot of applications running at once, i was thinking is it possible to SUSPEND all applications, i want to do that to run periodically one other application that is using a lot the CPU so want it to have all the processor time.
The thing is i want to suspend all applications run my thing that uses the CPU a lot, then when my thingy exit, to resume all applications and all work to be resumed fine....
Any comments are welcome.
It's possible but not recommended at all.
Set the process and thread priority so your application will be given a larger slice of the CPU.
This also means it won't kill the desktop, any network connections, antivirus, start menu, the window manager, etc as your method will.
You could possibly keep a list that you yourself manually generate of programs that are too demanding (say, for (bad) example, Steam.exe, chrome.exe, 90GB-video-game.exe, etc). Basically, you get the entire list of all running processes, search that list for all of the blacklisted names, and NtSuspendProcess/NtResumeProcess (should you need to allow it to run again in the future).
I don't believe suspending all user processes is a good idea. Much of those are weirdly protected and probably should remain running, anyway, and it's an uphill battle with very little to gain.
As mentioned in another answer, you can of course just adjust your processes priority up if you have permission to do so. This sorts the OS-wide process list in favor of your process, so you get CPU time first.
Here's an example of something similar to your original request. I'm writing a program in C++ that needed this exact feature, so I figured I'd help out. This will find Steam.exe or chrome.exe, and suspend the first one it finds for 10 seconds.. then will resume it. This will show as "not responding" on Windows if you try to interact with the window whilst it's suspended. Some applications may not like being suspended, YMMV.
/*Find, suspend, resume Win32 C++
*Written by jimmio92. No rights reserved. Public domain.
*NO WARRANTY! NO LIABILITY! (obviously)
*/
#include <windows.h>
#include <psapi.h>
typedef LONG (NTAPI *NtSuspendProcess)(IN HANDLE ProcessHandle);
typedef LONG (NTAPI *NtResumeProcess)(IN HANDLE ProcessHandle);
NtSuspendProcess dSuspendProcess = nullptr;
NtResumeProcess dResumeProcess = nullptr;
int get_the_pid() {
DWORD procs[4096], bytes;
int out = -1;
if(!EnumProcesses(procs, sizeof(procs), &bytes)) {
return -1;
}
for(size_t i = 0; i < bytes/sizeof(DWORD); ++i) {
TCHAR name[MAX_PATH] = "";
HMODULE mod;
HANDLE p = nullptr;
bool found = false;
p = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, procs[i]);
if(p == nullptr)
continue;
DWORD unused_bytes_for_all_modules = 0;
if(EnumProcessModules(p, &mod, sizeof(mod), &unused_bytes_for_all_modules)) {
GetModuleBaseName(p, mod, name, sizeof(name));
//change this to use an array of names or whatever fits your need better
if(strcmp(name, "Steam.exe") == 0 || strcmp(name, "chrome.exe") == 0) {
out = procs[i];
found = true;
}
}
CloseHandle(p);
if(found) break;
}
return out;
}
void suspend_process_by_id(int pid) {
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(h == nullptr)
return;
dSuspendProcess(h);
CloseHandle(h);
}
void resume_process_by_id(int pid) {
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(h == nullptr)
return;
dResumeProcess(h);
CloseHandle(h);
}
void init() {
//load NtSuspendProcess from ntdll.dll
HMODULE ntmod = GetModuleHandle("ntdll");
dSuspendProcess = (NtSuspendProcess)GetProcAddress(ntmod, "NtSuspendProcess");
dResumeProcess = (NtResumeProcess)GetProcAddress(ntmod, "NtResumeProcess");
}
int main() {
init();
int pid = get_the_pid();
if(pid < 0) {
printf("Steam.exe and chrome.exe not found");
}
suspend_process_by_id(pid);
//wait ten seconds for demonstration purposes
Sleep(10000);
resume_process_by_id(pid);
return 0;
}

Resources