cvmx-rwlock.h revision 210284
1/***********************license start*************** 2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * * Neither the name of Cavium Networks nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 * 23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 33 * 34 * 35 * For any questions regarding licensing please contact marketing@caviumnetworks.com 36 * 37 ***********************license end**************************************/ 38 39 40 41 42 43 44/** 45 * @file 46 * 47 * This file provides reader/writer locks. 48 * 49 * <hr>$Revision: 41586 $<hr> 50 * 51 * 52 */ 53 54 55#ifndef __CVMX_RWLOCK_H__ 56#define __CVMX_RWLOCK_H__ 57 58/* include to get atomic compare and store */ 59#include "cvmx-atomic.h" 60 61#ifdef __cplusplus 62extern "C" { 63#endif 64 65/* Flags for lock value in rw lock structure */ 66#define CVMX_RWLOCK_WRITE_FLAG 0x1 67#define CVMX_RWLOCK_READ_INC 0x2 68 69 70/* Writer preference locks (wp). Can be starved by writers. When a writer 71 * is waiting, no readers are given the lock until all writers are done. 72 */ 73typedef struct 74{ 75 volatile uint32_t lock; 76 volatile uint32_t write_req; 77 volatile uint32_t write_comp; 78} cvmx_rwlock_wp_lock_t; 79 80/** 81 * Initialize a reader/writer lock. This must be done 82 * by a single core before used. 83 * 84 * @param lock pointer to rwlock structure 85 */ 86static inline void cvmx_rwlock_wp_init(cvmx_rwlock_wp_lock_t *lock) 87{ 88 lock->lock = 0; 89 lock->write_req = 0; 90 lock->write_comp = 0; 91} 92 93/** 94 * Perform a reader lock. If a writer is pending, this 95 * will wait for that writer to complete before locking. 96 * 97 * NOTE: Each thread/process must only lock any rwlock 98 * once, or else a deadlock may result. 99 * 100 * @param lock pointer to rwlock structure 101 */ 102static inline void cvmx_rwlock_wp_read_lock(cvmx_rwlock_wp_lock_t *lock) 103{ 104 105 /* Wait for outstanding write requests to be serviced */ 106 while (lock->write_req != lock->write_comp) 107 ; 108 /* Add ourselves to interested reader count */ 109 cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), CVMX_RWLOCK_READ_INC); 110 /* Wait for writer to finish. No writer will start again 111 ** until after we are done since we have already incremented 112 ** the reader count 113 */ 114 while (lock->lock & CVMX_RWLOCK_WRITE_FLAG) 115 ; 116 117} 118 119/** 120 * Perform a reader unlock. 121 * 122 * @param lock pointer to rwlock structure 123 */ 124static inline void cvmx_rwlock_wp_read_unlock(cvmx_rwlock_wp_lock_t *lock) 125{ 126 /* Remove ourselves to reader count */ 127 cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), -CVMX_RWLOCK_READ_INC); 128} 129 130/** 131 * Perform a writer lock. Any readers that attempt 132 * to get a lock while there are any pending write locks 133 * will wait until all writers have completed. Starvation 134 * of readers by writers is possible and must be avoided 135 * by the application. 136 * 137 * @param lock pointer to rwlock structure 138 */ 139static inline void cvmx_rwlock_wp_write_lock(cvmx_rwlock_wp_lock_t *lock) 140{ 141 /* Get previous value of write requests */ 142 uint32_t prev_writers = ((uint32_t)cvmx_atomic_fetch_and_add32((int32_t *)&(lock->write_req), 1)); 143 /* Spin until our turn */ 144 while (prev_writers != lock->write_comp) 145 ; 146 /* Spin until no other readers or writers, then set write flag */ 147 while (!cvmx_atomic_compare_and_store32((uint32_t *)&(lock->lock), 0, CVMX_RWLOCK_WRITE_FLAG)) 148 ; 149 150} 151/** 152 * Perform a writer unlock. 153 * 154 * @param lock pointer to rwlock structure 155 */ 156static inline void cvmx_rwlock_wp_write_unlock(cvmx_rwlock_wp_lock_t *lock) 157{ 158 /* Remove our writer flag */ 159 CVMX_SYNCWS; /* Make sure all writes in protected region are visible before unlock */ 160 cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), -CVMX_RWLOCK_WRITE_FLAG); 161 cvmx_atomic_add32_nosync((int32_t *)&(lock->write_comp), 1); 162 CVMX_SYNCWS; /* push unlock writes out, but don't stall */ 163} 164 165#ifdef __cplusplus 166} 167#endif 168 169#endif /* __CVMX_RWLOCK_H__ */ 170