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

Tsetitimer()



Here's an implementation of Tsetitimer(), providing interval timers
like the BSD setitimer()/getitimer() system calls.


diff -u ../old/dos.c ./dos.c
--- ../old/dos.c	Fri Jul 22 03:48:08 1994
+++ ./dos.c	Fri Jul 22 05:53:48 1994
@@ -478,6 +478,211 @@
 	return oldalarm;
 }
 
+#define ITIMER_REAL 0
+#define ITIMER_VIRTUAL 1
+#define ITIMER_PROF 2
+
+/*
+ * helper function for t_setitimer: this will be called when the ITIMER_REAL
+ * timer goes off
+ */
+
+static void
+itimer_real_me(p)
+	PROC *p;
+{
+	PROC *real_curproc;
+
+	real_curproc = curproc;
+	curproc = p;
+	if (p->itimer[ITIMER_REAL].interval)
+	  p->itimer[ITIMER_REAL].timeout =
+		addtimeout(p->itimer[ITIMER_REAL].interval, itimer_real_me);
+	else
+	  p->itimer[ITIMER_REAL].timeout = 0;
+
+	curproc = real_curproc;
+	post_sig(p, SIGALRM);
+}
+
+/*
+ * helper function for t_setitimer: this will be called when the ITIMER_VIRTUAL
+ * timer goes off
+ */
+
+static void
+itimer_virtual_me(p)
+	PROC *p;
+{
+	PROC *real_curproc;
+	long timeleft;
+
+	real_curproc = curproc;
+	curproc = p;
+	timeleft = p->itimer[ITIMER_VIRTUAL].reqtime
+			- (p->systime - p->itimer[ITIMER_VIRTUAL].startsystime);
+	if (timeleft > 0) {
+		p->itimer[ITIMER_VIRTUAL].timeout =
+			addtimeout(timeleft, itimer_virtual_me);
+	} else {
+		timeleft = p->itimer[ITIMER_VIRTUAL].interval;
+		if (timeleft == 0) {
+			p->itimer[ITIMER_VIRTUAL].timeout = 0;
+		} else {
+			p->itimer[ITIMER_VIRTUAL].reqtime = timeleft;
+			p->itimer[ITIMER_VIRTUAL].startsystime = p->systime;
+			p->itimer[ITIMER_VIRTUAL].startusrtime = p->usrtime;
+			p->itimer[ITIMER_VIRTUAL].timeout =
+				addtimeout(timeleft, itimer_virtual_me);
+		}
+		post_sig(p, SIGVTALRM);
+	}
+	curproc = real_curproc;
+}
+
+/*
+ * helper function for t_setitimer: this will be called when the ITIMER_PROF
+ * timer goes off
+ */
+
+static void
+itimer_prof_me(p)
+	PROC *p;
+{
+	PROC *real_curproc;
+	long timeleft;
+
+	real_curproc = curproc;
+	curproc = p;
+	timeleft = p->itimer[ITIMER_PROF].reqtime
+			- (p->systime - p->itimer[ITIMER_PROF].startsystime)
+			- (p->usrtime - p->itimer[ITIMER_PROF].startusrtime);
+	if (timeleft > 0) {
+		p->itimer[ITIMER_PROF].timeout =
+			addtimeout(timeleft, itimer_prof_me);
+	} else {
+		timeleft = p->itimer[ITIMER_PROF].interval;
+		if (timeleft == 0) {
+			p->itimer[ITIMER_PROF].timeout = 0;
+		} else {
+			p->itimer[ITIMER_PROF].reqtime = timeleft;
+			p->itimer[ITIMER_PROF].startsystime = p->systime;
+			p->itimer[ITIMER_PROF].startusrtime = p->usrtime;
+			p->itimer[ITIMER_PROF].timeout =
+				addtimeout(timeleft, itimer_prof_me);
+		}
+		post_sig(p, SIGPROF);
+	}
+	curproc = real_curproc;
+}
+
+/*
+ * t_setitimer(which, interval, value, ointerval, ovalue):
+ * schedule an interval timer
+ * which is ITIMER_REAL (0) for SIGALRM, ITIMER_VIRTUAL (1) for SIGVTALRM,
+ * or ITIMER_PROF (2) for SIGPROF.
+ * the rest of the parameters are pointers to millisecond values.
+ * interval is the value to which the timer will be reset
+ * value is the current timer value
+ * ointerval and ovalue are the previous values
+ */
+
+long ARGS_ON_STACK
+t_setitimer(which, interval, value, ointerval, ovalue)
+	short which;
+	long *interval;
+	long *value;
+	long *ointerval;
+	long *ovalue;
+{
+	long oldtimer;
+	TIMEOUT *t;
+	void (*handler)() = 0;
+	long tmpold;
+
+	if ((which != ITIMER_REAL) && (which != ITIMER_VIRTUAL)
+		&& (which != ITIMER_PROF)) {
+			return EINVFN;
+	}
+
+/* ensure that any addresses specified by the calling process are in that
+   process's address space
+*/
+	if ((interval && (!(valid_address((long) interval))))
+		|| (value && (!(valid_address((long) value))))
+		|| (ointerval && (!(valid_address((long) ointerval))))
+		|| (ovalue && (!(valid_address((long) ovalue))))) {
+			return EIMBA;
+	}
+
+/* see how many milliseconds there were to the timeout */
+	oldtimer = 0;
+
+	if (curproc->itimer[which].timeout) {
+		for (t = tlist; t; t = t->next) {
+			oldtimer += t->when;
+			if (t == curproc->itimer[which].timeout)
+				goto foundtimer;
+		}
+		DEBUG(("Tsetitimer: old timer not found!"));
+		oldtimer = 0;
+foundtimer:
+		;
+	}
+
+	if (ointerval)
+		*ointerval = curproc->itimer[which].interval;
+	if (ovalue) {
+		if (which == ITIMER_REAL) {
+			*ovalue = oldtimer;
+		} else {
+		  tmpold = curproc->itimer[which].reqtime
+		    - (curproc->systime - curproc->itimer[which].startsystime);
+		  if (which == ITIMER_PROF)
+		    tmpold -=
+		      (curproc->usrtime - curproc->itimer[which].startusrtime);
+		  if (tmpold <= 0)
+			tmpold = 0;
+		  *ovalue = tmpold;
+		}
+	}
+	if (interval)
+		curproc->itimer[which].interval = *interval;
+	if (value) {
+/* cancel old timer */
+		if (curproc->itimer[which].timeout)
+			canceltimeout(curproc->itimer[which].timeout);
+		curproc->itimer[which].timeout = 0;
+
+/* add a new timer, to occur in x milliseconds */
+		if (*value) {
+			curproc->itimer[which].reqtime = *value;
+			curproc->itimer[which].startsystime =
+				curproc->systime;
+			curproc->itimer[which].startusrtime =
+				curproc->usrtime;
+			switch (which) {
+				case ITIMER_REAL:
+					handler = itimer_real_me;
+					break;
+				case ITIMER_VIRTUAL:
+					handler = itimer_virtual_me;
+					break;
+				case ITIMER_PROF:
+					handler = itimer_prof_me;
+					break;
+				default:
+					break;
+			}
+			curproc->itimer[which].timeout =
+				addtimeout(*value, handler);
+		}
+		else
+			curproc->itimer[which].timeout = 0;
+	}
+	return 0;
+}
+
 /*
  * sysconf(which): returns information about system configuration.
  * "which" specifies which aspect of the system configuration is to
@@ -697,4 +902,5 @@
 	dos_tab[0x146] = p_setauid;
 	dos_tab[0x147] = p_getgroups;
 	dos_tab[0x148] = p_setgroups;
+	dos_tab[0x149] = t_setitimer;
 }
diff -u ../old/proc.c ./proc.c
--- ../old/proc.c	Fri Jul 22 03:48:56 1994
+++ ./proc.c	Fri Jul 22 03:15:54 1994
@@ -116,6 +116,15 @@
 	p->slices = SLICES(p->pri);
 	p->starttime = timestamp;
 	p->startdate = datestamp;
+	p->itimer[0].interval = 0;
+	p->itimer[0].reqtime = 0;
+	p->itimer[0].timeout = 0;
+	p->itimer[1].interval = 0;
+	p->itimer[1].reqtime = 0;
+	p->itimer[1].timeout = 0;
+	p->itimer[2].interval = 0;
+	p->itimer[2].reqtime = 0;
+	p->itimer[2].timeout = 0;
 
 	((long *)p->sysstack)[1] = FRAME_MAGIC;
 	((long *)p->sysstack)[2] = 0;
diff -u ../old/proc.h ./proc.h
--- ../old/proc.h	Fri Jul 22 03:48:58 1994
+++ ./proc.h	Wed Jul 20 13:16:44 1994
@@ -69,6 +69,14 @@
 	void	(*func) P_((struct proc *)); /* function to call at timeout */
 	short	flags;
 } TIMEOUT;
