public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] RTC: Add mmap method to rtc character driver
@ 2006-07-25 17:41 Neil Horman
  2006-07-25 17:55 ` Arjan van de Ven
                   ` (3 more replies)
  0 siblings, 4 replies; 90+ messages in thread
From: Neil Horman @ 2006-07-25 17:41 UTC (permalink / raw)
  To: linux-kernel; +Cc: a.zummo, jg, nhorman

Hey-
	At OLS last week, During Dave Jones Userspace Sucks presentation, Jim
Geddys and some of the Xorg guys noted that they would be able to stop using gettimeofday
so frequently, if they had some other way to get a millisecond resolution timer
in userspace, one that they could perhaps read from a memory mapped page.  I was
right behind them and though that seemed like a reasonable request,  so I've
taken a stab at it.  This patch allows for a page to be mmaped from /dev/rtc
character interface, the first 4 bytes of which provide a regularly increasing
count, once every rtc interrupt.  The frequency is of course controlled by the
regular ioctls provided by the rtc driver. I've done some basic testing on it,
and it seems to work well.

Thanks And Regards
Neil

Signed-off-by: Neil Horman


 
 rtc.c |   41 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 40 insertions(+), 1 deletion(-)


diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 6e6a7c7..4ed673e 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -48,9 +48,10 @@
  *		CONFIG_HPET_EMULATE_RTC
  *	1.12a	Maciej W. Rozycki: Handle memory-mapped chips properly.
  *	1.12ac	Alan Cox: Allow read access to the day of week register
+ *	1.12b   Neil Horman: Allow memory mapping of /dev/rtc	
  */
 
-#define RTC_VERSION		"1.12ac"
+#define RTC_VERSION		"1.12b"
 
 /*
  *	Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
@@ -183,6 +184,8 @@ static int rtc_proc_open(struct inode *i
  */
 static unsigned long rtc_status = 0;	/* bitmapped status byte.	*/
 static unsigned long rtc_freq = 0;	/* Current periodic IRQ rate	*/
