linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/7] posix-timers: tidy up clock interfaces and consolidate dispatch logic
@ 2005-01-23 23:22 Roland McGrath
  2005-01-25  2:15 ` George Anzinger
  0 siblings, 1 reply; 5+ messages in thread
From: Roland McGrath @ 2005-01-23 23:22 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds
  Cc: linux-kernel, Christoph Lameter, Ulrich Drepper

This patch cleans up the posix-timers interfaces for defining clocks, and
the calls to them.  It fixes some sloppy types, adds a clockid_t parameter
to the calls that lacked it, and adds a function pointer that can be used
for clock_getres.  It further cleans up the posix-timers.c code using the
k_clock function pointers or default functions when no hooks are supplied,
consolidating repeated code into shared inline functions or macros.  
This paves the way for adding the CPU clock hooks.

The mmtimer.c changes are untested, but obviously can't be wrong.
There aren't any other struct k_clock definitions in the tree, but any
others would need to be updated for the function signature changes.


Signed-off-by: Roland McGrath <roland@redhat.com>

--- linux-2.6/drivers/char/mmtimer.c
+++ linux-2.6/drivers/char/mmtimer.c
@@ -378,7 +378,7 @@ static int sgi_clock_period;
 static struct timespec sgi_clock_offset;
 static int sgi_clock_period;
 
-static int sgi_clock_get(struct timespec *tp)
+static int sgi_clock_get(clockid_t clockid, struct timespec *tp)
 {
 	u64 nsec;
 
@@ -389,7 +389,7 @@ static int sgi_clock_get(struct timespec
 	return 0;
 };
 
-static int sgi_clock_set(struct timespec *tp)
+static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
 {
 
 	u64 nsec;
--- linux-2.6/include/linux/posix-timers.h
+++ linux-2.6/include/linux/posix-timers.h
@@ -30,12 +30,12 @@ struct k_clock_abs {
 };
 struct k_clock {
 	int res;		/* in nano seconds */
+	int (*clock_getres) (clockid_t which_clock, struct timespec *tp);
 	struct k_clock_abs *abs_struct;
-	int (*clock_set) (struct timespec * tp);
-	int (*clock_get) (struct timespec * tp);
+	int (*clock_set) (clockid_t which_clock, struct timespec * tp);
+	int (*clock_get) (clockid_t which_clock, struct timespec * tp);
 	int (*timer_create) (struct k_itimer *timer);
-	int (*nsleep) (int which_clock, int flags,
-		       struct timespec * t);
+	int (*nsleep) (clockid_t which_clock, int flags, struct timespec *);
 	int (*timer_set) (struct k_itimer * timr, int flags,
 			  struct itimerspec * new_setting,
 			  struct itimerspec * old_setting);
@@ -44,12 +44,12 @@ struct k_clock {
 			   struct itimerspec * cur_setting);
 };
 
-void register_posix_clock(int clock_id, struct k_clock *new_clock);
+void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock);
 
 /* Error handlers for timer_create, nanosleep and settime */
 int do_posix_clock_notimer_create(struct k_itimer *timer);
-int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);
-int do_posix_clock_nosettime(struct timespec *tp);
+int do_posix_clock_nonanosleep(clockid_t, int flags, struct timespec *);
+int do_posix_clock_nosettime(clockid_t, struct timespec *tp);
 
 /* function to call to trigger timer event */
 int posix_timer_event(struct k_itimer *timr, int si_private);
--- linux-2.6/kernel/posix-timers.c
+++ linux-2.6/kernel/posix-timers.c
@@ -173,22 +173,12 @@ static struct k_clock posix_clocks[MAX_C
 static struct k_clock_abs abs_list = {.list = LIST_HEAD_INIT(abs_list.list),
 				      .lock = SPIN_LOCK_UNLOCKED};
 
-#define if_clock_do(clock_fun,alt_fun,parms) \
-		(!clock_fun) ? alt_fun parms : clock_fun parms
-
-#define p_timer_get(clock,a,b) \
-	       	if_clock_do((clock)->timer_get,do_timer_gettime, (a,b))
-
-#define p_nsleep(clock,a,b,c) \
-		if_clock_do((clock)->nsleep, do_nsleep, (a,b,c))
-
-#define p_timer_del(clock,a) \
-		if_clock_do((clock)->timer_del, do_timer_delete, (a))
-
-static int do_posix_gettime(struct k_clock *clock, struct timespec *tp);
+static void posix_timer_fn(unsigned long);
 static u64 do_posix_clock_monotonic_gettime_parts(
 	struct timespec *tp, struct timespec *mo);
 int do_posix_clock_monotonic_gettime(struct timespec *tp);
+static int do_posix_clock_monotonic_get(clockid_t, struct timespec *tp);
+
 static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
 
 static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
@@ -197,6 +187,109 @@ static inline void unlock_timer(struct k
 }
 
 /*
+ * Define this to initialize every k_clock function table so all its
+ * function pointers are non-null, and always do indirect calls through the
+ * table.  Leave it undefined to instead leave null function pointers and
+ * decide at the call sites between a direct call (maybe inlined) to the
+ * default function and an indirect call through the table when it's filled
+ * in.  Which style is preferable is whichever performs better in the
+ * common case of using the default functions.
+ *
+#define CLOCK_DISPATCH_DIRECT
+ */
+
+#ifdef CLOCK_DISPATCH_DIRECT
+#define CLOCK_DISPATCH(clock, call, arglist) \
+	((*posix_clocks[clock].call) arglist)
+#define DEFHOOK(name)	if (clock->name == NULL) clock->name = common_##name
+#define COMMONDEFN	static
+#else
+#define CLOCK_DISPATCH(clock, call, arglist) \
+	(posix_clocks[clock].call != NULL \
+	 ? (*posix_clocks[clock].call) arglist : common_##call arglist)
+#define DEFHOOK(name)		(void) 0 /* Nothing here.  */
+#define COMMONDEFN	static inline
+#endif
+
+/*
+ * Default clock hook functions when the struct k_clock passed
+ * to register_posix_clock leaves a function pointer null.
+ *
+ * The function common_CALL is the default implementation for
+ * the function pointer CALL in struct k_clock.
+ */
+
+COMMONDEFN int common_clock_getres(clockid_t which_clock, struct timespec *tp)
+{
+	tp->tv_sec = 0;
+	tp->tv_nsec = posix_clocks[which_clock].res;
+	return 0;
+}
+
+COMMONDEFN int common_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+	getnstimeofday(tp);
+	return 0;
+}
+
+COMMONDEFN int common_clock_set(clockid_t which_clock, struct timespec *tp)
+{
+	return do_sys_settimeofday(tp, NULL);
+}
+
+COMMONDEFN int common_timer_create(struct k_itimer *new_timer)
+{
+	init_timer(&new_timer->it_timer);
+	new_timer->it_timer.expires = 0;
+	new_timer->it_timer.data = (unsigned long) new_timer;
+	new_timer->it_timer.function = posix_timer_fn;
+	set_timer_inactive(new_timer);
+	return 0;
+}
+
+/*
+ * These ones are defined below.
+ */
+static int common_nsleep(clockid_t, int flags, struct timespec *t);
+static void common_timer_get(struct k_itimer *, struct itimerspec *);
+static int common_timer_set(struct k_itimer *, int,
+			    struct itimerspec *, struct itimerspec *);
+static int common_timer_del(struct k_itimer *timer);
+
+/*
+ * Install default functions for hooks not filled in.
+ */
+static inline void common_default_hooks(struct k_clock *clock)
+{
+	DEFHOOK(clock_getres);
+	DEFHOOK(clock_get);
+	DEFHOOK(clock_set);
+	DEFHOOK(timer_create);
+	DEFHOOK(timer_set);
+	DEFHOOK(timer_get);
+	DEFHOOK(timer_del);
+	DEFHOOK(nsleep);
+}
+#undef	DEFHOOK
+
+/*
+ * Return nonzero iff we know a priori this clockid_t value is bogus.
+ */
+static inline int invalid_clockid(clockid_t which_clock)
+{
+	if ((unsigned) which_clock >= MAX_CLOCKS)
+		return 1;
+	if (posix_clocks[which_clock].clock_getres != NULL)
+		return 0;
+#ifndef CLOCK_DISPATCH_DIRECT
+	if (posix_clocks[which_clock].res != 0)
+		return 0;
+#endif
+	return 1;
+}
+
+
+/*
  * Initialize everything, well, just everything in Posix clocks/timers ;)
  */
 static __init int init_posix_timers(void)
@@ -206,7 +299,7 @@ static __init int init_posix_timers(void
 	};
 	struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES,
 		.abs_struct = NULL,
-		.clock_get = do_posix_clock_monotonic_gettime,
+		.clock_get = do_posix_clock_monotonic_get,
 		.clock_set = do_posix_clock_nosettime
 	};
 
@@ -481,7 +574,7 @@ static inline struct task_struct * good_
 	return rtn;
 }
 
-void register_posix_clock(int clock_id, struct k_clock *new_clock)
+void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock)
 {
 	if ((unsigned) clock_id >= MAX_CLOCKS) {
 		printk("POSIX clock register failed for clock_id %d\n",
@@ -488,7 +581,9 @@ void register_posix_clock(int clock_id, 
 		       clock_id);
 		return;
 	}
+
 	posix_clocks[clock_id] = *new_clock;
+	common_default_hooks(&posix_clocks[clock_id]);
 }
 
 static struct k_itimer * alloc_posix_timer(void)
@@ -538,8 +633,7 @@ sys_timer_create(clockid_t which_clock,
 	sigevent_t event;
 	int it_id_set = IT_ID_NOT_SET;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-				!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 
 	new_timer = alloc_posix_timer();
@@ -573,17 +667,9 @@ sys_timer_create(clockid_t which_clock,
 	new_timer->it_clock = which_clock;
 	new_timer->it_incr = 0;
 	new_timer->it_overrun = -1;
-	if (posix_clocks[which_clock].timer_create) {
-		error =  posix_clocks[which_clock].timer_create(new_timer);
-		if (error)
-			goto out;
-	} else {
-		init_timer(&new_timer->it_timer);
-		new_timer->it_timer.expires = 0;
-		new_timer->it_timer.data = (unsigned long) new_timer;
-		new_timer->it_timer.function = posix_timer_fn;
-		set_timer_inactive(new_timer);
-	}
+	error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
+	if (error)
+		goto out;
 
 	/*
 	 * return the timer_id now.  The next step is hard to
@@ -734,7 +820,7 @@ static struct k_itimer * lock_timer(time
  * report.
  */
 static void
-do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting)
+common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
 {
 	unsigned long expires;
 	struct now_struct now;
@@ -783,7 +869,7 @@ sys_timer_gettime(timer_t timer_id, stru
 	if (!timr)
 		return -EINVAL;
 
-	p_timer_get(&posix_clocks[timr->it_clock], timr, &cur_setting);
+	CLOCK_DISPATCH(timr->it_clock, timer_get, (timr, &cur_setting));
 
 	unlock_timer(timr, flags);
 
@@ -854,7 +940,7 @@ static int adjust_abs_time(struct k_cloc
 			/*
 			 * Not one of the basic clocks
 			 */
-			do_posix_gettime(clock, &now);	
+			clock->clock_get(clock - posix_clocks, &now);
 			jiffies_64_f = get_jiffies_64();
 		}
 		/*
@@ -906,15 +992,15 @@ static int adjust_abs_time(struct k_cloc
 
 /* Set a POSIX.1b interval timer. */
 /* timr->it_lock is taken. */
-static inline int
-do_timer_settime(struct k_itimer *timr, int flags,
+COMMONDEFN int
+common_timer_set(struct k_itimer *timr, int flags,
 		 struct itimerspec *new_setting, struct itimerspec *old_setting)
 {
 	struct k_clock *clock = &posix_clocks[timr->it_clock];
 	u64 expire_64;
 
 	if (old_setting)
-		do_timer_gettime(timr, old_setting);
+		common_timer_get(timr, old_setting);
 
 	/* disable the timer */
 	timr->it_incr = 0;
@@ -1003,12 +1089,9 @@ retry:
 	if (!timr)
 		return -EINVAL;
 
-	if (!posix_clocks[timr->it_clock].timer_set)
-		error = do_timer_settime(timr, flags, &new_spec, rtn);
-	else
-	        error = posix_clocks[timr->it_clock].timer_set(timr,
-							       flags,
-							       &new_spec, rtn);
+	error = CLOCK_DISPATCH(timr->it_clock, timer_set,
+			       (timr, flags, &new_spec, rtn));
+
 	unlock_timer(timr, flag);
 	if (error == TIMER_RETRY) {
 		rtn = NULL;	// We already got the old time...
@@ -1022,7 +1105,7 @@ retry:
 	return error;
 }
 
-static inline int do_timer_delete(struct k_itimer *timer)
+COMMONDEFN int common_timer_del(struct k_itimer *timer)
 {
 	timer->it_incr = 0;
 #ifdef CONFIG_SMP
@@ -1044,6 +1127,11 @@ static inline int do_timer_delete(struct
 	return 0;
 }
 
+static inline int timer_delete_hook(struct k_itimer *timer)
+{
+	return CLOCK_DISPATCH(timer->it_clock, timer_del, (timer));
+}
+
 /* Delete a POSIX.1b interval timer. */
 asmlinkage long
 sys_timer_delete(timer_t timer_id)
@@ -1060,14 +1148,14 @@ retry_delete:
 		return -EINVAL;
 
 #ifdef CONFIG_SMP
-	error = p_timer_del(&posix_clocks[timer->it_clock], timer);
+	error = timer_delete_hook(timer);
 
 	if (error == TIMER_RETRY) {
 		unlock_timer(timer, flags);
 		goto retry_delete;
 	}
 #else
-	p_timer_del(&posix_clocks[timer->it_clock], timer);
+	timer_delete_hook(timer);
 #endif
 	spin_lock(&current->sighand->siglock);
 	list_del(&timer->list);
@@ -1099,14 +1187,14 @@ retry_delete:
 	spin_lock_irqsave(&timer->it_lock, flags);
 
 #ifdef CONFIG_SMP
-	error = p_timer_del(&posix_clocks[timer->it_clock], timer);
+	error = timer_delete_hook(timer);
 
 	if (error == TIMER_RETRY) {
 		unlock_timer(timer, flags);
 		goto retry_delete;
 	}
 #else
-	p_timer_del(&posix_clocks[timer->it_clock], timer);
+	timer_delete_hook(timer);
 #endif
 	list_del(&timer->list);
 	/*
@@ -1143,14 +1231,6 @@ void exit_itimers(struct signal_struct *
  * spin_lock_irq() held and from clock calls with no locking.	They must
  * use the save flags versions of locks.
  */
-static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
-{
-	if (clock->clock_get)
-		return clock->clock_get(tp);
-
-	getnstimeofday(tp);
-	return 0;
-}
 
 /*
  * We do ticks here to avoid the irq lock ( they take sooo long).
@@ -1177,7 +1257,7 @@ static u64 do_posix_clock_monotonic_gett
 	return jiff;
 }
 
-int do_posix_clock_monotonic_gettime(struct timespec *tp)
+static int do_posix_clock_monotonic_get(clockid_t clock, struct timespec *tp)
 {
 	struct timespec wall_to_mono;
 
@@ -1193,7 +1273,13 @@ int do_posix_clock_monotonic_gettime(str
 	return 0;
 }
 
-int do_posix_clock_nosettime(struct timespec *tp)
+int do_posix_clock_monotonic_gettime(struct timespec *tp)
+{
+	return do_posix_clock_monotonic_get(CLOCK_MONOTONIC, tp);
+}
+
+
+int do_posix_clock_nosettime(clockid_t clockid, struct timespec *tp)
 {
 	return -EINVAL;
 }
@@ -1203,7 +1289,7 @@ int do_posix_clock_notimer_create(struct
 	return -EINVAL;
 }
 
-int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec *t)
+int do_posix_clock_nonanosleep(clockid_t clock, int flags, struct timespec *t)
 {
 #ifndef ENOTSUP
 	return -EOPNOTSUPP;	/* aka ENOTSUP in userland for POSIX */
@@ -1217,24 +1303,12 @@ sys_clock_settime(clockid_t which_clock,
 {
 	struct timespec new_tp;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 	if (copy_from_user(&new_tp, tp, sizeof (*tp)))
 		return -EFAULT;
-	if (posix_clocks[which_clock].clock_set)
-		return posix_clocks[which_clock].clock_set(&new_tp);
 
-	return do_sys_settimeofday(&new_tp, NULL);
-}
-
-static int do_clock_gettime(clockid_t which_clock, struct timespec *tp)
-{
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
-		return -EINVAL;
-
-	return do_posix_gettime(&posix_clocks[which_clock], tp);
+	return CLOCK_DISPATCH(which_clock, clock_set, (which_clock, &new_tp));
 }
 
 asmlinkage long
@@ -1243,7 +1317,10 @@ sys_clock_gettime(clockid_t which_clock,
 	struct timespec kernel_tp;
 	int error;
 
-	error = do_clock_gettime(which_clock, &kernel_tp);
+	if (invalid_clockid(which_clock))
+		return -EINVAL;
+	error = CLOCK_DISPATCH(which_clock, clock_get,
+			       (which_clock, &kernel_tp));
 	if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
 		error = -EFAULT;
 
@@ -1255,18 +1332,19 @@ asmlinkage long
 sys_clock_getres(clockid_t which_clock, struct timespec __user *tp)
 {
 	struct timespec rtn_tp;
+	int error;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 
-	rtn_tp.tv_sec = 0;
-	rtn_tp.tv_nsec = posix_clocks[which_clock].res;
-	if (tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
-		return -EFAULT;
+	error = CLOCK_DISPATCH(which_clock, clock_getres,
+			       (which_clock, &rtn_tp));
 
-	return 0;
+	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) {
+		error = -EFAULT;
+	}
 
+	return error;
 }
 
 static void nanosleep_wake_up(unsigned long __data)
@@ -1379,9 +1457,6 @@ void clock_was_set(void)
 
 long clock_nanosleep_restart(struct restart_block *restart_block);
 
-extern long do_clock_nanosleep(clockid_t which_clock, int flags,
-			       struct timespec *t);
-
 asmlinkage long
 sys_clock_nanosleep(clockid_t which_clock, int flags,
 		    const struct timespec __user *rqtp,
@@ -1392,8 +1467,7 @@ sys_clock_nanosleep(clockid_t which_cloc
 	    &(current_thread_info()->restart_block);
 	int ret;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 
 	if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
@@ -1402,12 +1476,10 @@ sys_clock_nanosleep(clockid_t which_cloc
 	if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0)
 		return -EINVAL;
 
-	if (posix_clocks[which_clock].nsleep)
-		ret = posix_clocks[which_clock].nsleep(which_clock, flags, &t);
-	else
-		ret = do_clock_nanosleep(which_clock, flags, &t);
+	ret = CLOCK_DISPATCH(which_clock, nsleep, (which_clock, flags, &t));
+
 	/*
-	 * Do this here as do_clock_nanosleep does not have the real address
+	 * Do this here as common_nsleep does not have the real address
 	 */
 	restart_block->arg1 = (unsigned long)rmtp;
 
@@ -1417,8 +1489,9 @@ sys_clock_nanosleep(clockid_t which_cloc
 	return ret;
 }
 
-long
-do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave)
+
+static int common_nsleep(clockid_t which_clock,
+			 int flags, struct timespec *tsave)
 {
 	struct timespec t, dum;
 	struct timer_list new_timer;
@@ -1525,7 +1598,7 @@ long
 clock_nanosleep_restart(struct restart_block *restart_block)
 {
 	struct timespec t;
-	int ret = do_clock_nanosleep(restart_block->arg0, 0, &t);
+	int ret = common_nsleep(restart_block->arg0, 0, &t);
 
 	if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 &&
 	    copy_to_user((struct timespec __user *)(restart_block->arg1), &t,

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/7] posix-timers: tidy up clock interfaces and consolidate dispatch logic
  2005-01-23 23:22 [PATCH 1/7] posix-timers: tidy up clock interfaces and consolidate dispatch logic Roland McGrath
@ 2005-01-25  2:15 ` George Anzinger
  2005-01-25  2:49   ` Andrew Morton
  2005-01-25  4:11   ` Ulrich Drepper
  0 siblings, 2 replies; 5+ messages in thread
