diff mbox

[V8,08/13] posix clocks: cleanup the CLOCK_DISPTACH macro

Message ID 503cd1fa268867573001cfc9bb5681ee3b5b32fa.1293820862.git.richard.cochran@omicron.at
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Richard Cochran Dec. 31, 2010, 7:15 p.m. UTC
Paraphrasing tglx:

This patch simplifies and clarifies the code, doing the normal thing
with function pointer structures. Stuff which is not implemented does
not magically become called via some common function. There is no
point in doing that.

We fill in the various k_clock structs with the correct pointers in
the first place and let the NULL case return a sensible error
value. The data structure does not become larger that way. It's a
little bit more init code, but that's fine if we make the code better
in general. In that case it's not even more init code, it's just
filling the data structures which we register.

My own words:

For now, each of the registered k_clocks has the previously NULL
functions assigned to the common_xyz function, since that usage was
implicitly enforced by the CLOCK_DISPTACH macro. These functions are
marked with a /* default: */ comment.

As as possible further improvement for the future, one could go
through and replace the various no_xyz function pointers in the
k_clocks with NULL pointers.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
---
 include/linux/posix-timers.h |   14 +++
 include/linux/time.h         |    2 +
 kernel/posix-timers.c        |  241 ++++++++++++++++++++++++++++++++++--------
 3 files changed, 213 insertions(+), 44 deletions(-)

Comments

Peter Zijlstra Jan. 3, 2011, 9:29 a.m. UTC | #1
On Fri, 2010-12-31 at 20:15 +0100, Richard Cochran wrote:
> +#define CLOCK_DISPATCH(clock, call, arglist) dispatch_##call arglist

How about you run something like:

 :% s/CLOCK_DISPATCH([^,]*, \([^,]*\), \([^)]*)\))/dispatch_\1\2/g

and remove that cruft all together?

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Richard Cochran Jan. 3, 2011, 11:51 a.m. UTC | #2
On Mon, Jan 03, 2011 at 10:29:09AM +0100, Peter Zijlstra wrote:
> On Fri, 2010-12-31 at 20:15 +0100, Richard Cochran wrote:
> > +#define CLOCK_DISPATCH(clock, call, arglist) dispatch_##call arglist
> 
> How about you run something like:
> 
>  :% s/CLOCK_DISPATCH([^,]*, \([^,]*\), \([^)]*)\))/dispatch_\1\2/g
> 
> and remove that cruft all together?

Gladly ;^)

