I'd like to figure out how to schedule a real ISR on normal win32 architecture (not Windows CE!)
Is it possible?
What do you mean by schedule? You can hook a Hardware interrupt (and you should save and call the old hook in most cases); you can trigger a HW interrupt manually - but there consequences when handling those; you can hook one of the timer int's, and implement a scheduling mechanism, but AFAIK you can't "schedule an ISR".
Related
I need to use workqueue-like feature on Mac OSX (kernel mode driver) and am looking for a way to add work into a queue to be processed by a kernel thread later. Conceptually this is the same thing as workqueue feature available in Linux kernel. Is there something similar on XNU kernel as well?
I don't think there's a direct equivalent as such, although I admit I'm not intimately familiar with the Linux side, so I'll avoid comparing and just tell you about what's available on macOS/xnu.
I/O Kit IOWorkLoops
If you're building an I/O Kit driver, and especially if you're writing a secondary interrupt handler, you'll be using IOWorkLoops. Interrupts are abstracted by IOEventSource objects, which schedule secondary interrupt handlers to run on the driver's IOWorkLoop.
Each IOWorkLoop wraps one kernel thread and also provides a serialisation/locking mechanism for resources shared with that thread. All jobs submitted to a workloop either explicitly through an IOCommandGate or the workloop object directly, or as a result of an IOEventSource event will be serialised. Note that IOCommandGate jobs will run synchronously on the calling thread, not the workloop thread.
As always with macOS/OSX internals, you will want to look at the header file comments and possibly the implementation in the xnu source for details. I personally find IOWorkLoops a bit clumsy for some tasks, but if you're dealing with PCI devices, etc. you don't really have a choice.
thread_call
A more lightweight background work mechanism is the thread_call API. It's defined in <kern/thread_call.h> and supports running functions on an OS-managed background thread, optionally after a delay or with a specific priority. This is probably closer to what you know from Linux, has a fairly straightforward API, but is not suitable for secondary interrupt handlers.
I am trying to understand Asynchronous Interrupt handling in kernel, ofcourse through the legendary Understanding the Linux Kernel.
In this process how and who will trigger Kernel Interrupt Handler?
I would like some one to help me correcting this and to clarify my question on
1)How and Who trigger Kernel Interrupt Handler?
2)How to define new or change existing hardware interrupt handlers?
Thank you in Advance!
This picture from Robert Love's "Linux Kernel Development" pretty well describes path of interrupt. Processor interrupts the kernel in the predefined enty point do_IRQ(). If there is corresponding interrupt handler, it will get executed.
To handle interrupt, you should register your interrupt handler with request_irq().
I'm new to Linux device drivers writing and I'm trying to make a device driver that handles an UART chip. For this I decided to use work ques as my bottom half processing because I have to use some semaphores when handling the data that I get from the UART chip.
A work queue handler that was scheduled earlier in an interrupt now gets executed and during it's execution it will sleep at a semaphore. During this time the interrupt handler is called again and schedules the same work queue handler. Will the work queue handler be executed again before the first execution of it finishes ?
Thanks.
The default behavior of work queues is to allow concurrent execution on different CPUs. There is a flag WQ_NON_REENTRANT that changes this behavior. More information can be found in this post http://lwn.net/Articles/403891/
But it seems that in recent kernels work queues are non-reentrant by default - see
http://lwn.net/Articles/511190
Every device driver book talks about not using functions that sleep in interrupt routines.
What issues occur by calling these functions from ISRs ?
A total lockdown of the kernel is the issue here. The kernel is in interrupt context when executing interrupt handlers, that is, the interrupt handler is not associated with any process (the current macro cannot be used).
If you are able to sleep, you would never be able to get back to the interrupted code, since the scheduler would not know how to get back to it.
Holding a lock in the interrupt handler, and then sleeping, allowing another process to run and then entering the interrupt handler again and trying to re-acquire the lock would deadlock the kernel.
If you try to read more about how the scheduling in the kernel works, you will soon realize why sleeping is a no go in certain contexts.
I am spawning few threads inside ioctl call to my driver. I am also assigning kernel affinity to my driver. I want to ensure one of the thread does not get scheduled out till a particular event is flagged by the other thread. Is there any way to not allow windows scheduler to context out my thread. Using _disable() may hang the system as event may take couple of seconds.
Environment is windows 7,64bit
Thanks,
What you are probably after is a spin lock. However this is probably a bad idea unless you can guarantee that your driver/application is always run on a multi-processor system, even then it is still very bad practice. On a single processor system if a thread spin locks then the other thread signalling the spin locked thread will never be scheduled and so can't signal your event. Spin locks are meant to be used sparingly and only when the lock is for a very short time, never a couple of seconds.
It sounds like you need to use an event or other signally mechanism to synchronise your threads and let the windows scheduler do its job. If you need to respond to an event very quickly then interrupts or a Deferred Procedure Call (DPC) could be used instead.