17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 562387023Sdduvall * Common Development and Distribution License (the "License"). 662387023Sdduvall * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2162387023Sdduvall 227c478bd9Sstevel@tonic-gate /* 2362387023Sdduvall * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 29f724721bSzh199473 #include "bge_impl.h" 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Atomically decrement a counter, but only if it will remain 337c478bd9Sstevel@tonic-gate * strictly positive (greater than zero) afterwards. We return 347c478bd9Sstevel@tonic-gate * the decremented value if so, otherwise zero (in which case 357c478bd9Sstevel@tonic-gate * the counter is unchanged). 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate * This is used for keeping track of available resources such 387c478bd9Sstevel@tonic-gate * as transmit ring slots ... 397c478bd9Sstevel@tonic-gate */ 407c478bd9Sstevel@tonic-gate uint64_t 417c478bd9Sstevel@tonic-gate bge_atomic_reserve(uint64_t *count_p, uint64_t n) 427c478bd9Sstevel@tonic-gate { 437c478bd9Sstevel@tonic-gate uint64_t oldval; 447c478bd9Sstevel@tonic-gate uint64_t newval; 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate /* ATOMICALLY */ 477c478bd9Sstevel@tonic-gate do { 487c478bd9Sstevel@tonic-gate oldval = *count_p; 497c478bd9Sstevel@tonic-gate newval = oldval - n; 507c478bd9Sstevel@tonic-gate if (oldval <= n) 517c478bd9Sstevel@tonic-gate return (0); /* no resources left */ 527c478bd9Sstevel@tonic-gate } while (cas64(count_p, oldval, newval) != oldval); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate return (newval); 557c478bd9Sstevel@tonic-gate } 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * Atomically increment a counter 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate void 617c478bd9Sstevel@tonic-gate bge_atomic_renounce(uint64_t *count_p, uint64_t n) 627c478bd9Sstevel@tonic-gate { 637c478bd9Sstevel@tonic-gate uint64_t oldval; 647c478bd9Sstevel@tonic-gate uint64_t newval; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* ATOMICALLY */ 677c478bd9Sstevel@tonic-gate do { 687c478bd9Sstevel@tonic-gate oldval = *count_p; 697c478bd9Sstevel@tonic-gate newval = oldval + n; 707c478bd9Sstevel@tonic-gate } while (cas64(count_p, oldval, newval) != oldval); 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * Atomically claim a slot in a descriptor ring 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate uint64_t 777c478bd9Sstevel@tonic-gate bge_atomic_claim(uint64_t *count_p, uint64_t limit) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate uint64_t oldval; 807c478bd9Sstevel@tonic-gate uint64_t newval; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* ATOMICALLY */ 837c478bd9Sstevel@tonic-gate do { 847c478bd9Sstevel@tonic-gate oldval = *count_p; 857c478bd9Sstevel@tonic-gate newval = NEXT(oldval, limit); 867c478bd9Sstevel@tonic-gate } while (cas64(count_p, oldval, newval) != oldval); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate return (oldval); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* 92*931dca7dSgs150176 * Atomically NEXT a 64-bit integer, returning the 93*931dca7dSgs150176 * value it had *before* the NEXT was applied 94*931dca7dSgs150176 */ 95*931dca7dSgs150176 uint64_t 96*931dca7dSgs150176 bge_atomic_next(uint64_t *sp, uint64_t limit) 97*931dca7dSgs150176 { 98*931dca7dSgs150176 uint64_t oldval; 99*931dca7dSgs150176 uint64_t newval; 100*931dca7dSgs150176 101*931dca7dSgs150176 /* ATOMICALLY */ 102*931dca7dSgs150176 do { 103*931dca7dSgs150176 oldval = *sp; 104*931dca7dSgs150176 newval = NEXT(oldval, limit); 105*931dca7dSgs150176 } while (cas64(sp, oldval, newval) != oldval); 106*931dca7dSgs150176 107*931dca7dSgs150176 return (oldval); 108*931dca7dSgs150176 } 109*931dca7dSgs150176 110*931dca7dSgs150176 /* 111*931dca7dSgs150176 * Atomically decrement a counter 112*931dca7dSgs150176 */ 113*931dca7dSgs150176 void 114*931dca7dSgs150176 bge_atomic_sub64(uint64_t *count_p, uint64_t n) 115*931dca7dSgs150176 { 116*931dca7dSgs150176 uint64_t oldval; 117*931dca7dSgs150176 uint64_t newval; 118*931dca7dSgs150176 119*931dca7dSgs150176 /* ATOMICALLY */ 120*931dca7dSgs150176 do { 121*931dca7dSgs150176 oldval = *count_p; 122*931dca7dSgs150176 newval = oldval - n; 123*931dca7dSgs150176 } while (cas64(count_p, oldval, newval) != oldval); 124*931dca7dSgs150176 } 125*931dca7dSgs150176 126*931dca7dSgs150176 /* 1277c478bd9Sstevel@tonic-gate * Atomically clear bits in a 64-bit word, returning 1287c478bd9Sstevel@tonic-gate * the value it had *before* the bits were cleared. 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate uint64_t 1317c478bd9Sstevel@tonic-gate bge_atomic_clr64(uint64_t *sp, uint64_t bits) 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate uint64_t oldval; 1347c478bd9Sstevel@tonic-gate uint64_t newval; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate /* ATOMICALLY */ 1377c478bd9Sstevel@tonic-gate do { 1387c478bd9Sstevel@tonic-gate oldval = *sp; 1397c478bd9Sstevel@tonic-gate newval = oldval & ~bits; 1407c478bd9Sstevel@tonic-gate } while (cas64(sp, oldval, newval) != oldval); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate return (oldval); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * Atomically shift a 32-bit word left, returning 1477c478bd9Sstevel@tonic-gate * the value it had *before* the shift was applied 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate uint32_t 1507c478bd9Sstevel@tonic-gate bge_atomic_shl32(uint32_t *sp, uint_t count) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate uint32_t oldval; 1537c478bd9Sstevel@tonic-gate uint32_t newval; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* ATOMICALLY */ 1567c478bd9Sstevel@tonic-gate do { 1577c478bd9Sstevel@tonic-gate oldval = *sp; 1587c478bd9Sstevel@tonic-gate newval = oldval << count; 1597c478bd9Sstevel@tonic-gate } while (cas32(sp, oldval, newval) != oldval); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate return (oldval); 1627c478bd9Sstevel@tonic-gate } 163