Measure time a task spends between 2 points in linux (task profiling)

对着背影说爱祢 提交于 2019-12-22 09:48:49

问题


I'll soon start banging my head on the wall:

It's very simple really, I want to measure the time a task spends between 2 points (in Linux - 1 core - 1 CPU). During this time the task must have total control over the CPU and NOT get interrupted by any other task or HW interrupts.

To achieve this, I'v created a kernel module to make sure the above criterions are met. In this kernel module I've tried to:

First, disable IRQs:

  • I've used spin_lock_irqsave()/spin_lock_irqrestore() - Which i presume is the right way to be sure that all local interrupts are disabled and my task has the cpu for it self during the critical region.

Then,

  • Used preempt_disable() -> Since current = my task, then logically the kernel should continue running my task until I re-enable preemption -> Does not work (my_task->nvcsw and my_task->nivcsw show that a csw has occurred -> my-task got preempted)

I've tried to increase the priority of my task by changing my_task->prio and my_task->static_prio to 1 -> highest real-time prio (my_task->policy = SCHED_FIFO)...

Did not work either (my_task->nvcsw and my_task->nivcsw show that a csw has occurred -> my-task got preempted) and my_task->prio got a new prio (120) by the scheduler I presume....

Is there any way to deterministically garantee that a task does not get interrupted/preeempted in Linux? Is there any way to force the scheduler to run a task (for a short time 50-500us) until it's done?

Here is my code to enable/disable parts of the OS (the task in question sends a enable/disable commands before and after the critical region using procfs and handled by this switch):

// Handle request
switch( enable ){
    // Disable OS
    case COS_OS_DISABLE:
                    // Disable preemption
                    preempt_disable()
        // Save policy
        last_policy         = pTask->policy;
        // Save task priorities
        last_prio       = pTask->prio;
        last_static_prio    = pTask->static_prio;
        last_normal_prio    = pTask->normal_prio;
        last_rt_priority    = pTask->rt_priority;
        // Set priorities to highest real time prio 
        pTask->prio         = 1;
        pTask->static_prio  = 1;
        pTask->normal_prio  = 1;
        pTask->rt_priority  = 1;
        // Set scheduler policy to FIFO
        pTask->policy       = SCHED_FIFO;
        // Lock kernel: It will disable interrupts _locally_, but the spinlock itself will guarantee the global lock, so it will guarantee that there is only one thread-of-control within the region(s) protected by that lock.
        spin_lock_irqsave( &mr_lock , flags );
        break;
    // Default: Enable OS always
    case COS_OS_ENABLE:
    default:
        // Reset task priorities
        pTask->prio         = last_prio;
        pTask->static_prio  = last_static_prio;
        pTask->normal_prio  = last_normal_prio;
        pTask->rt_priority  = last_rt_priority;
        // Reset scheduler policy
        pTask->policy       = last_policy;
        // Unlock kernel
        spin_unlock_irqrestore( &mr_lock , flags );
                    // Enable preemption
                    preempt_enable();
        break;
}

回答1:


Disabling interrupts is allowed only for kernel code, and only for a short time. With the stock kernel, it is not possible to give a user-space task total control of the CPU.

If you want to measure only the time used by your user-space task, you could run your task normally and use the u modifer of perf to ignore interrupts; however, this would not prevent any cache effects of the interrupt handlers.



来源:https://stackoverflow.com/questions/21704386/measure-time-a-task-spends-between-2-points-in-linux-task-profiling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!