Richard

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thomas Gleixner Jan. 11, 2011, 12:57 p.m. UTC | #3
On Fri, 31 Dec 2010, Richard Cochran wrote:
> +static inline bool clock_is_posix_cpu(const clockid_t id)
> +{
> +	if ((id & CLOCKFD_MASK) == CLOCKFD)
> +		return false;
> +	else
> +		return true;
> +}
> +
> +static inline int dispatch_clock_getres(const clockid_t id, struct timespec *ts)
> +{
> +	if (id >= 0) {
> +		return posix_clocks[id].clock_getres ?
> +			posix_clocks[id].clock_getres(id, ts) : -EINVAL;
> +	}
> +
> +	if (clock_is_posix_cpu(id))
> +		return posix_cpu_clock_getres(id, ts);

I wonder whether we should be a bit more clever here and create an
extra entry for posix_cpu_timers in the posix_clocks array and do the
following:

/* These are local to posix-timer.c and not exposed to anything else */
#define POSIX_INV_CLOCK_ID	MAX_CLOCKS
#define POSIX_CPU_CLOCK_ID	(MAX_CLOCKS + 1)
#define NR_CLOCK_ENTRIES	(MAX_CLOCKS + 2)

static struct k_clock posix_clocks[NR_CLOCK_ENTRIES];

static __init int init_posix_timers(void)
{
	......
	/*
	 * We leave the POSIX_INV_CLOCK_ID entries zeroed out, so the 
	 * the dispatch code will return -EINVAL.
	 */

	init_posix_cpu_timer_entries();
}

static clockid_t clock_get_array_id(const clockid_t id)
{
	if (id >= 0)
	       return id < MAX_CLOCKS ? id : POSIX_INV_CLOCK_ID;

      	if (clock_is_posix_cpu(id))
		return POSIX_CPU_CLOCK_ID;

	return POSIX_INV_CLOCK_ID;
}

static inline int dispatch_clock_getres(const clockid_t id, struct timespec *ts)
{
	struct k_clock *clk = &posix_clocks[clock_get_array_id(id)];

	return clk->clock_getres ? clk->clock_getres(id, ts) : -EINVAL;
}

That reduces the code significantly and the MAX_CLOCKS check in
clock_get_array_id() replaces the invalid_clock() check in the
syscalls as well. It does not matter whether we check this before or
after copying stuff from user.

Adding your new stuff requires just another entry in the array, the
setup of the function pointers and the CLOCKFD check in
clock_get_array_id(). Everything else just falls in place.

> +
> +#define CLOCK_DISPATCH(clock, call, arglist) dispatch_##call arglist
> +

Can we get rid of this completely please ?

>  clock_nanosleep_restart(struct restart_block *restart_block)
>  {
> -	clockid_t which_clock = restart_block->arg0;
> -

How does that compile ?

>  	return CLOCK_DISPATCH(which_clock, nsleep_restart,
>  			      (restart_block));
>  }

Thanks,

	tglx
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Richard Cochran Jan. 12, 2011, 7:37 a.m. UTC | #4
On Tue, Jan 11, 2011 at 01:57:23PM +0100, Thomas Gleixner wrote:
> I wonder whether we should be a bit more clever here and create an
> extra entry for posix_cpu_timers in the posix_clocks array and do the
> following:
...
> That reduces the code significantly and the MAX_CLOCKS check in
> clock_get_array_id() replaces the invalid_clock() check in the
> syscalls as well. It does not matter whether we check this before or
> after copying stuff from user.

Well, this does reduce the number of LOC, but the number of
comparisons is the same. I think the code size would be also no
different.

> Adding your new stuff requires just another entry in the array, the
> setup of the function pointers and the CLOCKFD check in
> clock_get_array_id(). Everything else just falls in place.

For me, I am not sure if either version is really very pretty or easy
to understand.

My instinct is to keep the posix_cpu_X and pc_X functions out of the
array of static clock id functions, if only to make the distinction
between the legacy static ids and new dynamic ids clear.

The conclusion from the "dynamic clock as file" discussion was that we
don't want to add any more static clock ids, and new clocks should use
the new, dynamic clock API. So, we should discourage any future
attempt to add to that function array!

Having said that, if you insist on it, I won't mind reworking the
dispatch code as you suggested.

> > +
> > +#define CLOCK_DISPATCH(clock, call, arglist) dispatch_##call arglist
> > +
> 
> Can we get rid of this completely please ?

Yes, gladly.

> >  clock_nanosleep_restart(struct restart_block *restart_block)
> >  {
> > -	clockid_t which_clock = restart_block->arg0;
> > -
> 
> How does that compile ?

Because the CLOCK_DISPATCH macro, above, makes no use of the first
argument! I have removed the macro for the next round.

> >  	return CLOCK_DISPATCH(which_clock, nsleep_restart,
> >  			      (restart_block));
> >  }

Thanks,
Richard
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thomas Gleixner Jan. 12, 2011, 11:16 a.m. UTC | #5
On Wed, 12 Jan 2011, Richard Cochran wrote:

> On Tue, Jan 11, 2011 at 01:57:23PM +0100, Thomas Gleixner wrote:
> > I wonder whether we should be a bit more clever here and create an
> > extra entry for posix_cpu_timers in the posix_clocks array and do the
> > following:
> ...
> > That reduces the code significantly and the MAX_CLOCKS check in
> > clock_get_array_id() replaces the invalid_clock() check in the
> > syscalls as well. It does not matter whether we check this before or
> > after copying stuff from user.
> 
> Well, this does reduce the number of LOC, but the number of
> comparisons is the same. I think the code size would be also no
> different.

Right, It's about lines of code and ever repeated if / else constructs
in the dispatch functions. The number of comparisons is probably the
same, but I'm sure that the binary size will be smaller.

We probably can remove the dispatch inlines that way completely and do
the call directly from the syscall function.
 
> > Adding your new stuff requires just another entry in the array, the
> > setup of the function pointers and the CLOCKFD check in
> > clock_get_array_id(). Everything else just falls in place.
> 
> For me, I am not sure if either version is really very pretty or easy
> to understand.

Well, if we document clock_get_array_id() proper, then it's easier to
follow than 10 dispatch functions which have all the same checks and
comparisons inside.
 
> My instinct is to keep the posix_cpu_X and pc_X functions out of the
> array of static clock id functions, if only to make the distinction
> between the legacy static ids and new dynamic ids clear.
> 
> The conclusion from the "dynamic clock as file" discussion was that we
> don't want to add any more static clock ids, and new clocks should use
> the new, dynamic clock API. So, we should discourage any future
> attempt to add to that function array!

These IDs are not public, they are helpers to make the code simpler,
nothing else. I agree, that we don't want to extend the static ids for
public consumption, but implementation wise we can do that confined to
posix-timers.c.

> Having said that, if you insist on it, I won't mind reworking the
> dispatch code as you suggested.

I'm not insisting. I just saw the repeated if/else constructs and
added the clockfd check mentally :) That's where I started to wonder
about a way to do the same thing with way less lines of code.

