mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: Roman Zippel <zippel@linux-m68k.org>
Cc: Ingo Molnar <mingo@elte.hu>,
	Christopher Friesen <cfriesen@nortel.com>,
	linux-kernel@vger.kernel.org, akpm@osdl.org, george@mvista.com,
	johnstul@us.ibm.com, paulmck@us.ibm.com
Subject: Re: [ANNOUNCE] ktimers subsystem
Date: Sat, 24 Sep 2005 15:56:52 +0200	[thread overview]
Message-ID: <1127570212.15115.77.camel@tglx.tec.linutronix.de> (raw)
In-Reply-To: <Pine.LNX.4.61.0509241212170.3728@scrub.home>

On Sat, 2005-09-24 at 12:35 +0200, Roman Zippel wrote:
> Hi,
> 
> On Sat, 24 Sep 2005, Ingo Molnar wrote:
> 
> > > Anyway, the biggest cost is the conversion from/to the 64bit ns value 
> > > [...]
> > 
> > Where do you get that notion from? Have you personally measured the 
> > performance and code size impact of it? If yes, would you mind to share 
> > the resulting data with us?
> > 
> > Our data is that the use of 64-bit nsec_t significantly reduces the size 
> > of a representative piece of code (object size in bytes):
> > 
> >                 AMD64    I386        ARM          PPC32       M68K
> >    nsec_t_ops   226      284         252          428         206
> >    timespec_ops 412      324         448          640         342
> > 
> > i.e. a ~40% size reduction when going to nsec_t on m68k, in that 
> > particular function. Even larger, ~45% code size reduction on a true 
> > 64-bit platform.
> 
> Without any source these numbers are not verifiable. You don't even 
> mention here what that "representative piece of code" is...

struct base {
        nsec_t now;
        struct ktimer *timers[16];
        struct ktimer *running;
};

void nsec_t_ops(struct base *base, struct ktimer *next,
                  nsec_t *tim, int mode)
{
        int i;
        nsec_t now = base->now;

        for (i = 0; i < 16; i++) {

                void (*fn)(void *);
                void *data;
                struct ktimer *timer = base->timers[i];

                if (timer->expires > now)
                        break;
                timer->expired = now;
                fn = timer->function;
                data = timer->data;
                base->running = timer;
                fn(data);
                base->running = NULL;
        }

        switch(mode) {
        case 0:
                next->expires = *tim;
                break;
        case 1:
                next->expires = now + *tim;
                break;
        case 2:
                next->expires += *tim;
                break;
        case 3:
                while (next->expires > now) {
                        next->expires += *tim;
                }
                break;
        }
        base->timers[0] = next;
}


versus:

#define NSEC_PER_SEC 1000000000
struct base {
        struct timespec now;
        struct ktimer *timers[16];
        struct ktimer *running;
};

#define timespec_gt(a,b)                       	\
        (((a).tv_sec > (b).tv_sec) ? 1 :        \
        (((a).tv_sec < (b).tv_sec) ? 0 :        \
        ((a).tv_nsec > (b).tv_nsec)))

#define timespec_addptr(a,b)                            \
        (a)->tv_sec = ((a)->tv_sec + (b)->tv_sec);      \
        (a)->tv_nsec = ((a)->tv_nsec + (b)->tv_nsec);   \
        if ((a)->tv_nsec >= NSEC_PER_SEC){               \
                (a)->tv_nsec -= NSEC_PER_SEC;           \
                (a)->tv_sec++;                          \
        }

#define timespec_addppp(c,a,b)                          \
        (c)->tv_sec = ((a)->tv_sec + (b)->tv_sec);      \
        (c)->tv_nsec = ((a)->tv_nsec + (b)->tv_nsec);   \
        if ((c)->tv_nsec >= NSEC_PER_SEC){               \
                (c)->tv_nsec -= NSEC_PER_SEC;           \
                (c)->tv_sec++;                          \
        }


void timespec_ops(struct base *base, struct ktimer *next,
                  struct timespec *tim, int mode)
{
        int i;
        struct timespec now = base->now;

        for (i = 0; i < 16; i++) {

                void (*fn)(void *);
                void *data;
                struct ktimer *timer = base->timers[i];

                if (timespec_gt(timer->expires, now))
                        break;
                timer->expired = now;
                fn = timer->function;
                data = timer->data;
                base->running = timer;
                fn(data);
                base->running = NULL;
        }

        switch(mode) {
        case 0:
                next->expires = *tim;
                break;
        case 1:
                timespec_addppp(&next->expires, &now, tim);
                break;
        case 2:
                timespec_addptr(&next->expires, tim);
                break;
        case 3:
                while (timespec_gt(now, next->expires)) {
                        timespec_addptr(&next->expires, tim);
                }
                break;
        }
        base->timers[0] = next;
}


