usr/src/uts/common/io/stream.c
author masputra
Sat, 22 Oct 2005 22:50:14 -0700
changeset 741 40027a3621ac
parent 577 65796fd3c2db
child 898 64b2a371a6bd
permissions -rw-r--r--
PSARC 2005/082 Yosemite: UDP Performance Enhancement 4796051 Solaris needs a more complete HW checksumming support 4905227 duplicate macros in ipclassifier.h and ip.h 4915681 need hardware checksum offload for the case of IP/UDP reassembly 6201076 outbound flow-control dysfunctional, ip to ce using mdt 6223331 ipv6 flow control may corrupt UDP packets 6223809 16-bit aligned IP header should be allowed for all x86 platforms 6275398 Galaxy hangs when running lmbench 6281836 Yosemite project integration into Solaris 6281885 xge needs to support IPv6 checksum offload 6282776 IPv6 NCE fast path is not created for incoming solicitation 6304890 IP transmit-side checksum logic needs to be tightened 6304902 IP6_IN_NOCKSUM is obsolete and should be torched 6304904 UDP should reject TI_GETPEERNAME for non-connected endpoint 6306768 IP and UDP device and module definitions need to be centralized
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
/*	  All Rights Reserved  	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/thread.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/stropts.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/stream.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/strsubr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/strsun.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/conf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/atomic.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/vtrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <sys/ftrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/ontrap.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/multidata.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/multidata_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/sdt.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <sys/kmem_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
 * This file contains all the STREAMS utility routines that may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
 * be used by modules and drivers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
 * STREAMS message allocator: principles of operation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
 * The streams message allocator consists of all the routines that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
 * allocate, dup and free streams messages: allocb(), [d]esballoc[a],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
 * dupb(), freeb() and freemsg().  What follows is a high-level view
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
 * of how the allocator works.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
 * Every streams message consists of one or more mblks, a dblk, and data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
 * All mblks for all types of messages come from a common mblk_cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
 * The dblk and data come in several flavors, depending on how the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
 * message is allocated:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
 * (1) mblks up to DBLK_MAX_CACHE size are allocated from a collection of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
 *     fixed-size dblk/data caches. For message sizes that are multiples of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
 *     PAGESIZE, dblks are allocated separately from the buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
 *     The associated buffer is allocated by the constructor using kmem_alloc().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
 *     For all other message sizes, dblk and its associated data is allocated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 *     as a single contiguous chunk of memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 *     Objects in these caches consist of a dblk plus its associated data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 *     allocb() determines the nearest-size cache by table lookup:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 *     the dblk_cache[] array provides the mapping from size to dblk cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 * (2) Large messages (size > DBLK_MAX_CACHE) are constructed by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 *     kmem_alloc()'ing a buffer for the data and supplying that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 *     buffer to gesballoc(), described below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
 * (3) The four flavors of [d]esballoc[a] are all implemented by a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
 *     common routine, gesballoc() ("generic esballoc").  gesballoc()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
 *     allocates a dblk from the global dblk_esb_cache and sets db_base,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
 *     db_lim and db_frtnp to describe the caller-supplied buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
 * While there are several routines to allocate messages, there is only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
 * one routine to free messages: freeb().  freeb() simply invokes the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
 * dblk's free method, dbp->db_free(), which is set at allocation time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
 * dupb() creates a new reference to a message by allocating a new mblk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 * incrementing the dblk reference count and setting the dblk's free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 * method to dblk_decref().  The dblk's original free method is retained
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 * in db_lastfree.  dblk_decref() decrements the reference count on each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 * freeb().  If this is not the last reference it just frees the mblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
 * if this *is* the last reference, it restores db_free to db_lastfree,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
 * sets db_mblk to the current mblk (see below), and invokes db_lastfree.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
 * The implementation makes aggressive use of kmem object caching for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
 * maximum performance.  This makes the code simple and compact, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
 * also a bit abstruse in some places.  The invariants that constitute a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 * message's constructed state, described below, are more subtle than usual.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
 * Every dblk has an "attached mblk" as part of its constructed state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
 * The mblk is allocated by the dblk's constructor and remains attached
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
 * until the message is either dup'ed or pulled up.  In the dupb() case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
 * the mblk association doesn't matter until the last free, at which time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
 * dblk_decref() attaches the last mblk to the dblk.  pullupmsg() affects
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
 * the mblk association because it swaps the leading mblks of two messages,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
 * so it is responsible for swapping their db_mblk pointers accordingly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 * From a constructed-state viewpoint it doesn't matter that a dblk's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 * attached mblk can change while the message is allocated; all that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 * matters is that the dblk has *some* attached mblk when it's freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
 * The sizes of the allocb() small-message caches are not magical.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
 * They represent a good trade-off between internal and external
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
 * fragmentation for current workloads.  They should be reevaluated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
 * periodically, especially if allocations larger than DBLK_MAX_CACHE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
 * become common.  We use 64-byte alignment so that dblks don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
 * straddle cache lines unnecessarily.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
#define	DBLK_MAX_CACHE		73728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
#define	DBLK_CACHE_ALIGN	64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
#define	DBLK_MIN_SIZE		8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
#define	DBLK_SIZE_SHIFT		3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
#ifdef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
#define	DBLK_RTFU_SHIFT(field)	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	(8 * (&((dblk_t *)0)->db_struioflag - &((dblk_t *)0)->field))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
#define	DBLK_RTFU_SHIFT(field)	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	(8 * (&((dblk_t *)0)->field - &((dblk_t *)0)->db_ref))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
#define	DBLK_RTFU(ref, type, flags, uioflag)	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
	(((ref) << DBLK_RTFU_SHIFT(db_ref)) | \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	((type) << DBLK_RTFU_SHIFT(db_type)) | \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	(((flags) | (ref - 1)) << DBLK_RTFU_SHIFT(db_flags)) | \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	((uioflag) << DBLK_RTFU_SHIFT(db_struioflag)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
#define	DBLK_RTFU_REF_MASK	(DBLK_REFMAX << DBLK_RTFU_SHIFT(db_ref))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
#define	DBLK_RTFU_WORD(dbp)	(*((uint32_t *)&(dbp)->db_ref))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
#define	MBLK_BAND_FLAG_WORD(mp)	(*((uint32_t *)&(mp)->b_band))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
static size_t dblk_sizes[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
#ifdef _LP64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
	16, 80, 144, 208, 272, 336, 528, 1040, 1488, 1936, 2576, 3920,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
	8192, 12112, 16384, 20304, 24576, 28496, 32768, 36688,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
	40960, 44880, 49152, 53072, 57344, 61264, 65536, 69456,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	64, 128, 320, 576, 1088, 1536, 1984, 2624, 3968,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	8192, 12160, 16384, 20352, 24576, 28544, 32768, 36736,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	40960, 44928, 49152, 53120, 57344, 61312, 65536, 69504,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
	DBLK_MAX_CACHE, 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
static struct kmem_cache *dblk_cache[DBLK_MAX_CACHE / DBLK_MIN_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
static struct kmem_cache *mblk_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
static struct kmem_cache *dblk_esb_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
static struct kmem_cache *fthdr_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
static struct kmem_cache *ftblk_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
static void dblk_lastfree(mblk_t *mp, dblk_t *dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
static mblk_t *allocb_oversize(size_t size, int flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
static int allocb_tryhard_fails;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
static void frnop_func(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
frtn_t frnop = { frnop_func };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
static void bcache_dblk_lastfree(mblk_t *mp, dblk_t *dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
static boolean_t rwnext_enter(queue_t *qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
static void rwnext_exit(queue_t *qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
 * Patchable mblk/dblk kmem_cache flags.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
int dblk_kmem_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
int mblk_kmem_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
dblk_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
	dblk_t *dbp = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
	ssize_t msg_size = (ssize_t)cdrarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	size_t index;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
	ASSERT(msg_size != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	index = (msg_size - 1) >> DBLK_SIZE_SHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
577
65796fd3c2db 4790586 bogus coding in kstrputmsg()
meem
parents: 235
diff changeset
   199
	ASSERT(index < (DBLK_MAX_CACHE >> DBLK_SIZE_SHIFT));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	if ((dbp->db_mblk = kmem_cache_alloc(mblk_cache, kmflags)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	if ((msg_size & PAGEOFFSET) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
		dbp->db_base = kmem_alloc(msg_size, kmflags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
		if (dbp->db_base == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
			kmem_cache_free(mblk_cache, dbp->db_mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
		dbp->db_base = (unsigned char *)&dbp[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	dbp->db_mblk->b_datap = dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	dbp->db_cache = dblk_cache[index];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	dbp->db_lim = dbp->db_base + msg_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
	dbp->db_free = dbp->db_lastfree = dblk_lastfree;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
	dbp->db_frtnp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
	dbp->db_fthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
	dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
dblk_esb_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
	dblk_t *dbp = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
	if ((dbp->db_mblk = kmem_cache_alloc(mblk_cache, kmflags)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
	dbp->db_mblk->b_datap = dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
	dbp->db_cache = dblk_esb_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
	dbp->db_fthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
	dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
bcache_dblk_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
	dblk_t *dbp = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
	bcache_t *bcp = (bcache_t *)cdrarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
	if ((dbp->db_mblk = kmem_cache_alloc(mblk_cache, kmflags)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
	if ((dbp->db_base = (unsigned char *)kmem_cache_alloc(bcp->buffer_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	    kmflags)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
		kmem_cache_free(mblk_cache, dbp->db_mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
	dbp->db_mblk->b_datap = dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
	dbp->db_cache = (void *)bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
	dbp->db_lim = dbp->db_base + bcp->size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
	dbp->db_free = dbp->db_lastfree = bcache_dblk_lastfree;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
	dbp->db_frtnp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
	dbp->db_fthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
	dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
dblk_destructor(void *buf, void *cdrarg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
	dblk_t *dbp = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
	ssize_t msg_size = (ssize_t)cdrarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
	ASSERT(dbp->db_mblk->b_datap == dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
	ASSERT(msg_size != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
	ASSERT(dbp->db_struioflag == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
	ASSERT(dbp->db_struioun.cksum.flags == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
	if ((msg_size & PAGEOFFSET) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
		kmem_free(dbp->db_base, msg_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
	kmem_cache_free(mblk_cache, dbp->db_mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
bcache_dblk_destructor(void *buf, void *cdrarg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
	dblk_t *dbp = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
	bcache_t *bcp = (bcache_t *)cdrarg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
	kmem_cache_free(bcp->buffer_cache, dbp->db_base);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
	ASSERT(dbp->db_mblk->b_datap == dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
	ASSERT(dbp->db_struioflag == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
	ASSERT(dbp->db_struioun.cksum.flags == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
	kmem_cache_free(mblk_cache, dbp->db_mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
streams_msg_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
	char name[40];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
	size_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
	size_t lastsize = DBLK_MIN_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
	size_t *sizep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
	struct kmem_cache *cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	size_t tot_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	int offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	mblk_cache = kmem_cache_create("streams_mblk",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
		sizeof (mblk_t), 32, NULL, NULL, NULL, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
		mblk_kmem_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	for (sizep = dblk_sizes; (size = *sizep) != 0; sizep++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
		if ((offset = (size & PAGEOFFSET)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
			 * We are in the middle of a page, dblk should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
			 * be allocated on the same page
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
			tot_size = size + sizeof (dblk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
			ASSERT((offset + sizeof (dblk_t) + sizeof (kmem_slab_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
								< PAGESIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
			ASSERT((tot_size & (DBLK_CACHE_ALIGN - 1)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
			 * buf size is multiple of page size, dblk and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
			 * buffer are allocated separately.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
			ASSERT((size & (DBLK_CACHE_ALIGN - 1)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
			tot_size = sizeof (dblk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
		(void) sprintf(name, "streams_dblk_%ld", size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
		cp = kmem_cache_create(name, tot_size,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
			DBLK_CACHE_ALIGN, dblk_constructor,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
			dblk_destructor, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
			(void *)(size), NULL, dblk_kmem_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
		while (lastsize <= size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
			dblk_cache[(lastsize - 1) >> DBLK_SIZE_SHIFT] = cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
			lastsize += DBLK_MIN_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	dblk_esb_cache = kmem_cache_create("streams_dblk_esb",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
			sizeof (dblk_t), DBLK_CACHE_ALIGN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
			dblk_esb_constructor, dblk_destructor, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
			(void *) sizeof (dblk_t), NULL, dblk_kmem_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
	fthdr_cache = kmem_cache_create("streams_fthdr",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
		sizeof (fthdr_t), 32, NULL, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
	ftblk_cache = kmem_cache_create("streams_ftblk",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
		sizeof (ftblk_t), 32, NULL, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	/* Initialize Multidata caches */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
	mmd_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
