mmap langsamer als ioremap
Ich entwickle für ein ARM-Gerät mit Linux-2.6.37. Ich bin versucht zu wechseln, ein IO-pin so schnell wie möglich. Ich machte einen kleinen kernel-Moduls und einer user-space-Anwendung. Ich habe versucht, zwei Dinge :
- Manipulieren die GPIO-control-Register, die direkt aus dem kernel-space mit
ioremap
. mmap()
die GPIO-control-Register ohne Zwischenspeicherung und Verwendung von user-space.
Beide Methoden funktionieren, aber der zweite ist etwa 3-mal langsamer als die erste (beobachtet am Oszilloskop). Ich denke, dass ich alle deaktiviert caching-Mechanismen.
Natürlich würde ich gerne das beste aus beiden Welten : Flexibilität und einfache Entwicklung von user-space mit der Geschwindigkeit des kernel-space.
Weiß jemand, warum die mmap()
könnte langsamer sein als die ioremap()
?
Hier ist mein code :
Kernel-Modul-code
static int ti81xx_usmap_mmap(struct file* pFile, struct vm_area_struct* pVma)
{
pVma->vm_flags |= VM_RESERVED;
pVma->vm_page_prot = pgprot_noncached(pVma->vm_page_prot);
if (io_remap_pfn_range(pVma, pVma->vm_start, pVma->vm_pgoff,
pVma->vm_end - pVma->vm_start, pVma->vm_page_prot))
return -EAGAIN;
pVma->vm_ops = &ti81xx_usmap_vm_ops;
return 0;
}
static void ti81xx_usmap_test_gpio(void)
{
u32* pGpIoRegisters = ioremap_nocache(TI81XX_GPIO0_BASE, 0x400);
const u32 pin = 1 << 24;
int i;
/* I should use IO read/write functions instead of pointer deferencing,
* but portability isn't the issue here */
pGpIoRegisters[OMAP4_GPIO_OE >> 2] &= ~pin; /* Set pin as output*/
for (i = 0; i < 200000000; ++i)
{
pGpIoRegisters[OMAP4_GPIO_SETDATAOUT >> 2] = pin;
pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT >> 2] = pin;
}
pGpIoRegisters[OMAP4_GPIO_OE >> 2] |= pin; /* Set pin as input*/
iounmap(pGpIoRegisters);
}
User-space-Anwendung-code
int main(int argc, char** argv)
{
int file, i;
ulong* pGpIoRegisters = NULL;
ulong pin = 1 << 24;
file = open("/dev/ti81xx-usmap", O_RDWR | O_SYNC);
if (file < 0)
{
printf("open failed (%d)\n", errno);
return 1;
}
printf("Toggle from kernel space...");
fflush(stdout);
ioctl(file, TI81XX_USMAP_IOCTL_TEST_GPIO);
printf(" done\n");
pGpIoRegisters = mmap(NULL, 0x400, PROT_READ | PROT_WRITE, MAP_SHARED, file, TI81XX_GPIO0_BASE);
printf("Toggle from user space...");
fflush(stdout);
pGpIoRegisters[OMAP4_GPIO_OE >> 2] &= ~pin;
for (i = 0; i < 30000000; ++i)
{
pGpIoRegisters[OMAP4_GPIO_SETDATAOUT >> 2] = pin;
pGpIoRegisters[OMAP4_GPIO_CLEARDATAOUT >> 2] = pin;
}
pGpIoRegisters[OMAP4_GPIO_OE >> 2] |= pin;
printf(" done\n");
fflush(stdout);
munmap(pGpIoRegisters, 0x400);
close(file);
return 0;
}
- Was meinst du mit 3x langsamer ? Individuelle Schwingung länger sind, oder die Allgemeine Ausführung ?
- Beide, die Schwingungen sind 3 mal langsamer über den Umfang, der Prozessor mehr Zeit damit verbringt, in der "str" - Anweisung, aber ich weiß nicht, warum. Ist es noch für einige hardware (bus-transfer ?), oder einige software wie ein kernel page fault exception-handler ? Das ist das Herz meiner Frage...
- Beachten Sie, dass in Ihrem Beispiel-code die Anzahl der Iterationen der Schleifen ist sehr unterschiedlich.
- zu kompensieren, die Tatsache, das man schneller ist (in der Frequenz) als das andere :-). Mit 30000000 Iterationen im kernel-space, ich habe kaum die Zeit, um etwas zu Messen, der auf meinem Rahmen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist, weil ioremap_nocache() immer noch ermöglicht, die CPU-write-Puffer in Ihrem VM-mapping in der Erwägung, dass pgprot_noncached() schaltet sowohl bufferability und cachefähigkeit.
Äpfel mit äpfeln Vergleich, würde ioremap_strongly_ordered() statt.
Meine Vermutung wäre, dass da
mmap
hat zu prüfen, um sicherzustellen, dass Sie in den Speicher geschrieben wird darf man schreiben, es wird langsamer sein, als der kernel-version (die ich glauben/davon ausgehen nicht tun, die Art der Prüfung-mit einem kernel-Modul sind Sie verantwortlich für das testen, bis du ganz sicher, dass Sie nicht kaputt zu machen).Versuchen Sie es mit
do_mmap
(ich glaube, das ist die eine) zu verwendenmmap
von kernel-space und sehen, wie sich das vergleicht. Wenn es vergleichsweise schneller, dann bin ich richtig. Wenn nicht, ist es etwas anderes.