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