1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 /* 28 * A few excerpts from smb_kutil.c 29 */ 30 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/atomic.h> 34 #include <sys/debug.h> 35 #include <sys/time.h> 36 #include <sys/stddef.h> 37 #include <smbsrv/smb_kproto.h> 38 39 40 /* 41 * smb_llist_constructor 42 * 43 * This function initializes a locked list. 44 */ 45 void 46 smb_llist_constructor( 47 smb_llist_t *ll, 48 size_t size, 49 size_t offset) 50 { 51 rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL); 52 mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL); 53 list_create(&ll->ll_list, size, offset); 54 list_create(&ll->ll_deleteq, sizeof (smb_dtor_t), 55 offsetof(smb_dtor_t, dt_lnd)); 56 ll->ll_count = 0; 57 ll->ll_wrop = 0; 58 ll->ll_deleteq_count = 0; 59 ll->ll_flushing = B_FALSE; 60 } 61 62 /* 63 * Flush the delete queue and destroy a locked list. 64 */ 65 void 66 smb_llist_destructor( 67 smb_llist_t *ll) 68 { 69 /* smb_llist_flush(ll); */ 70 71 ASSERT(ll->ll_count == 0); 72 ASSERT(ll->ll_deleteq_count == 0); 73 74 rw_destroy(&ll->ll_lock); 75 list_destroy(&ll->ll_list); 76 list_destroy(&ll->ll_deleteq); 77 mutex_destroy(&ll->ll_mutex); 78 } 79 80 void 81 smb_llist_enter(smb_llist_t *ll, krw_t mode) 82 { 83 rw_enter(&ll->ll_lock, mode); 84 } 85 86 /* 87 * Exit the list lock and process the delete queue. 88 */ 89 void 90 smb_llist_exit(smb_llist_t *ll) 91 { 92 rw_exit(&ll->ll_lock); 93 /* smb_llist_flush(ll); */ 94 } 95 96 /* 97 * smb_llist_upgrade 98 * 99 * This function tries to upgrade the lock of the locked list. It assumes the 100 * locked has already been entered in RW_READER mode. It first tries using the 101 * Solaris function rw_tryupgrade(). If that call fails the lock is released 102 * and reentered in RW_WRITER mode. In that last case a window is opened during 103 * which the contents of the list may have changed. The return code indicates 104 * whether or not the list was modified when the lock was exited. 105 */ 106 int smb_llist_upgrade( 107 smb_llist_t *ll) 108 { 109 uint64_t wrop; 110 111 if (rw_tryupgrade(&ll->ll_lock) != 0) { 112 return (0); 113 } 114 wrop = ll->ll_wrop; 115 rw_exit(&ll->ll_lock); 116 rw_enter(&ll->ll_lock, RW_WRITER); 117 return (wrop != ll->ll_wrop); 118 } 119 120 /* 121 * smb_llist_insert_head 122 * 123 * This function inserts the object passed a the beginning of the list. This 124 * function assumes the lock of the list has already been entered. 125 */ 126 void 127 smb_llist_insert_head( 128 smb_llist_t *ll, 129 void *obj) 130 { 131 list_insert_head(&ll->ll_list, obj); 132 ++ll->ll_wrop; 133 ++ll->ll_count; 134 } 135 136 /* 137 * smb_llist_insert_tail 138 * 139 * This function appends to the object passed to the list. This function assumes 140 * the lock of the list has already been entered. 141 * 142 */ 143 void 144 smb_llist_insert_tail( 145 smb_llist_t *ll, 146 void *obj) 147 { 148 list_insert_tail(&ll->ll_list, obj); 149 ++ll->ll_wrop; 150 ++ll->ll_count; 151 } 152 153 /* 154 * smb_llist_remove 155 * 156 * This function removes the object passed from the list. This function assumes 157 * the lock of the list has already been entered. 158 */ 159 void 160 smb_llist_remove( 161 smb_llist_t *ll, 162 void *obj) 163 { 164 list_remove(&ll->ll_list, obj); 165 ++ll->ll_wrop; 166 --ll->ll_count; 167 } 168 169 /* 170 * smb_llist_get_count 171 * 172 * This function returns the number of elements in the specified list. 173 */ 174 uint32_t 175 smb_llist_get_count( 176 smb_llist_t *ll) 177 { 178 return (ll->ll_count); 179 } 180