+
+struct itimervalue {
+	TIMEOUT *timeout;
+	long interval;
+	long reqtime;
+	long startsystime;
+	long startusrtime;
+};
 
 #ifndef GENMAGIC
 extern TIMEOUT *tlist;
@@ -224,6 +232,7 @@
 #define	NGROUPMAX	8
 	short	ngroups;		/* ts: number of supplementary groups */
 	short	ngroup[NGROUPMAX];	/* ts: supplementary groups */
+	struct itimervalue itimer[3];	/* interval timers */
 } PROC;
 
 
diff -u ../old/proto.h ./proto.h
--- ../old/proto.h	Fri Jul 22 03:50:08 1994
+++ ./proto.h	Fri Jul 22 04:15:26 1994
@@ -93,6 +93,7 @@
 long ARGS_ON_STACK p_pause P_((void));
 long ARGS_ON_STACK t_alarm P_((long x));
 long ARGS_ON_STACK t_malarm P_((long x));
+long ARGS_ON_STACK t_setitimer P_((short which, long *interval, long *value, long *ointerval, long *ovalue));
 long ARGS_ON_STACK s_ysconf P_((int which));
 long ARGS_ON_STACK s_alert P_((char *msg));
 void init_dos P_((void));

--
entropy -- it's not just a good idea, it's the second law.
Personal mail:      entropy@gnu.ai.mit.edu
MiNT library mail:  entropy@terminator.rs.itd.umich.edu
"what do you have against octal?" -jrb