Re: A better interface, perhaps: a timed signal flag

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> 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.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux