1/*- 2 * Copyright (c) 2009-2011, Juniper Networks, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30static void 31filemon_filemon_lock(struct filemon *filemon) 32{ 33 mtx_lock(&filemon->mtx); 34 35 while (filemon->locker != NULL && filemon->locker != curthread) 36 cv_wait(&filemon->cv, &filemon->mtx); 37 38 filemon->locker = curthread; 39 40 mtx_unlock(&filemon->mtx); 41} 42 43static void 44filemon_filemon_unlock(struct filemon *filemon) 45{ 46 mtx_lock(&filemon->mtx); 47 48 if (filemon->locker == curthread) 49 filemon->locker = NULL; 50 51 /* Wake up threads waiting. */ 52 cv_broadcast(&filemon->cv); 53 54 mtx_unlock(&filemon->mtx); 55} 56 57static void 58filemon_lock_read(void) 59{ 60 mtx_lock(&access_mtx); 61 62 while (access_owner != NULL || access_requester != NULL) 63 cv_wait(&access_cv, &access_mtx); 64 65 n_readers++; 66 67 /* Wake up threads waiting. */ 68 cv_broadcast(&access_cv); 69 70 mtx_unlock(&access_mtx); 71} 72 73static void 74filemon_unlock_read(void) 75{ 76 mtx_lock(&access_mtx); 77 78 if (n_readers > 0) 79 n_readers--; 80 81 /* Wake up a thread waiting. */ 82 cv_broadcast(&access_cv); 83 84 mtx_unlock(&access_mtx); 85} 86 87static void 88filemon_lock_write(void) 89{ 90 mtx_lock(&access_mtx); 91 92 while (access_owner != curthread) { 93 if (access_owner == NULL && 94 (access_requester == NULL || 95 access_requester == curthread)) { 96 access_owner = curthread; 97 access_requester = NULL; 98 } else { 99 if (access_requester == NULL) 100 access_requester = curthread; 101 102 cv_wait(&access_cv, &access_mtx); 103 } 104 } 105 106 mtx_unlock(&access_mtx); 107} 108 109static void 110filemon_unlock_write(void) 111{ 112 mtx_lock(&access_mtx); 113 114 /* Sanity check that the current thread actually has the write lock. */ 115 if (access_owner == curthread) 116 access_owner = NULL; 117 118 /* Wake up a thread waiting. */ 119 cv_broadcast(&access_cv); 120 121 mtx_unlock(&access_mtx); 122} 123