Question: Background:
-----------

I have a PCI card, which is basically a clock. It gets the time by GPS and saves the current time in a certain register. 

Goal:
-----

I want to read a limited number of registers/bytes (for example the current time) over and over again, with the **lowest possible latency**. (The clock provides very high precision and I think I will loose precision the higher the latency is.). The operating system is RedHat. The programming language is C/C++. I also want to write to the device memory, whereby latency is not an issue.

Possible Ways to go:
--------------------

I see these ways. If you see another, please tell me:

1. Writing a Linux kernel module driver, which creates a character device (or one character device for each register to read). Then a user space application can do a "read" on the /dev/ file(s).
2. DMA
3. mmap the sysfs resourceX file to user space by a user space application (systemcall). (like [here](https://github.com/billfarrow/pcimem/blob/master/pcimem.c) for example)
4. Write a Linux kernel module driver which implements a mmap file operation.

Questions:
----------

1. Which is the way with the lowest latency when it comes to the actual reading of the register? I am aware that mmap causes a lot of overhead in the kernel, but as far as I understand that is only for initialisation.
2. Is way 3 a legit way to go? It looks like a hack to me. How can I determine the /sys/ path automatically from the application?
3. Is there a difference between way 3 and 4? I am new to PCI driver programming and I think I didn't really understand how way 4 works. I read [this](https://www.safaribooksonline.com/library/view/linux-device-drivers/0596005903/ch15.html) (and other chapters of that book), but maybe you can give me a hint or an example. I would appreciate that.

Answer: 
It's a simple StackOverflow that happens *before* the recursion limit is reached.

In the second (generator) approach it hit the recursion limit with a depth of `2**12`. That means `2**11` should've hit the recursion limit in the first approach. That's because list-comprehensions create an additional stack frame so it's twice the stack frames than the generator solution. The fact that it doesn't throw a RecursionError means that something "fatal" happened to the interpreter (or there is an infinite loop somewhere).

However it's not an infinite loop because if you inspect the jupyter lab responses (for example if you start it from the command line with `jupyter lab`) you'll notice that shortly after running the `flatten(wrap_in_lists(1, 2**11))` line it will print a `kernel <xyz> restarted`. So it isn't correct that there is no response, the kernel just crashed and the `[*]` displayed in the jupyter lab cell in this case just means the calculation didn't finish (because of the crash).

That's one of the reasons why you be **really really careful** if you change Pythons recursion limit or use an interpreter that changed it *for you*.
I'm not sure why the error is getting silenced in your case. I can't reproduce it here. I tried many values and it either gives error or works.

```
>>> sys.setrecursionlimit(3000)
>>> flatten(wrap_in_lists(1, 2**10)) #works
[1]
>>> flatten(wrap_in_lists(1, 2**11)) #fails with exception
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  ...
RecursionError: maximum recursion depth exceeded

```

I'm also using python3 in jupyter notebook.