> > >  clock_nanosleep_restart(struct restart_block *restart_block)
> > >  {
> > > -	clockid_t which_clock = restart_block->arg0;
> > > -
> > 
> > How does that compile ?
> 
> Because the CLOCK_DISPATCH macro, above, makes no use of the first

Missed that, sorry.

> argument! I have removed the macro for the next round.

Cool.

Thanks,

	tglx
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Richard Cochran Jan. 12, 2011, 12:17 p.m. UTC | #6
On Wed, Jan 12, 2011 at 12:16:10PM +0100, Thomas Gleixner wrote:
> 
> We probably can remove the dispatch inlines that way completely and do
> the call directly from the syscall function.

Right, okay. I also wanted to put the whole logic into the syscall
itself. I'll try it that way.

Thanks,

Richard
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Richard Cochran Jan. 13, 2011, 4:30 a.m. UTC | #7
On Tue, Jan 11, 2011 at 01:57:23PM +0100, Thomas Gleixner wrote:
> 
> static clockid_t clock_get_array_id(const clockid_t id)
> {
> 	if (id >= 0)
> 	       return id < MAX_CLOCKS ? id : POSIX_INV_CLOCK_ID;
> 
>       	if (clock_is_posix_cpu(id))
> 		return POSIX_CPU_CLOCK_ID;
> 
> 	return POSIX_INV_CLOCK_ID;
> }
> 
> static inline int dispatch_clock_getres(const clockid_t id, struct timespec *ts)
> {
> 	struct k_clock *clk = &posix_clocks[clock_get_array_id(id)];
> 
> 	return clk->clock_getres ? clk->clock_getres(id, ts) : -EINVAL;
> }

I would like to take this idea one step further, like so:

static struct k_clock *clockid_to_kclock(const clockid_t id)
{
	if (id >= 0)
		return id < MAX_CLOCKS ?
			&posix_clocks[id] : &posix_clocks[POSIX_INV_CLOCK_ID];
	...
}

SYSCALL( ... , const clockid_t id, struct timespec *ts)
{
	struct k_clock *clk = clockid_to_kclock(id);

	return clk->clock_getres ? clk->clock_getres(id, ts) : -EINVAL;
}

What do you think?

Thanks,

Richard
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thomas Gleixner Jan. 13, 2011, 11:25 a.m. UTC | #8
On Thu, 13 Jan 2011, Richard Cochran wrote:
> On Tue, Jan 11, 2011 at 01:57:23PM +0100, Thomas Gleixner wrote:
> > 
> > static clockid_t clock_get_array_id(const clockid_t id)
> > {
> > 	if (id >= 0)
> > 	       return id < MAX_CLOCKS ? id : POSIX_INV_CLOCK_ID;
> > 
> >       	if (clock_is_posix_cpu(id))
> > 		return POSIX_CPU_CLOCK_ID;
> > 
> > 	return POSIX_INV_CLOCK_ID;
> > }
> > 
> > static inline int dispatch_clock_getres(const clockid_t id, struct timespec *ts)
> > {
> > 	struct k_clock *clk = &posix_clocks[clock_get_array_id(id)];
> > 
> > 	return clk->clock_getres ? clk->clock_getres(id, ts) : -EINVAL;
> > }
> 
> I would like to take this idea one step further, like so:
> 
> static struct k_clock *clockid_to_kclock(const clockid_t id)
> {
> 	if (id >= 0)
> 		return id < MAX_CLOCKS ?
> 			&posix_clocks[id] : &posix_clocks[POSIX_INV_CLOCK_ID];
> 	...
> }
> 
> SYSCALL( ... , const clockid_t id, struct timespec *ts)
> {
> 	struct k_clock *clk = clockid_to_kclock(id);
> 
> 	return clk->clock_getres ? clk->clock_getres(id, ts) : -EINVAL;
> }
> 
> What do you think?

Yeah, that's even better!
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index b05d9b8..eef7f9c 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -18,6 +18,18 @@  struct cpu_timer_list {
 	int firing;
 };
 
+/* Bit fields within a clockid:
+ *
+ * The most significant 29 bits hold either a pid or a file descriptor.
+ *
+ * Bit 2 indicates whether a cpu clock refers to a thread or a process.
+ *
+ * Bits 1 and 0 give the type: PROF=0, VIRT=1, SCHED=2, or FD=3.
+ *
+ * A clockid is invalid if bits 2, 1, and 0 all set (see also CLOCK_INVALID
+ * in include/linux/time.h)
+ */
+
 #define CPUCLOCK_PID(clock)		((pid_t) ~((clock) >> 3))
 #define CPUCLOCK_PERTHREAD(clock) \
 	(((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0)
@@ -29,6 +41,8 @@  struct cpu_timer_list {
 #define CPUCLOCK_VIRT		1
 #define CPUCLOCK_SCHED		2
 #define CPUCLOCK_MAX		3
+#define CLOCKFD			CPUCLOCK_MAX
+#define CLOCKFD_MASK		(CPUCLOCK_PERTHREAD_MASK|CPUCLOCK_CLOCK_MASK)
 
 #define MAKE_PROCESS_CPUCLOCK(pid, clock) \
 	((~(clockid_t) (pid) << 3) | (clockid_t) (clock))
diff --git a/include/linux/time.h b/include/linux/time.h
index b402134..99d4b14 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -300,6 +300,8 @@  struct itimerval {
 #define CLOCKS_MASK			(CLOCK_REALTIME | CLOCK_MONOTONIC)
 #define CLOCKS_MONO			CLOCK_MONOTONIC
 
+#define CLOCK_INVALID			-1
+
 /*
  * The various flags for setting POSIX.1b interval timers:
  */
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 502bde4..65b0599 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -138,6 +138,7 @@  static struct k_clock posix_clocks[MAX_CLOCKS];
  */
 static int common_nsleep(const clockid_t, int flags, struct timespec *t,
 			 struct timespec __user *rmtp);
+static long common_nsleep_restart(struct restart_block *restart_block);
 static void common_timer_get(struct k_itimer *, struct itimerspec *);
 static int common_timer_set(struct k_itimer *, int,
 			    struct itimerspec *, struct itimerspec *);
@@ -152,41 +153,14 @@  static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
 	spin_unlock_irqrestore(&timr->it_lock, flags);
 }
 
-/*
- * Call the k_clock hook function if non-null, or the default function.
- */
-#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))
-
-/*
- * 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.
- */
 
-static inline int common_clock_getres(const clockid_t which_clock,
-				      struct timespec *tp)
-{
-	tp->tv_sec = 0;
-	tp->tv_nsec = posix_clocks[which_clock].res;
-	return 0;
-}
-
-/*
- * Get real time for posix timers
- */
 static int common_clock_get(clockid_t which_clock, struct timespec *tp)
 {
 	ktime_get_real_ts(tp);
 	return 0;
 }
 
-static inline int common_clock_set(const clockid_t which_clock,
-				   struct timespec *tp)
+static int common_clock_set(const clockid_t which_clock, struct timespec *tp)
 {
 	return do_sys_settimeofday(tp, NULL);
 }
@@ -197,7 +171,7 @@  static int common_timer_create(struct k_itimer *new_timer)
 	return 0;
 }
 
-static inline int common_clock_adj(const clockid_t which_clock, struct timex *t)
+static int common_clock_adj(const clockid_t which_clock, struct timex *t)
 {
 	return do_adjtimex(t);
 }
@@ -214,19 +188,14 @@  static int no_nsleep(const clockid_t which_clock, int flags,
 }
 
 /*
- * Return nonzero if we know a priori this clockid_t value is bogus.
+ * Return 'true' if we know a priori this clockid_t value is bogus.
  */
-static inline int invalid_clockid(const clockid_t which_clock)
+static inline bool invalid_clockid(const clockid_t which_clock)
 {
-	if (which_clock < 0)	/* CPU clock, posix_cpu_* will check it */
-		return 0;
-	if ((unsigned) which_clock >= MAX_CLOCKS)
-		return 1;
-	if (posix_clocks[which_clock].clock_getres != NULL)
-		return 0;
-	if (posix_clocks[which_clock].res != 0)
-		return 0;
-	return 1;
+	if (which_clock >= MAX_CLOCKS)
+		return true;
+	else
+		return false;
 }
 
 /*
@@ -273,12 +242,29 @@  static __init int init_posix_timers(void)
 {
 	struct k_clock clock_realtime = {
 		.clock_getres = hrtimer_get_res,
+		/* defaults: */
+		.clock_adj	= common_clock_adj,
+		.clock_get	= common_clock_get,
+		.clock_set	= common_clock_set,
+		.nsleep		= common_nsleep,
+		.nsleep_restart	= common_nsleep_restart,
+		.timer_create	= common_timer_create,
+		.timer_del	= common_timer_del,
+		.timer_get	= common_timer_get,
+		.timer_set	= common_timer_set,
 	};
 	struct k_clock clock_monotonic = {
 		.clock_getres = hrtimer_get_res,
 		.clock_get = posix_ktime_get_ts,
 		.clock_set = do_posix_clock_nosettime,
 		.clock_adj = do_posix_clock_noadjtime,
+		/* defaults: */
+		.nsleep		= common_nsleep,
+		.nsleep_restart	= common_nsleep_restart,
+		.timer_create	= common_timer_create,
+		.timer_del	= common_timer_del,
+		.timer_get	= common_timer_get,
+		.timer_set	= common_timer_set,
 	};
 	struct k_clock clock_monotonic_raw = {
 		.clock_getres = hrtimer_get_res,
@@ -287,6 +273,11 @@  static __init int init_posix_timers(void)
 		.clock_adj = do_posix_clock_noadjtime,
 		.timer_create = no_timer_create,
 		.nsleep = no_nsleep,
+		/* defaults: */
+		.nsleep_restart	= common_nsleep_restart,
+		.timer_del	= common_timer_del,
+		.timer_get	= common_timer_get,
+		.timer_set	= common_timer_set,
 	};
 	struct k_clock clock_realtime_coarse = {
 		.clock_getres = posix_get_coarse_res,
@@ -295,6 +286,11 @@  static __init int init_posix_timers(void)
 		.clock_adj = do_posix_clock_noadjtime,
 		.timer_create = no_timer_create,
 		.nsleep = no_nsleep,
+		/* defaults: */
+		.nsleep_restart	= common_nsleep_restart,
+		.timer_del	= common_timer_del,
+		.timer_get	= common_timer_get,
+		.timer_set	= common_timer_set,
 	};
 	struct k_clock clock_monotonic_coarse = {
 		.clock_getres = posix_get_coarse_res,
@@ -303,6 +299,11 @@  static __init int init_posix_timers(void)
 		.clock_adj = do_posix_clock_noadjtime,
 		.timer_create = no_timer_create,
 		.nsleep = no_nsleep,
+		/* defaults: */
+		.nsleep_restart	= common_nsleep_restart,
+		.timer_del	= common_timer_del,
+		.timer_get	= common_timer_get,
+		.timer_set	= common_timer_set,
 	};
 
 	register_posix_clock(CLOCK_REALTIME, &clock_realtime);
@@ -526,6 +527,160 @@  static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
 	kmem_cache_free(posix_timers_cache, tmr);
 }
 
+static inline bool clock_is_posix_cpu(const clockid_t id)
+{
+	if ((id & CLOCKFD_MASK) == CLOCKFD)
+		return false;
+	else
+		return true;
+}
+
+static inline int dispatch_clock_getres(const clockid_t id, struct timespec *ts)
+{
+	if (id >= 0) {
+		return posix_clocks[id].clock_getres ?
+			posix_clocks[id].clock_getres(id, ts) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_clock_getres(id, ts);
+
+	return -EINVAL;
+}
+
+static inline int dispatch_clock_set(const clockid_t id, struct timespec *ts)
+{
+	if (id >= 0) {
+		return posix_clocks[id].clock_set ?
+			posix_clocks[id].clock_set(id, ts) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_clock_set(id, ts);
+
+	return -EINVAL;
+}
+
+static inline int dispatch_clock_get(const clockid_t id, struct timespec *ts)
+{
+	if (id >= 0) {
+		return posix_clocks[id].clock_get ?
+			posix_clocks[id].clock_get(id, ts) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_clock_get(id, ts);
+
+	return -EINVAL;
+}
+
+static inline int dispatch_clock_adj(const clockid_t id, struct timex *tx)
+{
+	if (id >= 0) {
+		return posix_clocks[id].clock_adj ?
+			posix_clocks[id].clock_adj(id, tx) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_clock_adj(id, tx);
+
+	return -EINVAL;
+}
+
+static inline int dispatch_timer_create(struct k_itimer *kit)
+{
+	clockid_t id = kit->it_clock;
+
+	if (id >= 0) {
+		return posix_clocks[id].timer_create ?
+			posix_clocks[id].timer_create(kit) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_timer_create(kit);
+
+	return -EINVAL;
+}
+
+static inline int dispatch_nsleep(const clockid_t id, int flags,
+				  struct timespec *ts,
+				  struct timespec __user *rts)
+{
+	if (id >= 0) {
+		return posix_clocks[id].nsleep ?
+			posix_clocks[id].nsleep(id, flags, ts, rts) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_nsleep(id, flags, ts, rts);
+
+	return -EINVAL;
+}
+
+static inline long dispatch_nsleep_restart(struct restart_block *block)
+{
+	clockid_t id = block->arg0;
+
+	if (id >= 0) {
+		return posix_clocks[id].nsleep_restart ?
+			posix_clocks[id].nsleep_restart(block) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_nsleep_restart(block);
+
+	return -EINVAL;
+}
+
+static inline int dispatch_timer_set(struct k_itimer *kit, int flags,
+				     struct itimerspec *tsp,
+				     struct itimerspec *old)
+{
+	clockid_t id = kit->it_clock;
+
+	if (id >= 0) {
+		return posix_clocks[id].timer_set ?
+			posix_clocks[id].timer_set(kit, flags, tsp, old) :
+			-EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_timer_set(kit, flags, tsp, old);
+
+	return -EINVAL;
+}
+
+static inline int dispatch_timer_del(struct k_itimer *kit)
+{
+	clockid_t id = kit->it_clock;
+
+	if (id >= 0) {
+		return posix_clocks[id].timer_del ?
+			posix_clocks[id].timer_del(kit) : -EINVAL;
+	}
+
+	if (clock_is_posix_cpu(id))
+		return posix_cpu_timer_del(kit);
+
+	return -EINVAL;
+}
+
+static inline void dispatch_timer_get(struct k_itimer *kit,
+				      struct itimerspec *tsp)
+{
+	clockid_t id = kit->it_clock;
+
+	if (id >= 0 && posix_clocks[id].timer_get)
+
+		posix_clocks[id].timer_get(kit, tsp);
+
+	else if (clock_is_posix_cpu(id))
+
+		posix_cpu_timer_get(kit, tsp);
+}
+
+#define CLOCK_DISPATCH(clock, call, arglist) dispatch_##call arglist
+
 /* Create a POSIX.1b interval timer. */
 
 SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
@@ -847,7 +1002,7 @@  retry:
 	return error;
 }
 
-static inline int common_timer_del(struct k_itimer *timer)
+static int common_timer_del(struct k_itimer *timer)
 {
 	timer->it.real.interval.tv64 = 0;
 
@@ -1056,7 +1211,7 @@  SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 /*
  * nanosleep_restart for monotonic and realtime clocks
  */
-static int common_nsleep_restart(struct restart_block *restart_block)
+static long common_nsleep_restart(struct restart_block *restart_block)
 {
 	return hrtimer_nanosleep_restart(restart_block);
 }
@@ -1068,8 +1223,6 @@  static int common_nsleep_restart(struct restart_block *restart_block)
 long
 clock_nanosleep_restart(struct restart_block *restart_block)
 {
-	clockid_t which_clock = restart_block->arg0;
-
 	return CLOCK_DISPATCH(which_clock, nsleep_restart,
 			      (restart_block));
 }