allocb(size_t size, uint_t pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	dblk_t *dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
	size_t index;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
	index =  (size - 1)  >> DBLK_SIZE_SHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	if (index >= (DBLK_MAX_CACHE >> DBLK_SIZE_SHIFT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
		if (size != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
			mp = allocb_oversize(size, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
		index = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
	if ((dbp = kmem_cache_alloc(dblk_cache[index], KM_NOSLEEP)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
		mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
	mp = dbp->db_mblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	DBLK_RTFU_WORD(dbp) = DBLK_RTFU(1, M_DATA, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	mp->b_next = mp->b_prev = mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	mp->b_rptr = mp->b_wptr = dbp->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	MBLK_BAND_FLAG_WORD(mp) = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
	STR_FTALLOC(&dbp->db_fthdr, FTEV_ALLOCB, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
	FTRACE_1("allocb(): mp=0x%p", (uintptr_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
allocb_tmpl(size_t size, const mblk_t *tmpl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
	mblk_t *mp = allocb(size, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
		cred_t *cr = DB_CRED(tmpl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
		if (cr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
			crhold(mp->b_datap->db_credp = cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
		DB_CPID(mp) = DB_CPID(tmpl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
		DB_TYPE(mp) = DB_TYPE(tmpl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
allocb_cred(size_t size, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	mblk_t *mp = allocb(size, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
	if (mp != NULL && cr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
		crhold(mp->b_datap->db_credp = cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
allocb_cred_wait(size_t size, uint_t flags, int *error, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
	mblk_t *mp = allocb_wait(size, 0, flags, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
	if (mp != NULL && cr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
		crhold(mp->b_datap->db_credp = cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
freeb(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
	dblk_t *dbp = mp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
	ASSERT(dbp->db_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
	ASSERT(mp->b_next == NULL && mp->b_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
	FTRACE_1("freeb(): mp=0x%lx", (uintptr_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
	STR_FTEVENT_MBLK(mp, caller(), FTEV_FREEB, dbp->db_ref);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
	dbp->db_free(mp, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
freemsg(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
	FTRACE_1("freemsg(): mp=0x%lx", (uintptr_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
	while (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
		dblk_t *dbp = mp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
		mblk_t *mp_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
		ASSERT(dbp->db_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
		ASSERT(mp->b_next == NULL && mp->b_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
		STR_FTEVENT_MBLK(mp, caller(), FTEV_FREEB, dbp->db_ref);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
		dbp->db_free(mp, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
		mp = mp_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
 * Reallocate a block for another use.  Try hard to use the old block.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
 * If the old data is wanted (copy), leave b_wptr at the end of the data,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
 * otherwise return b_wptr = b_rptr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
 * This routine is private and unstable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
mblk_t	*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
reallocb(mblk_t *mp, size_t size, uint_t copy)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
	unsigned char	*old_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
	ptrdiff_t	cur_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
		return (allocb(size, BPRI_HI));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
	cur_size = mp->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
	old_rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
	ASSERT(mp->b_datap->db_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	if (mp->b_datap->db_ref == 1 && MBLKSIZE(mp) >= size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
		 * If the data is wanted and it will fit where it is, no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
		 * work is required.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
		if (copy && mp->b_datap->db_lim - mp->b_rptr >= size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
		mp->b_wptr = mp->b_rptr = mp->b_datap->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
	} else if ((mp1 = allocb_tmpl(size, mp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
		/* XXX other mp state could be copied too, db_flags ... ? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
		mp1->b_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
	if (copy) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		bcopy(old_rptr, mp1->b_rptr, cur_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
		mp1->b_wptr = mp1->b_rptr + cur_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
	if (mp != mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
		freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
	return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
dblk_lastfree(mblk_t *mp, dblk_t *dbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
	ASSERT(dbp->db_mblk == mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
	if (dbp->db_fthdr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
		str_ftfree(dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
	/* set credp and projid to be 'unspecified' before returning to cache */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
	if (dbp->db_credp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		crfree(dbp->db_credp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
	/* Reset the struioflag and the checksum flag fields */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
	kmem_cache_free(dbp->db_cache, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
dblk_decref(mblk_t *mp, dblk_t *dbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	if (dbp->db_ref != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
		uint32_t rtfu = atomic_add_32_nv(&DBLK_RTFU_WORD(dbp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
		    -(1 << DBLK_RTFU_SHIFT(db_ref)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
		 * atomic_add_32_nv() just decremented db_ref, so we no longer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
		 * have a reference to the dblk, which means another thread
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
		 * could free it.  Therefore we cannot examine the dblk to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
		 * determine whether ours was the last reference.  Instead,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
		 * we extract the new and minimum reference counts from rtfu.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
		 * Note that all we're really saying is "if (ref != refmin)".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
		if (((rtfu >> DBLK_RTFU_SHIFT(db_ref)) & DBLK_REFMAX) !=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
		    ((rtfu >> DBLK_RTFU_SHIFT(db_flags)) & DBLK_REFMIN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
			kmem_cache_free(mblk_cache, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
	dbp->db_mblk = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
	dbp->db_free = dbp->db_lastfree;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	dbp->db_lastfree(mp, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
dupb(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
	dblk_t *dbp = mp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	mblk_t *new_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
	uint32_t oldrtfu, newrtfu;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
	if ((new_mp = kmem_cache_alloc(mblk_cache, KM_NOSLEEP)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
	new_mp->b_next = new_mp->b_prev = new_mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
	new_mp->b_rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
	new_mp->b_wptr = mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	new_mp->b_datap = dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
	new_mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
	MBLK_BAND_FLAG_WORD(new_mp) = MBLK_BAND_FLAG_WORD(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
	STR_FTEVENT_MBLK(mp, caller(), FTEV_DUPB, dbp->db_ref);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
	 * First-dup optimization.  The enabling assumption is that there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	 * can can never be a race (in correct code) to dup the first copy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
	 * of a message.  Therefore we don't need to do it atomically.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	if (dbp->db_free != dblk_decref) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
		dbp->db_free = dblk_decref;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
		dbp->db_ref++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
		ASSERT(dbp->db_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
		oldrtfu = DBLK_RTFU_WORD(dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
		newrtfu = oldrtfu + (1 << DBLK_RTFU_SHIFT(db_ref));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
		 * If db_ref is maxed out we can't dup this message anymore.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
		if ((oldrtfu & DBLK_RTFU_REF_MASK) == DBLK_RTFU_REF_MASK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
			kmem_cache_free(mblk_cache, new_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
			new_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
	} while (cas32(&DBLK_RTFU_WORD(dbp), oldrtfu, newrtfu) != oldrtfu);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
	FTRACE_1("dupb(): new_mp=0x%lx", (uintptr_t)new_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
	return (new_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
dblk_lastfree_desb(mblk_t *mp, dblk_t *dbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
	frtn_t *frp = dbp->db_frtnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
	ASSERT(dbp->db_mblk == mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
	frp->free_func(frp->free_arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
	if (dbp->db_fthdr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
		str_ftfree(dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
	/* set credp and projid to be 'unspecified' before returning to cache */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
	if (dbp->db_credp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
		crfree(dbp->db_credp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
		dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
	kmem_cache_free(dbp->db_cache, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
frnop_func(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
 * Generic esballoc used to implement the four flavors: [d]esballoc[a].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
gesballoc(unsigned char *base, size_t size, uint32_t db_rtfu, frtn_t *frp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
	void (*lastfree)(mblk_t *, dblk_t *), int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
	dblk_t *dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
	ASSERT(base != NULL && frp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
	if ((dbp = kmem_cache_alloc(dblk_esb_cache, kmflags)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
		mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
	mp = dbp->db_mblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
	dbp->db_base = base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	dbp->db_lim = base + size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
	dbp->db_free = dbp->db_lastfree = lastfree;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
	dbp->db_frtnp = frp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
	DBLK_RTFU_WORD(dbp) = db_rtfu;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
	mp->b_next = mp->b_prev = mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	mp->b_rptr = mp->b_wptr = base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
	mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	MBLK_BAND_FLAG_WORD(mp) = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	FTRACE_1("gesballoc(): mp=0x%lx", (uintptr_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
esballoc(unsigned char *base, size_t size, uint_t pri, frtn_t *frp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
	 * Note that this is structured to allow the common case (i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
	 * STREAMS flowtracing disabled) to call gesballoc() with tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
	 * call optimization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
	if (!str_ftnever) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
		mp = gesballoc(base, size, DBLK_RTFU(1, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
		    frp, freebs_enqueue, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
			STR_FTALLOC(&DB_FTHDR(mp), FTEV_ESBALLOC, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
	return (gesballoc(base, size, DBLK_RTFU(1, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
	    frp, freebs_enqueue, KM_NOSLEEP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
 * Same as esballoc() but sleeps waiting for memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
esballoc_wait(unsigned char *base, size_t size, uint_t pri, frtn_t *frp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
	 * Note that this is structured to allow the common case (i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
	 * STREAMS flowtracing disabled) to call gesballoc() with tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	 * call optimization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
	if (!str_ftnever) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
		mp = gesballoc(base, size, DBLK_RTFU(1, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
		    frp, freebs_enqueue, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
		STR_FTALLOC(&DB_FTHDR(mp), FTEV_ESBALLOC, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	return (gesballoc(base, size, DBLK_RTFU(1, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	    frp, freebs_enqueue, KM_SLEEP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
desballoc(unsigned char *base, size_t size, uint_t pri, frtn_t *frp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	 * Note that this is structured to allow the common case (i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	 * STREAMS flowtracing disabled) to call gesballoc() with tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	 * call optimization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
	if (!str_ftnever) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
		mp = gesballoc(base, size, DBLK_RTFU(1, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
			frp, dblk_lastfree_desb, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
			STR_FTALLOC(&DB_FTHDR(mp), FTEV_DESBALLOC, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
	return (gesballoc(base, size, DBLK_RTFU(1, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
	    frp, dblk_lastfree_desb, KM_NOSLEEP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
esballoca(unsigned char *base, size_t size, uint_t pri, frtn_t *frp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
	 * Note that this is structured to allow the common case (i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
	 * STREAMS flowtracing disabled) to call gesballoc() with tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
	 * call optimization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
	if (!str_ftnever) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
		mp = gesballoc(base, size, DBLK_RTFU(2, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
		    frp, freebs_enqueue, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
			STR_FTALLOC(&DB_FTHDR(mp), FTEV_ESBALLOCA, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	return (gesballoc(base, size, DBLK_RTFU(2, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
	    frp, freebs_enqueue, KM_NOSLEEP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
desballoca(unsigned char *base, size_t size, uint_t pri, frtn_t *frp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
	 * Note that this is structured to allow the common case (i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	 * STREAMS flowtracing disabled) to call gesballoc() with tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	 * call optimization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
	if (!str_ftnever) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
		mp = gesballoc(base, size, DBLK_RTFU(2, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
		    frp, dblk_lastfree_desb, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
			STR_FTALLOC(&DB_FTHDR(mp), FTEV_DESBALLOCA, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
	return (gesballoc(base, size, DBLK_RTFU(2, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
	    frp, dblk_lastfree_desb, KM_NOSLEEP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
bcache_dblk_lastfree(mblk_t *mp, dblk_t *dbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
	bcache_t *bcp = dbp->db_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	ASSERT(dbp->db_mblk == mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
	if (dbp->db_fthdr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
		str_ftfree(dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
	/* set credp and projid to be 'unspecified' before returning to cache */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
	if (dbp->db_credp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
		crfree(dbp->db_credp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
		dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
	mutex_enter(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	kmem_cache_free(bcp->dblk_cache, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
	bcp->alloc--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	if (bcp->alloc == 0 && bcp->destroy != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
		kmem_cache_destroy(bcp->dblk_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
		kmem_cache_destroy(bcp->buffer_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
		mutex_exit(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
		mutex_destroy(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
		kmem_free(bcp, sizeof (bcache_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
		mutex_exit(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
bcache_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
bcache_create(char *name, size_t size, uint_t align)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
	bcache_t *bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
	char buffer[255];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
	ASSERT((align & (align - 1)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
	if ((bcp = (bcache_t *)kmem_alloc(sizeof (bcache_t), KM_NOSLEEP)) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
	    NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
	bcp->size = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
	bcp->align = align;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
	bcp->alloc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
	bcp->destroy = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
	mutex_init(&bcp->mutex, NULL, MUTEX_DRIVER, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
	(void) sprintf(buffer, "%s_buffer_cache", name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
	bcp->buffer_cache = kmem_cache_create(buffer, size, align, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
	    NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
	(void) sprintf(buffer, "%s_dblk_cache", name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
	bcp->dblk_cache = kmem_cache_create(buffer, sizeof (dblk_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
	    DBLK_CACHE_ALIGN, bcache_dblk_constructor, bcache_dblk_destructor,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
						NULL, (void *)bcp, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
	return (bcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
bcache_destroy(bcache_t *bcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
	ASSERT(bcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
	mutex_enter(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
	if (bcp->alloc == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
		kmem_cache_destroy(bcp->dblk_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
		kmem_cache_destroy(bcp->buffer_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
		mutex_exit(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
		mutex_destroy(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
		kmem_free(bcp, sizeof (bcache_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
		bcp->destroy++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
		mutex_exit(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
bcache_allocb(bcache_t *bcp, uint_t pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
	dblk_t *dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
	mblk_t *mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
	ASSERT(bcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
	mutex_enter(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
	if (bcp->destroy != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
		mutex_exit(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
	if ((dbp = kmem_cache_alloc(bcp->dblk_cache, KM_NOSLEEP)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
		mutex_exit(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
	bcp->alloc++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
	mutex_exit(&bcp->mutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
	ASSERT(((uintptr_t)(dbp->db_base) & (bcp->align - 1)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
	mp = dbp->db_mblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
	DBLK_RTFU_WORD(dbp) = DBLK_RTFU(1, M_DATA, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
	mp->b_next = mp->b_prev = mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
	mp->b_rptr = mp->b_wptr = dbp->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
	mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
	MBLK_BAND_FLAG_WORD(mp) = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
	STR_FTALLOC(&dbp->db_fthdr, FTEV_BCALLOCB, bcp->size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
	FTRACE_1("bcache_allocb(): mp=0x%p", (uintptr_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
dblk_lastfree_oversize(mblk_t *mp, dblk_t *dbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
	ASSERT(dbp->db_mblk == mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
	if (dbp->db_fthdr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
		str_ftfree(dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
	/* set credp and projid to be 'unspecified' before returning to cache */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
	if (dbp->db_credp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
		crfree(dbp->db_credp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
		dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
	kmem_free(dbp->db_base, dbp->db_lim - dbp->db_base);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
	kmem_cache_free(dbp->db_cache, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
allocb_oversize(size_t size, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
	void *buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
	size = P2ROUNDUP(size, DBLK_CACHE_ALIGN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
	if ((buf = kmem_alloc(size, kmflags)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
	if ((mp = gesballoc(buf, size, DBLK_RTFU(1, M_DATA, 0, 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
	    &frnop, dblk_lastfree_oversize, kmflags)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
		kmem_free(buf, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
	if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
		STR_FTALLOC(&DB_FTHDR(mp), FTEV_ALLOCBIG, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
allocb_tryhard(size_t target_size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
	size_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
	for (size = target_size; size < target_size + 512;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
	    size += DBLK_CACHE_ALIGN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
		if ((bp = allocb(size, BPRI_HI)) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
			return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
	allocb_tryhard_fails++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
 * This routine is consolidation private for STREAMS internal use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
 * This routine may only be called from sync routines (i.e., not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
 * from put or service procedures).  It is located here (rather
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
 * than strsubr.c) so that we don't have to expose all of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
 * allocb() implementation details in header files.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
allocb_wait(size_t size, uint_t pri, uint_t flags, int *error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
	dblk_t *dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
	size_t index;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
	index = (size -1) >> DBLK_SIZE_SHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
	if (flags & STR_NOSIG) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
		if (index >= (DBLK_MAX_CACHE >> DBLK_SIZE_SHIFT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
			if (size != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
				mp = allocb_oversize(size, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
				FTRACE_1("allocb_wait (NOSIG): mp=0x%lx",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
				    (uintptr_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
				return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
			index = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
		dbp = kmem_cache_alloc(dblk_cache[index], KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
		mp = dbp->db_mblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
		DBLK_RTFU_WORD(dbp) = DBLK_RTFU(1, M_DATA, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
		mp->b_next = mp->b_prev = mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
		mp->b_rptr = mp->b_wptr = dbp->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
		mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
		MBLK_BAND_FLAG_WORD(mp) = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
		STR_FTALLOC(&DB_FTHDR(mp), FTEV_ALLOCBW, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
		FTRACE_1("allocb_wait (NOSIG): mp=0x%lx", (uintptr_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
		while ((mp = allocb(size, pri)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
			if ((*error = strwaitbuf(size, BPRI_HI)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
				return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
 * Call function 'func' with 'arg' when a class zero block can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
 * be allocated with priority 'pri'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
bufcall_id_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
esbbcall(uint_t pri, void (*func)(void *), void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
	return (bufcall(1, pri, func, arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
 * Allocates an iocblk (M_IOCTL) block. Properly sets the credentials
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
 * ioc_id, rval and error of the struct ioctl to set up an ioctl call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
 * This provides consistency for all internal allocators of ioctl.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
mkiocb(uint_t cmd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
	struct iocblk	*ioc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
	 * Allocate enough space for any of the ioctl related messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
	if ((mp = allocb(sizeof (union ioctypes), BPRI_MED)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
	bzero(mp->b_rptr, sizeof (union ioctypes));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
	 * Set the mblk_t information and ptrs correctly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
	mp->b_wptr += sizeof (struct iocblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
	mp->b_datap->db_type = M_IOCTL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
	 * Fill in the fields.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
	ioc		= (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
	ioc->ioc_cmd	= cmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
	ioc->ioc_cr	= kcred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
	ioc->ioc_id	= getiocseqno();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
	ioc->ioc_flag	= IOC_NATIVE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
 * test if block of given size can be allocated with a request of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
 * the given priority.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
 * 'pri' is no longer used, but is retained for compatibility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
testb(size_t size, uint_t pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
	return ((size + sizeof (dblk_t)) <= kmem_avail());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
 * Call function 'func' with argument 'arg' when there is a reasonably
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
 * good chance that a block of size 'size' can be allocated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
 * 'pri' is no longer used, but is retained for compatibility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
bufcall_id_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
bufcall(size_t size, uint_t pri, void (*func)(void *), void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
	static long bid = 1;	/* always odd to save checking for zero */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
	bufcall_id_t bc_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
	struct strbufcall *bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
	if ((bcp = kmem_alloc(sizeof (strbufcall_t), KM_NOSLEEP)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
	bcp->bc_func = func;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
	bcp->bc_arg = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
	bcp->bc_size = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
	bcp->bc_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
	bcp->bc_executor = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
	mutex_enter(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
	 * After bcp is linked into strbcalls and strbcall_lock is dropped there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
	 * should be no references to bcp since it may be freed by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
	 * runbufcalls(). Since bcp_id field is returned, we save its value in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
	 * the local var.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
	bc_id = bcp->bc_id = (bufcall_id_t)(bid += 2);	/* keep it odd */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
	 * add newly allocated stream event to existing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
	 * linked list of events.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
	if (strbcalls.bc_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
		strbcalls.bc_head = strbcalls.bc_tail = bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
		strbcalls.bc_tail->bc_next = bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
		strbcalls.bc_tail = bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
	cv_signal(&strbcall_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
	mutex_exit(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
	return (bc_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
 * Cancel a bufcall request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
unbufcall(bufcall_id_t id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
	strbufcall_t *bcp, *pbcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
	mutex_enter(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
again:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
	pbcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
	for (bcp = strbcalls.bc_head; bcp; bcp = bcp->bc_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
		if (id == bcp->bc_id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
		pbcp = bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
	if (bcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
		if (bcp->bc_executor != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
			if (bcp->bc_executor != curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
				cv_wait(&bcall_cv, &strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
				goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
			if (pbcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
				pbcp->bc_next = bcp->bc_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
				strbcalls.bc_head = bcp->bc_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
			if (bcp == strbcalls.bc_tail)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
				strbcalls.bc_tail = pbcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
			kmem_free(bcp, sizeof (strbufcall_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
	mutex_exit(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
 * Duplicate a message block by block (uses dupb), returning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
 * a pointer to the duplicate message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
 * Returns a non-NULL value only if the entire message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
 * was dup'd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
dupmsg(mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
	mblk_t *head, *nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
	if (!bp || !(nbp = head = dupb(bp)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
	while (bp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
		if (!(nbp->b_cont = dupb(bp->b_cont))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
			freemsg(head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
		nbp = nbp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
		bp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
	return (head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
#define	DUPB_NOLOAN(bp) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
	((((bp)->b_datap->db_struioflag & STRUIO_ZC) != 0) ? \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
	copyb((bp)) : dupb((bp)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
dupmsg_noloan(mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
	mblk_t *head, *nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
	if (bp == NULL || DB_TYPE(bp) != M_DATA ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
	    ((nbp = head = DUPB_NOLOAN(bp)) == NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
	while (bp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
		if ((nbp->b_cont = DUPB_NOLOAN(bp->b_cont)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
			freemsg(head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
		nbp = nbp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
		bp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
	return (head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
 * Copy data from message and data block to newly allocated message and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
 * data block. Returns new message block pointer, or NULL if error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
 * The alignment of rptr (w.r.t. word alignment) will be the same in the copy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
 * as in the original even when db_base is not word aligned. (bug 1052877)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
copyb(mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
	mblk_t	*nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
	dblk_t	*dp, *ndp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
	uchar_t *base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
	size_t	size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
	size_t	unaligned;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
	ASSERT(bp->b_wptr >= bp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
	dp = bp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
	if (dp->db_fthdr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
		STR_FTEVENT_MBLK(bp, caller(), FTEV_COPYB, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
	 * Special handling for Multidata message; this should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
	 * removed once a copy-callback routine is made available.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
	if (dp->db_type == M_MULTIDATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
		cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
		if ((nbp = mmd_copy(bp, KM_NOSLEEP)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
		nbp->b_flag = bp->b_flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
		nbp->b_band = bp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
		ndp = nbp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
		/* See comments below on potential issues. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
		STR_FTEVENT_MBLK(nbp, caller(), FTEV_COPYB, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
		ASSERT(ndp->db_type == dp->db_type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
		cr = dp->db_credp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
		if (cr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
			crhold(ndp->db_credp = cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
		ndp->db_cpid = dp->db_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
		return (nbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
	size = dp->db_lim - dp->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
	unaligned = P2PHASE((uintptr_t)dp->db_base, sizeof (uint_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
	if ((nbp = allocb_tmpl(size + unaligned, bp)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
	nbp->b_flag = bp->b_flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
	nbp->b_band = bp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
	ndp = nbp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
	 * Well, here is a potential issue.  If we are trying to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
	 * trace a flow, and we copy the message, we might lose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
	 * information about where this message might have been.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
	 * So we should inherit the FT data.  On the other hand,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
	 * a user might be interested only in alloc to free data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
	 * So I guess the real answer is to provide a tunable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
	STR_FTEVENT_MBLK(nbp, caller(), FTEV_COPYB, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
	base = ndp->db_base + unaligned;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
	bcopy(dp->db_base, ndp->db_base + unaligned, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
	nbp->b_rptr = base + (bp->b_rptr - dp->db_base);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
	nbp->b_wptr = nbp->b_rptr + MBLKL(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
	return (nbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
 * Copy data from message to newly allocated message using new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
 * data blocks.  Returns a pointer to the new message, or NULL if error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
copymsg(mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
	mblk_t *head, *nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
	if (!bp || !(nbp = head = copyb(bp)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
	while (bp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
		if (!(nbp->b_cont = copyb(bp->b_cont))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
			freemsg(head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
		nbp = nbp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
		bp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
	return (head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
 * link a message block to tail of message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
linkb(mblk_t *mp, mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
	ASSERT(mp && bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
	for (; mp->b_cont; mp = mp->b_cont)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
		;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	mp->b_cont = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
 * unlink a message block from head of message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
 * return pointer to new message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
 * NULL if message becomes empty.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
unlinkb(mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
	mblk_t *bp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
	bp1 = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
	bp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
	return (bp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
 * remove a message block "bp" from message "mp"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
 * Return pointer to new message or NULL if no message remains.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
 * Return -1 if bp is not found in message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
rmvb(mblk_t *mp, mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
	mblk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
	mblk_t *lastp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
	ASSERT(mp && bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
	for (tmp = mp; tmp; tmp = tmp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
		if (tmp == bp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
			if (lastp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
				lastp->b_cont = tmp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
				mp = tmp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
			tmp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
		lastp = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
	return ((mblk_t *)-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
 * Concatenate and align first len bytes of common
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
 * message type.  Len == -1, means concat everything.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
 * Returns 1 on success, 0 on failure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
 * After the pullup, mp points to the pulled up data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
pullupmsg(mblk_t *mp, ssize_t len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
	mblk_t *bp, *b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
	dblk_t *dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
	ssize_t n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
	ASSERT(mp->b_datap->db_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
	ASSERT(mp->b_next == NULL && mp->b_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
	 * We won't handle Multidata message, since it contains
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
	 * metadata which this function has no knowledge of; we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
	 * assert on DEBUG, and return failure otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
	ASSERT(mp->b_datap->db_type != M_MULTIDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
	if (mp->b_datap->db_type == M_MULTIDATA)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
	if (len == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
		if (mp->b_cont == NULL && str_aligned(mp->b_rptr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
			return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
		len = xmsgsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
		ssize_t first_mblk_len = mp->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
		ASSERT(first_mblk_len >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
		 * If the length is less than that of the first mblk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
		 * we want to pull up the message into an aligned mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
		 * Though not part of the spec, some callers assume it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
		if (len <= first_mblk_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
			if (str_aligned(mp->b_rptr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
				return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
			len = first_mblk_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
		} else if (xmsgsize(mp) < len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
	if ((bp = allocb_tmpl(len, mp)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
	dbp = bp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
	*bp = *mp;		/* swap mblks so bp heads the old msg... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
	mp->b_datap = dbp;	/* ... and mp heads the new message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
	mp->b_datap->db_mblk = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
	bp->b_datap->db_mblk = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
	mp->b_rptr = mp->b_wptr = dbp->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
		ASSERT(bp->b_datap->db_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
		ASSERT(bp->b_wptr >= bp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
		n = MIN(bp->b_wptr - bp->b_rptr, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
		bcopy(bp->b_rptr, mp->b_wptr, (size_t)n);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
		mp->b_wptr += n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
		bp->b_rptr += n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
		len -= n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
		if (bp->b_rptr != bp->b_wptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
		b_cont = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
		freeb(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
		bp = b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
	} while (len && bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
	mp->b_cont = bp;	/* tack on whatever wasn't pulled up */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
 * Concatenate and align at least the first len bytes of common message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
 * type.  Len == -1 means concatenate everything.  The original message is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
 * unaltered.  Returns a pointer to a new message on success, otherwise
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
 * returns NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
msgpullup(mblk_t *mp, ssize_t len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
	mblk_t	*newmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
	ssize_t	totlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
	ssize_t	n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
	 * We won't handle Multidata message, since it contains
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
	 * metadata which this function has no knowledge of; we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
	 * assert on DEBUG, and return failure otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
	ASSERT(mp->b_datap->db_type != M_MULTIDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
	if (mp->b_datap->db_type == M_MULTIDATA)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
	totlen = xmsgsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
	if ((len > 0) && (len > totlen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
	 * Copy all of the first msg type into one new mblk, then dupmsg
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
	 * and link the rest onto this.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
	len = totlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
	if ((newmp = allocb_tmpl(len, mp)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
	newmp->b_flag = mp->b_flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
	newmp->b_band = mp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
	while (len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
		n = mp->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
		ASSERT(n >= 0);		/* allow zero-length mblk_t's */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
		if (n > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
			bcopy(mp->b_rptr, newmp->b_wptr, n);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
		newmp->b_wptr += n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
		len -= n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
		newmp->b_cont = dupmsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
		if (newmp->b_cont == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
			freemsg(newmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
	return (newmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
 * Trim bytes from message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
 *  len > 0, trim from head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
 *  len < 0, trim from tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
 * Returns 1 on success, 0 on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
adjmsg(mblk_t *mp, ssize_t len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
	mblk_t *save_bp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
	mblk_t *prev_bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
	mblk_t *bcont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
	unsigned char type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
	ssize_t n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
	int fromhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
	int first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
	ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
	 * We won't handle Multidata message, since it contains
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
	 * metadata which this function has no knowledge of; we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
	 * assert on DEBUG, and return failure otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
	ASSERT(mp->b_datap->db_type != M_MULTIDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
	if (mp->b_datap->db_type == M_MULTIDATA)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
	if (len < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
		fromhead = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
		len = -len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
		fromhead = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
	if (xmsgsize(mp) < len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
	if (fromhead) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
		first = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
		while (len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
			ASSERT(mp->b_wptr >= mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
			n = MIN(mp->b_wptr - mp->b_rptr, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
			mp->b_rptr += n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
			len -= n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
			 * If this is not the first zero length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
			 * message remove it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
			if (!first && (mp->b_wptr == mp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
				bcont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
				freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
				mp = save_bp->b_cont = bcont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
				save_bp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
				mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
			first = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
		type = mp->b_datap->db_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
		while (len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
			bp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
			save_bp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
			 * Find the last message of same type
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
			while (bp && bp->b_datap->db_type == type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
				ASSERT(bp->b_wptr >= bp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
				prev_bp = save_bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
				save_bp = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
				bp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
			if (save_bp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
			n = MIN(save_bp->b_wptr - save_bp->b_rptr, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
			save_bp->b_wptr -= n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
			len -= n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
			 * If this is not the first message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
			 * and we have taken away everything
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
			 * from this message, remove it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
			if ((save_bp != mp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
				(save_bp->b_wptr == save_bp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
				bcont = save_bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
				freeb(save_bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
				prev_bp->b_cont = bcont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
 * get number of data bytes in message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
size_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
msgdsize(mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
	size_t count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
	for (; bp; bp = bp->b_cont)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
		if (bp->b_datap->db_type == M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
			ASSERT(bp->b_wptr >= bp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
			count += bp->b_wptr - bp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
	return (count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
 * Get a message off head of queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
 * If queue has no buffers then mark queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
 * with QWANTR. (queue wants to be read by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
 * someone when data becomes available)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
 * If there is something to take off then do so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
 * If queue falls below hi water mark turn off QFULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
 * flag.  Decrement weighted count of queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
 * Also turn off QWANTR because queue is being read.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
 * The queue count is maintained on a per-band basis.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
 * Priority band 0 (normal messages) uses q_count,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
 * q_lowat, etc.  Non-zero priority bands use the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
 * fields in their respective qband structures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
 * (qb_count, qb_lowat, etc.)  All messages appear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
 * on the same list, linked via their b_next pointers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
 * q_first is the head of the list.  q_count does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
 * not reflect the size of all the messages on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
 * queue.  It only reflects those messages in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
 * normal band of flow.  The one exception to this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
 * deals with high priority messages.  They are in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
 * their own conceptual "band", but are accounted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
 * against q_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
 * If queue count is below the lo water mark and QWANTW
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
 * is set, enable the closest backq which has a service
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
 * procedure and turn off the QWANTW flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
 * getq could be built on top of rmvq, but isn't because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
 * of performance considerations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
 * A note on the use of q_count and q_mblkcnt:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
 *   q_count is the traditional byte count for messages that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
 *   have been put on a queue.  Documentation tells us that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
 *   we shouldn't rely on that count, but some drivers/modules
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
 *   do.  What was needed, however, is a mechanism to prevent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
 *   runaway streams from consuming all of the resources,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
 *   and particularly be able to flow control zero-length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
 *   messages.  q_mblkcnt is used for this purpose.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
 *   counts the number of mblk's that are being put on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
 *   the queue.  The intention here, is that each mblk should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
 *   contain one byte of data and, for the purpose of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
 *   flow-control, logically does.  A queue will become
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
 *   full when EITHER of these values (q_count and q_mblkcnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
 *   reach the highwater mark.  It will clear when BOTH
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
 *   of them drop below the highwater mark.  And it will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
 *   backenable when BOTH of them drop below the lowwater
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
 *   mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
 *   With this algorithm, a driver/module might be able
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
 *   to find a reasonably accurate q_count, and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
 *   framework can still try and limit resource usage.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
getq(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
	mblk_t *bp;
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 0
diff changeset
  1675
	uchar_t band = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
	bp = getq_noenab(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
	if (bp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
		band = bp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
	 * Inlined from qbackenable().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
	 * Quick check without holding the lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
	if (band == 0 && (q->q_flag & (QWANTW|QWANTWSYNC)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
		return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
	qbackenable(q, band);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
	return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1693
 * Calculate number of data bytes in a single data message block taking
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1694
 * multidata messages into account.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1695
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1696
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1697
#define	ADD_MBLK_SIZE(mp, size) 					\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1698
	if (DB_TYPE(mp) != M_MULTIDATA) {				\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1699
		(size) += MBLKL(mp);					\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1700
	} else {							\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1701
		uint_t	pinuse;						\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1702
									\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1703
		mmd_getsize(mmd_getmultidata(mp), NULL, &pinuse);	\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1704
		(size) += pinuse;					\
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1705
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1706
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1707
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
 * Like getq() but does not backenable.  This is used by the stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
 * head when a putback() is likely.  The caller must call qbackenable()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
 * after it is done with accessing the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
getq_noenab(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
	mblk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
	kthread_id_t freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
	int	bytecnt = 0, mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
	/* freezestr should allow its caller to call getq/putq */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
	if ((bp = q->q_first) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
		q->q_flag |= QWANTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
		if ((q->q_first = bp->b_next) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
			q->q_last = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
			q->q_first->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
		/* Get message byte count for q_count accounting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
		for (tmp = bp; tmp; tmp = tmp->b_cont) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1739
			ADD_MBLK_SIZE(tmp, bytecnt);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
			mblkcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
		if (bp->b_band == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
			q->q_count -= bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
			q->q_mblkcnt -= mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
			if ((q->q_count < q->q_hiwat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
			    (q->q_mblkcnt < q->q_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
				q->q_flag &= ~QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
			int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
			ASSERT(bp->b_band <= q->q_nband);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
			ASSERT(q->q_bandp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
			ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
			qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
			i = bp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
			while (--i > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
				qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
			if (qbp->qb_first == qbp->qb_last) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
				qbp->qb_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
				qbp->qb_last = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
				qbp->qb_first = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
			qbp->qb_count -= bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
			qbp->qb_mblkcnt -= mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
			if ((qbp->qb_count < qbp->qb_hiwat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
			    (qbp->qb_mblkcnt < qbp->qb_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
				qbp->qb_flag &= ~QB_FULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
		q->q_flag &= ~QWANTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
		bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
		bp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
	STR_FTEVENT_MSG(bp, q, FTEV_GETQ, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
	return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
 * Determine if a backenable is needed after removing a message in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
 * specified band.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
 * NOTE: This routine assumes that something like getq_noenab() has been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
 * already called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
 * For the read side it is ok to hold sd_lock across calling this (and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
 * stream head often does).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
 * But for the write side strwakeq might be invoked and it acquires sd_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
void
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 0
diff changeset
  1796
qbackenable(queue_t *q, uchar_t band)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
	int backenab = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
	kthread_id_t freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
	ASSERT(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
	ASSERT((q->q_flag & QREADR) || MUTEX_NOT_HELD(&STREAM(q)->sd_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
	 * Quick check without holding the lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
	 * OK since after getq() has lowered the q_count these flags
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
	 * would not change unless either the qbackenable() is done by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
	 * another thread (which is ok) or the queue has gotten QFULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
	 * in which case another backenable will take place when the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
	 * drops below q_lowat.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
	if (band == 0 && (q->q_flag & (QWANTW|QWANTWSYNC)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
	/* freezestr should allow its caller to call getq/putq */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
	if (band == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
		if (q->q_lowat == 0 || (q->q_count < q->q_lowat &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
		    q->q_mblkcnt < q->q_lowat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
			backenab = q->q_flag & (QWANTW|QWANTWSYNC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
		ASSERT((unsigned)band <= q->q_nband);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
		ASSERT(q->q_bandp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
		i = band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
		while (--i > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
		if (qbp->qb_lowat == 0 || (qbp->qb_count < qbp->qb_lowat &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
		    qbp->qb_mblkcnt < qbp->qb_lowat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
			backenab = qbp->qb_flag & QB_WANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
	if (backenab == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
		if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
	/* Have to drop the lock across strwakeq and backenable */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
	if (backenab & QWANTWSYNC)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
		q->q_flag &= ~QWANTWSYNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
	if (backenab & (QWANTW|QB_WANTW)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
		if (band != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
			qbp->qb_flag &= ~QB_WANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
		else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
			q->q_flag &= ~QWANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
	if (backenab & QWANTWSYNC)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
		strwakeq(q, QWANTWSYNC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
	if (backenab & (QWANTW|QB_WANTW))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
		backenable(q, band);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
 * Remove a message from a queue.  The queue count and other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
 * flow control parameters are adjusted and the back queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
 * enabled if necessary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
 * rmvq can be called with the stream frozen, but other utility functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
 * holding QLOCK, and by streams modules without any locks/frozen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
rmvq(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
	ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
	rmvq_noenab(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
	if (curthread != STREAM(q)->sd_freezer && MUTEX_HELD(QLOCK(q))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
		 * qbackenable can handle a frozen stream but not a "random"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
		 * qlock being held. Drop lock across qbackenable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
		qbackenable(q, mp->b_band);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
		qbackenable(q, mp->b_band);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
 * Like rmvq() but without any backenabling.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
 * This exists to handle SR_CONSOL_DATA in strrput().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
rmvq_noenab(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
	mblk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
	qband_t *qbp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
	kthread_id_t freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
	int	bytecnt = 0, mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
	} else if (MUTEX_HELD(QLOCK(q))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
		/* Don't drop lock on exit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
		freezer = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
	ASSERT(mp->b_band <= q->q_nband);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
	if (mp->b_band != 0) {		/* Adjust band pointers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
		ASSERT(q->q_bandp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
		i = mp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
		while (--i > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
		if (mp == qbp->qb_first) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
			if (mp->b_next && mp->b_band == mp->b_next->b_band)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
				qbp->qb_first = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
				qbp->qb_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
		if (mp == qbp->qb_last) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
			if (mp->b_prev && mp->b_band == mp->b_prev->b_band)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
				qbp->qb_last = mp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
				qbp->qb_last = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
	 * Remove the message from the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
	if (mp->b_prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
		mp->b_prev->b_next = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
		q->q_first = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
	if (mp->b_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
		mp->b_next->b_prev = mp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
		q->q_last = mp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
	mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
	mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
	/* Get the size of the message for q_count accounting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
	for (tmp = mp; tmp; tmp = tmp->b_cont) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  1959
		ADD_MBLK_SIZE(tmp, bytecnt);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
		mblkcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
	if (mp->b_band == 0) {		/* Perform q_count accounting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
		q->q_count -= bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
		q->q_mblkcnt -= mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
		if ((q->q_count < q->q_hiwat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
		    (q->q_mblkcnt < q->q_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
			q->q_flag &= ~QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
	} else {			/* Perform qb_count accounting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
		qbp->qb_count -= bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
		qbp->qb_mblkcnt -= mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
		if ((qbp->qb_count < qbp->qb_hiwat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
		    (qbp->qb_mblkcnt < qbp->qb_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
			qbp->qb_flag &= ~QB_FULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
	STR_FTEVENT_MSG(mp, q, FTEV_RMVQ, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
 * Empty a queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
 * If flag is set, remove all messages.  Otherwise, remove
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
 * only non-control messages.  If queue falls below its low
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
 * water mark, and QWANTW is set, enable the nearest upstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
 * service procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
 * Historical note: when merging the M_FLUSH code in strrput with this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
 * code one difference was discovered. flushq did not have a check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
 * for q_lowat == 0 in the backenabling test.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
 * pcproto_flag specifies whether or not a M_PCPROTO message should be flushed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
 * if one exists on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
flushq_common(queue_t *q, int flag, int pcproto_flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
	mblk_t *mp, *nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
	int backenab = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
	unsigned char bpri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
	unsigned char	qbf[NBAND];	/* band flushing backenable flags */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
	if (q->q_first == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
	mp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
	q->q_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
	q->q_last = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
	q->q_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
	q->q_mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
	for (qbp = q->q_bandp; qbp; qbp = qbp->qb_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
		qbp->qb_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
		qbp->qb_last = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
		qbp->qb_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
		qbp->qb_mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
		qbp->qb_flag &= ~QB_FULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
	q->q_flag &= ~QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
	while (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
		nmp = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
		mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
		STR_FTEVENT_MBLK(mp, q, FTEV_FLUSHQ, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
		if (pcproto_flag && (mp->b_datap->db_type == M_PCPROTO))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
			(void) putq(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
		else if (flag || datamsg(mp->b_datap->db_type))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
			(void) putq(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
		mp = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
	bpri = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
	for (qbp = q->q_bandp; qbp; qbp = qbp->qb_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
		if ((qbp->qb_flag & QB_WANTW) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
		    (((qbp->qb_count < qbp->qb_lowat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
		    (qbp->qb_mblkcnt < qbp->qb_lowat)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
		    qbp->qb_lowat == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
			qbp->qb_flag &= ~QB_WANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
			backenab = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
			qbf[bpri] = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
			qbf[bpri] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
		bpri++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
	ASSERT(bpri == (unsigned char)(q->q_nband + 1));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
	if ((q->q_flag & QWANTW) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
	    (((q->q_count < q->q_lowat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
	    (q->q_mblkcnt < q->q_lowat)) || q->q_lowat == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
		q->q_flag &= ~QWANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
		backenab = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
		qbf[0] = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
		qbf[0] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
	 * If any band can now be written to, and there is a writer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
	 * for that band, then backenable the closest service procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
	if (backenab) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
		for (bpri = q->q_nband; bpri != 0; bpri--)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
			if (qbf[bpri])
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 0
diff changeset
  2071
				backenable(q, bpri);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
		if (qbf[0])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
			backenable(q, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
 * The real flushing takes place in flushq_common. This is done so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
 * a flag which specifies whether or not M_PCPROTO messages should be flushed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2081
 * or not. Currently the only place that uses this flag is the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
flushq(queue_t *q, int flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
	flushq_common(q, flag, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
 * Flush the queue of messages of the given priority band.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
 * There is some duplication of code between flushq and flushband.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
 * This is because we want to optimize the code as much as possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
 * The assumption is that there will be more messages in the normal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
 * (priority 0) band than in any other.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
 * Historical note: when merging the M_FLUSH code in strrput with this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
 * code one difference was discovered. flushband had an extra check for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
 * did not have a check for (mp->b_datap->db_type < QPCTL) in the band 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
 * case. That check does not match the man page for flushband and was not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
 * in the strrput flush code hence it was removed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
flushband(queue_t *q, unsigned char pri, int flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
	mblk_t *nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
	mblk_t *last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
	int band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
	ASSERT((flag == FLUSHDATA) || (flag == FLUSHALL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
	if (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
	if (pri == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
		mp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
		q->q_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
		q->q_last = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
		q->q_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
		q->q_mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
		for (qbp = q->q_bandp; qbp; qbp = qbp->qb_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
			qbp->qb_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
			qbp->qb_last = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
			qbp->qb_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
			qbp->qb_mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
			qbp->qb_flag &= ~QB_FULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
		q->q_flag &= ~QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
		while (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
			nmp = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
			mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
			if ((mp->b_band == 0) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
				((flag == FLUSHALL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
				datamsg(mp->b_datap->db_type)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
				(void) putq(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
			mp = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
		if ((q->q_flag & QWANTW) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
		    (((q->q_count < q->q_lowat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
		    (q->q_mblkcnt < q->q_lowat)) || q->q_lowat == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
			q->q_flag &= ~QWANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 0
diff changeset
  2149
			backenable(q, pri);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
	} else {	/* pri != 0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
		boolean_t flushed = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
		band = pri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
		while (--band > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
		mp = qbp->qb_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
		last = qbp->qb_last->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
		 * rmvq_noenab() and freemsg() are called for each mblk that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
		 * meets the criteria.  The loop is executed until the last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
		 * mblk has been processed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
		while (mp != last) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
			ASSERT(mp->b_band == pri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
			nmp = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
			if (flag == FLUSHALL || datamsg(mp->b_datap->db_type)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
				rmvq_noenab(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
				flushed = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
			mp = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
		 * If any mblk(s) has been freed, we know that qbackenable()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
		 * will need to be called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
		if (flushed)
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 0
diff changeset
  2188
			qbackenable(q, pri);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
 * Return 1 if the queue is not full.  If the queue is full, return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
 * 0 (may not put message) and set QWANTW flag (caller wants to write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
 * to the queue).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2196
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
canput(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
	TRACE_1(TR_FAC_STREAMS_FR, TR_CANPUT_IN, "canput:%p", q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
	/* this is for loopback transports, they should not do a canput */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
	ASSERT(STRMATED(q->q_stream) || STREAM(q) == STREAM(q->q_nfsrv));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
	/* Find next forward module that has a service procedure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
	q = q->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
	if (!(q->q_flag & QFULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
		TRACE_2(TR_FAC_STREAMS_FR, TR_CANPUT_OUT, "canput:%p %d", q, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
		return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
	if (q->q_flag & QFULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
		q->q_flag |= QWANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
		TRACE_2(TR_FAC_STREAMS_FR, TR_CANPUT_OUT, "canput:%p %d", q, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
	TRACE_2(TR_FAC_STREAMS_FR, TR_CANPUT_OUT, "canput:%p %d", q, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
 * This is the new canput for use with priority bands.  Return 1 if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
 * band is not full.  If the band is full, return 0 (may not put message)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
 * and set QWANTW(QB_WANTW) flag for zero(non-zero) band (caller wants to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
 * write to the queue).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
bcanput(queue_t *q, unsigned char pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
	TRACE_2(TR_FAC_STREAMS_FR, TR_BCANPUT_IN, "bcanput:%p %p", q, pri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
	if (!q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
	/* Find next forward module that has a service procedure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2240
	q = q->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
	if (pri == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
		if (q->q_flag & QFULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
			q->q_flag |= QWANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
			TRACE_3(TR_FAC_STREAMS_FR, TR_BCANPUT_OUT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
				"bcanput:%p %X %d", q, pri, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
	} else {	/* pri != 0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
		if (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
			 * No band exists yet, so return success.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
			TRACE_3(TR_FAC_STREAMS_FR, TR_BCANPUT_OUT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
				"bcanput:%p %X %d", q, pri, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
			return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
		while (--pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
		if (qbp->qb_flag & QB_FULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
			qbp->qb_flag |= QB_WANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
			TRACE_3(TR_FAC_STREAMS_FR, TR_BCANPUT_OUT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
				"bcanput:%p %X %d", q, pri, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
	TRACE_3(TR_FAC_STREAMS_FR, TR_BCANPUT_OUT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
		"bcanput:%p %X %d", q, pri, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
 * Put a message on a queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
 * Messages are enqueued on a priority basis.  The priority classes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
 * are HIGH PRIORITY (type >= QPCTL), PRIORITY (type < QPCTL && band > 0),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
 * and B_NORMAL (type < QPCTL && band == 0).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
 * Add appropriate weighted data block sizes to queue count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
 * If queue hits high water mark then set QFULL flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
 * If QNOENAB is not set (putq is allowed to enable the queue),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
 * enable the queue only if the message is PRIORITY,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
 * or the QWANTR flag is set (indicating that the service procedure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
 * is ready to read the queue.  This implies that a service
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
 * procedure must NEVER put a high priority message back on its own
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
 * queue, as this would result in an infinite loop (!).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
putq(queue_t *q, mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
	mblk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
	qband_t *qbp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
	int mcls = (int)queclass(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
	kthread_id_t freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
	int	bytecnt = 0, mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
	 * Make sanity checks and if qband structure is not yet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
	 * allocated, do so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
	if (mcls == QPCTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
		if (bp->b_band != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
			bp->b_band = 0;		/* force to be correct */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
	} else if (bp->b_band != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
		qband_t **qbpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
		if (bp->b_band > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
			 * The qband structure for this priority band is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
			 * not on the queue yet, so we have to allocate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
			 * one on the fly.  It would be wasteful to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
			 * associate the qband structures with every
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
			 * queue when the queues are allocated.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
			 * because most queues will only need the normal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
			 * band of flow which can be described entirely
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
			 * by the queue itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
			qbpp = &q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
			while (*qbpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
			while (bp->b_band > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
				if ((*qbpp = allocband()) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
					if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
						mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
				(*qbpp)->qb_hiwat = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
				(*qbpp)->qb_lowat = q->q_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
				q->q_nband++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
		i = bp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
		while (--i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
	 * If queue is empty, add the message and initialize the pointers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
	 * Otherwise, adjust message pointers and queue pointers based on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
	 * the type of the message and where it belongs on the queue.  Some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
	 * code is duplicated to minimize the number of conditionals and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
	 * hopefully minimize the amount of time this routine takes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
	if (!q->q_first) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
		bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
		bp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
		q->q_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
		q->q_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
		if (qbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
			qbp->qb_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
			qbp->qb_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
	} else if (!qbp) {	/* bp->b_band == 0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
		 * If queue class of message is less than or equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
		 * that of the last one on the queue, tack on to the end.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
		tmp = q->q_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
		if (mcls <= (int)queclass(tmp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
			bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
			bp->b_prev = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
			tmp->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
			q->q_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
			tmp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
			while ((int)queclass(tmp) >= mcls)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
				tmp = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
			 * Insert bp before tmp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
			bp->b_next = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
			bp->b_prev = tmp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
			if (tmp->b_prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
				tmp->b_prev->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
				q->q_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
			tmp->b_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
	} else {		/* bp->b_band != 0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
		if (qbp->qb_first) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
			tmp = qbp->qb_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
			 * Insert bp after the last message in this band.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
			bp->b_next = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
			if (tmp->b_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
				tmp->b_next->b_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
				q->q_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
			bp->b_prev = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
			tmp->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
			tmp = q->q_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
			if ((mcls < (int)queclass(tmp)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
			    (bp->b_band <= tmp->b_band)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
				 * Tack bp on end of queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
				bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
				bp->b_prev = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
				tmp->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
				q->q_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
				tmp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
				while (tmp->b_datap->db_type >= QPCTL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
					tmp = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
				while (tmp->b_band >= bp->b_band)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
					tmp = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
				 * Insert bp before tmp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
				bp->b_next = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
				bp->b_prev = tmp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
				if (tmp->b_prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
					tmp->b_prev->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
					q->q_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
				tmp->b_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
			qbp->qb_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
		qbp->qb_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
	/* Get message byte count for q_count accounting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
	for (tmp = bp; tmp; tmp = tmp->b_cont) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2451
		ADD_MBLK_SIZE(tmp, bytecnt);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
		mblkcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2454
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
	if (qbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
		qbp->qb_count += bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
		qbp->qb_mblkcnt += mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
		if ((qbp->qb_count >= qbp->qb_hiwat) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
		    (qbp->qb_mblkcnt >= qbp->qb_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
			qbp->qb_flag |= QB_FULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
		q->q_count += bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
		q->q_mblkcnt += mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
		if ((q->q_count >= q->q_hiwat) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
		    (q->q_mblkcnt >= q->q_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
			q->q_flag |= QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
	STR_FTEVENT_MSG(bp, q, FTEV_PUTQ, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
	if ((mcls > QNORM) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
	    (canenable(q) && (q->q_flag & QWANTR || bp->b_band)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
		qenable_locked(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
	ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
 * Put stuff back at beginning of Q according to priority order.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
 * See comment on putq above for details.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
putbq(queue_t *q, mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
	mblk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
	qband_t *qbp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
	int mcls = (int)queclass(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
	kthread_id_t freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
	int	bytecnt = 0, mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
	ASSERT(q && bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
	ASSERT(bp->b_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
	 * Make sanity checks and if qband structure is not yet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
	 * allocated, do so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
	if (mcls == QPCTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
		if (bp->b_band != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
			bp->b_band = 0;		/* force to be correct */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
	} else if (bp->b_band != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
		qband_t **qbpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
		if (bp->b_band > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
			qbpp = &q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
			while (*qbpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
			while (bp->b_band > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
				if ((*qbpp = allocband()) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
					if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
						mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
				(*qbpp)->qb_hiwat = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
				(*qbpp)->qb_lowat = q->q_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
				q->q_nband++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
		i = bp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
		while (--i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
	 * If queue is empty or if message is high priority,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
	 * place on the front of the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
	tmp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
	if ((!tmp) || (mcls == QPCTL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
		bp->b_next = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
		if (tmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
			tmp->b_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
			q->q_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
		q->q_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
		bp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
		if (qbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
			qbp->qb_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
			qbp->qb_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
	} else if (qbp) {	/* bp->b_band != 0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
		tmp = qbp->qb_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
		if (tmp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
			 * Insert bp before the first message in this band.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
			bp->b_next = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
			bp->b_prev = tmp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
			if (tmp->b_prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
				tmp->b_prev->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
				q->q_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
			tmp->b_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
			tmp = q->q_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
			if ((mcls < (int)queclass(tmp)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
			    (bp->b_band < tmp->b_band)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
				 * Tack bp on end of queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
				bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
				bp->b_prev = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
				tmp->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
				q->q_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
				tmp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
				while (tmp->b_datap->db_type >= QPCTL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
					tmp = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
				while (tmp->b_band > bp->b_band)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
					tmp = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
				 * Insert bp before tmp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
				bp->b_next = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
				bp->b_prev = tmp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
				if (tmp->b_prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
					tmp->b_prev->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
					q->q_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
				tmp->b_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
			qbp->qb_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
		qbp->qb_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
	} else {		/* bp->b_band == 0 && !QPCTL */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
		 * If the queue class or band is less than that of the last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
		 * message on the queue, tack bp on the end of the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
		tmp = q->q_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
		if ((mcls < (int)queclass(tmp)) || (bp->b_band < tmp->b_band)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
			bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
			bp->b_prev = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
			tmp->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
			q->q_last = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2615
			tmp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2616
			while (tmp->b_datap->db_type >= QPCTL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
				tmp = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
			while (tmp->b_band > bp->b_band)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
				tmp = tmp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2621
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2622
			 * Insert bp before tmp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
			bp->b_next = tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
			bp->b_prev = tmp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
			if (tmp->b_prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
				tmp->b_prev->b_next = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
				q->q_first = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
			tmp->b_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
	/* Get message byte count for q_count accounting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
	for (tmp = bp; tmp; tmp = tmp->b_cont) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2636
		ADD_MBLK_SIZE(tmp, bytecnt);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
		mblkcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
	if (qbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
		qbp->qb_count += bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
		qbp->qb_mblkcnt += mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
		if ((qbp->qb_count >= qbp->qb_hiwat) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
		    (qbp->qb_mblkcnt >= qbp->qb_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
			qbp->qb_flag |= QB_FULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2646
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2647
		q->q_count += bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2648
		q->q_mblkcnt += mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2649
		if ((q->q_count >= q->q_hiwat) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2650
		    (q->q_mblkcnt >= q->q_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2651
			q->q_flag |= QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2652
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2653
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2655
	STR_FTEVENT_MSG(bp, q, FTEV_PUTBQ, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2656
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2657
	if ((mcls > QNORM) || (canenable(q) && (q->q_flag & QWANTR)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2658
		qenable_locked(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2659
	ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2660
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2661
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2663
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2664
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2666
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2667
 * Insert a message before an existing message on the queue.  If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2668
 * existing message is NULL, the new messages is placed on the end of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2669
 * the queue.  The queue class of the new message is ignored.  However,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2670
 * the priority band of the new message must adhere to the following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2671
 * ordering:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2672
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2673
 *	emp->b_prev->b_band >= mp->b_band >= emp->b_band.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
 * All flow control parameters are updated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
 * insq can be called with the stream frozen, but other utility functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
 * holding QLOCK, and by streams modules without any locks/frozen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
insq(queue_t *q, mblk_t *emp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
	mblk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
	qband_t *qbp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
	int mcls = (int)queclass(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
	kthread_id_t freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
	int	bytecnt = 0, mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
	} else if (MUTEX_HELD(QLOCK(q))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
		/* Don't drop lock on exit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
		freezer = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
	if (mcls == QPCTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
		if (mp->b_band != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
			mp->b_band = 0;		/* force to be correct */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
		if (emp && emp->b_prev &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
		    (emp->b_prev->b_datap->db_type < QPCTL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
			goto badord;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
	if (emp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
		if (((mcls == QNORM) && (mp->b_band < emp->b_band)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
		    (emp->b_prev && (emp->b_prev->b_datap->db_type < QPCTL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
		    (emp->b_prev->b_band < mp->b_band))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
			goto badord;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
		tmp = q->q_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
		if (tmp && (mcls == QNORM) && (mp->b_band > tmp->b_band)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
badord:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
			cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
			    "insq: attempt to insert message out of order "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
			    "on q %p", (void *)q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
			if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2720
				mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2721
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2722
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2723
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2725
	if (mp->b_band != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2726
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2727
		qband_t **qbpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2729
		if (mp->b_band > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2730
			qbpp = &q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2731
			while (*qbpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2732
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2733
			while (mp->b_band > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2734
				if ((*qbpp = allocband()) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2735
					if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2736
						mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2738
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2739
				(*qbpp)->qb_hiwat = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2740
				(*qbpp)->qb_lowat = q->q_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2741
				q->q_nband++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2742
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2743
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2744
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2745
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2746
		i = mp->b_band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2747
		while (--i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2748
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2749
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2751
	if ((mp->b_next = emp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2752
		if ((mp->b_prev = emp->b_prev) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2753
			emp->b_prev->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2754
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2755
			q->q_first = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2756
		emp->b_prev = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2757
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2758
		if ((mp->b_prev = q->q_last) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2759
			q->q_last->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2760
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2761
			q->q_first = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2762
		q->q_last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2763
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2765
	/* Get mblk and byte count for q_count accounting */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2766
	for (tmp = mp; tmp; tmp = tmp->b_cont) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2767
		ADD_MBLK_SIZE(tmp, bytecnt);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2768
		mblkcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2769
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2771
	if (qbp) {	/* adjust qband pointers and count */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2772
		if (!qbp->qb_first) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2773
			qbp->qb_first = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2774
			qbp->qb_last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2775
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2776
			if (mp->b_prev == NULL || (mp->b_prev != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2777
			    (mp->b_prev->b_band != mp->b_band)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2778
				qbp->qb_first = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2779
			else if (mp->b_next == NULL || (mp->b_next != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2780
			    (mp->b_next->b_band != mp->b_band)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2781
				qbp->qb_last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2782
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2783
		qbp->qb_count += bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2784
		qbp->qb_mblkcnt += mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2785
		if ((qbp->qb_count >= qbp->qb_hiwat) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2786
		    (qbp->qb_mblkcnt >= qbp->qb_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
			qbp->qb_flag |= QB_FULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2789
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2790
		q->q_count += bytecnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
		q->q_mblkcnt += mblkcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
		if ((q->q_count >= q->q_hiwat) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
		    (q->q_mblkcnt >= q->q_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
			q->q_flag |= QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2798
	STR_FTEVENT_MSG(mp, q, FTEV_INSQ, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2800
	if (canenable(q) && (q->q_flag & QWANTR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
		qenable_locked(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
	ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2811
 * Create and put a control message on queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
putctl(queue_t *q, int type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
	if ((datamsg(type) && (type != M_DELAY)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2819
	    (bp = allocb_tryhard(0)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
	bp->b_datap->db_type = (unsigned char) type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
	put(q, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
 * Control message with a single-byte parameter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
putctl1(queue_t *q, int type, int param)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2834
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2836
	if ((datamsg(type) && (type != M_DELAY)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
	    (bp = allocb_tryhard(1)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
	bp->b_datap->db_type = (unsigned char)type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
	*bp->b_wptr++ = (unsigned char)param;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
	put(q, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2847
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
putnextctl1(queue_t *q, int type, int param)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
	if ((datamsg(type) && (type != M_DELAY)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
		((bp = allocb_tryhard(1)) == NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
	bp->b_datap->db_type = (unsigned char)type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
	*bp->b_wptr++ = (unsigned char)param;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
	putnext(q, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2861
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2862
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
putnextctl(queue_t *q, int type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
	if ((datamsg(type) && (type != M_DELAY)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
		((bp = allocb_tryhard(0)) == NULL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
	bp->b_datap->db_type = (unsigned char)type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
	putnext(q, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2875
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2876
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2877
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2879
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
 * Return the queue upstream from this one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2881
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2882
queue_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2883
backq(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2884
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2885
	q = _OTHERQ(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2886
	if (q->q_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2887
		q = q->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2888
		return (_OTHERQ(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2889
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2890
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2891
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2892
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2893
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2894
 * Send a block back up the queue in reverse from this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2895
 * one (e.g. to respond to ioctls)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2896
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2897
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2898
qreply(queue_t *q, mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2899
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
	ASSERT(q && bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
	putnext(_OTHERQ(q), bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
 * Streams Queue Scheduling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
 * Queues are enabled through qenable() when they have messages to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
 * process.  They are serviced by queuerun(), which runs each enabled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
 * queue's service procedure.  The call to queuerun() is processor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
 * dependent - the general principle is that it be run whenever a queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
 * is enabled but before returning to user level.  For system calls,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2913
 * the function runqueues() is called if their action causes a queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
 * to be enabled.  For device interrupts, queuerun() should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
 * called before returning from the last level of interrupt.  Beyond
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
 * this, no timing assumptions should be made about queue scheduling.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
 * Enable a queue: put it on list of those whose service procedures are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
 * ready to run and set up the scheduling mechanism.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
 * The broadcast is done outside the mutex -> to avoid the woken thread
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
 * from contending with the mutex. This is OK 'cos the queue has been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
 * enqueued on the runlist and flagged safely at this point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
qenable(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2928
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
	qenable_locked(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
 * Return number of messages on queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2937
qsize(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2938
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2939
	int count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2942
	mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2943
	for (mp = qp->q_first; mp; mp = mp->b_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
		count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
	mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
	return (count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2950
 * noenable - set queue so that putq() will not enable it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
 * enableok - set queue so that putq() can enable it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
noenable(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2957
	q->q_flag |= QNOENB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2958
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2959
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2960
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2961
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2962
enableok(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2963
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2964
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2965
	q->q_flag &= ~QNOENB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2966
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2967
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2968
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2969
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2970
 * Set queue fields.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2971
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2972
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2973
strqset(queue_t *q, qfields_t what, unsigned char pri, intptr_t val)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2974
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2975
	qband_t *qbp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2976
	queue_t	*wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2977
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2978
	kthread_id_t freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2979
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2980
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2981
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2982
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2983
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2984
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2985
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2987
	if (what >= QBAD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2988
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2989
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2990
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2991
	if (pri != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2992
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2993
		qband_t **qbpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2995
		if (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2996
			qbpp = &q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2997
			while (*qbpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2998
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2999
			while (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3000
				if ((*qbpp = allocband()) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3001
					error = EAGAIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3002
					goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3003
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3004
				(*qbpp)->qb_hiwat = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3005
				(*qbpp)->qb_lowat = q->q_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3006
				q->q_nband++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3007
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3008
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3009
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3010
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3011
		i = pri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3012
		while (--i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3013
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3014
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3015
	switch (what) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3017
	case QHIWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3018
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3019
			qbp->qb_hiwat = (size_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3020
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3021
			q->q_hiwat = (size_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3022
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3024
	case QLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3025
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3026
			qbp->qb_lowat = (size_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3027
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3028
			q->q_lowat = (size_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3029
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3031
	case QMAXPSZ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3032
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3033
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3034
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3035
			q->q_maxpsz = (ssize_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3036
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3037
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3038
		 * Performance concern, strwrite looks at the module below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3039
		 * the stream head for the maxpsz each time it does a write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3040
		 * we now cache it at the stream head.  Check to see if this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3041
		 * queue is sitting directly below the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3042
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3043
		wrq = STREAM(q)->sd_wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3044
		if (q != wrq->q_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3045
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3046
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3047
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3048
		 * If the stream is not frozen drop the current QLOCK and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3049
		 * acquire the sd_wrq QLOCK which protects sd_qn_*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3050
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3051
		if (freezer != curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3052
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3053
			mutex_enter(QLOCK(wrq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3054
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3055
		ASSERT(MUTEX_HELD(QLOCK(wrq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3057
		if (strmsgsz != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3058
			if (val == INFPSZ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3059
				val = strmsgsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3060
			else  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3061
				if (STREAM(q)->sd_vnode->v_type == VFIFO)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3062
					val = MIN(PIPE_BUF, val);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3063
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3064
					val = MIN(strmsgsz, val);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3065
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3066
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3067
		STREAM(q)->sd_qn_maxpsz = val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3068
		if (freezer != curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3069
			mutex_exit(QLOCK(wrq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3070
			mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3071
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3072
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3073
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3074
	case QMINPSZ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3075
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3076
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3077
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3078
			q->q_minpsz = (ssize_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3079
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3080
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3081
		 * Performance concern, strwrite looks at the module below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3082
		 * the stream head for the maxpsz each time it does a write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3083
		 * we now cache it at the stream head.  Check to see if this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3084
		 * queue is sitting directly below the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3085
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3086
		wrq = STREAM(q)->sd_wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3087
		if (q != wrq->q_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3088
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3089
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3090
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3091
		 * If the stream is not frozen drop the current QLOCK and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3092
		 * acquire the sd_wrq QLOCK which protects sd_qn_*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3093
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3094
		if (freezer != curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3095
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3096
			mutex_enter(QLOCK(wrq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3097
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3098
		STREAM(q)->sd_qn_minpsz = (ssize_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3100
		if (freezer != curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3101
			mutex_exit(QLOCK(wrq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3102
			mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3103
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3104
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3105
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3106
	case QSTRUIOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3107
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3108
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3109
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3110
			q->q_struiot = (ushort_t)val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3111
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3113
	case QCOUNT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3114
	case QFIRST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3115
	case QLAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3116
	case QFLAG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3117
		error = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3118
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3120
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3121
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3122
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3123
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3124
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3125
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3126
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3127
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3128
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3130
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3131
 * Get queue fields.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3132
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3133
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3134
strqget(queue_t *q, qfields_t what, unsigned char pri, void *valp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3135
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3136
	qband_t 	*qbp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3137
	int 		error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3138
	kthread_id_t 	freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3140
	freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3141
	if (freezer == curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3142
		ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3143
		ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3144
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3145
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3146
	if (what >= QBAD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3147
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3148
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3149
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3150
	if (pri != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3151
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3152
		qband_t **qbpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3154
		if (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3155
			qbpp = &q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3156
			while (*qbpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3157
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3158
			while (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3159
				if ((*qbpp = allocband()) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3160
					error = EAGAIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3161
					goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3162
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3163
				(*qbpp)->qb_hiwat = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3164
				(*qbpp)->qb_lowat = q->q_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3165
				q->q_nband++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3166
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3167
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3168
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3169
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3170
		i = pri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3171
		while (--i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3172
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3173
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3174
	switch (what) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3175
	case QHIWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3176
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3177
			*(size_t *)valp = qbp->qb_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3178
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3179
			*(size_t *)valp = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3180
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3182
	case QLOWAT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3183
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3184
			*(size_t *)valp = qbp->qb_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3185
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3186
			*(size_t *)valp = q->q_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3187
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3189
	case QMAXPSZ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3190
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3191
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3192
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3193
			*(ssize_t *)valp = q->q_maxpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3194
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3196
	case QMINPSZ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3197
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3198
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3199
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3200
			*(ssize_t *)valp = q->q_minpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3201
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3203
	case QCOUNT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3204
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3205
			*(size_t *)valp = qbp->qb_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3206
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3207
			*(size_t *)valp = q->q_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3208
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3210
	case QFIRST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3211
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3212
			*(mblk_t **)valp = qbp->qb_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3213
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3214
			*(mblk_t **)valp = q->q_first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3215
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3217
	case QLAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3218
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3219
			*(mblk_t **)valp = qbp->qb_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3220
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3221
			*(mblk_t **)valp = q->q_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3222
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3224
	case QFLAG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3225
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3226
			*(uint_t *)valp = qbp->qb_flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3227
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3228
			*(uint_t *)valp = q->q_flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3229
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3231
	case QSTRUIOT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3232
		if (qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3233
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3234
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3235
			*(short *)valp = q->q_struiot;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3236
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3238
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3239
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3240
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3241
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3242
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3243
	if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3244
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3245
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3246
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3248
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3249
 * Function awakes all in cvwait/sigwait/pollwait, on one of:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3250
 *	QWANTWSYNC or QWANTR or QWANTW,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3251
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3252
 * Note: for QWANTWSYNC/QWANTW and QWANTR, if no WSLEEPer or RSLEEPer then a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3253
 *	 deferred wakeup will be done. Also if strpoll() in progress then a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3254
 *	 deferred pollwakeup will be done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3255
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3256
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3257
strwakeq(queue_t *q, int flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3258
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3259
	stdata_t 	*stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3260
	pollhead_t 	*pl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3261
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3262
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3263
	pl = &stp->sd_pollist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3264
	if (flag & QWANTWSYNC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3265
		ASSERT(!(q->q_flag & QREADR));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3266
		if (stp->sd_flag & WSLEEP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3267
			stp->sd_flag &= ~WSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3268
			cv_broadcast(&stp->sd_wrq->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3269
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3270
			stp->sd_wakeq |= WSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3271
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3273
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3274
		pollwakeup(pl, POLLWRNORM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3275
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3276
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3277
		if (stp->sd_sigflags & S_WRNORM)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3278
			strsendsig(stp->sd_siglist, S_WRNORM, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3279
	} else if (flag & QWANTR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3280
		if (stp->sd_flag & RSLEEP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3281
			stp->sd_flag &= ~RSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3282
			cv_broadcast(&_RD(stp->sd_wrq)->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3283
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3284
			stp->sd_wakeq |= RSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3285
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3287
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3288
		pollwakeup(pl, POLLIN | POLLRDNORM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3289
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3291
		{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3292
			int events = stp->sd_sigflags & (S_INPUT | S_RDNORM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3294
			if (events)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3295
				strsendsig(stp->sd_siglist, events, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3296
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3297
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3298
		if (stp->sd_flag & WSLEEP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3299
			stp->sd_flag &= ~WSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3300
			cv_broadcast(&stp->sd_wrq->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3301
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3303
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3304
		pollwakeup(pl, POLLWRNORM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3305
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3307
		if (stp->sd_sigflags & S_WRNORM)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3308
			strsendsig(stp->sd_siglist, S_WRNORM, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3309
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3310
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3311
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3312
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3313
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3314
struioget(queue_t *q, mblk_t *mp, struiod_t *dp, int noblock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3315
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3316
	stdata_t *stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3317
	int typ  = STRUIOT_STANDARD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3318
	uio_t	 *uiop = &dp->d_uio;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3319
	dblk_t	 *dbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3320
	ssize_t	 uiocnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3321
	ssize_t	 cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3322
	unsigned char *ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3323
	ssize_t	 resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3324
	int	 error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3325
	on_trap_data_t otd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3326
	queue_t	*stwrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3328
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3329
	 * Plumbing may change while taking the type so store the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3330
	 * queue in a temporary variable. It doesn't matter even
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3331
	 * if the we take the type from the previous plumbing,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3332
	 * that's because if the plumbing has changed when we were
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3333
	 * holding the queue in a temporary variable, we can continue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3334
	 * processing the message the way it would have been processed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3335
	 * in the old plumbing, without any side effects but a bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3336
	 * extra processing for partial ip header checksum.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3337
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3338
	 * This has been done to avoid holding the sd_lock which is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3339
	 * very hot.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3340
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3341
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3342
	stwrq = stp->sd_struiowrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3343
	if (stwrq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3344
		typ = stwrq->q_struiot;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3346
	for (; (resid = uiop->uio_resid) > 0 && mp; mp = mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3347
		dbp = mp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3348
		ptr = (uchar_t *)(mp->b_rptr + dbp->db_cksumstuff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3349
		uiocnt = dbp->db_cksumend - dbp->db_cksumstuff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3350
		cnt = MIN(uiocnt, uiop->uio_resid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3351
		if (!(dbp->db_struioflag & STRUIO_SPEC) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3352
		    (dbp->db_struioflag & STRUIO_DONE) || cnt == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3353
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3354
			 * Either this mblk has already been processed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3355
			 * or there is no more room in this mblk (?).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3356
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3357
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3358
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3359
		switch (typ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3360
		case STRUIOT_STANDARD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3361
			if (noblock) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3362
				if (on_trap(&otd, OT_DATA_ACCESS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3363
					no_trap();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3364
					error = EWOULDBLOCK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3365
					goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3366
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3367
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3368
			if (error = uiomove(ptr, cnt, UIO_WRITE, uiop)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3369
				if (noblock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3370
					no_trap();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3371
				goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3372
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3373
			if (noblock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3374
				no_trap();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3375
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3376
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3377
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3378
			error = EIO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3379
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3380
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3381
		dbp->db_struioflag |= STRUIO_DONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3382
		dbp->db_cksumstuff += cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3383
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3384
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3385
	if (error == EWOULDBLOCK && (resid -= uiop->uio_resid) > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3386
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3387
		 * A fault has occured and some bytes were moved to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3388
		 * current mblk, the uio_t has already been updated by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3389
		 * the appropriate uio routine, so also update the mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3390
		 * to reflect this in case this same mblk chain is used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3391
		 * again (after the fault has been handled).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3392
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3393
		uiocnt = dbp->db_cksumend - dbp->db_cksumstuff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3394
		if (uiocnt >= resid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3395
			dbp->db_cksumstuff += resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3396
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3397
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3398
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3400
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3401
 * Try to enter queue synchronously. Any attempt to enter a closing queue will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3402
 * fails. The qp->q_rwcnt keeps track of the number of successful entries so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3403
 * that removeq() will not try to close the queue while a thread is inside the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3404
 * queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3405
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3406
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3407
rwnext_enter(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3408
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3409
	mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3410
	if (qp->q_flag & QWCLOSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3411
		mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3412
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3413
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3414
	qp->q_rwcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3415
	ASSERT(qp->q_rwcnt != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3416
	mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3417
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3418
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3420
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3421
 * Decrease the count of threads running in sync stream queue and wake up any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3422
 * threads blocked in removeq().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3423
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3424
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3425
rwnext_exit(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3426
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3427
	mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3428
	qp->q_rwcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3429
	if (qp->q_flag & QWANTRMQSYNC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3430
		qp->q_flag &= ~QWANTRMQSYNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3431
		cv_broadcast(&qp->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3432
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3433
	mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3434
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3436
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3437
 * The purpose of rwnext() is to call the rw procedure of the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3438
 * (downstream) modules queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3439
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3440
 * treated as put entrypoint for perimeter syncronization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3441
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3442
 * There's no need to grab sq_putlocks here (which only exist for CIPUT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3443
 * sync queues). If it is CIPUT sync queue sq_count is incremented and it does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3444
 * not matter if any regular put entrypoints have been already entered. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3445
 * can't increment one of the sq_putcounts (instead of sq_count) because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3446
 * qwait_rw won't know which counter to decrement.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3447
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3448
 * It would be reasonable to add the lockless FASTPUT logic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3449
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3450
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3451
rwnext(queue_t *qp, struiod_t *dp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3452
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3453
	queue_t		*nqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3454
	syncq_t		*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3455
	uint16_t	count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3456
	uint16_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3457
	struct qinit	*qi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3458
	int		(*proc)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3459
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3460
	int		isread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3461
	int		rval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3463
	stp = STREAM(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3464
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3465
	 * Prevent q_next from changing by holding sd_lock until acquiring
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3466
	 * SQLOCK. Note that a read-side rwnext from the streamhead will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3467
	 * already have sd_lock acquired. In either case sd_lock is always
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3468
	 * released after acquiring SQLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3469
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3470
	 * The streamhead read-side holding sd_lock when calling rwnext is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3471
	 * required to prevent a race condition were M_DATA mblks flowing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3472
	 * up the read-side of the stream could be bypassed by a rwnext()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3473
	 * down-call. In this case sd_lock acts as the streamhead perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3474
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3475
	if ((nqp = _WR(qp)) == qp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3476
		isread = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3477
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3478
		qp = nqp->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3479
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3480
		isread = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3481
		if (nqp != stp->sd_wrq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3482
			/* Not streamhead */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3483
			mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3484
		qp = _RD(nqp->q_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3485
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3486
	qi = qp->q_qinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3487
	if (qp->q_struiot == STRUIOT_NONE || ! (proc = qi->qi_rwp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3488
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3489
		 * Not a synchronous module or no r/w procedure for this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3490
		 * queue, so just return EINVAL and let the caller handle it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3491
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3492
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3493
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3494
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3496
	if (rwnext_enter(qp) == B_FALSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3497
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3498
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3499
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3501
	sq = qp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3502
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3503
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3504
	count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3505
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3506
	ASSERT(sq->sq_ciputctrl == NULL || (flags & SQ_CIPUT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3508
	while ((flags & SQ_GOAWAY) || (!(flags & SQ_CIPUT) && count != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3509
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3510
		 * if this queue is being closed, return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3511
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3512
		if (qp->q_flag & QWCLOSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3513
			mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3514
			rwnext_exit(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3515
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3516
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3518
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3519
		 * Wait until we can enter the inner perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3520
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3521
		sq->sq_flags = flags | SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3522
		cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3523
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3524
		flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3525
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3526
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3527
	if (isread == 0 && stp->sd_struiowrq == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3528
	    isread == 1 && stp->sd_struiordq == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3529
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3530
		 * Stream plumbing changed while waiting for inner perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3531
		 * so just return EINVAL and let the caller handle it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3532
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3533
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3534
		rwnext_exit(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3535
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3536
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3537
	if (!(flags & SQ_CIPUT))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3538
		sq->sq_flags = flags | SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3539
	sq->sq_count = count + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3540
	ASSERT(sq->sq_count != 0);		/* Wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3541
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3542
	 * Note: The only message ordering guarantee that rwnext() makes is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3543
	 *	 for the write queue flow-control case. All others (r/w queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3544
	 *	 with q_count > 0 (or q_first != 0)) are the resposibilty of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3545
	 *	 the queue's rw procedure. This could be genralized here buy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3546
	 *	 running the queue's service procedure, but that wouldn't be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3547
	 *	 the most efficent for all cases.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3548
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3549
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3550
	if (! isread && (qp->q_flag & QFULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3551
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3552
		 * Write queue may be flow controlled. If so,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3553
		 * mark the queue for wakeup when it's not.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3554
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3555
		mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3556
		if (qp->q_flag & QFULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3557
			qp->q_flag |= QWANTWSYNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3558
			mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3559
			rval = EWOULDBLOCK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3560
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3561
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3562
		mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3563
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3565
	if (! isread && dp->d_mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3566
		STR_FTEVENT_MSG(dp->d_mp, nqp, FTEV_RWNEXT, dp->d_mp->b_rptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3567
		    dp->d_mp->b_datap->db_base);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3569
	rval = (*proc)(qp, dp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3570
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3571
	if (isread && dp->d_mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3572
		STR_FTEVENT_MSG(dp->d_mp, _RD(nqp), FTEV_RWNEXT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3573
		    dp->d_mp->b_rptr - dp->d_mp->b_datap->db_base);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3574
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3575
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3576
	 * The queue is protected from being freed by sq_count, so it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3577
	 * safe to call rwnext_exit and reacquire SQLOCK(sq).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3578
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3579
	rwnext_exit(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3581
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3582
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3583
	ASSERT(sq->sq_count != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3584
	sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3585
	if (flags & SQ_TAIL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3586
		putnext_tail(sq, qp, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3587
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3588
		 * The only purpose of this ASSERT is to preserve calling stack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3589
		 * in DEBUG kernel.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3590
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3591
		ASSERT(flags & SQ_TAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3592
		return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3593
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3594
	ASSERT(flags & (SQ_EXCL|SQ_CIPUT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3595
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3596
	 * Safe to always drop SQ_EXCL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3597
	 *	Not SQ_CIPUT means we set SQ_EXCL above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3598
	 *	For SQ_CIPUT SQ_EXCL will only be set if the put procedure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3599
	 *	did a qwriter(INNER) in which case nobody else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3600
	 *	is in the inner perimeter and we are exiting.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3601
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3602
	 * I would like to make the following assertion:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3603
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3604
	 * ASSERT((flags & (SQ_EXCL|SQ_CIPUT)) != (SQ_EXCL|SQ_CIPUT) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3605
	 * 	sq->sq_count == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3606
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3607
	 * which indicates that if we are both putshared and exclusive,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3608
	 * we became exclusive while executing the putproc, and the only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3609
	 * claim on the syncq was the one we dropped a few lines above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3610
	 * But other threads that enter putnext while the syncq is exclusive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3611
	 * need to make a claim as they may need to drop SQLOCK in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3612
	 * has_writers case to avoid deadlocks.  If these threads are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3613
	 * delayed or preempted, it is possible that the writer thread can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3614
	 * find out that there are other claims making the (sq_count == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3615
	 * test invalid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3616
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3618
	sq->sq_flags = flags & ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3619
	if (sq->sq_flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3620
		sq->sq_flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3621
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3622
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3623
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3624
	return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3625
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3627
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3628
 * The purpose of infonext() is to call the info procedure of the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3629
 * (downstream) modules queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3630
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3631
 * treated as put entrypoint for perimeter syncronization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3632
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3633
 * There's no need to grab sq_putlocks here (which only exist for CIPUT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3634
 * sync queues). If it is CIPUT sync queue regular sq_count is incremented and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3635
 * it does not matter if any regular put entrypoints have been already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3636
 * entered.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3637
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3638
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3639
infonext(queue_t *qp, infod_t *idp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3640
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3641
	queue_t		*nqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3642
	syncq_t		*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3643
	uint16_t	count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3644
	uint16_t 	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3645
	struct qinit	*qi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3646
	int		(*proc)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3647
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3648
	int		rval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3650
	stp = STREAM(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3651
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3652
	 * Prevent q_next from changing by holding sd_lock until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3653
	 * acquiring SQLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3654
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3655
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3656
	if ((nqp = _WR(qp)) == qp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3657
		qp = nqp->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3658
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3659
		qp = _RD(nqp->q_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3660
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3661
	qi = qp->q_qinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3662
	if (qp->q_struiot == STRUIOT_NONE || ! (proc = qi->qi_infop)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3663
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3664
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3665
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3666
	sq = qp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3667
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3668
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3669
	count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3670
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3671
	ASSERT(sq->sq_ciputctrl == NULL || (flags & SQ_CIPUT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3672
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3673
	while ((flags & SQ_GOAWAY) || (!(flags & SQ_CIPUT) && count != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3674
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3675
		 * Wait until we can enter the inner perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3676
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3677
		sq->sq_flags = flags | SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3678
		cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3679
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3680
		flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3681
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3683
	if (! (flags & SQ_CIPUT))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3684
		sq->sq_flags = flags | SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3685
	sq->sq_count = count + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3686
	ASSERT(sq->sq_count != 0);		/* Wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3687
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3689
	rval = (*proc)(qp, idp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3690
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3691
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3692
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3693
	ASSERT(sq->sq_count != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3694
	sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3695
	if (flags & SQ_TAIL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3696
		putnext_tail(sq, qp, flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3697
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3698
		 * The only purpose of this ASSERT is to preserve calling stack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3699
		 * in DEBUG kernel.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3700
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3701
		ASSERT(flags & SQ_TAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3702
		return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3703
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3704
	ASSERT(flags & (SQ_EXCL|SQ_CIPUT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3705
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3706
 * XXXX
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3707
 * I am not certain the next comment is correct here.  I need to consider
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3708
 * why the infonext is called, and if dropping SQ_EXCL unless non-CIPUT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3709
 * might cause other problems.  It just might be safer to drop it if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3710
 * !SQ_CIPUT because that is when we set it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3711
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3712
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3713
	 * Safe to always drop SQ_EXCL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3714
	 *	Not SQ_CIPUT means we set SQ_EXCL above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3715
	 *	For SQ_CIPUT SQ_EXCL will only be set if the put procedure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3716
	 *	did a qwriter(INNER) in which case nobody else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3717
	 *	is in the inner perimeter and we are exiting.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3718
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3719
	 * I would like to make the following assertion:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3720
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3721
	 * ASSERT((flags & (SQ_EXCL|SQ_CIPUT)) != (SQ_EXCL|SQ_CIPUT) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3722
	 *	sq->sq_count == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3723
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3724
	 * which indicates that if we are both putshared and exclusive,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3725
	 * we became exclusive while executing the putproc, and the only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3726
	 * claim on the syncq was the one we dropped a few lines above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3727
	 * But other threads that enter putnext while the syncq is exclusive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3728
	 * need to make a claim as they may need to drop SQLOCK in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3729
	 * has_writers case to avoid deadlocks.  If these threads are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3730
	 * delayed or preempted, it is possible that the writer thread can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3731
	 * find out that there are other claims making the (sq_count == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3732
	 * test invalid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3733
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3735
	sq->sq_flags = flags & ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3736
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3737
	return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3738
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3740
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3741
 * Return nonzero if the queue is responsible for struio(), else return 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3742
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3743
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3744
isuioq(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3745
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3746
	if (q->q_flag & QREADR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3747
		return (STREAM(q)->sd_struiordq == q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3748
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3749
		return (STREAM(q)->sd_struiowrq == q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3750
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3752
#if defined(__sparc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3753
int disable_putlocks = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3754
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3755
int disable_putlocks = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3756
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3758
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3759
 * called by create_putlock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3760
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3761
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3762
create_syncq_putlocks(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3763
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3764
	syncq_t	*sq = q->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3765
	ciputctrl_t *cip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3766
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3767
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3768
	ASSERT(sq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3769
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3770
	ASSERT(disable_putlocks == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3771
	ASSERT(n_ciputctrl >= min_n_ciputctrl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3772
	ASSERT(ciputctrl_cache != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3774
	if (!(sq->sq_type & SQ_CIPUT))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3775
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3777
	for (i = 0; i <= 1; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3778
		if (sq->sq_ciputctrl == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3779
			cip = kmem_cache_alloc(ciputctrl_cache, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3780
			SUMCHECK_CIPUTCTRL_COUNTS(cip, n_ciputctrl - 1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3781
			mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3782
			if (sq->sq_ciputctrl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3783
				mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3784
				kmem_cache_free(ciputctrl_cache, cip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3785
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3786
				ASSERT(sq->sq_nciputctrl == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3787
				sq->sq_nciputctrl = n_ciputctrl - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3788
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3789
				 * putnext checks sq_ciputctrl without holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3790
				 * SQLOCK. if it is not NULL putnext assumes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3791
				 * sq_nciputctrl is initialized. membar below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3792
				 * insures that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3793
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3794
				membar_producer();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3795
				sq->sq_ciputctrl = cip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3796
				mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3797
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3798
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3799
		ASSERT(sq->sq_nciputctrl == n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3800
		if (i == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3801
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3802
		q = _OTHERQ(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3803
		if (!(q->q_flag & QPERQ)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3804
			ASSERT(sq == q->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3805
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3806
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3807
		ASSERT(q->q_syncq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3808
		ASSERT(sq != q->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3809
		sq = q->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3810
		ASSERT(sq->sq_type & SQ_CIPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3811
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3812
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3814
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3815
 * If stream argument is 0 only create per cpu sq_putlocks/sq_putcounts for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3816
 * syncq of q. If stream argument is not 0 create per cpu stream_putlocks for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3817
 * the stream of q and per cpu sq_putlocks/sq_putcounts for all syncq's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3818
 * starting from q and down to the driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3819
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3820
 * This should be called after the affected queues are part of stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3821
 * geometry. It should be called from driver/module open routine after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3822
 * qprocson() call. It is also called from nfs syscall where it is known that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3823
 * stream is configured and won't change its geometry during create_putlock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3824
 * call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3825
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3826
 * caller normally uses 0 value for the stream argument to speed up MT putnext
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3827
 * into the perimeter of q for example because its perimeter is per module
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3828
 * (e.g. IP).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3829
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3830
 * caller normally uses non 0 value for the stream argument to hint the system
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3831
 * that the stream of q is a very contended global system stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3832
 * (e.g. NFS/UDP) and the part of the stream from q to the driver is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3833
 * particularly MT hot.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3834
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3835
 * Caller insures stream plumbing won't happen while we are here and therefore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3836
 * q_next can be safely used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3837
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3838
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3839
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3840
create_putlocks(queue_t *q, int stream)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3841
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3842
	ciputctrl_t	*cip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3843
	struct stdata	*stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3844
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3845
	q = _WR(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3846
	ASSERT(stp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3848
	if (disable_putlocks != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3849
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3850
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3851
	if (n_ciputctrl < min_n_ciputctrl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3852
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3854
	ASSERT(ciputctrl_cache != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3856
	if (stream != 0 && stp->sd_ciputctrl == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3857
		cip = kmem_cache_alloc(ciputctrl_cache, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3858
		SUMCHECK_CIPUTCTRL_COUNTS(cip, n_ciputctrl - 1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3859
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3860
		if (stp->sd_ciputctrl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3861
			mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3862
			kmem_cache_free(ciputctrl_cache, cip);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3863
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3864
			ASSERT(stp->sd_nciputctrl == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3865
			stp->sd_nciputctrl = n_ciputctrl - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3866
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3867
			 * putnext checks sd_ciputctrl without holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3868
			 * sd_lock. if it is not NULL putnext assumes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3869
			 * sd_nciputctrl is initialized. membar below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3870
			 * insures that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3871
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3872
			membar_producer();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3873
			stp->sd_ciputctrl = cip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3874
			mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3875
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3876
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3877
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3878
	ASSERT(stream == 0 || stp->sd_nciputctrl == n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3879
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3880
	while (_SAMESTR(q)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3881
		create_syncq_putlocks(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3882
		if (stream == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3883
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3884
		q = q->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3885
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3886
	ASSERT(q != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3887
	create_syncq_putlocks(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3888
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3890
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3891
 * STREAMS Flow Trace - record STREAMS Flow Trace events as an mblk flows
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3892
 * through a stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3893
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3894
 * Data currently record per event is a hrtime stamp, queue address, event
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3895
 * type, and a per type datum.  Much of the STREAMS framework is instrumented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3896
 * for automatic flow tracing (when enabled).  Events can be defined and used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3897
 * by STREAMS modules and drivers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3898
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3899
 * Global objects:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3900
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3901
 *	str_ftevent() - Add a flow-trace event to a dblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3902
 *	str_ftfree() - Free flow-trace data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3903
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3904
 * Local objects:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3905
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3906
 *	fthdr_cache - pointer to the kmem cache for trace header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3907
 *	ftblk_cache - pointer to the kmem cache for trace data blocks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3908
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3910
int str_ftnever = 1;	/* Don't do STREAMS flow tracing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3912
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3913
str_ftevent(fthdr_t *hp, void *p, ushort_t evnt, ushort_t data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3914
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3915
	ftblk_t *bp = hp->tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3916
	ftblk_t *nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3917
	ftevnt_t *ep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3918
	int ix, nix;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3919
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3920
	ASSERT(hp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3922
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3923
		if ((ix = bp->ix) == FTBLK_EVNTS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3924
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3925
			 * Tail doesn't have room, so need a new tail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3926
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3927
			 * To make this MT safe, first, allocate a new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3928
			 * ftblk, and initialize it.  To make life a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3929
			 * little easier, reserve the first slot (mostly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3930
			 * by making ix = 1).  When we are finished with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3931
			 * the initialization, CAS this pointer to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3932
			 * tail.  If this succeeds, this is the new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3933
			 * "next" block.  Otherwise, another thread
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3934
			 * got here first, so free the block and start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3935
			 * again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3936
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3937
			if (!(nbp = kmem_cache_alloc(ftblk_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3938
			    KM_NOSLEEP))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3939
				/* no mem, so punt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3940
				str_ftnever++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3941
				/* free up all flow data? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3942
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3943
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3944
			nbp->nxt = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3945
			nbp->ix = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3946
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3947
			 * Just in case there is another thread about
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3948
			 * to get the next index, we need to make sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3949
			 * the value is there for it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3950
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3951
			membar_producer();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3952
			if (casptr(&hp->tail, bp, nbp) == bp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3953
				/* CAS was successful */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3954
				bp->nxt = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3955
				membar_producer();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3956
				bp = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3957
				ix = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3958
				goto cas_good;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3959
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3960
				kmem_cache_free(ftblk_cache, nbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3961
				bp = hp->tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3962
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3963
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3964
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3965
		nix = ix + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3966
		if (cas32((uint32_t *)&bp->ix, ix, nix) == ix) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3967
		cas_good:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3968
			if (curthread != hp->thread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3969
				hp->thread = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3970
				evnt |= FTEV_CS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3971
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3972
			if (CPU->cpu_seqid != hp->cpu_seqid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3973
				hp->cpu_seqid = CPU->cpu_seqid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3974
				evnt |= FTEV_PS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3975
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3976
			ep = &bp->ev[ix];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3977
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3978
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3979
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3981
	if (evnt & FTEV_QMASK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3982
		queue_t *qp = p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3983
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3984
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3985
		 * It is possible that the module info is broke
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3986
		 * (as is logsubr.c at this comment writing).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3987
		 * Instead of panicing or doing other unmentionables,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3988
		 * we shall put a dummy name as the mid, and continue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3989
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3990
		if (qp->q_qinfo == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3991
			ep->mid = "NONAME";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3992
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3993
			ep->mid = qp->q_qinfo->qi_minfo->mi_idname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3995
		if (!(qp->q_flag & QREADR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3996
			evnt |= FTEV_ISWR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3997
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3998
		ep->mid = (char *)p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3999
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4001
	ep->ts = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4002
	ep->evnt = evnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4003
	ep->data = data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4004
	hp->hash = (hp->hash << 9) + hp->hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4005
	hp->hash += (evnt << 16) | data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4006
	hp->hash += (uintptr_t)ep->mid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4007
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4009
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4010
 * Free flow-trace data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4011
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4012
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4013
str_ftfree(dblk_t *dbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4014
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4015
	fthdr_t *hp = dbp->db_fthdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4016
	ftblk_t *bp = &hp->first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4017
	ftblk_t *nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4019
	if (bp != hp->tail || bp->ix != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4020
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4021
		 * Clear out the hash, have the tail point to itself, and free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4022
		 * any continuation blocks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4023
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4024
		bp = hp->first.nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4025
		hp->tail = &hp->first;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4026
		hp->hash = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4027
		hp->first.nxt = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4028
		hp->first.ix = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4029
		while (bp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4030
			nbp = bp->nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4031
			kmem_cache_free(ftblk_cache, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4032
			bp = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4033
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4034
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4035
	kmem_cache_free(fthdr_cache, hp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4036
	dbp->db_fthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4037
}