[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