From: George Anzinger @ 2005-01-25  2:15 UTC (permalink / raw)
  To: Roland McGrath
  Cc: Andrew Morton, Linus Torvalds, linux-kernel, Christoph Lameter,
	Ulrich Drepper

Where were you when I was writing this stuff :).  I agree with most all of it, 
save the following:

 >  /*
 > + * Define this to initialize every k_clock function table so all its
 > + * function pointers are non-null, and always do indirect calls through the
 > + * table.  Leave it undefined to instead leave null function pointers and
 > + * decide at the call sites between a direct call (maybe inlined) to the
 > + * default function and an indirect call through the table when it's filled
 > + * in.  Which style is preferable is whichever performs better in the
 > + * common case of using the default functions.

 > +#define CLOCK_DISPATCH_DIRECT

As I understand it modern machines, the indirect call does really bad things to 
the pipeline.  The default call, even preceeded by the if, will be much faster 
by this reasoning.  I would, therefor, prefer not defining CLOCK_DISPATCH_DIRECT.


-- 
George Anzinger   george@mvista.com
High-res-timers:  http://sourceforge.net/projects/high-res-timers/


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/7] posix-timers: tidy up clock interfaces and consolidate dispatch logic
  2005-01-25  2:15 ` George Anzinger
@ 2005-01-25  2:49   ` Andrew Morton
  2005-01-25 23:13     ` Roland McGrath
  2005-01-25  4:11   ` Ulrich Drepper
  1 sibling, 1 reply; 5+ messages in thread
From: Andrew Morton @ 2005-01-25  2:49 UTC (permalink / raw)
  To: george; +Cc: roland, torvalds, linux-kernel, clameter, drepper

George Anzinger <george@mvista.com> wrote:
>
>  >  /*
>   > + * Define this to initialize every k_clock function table so all its
>   > + * function pointers are non-null, and always do indirect calls through the
>   > + * table.  Leave it undefined to instead leave null function pointers and
>   > + * decide at the call sites between a direct call (maybe inlined) to the
>   > + * default function and an indirect call through the table when it's filled
>   > + * in.  Which style is preferable is whichever performs better in the
>   > + * common case of using the default functions.
> 
>   > +#define CLOCK_DISPATCH_DIRECT
> 
>  As I understand it modern machines, the indirect call does really bad things to 
>  the pipeline.  The default call, even preceeded by the if, will be much faster 
>  by this reasoning.  I would, therefor, prefer not defining CLOCK_DISPATCH_DIRECT.

We do need to do one or the other.  I assume the current indecision is
pending some benchmarking work?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/7] posix-timers: tidy up clock interfaces and consolidate dispatch logic
  2005-01-25  2:15 ` George Anzinger
  2005-01-25  2:49   ` Andrew Morton
@ 2005-01-25  4:11   ` Ulrich Drepper
  1 sibling, 0 replies; 5+ messages in thread
From: Ulrich Drepper @ 2005-01-25  4:11 UTC (permalink / raw)
  To: george
  Cc: Roland McGrath, Andrew Morton, Linus Torvalds, linux-kernel,
	Christoph Lameter

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

George Anzinger wrote:
> As I understand it modern machines, the indirect call does really bad 
> things to the pipeline.

Unless the call happens often, really often, you'll not be able to 
measure differences.  Indirect jump obviously cause pipeline stalls 
which often, but not always, can be avoided with direct calls.  But we 
are not talking here about huge delays.  And the delays are equivalent 
in cost to a mispredicted branch.  If you have a couple of ifs in a row 
you are likely to incur problems with the branch prediction.  I would 
just use the indirect jumps but if you want, do some timing and see 
whether you can filter the difference out of the noise.

-- 
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/7] posix-timers: tidy up clock interfaces and consolidate dispatch logic
  2005-01-25  2:49   ` Andrew Morton
@ 2005-01-25 23:13     ` Roland McGrath
  0 siblings, 0 replies; 5+ messages in thread
From: Roland McGrath @ 2005-01-25 23:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: george, torvalds, linux-kernel, clameter, drepper

> We do need to do one or the other.  I assume the current indecision is
> pending some benchmarking work?

That was more or less the idea.  But I kind of figured someone would just
tell me which one to do without actually doing any timings.  This patch
(applies after the cpuclocks patch) makes the one decision, to use
conditional branches rather than indirect calls in the common case.
That is consistent with what the old code did.  


Thanks,
Roland


Signed-off-by: Roland McGrath <roland@redhat.com>

--- linux-2.6/kernel/posix-timers.c
+++ linux-2.6/kernel/posix-timers.c
@@ -185,31 +185,12 @@ static inline void unlock_timer(struct k
 }
 
 /*
- * Define this to initialize every k_clock function table so all its
- * function pointers are non-null, and always do indirect calls through the
- * table.  Leave it undefined to instead leave null function pointers and
- * decide at the call sites between a direct call (maybe inlined) to the
- * default function and an indirect call through the table when it's filled
- * in.  Which style is preferable is whichever performs better in the
- * common case of using the default functions.
- *
-#define CLOCK_DISPATCH_DIRECT
+ * Call the k_clock hook function if non-null, or the default function.
  */
