mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Remy Bohmer" <linux@bohmer.net>
To: "Daniel Walker" <dwalker@mvista.com>, "Ingo Molnar" <mingo@elte.hu>
Cc: linux-kernel@vger.kernel.org, linux-rt-users@vger.kernel.org
Subject: [RT] seqlocks: use of PICK_FUNCTION breaks kernel compile when CONFIG_GENERIC_TIME is NOT set
Date: Tue, 16 Oct 2007 10:35:15 +0200	[thread overview]
Message-ID: <3efb10970710160135q31fd3982h17fa23768960186d@mail.gmail.com> (raw)

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

Hello Daniel and Ingo,

I use 2.6.23-rt1 and the patch of Daniel below which seems to be in
there breaks the compilation of the RT-kernel when CONFIG_GENERIC_TIME
is NOT set.

It breaks in the do_gettimeofday(struct timeval *tv) code in the
architecture specific code
where there is a call to: seq = read_seqbegin_irqsave(&xtime_lock, flags);
The PICK_FUNCTION implementation does not return anything, so the
compile breaks here.

I am figuring out how to solve this problem nicely, but I have not
found a nice solution yet. Attached I have put my hack to make it
compile on ARM again, but maybe one of you can do a better proposal to
fix this.

Here is a list of files that will probably all fail to build: (I only
tested ARM)
linux-2.6.23/arch/arm/kernel/time.c:254
linux-2.6.23/arch/xtensa/kernel/time.c:132
linux-2.6.23/arch/sparc/kernel/time.c:453
linux-2.6.23/arch/sparc/kernel/pcic.c:776
linux-2.6.23/arch/blackfin/kernel/time.c:269
linux-2.6.23/arch/m68knommu/kernel/time.c:130
linux-2.6.23/arch/sh64/kernel/time.c:193
linux-2.6.23/arch/alpha/kernel/time.c:408
linux-2.6.23/arch/sh/kernel/time.c:65
linux-2.6.23/arch/m68k/kernel/time.c:104
linux-2.6.23/arch/ppc/kernel/time.c:207
linux-2.6.23/arch/s390/kernel/time.c:197


Kind Regards,

Remy Bohmer


