2012-04-06 13:54:56 -07:00
# ifndef _ASM_WORD_AT_A_TIME_H
# define _ASM_WORD_AT_A_TIME_H
2012-05-23 20:12:50 -07:00
# include <linux/kernel.h>
2012-04-06 13:54:56 -07:00
/*
* This is largely generic for little - endian machines , but the
* optimal byte mask counting is probably going to be something
* that is architecture - specific . If you have a reliably fast
* bit count instruction , that might be better than the multiply
* and shift , for example .
*/
word-at-a-time: make the interfaces truly generic
This changes the interfaces in <asm/word-at-a-time.h> to be a bit more
complicated, but a lot more generic.
In particular, it allows us to really do the operations efficiently on
both little-endian and big-endian machines, pretty much regardless of
machine details. For example, if you can rely on a fast population
count instruction on your architecture, this will allow you to make your
optimized <asm/word-at-a-time.h> file with that.
NOTE! The "generic" version in include/asm-generic/word-at-a-time.h is
not truly generic, it actually only works on big-endian. Why? Because
on little-endian the generic algorithms are wasteful, since you can
inevitably do better. The x86 implementation is an example of that.
(The only truly non-generic part of the asm-generic implementation is
the "find_zero()" function, and you could make a little-endian version
of it. And if the Kbuild infrastructure allowed us to pick a particular
header file, that would be lovely)
The <asm/word-at-a-time.h> functions are as follows:
- WORD_AT_A_TIME_CONSTANTS: specific constants that the algorithm
uses.
- has_zero(): take a word, and determine if it has a zero byte in it.
It gets the word, the pointer to the constant pool, and a pointer to
an intermediate "data" field it can set.
This is the "quick-and-dirty" zero tester: it's what is run inside
the hot loops.
- "prep_zero_mask()": take the word, the data that has_zero() produced,
and the constant pool, and generate an *exact* mask of which byte had
the first zero. This is run directly *outside* the loop, and allows
the "has_zero()" function to answer the "is there a zero byte"
question without necessarily getting exactly *which* byte is the
first one to contain a zero.
If you do multiple byte lookups concurrently (eg "hash_name()", which
looks for both NUL and '/' bytes), after you've done the prep_zero_mask()
phase, the result of those can be or'ed together to get the "either
or" case.
- The result from "prep_zero_mask()" can then be fed into "find_zero()"
(to find the byte offset of the first byte that was zero) or into
"zero_bytemask()" (to find the bytemask of the bytes preceding the
zero byte).
The existence of zero_bytemask() is optional, and is not necessary
for the normal string routines. But dentry name hashing needs it, so
if you enable DENTRY_WORD_AT_A_TIME you need to expose it.
This changes the generic strncpy_from_user() function and the dentry
hashing functions to use these modified word-at-a-time interfaces. This
gets us back to the optimized state of the x86 strncpy that we lost in
the previous commit when moving over to the generic version.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-26 10:43:17 -07:00
struct word_at_a_time {
const unsigned long one_bits , high_bits ;
} ;
# define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
2012-04-06 13:54:56 -07:00
# ifdef CONFIG_64BIT
/*
* Jan Achrenius on G + : microoptimized version of
* the simpler " (mask & ONEBYTES) * ONEBYTES >> 56 "
* that works for the bytemasks without having to
* mask them first .
*/
static inline long count_masked_bytes ( unsigned long mask )
{
return mask * 0x0001020304050608ul > > 56 ;
}
# else /* 32-bit case */
/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
static inline long count_masked_bytes ( long mask )
{
/* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
long a = ( 0x0ff0001 + mask ) > > 23 ;
/* Fix the 1 for 00 case */
return a & mask ;
}
# endif
word-at-a-time: make the interfaces truly generic
This changes the interfaces in <asm/word-at-a-time.h> to be a bit more
complicated, but a lot more generic.
In particular, it allows us to really do the operations efficiently on
both little-endian and big-endian machines, pretty much regardless of
machine details. For example, if you can rely on a fast population
count instruction on your architecture, this will allow you to make your
optimized <asm/word-at-a-time.h> file with that.
NOTE! The "generic" version in include/asm-generic/word-at-a-time.h is
not truly generic, it actually only works on big-endian. Why? Because
on little-endian the generic algorithms are wasteful, since you can
inevitably do better. The x86 implementation is an example of that.
(The only truly non-generic part of the asm-generic implementation is
the "find_zero()" function, and you could make a little-endian version
of it. And if the Kbuild infrastructure allowed us to pick a particular
header file, that would be lovely)
The <asm/word-at-a-time.h> functions are as follows:
- WORD_AT_A_TIME_CONSTANTS: specific constants that the algorithm
uses.
- has_zero(): take a word, and determine if it has a zero byte in it.
It gets the word, the pointer to the constant pool, and a pointer to
an intermediate "data" field it can set.
This is the "quick-and-dirty" zero tester: it's what is run inside
the hot loops.
- "prep_zero_mask()": take the word, the data that has_zero() produced,
and the constant pool, and generate an *exact* mask of which byte had
the first zero. This is run directly *outside* the loop, and allows
the "has_zero()" function to answer the "is there a zero byte"
question without necessarily getting exactly *which* byte is the
first one to contain a zero.
If you do multiple byte lookups concurrently (eg "hash_name()", which
looks for both NUL and '/' bytes), after you've done the prep_zero_mask()
phase, the result of those can be or'ed together to get the "either
or" case.
- The result from "prep_zero_mask()" can then be fed into "find_zero()"
(to find the byte offset of the first byte that was zero) or into
"zero_bytemask()" (to find the bytemask of the bytes preceding the
zero byte).
The existence of zero_bytemask() is optional, and is not necessary
for the normal string routines. But dentry name hashing needs it, so
if you enable DENTRY_WORD_AT_A_TIME you need to expose it.
This changes the generic strncpy_from_user() function and the dentry
hashing functions to use these modified word-at-a-time interfaces. This
gets us back to the optimized state of the x86 strncpy that we lost in
the previous commit when moving over to the generic version.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-26 10:43:17 -07:00
/* Return nonzero if it has a zero */
static inline unsigned long has_zero ( unsigned long a , unsigned long * bits , const struct word_at_a_time * c )
{
unsigned long mask = ( ( a - c - > one_bits ) & ~ a ) & c - > high_bits ;
* bits = mask ;
return mask ;
}
static inline unsigned long prep_zero_mask ( unsigned long a , unsigned long bits , const struct word_at_a_time * c )
{
return bits ;
}
static inline unsigned long create_zero_mask ( unsigned long bits )
{
bits = ( bits - 1 ) & ~ bits ;
return bits > > 7 ;
}
/* The mask we created is directly usable as a bytemask */
# define zero_bytemask(mask) (mask)
static inline unsigned long find_zero ( unsigned long mask )
2012-04-06 13:54:56 -07:00
{
word-at-a-time: make the interfaces truly generic
This changes the interfaces in <asm/word-at-a-time.h> to be a bit more
complicated, but a lot more generic.
In particular, it allows us to really do the operations efficiently on
both little-endian and big-endian machines, pretty much regardless of
machine details. For example, if you can rely on a fast population
count instruction on your architecture, this will allow you to make your
optimized <asm/word-at-a-time.h> file with that.
NOTE! The "generic" version in include/asm-generic/word-at-a-time.h is
not truly generic, it actually only works on big-endian. Why? Because
on little-endian the generic algorithms are wasteful, since you can
inevitably do better. The x86 implementation is an example of that.
(The only truly non-generic part of the asm-generic implementation is
the "find_zero()" function, and you could make a little-endian version
of it. And if the Kbuild infrastructure allowed us to pick a particular
header file, that would be lovely)
The <asm/word-at-a-time.h> functions are as follows:
- WORD_AT_A_TIME_CONSTANTS: specific constants that the algorithm
uses.
- has_zero(): take a word, and determine if it has a zero byte in it.
It gets the word, the pointer to the constant pool, and a pointer to
an intermediate "data" field it can set.
This is the "quick-and-dirty" zero tester: it's what is run inside
the hot loops.
- "prep_zero_mask()": take the word, the data that has_zero() produced,
and the constant pool, and generate an *exact* mask of which byte had
the first zero. This is run directly *outside* the loop, and allows
the "has_zero()" function to answer the "is there a zero byte"
question without necessarily getting exactly *which* byte is the
first one to contain a zero.
If you do multiple byte lookups concurrently (eg "hash_name()", which
looks for both NUL and '/' bytes), after you've done the prep_zero_mask()
phase, the result of those can be or'ed together to get the "either
or" case.
- The result from "prep_zero_mask()" can then be fed into "find_zero()"
(to find the byte offset of the first byte that was zero) or into
"zero_bytemask()" (to find the bytemask of the bytes preceding the
zero byte).
The existence of zero_bytemask() is optional, and is not necessary
for the normal string routines. But dentry name hashing needs it, so
if you enable DENTRY_WORD_AT_A_TIME you need to expose it.
This changes the generic strncpy_from_user() function and the dentry
hashing functions to use these modified word-at-a-time interfaces. This
gets us back to the optimized state of the x86 strncpy that we lost in
the previous commit when moving over to the generic version.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-26 10:43:17 -07:00
return count_masked_bytes ( mask ) ;
2012-04-06 13:54:56 -07:00
}
2012-05-03 10:16:43 -07:00
/*
* Load an unaligned word from kernel space .
*
* In the ( very unlikely ) case of the word being a page - crosser
* and the next page not being mapped , take the exception and
* return zeroes in the non - existing part .
*/
static inline unsigned long load_unaligned_zeropad ( const void * addr )
{
unsigned long ret , dummy ;
asm (
" 1: \t mov %2,%0 \n "
" 2: \n "
" .section .fixup, \" ax \" \n "
" 3: \t "
" lea %2,%1 \n \t "
" and %3,%1 \n \t "
" mov (%1),%0 \n \t "
" leal %2,%%ecx \n \t "
" andl %4,%%ecx \n \t "
" shll $3,%%ecx \n \t "
" shr %%cl,%0 \n \t "
" jmp 2b \n "
" .previous \n "
_ASM_EXTABLE ( 1 b , 3 b )
: " =&r " ( ret ) , " =&c " ( dummy )
: " m " ( * ( unsigned long * ) addr ) ,
" i " ( - sizeof ( unsigned long ) ) ,
" i " ( sizeof ( unsigned long ) - 1 ) ) ;
return ret ;
}
2012-04-06 13:54:56 -07:00
# endif /* _ASM_WORD_AT_A_TIME_H */