sysmacros.h revision 174049
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23/*	  All Rights Reserved  	*/
24
25
26/*
27 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28 * Use is subject to license terms.
29 */
30
31#ifndef _SYS_SYSMACROS_H
32#define	_SYS_SYSMACROS_H
33
34#pragma ident	"%Z%%M%	%I%	%E% SMI"
35
36#include <sys/param.h>
37
38#ifdef	__cplusplus
39extern "C" {
40#endif
41
42/*
43 * Some macros for units conversion
44 */
45/*
46 * Disk blocks (sectors) and bytes.
47 */
48#define	dtob(DD)	((DD) << DEV_BSHIFT)
49#define	btod(BB)	(((BB) + DEV_BSIZE - 1) >> DEV_BSHIFT)
50#define	btodt(BB)	((BB) >> DEV_BSHIFT)
51#define	lbtod(BB)	(((offset_t)(BB) + DEV_BSIZE - 1) >> DEV_BSHIFT)
52
53/* common macros */
54#ifndef MIN
55#define	MIN(a, b)	((a) < (b) ? (a) : (b))
56#endif
57#ifndef MAX
58#define	MAX(a, b)	((a) < (b) ? (b) : (a))
59#endif
60#ifndef ABS
61#define	ABS(a)		((a) < 0 ? -(a) : (a))
62#endif
63
64#ifdef _KERNEL
65
66/*
67 * Convert a single byte to/from binary-coded decimal (BCD).
68 */
69extern unsigned char byte_to_bcd[256];
70extern unsigned char bcd_to_byte[256];
71
72#define	BYTE_TO_BCD(x)	byte_to_bcd[(x) & 0xff]
73#define	BCD_TO_BYTE(x)	bcd_to_byte[(x) & 0xff]
74
75#endif	/* _KERNEL */
76
77/*
78 * WARNING: The device number macros defined here should not be used by device
79 * drivers or user software. Device drivers should use the device functions
80 * defined in the DDI/DKI interface (see also ddi.h). Application software
81 * should make use of the library routines available in makedev(3). A set of
82 * new device macros are provided to operate on the expanded device number
83 * format supported in SVR4. Macro versions of the DDI device functions are
84 * provided for use by kernel proper routines only. Macro routines bmajor(),
85 * major(), minor(), emajor(), eminor(), and makedev() will be removed or
86 * their definitions changed at the next major release following SVR4.
87 */
88
89#define	O_BITSMAJOR	7	/* # of SVR3 major device bits */
90#define	O_BITSMINOR	8	/* # of SVR3 minor device bits */
91#define	O_MAXMAJ	0x7f	/* SVR3 max major value */
92#define	O_MAXMIN	0xff	/* SVR3 max minor value */
93
94
95#define	L_BITSMAJOR32	14	/* # of SVR4 major device bits */
96#define	L_BITSMINOR32	18	/* # of SVR4 minor device bits */
97#define	L_MAXMAJ32	0x3fff	/* SVR4 max major value */
98#define	L_MAXMIN32	0x3ffff	/* MAX minor for 3b2 software drivers. */
99				/* For 3b2 hardware devices the minor is */
100				/* restricted to 256 (0-255) */
101
102#ifdef _LP64
103#define	L_BITSMAJOR	32	/* # of major device bits in 64-bit Solaris */
104#define	L_BITSMINOR	32	/* # of minor device bits in 64-bit Solaris */
105#define	L_MAXMAJ	0xfffffffful	/* max major value */
106#define	L_MAXMIN	0xfffffffful	/* max minor value */
107#else
108#define	L_BITSMAJOR	L_BITSMAJOR32
109#define	L_BITSMINOR	L_BITSMINOR32
110#define	L_MAXMAJ	L_MAXMAJ32
111#define	L_MAXMIN	L_MAXMIN32
112#endif
113
114#if defined(sun)
115#ifdef _KERNEL
116
117/* major part of a device internal to the kernel */
118
119#define	major(x)	(major_t)((((unsigned)(x)) >> O_BITSMINOR) & O_MAXMAJ)
120#define	bmajor(x)	(major_t)((((unsigned)(x)) >> O_BITSMINOR) & O_MAXMAJ)
121
122/* get internal major part of expanded device number */
123
124#define	getmajor(x)	(major_t)((((dev_t)(x)) >> L_BITSMINOR) & L_MAXMAJ)
125
126/* minor part of a device internal to the kernel */
127
128#define	minor(x)	(minor_t)((x) & O_MAXMIN)
129
130/* get internal minor part of expanded device number */
131
132#define	getminor(x)	(minor_t)((x) & L_MAXMIN)
133
134#else
135
136/* major part of a device external from the kernel (same as emajor below) */
137
138#define	major(x)	(major_t)((((unsigned)(x)) >> O_BITSMINOR) & O_MAXMAJ)
139
140/* minor part of a device external from the kernel  (same as eminor below) */
141
142#define	minor(x)	(minor_t)((x) & O_MAXMIN)
143
144#endif	/* _KERNEL */
145
146/* create old device number */
147
148#define	makedev(x, y) (unsigned short)(((x) << O_BITSMINOR) | ((y) & O_MAXMIN))
149
150/* make an new device number */
151
152#define	makedevice(x, y) (dev_t)(((dev_t)(x) << L_BITSMINOR) | ((y) & L_MAXMIN))
153
154
155/*
156 * emajor() allows kernel/driver code to print external major numbers
157 * eminor() allows kernel/driver code to print external minor numbers
158 */
159
160#define	emajor(x) \
161	(major_t)(((unsigned int)(x) >> O_BITSMINOR) > O_MAXMAJ) ? \
162	    NODEV : (((unsigned int)(x) >> O_BITSMINOR) & O_MAXMAJ)
163
164#define	eminor(x) \
165	(minor_t)((x) & O_MAXMIN)
166
167/*
168 * get external major and minor device
169 * components from expanded device number
170 */
171#define	getemajor(x)	(major_t)((((dev_t)(x) >> L_BITSMINOR) > L_MAXMAJ) ? \
172			    NODEV : (((dev_t)(x) >> L_BITSMINOR) & L_MAXMAJ))
173#define	geteminor(x)	(minor_t)((x) & L_MAXMIN)
174
175#endif /* sun */
176
177/*
178 * These are versions of the kernel routines for compressing and
179 * expanding long device numbers that don't return errors.
180 */
181#if (L_BITSMAJOR32 == L_BITSMAJOR) && (L_BITSMINOR32 == L_BITSMINOR)
182
183#define	DEVCMPL(x)	(x)
184#define	DEVEXPL(x)	(x)
185
186#else
187
188#define	DEVCMPL(x)	\
189	(dev32_t)((((x) >> L_BITSMINOR) > L_MAXMAJ32 || \
190	    ((x) & L_MAXMIN) > L_MAXMIN32) ? NODEV32 : \
191	    ((((x) >> L_BITSMINOR) << L_BITSMINOR32) | ((x) & L_MAXMIN32)))
192
193#define	DEVEXPL(x)	\
194	(((x) == NODEV32) ? NODEV : \
195	makedevice(((x) >> L_BITSMINOR32) & L_MAXMAJ32, (x) & L_MAXMIN32))
196
197#endif /* L_BITSMAJOR32 ... */
198
199/* convert to old (SVR3.2) dev format */
200
201#define	cmpdev(x) \
202	(o_dev_t)((((x) >> L_BITSMINOR) > O_MAXMAJ || \
203	    ((x) & L_MAXMIN) > O_MAXMIN) ? NODEV : \
204	    ((((x) >> L_BITSMINOR) << O_BITSMINOR) | ((x) & O_MAXMIN)))
205
206/* convert to new (SVR4) dev format */
207
208#define	expdev(x) \
209	(dev_t)(((dev_t)(((x) >> O_BITSMINOR) & O_MAXMAJ) << L_BITSMINOR) | \
210	    ((x) & O_MAXMIN))
211
212/*
213 * Macro for checking power of 2 address alignment.
214 */
215#define	IS_P2ALIGNED(v, a) ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0)
216
217/*
218 * Macros for counting and rounding.
219 */
220#define	howmany(x, y)	(((x)+((y)-1))/(y))
221#define	roundup(x, y)	((((x)+((y)-1))/(y))*(y))
222
223/*
224 * Macro to determine if value is a power of 2
225 */
226#define	ISP2(x)		(((x) & ((x) - 1)) == 0)
227
228/*
229 * Macros for various sorts of alignment and rounding when the alignment
230 * is known to be a power of 2.
231 */
232#define	P2ALIGN(x, align)		((x) & -(align))
233#define	P2PHASE(x, align)		((x) & ((align) - 1))
234#define	P2NPHASE(x, align)		(-(x) & ((align) - 1))
235#define	P2ROUNDUP(x, align)		(-(-(x) & -(align)))
236#define	P2END(x, align)			(-(~(x) & -(align)))
237#define	P2PHASEUP(x, align, phase)	((phase) - (((phase) - (x)) & -(align)))
238#define	P2CROSS(x, y, align)		(((x) ^ (y)) > (align) - 1)
239/*
240 * Determine whether two numbers have the same high-order bit.
241 */
242#define	P2SAMEHIGHBIT(x, y)		(((x) ^ (y)) < ((x) & (y)))
243
244/*
245 * Typed version of the P2* macros.  These macros should be used to ensure
246 * that the result is correctly calculated based on the data type of (x),
247 * which is passed in as the last argument, regardless of the data
248 * type of the alignment.  For example, if (x) is of type uint64_t,
249 * and we want to round it up to a page boundary using "PAGESIZE" as
250 * the alignment, we can do either
251 *	P2ROUNDUP(x, (uint64_t)PAGESIZE)
252 * or
253 *	P2ROUNDUP_TYPED(x, PAGESIZE, uint64_t)
254 */
255#define	P2ALIGN_TYPED(x, align, type)	\
256	((type)(x) & -(type)(align))
257#define	P2PHASE_TYPED(x, align, type)	\
258	((type)(x) & ((type)(align) - 1))
259#define	P2NPHASE_TYPED(x, align, type)	\
260	(-(type)(x) & ((type)(align) - 1))
261#define	P2ROUNDUP_TYPED(x, align, type)	\
262	(-(-(type)(x) & -(type)(align)))
263#define	P2END_TYPED(x, align, type)	\
264	(-(~(type)(x) & -(type)(align)))
265#define	P2PHASEUP_TYPED(x, align, phase, type)	\
266	((type)(phase) - (((type)(phase) - (type)(x)) & -(type)(align)))
267#define	P2CROSS_TYPED(x, y, align, type)	\
268	(((type)(x) ^ (type)(y)) > (type)(align) - 1)
269#define	P2SAMEHIGHBIT_TYPED(x, y, type) \
270	(((type)(x) ^ (type)(y)) < ((type)(x) & (type)(y)))
271
272/*
273 * Macros to atomically increment/decrement a variable.  mutex and var
274 * must be pointers.
275 */
276#define	INCR_COUNT(var, mutex) mutex_enter(mutex), (*(var))++, mutex_exit(mutex)
277#define	DECR_COUNT(var, mutex) mutex_enter(mutex), (*(var))--, mutex_exit(mutex)
278
279#if defined(_KERNEL) && !defined(_KMEMUSER) && !defined(offsetof)
280
281/* avoid any possibility of clashing with <stddef.h> version */
282
283#define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
284#endif
285
286#ifdef	__cplusplus
287}
288#endif
289
290#endif	/* _SYS_SYSMACROS_H */
291