2007/8/28, Daniel Walker <dwalker@mvista.com>:
> Replace the old PICK_OP style macros with PICK_FUNCTION. Although,
> seqlocks has some alien code, which I also replaced as can be seen
> from the line count below.
>
> Signed-off-by: Daniel Walker <dwalker@mvista.com>
>
> ---
>  include/linux/pickop.h  |    4
>  include/linux/seqlock.h |  235 +++++++++++++++++++++++++++---------------------
>  2 files changed, 135 insertions(+), 104 deletions(-)
>
> Index: linux-2.6.22/include/linux/pickop.h
> ===================================================================
> --- linux-2.6.22.orig/include/linux/pickop.h
> +++ linux-2.6.22/include/linux/pickop.h
> @@ -1,10 +1,6 @@
>  #ifndef _LINUX_PICKOP_H
>  #define _LINUX_PICKOP_H
>
> -#undef TYPE_EQUAL
> -#define TYPE_EQUAL(var, type) \
> -               __builtin_types_compatible_p(typeof(var), type *)
> -
>  #undef PICK_TYPE_EQUAL
>  #define PICK_TYPE_EQUAL(var, type) \
>                 __builtin_types_compatible_p(typeof(var), type)
> Index: linux-2.6.22/include/linux/seqlock.h
> ===================================================================
> --- linux-2.6.22.orig/include/linux/seqlock.h
> +++ linux-2.6.22/include/linux/seqlock.h
> @@ -90,6 +90,12 @@ static inline void __write_seqlock(seqlo
>         smp_wmb();
>  }
>
> +static __always_inline unsigned long __write_seqlock_irqsave(seqlock_t *sl)
> +{
> +       __write_seqlock(sl);
> +       return 0;
> +}
> +
>  static inline void __write_sequnlock(seqlock_t *sl)
>  {
>         smp_wmb();
> @@ -97,6 +103,8 @@ static inline void __write_sequnlock(seq
>         spin_unlock(&sl->lock);
>  }
>
> +#define __write_sequnlock_irqrestore(sl, flags)        __write_sequnlock(sl)
> +
>  static inline int __write_tryseqlock(seqlock_t *sl)
>  {
>         int ret = spin_trylock(&sl->lock);
> @@ -149,6 +157,28 @@ static __always_inline void __write_seql
>         smp_wmb();
>  }
>
> +static __always_inline unsigned long
> +__write_seqlock_irqsave_raw(raw_seqlock_t *sl)
> +{
> +       unsigned long flags;
> +
> +       local_irq_save(flags);
> +       __write_seqlock_raw(sl);
> +       return flags;
> +}
> +
> +static __always_inline void __write_seqlock_irq_raw(raw_seqlock_t *sl)
> +{
> +       local_irq_disable();
> +       __write_seqlock_raw(sl);
> +}
> +
> +static __always_inline void __write_seqlock_bh_raw(raw_seqlock_t *sl)
> +{
> +       local_bh_disable();
> +       __write_seqlock_raw(sl);
> +}
> +
>  static __always_inline void __write_sequnlock_raw(raw_seqlock_t *sl)
>  {
>         smp_wmb();
> @@ -156,6 +186,27 @@ static __always_inline void __write_sequ
>         spin_unlock(&sl->lock);
>  }
>
> +static __always_inline void
> +__write_sequnlock_irqrestore_raw(raw_seqlock_t *sl, unsigned long flags)
> +{
> +       __write_sequnlock_raw(sl);
> +       local_irq_restore(flags);
> +       preempt_check_resched();
> +}
> +
> +static __always_inline void __write_sequnlock_irq_raw(raw_seqlock_t *sl)
> +{
> +       __write_sequnlock_raw(sl);
> +       local_irq_enable();
> +       preempt_check_resched();
> +}
> +
> +static __always_inline void __write_sequnlock_bh_raw(raw_seqlock_t *sl)
> +{
> +       __write_sequnlock_raw(sl);
> +       local_bh_enable();
> +}
> +
>  static __always_inline int __write_tryseqlock_raw(raw_seqlock_t *sl)
>  {
>         int ret = spin_trylock(&sl->lock);
> @@ -182,60 +233,93 @@ static __always_inline int __read_seqret
>
>  extern int __bad_seqlock_type(void);
>
> -#define PICK_SEQOP(op, lock)                                   \
> +/*
> + * PICK_SEQ_OP() is a small redirector to allow less typing of the lock
> + * types raw_seqlock_t, seqlock_t, at the front of the PICK_FUNCTION
> + * macro.
> + */
> +#define PICK_SEQ_OP(...)       \
> +       PICK_FUNCTION(raw_seqlock_t *, seqlock_t *, ##__VA_ARGS__)
> +#define PICK_SEQ_OP_RET(...) \
> +       PICK_FUNCTION_RET(raw_seqlock_t *, seqlock_t *, ##__VA_ARGS__)
> +
> +#define write_seqlock(sl) PICK_SEQ_OP(__write_seqlock_raw, __write_seqlock, sl)
> +
> +#define write_sequnlock(sl)    \
> +       PICK_SEQ_OP(__write_sequnlock_raw, __write_sequnlock, sl)
> +
> +#define write_tryseqlock(sl)   \
> +       PICK_SEQ_OP_RET(__write_tryseqlock_raw, __write_tryseqlock, sl)
> +
> +#define read_seqbegin(sl)      \
> +       PICK_SEQ_OP_RET(__read_seqbegin_raw, __read_seqbegin, sl)
> +
> +#define read_seqretry(sl, iv)  \
> +       PICK_SEQ_OP_RET(__read_seqretry_raw, __read_seqretry, sl, iv)
> +
> +#define write_seqlock_irqsave(lock, flags)                     \
>  do {                                                           \
> -       if (TYPE_EQUAL((lock), raw_seqlock_t))                  \
> -               op##_raw((raw_seqlock_t *)(lock));              \
> -       else if (TYPE_EQUAL((lock), seqlock_t))                 \
> -               op((seqlock_t *)(lock));                        \
> -       else __bad_seqlock_type();                              \
> +       flags = PICK_SEQ_OP_RET(__write_seqlock_irqsave_raw,    \
> +               __write_seqlock_irqsave, lock);                 \
>  } while (0)
>
> -#define PICK_SEQOP_RET(op, lock)                               \
> -({                                                             \
> -       unsigned long __ret;                                    \
> -                                                               \
> -       if (TYPE_EQUAL((lock), raw_seqlock_t))                  \
> -               __ret = op##_raw((raw_seqlock_t *)(lock));      \
> -       else if (TYPE_EQUAL((lock), seqlock_t))                 \
> -               __ret = op((seqlock_t *)(lock));                \
> -       else __ret = __bad_seqlock_type();                      \
> -                                                               \
> -       __ret;                                                  \
> -})
> -
> -#define PICK_SEQOP_CONST_RET(op, lock)                         \
> -({                                                             \
> -       unsigned long __ret;                                    \
> -                                                               \
> -       if (TYPE_EQUAL((lock), raw_seqlock_t))                  \
> -               __ret = op##_raw((const raw_seqlock_t *)(lock));\
> -       else if (TYPE_EQUAL((lock), seqlock_t))                 \
> -               __ret = op((seqlock_t *)(lock));                \
> -       else __ret = __bad_seqlock_type();                      \
> -                                                               \
> -       __ret;                                                  \
> -})
> -
> -#define PICK_SEQOP2_CONST_RET(op, lock, arg)                           \
> - ({                                                                    \
> -       unsigned long __ret;                                            \
> -                                                                       \
> -       if (TYPE_EQUAL((lock), raw_seqlock_t))                          \
> -               __ret = op##_raw((const raw_seqlock_t *)(lock), (arg)); \
> -       else if (TYPE_EQUAL((lock), seqlock_t))                         \
> -               __ret = op((seqlock_t *)(lock), (arg));                 \
> -       else __ret = __bad_seqlock_type();                              \
> -                                                                       \
> -       __ret;                                                          \
> -})
> -
> -
> -#define write_seqlock(sl)      PICK_SEQOP(__write_seqlock, sl)
> -#define write_sequnlock(sl)    PICK_SEQOP(__write_sequnlock, sl)
> -#define write_tryseqlock(sl)   PICK_SEQOP_RET(__write_tryseqlock, sl)
> -#define read_seqbegin(sl)      PICK_SEQOP_CONST_RET(__read_seqbegin, sl)
> -#define read_seqretry(sl, iv)  PICK_SEQOP2_CONST_RET(__read_seqretry, sl, iv)
> +#define write_seqlock_irq(lock)        \
> +       PICK_SEQ_OP(__write_seqlock_irq_raw, __write_seqlock, lock)
> +
> +#define write_seqlock_bh(lock) \
> +       PICK_SEQ_OP(__write_seqlock_bh_raw, __write_seqlock, lock)
> +
> +#define write_sequnlock_irqrestore(lock, flags)                \
> +       PICK_SEQ_OP(__write_sequnlock_irqrestore_raw,   \
> +               __write_sequnlock_irqrestore, lock, flags)
> +
> +#define write_sequnlock_bh(lock)       \
> +       PICK_SEQ_OP(__write_sequnlock_bh_raw, __write_sequnlock, lock)
> +
> +#define write_sequnlock_irq(lock)      \
> +       PICK_SEQ_OP(__write_sequnlock_irq_raw, __write_sequnlock, lock)
> +
> +static __always_inline
> +unsigned long __read_seqbegin_irqsave_raw(raw_seqlock_t *sl)
> +{
> +       unsigned long flags;
> +
> +       local_irq_save(flags);
> +       __read_seqbegin_raw(sl);
> +       return flags;
> +}
> +
> +static __always_inline unsigned long __read_seqbegin_irqsave(seqlock_t *sl)
> +{
> +       __read_seqbegin(sl);
> +       return 0;
> +}
> +
> +#define read_seqbegin_irqsave(lock, flags)                     \
> +do {                                                           \
> +       flags = PICK_SEQ_OP_RET(__read_seqbegin_irqsave_raw,    \
> +               __read_seqbegin_irqsave, lock);                 \
> +} while (0)
> +
> +static __always_inline int
> +__read_seqretry_irqrestore(seqlock_t *sl, unsigned iv, unsigned long flags)
> +{
> +       return __read_seqretry(sl, iv);
> +}
> +
> +static __always_inline int
> +__read_seqretry_irqrestore_raw(raw_seqlock_t *sl, unsigned iv,
> +                              unsigned long flags)
> +{
> +       int ret = read_seqretry(sl, iv);
> +       local_irq_restore(flags);
> +       preempt_check_resched();
> +       return ret;
> +}
> +
> +#define read_seqretry_irqrestore(lock, iv, flags)                      \
> +       PICK_SEQ_OP_RET(__read_seqretry_irqrestore_raw,                 \
> +               __read_seqretry_irqrestore, lock, iv, flags)
>
>  /*
>   * Version using sequence counter only.
> @@ -286,53 +370,4 @@ static inline void write_seqcount_end(se
>         smp_wmb();
>         s->sequence++;
>  }
> -
> -#define PICK_IRQOP(op, lock)                                   \
> -do {                                                           \
> -       if (TYPE_EQUAL((lock), raw_seqlock_t))                  \
> -               op();                                           \
> -       else if (TYPE_EQUAL((lock), seqlock_t))                 \
> -               { /* nothing */ }                               \
> -       else __bad_seqlock_type();                              \
> -} while (0)
> -
> -#define PICK_IRQOP2(op, arg, lock)                             \
> -do {                                                           \
> -       if (TYPE_EQUAL((lock), raw_seqlock_t))                  \
> -               op(arg);                                        \
> -       else if (TYPE_EQUAL(lock, seqlock_t))                   \
> -               { /* nothing */ }                               \
> -       else __bad_seqlock_type();                              \
> -} while (0)
> -
> -
> -
> -/*
> - * Possible sw/hw IRQ protected versions of the interfaces.
> - */
> -#define write_seqlock_irqsave(lock, flags)                             \
> -       do { PICK_IRQOP2(local_irq_save, flags, lock); write_seqlock(lock); } while (0)
> -#define write_seqlock_irq(lock)                                                \
> -       do { PICK_IRQOP(local_irq_disable, lock); write_seqlock(lock); } while (0)
> -#define write_seqlock_bh(lock)                                         \
> -        do { PICK_IRQOP(local_bh_disable, lock); write_seqlock(lock); } while (0)
> -
> -#define write_sequnlock_irqrestore(lock, flags)                                \
> -       do { write_sequnlock(lock); PICK_IRQOP2(local_irq_restore, flags, lock); preempt_check_resched(); } while(0)
> -#define write_sequnlock_irq(lock)                                      \
> -       do { write_sequnlock(lock); PICK_IRQOP(local_irq_enable, lock); preempt_check_resched(); } while(0)
> -#define write_sequnlock_bh(lock)                                       \
> -       do { write_sequnlock(lock); PICK_IRQOP(local_bh_enable, lock); } while(0)
> -
> -#define read_seqbegin_irqsave(lock, flags)                             \
> -       ({ PICK_IRQOP2(local_irq_save, flags, lock); read_seqbegin(lock); })
> -
> -#define read_seqretry_irqrestore(lock, iv, flags)                      \
> -       ({                                                              \
> -               int ret = read_seqretry(lock, iv);                      \
> -               PICK_IRQOP2(local_irq_restore, flags, lock);            \
> -               preempt_check_resched();                                \
> -               ret;                                                    \
> -       })
> -
>  #endif /* __LINUX_SEQLOCK_H */
>
> --
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: fix-compile-error-non-rt.patch --]
[-- Type: text/x-patch; name="fix-compile-error-non-rt.patch", Size: 958 bytes --]

This patch is hack that makes the RT-kernel compile again when
CONFIG_GENERIC_TIME is NOT set. Probably every architecture
has the same problem because the read_seqbegin_irqsave() macro
has been changed to something not returning anything.

Signed-off-by: Remy Bohmer <linux@bohmer.net>
---
 arch/arm/kernel/time.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Index: linux-2.6.23/arch/arm/kernel/time.c
===================================================================
--- linux-2.6.23.orig/arch/arm/kernel/time.c	2007-10-16 09:17:25.000000000 +0200
+++ linux-2.6.23/arch/arm/kernel/time.c	2007-10-16 10:08:02.000000000 +0200
@@ -251,7 +251,8 @@ void do_gettimeofday(struct timeval *tv)
 	unsigned long usec, sec;
 
 	do {
-		seq = read_seqbegin_irqsave(&xtime_lock, flags);
+		read_seqbegin_irqsave(&xtime_lock, flags);
+		seq = xtime_lock.sequence;
 		usec = system_timer->offset();
 		sec = xtime.tv_sec;
 		usec += xtime.tv_nsec / 1000;

             reply	other threads:[~2007-10-16  8:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-16  8:35 Remy Bohmer [this message]
2007-10-16 16:52 ` Daniel Walker
2007-10-17 14:07   ` Remy Bohmer
     [not found] <1192632502.17527.129.camel@imap.mvista.com>
2007-10-17 15:10 ` Steven Rostedt
2007-10-17 15:24   ` Daniel Walker
2007-10-17 15:34     ` Steven Rostedt
2007-10-22 18:53       ` Daniel Walker

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=3efb10970710160135q31fd3982h17fa23768960186d@mail.gmail.com \
    --to=linux@bohmer.net \
    --cc=dwalker@mvista.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=mingo@elte.hu \
    /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®