/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* * A few excerpts from smb_kutil.c */ #include #include #include #include #include #include #include /* * smb_llist_constructor * * This function initializes a locked list. */ void smb_llist_constructor( smb_llist_t *ll, size_t size, size_t offset) { rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL); mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL); list_create(&ll->ll_list, size, offset); list_create(&ll->ll_deleteq, sizeof (smb_dtor_t), offsetof(smb_dtor_t, dt_lnd)); ll->ll_count = 0; ll->ll_wrop = 0; ll->ll_deleteq_count = 0; ll->ll_flushing = B_FALSE; } /* * Flush the delete queue and destroy a locked list. */ void smb_llist_destructor( smb_llist_t *ll) { /* smb_llist_flush(ll); */ ASSERT(ll->ll_count == 0); ASSERT(ll->ll_deleteq_count == 0); rw_destroy(&ll->ll_lock); list_destroy(&ll->ll_list); list_destroy(&ll->ll_deleteq); mutex_destroy(&ll->ll_mutex); } void smb_llist_enter(smb_llist_t *ll, krw_t mode) { rw_enter(&ll->ll_lock, mode); } /* * Exit the list lock and process the delete queue. */ void smb_llist_exit(smb_llist_t *ll) { rw_exit(&ll->ll_lock); /* smb_llist_flush(ll); */ } /* * smb_llist_upgrade * * This function tries to upgrade the lock of the locked list. It assumes the * locked has already been entered in RW_READER mode. It first tries using the * Solaris function rw_tryupgrade(). If that call fails the lock is released * and reentered in RW_WRITER mode. In that last case a window is opened during * which the contents of the list may have changed. The return code indicates * whether or not the list was modified when the lock was exited. */ int smb_llist_upgrade( smb_llist_t *ll) { uint64_t wrop; if (rw_tryupgrade(&ll->ll_lock) != 0) { return (0); } wrop = ll->ll_wrop; rw_exit(&ll->ll_lock); rw_enter(&ll->ll_lock, RW_WRITER); return (wrop != ll->ll_wrop); } /* * smb_llist_insert_head * * This function inserts the object passed a the beginning of the list. This * function assumes the lock of the list has already been entered. */ void smb_llist_insert_head( smb_llist_t *ll, void *obj) { list_insert_head(&ll->ll_list, obj); ++ll->ll_wrop; ++ll->ll_count; } /* * smb_llist_insert_tail * * This function appends to the object passed to the list. This function assumes * the lock of the list has already been entered. * */ void smb_llist_insert_tail( smb_llist_t *ll, void *obj) { list_insert_tail(&ll->ll_list, obj); ++ll->ll_wrop; ++ll->ll_count; } /* * smb_llist_remove * * This function removes the object passed from the list. This function assumes * the lock of the list has already been entered. */ void smb_llist_remove( smb_llist_t *ll, void *obj) { list_remove(&ll->ll_list, obj); ++ll->ll_wrop; --ll->ll_count; } /* * smb_llist_get_count * * This function returns the number of elements in the specified list. */ uint32_t smb_llist_get_count( smb_llist_t *ll) { return (ll->ll_count); }