-
-#ifdef CLOCK_DISPATCH_DIRECT
 #define CLOCK_DISPATCH(clock, call, arglist) \
-	((clock) < 0 ? posix_cpu_##call arglist : \
-	 (*posix_clocks[clock].call) arglist)
-#define DEFHOOK(name)	if (clock->name == NULL) clock->name = common_##name
-#define COMMONDEFN	static
-#else
-#define CLOCK_DISPATCH(clock, call, arglist) \
-	((clock) < 0 ? posix_cpu_##call arglist : \
-	 (posix_clocks[clock].call != NULL \
-	  ? (*posix_clocks[clock].call) arglist : common_##call arglist))
-#define DEFHOOK(name)		(void) 0 /* Nothing here.  */
-#define COMMONDEFN	static inline
-#endif
+ 	((clock) < 0 ? posix_cpu_##call arglist : \
+ 	 (posix_clocks[clock].call != NULL \
+ 	  ? (*posix_clocks[clock].call) arglist : common_##call arglist))
 
 /*
  * Default clock hook functions when the struct k_clock passed
@@ -219,25 +200,26 @@ static inline void unlock_timer(struct k
  * the function pointer CALL in struct k_clock.
  */
 
-COMMONDEFN int common_clock_getres(clockid_t which_clock, struct timespec *tp)
+static inline int common_clock_getres(clockid_t which_clock,
+				      struct timespec *tp)
 {
 	tp->tv_sec = 0;
 	tp->tv_nsec = posix_clocks[which_clock].res;
 	return 0;
 }
 
-COMMONDEFN int common_clock_get(clockid_t which_clock, struct timespec *tp)
+static inline int common_clock_get(clockid_t which_clock, struct timespec *tp)
 {
 	getnstimeofday(tp);
 	return 0;
 }
 
-COMMONDEFN int common_clock_set(clockid_t which_clock, struct timespec *tp)
+static inline int common_clock_set(clockid_t which_clock, struct timespec *tp)
 {
 	return do_sys_settimeofday(tp, NULL);
 }
 
-COMMONDEFN int common_timer_create(struct k_itimer *new_timer)
+static inline int common_timer_create(struct k_itimer *new_timer)
 {
 	new_timer->it.real.incr = 0;
 	init_timer(&new_timer->it.real.timer);
@@ -258,22 +240,6 @@ static int common_timer_set(struct k_iti
 static int common_timer_del(struct k_itimer *timer);
 
 /*
- * Install default functions for hooks not filled in.
- */
-static inline void common_default_hooks(struct k_clock *clock)
-{
-	DEFHOOK(clock_getres);
-	DEFHOOK(clock_get);
-	DEFHOOK(clock_set);
-	DEFHOOK(timer_create);
-	DEFHOOK(timer_set);
-	DEFHOOK(timer_get);
-	DEFHOOK(timer_del);
-	DEFHOOK(nsleep);
-}
-#undef	DEFHOOK
-
-/*
  * Return nonzero iff we know a priori this clockid_t value is bogus.
  */
 static inline int invalid_clockid(clockid_t which_clock)
@@ -589,7 +555,6 @@ void register_posix_clock(clockid_t cloc
 	}
 
 	posix_clocks[clock_id] = *new_clock;
-	common_default_hooks(&posix_clocks[clock_id]);
 }
 
 static struct k_itimer * alloc_posix_timer(void)
@@ -997,7 +962,7 @@ static int adjust_abs_time(struct k_cloc
 
 /* Set a POSIX.1b interval timer. */
 /* timr->it_lock is taken. */
-COMMONDEFN int
+static inline int
 common_timer_set(struct k_itimer *timr, int flags,
 		 struct itimerspec *new_setting, struct itimerspec *old_setting)
 {
@@ -1110,7 +1075,7 @@ retry:
 	return error;
 }
 
-COMMONDEFN int common_timer_del(struct k_itimer *timer)
+static inline int common_timer_del(struct k_itimer *timer)
 {
 	timer->it.real.incr = 0;
 #ifdef CONFIG_SMP

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2005-01-25 23:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-01-23 23:22 [PATCH 1/7] posix-timers: tidy up clock interfaces and consolidate dispatch logic Roland McGrath
2005-01-25  2:15 ` George Anzinger
2005-01-25  2:49   ` Andrew Morton
2005-01-25 23:13     ` Roland McGrath
2005-01-25  4:11   ` Ulrich Drepper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).