1210284Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett/** 47210284Sjmallett * @file 48210284Sjmallett * 49210284Sjmallett * This file provides reader/writer locks. 50210284Sjmallett * 51232812Sjmallett * <hr>$Revision: 70030 $<hr> 52210284Sjmallett * 53210284Sjmallett * 54210284Sjmallett */ 55210284Sjmallett 56210284Sjmallett 57210284Sjmallett#ifndef __CVMX_RWLOCK_H__ 58210284Sjmallett#define __CVMX_RWLOCK_H__ 59210284Sjmallett 60210284Sjmallett/* include to get atomic compare and store */ 61210284Sjmallett#include "cvmx-atomic.h" 62210284Sjmallett 63210284Sjmallett#ifdef __cplusplus 64210284Sjmallettextern "C" { 65210284Sjmallett#endif 66210284Sjmallett 67210284Sjmallett/* Flags for lock value in rw lock structure */ 68210284Sjmallett#define CVMX_RWLOCK_WRITE_FLAG 0x1 69210284Sjmallett#define CVMX_RWLOCK_READ_INC 0x2 70210284Sjmallett 71210284Sjmallett 72210284Sjmallett/* Writer preference locks (wp). Can be starved by writers. When a writer 73210284Sjmallett * is waiting, no readers are given the lock until all writers are done. 74210284Sjmallett */ 75210284Sjmalletttypedef struct 76210284Sjmallett{ 77210284Sjmallett volatile uint32_t lock; 78210284Sjmallett volatile uint32_t write_req; 79210284Sjmallett volatile uint32_t write_comp; 80210284Sjmallett} cvmx_rwlock_wp_lock_t; 81210284Sjmallett 82210284Sjmallett/** 83210284Sjmallett * Initialize a reader/writer lock. This must be done 84210284Sjmallett * by a single core before used. 85210284Sjmallett * 86210284Sjmallett * @param lock pointer to rwlock structure 87210284Sjmallett */ 88210284Sjmallettstatic inline void cvmx_rwlock_wp_init(cvmx_rwlock_wp_lock_t *lock) 89210284Sjmallett{ 90210284Sjmallett lock->lock = 0; 91210284Sjmallett lock->write_req = 0; 92210284Sjmallett lock->write_comp = 0; 93210284Sjmallett} 94210284Sjmallett 95210284Sjmallett/** 96210284Sjmallett * Perform a reader lock. If a writer is pending, this 97210284Sjmallett * will wait for that writer to complete before locking. 98210284Sjmallett * 99210284Sjmallett * NOTE: Each thread/process must only lock any rwlock 100210284Sjmallett * once, or else a deadlock may result. 101210284Sjmallett * 102210284Sjmallett * @param lock pointer to rwlock structure 103210284Sjmallett */ 104210284Sjmallettstatic inline void cvmx_rwlock_wp_read_lock(cvmx_rwlock_wp_lock_t *lock) 105210284Sjmallett{ 106210284Sjmallett 107210284Sjmallett /* Wait for outstanding write requests to be serviced */ 108210284Sjmallett while (lock->write_req != lock->write_comp) 109210284Sjmallett ; 110210284Sjmallett /* Add ourselves to interested reader count */ 111210284Sjmallett cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), CVMX_RWLOCK_READ_INC); 112210284Sjmallett /* Wait for writer to finish. No writer will start again 113210284Sjmallett ** until after we are done since we have already incremented 114210284Sjmallett ** the reader count 115210284Sjmallett */ 116210284Sjmallett while (lock->lock & CVMX_RWLOCK_WRITE_FLAG) 117210284Sjmallett ; 118210284Sjmallett 119210284Sjmallett} 120210284Sjmallett 121210284Sjmallett/** 122210284Sjmallett * Perform a reader unlock. 123210284Sjmallett * 124210284Sjmallett * @param lock pointer to rwlock structure 125210284Sjmallett */ 126210284Sjmallettstatic inline void cvmx_rwlock_wp_read_unlock(cvmx_rwlock_wp_lock_t *lock) 127210284Sjmallett{ 128210284Sjmallett /* Remove ourselves to reader count */ 129210284Sjmallett cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), -CVMX_RWLOCK_READ_INC); 130210284Sjmallett} 131210284Sjmallett 132210284Sjmallett/** 133210284Sjmallett * Perform a writer lock. Any readers that attempt 134210284Sjmallett * to get a lock while there are any pending write locks 135210284Sjmallett * will wait until all writers have completed. Starvation 136210284Sjmallett * of readers by writers is possible and must be avoided 137210284Sjmallett * by the application. 138210284Sjmallett * 139210284Sjmallett * @param lock pointer to rwlock structure 140210284Sjmallett */ 141210284Sjmallettstatic inline void cvmx_rwlock_wp_write_lock(cvmx_rwlock_wp_lock_t *lock) 142210284Sjmallett{ 143210284Sjmallett /* Get previous value of write requests */ 144210284Sjmallett uint32_t prev_writers = ((uint32_t)cvmx_atomic_fetch_and_add32((int32_t *)&(lock->write_req), 1)); 145210284Sjmallett /* Spin until our turn */ 146210284Sjmallett while (prev_writers != lock->write_comp) 147210284Sjmallett ; 148210284Sjmallett /* Spin until no other readers or writers, then set write flag */ 149210284Sjmallett while (!cvmx_atomic_compare_and_store32((uint32_t *)&(lock->lock), 0, CVMX_RWLOCK_WRITE_FLAG)) 150210284Sjmallett ; 151210284Sjmallett 152210284Sjmallett} 153210284Sjmallett/** 154210284Sjmallett * Perform a writer unlock. 155210284Sjmallett * 156210284Sjmallett * @param lock pointer to rwlock structure 157210284Sjmallett */ 158210284Sjmallettstatic inline void cvmx_rwlock_wp_write_unlock(cvmx_rwlock_wp_lock_t *lock) 159210284Sjmallett{ 160210284Sjmallett /* Remove our writer flag */ 161210284Sjmallett CVMX_SYNCWS; /* Make sure all writes in protected region are visible before unlock */ 162210284Sjmallett cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), -CVMX_RWLOCK_WRITE_FLAG); 163210284Sjmallett cvmx_atomic_add32_nosync((int32_t *)&(lock->write_comp), 1); 164210284Sjmallett CVMX_SYNCWS; /* push unlock writes out, but don't stall */ 165210284Sjmallett} 166210284Sjmallett 167210284Sjmallett#ifdef __cplusplus 168210284Sjmallett} 169210284Sjmallett#endif 170210284Sjmallett 171210284Sjmallett#endif /* __CVMX_RWLOCK_H__ */ 172