[ccan] [PATCH v2 2/2] maskn & bitops: add new modules
Cody P Schafer
dev at codyps.com
Fri Jul 11 10:29:32 EST 2014
On Thu, Jul 10, 2014 at 7:08 AM, David Gibson
<david at gibson.dropbear.id.au> wrote:
> On Wed, Jul 09, 2014 at 09:49:44PM -0400, Cody P Schafer wrote:
>> 'maskn' provides generation of n-bit masks from a given range.
>> 'bitops' provides some generic bit operations that maskn needs.
[...]
>> diff --git a/ccan/bitops/bitops.c b/ccan/bitops/bitops.c
>> new file mode 100644
>> index 0000000..a9c233b
>> --- /dev/null
>> +++ b/ccan/bitops/bitops.c
>> @@ -0,0 +1,10 @@
>> +/* CC0 (Public Domain) - see LICENSE file for details */
>> +#include <ccan/bitops/bitops.h>
>> +
>> +extern inline uintmax_t bit_mask_nz(unsigned bits);
>> +extern inline uintmax_t bit_mask(unsigned bits);
>
> Hrm.. does "extern inline" actually have a well-defined portable
> meeting?
In c99 and later, yes. The c99 rationale (
http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf ) has
some details, which this stack overflow post (
http://stackoverflow.com/a/6312854 ) has a textual copy of.
c89, on the other hand, lacks inline and gnu89 reverses the meaning of
"extern inline" and "inline".
> I still think these functions are so simple they should be static
> inlines, at least the builtin versions. Not everyone has LTO.
Well, I don't want these to be unconditionally inlined. I'd very much
rather have the compiler decide than increase code size even when it
isn't a great idea.
>> +extern inline unsigned clz_32(uint32_t v);
>> +extern inline unsigned ctz_32(uint32_t v);
>> +extern inline unsigned fls_32(uint32_t v);
>> +extern inline unsigned fls_r1_32(uint32_t v);
>
> As I recall, fls_r1_32 was useful in maskn, but didn't have a
> particularly obvious function outside that. So, wouldn't it make more
> sense to be a static in the maskn module itself?
I don't really see a point in hiding it. Someone else may have an
algorithm it's useful in.
>> +/**
>> + * bit_mask_nz - given a non-zero number of bits, returns a left justified bit
>> + * mask with that many bits set
>
> It's right justified, not left, isn't it?
ya, you're correct, it is right justified.
>> + *
>> + * Note that the number of bits must be non-zero AND less than or equal to
>> + * CHAR_BIT * sizeof(uintmax_t), ie: the number of bits in a uintmax_t.
>> + */
>
> I think these descriptive comments would be more accessible in the .h
> than the .c.
This is the header. I could move them from the definitions to the
declarations, though. Perhaps move the definitions to a seperate
header to make clear what the api is.
>> +CONST_FUNCTION
>> +inline uintmax_t bit_mask_nz(unsigned bits)
>> +{
>> + assert(bits);
>> + assert(bits <= (CHAR_BIT * sizeof(uintmax_t)));
>> + return (UINTMAX_C(1) << ((bits) - 1) << 1) - 1;
>> +}
>> +
>> +/**
>> + * bit_mask - given a number of bits, returns a left justified bit mask with
>> + * that many bits set
>> + *
>> + * Note that the number of bits must be less than or equal to CHAR_BIT *
>> + * sizeof(uintmax_t), ie: the number of bits in a uintmax_t.
>> + */
>> +CONST_FUNCTION
>> +inline uintmax_t bit_mask(unsigned bits)
>> +{
>> + return bits ? bit_mask_nz(bits) : 0;
>> +}
>
> This still seems a ludicrously round about way of constructing a
> mask. The -1 << 1 trick pushes the limit on bits out by one by opens
> a new problem with bits == 0. What about
>
> static inline uint uintmax_t bit_mask(unsigned bits)
> {
> if (bits >= CHAR_BIT * sizeof(uintmax_t))
> return UINTMAX_C(-1);
> else
> return ~(UINTMAX_MAX << bits);
> }
>
> [snip]
I'm not opposed to swapping it out. Defining the function for all
inputs certainly has some benefits.
>> diff --git a/ccan/maskn/LICENSE b/ccan/maskn/LICENSE
>> new file mode 120000
>> index 0000000..7455044
>> --- /dev/null
>> +++ b/ccan/maskn/LICENSE
>> @@ -0,0 +1 @@
>> +../../licenses/LGPL-3
>> \ No newline at end of file
>> diff --git a/ccan/maskn/_info b/ccan/maskn/_info
>> new file mode 100644
>> index 0000000..6a71f33
>> --- /dev/null
>> +++ b/ccan/maskn/_info
>> @@ -0,0 +1,44 @@
>> +#include "config.h"
>> +#include <string.h>
>> +#include <stdio.h>
>> +
>> +/**
>> + * maskn - generate masks of N bits for a given range
>> + *
>> + * This module generates masks of N bits, as opposed to arbitrary masks where
>> + * any bits can be 0 or * 1. In this module, only the trailing bits are 0, all
>> + * others are 1.
>> + *
>> + * This mask generation is useful in interfacing with hardware that only
>> + * provides limited matching capabilities. An example is the cortex-m3 DWT
>> + * hardware module, which can be given a comparison value and a number of bits
>> + * to mask off the of anything compared against it.
>
> "off the of"?
>
"off the lower bits of"
More information about the ccan
mailing list