xref: /onnv-gate/usr/src/uts/common/io/nge/nge_atomic.c (revision 5578:c0773208044e)
1*5578Smx205022 /*
2*5578Smx205022  * CDDL HEADER START
3*5578Smx205022  *
4*5578Smx205022  * The contents of this file are subject to the terms of the
5*5578Smx205022  * Common Development and Distribution License (the "License").
6*5578Smx205022  * You may not use this file except in compliance with the License.
7*5578Smx205022  *
8*5578Smx205022  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5578Smx205022  * or http://www.opensolaris.org/os/licensing.
10*5578Smx205022  * See the License for the specific language governing permissions
11*5578Smx205022  * and limitations under the License.
12*5578Smx205022  *
13*5578Smx205022  * When distributing Covered Code, include this CDDL HEADER in each
14*5578Smx205022  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5578Smx205022  * If applicable, add the following below this CDDL HEADER, with the
16*5578Smx205022  * fields enclosed by brackets "[]" replaced with your own identifying
17*5578Smx205022  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5578Smx205022  *
19*5578Smx205022  * CDDL HEADER END
20*5578Smx205022  */
21*5578Smx205022 
225574Smx205022 /*
235574Smx205022  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
245574Smx205022  * Use is subject to license terms.
255574Smx205022  */
265574Smx205022 
275574Smx205022 #pragma ident	"%Z%%M%	%I%	%E% SMI"
285574Smx205022 
295574Smx205022 #include "nge.h"
305574Smx205022 
315574Smx205022 /*
325574Smx205022  * Atomically decrement a counter, but only if it will remain
335574Smx205022  * positive (>=0) afterwards.
345574Smx205022  */
355574Smx205022 boolean_t
nge_atomic_decrease(uint64_t * count_p,uint64_t n)365574Smx205022 nge_atomic_decrease(uint64_t *count_p, uint64_t n)
375574Smx205022 {
385574Smx205022 	uint64_t oldval;
395574Smx205022 	uint64_t newval;
405574Smx205022 
415574Smx205022 	/* ATOMICALLY */
425574Smx205022 	do {
435574Smx205022 		oldval = *count_p;
445574Smx205022 		newval = oldval - n;
455574Smx205022 		if (oldval < n)
465574Smx205022 			return (B_FALSE);
475574Smx205022 	} while (cas64(count_p, oldval, newval) != oldval);
485574Smx205022 
495574Smx205022 	return (B_TRUE);
505574Smx205022 }
515574Smx205022 
525574Smx205022 /*
535574Smx205022  * Atomically increment a counter
545574Smx205022  */
555574Smx205022 void
nge_atomic_increase(uint64_t * count_p,uint64_t n)565574Smx205022 nge_atomic_increase(uint64_t *count_p, uint64_t n)
575574Smx205022 {
585574Smx205022 	uint64_t oldval;
595574Smx205022 	uint64_t newval;
605574Smx205022 
615574Smx205022 	/* ATOMICALLY */
625574Smx205022 	do {
635574Smx205022 		oldval = *count_p;
645574Smx205022 		newval = oldval + n;
655574Smx205022 	} while (cas64(count_p, oldval, newval) != oldval);
665574Smx205022 }
675574Smx205022 
685574Smx205022 
695574Smx205022 /*
705574Smx205022  * Atomically shift a 32-bit word left, returning
715574Smx205022  * the value it had *before* the shift was applied
725574Smx205022  */
735574Smx205022 uint32_t
nge_atomic_shl32(uint32_t * sp,uint_t count)745574Smx205022 nge_atomic_shl32(uint32_t *sp, uint_t count)
755574Smx205022 {
765574Smx205022 	uint32_t oldval;
775574Smx205022 	uint32_t newval;
785574Smx205022 
795574Smx205022 	/* ATOMICALLY */
805574Smx205022 	do {
815574Smx205022 		oldval = *sp;
825574Smx205022 		newval = oldval << count;
835574Smx205022 	} while (cas32(sp, oldval, newval) != oldval);
845574Smx205022 
855574Smx205022 	return (oldval);
865574Smx205022 }
87