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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "bge_impl.h" 30 31 /* 32 * Atomically decrement a counter, but only if it will remain 33 * strictly positive (greater than zero) afterwards. We return 34 * the decremented value if so, otherwise zero (in which case 35 * the counter is unchanged). 36 * 37 * This is used for keeping track of available resources such 38 * as transmit ring slots ... 39 */ 40 uint64_t 41 bge_atomic_reserve(uint64_t *count_p, uint64_t n) 42 { 43 uint64_t oldval; 44 uint64_t newval; 45 46 /* ATOMICALLY */ 47 do { 48 oldval = *count_p; 49 newval = oldval - n; 50 if (oldval <= n) 51 return (0); /* no resources left */ 52 } while (cas64(count_p, oldval, newval) != oldval); 53 54 return (newval); 55 } 56 57 /* 58 * Atomically increment a counter 59 */ 60 void 61 bge_atomic_renounce(uint64_t *count_p, uint64_t n) 62 { 63 uint64_t oldval; 64 uint64_t newval; 65 66 /* ATOMICALLY */ 67 do { 68 oldval = *count_p; 69 newval = oldval + n; 70 } while (cas64(count_p, oldval, newval) != oldval); 71 } 72 73 /* 74 * Atomically claim a slot in a descriptor ring 75 */ 76 uint64_t 77 bge_atomic_claim(uint64_t *count_p, uint64_t limit) 78 { 79 uint64_t oldval; 80 uint64_t newval; 81 82 /* ATOMICALLY */ 83 do { 84 oldval = *count_p; 85 newval = NEXT(oldval, limit); 86 } while (cas64(count_p, oldval, newval) != oldval); 87 88 return (oldval); 89 } 90 91 /* 92 * Atomically NEXT a 64-bit integer, returning the 93 * value it had *before* the NEXT was applied 94 */ 95 uint64_t 96 bge_atomic_next(uint64_t *sp, uint64_t limit) 97 { 98 uint64_t oldval; 99 uint64_t newval; 100 101 /* ATOMICALLY */ 102 do { 103 oldval = *sp; 104 newval = NEXT(oldval, limit); 105 } while (cas64(sp, oldval, newval) != oldval); 106 107 return (oldval); 108 } 109 110 /* 111 * Atomically decrement a counter 112 */ 113 void 114 bge_atomic_sub64(uint64_t *count_p, uint64_t n) 115 { 116 uint64_t oldval; 117 uint64_t newval; 118 119 /* ATOMICALLY */ 120 do { 121 oldval = *count_p; 122 newval = oldval - n; 123 } while (cas64(count_p, oldval, newval) != oldval); 124 } 125 126 /* 127 * Atomically clear bits in a 64-bit word, returning 128 * the value it had *before* the bits were cleared. 129 */ 130 uint64_t 131 bge_atomic_clr64(uint64_t *sp, uint64_t bits) 132 { 133 uint64_t oldval; 134 uint64_t newval; 135 136 /* ATOMICALLY */ 137 do { 138 oldval = *sp; 139 newval = oldval & ~bits; 140 } while (cas64(sp, oldval, newval) != oldval); 141 142 return (oldval); 143 } 144 145 /* 146 * Atomically shift a 32-bit word left, returning 147 * the value it had *before* the shift was applied 148 */ 149 uint32_t 150 bge_atomic_shl32(uint32_t *sp, uint_t count) 151 { 152 uint32_t oldval; 153 uint32_t newval; 154 155 /* ATOMICALLY */ 156 do { 157 oldval = *sp; 158 newval = oldval << count; 159 } while (cas32(sp, oldval, newval) != oldval); 160 161 return (oldval); 162 } 163