LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Joerg Dorchain <joerg@dorchain.net>
To: linuxppc-dev list <linuxppc-dev@ozlabs.org>
Subject: Heartbeat apps thoughts
Date: Mon, 14 Mar 2005 16:45:04 +0100	[thread overview]
Message-ID: <20050314154504.GA7267@Redstar.dorchain.net> (raw)

[-- Attachment #1: Type: text/plain, Size: 4453 bytes --]

Hi list,

I am pondering a heartbeat functionality implementation. Currently, I
have a patch that adds a few line to the timer interrupt to switch the
led on and off when appropriate.

On the list, there were opinions that switching the led on and off would
be best done via userspace. While I in principle agree, I have some
considerations:

- The heartbeat frequency is calculated dynamically as a function of the
  current load. While this is available e.g. via /proc/loadavg, there is
  the effect that a daemon serving the led would need more cpu on high
  loads (led is blinking faster), even though it is less likely to be
  scheduled. This leads the heartbeat idea ad absurdum.
- Can real time scheduling of the heartbeat daemon avoid the effect
  described above?
- If so, is locking some pages of memory and a real time process still
  more adequate than a few lines in the timer interrupt?

For a discussion base I've attached my current idea of an heartbeatd.
(The DEBUG define might help those without an ibook to get something
running ;-)

Curous for any comments,

Joerg


/*
 * heartbeatd 2005-03-14 Joerg Dorchain <joerg@dorchain.net>
 * led code taken from ibook-led Nico Schottelius (nico-linux@schottelius.org) 2005-02-18 v0.3
 *
 * might replace the kernel heartbeat code in arch/.../time.c
 *
 */

/* open() */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/* write */
#include <unistd.h>

/* fopen.. */
#include <stdio.h>
/* exit */
#include <stdlib.h>
/* nanosleep..*/
#include <time.h>
/* sigaction */
#include <signal.h>

/* HZ */
#include <sys/param.h>
/* ioctl */
#include <sys/ioctl.h>

/* realtime scheduling */
#include <sched.h>
/* mlockall */
#include <sys/mman.h>

/* Linux */
#define FSHIFT 11
#define ADB_DEVICE "/dev/adb"
#define LOADAVG "/proc/loadavg"
#define PIDFILE "/var/run/heartbeatd.pid"

#undef DEBUG
#ifdef DEBUG
#undef LOADAVG
#define LOADAVG "/tmp/loadavg"
#endif

int adbfd;

inline void heartbeat_init(void)
{
#ifndef DEBUG
   /* open /dev/adb */
   if((adbfd = open(ADB_DEVICE,O_RDWR)) == -1) exit(1);
#endif
}

inline void heartbeat(int i)
{
	char adb_on[5] = {0x06, 0xee, 0x04, 0x00, 0x01};
	char adb_off[5] = {0x06, 0xee, 0x04, 0x00, 0x00};

#ifndef DEBUG
	if (i)
		write(adbfd, adb_on, 5);
	else
		write(adbfd, adb_off, 5);
#else
	if (i)
		printf("pump\r");
	else
		printf("    \r");
	fflush(stdout);
#endif
}

inline unsigned int period_calc(void)
{
	FILE *lf;
	unsigned int ldint, ldfrac, load;

	if (( lf = fopen(LOADAVG, "r")) == NULL)
		exit(1);
	fscanf(lf, "%u.%u", &ldint, &ldfrac);
	fclose(lf);
	load = (ldint << FSHIFT) + (ldfrac << FSHIFT) / 100;
	return ((672<<FSHIFT)/(5*load+(7<<FSHIFT))) + 30;
}

void cleanup(int unused_signal)
{
	unlink(PIDFILE);
	exit(1);
}

int main(int argc, char **argv)
{
   unsigned int period;
   struct timespec ts0, ts1, ts2, ts3;
   int fd;
   struct sched_param sp;
   FILE *pidf;
   struct sigaction sa;
  
#ifndef DEBUG
   /* daemonize */
   if (fork() != 0)
	   exit(0);
   if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
	   ioctl(fd, TIOCNOTTY);
	   close(fd);
   }
   /* make pidfile and remove once done */
   if ((pidf = fopen(PIDFILE,"w+")) != NULL) {
	   fprintf(pidf, "%d\n", getpid());
	   fclose(pidf);
	   sa.sa_handler = cleanup;
	   sigemptyset(&sa.sa_mask);
	   sa.sa_flags= SA_ONESHOT;
	   sigaction(SIGHUP, &sa, NULL);
	   sigaction(SIGQUIT, &sa, NULL);
	   sigaction(SIGTERM, &sa, NULL);
   }
   /* get priority */
   if (nice(-19) != 0)
	   perror("nice");
   if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
	   perror("mlockall");
   sp.sched_priority=10;
   if (sched_setscheduler(0, SCHED_RR, &sp) != 0)
	   perror("sched_setscheduler");
#endif

   heartbeat_init();

   while (1) {
	   period = period_calc();
	   ts0.tv_sec = 0;
	   ts0.tv_nsec = 7*(1000000000/HZ);
	   ts1.tv_sec = 0;
	   ts1.tv_nsec = (period/4)*(1000000000/HZ) - ts0.tv_nsec;
	   ts2.tv_sec = 0;
	   ts2.tv_nsec = (period/4+7)*(1000000000/HZ) - ts0.tv_nsec - ts1.tv_nsec;
	   ts3.tv_sec = 0;
	   ts3.tv_nsec = (period)*(1000000000/HZ) - ts0.tv_nsec - ts1.tv_nsec - ts2.tv_nsec;

	   heartbeat(1);
	   nanosleep(&ts0,NULL);
	   heartbeat(0);
	   nanosleep(&ts1,NULL);
	   heartbeat(1);
	   nanosleep(&ts2,NULL);
	   heartbeat(0);
	   nanosleep(&ts3,NULL);
   }
}

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

             reply	other threads:[~2005-03-14 15:45 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-14 15:45 Joerg Dorchain [this message]
2005-03-14 16:02 ` Heartbeat apps thoughts Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050314154504.GA7267@Redstar.dorchain.net \
    --to=joerg@dorchain.net \
    --cc=linuxppc-dev@ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox