say I have some code as follows:
local_irq_disable();
... // some interrupts come during this time
local_irq_enable();
after I called local_irq_enable(), all interrupts blocked(pending interrupts) are still there & cause the cpu to respond.
Is there anything will clear pending interrupts?
my code runs on an ARM aarch64 machine.
A typical chain is that the cpu interrupt pin is multiplexed via an interrupt controller (ex. GIC) to a set of devices.
Disabling interrupts merely shunts the pin on the CPU, the interrupt controller still maintains the pending state. You could use a feature on the interrupt controller to mask all interrupts, which would permit you to then enable the CPU interrupts without receiving any. Not really sure the point in that, when you could just leave the CPU ignoring interrupts.
To truly clear the pending interrupts, you need to invoke the device specific code (ie. interrupt handler) for each device with a pending interrupt. You could look through the status bits of the GIC, identify each pending interrupt, then look through the kernel's interrupt structure to determine the relevant device and invoke its handler. It is a lot easier to just turn interrupts back on.
If you disable interrupts, there will probably be a pending interrupt that's been sent to your CPU from the PIC that it's waiting for you to acknowledge. So before you re-enable interrupts, you'd have to tell the PIC to de-assert this interrupt if present.
While the PIC was waiting for acknowledgment, it may have been buffering other interrupts (or sending them to other CPUs). So you'd need to tell the PIC to clear these if present, or wait a sufficient amount of time for other CPUs to handle all these interrupts. This is assuming of course that the interrupts are being distributed evenly and no interrupt is biased towards your CPU.
Related
Assuming I set the process to the highest possible priority and there is no swap...
What's the longest time that a thread, which is blocking on receiving from an RS232 serial port, can take to wake up?
I want to know whether the thread will be woken within microseconds of the UART interrupt hitting the kernel, or whether it will have to wait for the next 100ms timeslice on a CPU.
What's the longest time that a thread, which is blocking on receiving from an RS232 serial port, can take to wake up?
Depending on the mode (e.g. canonical) a process could wait forever (e.g. for the EOL character).
I want to know whether the thread will be woken within microseconds of the UART interrupt hitting the kernel, or
The end of frame (i.e. the stop bit) on the wire is a better (i.e. consistent) reference point.
"UART interrupt hitting the kernel" is a poor reference point considering interrupt generation and processing can be deferred.
A UART FIFO may not generate an interrupt for every character/byte.
The interrupt controller prioritizes pending interrupts, and UARTs are rarely assigned high priorities.
Software can disable interrupts for critical regions.
whether it will have to wait for the next 100ms timeslice on a CPU.
The highest-priority runable process gets control after a syscall completes.
Reference: Linux Kernel Development: Preemption and Context Switching:
Consequently, whenever the kernel is preparing to return to user-space, either
on return from an interrupt or after a system call, the value of need_resched
is checked. If it is set, the scheduler is invoked to select a new (more fit)
process to execute.
I'm looking to minimise Linux serial latency between the received stop bit and the start bit of the reply from a high-priority userspace thread.
I suspected that is what you are really seeking.
Configuration of the serial terminal is crucial for minimizing such latency, e.g. research the ASYNC_LOW_LATENCY serial flag.
However configuration of the Linux kernel can further improve/minimize such latency, e.g. this developer reports a magnitude reduction from millisecs to only ~100 microsec.
I'm only familiar with serial interfaces on ATMEGA and STM32 microcontrollers ...
Then be sure to review Linux serial drivers.
Consider a very old single-core CPU that does not support hardware interrupts, and let's say I want to write a multi-tasked operating system. Using a hardware timer, one can poll an IRQ line in order to determine whether the timer has elapsed, and if so then switch threads/processes.
However, in order to be able to poll, the kernel has to have execution attention by the CPU. For a CPU that supports hardware interrupts, an ISR is called upon an interrupt and (correct me if I'm wrong) if the interrupt is by the context-switch timer, the appropriate ISR calls the kernel code that handles context switching.
If a CPU does not support hardware interrupts (again, correct me if I'm wrong), then the kernel has to repeatedly check for interrupts and the appropriate ISR is called in kernel space.
But, if a user thread is currently in execution on this hypothetical processor, the thread has to manually yield execution to the kernel for it to be able check whether the context-switch is due according to the timer through the appropriate IRQ line. This can be done by calling an appropriate kernel function.
Is there a way to implement non-cooperative multithreading on a single-core processor that only supports software interrupts? Are my thoughts correct, or am I missing something?
Well, you are generally correct that the kernel can't do multitasking until it gains control of the CPU. That happens via an interrupt or when user code makes a system call.
The timer interrupt, in particular, is used for preemptive time slicing. I think it would be pretty hard to find a whole CPU that didn't support a timer interrupt, that you didn't have to program with punch cards or switches. Interrupts are much older than multiple cores or virtual memory or DMA or anything fancy at all.
Some SoCs have real time sub-components that have this sort of restriction (like Beaglebone), and it might come up if you were coding a small CPU in an FPGA or something.
Without interrupts, you have to wait for system calls, which basically becomes cooperative multitasking.
In linux, when net card receive a packet, would trigger a hard interrupt, and then in the interrupt call back function, it will raise a NET_RX_SOFTIRQ, would this softirq run at the same cpu with hard irq?
An interrupt request (IRQ) is a request for service, sent at the hardware level. Interrupts can be sent by either a dedicated hardware line, or across a hardware bus as an information packet (a Message Signaled Interrupt, or MSI).
When interrupts are enabled, receipt of an IRQ prompts a switch to interrupt context. Kernel interrupt dispatch code retrieves the IRQ number and its associated list of registered Interrupt Service Routines (ISRs), and calls each ISR in turn. The ISR acknowledges the interrupt and ignores redundant interrupts from the same IRQ, then queues a deferred handler to finish processing the interrupt and stop the ISR from ignoring future interrupts.
IRQs have an associated "affinity" property, smp_affinity, which defines the CPU cores that are allowed to execute the ISR for that IRQ. This property can be used to improve application performance by assigning both interrupt affinity and the application's thread affinity to one or more specific CPU cores. This allows cache line sharing between the specified interrupt and application threads.
# cat /proc/irq/32/smp_affinity
f
The default value for smp_affinity is f, meaning that the IRQ can be serviced on any of the CPUs in the system. Setting this value to 1, as follows, means that only CPU 0 can service this interrupt:
# echo 1 >/proc/irq/32/smp_affinity
# cat /proc/irq/32/smp_affinity
1
On systems that support interrupt steering, modifying the smp_affinity of an IRQ sets up the hardware so that the decision to service an interrupt with a particular CPU is made at the hardware level, with no intervention from the kernel.
More detailed information present at Redhat's DOC - 4.3 Interrupts and IRQ tuning
Are interrupts executed on all processors, or only on one?
For instance, when I type, do all processors handle the interrupt? Or only one of them and the rest carry on with other taks?
Here's a high-level view of the low-level processing. I'm describing a simple typical architecture, real architectures can be more complex or differ in ways that don't matter at this level of detail.
When an interrupt occurs, the processor looks if interrupts are masked. If they are, nothing happens until they are unmasked. When interrupts become unmasked, if there are any pending interrupts, the processor picks one.
Then the processor executes the interrupt by branching to a particular address in memory. The code at that address is called the interrupt handler. When the processor branches there, it masks interrupts (so the interrupt handler has exclusive control) and saves the contents of some registers in some place (typically other registers).
The interrupt handler does what it must do, typically by communicating with the peripheral that triggered the interrupt to send or receive data. If the interrupt was raised by the timer, the handler might trigger the OS scheduler, to switch to a different thread. When the handler finishes executing, it executes a special return-from-interrupt instruction that restores the saved registers and unmasks interrupts.
The interrupt handler must run quickly, because it's preventing any other interrupt from running. In the Linux kernel, interrupt processing is divided in two parts:
The “top half” is the interrupt handler. It does the minimum necessary, typically communicate with the hardware and set a flag somewhere in kernel memory.
The “bottom half” does any other necessary processing, for example copying data into process memory, updating kernel data structures, etc. It can take its time and even block waiting for some other part of the system since it runs with interrupts enabled.
I'm trying to better understand the interaction between the "return IRQ_HANDLED" statement used in a GPIO pin-based interrupt handler (top-half) and the GPIO pin hardware. In particular, consider the hypothetical situation wherein a device has pulled a GPIO pin low to indicate that it needs attention. This causes the associated (top half) interrupt handler to be invoked. Now assume that the top-half handler queues up some work and then returns with "return IRQ_HANDLED" but that for whatever reason the interrupt has not been cleared on the device that generated it (i.e. the device is holding the GPIO pin in the low state). Does invocation of "return IRQ_HANDLED" cause the interrupt to be regenerated? I ask this in the context of the following article:
http://www.makelinux.net/books/lkd2/ch06lev1sec4
"Reentrancy and Interrupt Handlers
Interrupt handlers in Linux need not be reentrant. When a given interrupt handler is executing, the corresponding interrupt line is masked out on all processors, preventing another interrupt on the same line from being received. Normally all other interrupts are enabled, so other interrupts are serviced, but the current line is always disabled. Consequently, the same interrupt handler is never invoked concurrently to service a nested interrupt. This greatly simplifies writing your interrupt handler."
The above comment indicates that upon invocation of an interrupt handler, the interrupt line for that interrupt is masked. I'm trying to figure out if the invocation of "return IRQ_HANDLED" is what unmasks the interrupt line. And, with respect to the hypothetical case described above, what would happen if I "return IRQ_HANDLED" yet the device has not really had its interrupt cleared and hence is still holding the GPIO pin in a low (triggered) state. More specifically, will this cause the interrupt to be generated again such that the processor never has a chance to do the work queued when the interrupt first occurred. I.e., would this lead to an interrupt storm wherein the processor could be interrupted endlessly thus not allowing any useful processing to occur. I should add that I ask this question in the context of a single CPU linux ARM9 system (Phytec LPC3180) running kernel 2.6.10.
Thanks in advance,
Jim
PS: I'm not clear as to the difference between enabling/disabling an interrupt (in particular, an interrupt associated with a particular GPIO pin) and masking/unmasking the same GPIO interrupt.