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