[PATCH] Re: [MPlayer-dev-eng] Real Time Clock into timer-lx.c?
Sidik Isani
lksi at cfht.hawaii.edu
Sun Sep 22 17:28:03 CEST 2002
On Sun, Sep 22, 2002 at 01:37:05PM +0200, Arpi wrote:
> Hi,
>
> > 1. Some previous program happens to have left it at >= 256Hz.
> hmm i thought it was fixed long time ago
nope
> > 2. I'm running as root, or setuid-root
> it's kernel thing - you can override the 64hz limit in 2.4.19 /proc/sys/...
>
> > 1. *Set* the RTC to 256Hz rather than accepting whatever frequency
> maybe 256hz is not enough, i prefer 1024
fine. Please note the effective rate you were seeing was 512Hz,
because the code was reading TWO 32-bit words from /dev/rtc. If
you were happy with 1024, it should just as well for you at 512
with that bug fixed...
> > than that. Since only one application can use the RTC at a time,
> > does anyone see a problem with just putting a value in?
> no
>
> > 2. Actually look at what the RTC returns (exact count of interrupts
> > since last call) and use this to efficiently calculate
> > GetRelativeTime() instead of banging on gettimeofday.
> why?
The upper 24 bits of the 32-bit value returned by reading /dev/rtc
does exactly what GetRelativeTime() wants: an exact measure of how
much time elapsed since the last time you read it. I just thought,
why read gettimeofday too, when it may not be as consistent?
> > 3. At the same time, move RTC into linux/timer-lx.c (still inside
> why?
That's why I asked :-) OK, maybe its own file would be better?
It's just that RTC is a very low level, hardware-specific way of
implementing a sleep. In the case of usleep()/nanosleep() it's
nicely encapsulated in a separate module so I thought the same
would make sense for RTC. Please take a look at this patch (which
still patches timer-lx.c ... though I'll do another patch with it
in a separate file if you like it), and note that mplayer.c becomes
nicer to read.
> send patch, i'll see
> i agree with 1, but see no reason for 2 and 3
Attached...
-------------- next part --------------
diff -ru MPlayer-last/linux/timer-lx.c MPlayer-isani/linux/timer-lx.c
--- MPlayer-last/linux/timer-lx.c Sat Mar 23 14:58:27 2002
+++ MPlayer-isani/linux/timer-lx.c Sun Sep 22 05:21:27 2002
@@ -6,13 +6,63 @@
#include <sys/time.h>
#include "../config.h"
+#ifdef HAVE_RTC
+#include "../mp_msg.h"
+#include "../help_mp.h"
+#include <linux/rtc.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int nortc=0; /* Set if RTC is disabled at run-time */
+static int rtc_fd=-1; /* RTC compiled in, but some problem occurred */
+static unsigned long rtc_irq_freq=0; /* Frequency of the interrupt */
+static int rtc_events = 0;
+
+static int get_rtc_count(void)
+/*
+ * NOTE: Implicit in get_rtc_count is a tiny sleep of <= 1 clock tick.
+ * To just peek at the latest value of RTC events which have not been
+ * returned to the user yet (by a call to GetTimerRelative()) use the
+ * value of rtc_events instead.
+ */
+{
+ unsigned long rtc_ts;
+ if (rtc_fd == -1) return 0;
+ if (read (rtc_fd, &rtc_ts, sizeof(rtc_ts)) <= 0) {
+ close(rtc_fd);
+ rtc_fd = -1;
+ return 0;
+ }
+ return rtc_ts>>8;
+}
+#endif
+
int usec_sleep(int usec_delay)
{
+#ifdef HAVE_RTC
+ unsigned long ev, ev_total = 0;
+
+ if (rtc_fd != -1){
+ if (usec_delay==0)
+ return 0; /* GetTimeRelative() will actually sleep for the tick. */
+ do{
+ ev = get_rtc_count();
+ if (!ev) break; /* RTC failed. Continue with nanosleep. */
+ rtc_events += ev;
+ ev_total += ev;
+ } while (ev_total * 1000000 < rtc_irq_freq * usec_delay);
+ if (ev) return 0; /* RTC worked. Return success. */
+ }
+#endif
#ifdef HAVE_NANOSLEEP
+ {
struct timespec ts;
ts.tv_sec = usec_delay / 1000000;
ts.tv_nsec = (usec_delay % 1000000) * 1000;
return nanosleep(&ts, NULL);
+ }
#else
return usleep(usec_delay);
#endif
@@ -44,6 +94,15 @@
// Returns time spent between now and last call in seconds
float GetRelativeTime(){
unsigned int t,r;
+#ifdef HAVE_RTC
+ if (rtc_fd>=0){
+ int ev_total;
+
+ ev_total = get_rtc_count() + rtc_events;
+ rtc_events = 0;
+ return (float)ev_total/(float)rtc_irq_freq;
+ }
+#endif
t=GetTimer();
// t*=16;printf("time=%ud\n",t);
r=t-RelativeTime;
@@ -53,6 +112,44 @@
// Initialize timer, must be called at least once at start
void InitTimer(){
+#ifdef HAVE_RTC
+ if(!nortc)
+ {
+ rtc_irq_freq = 512; /* 256 seemed OK too. 128 is already jerky.
+ * 64 is the only speed non-root can use
+ * (and is way too slow to be better than usleep.)
+ * Unfortunately the RTC can only be programmed
+ * at frequencies that a powers of 2. For a non-
+ * root user, something like 2*vo_fps would have
+ * been great, but it doesn't work.
+ */
+ seteuid(0);
+ if ((rtc_fd = open("/dev/rtc", O_RDONLY)) < 0) {
+ mp_msg(MSGT_CPLAYER, MSGL_ERR, "Linux RTC init error: %s\n", strerror(errno));
+ if (errno == EPERM)
+ mp_msg(MSGT_CPLAYER, MPGL_ERR, "Try making /dev/rtc readable or making mplayer setuid root.\n");
+ } else if (ioctl(rtc_fd, RTC_IRQP_SET, rtc_irq_freq) < 0) {
+ mp_msg(MSGT_CPLAYER, MSGL_ERR, "Linux RTC init error in ioctl (RTC_IRQP_SET): %s\n", strerror(errno));
+ mp_msg(MSGT_CPLAYER, MPGL_ERR, "Try adding \"echo %lu > /proc/sys/dev/rtc/max-user-freq\" to your system startup scripts.\n", rtc_irq_freq);
+ close (rtc_fd);
+ rtc_fd = -1;
+ } else if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
+ /* variable only by the root */
+ mp_msg(MSGT_CPLAYER, MSGL_ERR, "Linux RTC init error in ioctl (RTC_PIE_ON): %s\n", strerror(errno));
+ close (rtc_fd);
+ rtc_fd = -1;
+ } else
+ mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_UsingRTCTiming, rtc_irq_freq);
+ seteuid(getuid());
+ /*
+ * NOTE! Setting the effective user ID back to the real user
+ * is the right thing to do here. Other parts of the code that
+ * need root privileges still have the option to call seteuid(0)
+ * when they need it. (setuid() instead of seteuid() on the other
+ * hand, would have given up root permanently.)
+ */
+ }
+#endif
GetRelativeTime();
}
diff -ru MPlayer-last/mplayer.c MPlayer-isani/mplayer.c
--- MPlayer-last/mplayer.c Sat Sep 21 17:59:29 2002
+++ MPlayer-isani/mplayer.c Sun Sep 22 05:23:51 2002
@@ -74,10 +74,6 @@
#define ABS(x) (((x)>=0)?(x):(-(x)))
-#ifdef HAVE_RTC
-#include <linux/rtc.h>
-#endif
-
#ifdef USE_TV
#include "libmpdemux/tv.h"
@@ -265,10 +261,6 @@
// ---
-#ifdef HAVE_RTC
-int nortc;
-#endif
-
static unsigned int inited_flags=0;
#define INITED_VO 1
#define INITED_AO 2
@@ -499,8 +491,6 @@
int osd_show_av_delay = 0;
int osd_show_sub_delay = 0;
-int rtc_fd=-1;
-
//float a_frame=0; // Audio
int i;
44_osd();
-#ifdef HAVE_RTC
- if(!nortc)
- {
- if ((rtc_fd = open("/dev/rtc", O_RDONLY)) < 0)
- mp_msg(MSGT_CPLAYER, MSGL_ERR, "Linux RTC init error: %s\n", strerror(errno));
- else {
- unsigned long irqp;
-
- /* if (ioctl(rtc_fd, RTC_IRQP_SET, _) < 0) { */
- if (ioctl(rtc_fd, RTC_IRQP_READ, &irqp) < 0) {
- mp_msg(MSGT_CPLAYER, MSGL_ERR, "Linux RTC init error in ioctl (rtc_irqp_read): %s\n", strerror(errno));
- close (rtc_fd);
- rtc_fd = -1;
- } else if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
- /* variable only by the root */
- mp_msg(MSGT_CPLAYER, MSGL_ERR, "Linux RTC init error in ioctl (rtc_pie_on): %s\n", strerror(errno));
- close (rtc_fd);
- rtc_fd = -1;
- } else
- mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_UsingRTCTiming, irqp);
- }
- }
-#ifdef HAVE_NEW_GUI
-// breaks DGA and SVGAlib and VESA drivers: --A'rpi
-// and now ? -- Pontscho
- if(use_gui) setuid( getuid() ); // strongly test, please check this.
-#endif
- if(rtc_fd<0)
-#endif
- mp_msg(MSGT_CPLAYER, MSGL_INFO, "Using %s timing\n",softsleep?"software":"usleep()");
+ /*
+ * This might be a good place to do:
+ *
+ *seteuid(getuid());
+ *
+ * for security. Other components which need root can always get
+ * it back temporarily by calling seteuid(0);
+ */
+
+ mp_msg(MSGT_CPLAYER, MSGL_INFO, "Using %s timing\n",softsleep?"software":"system");
#ifdef USE_TERMCAP
if ( !use_gui ) load_termcap(NULL); // load key-codes
@@ -1691,20 +1678,7 @@
// flag 256 means: libvo driver does its timing (dvb card)
if(time_frame>0.001 && !(vo_flags&256)){
-
-#ifdef HAVE_RTC
- if(rtc_fd>=0){
- // -------- RTC -----------
- current_module="sleep_rtc";
- while (time_frame > 0.000) {
- unsigned long long rtc_ts;
- if (read (rtc_fd, &rtc_ts, sizeof(rtc_ts)) <= 0)
- mp_msg(MSGT_CPLAYER, MSGL_ERR, "Linux RTC read error: %s\n", strerror(errno));
- time_frame-=GetRelativeTime();
- }
- } else
-#endif
- {
+ /* (re-indent) */
// -------- USLEEP + SOFTSLEEP -----------
float min=softsleep?0.021:0.005;
current_module="sleep_usleep";
14e<0) mp_msg(MSGT_AVSYNC, MSGL_WARN, "Warning! Softsleep underflow!\n");
while(time_frame>0) time_frame-=GetRelativeTime(); // burn the CPU
}
- }
}
More information about the MPlayer-dev-eng
mailing list