Is it safe to call getrawmonotonic() in Linux interrupt handler? - linux-kernel

I did some research online, and people suggest using getrawmonotonic to get timestamp in kernel. Now I need to get time stamp in ISR, just wondering if it's safe. The Linux kernel version is 2.6.34.
Thanks

Yes, it is safe to use getrawmonotonic in interrupt handler.
Implementation of that function (in kernel/time/timekeeping.c) uses seqlock functionality(read_seqbegin(), read_seqretry calls), which is interrupt-safe, and timespec_add_ns() call, which is just arithmetic operation.

Related

How do_async_page_fault is called?

I was looking into linux internals of how interrupts are handled by kernel. I couldn't find the way do_async_page_fault api is called. As far as my understanding goes, this is stored as function pointer and called when interrupt occurs. can you explain exactly how?

How to use delays in kernel driver ISR

I am aware that I certainly can't use msleep or usleep or any such function for introducing delays in a kernel ISR routine.
I have a kernel driver which have certain ISRs defined inside it. In one of the ISR block I have to insert a certain delay of order of millisecs. Lets say:
{
//A
//here I need sleep
//B
}
can I use something like:
{
//A
for(i=0;i<1000;i++);
//B
}
Lets say my processor is executing at 1Gbps, will the above for loop give me a delay of 1000 usecs, i.e. 1ms?
You must not sleep inside an interrupt handler.
Furthermore, you should wait for a long time inside an interrupt handler; this would block all proccesses and all other interrupts on the same CPU.
If you driver needs to do two things at different times, it should use a second interrupt or a timer to do the second thing.
I would be interested to hear about the reasons for having an intentional delay in an ISR. Generally speaking, it's a no-no. If you think you need one, then most probably it means that you need to rethink your code design.
As for introducing microscopic delays, one thing that I have used is cpu_relax(). This function is also used in the kernel to implement the above mentioned udelay() and ndelay() for some CPU architectures. I would advise you to take a look and see where and how this function is used in the Linux kernel. That might give you some ideas for your specific situation.
Functions udelay and ndelay implements busy-waiting delays, so you may use them in ISR. As suggested by Tsyvarev.

Calling schedule() inside Linux IRQ

I'm making an emulation driver that requires me to call schedule() in ATOMIC contexts in order to make the emulation part work. For now I have this hack that allows me to call schedule() inside ATOMIC (e.g. spinlock) context:
int p_count = current_thread_info()->preempt_count;
current_thread_info()->preempt_count = 0;
schedule();
current_thread_info()->preempt_count = p_count;
But that doesn't work inside IRQs, the system just stops afer calling schedule().
Is there any way to hack the kernel in a way to allow me to do it? I'm using Linux kernel 4.2.1 with User Mode Linux
In kernel code you can be either in interrupt context or in process context.
When you are in interrupt context, you cannot call any blocking function (e.g., schedule()) or access the current pointer. That's related to how the kernel is designed and there is no way for having such functionalities in interrupt context. See also this answer.
Depending on what is your purpose, you can find some strategy that allows you to reach your goal. To me, it sounds strange that you have to call schedule() explicitly instead of relying on the natural kernel flow.
One possible approach follows (but, again, it depends on your specific goal). Form the IRQ you can schedule the work on a work queue through schedule_work(). The work queue, in fact, by design, executes kernel code in process context. From there, you are allowed to call blocking functions and access the current process data.

BUG: Scheduling while atomic .... using sysfs_notify()

I have a kernel module that uses hrtimers to notify userspace when the timer has fired. I understand I can just use userspace timers, but it is emulating a driver that will actually talk to hardware in the future. Every once in a while I get a BUG: Scheduling while atomic. After doing some research I am assuming that the hrtimer.function that I register as a callback, is being called from an interrupt routine by the kernel internals (making my callback function in an "Atomic Context"). Then when I call sysfs_notify() within the callback, I get the kernel bug, because sysfs_notify() acquires a mutex.
1) Is this a correct assumption?
If this is correct, I have seen that there is a function called sys_notify_dirent() that I can use to notify userspace from an atomic context. But according to this source:
http://linux.derkeiler.com/Mailing-Lists/Kernel/2009-10/msg07510.html
It can only be called from a "process" context, and not an interrupt context (due to the spinlock).
2) Could someone explain the difference between process, interrupt, and atomic context?
3) If this cannot be used in an interrupt context, what is an alternative to notifying userspace in this context?
Correct, sysfs_notify() cannot be called from atomic context. And yes, sysfs_notify_dirent() appears to be safe to call from atomic context. The source you cite is a bug report that notices in an old kernel version that statement wasn't actually true, along with a patch to fix it. It now appears to be safe to call.
Follow the source code in gpiolib_sysfs.c, and you'll notice that sysfs_notify_dirent() eventually calls schedule_work(), which defers the actual call to sysfs_notify(), which is exactly what the comments to your question are advising you to do. It's just wrapped inside the convenience function.

Linux UART driver - debugging time taken for __init call

I am a bit new to the Linux kernel and our team is trying to optimize the boot-up time for the device. It was observed that 8250 UART driver takes more than 1 second to complete the __init call. Using printk's and going by the generated console time-stamps prefixed to every log message, I was able to narrow down the function call which takes the extra time:
ret = platform_driver_register(&serial8250_isa_driver);
Being a novice, I was unsure about what more could I do from a debugging standpoint to track down the issue ? I am looking for pointers/suggestions from some of the experienced Kernel developers out there.. Just curious as to what other approach would the Kernel developers, use from their "Debugging Toolbox" ?
Thanks,
Vijay
If I understand correct, the register function is doing stuff with that struct (maybe polling addresses or something). You would need to see if any of the functions defined within are being called by register.
To more answer your question, does the platform you're running on have an 8250 ISA UART? If not, that could well explain why it's taking so long to init (it's timing out).

Resources