Manuel Tobias Schiller wrote:
> Well, blocking all other threads is a bad thing in itself, because I  
> tend to lose button events when I can't poll them in time (remeber,  
> button polling is done with ioctls, it's got nothing to do with the  
> poll() syscall; poll() will only tell when a write to the device is  
> possible without blocking). Besides, blocking all threads inside
> usleep() or inside poll() or select() is all the same to the  
> application (it won't wake up in these 50 ms to poll the buttons when  
> it's time to do so) and therefore the realisation of making the process  
> block is not really that important, because streaming the mpeg data is  
> not critical when it comes to timing (the kernel level driver has 16 kb  
> buffers, for a 128 kbit stream, a full buffer lasts for a whole  
> second), but button polling (which has to be done via ioctls) is timing  
> critical, because this is what determines the responsiveness of the  
> application. One should probably poll the button status 25 to 50 times  
> per second; this won't take much time however, because the operation is  
> reasonably fast, so the button polling thread can remain blocked most  
> of the time.

Out of curiosity, I've tested how much CPU the following program uses
and how bad latency gets. The CPU is virtually idle and the latency
stays below 30 ms most of the time even when playing three videos to
utilize the CPU completely at the same time. Your button polling
thread wouldn't do anything else than this except using some
light-weight ioctl() calls instead of gettimeofday(), right? So I
don't think the button polling has to waste a lot CPU time.

#include <sys/types.h>
#include <sys/time.h>
#include <poll.h>
#include <stdio.h>

int
main(void)
{
        static struct timeval tv0;
        static unsigned long max_d;

        gettimeofday(&tv0, NULL);
        for (;;) {
                static struct timeval tv;
                unsigned long d;

                poll(NULL, 0, 10 /* ms */);
                gettimeofday(&tv, NULL);
                d = (tv.tv_sec - tv0.tv_sec) * 1000
                        + (tv.tv_usec - tv0.tv_usec) / 1000;
                tv0 = tv;
                if (d > max_d) {
                        max_d = d;
                        printf("max. %lu ms\n", max_d);
                }
        }

        return 0;
}

My suggestion would be to use such a helper process to poll for button
events and pass the collected events over a socket created with
socketpair().  Even if you use it for testing only, it might be useful
to sort out the timing issues. In your main process you can then
poll() for the button events without busy-loop alike polling. Of
course, without real-time scheduling there's no guarantee that all
button events are registered. If the CPU is rather slow or heavily
loaded, the 50 ms latency might not be achievable constantly. As far
as I understood, the problem is that these events cause no interrupt
and are also edge-triggered, meaning they're lost if you don't catch
them in time. I agree that handling the button events inside the
kernel is probably the best option.

-- 
Christian

Attachment: pgpFUHpuFqQqs.pgp
Description: PGP signature

Reply via email to