linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Paul Jackson <pj@sgi.com>
To: Paul Jackson <pj@sgi.com>
Cc: colpatch@us.ibm.com, wli@holomorphy.com, linux-kernel@vger.kernel.org
Subject: [Patch 5/23] mask v2 - Add new mask.h file
Date: Thu, 1 Apr 2004 13:11:29 -0800	[thread overview]
Message-ID: <20040401131129.4329336f.pj@sgi.com> (raw)
In-Reply-To: <20040401122802.23521599.pj@sgi.com>

Patch_5_of_23 - New mask ADT
	Adds new include/linux/mask.h header file

	==> See this mask.h header for more extensive mask documentation <==

Diffstat Patch_5_of_23:
 mask.h                         |  362 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 362 insertions(+)

===================================================================
--- 2.6.4.orig/include/linux/mask.h	1969-12-31 16:00:00.000000000 -0800
+++ 2.6.4/include/linux/mask.h	2004-04-01 09:31:34.000000000 -0800
@@ -0,0 +1,369 @@
+#ifndef __LINUX_MASK_H
+#define __LINUX_MASK_H
+
+/*
+ * include/linux/mask.h
+ *
+ * Copyright (c) 2004 Silicon Graphics, Inc. All rights reserved.
+ *
+ * Paul Jackson <pj@sgi.com>
+ *
+ * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this
+ * software for more info.
+ */
+
+/*
+ * Mask is an abstract data type for multi-word bit masks.  Masks
+ * are bitmaps (arrays of unsigned longs) wrapped in a struct.
+ * The struct wrapper enables them to be assigned and passed as
+ * arguments.  Masks are useful for representing sets of small
+ * numbers, such as the CPU numbers on a multi-processor system.
+ *
+ * How mask.h fits with bitops.h, bitmap.h, cpumask.h and nodemask.h:
+ *
+ *  1) bitmap.h and lib/bitmap.c provide several operations
+ *     for manipulating bitmaps, as arrays of unsigned long.
+ *     There are operations that and, or, set, clear, shift,
+ *     print, parse, and test these bitmaps.  The routines
+ *     typically require a pointer to an array of unsigned longs,
+ *     and a count of the number of valid bits therein.
+ *
+ *     The byte ordering of bitmaps is more natural on little
+ *     endian architectures.  See the big-endian headers
+ *     include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
+ *     for the best explanations of this ordering.
+ *
+ *  2) bitops.h provides a few specific inline routines for
+ *     finding the first set bit and the Hamming weight of
+ *     these same bitmaps.  Several architectures provide
+ *     include/asm-<arch>/bitops.h variants, optimized for
+ *     specific processor instruction sets.
+ *
+ *  3) mask.h makes use of bitmap.h, bitops.h and a few other
+ *     kernel utilities to provide a mask abstract data type
+ *     (ADT) as a structure of an array of unsigned longs.
+ *     mask.h attempts to provide a fairly complete set of
+ *     operations, to make it easy for users to write clear
+ *     concise and correct mask manipulation code.
+ *
+ *     The mask macros use the fairly rich compile time
+ *     optimizations of gcc in order to generate optimum code
+ *     for each architecture.  Some of these macros require the
+ *     current mask type or number of bits - the cpumask.h and
+ *     nodemask.h macros serve to hide such details.
+ *
+ *  4) cpumask.h and nodemask.h are both based on mask.h.
+ *     They provide cpu and node specific macros that hide
+ *     such details as NR_CPUS that might be needed by the
+ *     lower level mask macros defined below.
+ *
+ * Summary:
+ *     Don't use mask.h directly - use cpumask.h and nodemask.h.
+ *
+ * The available mask operations and their rough meaning in the
+ * case that "nbits == BITS_PER_LONG" are:
+ *
+ * __mask(nbits)			Use to define new *mask types
+ * mask_setbit(bit, mask)		mask |= bit
+ * mask_clearbit(bit, mask)		mask &= ~bit
+ * mask_setall(mask, nbits)		mask = ~0UL
+ * mask_clearall(mask, nbits)		mask = 0UL
+ * mask_isset(bit, mask)		Is bit set in mask?
+ * mask_test_and_set(bit, mask)		mask & bit ? 1 : (mask |= bit, 0)
+ * mask_and(dst, src1, src2, nbits)	dst = src1 & src2
+ * mask_or(dst, src1, src2, nbits)	dst = src1 | src2
+ * mask_xor(dst, src1, src2, nbits)	dst = src1 ^ src2
+ * mask_andnot(dst, src1, src2, nbits)	dst = src1 & ~src2
+ * mask_complement(dst, src, nbits)	dst = ~src
+ * mask_equal(mask1, mask2, nbits)	Are mask1 and mask2 equal?
+ * mask_intersects(mask1, mask2, nbits) Do mask1 and mask2 overlap?
+ * mask_subset(mask1, mask2, nbits)	Is mask1 a subset of mask2?
+ * mask_empty(mask, nbits)		Is mask empty?
+ * mask_full(mask, nbits)		Are all bits set in mask?
+ * mask_weight(mask, nbits)		Hamming Weight: number set bits
+ * mask_shift_right(dst, src, n, nbits)	dst = src >> n
+ * mask_shift_left(dst, src, n, nbits)	dst = src << n
+ * mask_first(mask, nbits)		find_first_bit(mask, nbits)
+ * mask_next(bit, mask, nbits)		find_next_bit(mask, size, bit, nbits)
+ * mask_of_bit(bit, T)			returns mask with a single bit set
+ * MASK_ALL(nbits)			returns mask with all bits set
+ * MASK_NONE(nbits)			returns mask with no bits set
+ * mask_addr(mask)			Array of unsigned long's in mask
+ * mask_scnprintf(buf, len, mask, nbits) scnprintf(buf, len, "%lx", mask, nbits)
+ * mask_parse(ubuf, ulen, mask, nbits)	parse comma sep 32 bit words to mask
+ *
+ *           Various Implementation Details
+ *           ==============================
+ *
+ * The parameter 'T' above must be a variable of the appropriate
+ *   mask type (cpumask_t or nodemask_t, for instance).  This
+ *   variable is only used for its typeof() information.
+ *
+ * For details of mask_scnprintf() and mask_parse(), see
+ *   bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c
+ *
+ * A new *mask type should be defined, such as cpumask_t or
+ *   nodemask_t, for each possibly different sized (number of
+ *   bits) bitmask based on this mask ADT.  The definition
+ *   for example of cpumask_t is:
+ *           typedef __mask(NR_CPUS) cpumask_t;
+ *
+ * The previous definitions of CPU_MASK_ALL were inconsistent.
+ *   For cpumasks of one word size or less, they set exactly
+ *   NR_CPUS bits, leaving any remaining high order bits zero.
+ *   For cpumasks of multiple words, all bits were set, which
+ *   might result in a cpumask of weight > NR_CPUS, if NR_CPUS is
+ *   not an exact multiple of the number of bits in an unsigned
+ *   long.  The MASK_ALL(nbits) macro fixes this inconsistency
+ *   by refining the static initializor to set only valid bits
+ *   in the last word.
+ *
+ * These macros presume that all masks passed in a given call
+ *   are the same nbits long, and that only bits in positions
+ *   b where 0 <= b < nbits might be set in input masks.
+ *   They ensure that no additional bits outside this range
+ *   become set (however don't protect against improperly set
+ *   bits that are outside this range but still inside the array
+ *   of unsigned longs representing the mask.)  In other words,
+ *   any implementation of these ops may assume as a precondition
+ *   that any unused bits (bits in the array of unsigned
+ *   longs, outside the range 0 to nbits-1) are zero.  And any
+ *   implementation of these ops must ensure as a postcondition
+ *   on all output masks that this same precondition (unused
+ *   bits are zero) holds.  If you manage to create, by some
+ *   other means, a mask with some unused bits non-zero, and
+ *   then pass that mask to one of these mask operations, that
+ *   operation may malfunction.
+ *
+ * The abstract bit model supported by these masks is that of
+ *   an infinite set of bits, in positions numbered 0 and up,
+ *   where all but the first 'nbits' bits are always zero.
+ *   Calls that implicitly attempt to set any bit outside of
+ *   the first 'nbits' bits successfully and quietly leave such
+ *   bits as zero.  Calls that query or modify specifically
+ *   numbered bit positions require as a precondition that the
+ *   specified bit position 'n' is the range 0 <= n < nbits, and
+ *   may malfunction if handed a bit position outside this range.
+ *
+ * The mask_addr() op enables violating this model.  It returns
+ *   the address of the start of the array of unsigned
+ *   longs, enabling the caller to directly manipulate them.
+ *   This can be used to intermix mask ops with classic 'C' bit
+ *   operations, usually only done on systems whose cpumask_t
+ *   fits in a single unsigned long word.
+ *
+ * The underlying bitmap.c operations such as bitmap_and() and
+ *   bitmap_or() don't follow this model.  They don't assume
+ *   the precondition that unused bits are zero, and they do not
+ *   mask off any unused portion of input masks in most cases.
+ *   The bitmap operations that produce Boolean or scalar results,
+ *   such as for empty, full and weight, _do_ filter out unused bits.
+ *   However the underlying bitop.h operations, such as set_bit()
+ *   and clear_bit(), do no sanitizing of their inputs, depending
+ *   heavily on preconditions.
+ *
+ * The declaration of the array _m[] of unsigned longs in the
+ *   definition of __mask() below intentionally does not use
+ *   the DECLARE_BITMAP() macro.  It would be gratuitously opaque
+ *   in this case - as the macro implementations below depend on
+ *   the internal details of this declaration.
+ *
+ * The MASK_LAST_WORD() macro defines the value of the last (high
+ *   order) word of a bitmask.  In particular, for the case of a
+ *   mask of a size that is an exact multiple of the word size,
+ *   with all bits set, it ensures that this value is all one's,
+ *   not all zero's.
+ *
+ * The file include/mask.h applies to all architectures.
+ *   Architectures requiring custom details should provide
+ *   them in their include/asm-<arch>/bitops.h file, and
+ *   if necessary modify the common include/linux/mask.h
+ *   file to conditionally generate the necessary code,
+ *   depending on compile time settings.  No need to write
+ *   ugly #ifdef's to do this - gcc provides a rich set
+ *   of compile time extensions.  See further for example:
+ *   http://gcc.gnu.org/onlinedocs/gcc-3.3.3/gcc/C-Extensions.html
+ *
+ * Some architectures (I'm told sparc32) do not pass structures
+ *   efficiently as arguments to subroutine calls, even if the
+ *   structure is just one word long.  If you need to pass
+ *   a cpumask or nodemask to a subroutine in a performance
+ *   critical path on such an architecture, then as an
+ *   alternative, pass the first unsigned long of the mask
+ *   directly, using cpus_addr() or nodes_addr().  Of course,
+ *   if your masks are more than one word long, this won't
+ *   be adequate.
+ */
+
+#include "linux/bitops.h"
+#include "linux/string.h"
+#include "linux/types.h"
+#include "linux/kernel.h"
+#include "linux/bitmap.h"
+
+#define __mask(bits)	struct { unsigned long _m[BITS_TO_LONGS(bits)]; }
+
+#define MASK_LAST_WORD(nbits)						\
+(									\
+	((nbits) % BITS_PER_LONG) ?					\
+		(1<<((nbits) % BITS_PER_LONG))-1 : ~0UL			\
+)				
+
+#define mask_setbit(bit, mask)						\
+	set_bit((bit), (mask)._m)
+
+#define mask_clearbit(bit, mask)					\
+	clear_bit((bit), (mask)._m)
+
+#define mask_setall(mask, nbits) 					\
+do {									\
+	size_t sz_all_but_last = sizeof(mask) - sizeof(unsigned long);	\
+	if (sz_all_but_last > 0)					\
+		memset((mask)._m, 0xff, sz_all_but_last);		\
+	(mask)._m[BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits);	\
+} while(0)
+
+#define mask_clearall(mask, nbits) 					\
+do {									\
+	if (sizeof(mask) == sizeof(unsigned long))			\
+		(mask)._m[0] = 0UL;					\
+	else								\
+		bitmap_clear((mask)._m, (nbits));			\
+} while(0)
+
+#define mask_isset(bit, mask)						\
+	test_bit((bit), (mask)._m)
+
+#define mask_test_and_set(bit, mask)					\
+	test_and_set_bit((bit), (mask)._m)
+
+#define mask_and(dst, src1, src2, nbits)				\
+do {									\
+	if (sizeof(dst) == sizeof(unsigned long))			\
+		(dst)._m[0] = (src1)._m[0] & (src2)._m[0];		\
+	else								\
+		bitmap_and((dst)._m, (src1)._m, (src2)._m, (nbits));	\
+} while(0)
+
+#define mask_or(dst, src1, src2, nbits)					\
+do {									\
+	if (sizeof(dst) == sizeof(unsigned long))			\
+		(dst)._m[0] = (src1)._m[0] | (src2)._m[0];		\
+	else								\
+		bitmap_or((dst)._m, (src1)._m, (src2)._m, (nbits));	\
+} while(0)
+
+#define mask_xor(dst, src1, src2, nbits)				\
+do {									\
+	if (sizeof(dst) == sizeof(unsigned long))			\
+		(dst)._m[0] = (src1)._m[0] ^ (src2)._m[0];		\
+	else								\
+		bitmap_xor((dst)._m, (src1)._m, (src2)._m, (nbits));	\
+} while(0)
+
+#define mask_andnot(dst, src1, src2, nbits)				\
+do {									\
+	if (sizeof(dst) == sizeof(unsigned long))			\
+		(dst)._m[0] = (src1)._m[0] & ~(src2)._m[0];		\
+	else								\
+		bitmap_andnot((dst)._m, (src1)._m, (src2)._m, (nbits));	\
+} while(0)
+
+#define mask_complement(dst, src, nbits)				\
+	bitmap_complement((dst)._m, (src)._m, (nbits))
+
+#define mask_equal(mask1, mask2, nbits)					\
+({									\
+	int r;								\
+	if (sizeof(mask1) == sizeof(unsigned long))			\
+		r = ((mask1)._m[0] == (mask2)._m[0]);			\
+	else								\
+		r = bitmap_equal((mask1)._m, (mask2)._m, (nbits));	\
+	r;								\
+})
+
+#define mask_intersects(mask1, mask2, nbits)				\
+({									\
+	int r;								\
+	if (sizeof(mask1) == sizeof(unsigned long))			\
+		r = (((mask1)._m[0] & (mask2)._m[0]) != 0);		\
+	else								\
+		r = bitmap_intersects((mask1)._m, (mask2)._m, (nbits));	\
+	r;								\
+})
+
+#define mask_subset(mask1, mask2, nbits)				\
+({									\
+	int r;								\
+	if (sizeof(mask1) == sizeof(unsigned long))			\
+		r = (((mask1)._m[0] & ~(mask2)._m[0]) == 0);		\
+	else								\
+		r = bitmap_subset((mask1)._m, (mask2)._m, (nbits));	\
+	r;								\
+})
+
+#define mask_empty(mask, nbits)						\
+({									\
+	int r;								\
+	if (sizeof(mask) == sizeof(unsigned long))			\
+		r = ((mask)._m[0] == 0UL);				\
+	else								\
+		r = bitmap_empty((mask)._m, (nbits));			\
+	r;								\
+})
+
+#define mask_full(mask, nbits)						\
+	bitmap_full((mask)._m, (nbits))
+
+#define mask_weight(mask, nbits)					\
+	bitmap_weight((mask)._m, (nbits))
+
+#define mask_shift_right(dst, src, n, nbits)				\
+	bitmap_shift_right((dst)._m, (src)._m, (n), (nbits))
+
+#define mask_shift_left(dst, src, n, nbits)				\
+	bitmap_shift_left((dst)._m, (src)._m, (n), (nbits))
+
+#define mask_first(mask, nbits)						\
+	find_first_bit((mask)._m, (nbits))
+
+#define mask_next(bit, mask, nbits)					\
+	find_next_bit((mask)._m, (nbits), (bit)+1)
+
+#define mask_of_bit(bit, T)						\
+({									\
+	typeof(T) m;							\
+	mask_clearall(m, 8*sizeof(m));					\
+	mask_setbit((bit), m);						\
+	m;								\
+})
+
+/* Use if nbits <= BITS_PER_LONG */
+#define MASK_ALL1(nbits)						\
+{ {									\
+	[BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits)		\
+} }
+
+/* Use if nbits > BITS_PER_LONG */
+#define MASK_ALL2(nbits)						\
+{ {									\
+	[0 ... BITS_TO_LONGS(nbits)-2] = ~0UL,				\
+	[BITS_TO_LONGS(nbits)-1] = MASK_LAST_WORD(nbits)		\
+} }
+
+#define MASK_NONE(nbits)						\
+{ {									\
+	[0 ... BITS_TO_LONGS(nbits)-1] =  0UL				\
+} }
+
+#define mask_addr(mask)							\
+	((mask)._m)
+
+#define mask_scnprintf(buf, len, mask, nbits)				\
+	bitmap_scnprintf((buf), (len), ((mask)._m), (nbits))
+
+#define mask_parse(ubuf, ulen, mask, nbits)				\
+	bitmap_parse((ubuf), (ulen), ((mask)._m), (nbits))
+
+#endif /* __LINUX_MASK_H */


