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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include "nge.h" 28 29 /* 30 * Atomically decrement a counter, but only if it will remain 31 * positive (>=0) afterwards. 32 */ 33 boolean_t 34 nge_atomic_decrease(uint64_t *count_p, uint64_t n) 35 { 36 uint64_t oldval; 37 uint64_t newval; 38 39 /* ATOMICALLY */ 40 do { 41 oldval = *count_p; 42 newval = oldval - n; 43 if (oldval < n) 44 return (B_FALSE); 45 } while (atomic_cas_64(count_p, oldval, newval) != oldval); 46 47 return (B_TRUE); 48 } 49 50 /* 51 * Atomically increment a counter 52 */ 53 void 54 nge_atomic_increase(uint64_t *count_p, uint64_t n) 55 { 56 uint64_t oldval; 57 uint64_t newval; 58 59 /* ATOMICALLY */ 60 do { 61 oldval = *count_p; 62 newval = oldval + n; 63 } while (atomic_cas_64(count_p, oldval, newval) != oldval); 64 } 65 66 67 /* 68 * Atomically shift a 32-bit word left, returning 69 * the value it had *before* the shift was applied 70 */ 71 uint32_t 72 nge_atomic_shl32(uint32_t *sp, uint_t count) 73 { 74 uint32_t oldval; 75 uint32_t newval; 76 77 /* ATOMICALLY */ 78 do { 79 oldval = *sp; 80 newval = oldval << count; 81 } while (atomic_cas_32(sp, oldval, newval) != oldval); 82 83 return (oldval); 84 } 85