|
Rockbox mail archiveSubject: X11 simulator clock runs too fastX11 simulator clock runs too fast
From: c s <rb_dev_at_yahoo.com>
Date: Wed, 5 Mar 2003 19:18:28 -0800 (PST) While developing a mod to the wps, I noticed that the X11 simulator clock was running much faster than the actual clock does on the Archos. As a result, when running on the X11 simulator, current_tick runs at more than 1000Hz and advances more than 200 ticks for every cycle of wps_refresh as opposed to 20 ticks per cycle of wps_refresh on the actual hardware. This throws off current rockbox code that is checking if a certain time period has passed using "TIMEAFTER(current_tick, xxx)". Part of the problem is how the clock is emulated in the simulator. In the function x11_sleep() (in uisimulator/x11/thread.c), current_tick is incremented by 5 every time someone calls sleep(), thus constant calls of sleep(1) (which rockbox software does) will cause current_tick to advance at 5 times the desired rate. Changing x11_sleep() to increment current_tick by the number of ticks the caller passes to the sleep() call makes current_tick run much closer to 100Hz, and is a decent quick fix, however this does not completely solve the fast clock problem. Even with that quick fix, the clock will still run a bit fast because more than one thread can call and be waiting in sleep() at the same time. If thread #1 calls sleep(10) and control is passed to thread #2 which immediately calls sleep(10), current_tick will be incremented by 20 (10 for each sleep call) when only 10/100ths of a second will have actually elapsed when the threads return from their sleep() calls. Because of this phenomenon, this quick fix is not perfect, but it makes it better the current situation. I wrote a better fix that uses a separate thread that does nothing but increment current_tick every 10ms, however there is a problem with it because on many (most?) Linux systems the shortest wait you can do with a call to poll() (or usleep(), or nanosleep() ) is 20ms. This makes current_tick run at only 50Hz on systems that can’t do a suspended wait of only 10ms. There are a couple of ways around this. We can update current_tick by 2 ticks every 20ms. Another is to write a routine that can sleep for the required 10ms period on most Linux systems. I wrote one such routine that uses calls to clock_gettime() and goes into a busy loop until 10ms has passed. Using this method, I can get a good solid 100Hz clock, but since it uses a busy loop to wait for the time to pass it's not doing a true sleep but instead sucking up CPU, however things still seem to run OK with the other threads still getting CPU time when they need it and the clock still remaining at 100Hz. The fix using clock_gettime() also requires that the simulator be linked with the –lrt library. Is this a standard library that everyone has? Does anybody have a better suggestion for a way to do a 10ms wait that will work with more Linux systems and doesn’t suck up CPU with a busy loop? We should at least put the first quick fix in the simulator code (correcting x11_sleep() to only increment current_tick by the number of ticks passed to it). Also I believe that similar problems exist in the win32 specific simulator code, but I didn't look into details or fixes for the win32 code. Is there any interest in using or improving the other fixes that I have discussed? I have included some of the code that I wrote below if anyonone is interested in the details of what I discussed above. ----------------------------------------- Here is the usleep that I wrote which uses a busy loop, but can do a 10ms wait on systems that can’t do a 10ms with the system usleep() call. /* requires –lrt flag when linking */ #include <time.h> void x11_usleep(int sleep_usec) { struct timespec time; int curr_sec, curr_usec; int sleep_until_sec, sleep_until_usec; clock_gettime(CLOCK_REALTIME, &time); curr_sec = time.tv_sec; curr_usec = time.tv_nsec/1000000; sleep_until_sec = curr_sec + ((curr_usec + sleep_usec) / 1000); sleep_until_usec = (curr_usec + sleep_usec) % 1000; while (1) { clock_gettime(CLOCK_REALTIME, &time); curr_sec = time.tv_sec; curr_usec = time.tv_nsec/1000000; if ((curr_sec >= sleep_until_sec) && (curr_usec >= sleep_until_usec)) break; } return; } Using the x11_usleep function above and this function to increment current_tick instead of incrementing it in function x11_sleep gives a solid 100Hz clock, but sucks up CPU. void clock_emulator_thread() { while (1) { x11_usleep(1000/HZ); current_tick++; } } ----------- This is our current x11_sleep from the CVS with my comments added. void x11_sleep(int ticks) { current_tick+=5; /* QUICK FIX: change this line to: "current_tick+=ticks;" */ pthread_mutex_unlock(&mp); /* return */ /* portable subsecond "sleep" */ poll((void *)0, 0, ticks * 1000/HZ); /* on many systems, this sleeps for a minumum of 20ms */ pthread_mutex_lock(&mp); /* get it again */ } --- Craig Sather __________________________________________________ Do you Yahoo!? Yahoo! Tax Center - forms, calculators, tips, more http://taxes.yahoo.com/Received on 2003-03-06 Page template was last modified "Tue Sep 7 00:00:02 2021" The Rockbox Crew -- Privacy Policy |