-- 
                          I won't rest till it's the best ...
                          Programmer, Linux Scalability
                          Paul Jackson <pj@sgi.com> 1.650.933.1373

  parent reply	other threads:[~2004-04-01 21:41 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-04-01 20:28 [Patch 0/23] mask v2 - Second version of mask, cpumask and nodemask consolidation Paul Jackson
2004-04-01 21:10 ` [Patch 1/23] mask v2 - Document bitmap.c bit model Paul Jackson
2004-04-01 21:10 ` [Patch 2/23] mask v2 - Tighten unused bitmap bit handling Paul Jackson
2004-04-01 21:11 ` [Patch 3/23] mask v2 - New bitmap operators Paul Jackson
2004-04-01 21:11 ` [Patch 4/23] mask v2 - two missing 'const' qualifiers Paul Jackson
2004-04-01 21:11 ` Paul Jackson [this message]
2004-04-02 20:26   ` [Patch 5/23] mask v2 - Add new mask.h file Matthew Dobson
2004-04-03  5:12     ` Paul Jackson
2004-04-01 21:11 ` [Patch 6/23] mask v2 - Replace cpumask_t with one using mask Paul Jackson
2004-04-02 22:24   ` Matthew Dobson
2004-04-02 23:35     ` Paul Jackson
2004-04-03  1:09       ` Matthew Dobson
2004-04-03  6:00         ` Paul Jackson
2004-04-04  5:57           ` Paul Jackson
2004-04-03  5:23     ` Paul Jackson
2004-04-01 21:11 ` [Patch 7/23] mask v2 - Remove i386 obsolete cpumask ops Paul Jackson
2004-04-01 21:11 ` [Patch 8/23] mask v2 - Remove ppc64 " Paul Jackson
2004-04-01 21:11 ` [Patch 9/23] mask v2 - Remove x86_64 " Paul Jackson
2004-04-01 21:12 ` [Patch 10/23] mask v2 - Remove obsolete cpumask emulation Paul Jackson
2004-04-01 21:12 ` [Patch 11/23] mask v2 - Add new nodemasks.h file Paul Jackson
2004-04-01 21:12 ` [Patch 12/23] mask v2 - [1/7] mmzone.h changes for nodemask Paul Jackson
2004-04-01 21:12 ` [Patch 13/23] mask v2 - [2/7] nodemask_t core changes Paul Jackson
2004-04-01 21:12 ` [Patch 14/23] mask v2 - [3/7] nodemask_t_i386_changes Paul Jackson
2004-04-01 21:12 ` [Patch 15/23] mask v2 - [4/7] nodemask_t_pp64_changes Paul Jackson
2004-04-01 21:12 ` [Patch 16/23] mask v2 - [5/7] nodemask_t_x86_64_changes Paul Jackson
2004-04-01 21:12 ` [Patch 17/23] mask v2 = [6/7] nodemask_t_ia64_changes Paul Jackson
2004-04-06 11:37   ` Paul Jackson
2004-04-07  5:55     ` Denis Vlasenko
2004-04-07  6:50       ` Paul Jackson
2004-04-07  7:44         ` Paul Jackson
2004-04-07 14:13           ` Nick Piggin
2004-04-07 14:44             ` Paul Jackson
2004-04-07 15:02               ` Nick Piggin
2004-04-07 15:21                 ` Paul Jackson
2004-04-09  7:54           ` Denis Vlasenko
2004-04-09 17:53             ` Paul Jackson
2004-04-09 20:04               ` Denis Vlasenko
2004-04-10  2:54                 ` Paul Jackson
2004-04-07 11:27         ` Paul Jackson
2004-04-09 18:54           ` Paul Jackson
2004-04-01 21:12 ` [Patch 18/23] mask v2 - [7/7] nodemask_t_other_arch_changes Paul Jackson
2004-04-01 21:12 ` [Patch 19/23] mask v2 - Simplify sparc64 cpumask loop code Paul Jackson
2004-04-01 21:12 ` [Patch 20/23] mask v2 - Optimize i386 cpumask macro usage Paul Jackson
2004-04-01 21:13 ` [Patch 21/23] mask v2 - Dyadic physids_complement() Paul Jackson
2004-04-01 21:13 ` [Patch 22/23] mask v2 - Fix cpumask in asm-x86_64/topology.h Paul Jackson
2004-04-01 21:13 ` [Patch 23/23] mask v2 - Cpumask tweak in kernel/sched.c Paul Jackson
2004-04-02  8:15 ` [Patch 24/23] mask v2 - Small system optimizations Paul Jackson
2004-04-04  5:56   ` Paul Jackson
2004-04-04  6:16 ` [Patch 24a/23] mask v2 - UP fix, faster mask_of_bit, MASK_ALL* names Paul Jackson

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=20040401131129.4329336f.pj@sgi.com \
    --to=pj@sgi.com \
    --cc=colpatch@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=wli@holomorphy.com \
    /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;
as well as URLs for NNTP newsgroup(s).