1236592Sobrien/*- 2236592Sobrien * Copyright (c) 2009-2011, Juniper Networks, Inc. 3236592Sobrien * All rights reserved. 4236592Sobrien * 5236592Sobrien * Redistribution and use in source and binary forms, with or without 6236592Sobrien * modification, are permitted provided that the following conditions 7236592Sobrien * are met: 8236592Sobrien * 1. Redistributions of source code must retain the above copyright 9236592Sobrien * notice, this list of conditions and the following disclaimer. 10236592Sobrien * 2. Redistributions in binary form must reproduce the above copyright 11236592Sobrien * notice, this list of conditions and the following disclaimer in the 12236592Sobrien * documentation and/or other materials provided with the distribution. 13236592Sobrien * 14236592Sobrien * THIS SOFTWARE IS PROVIDED BY JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND 15236592Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16236592Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17236592Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE 18236592Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19236592Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20236592Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21236592Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22236592Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23236592Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24236592Sobrien * SUCH DAMAGE. 25236592Sobrien */ 26236592Sobrien 27236592Sobrien#include <sys/cdefs.h> 28236592Sobrien__FBSDID("$FreeBSD$"); 29236592Sobrien 30236592Sobrienstatic void 31236592Sobrienfilemon_filemon_lock(struct filemon *filemon) 32236592Sobrien{ 33236592Sobrien mtx_lock(&filemon->mtx); 34236592Sobrien 35236592Sobrien while (filemon->locker != NULL && filemon->locker != curthread) 36236592Sobrien cv_wait(&filemon->cv, &filemon->mtx); 37236592Sobrien 38236592Sobrien filemon->locker = curthread; 39236592Sobrien 40236592Sobrien mtx_unlock(&filemon->mtx); 41236592Sobrien} 42236592Sobrien 43236592Sobrienstatic void 44236592Sobrienfilemon_filemon_unlock(struct filemon *filemon) 45236592Sobrien{ 46236592Sobrien mtx_lock(&filemon->mtx); 47236592Sobrien 48236592Sobrien if (filemon->locker == curthread) 49236592Sobrien filemon->locker = NULL; 50236592Sobrien 51236592Sobrien /* Wake up threads waiting. */ 52236592Sobrien cv_broadcast(&filemon->cv); 53236592Sobrien 54236592Sobrien mtx_unlock(&filemon->mtx); 55236592Sobrien} 56236592Sobrien 57236592Sobrienstatic void 58236592Sobrienfilemon_lock_read(void) 59236592Sobrien{ 60236592Sobrien mtx_lock(&access_mtx); 61236592Sobrien 62236592Sobrien while (access_owner != NULL || access_requester != NULL) 63236592Sobrien cv_wait(&access_cv, &access_mtx); 64236592Sobrien 65236592Sobrien n_readers++; 66236592Sobrien 67236592Sobrien /* Wake up threads waiting. */ 68236592Sobrien cv_broadcast(&access_cv); 69236592Sobrien 70236592Sobrien mtx_unlock(&access_mtx); 71236592Sobrien} 72236592Sobrien 73236592Sobrienstatic void 74236592Sobrienfilemon_unlock_read(void) 75236592Sobrien{ 76236592Sobrien mtx_lock(&access_mtx); 77236592Sobrien 78236592Sobrien if (n_readers > 0) 79236592Sobrien n_readers--; 80236592Sobrien 81236592Sobrien /* Wake up a thread waiting. */ 82236592Sobrien cv_broadcast(&access_cv); 83236592Sobrien 84236592Sobrien mtx_unlock(&access_mtx); 85236592Sobrien} 86236592Sobrien 87236592Sobrienstatic void 88236592Sobrienfilemon_lock_write(void) 89236592Sobrien{ 90236592Sobrien mtx_lock(&access_mtx); 91236592Sobrien 92236592Sobrien while (access_owner != curthread) { 93236592Sobrien if (access_owner == NULL && 94236592Sobrien (access_requester == NULL || 95236592Sobrien access_requester == curthread)) { 96236592Sobrien access_owner = curthread; 97236592Sobrien access_requester = NULL; 98236592Sobrien } else { 99236592Sobrien if (access_requester == NULL) 100236592Sobrien access_requester = curthread; 101236592Sobrien 102236592Sobrien cv_wait(&access_cv, &access_mtx); 103236592Sobrien } 104236592Sobrien } 105236592Sobrien 106236592Sobrien mtx_unlock(&access_mtx); 107236592Sobrien} 108236592Sobrien 109236592Sobrienstatic void 110236592Sobrienfilemon_unlock_write(void) 111236592Sobrien{ 112236592Sobrien mtx_lock(&access_mtx); 113236592Sobrien 114236592Sobrien /* Sanity check that the current thread actually has the write lock. */ 115236592Sobrien if (access_owner == curthread) 116236592Sobrien access_owner = NULL; 117236592Sobrien 118236592Sobrien /* Wake up a thread waiting. */ 119236592Sobrien cv_broadcast(&access_cv); 120236592Sobrien 121236592Sobrien mtx_unlock(&access_mtx); 122236592Sobrien} 123