+#define BUF_SIZE (PAGE_SIZE/sizeof(unsigned long))
+static unsigned long rtc_irq_buf[BUF_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
 static unsigned long rtc_irq_data = 0;	/* our output to the world	*/
 static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
 
@@ -230,6 +233,7 @@ static inline unsigned char rtc_is_updat
 
 irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long *count_ptr = (unsigned long *)rtc_irq_buf;
 	/*
 	 *	Can be an alarm interrupt, update complete interrupt,
 	 *	or a periodic interrupt. We store the status in the
@@ -265,6 +269,7 @@ irqreturn_t rtc_interrupt(int irq, void 
 
 	kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
 
+	*count_ptr = (*count_ptr)++;
 	return IRQ_HANDLED;
 }
 #endif
@@ -389,6 +394,37 @@ static ssize_t rtc_read(struct file *fil
 #endif
 }
 
+static int rtc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+        unsigned long rtc_addr;
+	unsigned long *count_ptr = rtc_irq_buf;
+
+        if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+                return -EINVAL;
+
+        if (vma->vm_flags & VM_WRITE)
+                return -EPERM;
+
+        if (PAGE_SIZE > (1 << 16))
+                return -ENOSYS;
+
+        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+        rtc_addr = __pa(rtc_irq_buf);
+        rtc_addr &= ~(PAGE_SIZE - 1);
+        rtc_addr &= -1;
+
+        if (remap_pfn_range(vma, vma->vm_start, rtc_addr >> PAGE_SHIFT,
+                                        PAGE_SIZE, vma->vm_page_prot)) {
+                printk(KERN_ERR "remap_pfn_range failed in rtc.c\n");
+                return -EAGAIN;
+        }
+
+	*count_ptr = 0;
+        return 0;
+
+}
+
 static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
 {
 	struct rtc_time wtime; 
@@ -890,6 +926,7 @@ static const struct file_operations rtc_
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= rtc_read,
+	.mmap		= rtc_mmap,
 #ifdef RTC_IRQ
 	.poll		= rtc_poll,
 #endif
@@ -1082,6 +1119,8 @@ no_irq:
 no_irq2:
 #endif
 
+	memset(rtc_irq_buf,0,PAGE_SIZE);
+
 	(void) init_sysctl();
 
 	printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n");
-- 
/***************************************************
 *Neil Horman
 *Software Engineer
 *gpg keyid: 1024D / 0x92A74FA1 - http://pgp.mit.edu
 ***************************************************/

^ permalink raw reply related	[flat|nested] 90+ messages in thread
* RE: A better interface, perhaps: a timed signal flag
@ 2006-07-26 15:15 Brown, Len
  0 siblings, 0 replies; 90+ messages in thread
From: Brown, Len @ 2006-07-26 15:15 UTC (permalink / raw)
  To: Theodore Tso, Neil Horman
  Cc: H. Peter Anvin, Segher Boessenkool, Dave Airlie, linux-kernel,
	a.zummo, jg

>if the application doesn't need to
>know exactly how many microseconds have gone by, but just whether or
>not 150us has ellapsed, why calculate the necessary time?  (Especially
>if it requires using some ACPI interface...)

Yes, ACPI is involved in the boot-time enumeration of various timers
and counters.  But at run-time; the use of any and all of them
(including the PM_TIMER supplied by ACPI hardware itself) could/should
appear generic to kernel users, who should not have to directly call
any routine with an "acpi" in it.

I believe that this is true today, and can/should stay true.

-Len

^ permalink raw reply	[flat|nested] 90+ messages in thread
* Re: A better interface, perhaps: a timed signal flag
@ 2006-07-29  6:56 linux
  0 siblings, 0 replies; 90+ messages in thread
From: linux @ 2006-07-29  6:56 UTC (permalink / raw)
  To: linux-kernel, tytso; +Cc: linux

> If we had such an interface, then the application would look like
> this:
> 
>	volatile int	flag = 0;
>
>	register_timout(&time_val, &flag);
>	while (work to do) {
>		do_a_bit_of_work();
>		if (flag)
>			break;
>	}
>
> Finally, a note about tickless designs.  Very often such applications
> don't need a constantly ticking design.  For example, the X server
> only needs to have the memory location incremented while it is
> processing events; if the laptop is idle, there's no reason to have
> the RTC generating interrupts and incrementing memory locations.
> Similarly, the Metronome garbage collector would only need to poll to
> see if the timeout has expired while the garbage collector is running,
> which is _not_ all of the time.  
> 
> Yes, you could use ioctl's to start and stop the RTC interrupt
> handler, but that's just ugly, and points out that maybe the interface
> should not be one of programming the RTC interrupt frequency directly,
> but rather one of "increment this flag after X units of
> (CPU/wallclock) time, and I don't care how it is implemented at the
> hardware level."

Actually, unless you want the kernel to have to poll the timeout_flag
periodically, it's more like:

	volatile bool	timeout_flag = false, armed_flag = false;

	register_timout(&time_val, &flag);
	while (work to do) {
		if (!armed_flag) {
			rearm_timeout();
			armed_flag = true;
		}
		do_a_bit_of_work();
		if (timeout_flag) {
			armed_flag = false;
			timeout_flag = false;
			break;
		}
	}

Personally, I use setitimer() for this.  You can maintain the flags in
software, and be slightly lazy about disarming it.  If you get a signal
while you shouldn't be armed, *then* disarm the timer in the kernel.
Likewise, when rearming, set the user-disarmed flag and chec if kernel-level
rearming is required.

volatile bool timeout_flag = false, armed_flag = false, sys_armed_flag = false;

void
sigalrm(int sig)
{
	(void)sig;
	if (!armed_flag) {
		static const struct itimerval it_zero = {{0,0},{0,0}};
		if (sys_armed_flag)
			warn_unexpected_sigalrm();
		setitimer(ITIMER_REAL, &it_zero, 0);
		
	} else if (timeout_flag)
		warn_gc_is_slow();
	else
		timeout_flag = true;
}

void
arm_timer()
{
	static const struct itimerval it_interval = { time_val, time_val };

	armed_flag = true;
	if (!sys_armed_flag) {
		setitimer(ITIMER_REAL, &it_interval, 0);
		sys_armed_flag = true;
	}
}

main_loop()
{
	signal(SIGALRM, sigalrm);

	while (work to do) {
		arm_timer();
		do_a_bit_of_work();
		if (timeout_flag) {
			gc();
			armed_flag = false;
			timeout_flag = false;
		}
	}
}

... where only do_a_bit_of_work can prompt the need for more gc() calls.
This really tries to minimize the number of system calls.

^ permalink raw reply	[flat|nested] 90+ messages in thread
[parent not found: <fa.xkoDc6Uvpcp6dnG8+9iwy53PPeo@ifi.uio.no>]

end of thread, other threads:[~2006-08-02  4:35 UTC | newest]

Thread overview: 90+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-25 17:41 [PATCH] RTC: Add mmap method to rtc character driver Neil Horman
2006-07-25 17:55 ` Arjan van de Ven
2006-07-25 18:01   ` Jim Gettys
2006-07-25 18:22   ` Neil Horman
2006-07-25 18:32     ` Arjan van de Ven
2006-07-25 18:43       ` Neil Horman
2006-07-25 18:53         ` Arjan van de Ven
2006-07-25 19:03           ` Neil Horman
2006-07-25 19:06             ` Arjan van de Ven
2006-07-25 19:07           ` John W. Linville
2006-07-25 19:16             ` Arjan van de Ven
2006-07-25 19:08           ` H. Peter Anvin
2006-07-25 17:57 ` Segher Boessenkool
2006-07-25 18:28   ` Neil Horman
2006-07-25 18:56     ` Segher Boessenkool
2006-07-25 19:07       ` Neil Horman
2006-07-25 19:10     ` H. Peter Anvin
2006-07-25 19:21       ` Neil Horman
2006-07-25 19:31         ` Segher Boessenkool
2006-07-25 19:47           ` Neil Horman
2006-07-25 20:04             ` Dave Airlie
2006-07-25 20:24               ` H. Peter Anvin
2006-07-25 20:47                 ` Neil Horman
2006-07-25 20:50                   ` H. Peter Anvin
2006-07-25 22:25                     ` Neil Horman
2006-07-25 22:33                       ` H. Peter Anvin
2006-07-25 23:10                         ` Neil Horman
2006-07-25 23:22                           ` H. Peter Anvin
2006-07-26  0:03                             ` Neil Horman
2006-07-25 23:29                           ` David Lang
2006-07-26  0:18                             ` Neil Horman
2006-07-25 23:29                       ` Segher Boessenkool
2006-07-25 23:56                         ` Neil Horman
2006-07-26  0:02                           ` H. Peter Anvin
2006-07-26  0:20                             ` Neil Horman
2006-07-26  0:36                               ` H. Peter Anvin
2006-07-26 14:45                               ` A better interface, perhaps: a timed signal flag Theodore Tso
2006-07-28 13:33                                 ` Steven Rostedt
2006-07-28 14:52                                   ` Theodore Tso
2006-07-28 15:05                                     ` Steven Rostedt
2006-07-28 16:41                                     ` Alan Cox
2006-07-28 16:44                                       ` Steven Rostedt
2006-07-28 20:01                                         ` Alan Cox
2006-07-28 20:12                                           ` Steven Rostedt
2006-07-28 20:36                                             ` Alan Cox
2006-07-28 20:31                                               ` Steven Rostedt
2006-07-28 17:11                                 ` H. Peter Anvin
2006-07-25 20:58                   ` [PATCH] RTC: Add mmap method to rtc character driver Jim Gettys
2006-07-25 21:04                     ` H. Peter Anvin
2006-07-25 21:14                       ` Jim Gettys
2006-07-25 21:18                         ` H. Peter Anvin
2006-07-25 21:39                           ` Jim Gettys
2006-07-29  4:28                             ` Bill Huey
2006-07-29 12:54                               ` Neil Horman
2006-07-29 20:41                                 ` Bill Huey
2006-07-29 21:43                                   ` Neil Horman
2006-07-29 22:45                                     ` Keith Packard
2006-07-29 23:18                                       ` Edgar Toernig
2006-07-29 21:49                                   ` Edgar Toernig
2006-07-29 22:51                                     ` itimer again (Re: [PATCH] RTC: Add mmap method to rtc character driver) Bill Huey
2006-07-29 23:35                                       ` Nicholas Miell
2006-07-30  1:00                                         ` Bill Huey
2006-07-30  1:22                                           ` Nicholas Miell
2006-07-30  1:39                                             ` Bill Huey
2006-07-30  2:02                                               ` Nicholas Miell
2006-07-30 14:33                                               ` Theodore Tso
2006-07-30 22:20                                                 ` Bill Huey
2006-07-31 15:40                                                   ` Theodore Tso
2006-07-30  0:16                                       ` Edgar Toernig
2006-07-30  0:24                                         ` Bill Huey
2006-07-29 14:02                             ` [PATCH] RTC: Add mmap method to rtc character driver Thomas Gleixner
2006-07-26 13:17                   ` Martin J. Bligh
2006-08-02  3:54               ` john stultz
2006-08-02  4:26                 ` H. Peter Anvin
2006-08-02  4:34                   ` john stultz
2006-07-25 23:26             ` Segher Boessenkool
2006-07-26  0:10               ` Neil Horman
2006-07-25 20:03       ` Paul Mackerras
2006-07-25 23:27         ` Segher Boessenkool
2006-07-26  0:06           ` Neil Horman
2006-07-25 18:00 ` Jim Gettys
2006-07-25 18:17   ` Neil Horman
2006-07-26 15:16 ` Andi Kleen
2006-07-26 17:25   ` Jim Gettys
2006-07-27 23:53   ` Paul Mackerras
2006-07-28  3:29     ` Jim Gettys
2006-07-28 11:59       ` Neil Horman
  -- strict thread matches above, loose matches on Subject: below --
2006-07-26 15:15 A better interface, perhaps: a timed signal flag Brown, Len
2006-07-29  6:56 linux
     [not found] <fa.xkoDc6Uvpcp6dnG8+9iwy53PPeo@ifi.uio.no>
     [not found] ` <fa.7gpoVg9wmtQ0g4u4T8FaCZGXup0@ifi.uio.no>
2006-07-29 18:29   ` Robert Hancock

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox