2005-10-30 00:03:06

by Adrian Bunk

[permalink] [raw]
Subject: [2.6 patch] parisc: "extern inline" -> "static inline"

"extern inline" doesn't make much sense.


Signed-off-by: Adrian Bunk <[email protected]>

---

arch/parisc/lib/memcpy.c | 4 +--
include/asm-parisc/bitops.h | 2 -
include/asm-parisc/io.h | 4 +--
include/asm-parisc/pci.h | 2 -
include/asm-parisc/pgtable.h | 40 ++++++++++++++++-----------------
include/asm-parisc/processor.h | 4 +--
include/asm-parisc/semaphore.h | 10 ++++----
include/asm-parisc/tlbflush.h | 2 -
8 files changed, 34 insertions(+), 34 deletions(-)

--- linux-2.6.14-rc5-mm1-full/arch/parisc/lib/memcpy.c.old 2005-10-30 01:58:43.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/arch/parisc/lib/memcpy.c 2005-10-30 01:59:11.000000000 +0200
@@ -158,12 +158,12 @@
#define stw(_s,_t,_o,_a,_e) def_store_insn(stw,"r",_s,_t,_o,_a,_e)

#ifdef CONFIG_PREFETCH
-extern inline void prefetch_src(const void *addr)
+static inline void prefetch_src(const void *addr)
{
__asm__("ldw 0(" s_space ",%0), %%r0" : : "r" (addr));
}

-extern inline void prefetch_dst(const void *addr)
+static inline void prefetch_dst(const void *addr)
{
__asm__("ldd 0(" d_space ",%0), %%r0" : : "r" (addr));
}
--- linux-2.6.14-rc5-mm1-full/include/asm-parisc/bitops.h.old 2005-10-30 01:59:21.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/include/asm-parisc/bitops.h 2005-10-30 01:59:35.000000000 +0200
@@ -474,7 +474,7 @@
#define ext2_find_first_zero_bit(addr, size) \
ext2_find_next_zero_bit((addr), (size), 0)

-extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
+static inline unsigned long ext2_find_next_zero_bit(void *addr,
unsigned long size, unsigned long offset)
{
unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
--- linux-2.6.14-rc5-mm1-full/include/asm-parisc/io.h.old 2005-10-30 01:59:44.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/include/asm-parisc/io.h 2005-10-30 01:59:49.000000000 +0200
@@ -163,7 +163,7 @@

extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);

-extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, 0);
}
@@ -173,7 +173,7 @@
* it's useful if some control registers are in such an area and write combining
* or read caching is not desirable:
*/
-extern inline void * ioremap_nocache(unsigned long offset, unsigned long size)
+static inline void * ioremap_nocache(unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, _PAGE_NO_CACHE /* _PAGE_PCD */);
}
--- linux-2.6.14-rc5-mm1-full/include/asm-parisc/pci.h.old 2005-10-30 01:59:57.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/include/asm-parisc/pci.h 2005-10-30 02:00:01.000000000 +0200
@@ -193,7 +193,7 @@
extern void pcibios_register_hba(struct pci_hba_data *);
extern void pcibios_set_master(struct pci_dev *);
#else
-extern inline void pcibios_register_hba(struct pci_hba_data *x)
+static inline void pcibios_register_hba(struct pci_hba_data *x)
{
}
#endif
--- linux-2.6.14-rc5-mm1-full/include/asm-parisc/pgtable.h.old 2005-10-30 02:00:14.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/include/asm-parisc/pgtable.h 2005-10-30 02:00:18.000000000 +0200
@@ -316,31 +316,31 @@
* setup: the pgd is never bad, and a pmd always exists (as it's folded
* into the pgd entry)
*/
-extern inline int pgd_none(pgd_t pgd) { return 0; }
-extern inline int pgd_bad(pgd_t pgd) { return 0; }
-extern inline int pgd_present(pgd_t pgd) { return 1; }
-extern inline void pgd_clear(pgd_t * pgdp) { }
+static inline int pgd_none(pgd_t pgd) { return 0; }
+static inline int pgd_bad(pgd_t pgd) { return 0; }
+static inline int pgd_present(pgd_t pgd) { return 1; }
+static inline void pgd_clear(pgd_t * pgdp) { }
#endif

/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
-extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
-extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
-extern inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-
-extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_READ; return pte; }
-extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_READ; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
+static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+
+static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_READ; return pte; }
+static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
+static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_READ; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }

/*
* Conversion functions: convert a page and protection to a page entry,
@@ -368,7 +368,7 @@
#define mk_pte_phys(physpage, pgprot) \
({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })

-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }

/* Permanent address of a page. On parisc we don't have highmem. */
--- linux-2.6.14-rc5-mm1-full/include/asm-parisc/processor.h.old 2005-10-30 02:00:28.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/include/asm-parisc/processor.h 2005-10-30 02:00:36.000000000 +0200
@@ -327,12 +327,12 @@
#define ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCHW

-extern inline void prefetch(const void *addr)
+static inline void prefetch(const void *addr)
{
__asm__("ldw 0(%0), %%r0" : : "r" (addr));
}

-extern inline void prefetchw(const void *addr)
+static inline void prefetchw(const void *addr)
{
__asm__("ldd 0(%0), %%r0" : : "r" (addr));
}
--- linux-2.6.14-rc5-mm1-full/include/asm-parisc/semaphore.h.old 2005-10-30 02:00:45.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/include/asm-parisc/semaphore.h 2005-10-30 02:00:51.000000000 +0200
@@ -58,7 +58,7 @@
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)

-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
{
*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}
@@ -86,7 +86,7 @@
* interrupts while we're messing with the semaphore. Sorry.
*/

-extern __inline__ void down(struct semaphore * sem)
+static inline void down(struct semaphore * sem)
{
might_sleep();
spin_lock_irq(&sem->sentry);
@@ -98,7 +98,7 @@
spin_unlock_irq(&sem->sentry);
}

-extern __inline__ int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
{
int ret = 0;
might_sleep();
@@ -116,7 +116,7 @@
* down_trylock returns 0 on success, 1 if we failed to get the lock.
* May not sleep, but must preserve irq state
*/
-extern __inline__ int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
{
int flags, count;

@@ -132,7 +132,7 @@
* Note! This is subtle. We jump to wake people up only if
* the semaphore was negative (== somebody was waiting on it).
*/
-extern __inline__ void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
{
int flags;
spin_lock_irqsave(&sem->sentry, flags);
--- linux-2.6.14-rc5-mm1-full/include/asm-parisc/tlbflush.h.old 2005-10-30 02:01:00.000000000 +0200
+++ linux-2.6.14-rc5-mm1-full/include/asm-parisc/tlbflush.h 2005-10-30 02:01:06.000000000 +0200
@@ -42,7 +42,7 @@
#endif
}

-extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
+static inline void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
{
}



2005-10-30 15:22:19

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [parisc-linux] [2.6 patch] parisc: "extern inline" -> "static inline"

On Sun, Oct 30, 2005 at 02:03:01AM +0200, Adrian Bunk wrote:
> "extern inline" doesn't make much sense.

Are you sure? It used to. Taking just one sample, pgd_none:

extern inline: alpha, parisc, s390
static inline: frv, ppc, sh64
define: arm, arm26, frv, h8300, m68knommu, ppc64, v850

I really don't think it makes any difference. Such a function (returning
always 0) is always going to be inlined, and the only difference between
static inline and extern inline is what happens when it can't be inlined.

2005-10-30 15:56:27

by Adrian Bunk

[permalink] [raw]
Subject: Re: [parisc-linux] [2.6 patch] parisc: "extern inline" -> "static inline"

On Sun, Oct 30, 2005 at 08:22:15AM -0700, Matthew Wilcox wrote:
> On Sun, Oct 30, 2005 at 02:03:01AM +0200, Adrian Bunk wrote:
> > "extern inline" doesn't make much sense.
>
> Are you sure? It used to. Taking just one sample, pgd_none:
>
> extern inline: alpha, parisc, s390
> static inline: frv, ppc, sh64
> define: arm, arm26, frv, h8300, m68knommu, ppc64, v850
>
> I really don't think it makes any difference. Such a function (returning
> always 0) is always going to be inlined, and the only difference between
> static inline and extern inline is what happens when it can't be inlined.

On !alpha we are defining inline to __attribute__((always_inline)) for
any non-ancient gcc making this a zero difference.

The bigger issue is that "extern inline" generates a warning with
-Wmissing-prototypes and I'm currently working on getting the kernel
cleaned up for adding this to the CFLAGS since it will help us to avoid
a nasty class of runtime errors.

cu
Adrian

--

"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed

2005-10-30 16:44:17

by John David Anglin

[permalink] [raw]
Subject: Re: [parisc-linux] [2.6 patch] parisc: "extern inline" -> "static

> > I really don't think it makes any difference. Such a function (returning
> > always 0) is always going to be inlined, and the only difference between
> > static inline and extern inline is what happens when it can't be inlined.
>
> On !alpha we are defining inline to __attribute__((always_inline)) for
> any non-ancient gcc making this a zero difference.

It looks as if there are subtle differences between "always_inline"
and "extern inline". From the GCC extensions document:

[always_inline]
Generally, functions are not inlined unless optimization is specified.
For functions declared inline, this attribute inlines the function even
if no optimization level was specified.

[extern inline]
If you specify both @code{inline} and @code{extern} in the function
definition, then the definition is used only for inlining. In no case
is the function compiled on its own, not even if you refer to its
address explicitly. Such an address becomes an external reference, as
if you had only declared the function, and had not defined it.

The primary difference between "static inline" and "extern inline"
is in what happens when the address of the function is referenced.
With "extern inline", you need a unique library function to resolve
external references. With "static inline", you may end up with
multiple copies of a function if its address is taken.

> The bigger issue is that "extern inline" generates a warning with
> -Wmissing-prototypes and I'm currently working on getting the kernel
> cleaned up for adding this to the CFLAGS since it will help us to avoid
> a nasty class of runtime errors.

The prototypes could be added.

Dave
--
J. David Anglin [email protected]
National Research Council of Canada (613) 990-0752 (FAX: 952-6602)

2005-10-30 17:14:43

by Adrian Bunk

[permalink] [raw]
Subject: Re: [parisc-linux] [2.6 patch] parisc: "extern inline" -> "static

On Sun, Oct 30, 2005 at 11:42:52AM -0500, John David Anglin wrote:
> > > I really don't think it makes any difference. Such a function (returning
> > > always 0) is always going to be inlined, and the only difference between
> > > static inline and extern inline is what happens when it can't be inlined.
> >
> > On !alpha we are defining inline to __attribute__((always_inline)) for
> > any non-ancient gcc making this a zero difference.
>
> It looks as if there are subtle differences between "always_inline"
> and "extern inline". From the GCC extensions document:
>
> [always_inline]
> Generally, functions are not inlined unless optimization is specified.
> For functions declared inline, this attribute inlines the function even
> if no optimization level was specified.
>
> [extern inline]
> If you specify both @code{inline} and @code{extern} in the function
> definition, then the definition is used only for inlining. In no case
> is the function compiled on its own, not even if you refer to its
> address explicitly. Such an address becomes an external reference, as
> if you had only declared the function, and had not defined it.
>
> The primary difference between "static inline" and "extern inline"
> is in what happens when the address of the function is referenced.
> With "extern inline", you need a unique library function to resolve
> external references. With "static inline", you may end up with
> multiple copies of a function if its address is taken.
>...

In the kernel, "static inline" expands to
"static inline __attribute__((always_inline))" and
"extern inline" expands to
"extern inline __attribute__((always_inline))".

> Dave

cu
Adrian

--

"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed

2005-11-02 13:49:21

by Jan Engelhardt

[permalink] [raw]
Subject: Re: [parisc-linux] [2.6 patch] parisc: "extern inline" -> "static inline"


>> "extern inline" doesn't make much sense.

But GNU's ld is said to be smart enough to handle this like the
developerwants "extern AND inline". I did not try, though.


Jen

2005-11-02 13:53:54

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [parisc-linux] [2.6 patch] parisc: "extern inline" -> "static inline"

On Wed, Nov 02, 2005 at 02:48:42PM +0100, Jan Engelhardt wrote:
>
> >> "extern inline" doesn't make much sense.
>
> But GNU's ld is said to be smart enough to handle this like the
> developerwants "extern AND inline". I did not try, though.

I think you're gravely confused. Look at the assembly that gcc spits
out for extern inline functions. The linker never even gets to see the
function. Try it out, it'll be good practice for you.