include/linux/bitfield.h

Source file repositories/reference/linux-study-clean/include/linux/bitfield.h

File Facts

System
Linux kernel
Corpus path
include/linux/bitfield.h
Extension
.h
Size
10517 bytes
Lines
320
Domain
Core OS
Bucket
Core Kernel Interface
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

#ifndef _LINUX_BITFIELD_H
#define _LINUX_BITFIELD_H

#include <linux/build_bug.h>
#include <linux/compiler.h>
#include <linux/typecheck.h>
#include <asm/byteorder.h>

/*
 * Bitfield access macros
 *
 * FIELD_{GET,PREP} macros take as first parameter shifted mask
 * from which they extract the base mask and shift amount.
 * Mask must be a compilation time constant.
 * field_{get,prep} are variants that take a non-const mask.
 *
 * Example:
 *
 *  #include <linux/bitfield.h>
 *  #include <linux/bits.h>
 *
 *  #define REG_FIELD_A  GENMASK(6, 0)
 *  #define REG_FIELD_B  BIT(7)
 *  #define REG_FIELD_C  GENMASK(15, 8)
 *  #define REG_FIELD_D  GENMASK(31, 16)
 *
 * Get:
 *  a = FIELD_GET(REG_FIELD_A, reg);
 *  b = FIELD_GET(REG_FIELD_B, reg);
 *
 * Set:
 *  reg = FIELD_PREP(REG_FIELD_A, 1) |
 *	  FIELD_PREP(REG_FIELD_B, 0) |
 *	  FIELD_PREP(REG_FIELD_C, c) |
 *	  FIELD_PREP(REG_FIELD_D, 0x40);
 *
 * Modify:
 *  FIELD_MODIFY(REG_FIELD_C, &reg, c);
 */

#define __bf_shf __builtin_ctzll

#define __scalar_type_to_unsigned_cases(type)				\
		unsigned type:	(unsigned type)0,			\
		signed type:	(unsigned type)0

#define __unsigned_scalar_typeof(x) typeof(				\
		_Generic((x),						\
			char:	(unsigned char)0,			\
			__scalar_type_to_unsigned_cases(char),		\
			__scalar_type_to_unsigned_cases(short),		\
			__scalar_type_to_unsigned_cases(int),		\
			__scalar_type_to_unsigned_cases(long),		\
			__scalar_type_to_unsigned_cases(long long),	\
			default: (x)))

#define __bf_cast_unsigned(type, x)	((__unsigned_scalar_typeof(type))(x))

#define __BF_FIELD_CHECK_MASK(_mask, _val, _pfx)			\
	({								\
		BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask),		\
				 _pfx "mask is not constant");		\
		BUILD_BUG_ON_MSG((_mask) == 0, _pfx "mask is zero");	\
		BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ?		\
				 ~((_mask) >> __bf_shf(_mask)) &	\
					(0 + (_val)) : 0,		\
				 _pfx "value too large for the field"); \
		__BUILD_BUG_ON_NOT_POWER_OF_2((_mask) +			\
					      (1ULL << __bf_shf(_mask))); \
	})

#define __BF_FIELD_CHECK_REG(mask, reg, pfx)				\
	BUILD_BUG_ON_MSG(__bf_cast_unsigned(mask, mask) >		\
			 __bf_cast_unsigned(reg, ~0ull),		\
			 pfx "type of reg too small for mask")

#define __BF_FIELD_CHECK(mask, reg, val, pfx)				\
	({								\
		__BF_FIELD_CHECK_MASK(mask, val, pfx);			\
		__BF_FIELD_CHECK_REG(mask, reg, pfx);			\
	})

#define __FIELD_PREP(mask, val, pfx)					\
	({								\
		__BF_FIELD_CHECK_MASK(mask, val, pfx);			\
		((typeof(mask))(val) << __bf_shf(mask)) & (mask);	\
	})

#define __FIELD_GET(mask, reg, pfx)					\
	({								\

Annotation

Implementation Notes