xref: /onnv-gate/usr/src/uts/common/io/bge/bge_atomic.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include "sys/bge_impl.h"
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate /*
32*0Sstevel@tonic-gate  * Atomically decrement a counter, but only if it will remain
33*0Sstevel@tonic-gate  * strictly positive (greater than zero) afterwards.  We return
34*0Sstevel@tonic-gate  * the decremented value if so, otherwise zero (in which case
35*0Sstevel@tonic-gate  * the counter is unchanged).
36*0Sstevel@tonic-gate  *
37*0Sstevel@tonic-gate  * This is used for keeping track of available resources such
38*0Sstevel@tonic-gate  * as transmit ring slots ...
39*0Sstevel@tonic-gate  */
40*0Sstevel@tonic-gate uint64_t
41*0Sstevel@tonic-gate bge_atomic_reserve(uint64_t *count_p, uint64_t n)
42*0Sstevel@tonic-gate {
43*0Sstevel@tonic-gate 	uint64_t oldval;
44*0Sstevel@tonic-gate 	uint64_t newval;
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate 	/* ATOMICALLY */
47*0Sstevel@tonic-gate 	do {
48*0Sstevel@tonic-gate 		oldval = *count_p;
49*0Sstevel@tonic-gate 		newval = oldval - n;
50*0Sstevel@tonic-gate 		if (oldval <= n)
51*0Sstevel@tonic-gate 			return (0);		/* no resources left	*/
52*0Sstevel@tonic-gate 	} while (cas64(count_p, oldval, newval) != oldval);
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate 	return (newval);
55*0Sstevel@tonic-gate }
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate /*
58*0Sstevel@tonic-gate  * Atomically increment a counter
59*0Sstevel@tonic-gate  */
60*0Sstevel@tonic-gate void
61*0Sstevel@tonic-gate bge_atomic_renounce(uint64_t *count_p, uint64_t n)
62*0Sstevel@tonic-gate {
63*0Sstevel@tonic-gate 	uint64_t oldval;
64*0Sstevel@tonic-gate 	uint64_t newval;
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate 	/* ATOMICALLY */
67*0Sstevel@tonic-gate 	do {
68*0Sstevel@tonic-gate 		oldval = *count_p;
69*0Sstevel@tonic-gate 		newval = oldval + n;
70*0Sstevel@tonic-gate 	} while (cas64(count_p, oldval, newval) != oldval);
71*0Sstevel@tonic-gate }
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate /*
74*0Sstevel@tonic-gate  * Atomically claim a slot in a descriptor ring
75*0Sstevel@tonic-gate  */
76*0Sstevel@tonic-gate uint64_t
77*0Sstevel@tonic-gate bge_atomic_claim(uint64_t *count_p, uint64_t limit)
78*0Sstevel@tonic-gate {
79*0Sstevel@tonic-gate 	uint64_t oldval;
80*0Sstevel@tonic-gate 	uint64_t newval;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	/* ATOMICALLY */
83*0Sstevel@tonic-gate 	do {
84*0Sstevel@tonic-gate 		oldval = *count_p;
85*0Sstevel@tonic-gate 		newval = NEXT(oldval, limit);
86*0Sstevel@tonic-gate 	} while (cas64(count_p, oldval, newval) != oldval);
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 	return (oldval);
89*0Sstevel@tonic-gate }
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate /*
92*0Sstevel@tonic-gate  * Atomically clear bits in a 64-bit word, returning
93*0Sstevel@tonic-gate  * the value it had *before* the bits were cleared.
94*0Sstevel@tonic-gate  */
95*0Sstevel@tonic-gate uint64_t
96*0Sstevel@tonic-gate bge_atomic_clr64(uint64_t *sp, uint64_t bits)
97*0Sstevel@tonic-gate {
98*0Sstevel@tonic-gate 	uint64_t oldval;
99*0Sstevel@tonic-gate 	uint64_t newval;
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 	/* ATOMICALLY */
102*0Sstevel@tonic-gate 	do {
103*0Sstevel@tonic-gate 		oldval = *sp;
104*0Sstevel@tonic-gate 		newval = oldval & ~bits;
105*0Sstevel@tonic-gate 	} while (cas64(sp, oldval, newval) != oldval);
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	return (oldval);
108*0Sstevel@tonic-gate }
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate /*
111*0Sstevel@tonic-gate  * Atomically shift a 32-bit word left, returning
112*0Sstevel@tonic-gate  * the value it had *before* the shift was applied
113*0Sstevel@tonic-gate  */
114*0Sstevel@tonic-gate uint32_t
115*0Sstevel@tonic-gate bge_atomic_shl32(uint32_t *sp, uint_t count)
116*0Sstevel@tonic-gate {
117*0Sstevel@tonic-gate 	uint32_t oldval;
118*0Sstevel@tonic-gate 	uint32_t newval;
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 	/* ATOMICALLY */
121*0Sstevel@tonic-gate 	do {
122*0Sstevel@tonic-gate 		oldval = *sp;
123*0Sstevel@tonic-gate 		newval = oldval << count;
124*0Sstevel@tonic-gate 	} while (cas32(sp, oldval, newval) != oldval);
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	return (oldval);
127*0Sstevel@tonic-gate }
128