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 "sys/bge_impl2.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 clear bits in a 64-bit word, returning 93 * the value it had *before* the bits were cleared. 94 */ 95 uint64_t 96 bge_atomic_clr64(uint64_t *sp, uint64_t bits) 97 { 98 uint64_t oldval; 99 uint64_t newval; 100 101 /* ATOMICALLY */ 102 do { 103 oldval = *sp; 104 newval = oldval & ~bits; 105 } while (cas64(sp, oldval, newval) != oldval); 106 107 return (oldval); 108 } 109 110 /* 111 * Atomically shift a 32-bit word left, returning 112 * the value it had *before* the shift was applied 113 */ 114 uint32_t 115 bge_atomic_shl32(uint32_t *sp, uint_t count) 116 { 117 uint32_t oldval; 118 uint32_t newval; 119 120 /* ATOMICALLY */ 121 do { 122 oldval = *sp; 123 newval = oldval << count; 124 } while (cas32(sp, oldval, newval) != oldval); 125 126 return (oldval); 127 } 128