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 }