> Anyway, Thomas mentioned that this would be from the insert/remove code 
> and here you omitted the most important part of my mail:
> 
> typedef union {
> 	u64 tv64;
> 	struct {
> #ifdef __BIG_ENDIAN
> 		u32 sec, nsec;
> #else
> 		u32 nsec, sec;
> #endif
> 	} tv;
> } ktimespec;
> 
> IOW this would allow to keep the time value in timespec format and use 
> your nsec_t_ops for sorting.

Yes, it works for comparisons. 

But for any other operation this construct has the same problem than
struct timespec itself. You need at least an add function which is
always an add and a comparison / correction vs. nsec >= NSEC_PER_SEC. 

The 64 bit nsec_t value can just be used as is without inventing a
wrapper macro for each operation.

The only point, where (k)timespec has an advantage is that the userspace
value must not be converted to nsec_t, but deducing therefor this is the
better overall solution is a fallacy.

nsec_t				ktimespec

syscall:
32x32 mul
64bit add			2 x 32bit move

arm timer:
64 bit add			2 x 32 bit add
				  32 bit compare
				  32 bit sub
				  32 bit add

The 3 operation compensate for the 32x32 
multiplication.

For interval timers you have the 
				  32 bit compare
				  32 bit sub
				  32 bit add
additional overhead for each rearm.

The backward conversion from nsec_t to timespec is almost a non issue.
The vast majority of callers dont provide the second argument to
nanosleep(), setitimer(), set_timer() which makes the conversion
necessary and I think we optimize for the common use case.

Besides that the representation of time in nsec_t values is much
clearer. 

I know that we have to deal with timespecs vs. userspace, but keeping
this representation for kernel internal usage reminds me on the BCD
calculations which were a similar 2^x vs 10^x oddity in the early days
of microprocessors. Of course they were obstinate and survived a
surprisingly long time.

tglx



  reply	other threads:[~2005-09-24 13:56 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-19 16:48 tglx
2005-09-19 16:48 ` [PATCH] " tglx
2005-09-19 21:47 ` [ANNOUNCE] " Thomas Gleixner
2005-09-19 22:03 ` Christoph Lameter
2005-09-19 22:17   ` Thomas Gleixner
2005-09-19 22:24     ` Christoph Lameter
2005-09-19 22:44       ` Thomas Gleixner
2005-09-19 22:50         ` john stultz
2005-09-19 22:58           ` Thomas Gleixner
2005-09-19 23:04         ` Christoph Lameter
2005-09-19 23:12           ` Thomas Gleixner
2005-09-20  7:14             ` Ingo Molnar
2005-09-20  7:10       ` Ingo Molnar
2005-09-21 19:24       ` Pavel Machek
2005-09-19 22:39     ` Christopher Friesen
2005-09-19 22:54       ` Thomas Gleixner
2005-09-20  4:57         ` Christopher Friesen
2005-09-20  5:11           ` Thomas Gleixner
2005-09-20  0:43   ` George Anzinger
2005-09-21 19:50 ` Roman Zippel
2005-09-21 22:41   ` Thomas Gleixner
2005-09-22 12:59     ` Ingo Molnar
2005-09-22 23:09     ` Roman Zippel
2005-09-22 23:31       ` Christopher Friesen
2005-09-23  0:25         ` Roman Zippel
2005-09-23  6:49           ` Thomas Gleixner
2005-09-24  3:15             ` Roman Zippel
2005-09-24  5:16               ` Ingo Molnar
2005-09-24 10:35                 ` Roman Zippel
2005-09-24 13:56                   ` Thomas Gleixner [this message]
2005-09-24 16:51                     ` Daniel Walker
2005-09-24 23:45                     ` Roman Zippel
2005-09-25 21:00                       ` Thomas Gleixner
2005-09-27 16:54                         ` Roman Zippel
2005-09-27 19:03                           ` Tim Bird
2005-09-28 16:36                             ` Roman Zippel
2005-09-25 21:02                       ` Thomas Gleixner
2005-09-27 16:48                         ` Roman Zippel
2005-09-27 18:38                           ` Tim Bird
2005-09-27 20:36                             ` George Anzinger
2005-09-23  2:25       ` john stultz
2005-09-23  8:27       ` Thomas Gleixner
2005-09-24  2:43         ` Roman Zippel
2005-09-24  5:03           ` Ingo Molnar
2005-09-24  9:04           ` James Bruce
2005-09-23 15:21       ` Paul E. McKenney
2005-09-24  3:38         ` Roman Zippel
2005-09-25 15:48 Sid Boyce
2005-09-25 18:20 ` Zwane Mwaikambo
2005-09-26  0:02   ` Sid Boyce

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=1127570212.15115.77.camel@tglx.tec.linutronix.de \
    --to=tglx@linutronix.de \
    --cc=akpm@osdl.org \
    --cc=cfriesen@nortel.com \
    --cc=george@mvista.com \
    --cc=johnstul@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=paulmck@us.ibm.com \
    --cc=zippel@linux-m68k.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

all inboxes | Powered by JetHome®