usr/src/uts/common/os/strsubr.c
author masputra
Sat, 22 Oct 2005 22:50:14 -0700
changeset 741 40027a3621ac
parent 577 65796fd3c2db
child 898 64b2a371a6bd
permissions -rw-r--r--
PSARC 2005/082 Yosemite: UDP Performance Enhancement 4796051 Solaris needs a more complete HW checksumming support 4905227 duplicate macros in ipclassifier.h and ip.h 4915681 need hardware checksum offload for the case of IP/UDP reassembly 6201076 outbound flow-control dysfunctional, ip to ce using mdt 6223331 ipv6 flow control may corrupt UDP packets 6223809 16-bit aligned IP header should be allowed for all x86 platforms 6275398 Galaxy hangs when running lmbench 6281836 Yosemite project integration into Solaris 6281885 xge needs to support IPv6 checksum offload 6282776 IPv6 NCE fast path is not created for incoming solicitation 6304890 IP transmit-side checksum logic needs to be tightened 6304902 IP6_IN_NOCKSUM is obsolete and should be torched 6304904 UDP should reject TI_GETPEERNAME for non-connected endpoint 6306768 IP and UDP device and module definitions need to be centralized
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
/*	  All Rights Reserved  	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/signal.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/proc.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/conf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/cred.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/user.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/vnode.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/file.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/session.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/stream.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/strsubr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/stropts.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <sys/poll.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/cpuvar.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/uio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/priocntl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <sys/procset.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <sys/vmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <sys/bitmap.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <sys/siginfo.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <sys/vtrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <sys/callb.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <sys/modctl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <sys/vmsystm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <vm/page.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <sys/atomic.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#include <sys/suntpi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <sys/strlog.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <sys/promif.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
#include <sys/project.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <sys/vm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
#include <sys/taskq.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <sys/sunddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
#include <sys/sunldi_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#include <sys/strsun.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
#include <sys/isa_defs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#include <sys/multidata.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
#include <sys/pattr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
#include <sys/strft.h>
560
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
    79
#include <sys/fs/snode.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
#include <sys/zone.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
#define	O_SAMESTR(q)	(((q)->q_next) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
	(((q)->q_flag & QREADR) == ((q)->q_next->q_flag & QREADR)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 * WARNING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 * The variables and routines in this file are private, belonging
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 * to the STREAMS subsystem. These should not be used by modules
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 * or drivers. Compatibility will not be guaranteed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
 * Id value used to distinguish between different multiplexor links.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
static int32_t lnk_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
#define	STREAMS_LOPRI MINCLSYSPRI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
static pri_t streams_lopri = STREAMS_LOPRI;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
#define	STRSTAT(x)	(str_statistics.x.value.ui64++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
typedef struct str_stat {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
	kstat_named_t	sqenables;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
	kstat_named_t	stenables;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
	kstat_named_t	syncqservice;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
	kstat_named_t	freebs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
	kstat_named_t	qwr_outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
	kstat_named_t	rservice;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
	kstat_named_t	strwaits;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
	kstat_named_t	taskqfails;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
	kstat_named_t	bufcalls;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
	kstat_named_t	qhelps;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
	kstat_named_t	qremoved;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
	kstat_named_t	sqremoved;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
	kstat_named_t	bcwaits;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	kstat_named_t	sqtoomany;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
} str_stat_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
static str_stat_t str_statistics = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
	{ "sqenables",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
	{ "stenables",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	{ "syncqservice",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	{ "freebs",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
	{ "qwr_outer",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
	{ "rservice",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
	{ "strwaits",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	{ "taskqfails",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
	{ "bufcalls",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
	{ "qhelps",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	{ "qremoved",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
	{ "sqremoved",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
	{ "bcwaits",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
	{ "sqtoomany",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
static kstat_t *str_kstat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 * qrunflag was used previously to control background scheduling of queues. It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 * is not used anymore, but kept here in case some module still wants to access
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
 * it via qready() and setqsched macros.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
char qrunflag;			/*  Unused */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
 * Most of the streams scheduling is done via task queues. Task queues may fail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
 * for non-sleep dispatches, so there are two backup threads servicing failed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
 * requests for queues and syncqs. Both of these threads also service failed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
 * dispatches freebs requests. Queues are put in the list specified by `qhead'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
 * and `qtail' pointers, syncqs use `sqhead' and `sqtail' pointers and freebs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 * requests are put into `freebs_list' which has no tail pointer. All three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
 * lists are protected by a single `service_queue' lock and use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
 * `services_to_run' condition variable for signaling background threads. Use of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
 * a single lock should not be a problem because it is only used under heavy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
 * loads when task queues start to fail and at that time it may be a good idea
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
 * to throttle scheduling requests.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
 * NOTE: queues and syncqs should be scheduled by two separate threads because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
 * queue servicing may be blocked waiting for a syncq which may be also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
 * scheduled for background execution. This may create a deadlock when only one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
 * thread is used for both.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
static taskq_t *streams_taskq;		/* Used for most STREAMS scheduling */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
static kmutex_t service_queue;		/* protects all of servicing vars */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
static kcondvar_t services_to_run;	/* wake up background service thread */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
static kcondvar_t syncqs_to_run;	/* wake up background service thread */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
 * List of queues scheduled for background processing dueue to lack of resources
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
 * in the task queues. Protected by service_queue lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
static struct queue *qhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
static struct queue *qtail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
 * Same list for syncqs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
static syncq_t *sqhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
static syncq_t *sqtail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
static mblk_t *freebs_list;	/* list of buffers to free */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
 * Backup threads for servicing queues and syncqs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
kthread_t *streams_qbkgrnd_thread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
kthread_t *streams_sqbkgrnd_thread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
 * Bufcalls related variables.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
struct bclist	strbcalls;	/* list of waiting bufcalls */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
kmutex_t	strbcall_lock;	/* protects bufcall list (strbcalls) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
kcondvar_t	strbcall_cv;	/* Signaling when a bufcall is added */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
kmutex_t	bcall_monitor;	/* sleep/wakeup style monitor */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
kcondvar_t	bcall_cv;	/* wait 'till executing bufcall completes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
kthread_t	*bc_bkgrnd_thread; /* Thread to service bufcall requests */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
kmutex_t	strresources;	/* protects global resources */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
kmutex_t	muxifier;	/* single-threads multiplexor creation */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
extern void	time_to_wait(clock_t *, clock_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
 * run_queues is no longer used, but is kept in case some 3-d party
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
 * module/driver decides to use it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
int run_queues = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
 * sq_max_size is the depth of the syncq (in number of messages) before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
 * qfill_syncq() starts QFULL'ing destination queues. As its primary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
 * consumer - IP is no longer D_MTPERMOD, but there may be other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
 * modules/drivers depend on this syncq flow control, we prefer to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
 * choose a large number as the default value. For potential
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
 * performance gain, this value is tunable in /etc/system.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
int sq_max_size = 10000;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
 * the number of ciputctrl structures per syncq and stream we create when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
 * needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
int n_ciputctrl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
int max_n_ciputctrl = 16;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
 * if n_ciputctrl is < min_n_ciputctrl don't even create ciputctrl_cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
int min_n_ciputctrl = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
static struct mux_node *mux_nodes;	/* mux info for cycle checking */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
 * Per-driver/module syncqs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
 * ========================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
 * For drivers/modules that use PERMOD or outer syncqs we keep a list of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
 * perdm structures, new entries being added (and new syncqs allocated) when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
 * setq() encounters a module/driver with a streamtab that it hasn't seen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
 * before.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
 * The reason for this mechanism is that some modules and drivers share a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
 * common streamtab and it is necessary for those modules and drivers to also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
 * share a common PERMOD syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
 * perdm_list --> dm_str == streamtab_1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
 *                dm_sq == syncq_1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
 *                dm_ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
 *                dm_next --> dm_str == streamtab_2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
 *                            dm_sq == syncq_2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
 *                            dm_ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
 *                            dm_next --> ... NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
 * The dm_ref field is incremented for each new driver/module that takes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
 * a reference to the perdm structure and hence shares the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
 * References are held in the fmodsw_impl_t structure for each STREAMS module
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
 * or the dev_impl array (indexed by device major number) for each driver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
 * perdm_list -> [dm_ref == 1] -> [dm_ref == 2] -> [dm_ref == 1] -> NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
 *		     ^                 ^ ^               ^
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
 *                   |  ______________/  |               |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
 *                   | /                 |               |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
 * dev_impl:     ...|x|y|...          module A	      module B
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
 * When a module/driver is unloaded the reference count is decremented and,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
 * when it falls to zero, the perdm structure is removed from the list and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
 * the syncq is freed (see rele_dm()).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
perdm_t *perdm_list = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
static krwlock_t perdm_rwlock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
cdevsw_impl_t *devimpl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
extern struct qinit strdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
extern struct qinit stwdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
static void runservice(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
static void streams_bufcall_service(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
static void streams_qbkgrnd_service(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
static void streams_sqbkgrnd_service(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
static syncq_t *new_syncq(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
static void free_syncq(syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
static void outer_insert(syncq_t *, syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
static void outer_remove(syncq_t *, syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
static void write_now(syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
static void clr_qfull(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
static void enable_svc(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
static void runbufcalls(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
static void sqenable(syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
static void sqfill_events(syncq_t *, queue_t *, mblk_t *, void (*)());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
static void wait_q_syncq(queue_t *);
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
   291
static void backenable_insertedq(queue_t *);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
static void queue_service(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
static void stream_service(stdata_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
static void syncq_service(syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
static void qwriter_outer_service(syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
static void mblk_free(mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
static int qprocsareon(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
static void set_nfsrv_ptr(queue_t *, queue_t *, queue_t *, queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
static void reset_nfsrv_ptr(queue_t *, queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
static void sq_run_events(syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
static int propagate_syncq(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
static void	blocksq(syncq_t *, ushort_t, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
static void	unblocksq(syncq_t *, ushort_t, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
static int	dropsq(syncq_t *, uint16_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
static void	emptysq(syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
static sqlist_t *sqlist_alloc(struct stdata *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
static void	sqlist_free(sqlist_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
static sqlist_t	*sqlist_build(queue_t *, struct stdata *, boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
static void	sqlist_insert(sqlist_t *, syncq_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
static void	sqlist_insertall(sqlist_t *, queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
static void	strsetuio(stdata_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
struct kmem_cache *stream_head_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
struct kmem_cache *queue_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
struct kmem_cache *syncq_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
struct kmem_cache *qband_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
struct kmem_cache *linkinfo_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
struct kmem_cache *ciputctrl_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
static linkinfo_t *linkinfo_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
 *  Qinit structure and Module_info structures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
 *	for passthru read and write queues
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
static void pass_wput(queue_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
static queue_t *link_addpassthru(stdata_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
static void link_rempassthru(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
struct  module_info passthru_info = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
	0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
	"passthru",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
	0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
	INFPSZ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
	STRHIGH,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
	STRLOW
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
struct  qinit passthru_rinit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
	(int (*)())putnext,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
	&passthru_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
	NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
struct  qinit passthru_winit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
	(int (*)()) pass_wput,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
	NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
	&passthru_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
	NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
 * Special form of assertion: verify that X implies Y i.e. when X is true Y
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
 * should also be true.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
#define	IMPLY(X, Y)	ASSERT(!(X) || (Y))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
 * Logical equivalence. Verify that both X and Y are either TRUE or FALSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
#define	EQUIV(X, Y)	{ IMPLY(X, Y); IMPLY(Y, X); }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
 * Verify correctness of list head/tail pointers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
#define	LISTCHECK(head, tail, link) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	EQUIV(head, tail);					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
	IMPLY(tail != NULL, tail->link == NULL);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
 * Enqueue a list element `el' in the end of a list denoted by `head' and `tail'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
 * using a `link' field.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
#define	ENQUEUE(el, head, tail, link) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	ASSERT(el->link == NULL);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
	LISTCHECK(head, tail, link);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
	if (head == NULL)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
		head = el;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
	else							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
		tail->link = el;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	tail = el;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
 * Dequeue the first element of the list denoted by `head' and `tail' pointers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
 * using a `link' field and put result into `el'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
#define	DQ(el, head, tail, link) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
	LISTCHECK(head, tail, link);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
	el = head;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
	if (head != NULL) {					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
		head = head->link;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
		if (head == NULL)				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
			tail = NULL;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
		el->link = NULL;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
	}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
 * Remove `el' from the list using `chase' and `curr' pointers and return result
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
 * in `succeed'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
#define	RMQ(el, head, tail, link, chase, curr, succeed) {	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
	LISTCHECK(head, tail, link);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
	chase = NULL;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
	succeed = 0;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
	for (curr = head; (curr != el) && (curr != NULL); curr = curr->link) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
		chase = curr;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
	if (curr != NULL) {					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
		succeed = 1;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
		ASSERT(curr == el);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
		if (chase != NULL)				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
			chase->link = curr->link;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
		else						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
			head = curr->link;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
		curr->link = NULL;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
		if (curr == tail)				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
			tail = chase;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
	}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
	LISTCHECK(head, tail, link);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
/* Handling of delayed messages on the inner syncq. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
 * DEBUG versions should use function versions (to simplify tracing) and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
 * non-DEBUG kernels should use macro versions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
 * Put a queue on the syncq list of queues.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
 * Assumes SQLOCK held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
#define	SQPUT_Q(sq, qp)							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
{									\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
	ASSERT(MUTEX_HELD(SQLOCK(sq)));					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
	if (!(qp->q_sqflags & Q_SQQUEUED)) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
		/* The queue should not be linked anywhere */		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
		ASSERT((qp->q_sqprev == NULL) && (qp->q_sqnext == NULL)); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
		/* Head and tail may only be NULL simultaneously */	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
		EQUIV(sq->sq_head, sq->sq_tail);			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
		/* Queue may be only enqueyed on its syncq */		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
		ASSERT(sq == qp->q_syncq);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
		/* Check the correctness of SQ_MESSAGES flag */		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
		EQUIV(sq->sq_head, (sq->sq_flags & SQ_MESSAGES));	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
		/* Sanity check first/last elements of the list */	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
		IMPLY(sq->sq_head != NULL, sq->sq_head->q_sqprev == NULL);\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
		IMPLY(sq->sq_tail != NULL, sq->sq_tail->q_sqnext == NULL);\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
		/*							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
		 * Sanity check of priority field: empty queue should	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
		 * have zero priority					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
		 * and nqueues equal to zero.				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
		 */							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
		IMPLY(sq->sq_head == NULL, sq->sq_pri == 0);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
		/* Sanity check of sq_nqueues field */			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
		EQUIV(sq->sq_head, sq->sq_nqueues);			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
		if (sq->sq_head == NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
			sq->sq_head = sq->sq_tail = qp;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
			sq->sq_flags |= SQ_MESSAGES;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
		} else if (qp->q_spri == 0) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
			qp->q_sqprev = sq->sq_tail;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
			sq->sq_tail->q_sqnext = qp;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
			sq->sq_tail = qp;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
			/*						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
			 * Put this queue in priority order: higher	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
			 * priority gets closer to the head.		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
			 */						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
			queue_t **qpp = &sq->sq_tail;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
			queue_t *qnext = NULL;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
									\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
			while (*qpp != NULL && qp->q_spri > (*qpp)->q_spri) { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
				qnext = *qpp;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
				qpp = &(*qpp)->q_sqprev;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
			qp->q_sqnext = qnext;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
			qp->q_sqprev = *qpp;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
			if (*qpp != NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
				(*qpp)->q_sqnext = qp;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
			} else {					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
				sq->sq_head = qp;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
				sq->sq_pri = sq->sq_head->q_spri;	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
			*qpp = qp;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
		qp->q_sqflags |= Q_SQQUEUED;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
		qp->q_sqtstamp = lbolt;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
		sq->sq_nqueues++;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
	}								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
 * Remove a queue from the syncq list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
 * Assumes SQLOCK held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
#define	SQRM_Q(sq, qp)							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
	{								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
		ASSERT(MUTEX_HELD(SQLOCK(sq)));				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
		ASSERT(qp->q_sqflags & Q_SQQUEUED);			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
		ASSERT(sq->sq_head != NULL && sq->sq_tail != NULL);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		ASSERT((sq->sq_flags & SQ_MESSAGES) != 0);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
		/* Check that the queue is actually in the list */	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
		ASSERT(qp->q_sqnext != NULL || sq->sq_tail == qp);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
		ASSERT(qp->q_sqprev != NULL || sq->sq_head == qp);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
		ASSERT(sq->sq_nqueues != 0);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
		if (qp->q_sqprev == NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
			/* First queue on list, make head q_sqnext */	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
			sq->sq_head = qp->q_sqnext;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
			/* Make prev->next == next */			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
			qp->q_sqprev->q_sqnext = qp->q_sqnext;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
		if (qp->q_sqnext == NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
			/* Last queue on list, make tail sqprev */	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
			sq->sq_tail = qp->q_sqprev;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
			/* Make next->prev == prev */			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
			qp->q_sqnext->q_sqprev = qp->q_sqprev;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		/* clear out references on this queue */		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		qp->q_sqprev = qp->q_sqnext = NULL;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
		qp->q_sqflags &= ~Q_SQQUEUED;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		/* If there is nothing queued, clear SQ_MESSAGES */	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
		if (sq->sq_head != NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
			sq->sq_pri = sq->sq_head->q_spri;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
		} else	{						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
			sq->sq_flags &= ~SQ_MESSAGES;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
			sq->sq_pri = 0;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
		sq->sq_nqueues--;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
		ASSERT(sq->sq_head != NULL || sq->sq_evhead != NULL ||	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
		    (sq->sq_flags & SQ_QUEUED) == 0);			\
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
/* Hide the definition from the header file. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
#ifdef SQPUT_MP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
#undef SQPUT_MP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
 * Put a message on the queue syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
 * Assumes QLOCK held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
#define	SQPUT_MP(qp, mp)						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
	{								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
		ASSERT(MUTEX_HELD(QLOCK(qp)));				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
		ASSERT(qp->q_sqhead == NULL ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
		    (qp->q_sqtail != NULL &&				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
		    qp->q_sqtail->b_next == NULL));			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
		qp->q_syncqmsgs++;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
		ASSERT(qp->q_syncqmsgs != 0);	/* Wraparound */	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
		if (qp->q_sqhead == NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
			qp->q_sqhead = qp->q_sqtail = mp;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
			qp->q_sqtail->b_next = mp;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
			qp->q_sqtail = mp;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
		ASSERT(qp->q_syncqmsgs > 0);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
#define	SQ_PUTCOUNT_SETFAST_LOCKED(sq) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
		ASSERT(MUTEX_HELD(SQLOCK(sq)));				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
		if ((sq)->sq_ciputctrl != NULL) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
			int i;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
			int nlocks = (sq)->sq_nciputctrl;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
			ciputctrl_t *cip = (sq)->sq_ciputctrl;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
			ASSERT((sq)->sq_type & SQ_CIPUT);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
			for (i = 0; i <= nlocks; i++) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
				ASSERT(MUTEX_HELD(&cip[i].ciputctrl_lock)); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
				cip[i].ciputctrl_count |= SQ_FASTPUT;	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
#define	SQ_PUTCOUNT_CLRFAST_LOCKED(sq) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
		ASSERT(MUTEX_HELD(SQLOCK(sq)));				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
		if ((sq)->sq_ciputctrl != NULL) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
			int i;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
			int nlocks = (sq)->sq_nciputctrl;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
			ciputctrl_t *cip = (sq)->sq_ciputctrl;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
			ASSERT((sq)->sq_type & SQ_CIPUT);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
			for (i = 0; i <= nlocks; i++) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
				ASSERT(MUTEX_HELD(&cip[i].ciputctrl_lock)); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
				cip[i].ciputctrl_count &= ~SQ_FASTPUT;	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
		}							\
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
 * Run service procedures for all queues in the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
#define	STR_SERVICE(stp, q) {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
	ASSERT(MUTEX_HELD(&stp->sd_qlock));				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
	while (stp->sd_qhead != NULL) {					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
		DQ(q, stp->sd_qhead, stp->sd_qtail, q_link);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
		ASSERT(stp->sd_nqueues > 0);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
		stp->sd_nqueues--;					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
		ASSERT(!(q->q_flag & QINSERVICE));			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
		mutex_exit(&stp->sd_qlock);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
		queue_service(q);					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
		mutex_enter(&stp->sd_qlock);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
	}								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
	ASSERT(stp->sd_nqueues == 0);					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
	ASSERT((stp->sd_qhead == NULL) && (stp->sd_qtail == NULL));	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
}
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
 * constructor/destructor routines for the stream head cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
stream_head_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
	stdata_t *stp = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
	mutex_init(&stp->sd_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
	mutex_init(&stp->sd_reflock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
	mutex_init(&stp->sd_qlock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
	cv_init(&stp->sd_monitor, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
	cv_init(&stp->sd_iocmonitor, NULL, CV_DEFAULT, NULL);
166
519e5268bee7 4657000 releasestr() should only wakeup waiters when sq_refcnt is zero.
xy158873
parents: 0
diff changeset
   638
	cv_init(&stp->sd_refmonitor, NULL, CV_DEFAULT, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
	cv_init(&stp->sd_qcv, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
	cv_init(&stp->sd_zcopy_wait, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
	stp->sd_wrq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
stream_head_destructor(void *buf, void *cdrarg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
	stdata_t *stp = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
	mutex_destroy(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
	mutex_destroy(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
	mutex_destroy(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
	cv_destroy(&stp->sd_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	cv_destroy(&stp->sd_iocmonitor);
166
519e5268bee7 4657000 releasestr() should only wakeup waiters when sq_refcnt is zero.
xy158873
parents: 0
diff changeset
   657
	cv_destroy(&stp->sd_refmonitor);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
	cv_destroy(&stp->sd_qcv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
	cv_destroy(&stp->sd_zcopy_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
 * constructor/destructor routines for the queue cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
queue_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	queinfo_t *qip = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
	queue_t *qp = &qip->qu_rqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
	queue_t *wqp = &qip->qu_wqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
	syncq_t	*sq = &qip->qu_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	qp->q_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
	qp->q_link = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	qp->q_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	qp->q_mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
	qp->q_sqhead = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	qp->q_sqtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	qp->q_sqnext = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
	qp->q_sqprev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
	qp->q_sqflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
	qp->q_rwcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
	qp->q_spri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
	mutex_init(QLOCK(qp), NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
	cv_init(&qp->q_wait, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
	wqp->q_first = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
	wqp->q_link = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
	wqp->q_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
	wqp->q_mblkcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
	wqp->q_sqhead = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
	wqp->q_sqtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
	wqp->q_sqnext = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
	wqp->q_sqprev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
	wqp->q_sqflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
	wqp->q_rwcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
	wqp->q_spri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
	mutex_init(QLOCK(wqp), NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
	cv_init(&wqp->q_wait, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
	sq->sq_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
	sq->sq_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
	sq->sq_evhead = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
	sq->sq_evtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
	sq->sq_callbpend = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
	sq->sq_outer = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
	sq->sq_onext = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
	sq->sq_oprev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
	sq->sq_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
	sq->sq_svcflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
	sq->sq_servcount = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
	sq->sq_needexcl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
	sq->sq_nqueues = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
	sq->sq_pri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	mutex_init(&sq->sq_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
	cv_init(&sq->sq_wait, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
	cv_init(&sq->sq_exitwait, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
queue_destructor(void *buf, void *cdrarg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	queinfo_t *qip = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
	queue_t *qp = &qip->qu_rqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
	queue_t *wqp = &qip->qu_wqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
	syncq_t	*sq = &qip->qu_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
	ASSERT(qp->q_sqhead == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
	ASSERT(wqp->q_sqhead == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
	ASSERT(qp->q_sqnext == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
	ASSERT(wqp->q_sqnext == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
	ASSERT(qp->q_rwcnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	ASSERT(wqp->q_rwcnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	mutex_destroy(&qp->q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	cv_destroy(&qp->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	mutex_destroy(&wqp->q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
	cv_destroy(&wqp->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
	mutex_destroy(&sq->sq_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
	cv_destroy(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
	cv_destroy(&sq->sq_exitwait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
 * constructor/destructor routines for the syncq cache
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
syncq_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
	syncq_t	*sq = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
	bzero(buf, sizeof (syncq_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
	mutex_init(&sq->sq_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
	cv_init(&sq->sq_wait, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
	cv_init(&sq->sq_exitwait, NULL, CV_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
syncq_destructor(void *buf, void *cdrarg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
	syncq_t	*sq = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
	ASSERT(sq->sq_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
	ASSERT(sq->sq_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
	ASSERT(sq->sq_evhead == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
	ASSERT(sq->sq_evtail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
	ASSERT(sq->sq_callbpend == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
	ASSERT(sq->sq_callbflags == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
	ASSERT(sq->sq_outer == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
	ASSERT(sq->sq_onext == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
	ASSERT(sq->sq_oprev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
	ASSERT(sq->sq_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
	ASSERT(sq->sq_needexcl == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
	ASSERT(sq->sq_svcflags == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	ASSERT(sq->sq_servcount == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
	ASSERT(sq->sq_nqueues == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	ASSERT(sq->sq_pri == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
	ASSERT(sq->sq_count == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
	ASSERT(sq->sq_rmqcount == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
	ASSERT(sq->sq_cancelid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
	ASSERT(sq->sq_ciputctrl == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
	ASSERT(sq->sq_nciputctrl == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
	ASSERT(sq->sq_type == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
	ASSERT(sq->sq_flags == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
	mutex_destroy(&sq->sq_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
	cv_destroy(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
	cv_destroy(&sq->sq_exitwait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
ciputctrl_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
	ciputctrl_t *cip = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
	for (i = 0; i < n_ciputctrl; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
		cip[i].ciputctrl_count = SQ_FASTPUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
		mutex_init(&cip[i].ciputctrl_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
ciputctrl_destructor(void *buf, void *cdrarg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	ciputctrl_t *cip = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	for (i = 0; i < n_ciputctrl; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
		ASSERT(cip[i].ciputctrl_count & SQ_FASTPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
		mutex_destroy(&cip[i].ciputctrl_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
 * Init routine run from main at boot time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
strinit(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
	int ncpus = ((boot_max_ncpus == -1) ? max_ncpus : boot_max_ncpus);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
	 * Set up mux_node structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
	mux_nodes = kmem_zalloc((sizeof (struct mux_node) * devcnt), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
	for (i = 0; i < devcnt; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
		mux_nodes[i].mn_imaj = i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	stream_head_cache = kmem_cache_create("stream_head_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
		sizeof (stdata_t), 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
		stream_head_constructor, stream_head_destructor, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
		NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
	queue_cache = kmem_cache_create("queue_cache", sizeof (queinfo_t), 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
		queue_constructor, queue_destructor, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
	syncq_cache = kmem_cache_create("syncq_cache", sizeof (syncq_t), 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
		syncq_constructor, syncq_destructor, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
	qband_cache = kmem_cache_create("qband_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
		sizeof (qband_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
	linkinfo_cache = kmem_cache_create("linkinfo_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
		sizeof (linkinfo_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
	n_ciputctrl = ncpus;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
	n_ciputctrl = 1 << highbit(n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
	ASSERT(n_ciputctrl >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
	n_ciputctrl = MIN(n_ciputctrl, max_n_ciputctrl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
	if (n_ciputctrl >= min_n_ciputctrl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
		ciputctrl_cache = kmem_cache_create("ciputctrl_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
			sizeof (ciputctrl_t) * n_ciputctrl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
			sizeof (ciputctrl_t), ciputctrl_constructor,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
			ciputctrl_destructor, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
	streams_taskq = system_taskq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
	if (streams_taskq == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
		panic("strinit: no memory for streams taskq!");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
	bc_bkgrnd_thread = thread_create(NULL, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
	    streams_bufcall_service, NULL, 0, &p0, TS_RUN, streams_lopri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
	streams_qbkgrnd_thread = thread_create(NULL, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
	    streams_qbkgrnd_service, NULL, 0, &p0, TS_RUN, streams_lopri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
	streams_sqbkgrnd_thread = thread_create(NULL, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
	    streams_sqbkgrnd_service, NULL, 0, &p0, TS_RUN, streams_lopri);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
	 * Create STREAMS kstats.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
	str_kstat = kstat_create("streams", 0, "strstat",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
	    "net", KSTAT_TYPE_NAMED,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
	    sizeof (str_statistics) / sizeof (kstat_named_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
	    KSTAT_FLAG_VIRTUAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
	if (str_kstat != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
		str_kstat->ks_data = &str_statistics;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
		kstat_install(str_kstat);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
	}
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
	 * TPI support routine initialisation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
	tpi_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
str_sendsig(vnode_t *vp, int event, uchar_t band, int error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
	struct stdata *stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
	ASSERT(vp->v_stream);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
	stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
	/* Have to hold sd_lock to prevent siglist from changing */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
	if (stp->sd_sigflags & event)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
		strsendsig(stp->sd_siglist, event, band, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
 * Send the "sevent" set of signals to a process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
 * This might send more than one signal if the process is registered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
 * for multiple events. The caller should pass in an sevent that only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
 * includes the events for which the process has registered.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
dosendsig(proc_t *proc, int events, int sevent, k_siginfo_t *info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
	uchar_t band, int error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
	ASSERT(MUTEX_HELD(&proc->p_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
	info->si_band = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
	info->si_errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
	if (sevent & S_ERROR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
		sevent &= ~S_ERROR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
		info->si_code = POLL_ERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
		info->si_errno = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
		TRACE_2(TR_FAC_STREAMS_FR, TR_STRSENDSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
			"strsendsig:proc %p info %p", proc, info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
		sigaddq(proc, NULL, info, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
		info->si_errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
	if (sevent & S_HANGUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
		sevent &= ~S_HANGUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
		info->si_code = POLL_HUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
		TRACE_2(TR_FAC_STREAMS_FR, TR_STRSENDSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
			"strsendsig:proc %p info %p", proc, info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
		sigaddq(proc, NULL, info, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
	if (sevent & S_HIPRI) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
		sevent &= ~S_HIPRI;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
		info->si_code = POLL_PRI;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
		TRACE_2(TR_FAC_STREAMS_FR, TR_STRSENDSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
			"strsendsig:proc %p info %p", proc, info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
		sigaddq(proc, NULL, info, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
	if (sevent & S_RDBAND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
		sevent &= ~S_RDBAND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
		if (events & S_BANDURG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
			sigtoproc(proc, NULL, SIGURG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
			sigtoproc(proc, NULL, SIGPOLL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
	if (sevent & S_WRBAND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
		sevent &= ~S_WRBAND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
		sigtoproc(proc, NULL, SIGPOLL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
	if (sevent & S_INPUT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
		sevent &= ~S_INPUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
		info->si_code = POLL_IN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
		info->si_band = band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
		TRACE_2(TR_FAC_STREAMS_FR, TR_STRSENDSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
			"strsendsig:proc %p info %p", proc, info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
		sigaddq(proc, NULL, info, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
		info->si_band = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
	if (sevent & S_OUTPUT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
		sevent &= ~S_OUTPUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
		info->si_code = POLL_OUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
		info->si_band = band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
		TRACE_2(TR_FAC_STREAMS_FR, TR_STRSENDSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
			"strsendsig:proc %p info %p", proc, info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
		sigaddq(proc, NULL, info, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
		info->si_band = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
	if (sevent & S_MSG) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
		sevent &= ~S_MSG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
		info->si_code = POLL_MSG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
		info->si_band = band;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
		TRACE_2(TR_FAC_STREAMS_FR, TR_STRSENDSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
			"strsendsig:proc %p info %p", proc, info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
		sigaddq(proc, NULL, info, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
		info->si_band = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
	if (sevent & S_RDNORM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
		sevent &= ~S_RDNORM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
		sigtoproc(proc, NULL, SIGPOLL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
	if (sevent != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
		panic("strsendsig: unknown event(s) %x", sevent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
 * Send SIGPOLL/SIGURG signal to all processes and process groups
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
 * registered on the given signal list that want a signal for at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
 * least one of the specified events.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
 * Must be called with exclusive access to siglist (caller holding sd_lock).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
 * strioctl(I_SETSIG/I_ESETSIG) will only change siglist when holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
 * sd_lock and the ioctl code maintains a PID_HOLD on the pid structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
 * while it is in the siglist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
 * For performance reasons (MP scalability) the code drops pidlock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
 * when sending signals to a single process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
 * When sending to a process group the code holds
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
 * pidlock to prevent the membership in the process group from changing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
 * while walking the p_pglink list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
strsendsig(strsig_t *siglist, int event, uchar_t band, int error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
	strsig_t *ssp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
	k_siginfo_t info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
	struct pid *pidp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
	proc_t  *proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
	info.si_signo = SIGPOLL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
	info.si_errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
	for (ssp = siglist; ssp; ssp = ssp->ss_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
		int sevent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
		sevent = ssp->ss_events & event;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
		if (sevent == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
		if ((pidp = ssp->ss_pidp) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
			/* pid was released but still on event list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
		if (ssp->ss_pid > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
			 * XXX This unfortunately still generates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
			 * a signal when a fd is closed but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
			 * the proc is active.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
			ASSERT(ssp->ss_pid == pidp->pid_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
			mutex_enter(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
			proc = prfind_zone(pidp->pid_id, ALL_ZONES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
			if (proc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
				mutex_exit(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
			mutex_enter(&proc->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
			mutex_exit(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
			dosendsig(proc, ssp->ss_events, sevent, &info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
				band, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
			mutex_exit(&proc->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
			 * Send to process group. Hold pidlock across
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
			 * calls to dosendsig().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
			pid_t pgrp = -ssp->ss_pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
			mutex_enter(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
			proc = pgfind_zone(pgrp, ALL_ZONES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
			while (proc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
				mutex_enter(&proc->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
				dosendsig(proc, ssp->ss_events, sevent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
					&info, band, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
				mutex_exit(&proc->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
				proc = proc->p_pglink;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
			mutex_exit(&pidlock);
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
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
 * Attach a stream device or module.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
 * qp is a read queue; the new queue goes in so its next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
 * read ptr is the argument, and the write queue corresponding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
 * to the argument points to this queue. Return 0 on success,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
 * or a non-zero errno on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
qattach(queue_t *qp, dev_t *devp, int oflag, cred_t *crp, fmodsw_impl_t *fp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
    boolean_t is_insert)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
	major_t			major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
	cdevsw_impl_t		*dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
	struct streamtab	*str;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
	queue_t			*rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
	queue_t			*wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
	uint32_t		qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
	uint32_t		sqtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
	perdm_t			*dmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
	int			error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
	int			sflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
	rq = allocq();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
	wrq = _WR(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
	STREAM(rq) = STREAM(wrq) = STREAM(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
	if (fp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
		str = fp->f_str;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
		qflag = fp->f_qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
		sqtype = fp->f_sqtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
		dmp = fp->f_dmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
		IMPLY((qflag & (QPERMOD | QMTOUTPERIM)), dmp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
		sflag = MODOPEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
		 * stash away a pointer to the module structure so we can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
		 * unref it in qdetach.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
		rq->q_fp = fp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
		ASSERT(!is_insert);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
		major = getmajor(*devp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
		dp = &devimpl[major];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
		str = dp->d_str;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
		ASSERT(str == STREAMSTAB(major));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
		qflag = dp->d_qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
		ASSERT(qflag & QISDRV);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
		sqtype = dp->d_sqtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
		/* create perdm_t if needed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
		if (NEED_DM(dp->d_dmp, qflag))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
			dp->d_dmp = hold_dm(str, qflag, sqtype);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
		dmp = dp->d_dmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
		sflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
	TRACE_2(TR_FAC_STREAMS_FR, TR_QATTACH_FLAGS,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
	    "qattach:qflag == %X(%X)", qflag, *devp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
	/* setq might sleep in allocator - avoid holding locks. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
	setq(rq, str->st_rdinit, str->st_wrinit, dmp, qflag, sqtype, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
	 * Before calling the module's open routine, set up the q_next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
	 * pointer for inserting a module in the middle of a stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
	 * Note that we can always set _QINSERTING and set up q_next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
	 * pointer for both inserting and pushing a module.  Then there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
	 * is no need for the is_insert parameter.  In insertq(), called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
	 * by qprocson(), assume that q_next of the new module always points
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
	 * to the correct queue and use it for insertion.  Everything should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
	 * work out fine.  But in the first release of _I_INSERT, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
	 * distinguish between inserting and pushing to make sure that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
	 * pushing a module follows the same code path as before.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
	if (is_insert) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
		rq->q_flag |= _QINSERTING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
		rq->q_next = qp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
	 * If there is an outer perimeter get exclusive access during
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
	 * the open procedure.  Bump up the reference count on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
	entersq(rq->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
	error = (*rq->q_qinfo->qi_qopen)(rq, devp, oflag, sflag, crp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
	if (error != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
	leavesq(rq->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
	ASSERT(qprocsareon(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
failed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
	rq->q_flag &= ~_QINSERTING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
	if (backq(wrq) != NULL && backq(wrq)->q_next == wrq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
		qprocsoff(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
	leavesq(rq->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
	rq->q_next = wrq->q_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
	qdetach(rq, 0, 0, crp, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
 * Handle second open of stream. For modules, set the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
 * last argument to MODOPEN and do not pass any open flags.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
 * Ignore dummydev since this is not the first open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
qreopen(queue_t *qp, dev_t *devp, int flag, cred_t *crp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
	int	error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
	dev_t dummydev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
	queue_t *wqp = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
	ASSERT(qp->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
	entersq(qp->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
	dummydev = *devp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
	if (error = ((*qp->q_qinfo->qi_qopen)(qp, &dummydev,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
	    (wqp->q_next ? 0 : flag), (wqp->q_next ? MODOPEN : 0), crp))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
		leavesq(qp->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
		mutex_enter(&STREAM(qp)->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
		qp->q_stream->sd_flag |= STREOPENFAIL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
		mutex_exit(&STREAM(qp)->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
	leavesq(qp->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
	 * successful open should have done qprocson()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
	ASSERT(qprocsareon(_RD(qp)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
 * Detach a stream module or device.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
 * If clmode == 1 then the module or driver was opened and its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
 * close routine must be called. If clmode == 0, the module
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
 * or driver was never opened or the open failed, and so its close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
 * should not be called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
qdetach(queue_t *qp, int clmode, int flag, cred_t *crp, boolean_t is_remove)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
	queue_t *wqp = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
	ASSERT(STREAM(qp)->sd_flag & (STRCLOSE|STWOPEN|STRPLUMB));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
	if (STREAM_NEEDSERVICE(STREAM(qp)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
		stream_runservice(STREAM(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
	if (clmode) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
		 * Make sure that all the messages on the write side syncq are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
		 * processed and nothing is left. Since we are closing, no new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
		 * messages may appear there.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
		wait_q_syncq(wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
		entersq(qp->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
		if (is_remove) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
			mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
			qp->q_flag |= _QREMOVING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
			mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
		(*qp->q_qinfo->qi_qclose)(qp, flag, crp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
		 * Check that qprocsoff() was actually called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
		ASSERT((qp->q_flag & QWCLOSE) && (wqp->q_flag & QWCLOSE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
		leavesq(qp->q_syncq, SQ_OPENCLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
		disable_svc(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
	 * Allow any threads blocked in entersq to proceed and discover
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
	 * the QWCLOSE is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
	 * Note: This assumes that all users of entersq check QWCLOSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
	 * Currently runservice is the only entersq that can happen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
	 * after removeq has finished.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
	 * Removeq will have discarded all messages destined to the closing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
	 * pair of queues from the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
	 * NOTE: Calling a function inside an assert is unconventional.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
	 * However, it does not cause any problem since flush_syncq() does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
	 * not change any state except when it returns non-zero i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
	 * when the assert will trigger.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
	ASSERT(flush_syncq(qp->q_syncq, qp) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
	ASSERT(flush_syncq(wqp->q_syncq, wqp) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
	ASSERT((qp->q_flag & QPERMOD) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
		((qp->q_syncq->sq_head == NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
		(wqp->q_syncq->sq_head == NULL)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
	 * Flush the queues before q_next is set to NULL. This is needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
	 * in order to backenable any downstream queue before we go away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
	 * Note: we are already removed from the stream so that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
	 * backenabling will not cause any messages to be delivered to our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
	 * put procedures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
	flushq(qp, FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
	flushq(wqp, FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
	 * wait for any pending service processing to complete
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
	wait_svc(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
	/* Tidy up - removeq only does a half-remove from stream */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
	qp->q_next = wqp->q_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
	ASSERT(!(qp->q_flag & QENAB));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
	ASSERT(!(wqp->q_flag & QENAB));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
	/* release any fmodsw_impl_t structure held on behalf of the queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
	ASSERT(qp->q_fp != NULL || qp->q_flag & QISDRV);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
	if (qp->q_fp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
		fmodsw_rele(qp->q_fp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
	/* freeq removes us from the outer perimeter if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
	freeq(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
/* Prevent service procedures from being called */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
disable_svc(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
	queue_t *wqp = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
	ASSERT(qp->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
	mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
	qp->q_flag |= QWCLOSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
	mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
	mutex_enter(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
	wqp->q_flag |= QWCLOSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
	mutex_exit(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
/* allow service procedures to be called again */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
enable_svc(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
	queue_t *wqp = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
	ASSERT(qp->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
	mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
	qp->q_flag &= ~QWCLOSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
	mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
	mutex_enter(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
	wqp->q_flag &= ~QWCLOSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
	mutex_exit(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
 * Remove queue from qhead/qtail if it is enabled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
 * Only reset QENAB if the queue was removed from the runlist.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
 * A queue goes through 3 stages:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
 *	It is on the service list and QENAB is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
 *	It is removed from the service list but QENAB is still set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
 *	QENAB gets changed to QINSERVICE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
 *	QINSERVICE is reset (when the service procedure is done)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
 * Thus we can not reset QENAB unless we actually removed it from the service
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
 * queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
remove_runlist(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
	if (qp->q_flag & QENAB && qhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
		queue_t *q_chase;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
		queue_t *q_curr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
		int removed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
		mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
		RMQ(qp, qhead, qtail, q_link, q_chase, q_curr, removed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
		mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
		if (removed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
			STRSTAT(qremoved);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
			qp->q_flag &= ~QENAB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
 * wait for any pending service processing to complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
 * The removal of queues from the runlist is not atomic with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
 * clearing of the QENABLED flag and setting the INSERVICE flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
 * consequently it is possible for remove_runlist in strclose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
 * to not find the queue on the runlist but for it to be QENABLED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
 * and not yet INSERVICE -> hence wait_svc needs to check QENABLED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
 * as well as INSERVICE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
wait_svc(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
	queue_t *wqp = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
	ASSERT(qp->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
	 * Try to remove queues from qhead/qtail list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
	if (qhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
		remove_runlist(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
		remove_runlist(wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
	 * Wait till the syncqs associated with the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
	 * will dissapear from background processing list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
	 * This only needs to be done for non-PERMOD perimeters since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
	 * for PERMOD perimeters the syncq may be shared and will only be freed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
	 * when the last module/driver is unloaded.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
	 * If for PERMOD perimeters queue was on the syncq list, removeq()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
	 * should call propagate_syncq() or drain_syncq() for it. Both of these
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
	 * function remove the queue from its syncq list, so sqthread will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
	 * try to access the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
	if (!(qp->q_flag & QPERMOD)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
		syncq_t *rsq = qp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
		syncq_t *wsq = wqp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
		 * Disable rsq and wsq and wait for any background processing of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
		 * syncq to complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
		wait_sq_svc(rsq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
		if (wsq != rsq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
			wait_sq_svc(wsq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
	mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
	while (qp->q_flag & (QINSERVICE|QENAB))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
		cv_wait(&qp->q_wait, QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
	mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
	mutex_enter(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
	while (wqp->q_flag & (QINSERVICE|QENAB))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
		cv_wait(&wqp->q_wait, QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
	mutex_exit(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
 * Put ioctl data from userland buffer `arg' into the mblk chain `bp'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
 * `flag' must always contain either K_TO_K or U_TO_K; STR_NOSIG may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
 * also be set, and is passed through to allocb_cred_wait().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
 * Returns errno on failure, zero on success.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
putiocd(mblk_t *bp, char *arg, int flag, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
	mblk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
	ssize_t  count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
	size_t n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
	ASSERT((flag & (U_TO_K | K_TO_K)) == U_TO_K ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
		(flag & (U_TO_K | K_TO_K)) == K_TO_K);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
	if (bp->b_datap->db_type == M_IOCTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
		count = ((struct iocblk *)bp->b_rptr)->ioc_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
		ASSERT(bp->b_datap->db_type == M_COPYIN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
		count = ((struct copyreq *)bp->b_rptr)->cq_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
	 * strdoioctl validates ioc_count, so if this assert fails it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
	 * cannot be due to user error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
	ASSERT(count >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
	while (count > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
		n = MIN(MAXIOCBSZ, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
		if ((tmp = allocb_cred_wait(n, (flag & STR_NOSIG), &error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
		    cr)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
		error = strcopyin(arg, tmp->b_wptr, n, flag & (U_TO_K|K_TO_K));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
		if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
			freeb(tmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
		arg += n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
		DB_CPID(tmp) = curproc->p_pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
		tmp->b_wptr += n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
		count -= n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
		bp = (bp->b_cont = tmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
 * Copy ioctl data to user-land. Return non-zero errno on failure,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
 * 0 for success.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
getiocd(mblk_t *bp, char *arg, int copymode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
	ssize_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
	size_t  n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
	int	error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
	if (bp->b_datap->db_type == M_IOCACK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
		count = ((struct iocblk *)bp->b_rptr)->ioc_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
		ASSERT(bp->b_datap->db_type == M_COPYOUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
		count = ((struct copyreq *)bp->b_rptr)->cq_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
	ASSERT(count >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
	for (bp = bp->b_cont; bp && count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
	    count -= n, bp = bp->b_cont, arg += n) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
		n = MIN(count, bp->b_wptr - bp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
		error = strcopyout(bp->b_rptr, arg, n, copymode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
	ASSERT(count == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
 * Allocate a linkinfo entry given the write queue of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
 * bottom module of the top stream and the write queue of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
 * stream head of the bottom stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
linkinfo_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
alloclink(queue_t *qup, queue_t *qdown, file_t *fpdown)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
	linkinfo_t *linkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
	linkp = kmem_cache_alloc(linkinfo_cache, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
	linkp->li_lblk.l_qtop = qup;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
	linkp->li_lblk.l_qbot = qdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
	linkp->li_fpdown = fpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
	mutex_enter(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
	linkp->li_next = linkinfo_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	linkp->li_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
	if (linkp->li_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
		linkp->li_next->li_prev = linkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
	linkinfo_list = linkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
	linkp->li_lblk.l_index = ++lnk_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
	ASSERT(lnk_id != 0);	/* this should never wrap in practice */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
	mutex_exit(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
	return (linkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
 * Free a linkinfo entry.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
lbfree(linkinfo_t *linkp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
	mutex_enter(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
	if (linkp->li_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
		linkp->li_next->li_prev = linkp->li_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
	if (linkp->li_prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
		linkp->li_prev->li_next = linkp->li_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
		linkinfo_list = linkp->li_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
	mutex_exit(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
	kmem_cache_free(linkinfo_cache, linkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
 * Check for a potential linking cycle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
 * Return 1 if a link will result in a cycle,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
 * and 0 otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
linkcycle(stdata_t *upstp, stdata_t *lostp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
	struct mux_node *np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
	struct mux_edge *ep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
	major_t lomaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
	major_t upmaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
	 * if the lower stream is a pipe/FIFO, return, since link
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
	 * cycles can not happen on pipes/FIFOs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
	if (lostp->sd_vnode->v_type == VFIFO)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
	for (i = 0; i < devcnt; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
		np = &mux_nodes[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
		MUX_CLEAR(np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
	lomaj = getmajor(lostp->sd_vnode->v_rdev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
	upmaj = getmajor(upstp->sd_vnode->v_rdev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
	np = &mux_nodes[lomaj];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
		if (!MUX_DIDVISIT(np)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
			if (np->mn_imaj == upmaj)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
				return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
			if (np->mn_outp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
				MUX_VISIT(np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
				if (np->mn_originp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
				np = np->mn_originp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
			MUX_VISIT(np);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
			np->mn_startp = np->mn_outp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
			if (np->mn_startp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
				if (np->mn_originp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
				else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
					np = np->mn_originp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
			 * If ep->me_nodep is a FIFO (me_nodep == NULL),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
			 * ignore the edge and move on. ep->me_nodep gets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
			 * set to NULL in mux_addedge() if it is a FIFO.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
			ep = np->mn_startp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
			np->mn_startp = ep->me_nextp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
			if (ep->me_nodep == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
			ep->me_nodep->mn_originp = np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
			np = ep->me_nodep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
 * Find linkinfo entry corresponding to the parameters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
linkinfo_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
findlinks(stdata_t *stp, int index, int type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
	linkinfo_t *linkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
	struct mux_edge *mep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
	struct mux_node *mnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
	queue_t *qup;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
	mutex_enter(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
	if ((type & LINKTYPEMASK) == LINKNORMAL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
		qup = getendq(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
		for (linkp = linkinfo_list; linkp; linkp = linkp->li_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
			if ((qup == linkp->li_lblk.l_qtop) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
			    (!index || (index == linkp->li_lblk.l_index))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
				mutex_exit(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
				return (linkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
		ASSERT((type & LINKTYPEMASK) == LINKPERSIST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
		mnp = &mux_nodes[getmajor(stp->sd_vnode->v_rdev)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
		mep = mnp->mn_outp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
		while (mep) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
			if ((index == 0) || (index == mep->me_muxid))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
			mep = mep->me_nextp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
		if (!mep) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
			mutex_exit(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
		for (linkp = linkinfo_list; linkp; linkp = linkp->li_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
			if ((!linkp->li_lblk.l_qtop) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
			    (mep->me_muxid == linkp->li_lblk.l_index)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
				mutex_exit(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
				return (linkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
	mutex_exit(&strresources);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
 * Given a queue ptr, follow the chain of q_next pointers until you reach the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
 * last queue on the chain and return it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
queue_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
getendq(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
	ASSERT(q != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
	while (_SAMESTR(q))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
		q = q->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
	return (q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
 * wait for the syncq count to drop to zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
 * sq could be either outer or inner.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
wait_syncq(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
	uint16_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
	count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
	SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
	SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
	while (count != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
		sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
		cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
		SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
		SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
	SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
 * Wait while there are any messages for the queue in its syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
wait_q_syncq(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
	if ((q->q_sqflags & Q_SQQUEUED) || (q->q_syncqmsgs > 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
		syncq_t *sq = q->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
		while ((q->q_sqflags & Q_SQQUEUED) || (q->q_syncqmsgs > 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
			sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
			cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
mlink_file(vnode_t *vp, int cmd, struct file *fpdown, cred_t *crp, int *rvalp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
    int lhlink)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
	struct stdata *stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
	struct strioctl strioc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
	struct linkinfo *linkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
	struct stdata *stpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
	struct streamtab *str;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
	queue_t *passq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
	syncq_t *passyncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
	queue_t *rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
	cdevsw_impl_t *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
	uint32_t qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
	uint32_t sqtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
	perdm_t *dmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
	stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
	TRACE_1(TR_FAC_STREAMS_FR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
		TR_I_LINK, "I_LINK/I_PLINK:stp %p", stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
	 * Test for invalid upper stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
	if (stp->sd_flag & STRHUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
		return (ENXIO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
	if (vp->v_type == VFIFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
	if (stp->sd_strtab == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
	if (!stp->sd_strtab->st_muxwinit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
	if (fpdown == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
		return (EBADF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
	if (getmajor(stp->sd_vnode->v_rdev) >= devcnt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
	mutex_enter(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
	if (stp->sd_flag & STPLEX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
		mutex_exit(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
		return (ENXIO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
	 * Test for invalid lower stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
	 * The check for the v_type != VFIFO and having a major
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
	 * number not >= devcnt is done to avoid problems with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
	 * adding mux_node entry past the end of mux_nodes[].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
	 * For FIFO's we don't add an entry so this isn't a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
	 * problem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
	if (((stpdown = fpdown->f_vnode->v_stream) == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
	    (stpdown == stp) || (stpdown->sd_flag &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
	    (STPLEX|STRHUP|STRDERR|STWRERR|IOCWAIT|STRPLUMB)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
	    ((stpdown->sd_vnode->v_type != VFIFO) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
	    (getmajor(stpdown->sd_vnode->v_rdev) >= devcnt)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
	    linkcycle(stp, stpdown)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
		mutex_exit(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1796
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
	TRACE_1(TR_FAC_STREAMS_FR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
		TR_STPDOWN, "stpdown:%p", stpdown);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
	rq = getendq(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
	if (cmd == I_PLINK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1801
		rq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
	linkp = alloclink(rq, stpdown->sd_wrq, fpdown);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
	strioc.ic_cmd = cmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
	strioc.ic_timout = INFTIM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
	strioc.ic_len = sizeof (struct linkblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
	strioc.ic_dp = (char *)&linkp->li_lblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
	 * STRPLUMB protects plumbing changes and should be set before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
	 * link_addpassthru()/link_rempassthru() are called, so it is set here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
	 * and cleared in the end of mlink when passthru queue is removed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
	 * Setting of STRPLUMB prevents reopens of the stream while passthru
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
	 * queue is in-place (it is not a proper module and doesn't have open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
	 * entry point).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
	 * STPLEX prevents any threads from entering the stream from above. It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
	 * can't be set before the call to link_addpassthru() because putnext
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
	 * from below may cause stream head I/O routines to be called and these
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
	 * routines assert that STPLEX is not set. After link_addpassthru()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
	 * nothing may come from below since the pass queue syncq is blocked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
	 * Note also that STPLEX should be cleared before the call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
	 * link_remmpassthru() since when messages start flowing to the stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
	 * head (e.g. because of message propagation from the pass queue) stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
	 * head I/O routines may be called with STPLEX flag set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
	 * When STPLEX is set, nothing may come into the stream from above and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
	 * it is safe to do a setq which will change stream head. So, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
	 * correct sequence of actions is:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
	 * 1) Set STRPLUMB
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
	 * 2) Call link_addpassthru()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
	 * 3) Set STPLEX
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
	 * 4) Call setq and update the stream state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
	 * 5) Clear STPLEX
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
	 * 6) Call link_rempassthru()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
	 * 7) Clear STRPLUMB
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
	 * The same sequence applies to munlink() code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
	mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
	stpdown->sd_flag |= STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
	mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
	 * Add passthru queue below lower mux. This will block
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
	 * syncqs of lower muxs read queue during I_LINK/I_UNLINK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
	passq = link_addpassthru(stpdown);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
	mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
	stpdown->sd_flag |= STPLEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
	mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
	rq = _RD(stpdown->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
	 * There may be messages in the streamhead's syncq due to messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
	 * that arrived before link_addpassthru() was done. To avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
	 * background processing of the syncq happening simultaneous with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
	 * setq processing, we disable the streamhead syncq and wait until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
	 * existing background thread finishes working on it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
	wait_sq_svc(rq->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
	passyncq = passq->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
	if (!(passyncq->sq_flags & SQ_BLOCKED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
		blocksq(passyncq, SQ_BLOCKED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
	ASSERT((rq->q_flag & QMT_TYPEMASK) == QMTSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
	ASSERT(rq->q_syncq == SQ(rq) && _WR(rq)->q_syncq == SQ(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
	rq->q_ptr = _WR(rq)->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
	/* setq might sleep in allocator - avoid holding locks. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
	/* Note: we are holding muxifier here. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
	str = stp->sd_strtab;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
	dp = &devimpl[getmajor(vp->v_rdev)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
	ASSERT(dp->d_str == str);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
	qflag = dp->d_qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
	sqtype = dp->d_sqtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
	/* create perdm_t if needed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
	if (NEED_DM(dp->d_dmp, qflag))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
		dp->d_dmp = hold_dm(str, qflag, sqtype);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
	dmp = dp->d_dmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
	setq(rq, str->st_muxrinit, str->st_muxwinit, dmp, qflag, sqtype,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
	    B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
	 * XXX Remove any "odd" messages from the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
	 * Keep only M_DATA, M_PROTO, M_PCPROTO.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
	error = strdoioctl(stp, &strioc, FNATIVE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	    K_TO_K | STR_NOERROR | STR_NOSIG, crp, rvalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
	if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
		lbfree(linkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
		if (!(passyncq->sq_flags & SQ_BLOCKED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
			blocksq(passyncq, SQ_BLOCKED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
		 * Restore the stream head queue and then remove
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
		 * the passq. Turn off STPLEX before we turn on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
		 * the stream by removing the passq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
		rq->q_ptr = _WR(rq)->q_ptr = stpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
		setq(rq, &strdata, &stwdata, NULL, QMTSAFE, SQ_CI|SQ_CO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
		    B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
		mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
		stpdown->sd_flag &= ~STPLEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
		mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
		link_rempassthru(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
		mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
		stpdown->sd_flag &= ~STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
		/* Wakeup anyone waiting for STRPLUMB to clear. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
		cv_broadcast(&stpdown->sd_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
		mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
		mutex_exit(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
	mutex_enter(&fpdown->f_tlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
	fpdown->f_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
	mutex_exit(&fpdown->f_tlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
	 * if we've made it here the linkage is all set up so we should also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
	 * set up the layered driver linkages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
	ASSERT((cmd == I_LINK) || (cmd == I_PLINK));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
	if (cmd == I_LINK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
		ldi_mlink_fp(stp, fpdown, lhlink, LINKNORMAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
		ldi_mlink_fp(stp, fpdown, lhlink, LINKPERSIST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
	link_rempassthru(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
	mux_addedge(stp, stpdown, linkp->li_lblk.l_index);
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
	 * Mark the upper stream as having dependent links
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
	 * so that strclose can clean it up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
	if (cmd == I_LINK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
		stp->sd_flag |= STRHASLINKS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
	 * Wake up any other processes that may have been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
	 * waiting on the lower stream. These will all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
	 * error out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
	mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
	/* The passthru module is removed so we may release STRPLUMB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
	stpdown->sd_flag &= ~STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
	cv_broadcast(&rq->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
	cv_broadcast(&_WR(rq)->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
	cv_broadcast(&stpdown->sd_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
	mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
	mutex_exit(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
	*rvalp = linkp->li_lblk.l_index;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
mlink(vnode_t *vp, int cmd, int arg, cred_t *crp, int *rvalp, int lhlink)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
	int		ret;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
	struct file	*fpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
	fpdown = getf(arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
	ret = mlink_file(vp, cmd, fpdown, crp, rvalp, lhlink);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
	if (fpdown != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
		releasef(arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
 * Unlink a multiplexor link. Stp is the controlling stream for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
 * link, and linkp points to the link's entry in the linkinfo list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
 * The muxifier lock must be held on entry and is dropped on exit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
 * NOTE : Currently it is assumed that mux would process all the messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
 * sitting on it's queue before ACKing the UNLINK. It is the responsibility
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
 * of the mux to handle all the messages that arrive before UNLINK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
 * If the mux has to send down messages on its lower stream before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
 * ACKing I_UNLINK, then it *should* know to handle messages even
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
 * after the UNLINK is acked (actually it should be able to handle till we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
 * re-block the read side of the pass queue here). If the mux does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
 * open up the lower stream, any messages that arrive during UNLINK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
 * will be put in the stream head. In the case of lower stream opening
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
 * up, some messages might land in the stream head depending on when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
 * the message arrived and when the read side of the pass queue was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
 * re-blocked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
munlink(stdata_t *stp, linkinfo_t *linkp, int flag, cred_t *crp, int *rvalp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
	struct strioctl strioc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
	struct stdata *stpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
	queue_t *rq, *wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
	queue_t	*passq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
	syncq_t *passyncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
	file_t *fpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
	ASSERT(MUTEX_HELD(&muxifier));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
	stpdown = linkp->li_fpdown->f_vnode->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
	 * See the comment in mlink() concerning STRPLUMB/STPLEX flags.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
	mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
	stpdown->sd_flag |= STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
	mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
	 * Add passthru queue below lower mux. This will block
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
	 * syncqs of lower muxs read queue during I_LINK/I_UNLINK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
	passq = link_addpassthru(stpdown);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
	if ((flag & LINKTYPEMASK) == LINKNORMAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
		strioc.ic_cmd = I_UNLINK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
		strioc.ic_cmd = I_PUNLINK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
	strioc.ic_timout = INFTIM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
	strioc.ic_len = sizeof (struct linkblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
	strioc.ic_dp = (char *)&linkp->li_lblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
	error = strdoioctl(stp, &strioc, FNATIVE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
	    K_TO_K | STR_NOERROR | STR_NOSIG, crp, rvalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
	 * If there was an error and this is not called via strclose,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
	 * return to the user. Otherwise, pretend there was no error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
	 * and close the link.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
	if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
		if (flag & LINKCLOSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
			cmn_err(CE_WARN, "KERNEL: munlink: could not perform "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
			    "unlink ioctl, closing anyway (%d)\n", error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
			link_rempassthru(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
			mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
			stpdown->sd_flag &= ~STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
			cv_broadcast(&stpdown->sd_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
			mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
			mutex_exit(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
	mux_rmvedge(stp, linkp->li_lblk.l_index);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
	fpdown = linkp->li_fpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
	lbfree(linkp);
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
	 * We go ahead and drop muxifier here--it's a nasty global lock that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
	 * can slow others down. It's okay to since attempts to mlink() this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
	 * stream will be stopped because STPLEX is still set in the stdata
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
	 * structure, and munlink() is stopped because mux_rmvedge() and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
	 * lbfree() have removed it from mux_nodes[] and linkinfo_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
	 * respectively.  Note that we defer the closef() of fpdown until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
	 * after we drop muxifier since strclose() can call munlinkall().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
	mutex_exit(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
	wrq = stpdown->sd_wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
	rq = _RD(wrq);
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
	 * Get rid of outstanding service procedure runs, before we make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
	 * it a stream head, since a stream head doesn't have any service
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
	 * procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
	disable_svc(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
	wait_svc(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
	 * Since we don't disable the syncq for QPERMOD, we wait for whatever
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
	 * is queued up to be finished. mux should take care that nothing is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
	 * send down to this queue. We should do it now as we're going to block
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
	 * passyncq if it was unblocked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
	if (wrq->q_flag & QPERMOD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
		syncq_t	*sq = wrq->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
		while (wrq->q_sqflags & Q_SQQUEUED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
			sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
			cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
	passyncq = passq->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
	if (!(passyncq->sq_flags & SQ_BLOCKED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
		syncq_t *sq, *outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
		 * Messages could be flowing from underneath. We will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
		 * block the read side of the passq. This would be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
		 * sufficient for QPAIR and QPERQ muxes to ensure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
		 * that no data is flowing up into this queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
		 * and hence no thread active in this instance of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
		 * lower mux. But for QPERMOD and QMTOUTPERIM there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
		 * could be messages on the inner and outer/inner
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
		 * syncqs respectively. We will wait for them to drain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
		 * Because passq is blocked messages end up in the syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
		 * And qfill_syncq could possibly end up setting QFULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
		 * which will access the rq->q_flag. Hence, we have to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
		 * acquire the QLOCK in setq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
		 * XXX Messages can also flow from top into this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
		 * queue though the unlink is over (Ex. some instance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
		 * in putnext() called from top that has still not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
		 * accessed this queue. And also putq(lowerq) ?).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
		 * Solution : How about blocking the l_qtop queue ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
		 * Do we really care about such pure D_MP muxes ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
		blocksq(passyncq, SQ_BLOCKED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
		sq = rq->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
		if ((outer = sq->sq_outer) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
			 * We have to just wait for the outer sq_count
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
			 * drop to zero. As this does not prevent new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
			 * messages to enter the outer perimeter, this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
			 * is subject to starvation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
			 * NOTE :Because of blocksq above, messages could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
			 * be in the inner syncq only because of some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
			 * thread holding the outer perimeter exclusively.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
			 * Hence it would be sufficient to wait for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
			 * exclusive holder of the outer perimeter to drain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
			 * the inner and outer syncqs. But we will not depend
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
			 * on this feature and hence check the inner syncqs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
			 * separately.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
			wait_syncq(outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
		 * There could be messages destined for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
		 * this queue. Let the exclusive holder
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
		 * drain it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
		wait_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
		ASSERT((rq->q_flag & QPERMOD) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
			((rq->q_syncq->sq_head == NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
			(_WR(rq)->q_syncq->sq_head == NULL)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
	 * We haven't taken care of QPERMOD case yet. QPERMOD is a special
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
	 * case as we don't disable its syncq or remove it off the syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
	 * service list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
	if (rq->q_flag & QPERMOD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
		syncq_t	*sq = rq->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
		while (rq->q_sqflags & Q_SQQUEUED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
			sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
			cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
	 * flush_syncq changes states only when there is some messages to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
	 * free. ie when it returns non-zero value to return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
	ASSERT(flush_syncq(rq->q_syncq, rq) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
	ASSERT(flush_syncq(wrq->q_syncq, wrq) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
	 * No body else should know about this queue now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
	 * If the mux did not process the messages before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
	 * acking the I_UNLINK, free them now.
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
	flushq(rq, FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
	flushq(_WR(rq), FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
	 * Convert the mux lower queue into a stream head queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
	 * Turn off STPLEX before we turn on the stream by removing the passq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
	rq->q_ptr = wrq->q_ptr = stpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
	setq(rq, &strdata, &stwdata, NULL, QMTSAFE, SQ_CI|SQ_CO, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
	ASSERT((rq->q_flag & QMT_TYPEMASK) == QMTSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
	ASSERT(rq->q_syncq == SQ(rq) && _WR(rq)->q_syncq == SQ(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
	enable_svc(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
	 * Now it is a proper stream, so STPLEX is cleared. But STRPLUMB still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
	 * needs to be set to prevent reopen() of the stream - such reopen may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
	 * try to call non-existent pass queue open routine and panic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
	mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
	stpdown->sd_flag &= ~STPLEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
	mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
	ASSERT(((flag & LINKTYPEMASK) == LINKNORMAL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
	    ((flag & LINKTYPEMASK) == LINKPERSIST));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
	/* clean up the layered driver linkages */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
	if ((flag & LINKTYPEMASK) == LINKNORMAL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
		ldi_munlink_fp(stp, fpdown, LINKNORMAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
		ldi_munlink_fp(stp, fpdown, LINKPERSIST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
	link_rempassthru(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
	 * Now all plumbing changes are finished and STRPLUMB is no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
	 * longer needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
	mutex_enter(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
	stpdown->sd_flag &= ~STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
	cv_broadcast(&stpdown->sd_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
	mutex_exit(&stpdown->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2241
	(void) closef(fpdown);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
 * Unlink all multiplexor links for which stp is the controlling stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
 * Return 0, or a non-zero errno on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
munlinkall(stdata_t *stp, int flag, cred_t *crp, int *rvalp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
	linkinfo_t *linkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
	mutex_enter(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
	while (linkp = findlinks(stp, 0, flag)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
		 * munlink() releases the muxifier lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
		if (error = munlink(stp, linkp, flag, crp, rvalp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
		mutex_enter(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
	mutex_exit(&muxifier);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
 * A multiplexor link has been made. Add an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
 * edge to the directed graph.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
mux_addedge(stdata_t *upstp, stdata_t *lostp, int muxid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
	struct mux_node *np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
	struct mux_edge *ep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
	major_t upmaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
	major_t lomaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
	upmaj = getmajor(upstp->sd_vnode->v_rdev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
	lomaj = getmajor(lostp->sd_vnode->v_rdev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
	np = &mux_nodes[upmaj];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
	if (np->mn_outp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
		ep = np->mn_outp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
		while (ep->me_nextp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
			ep = ep->me_nextp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
		ep->me_nextp = kmem_alloc(sizeof (struct mux_edge), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
		ep = ep->me_nextp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
		np->mn_outp = kmem_alloc(sizeof (struct mux_edge), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
		ep = np->mn_outp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
	ep->me_nextp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
	ep->me_muxid = muxid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
	if (lostp->sd_vnode->v_type == VFIFO)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
		ep->me_nodep = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
		ep->me_nodep = &mux_nodes[lomaj];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
 * A multiplexor link has been removed. Remove the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
 * edge in the directed graph.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
mux_rmvedge(stdata_t *upstp, int muxid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
	struct mux_node *np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
	struct mux_edge *ep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
	struct mux_edge *pep = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
	major_t upmaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
	upmaj = getmajor(upstp->sd_vnode->v_rdev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
	np = &mux_nodes[upmaj];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
	ASSERT(np->mn_outp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
	ep = np->mn_outp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
	while (ep) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
		if (ep->me_muxid == muxid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
			if (pep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
				pep->me_nextp = ep->me_nextp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
				np->mn_outp = ep->me_nextp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
			kmem_free(ep, sizeof (struct mux_edge));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
		pep = ep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
		ep = ep->me_nextp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
	ASSERT(0);	/* should not reach here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
 * Translate the device flags (from conf.h) to the corresponding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
 * qflag and sq_flag (type) values.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
devflg_to_qflag(struct streamtab *stp, uint32_t devflag, uint32_t *qflagp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
	uint32_t *sqtypep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
	uint32_t qflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
	uint32_t sqtype = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
	if (devflag & _D_OLD)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
	/* Inner perimeter presence and scope */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
	switch (devflag & D_MTINNER_MASK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
	case D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
		qflag |= QMTSAFE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
		sqtype |= SQ_CI;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
	case D_MTPERQ|D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
		qflag |= QPERQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
	case D_MTQPAIR|D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
		qflag |= QPAIR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
	case D_MTPERMOD|D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
		qflag |= QPERMOD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
	/* Outer perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
	if (devflag & D_MTOUTPERIM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
		switch (devflag & D_MTINNER_MASK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
		case D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
		case D_MTPERQ|D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
		case D_MTQPAIR|D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
		qflag |= QMTOUTPERIM;
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
	/* Inner perimeter modifiers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
	if (devflag & D_MTINNER_MOD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
		switch (devflag & D_MTINNER_MASK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
		case D_MP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
		if (devflag & D_MTPUTSHARED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
			sqtype |= SQ_CIPUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
		if (devflag & _D_MTOCSHARED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
			 * The code in putnext assumes that it has the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
			 * highest concurrency by not checking sq_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
			 * Thus _D_MTOCSHARED can only be supported when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
			 * D_MTPUTSHARED is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
			if (!(devflag & D_MTPUTSHARED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
			sqtype |= SQ_CIOC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
		if (devflag & _D_MTCBSHARED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
			 * The code in putnext assumes that it has the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
			 * highest concurrency by not checking sq_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
			 * Thus _D_MTCBSHARED can only be supported when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
			 * D_MTPUTSHARED is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
			if (!(devflag & D_MTPUTSHARED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
			sqtype |= SQ_CICB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
		if (devflag & _D_MTSVCSHARED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
			 * The code in putnext assumes that it has the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
			 * highest concurrency by not checking sq_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
			 * Thus _D_MTSVCSHARED can only be supported when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
			 * D_MTPUTSHARED is set. Also _D_MTSVCSHARED is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
			 * supported only for QPERMOD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
			if (!(devflag & D_MTPUTSHARED) || !(qflag & QPERMOD))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
			sqtype |= SQ_CISVC;
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
	/* Default outer perimeter concurrency */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
	sqtype |= SQ_CO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
	/* Outer perimeter modifiers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
	if (devflag & D_MTOCEXCL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
		if (!(devflag & D_MTOUTPERIM)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
			/* No outer perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
		sqtype &= ~SQ_COOC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
	/* Synchronous Streams extended qinit structure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
	if (devflag & D_SYNCSTR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
		qflag |= QSYNCSTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2440
	/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2441
	 * Private flag used by a transport module to indicate
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2442
	 * to sockfs that it supports direct-access mode without
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2443
	 * having to go through STREAMS.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2444
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2445
	if (devflag & _D_DIRECT) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2446
		/* Reject unless the module is fully-MT (no perimeter) */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2447
		if ((qflag & QMT_TYPEMASK) != QMTSAFE)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2448
			goto bad;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2449
		qflag |= _QDIRECT;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2450
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  2451
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
	*qflagp = qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
	*sqtypep = sqtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
bad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
	cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
	    "stropen: bad MT flags (0x%x) in driver '%s'",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
	    (int)(qflag & D_MTSAFETY_MASK),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
	    stp->st_rdinit->qi_minfo->mi_idname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
	return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
 * Set the interface values for a pair of queues (qinit structure,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
 * packet sizes, water marks).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
 * setq assumes that the caller does not have a claim (entersq or claimq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
 * on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
setq(queue_t *rq, struct qinit *rinit, struct qinit *winit,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
    perdm_t *dmp, uint32_t qflag, uint32_t sqtype, boolean_t lock_needed)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
	queue_t *wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
	syncq_t	*sq, *outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
	ASSERT(rq->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
	ASSERT((qflag & QMT_TYPEMASK) != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
	IMPLY((qflag & (QPERMOD | QMTOUTPERIM)), dmp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
	wq = _WR(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
	rq->q_qinfo = rinit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
	rq->q_hiwat = rinit->qi_minfo->mi_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
	rq->q_lowat = rinit->qi_minfo->mi_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
	rq->q_minpsz = rinit->qi_minfo->mi_minpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
	rq->q_maxpsz = rinit->qi_minfo->mi_maxpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
	wq->q_qinfo = winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
	wq->q_hiwat = winit->qi_minfo->mi_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
	wq->q_lowat = winit->qi_minfo->mi_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
	wq->q_minpsz = winit->qi_minfo->mi_minpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
	wq->q_maxpsz = winit->qi_minfo->mi_maxpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
	/* Remove old syncqs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
	sq = rq->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
	outer = sq->sq_outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
	if (outer != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
		ASSERT(wq->q_syncq->sq_outer == outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
		outer_remove(outer, rq->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
		if (wq->q_syncq != rq->q_syncq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
			outer_remove(outer, wq->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
	ASSERT(sq->sq_outer == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
	ASSERT(sq->sq_onext == NULL && sq->sq_oprev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
	if (sq != SQ(rq)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
		if (!(rq->q_flag & QPERMOD))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
			free_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
		if (wq->q_syncq == rq->q_syncq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
			wq->q_syncq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
		rq->q_syncq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
	if (wq->q_syncq != NULL && wq->q_syncq != sq &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
	    wq->q_syncq != SQ(rq)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
		free_syncq(wq->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
		wq->q_syncq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
	ASSERT(rq->q_syncq == NULL || (rq->q_syncq->sq_head == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
				rq->q_syncq->sq_tail == NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
	ASSERT(wq->q_syncq == NULL || (wq->q_syncq->sq_head == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
				wq->q_syncq->sq_tail == NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
	if (!(rq->q_flag & QPERMOD) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
	    rq->q_syncq != NULL && rq->q_syncq->sq_ciputctrl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
		ASSERT(rq->q_syncq->sq_nciputctrl == n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
		SUMCHECK_CIPUTCTRL_COUNTS(rq->q_syncq->sq_ciputctrl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
		    rq->q_syncq->sq_nciputctrl, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
		ASSERT(ciputctrl_cache != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
		kmem_cache_free(ciputctrl_cache, rq->q_syncq->sq_ciputctrl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
		rq->q_syncq->sq_ciputctrl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
		rq->q_syncq->sq_nciputctrl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
	if (!(wq->q_flag & QPERMOD) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
	    wq->q_syncq != NULL && wq->q_syncq->sq_ciputctrl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
		ASSERT(wq->q_syncq->sq_nciputctrl == n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
		SUMCHECK_CIPUTCTRL_COUNTS(wq->q_syncq->sq_ciputctrl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
		    wq->q_syncq->sq_nciputctrl, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
		ASSERT(ciputctrl_cache != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
		kmem_cache_free(ciputctrl_cache, wq->q_syncq->sq_ciputctrl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
		wq->q_syncq->sq_ciputctrl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
		wq->q_syncq->sq_nciputctrl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
	sq = SQ(rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
	ASSERT(sq->sq_head == NULL && sq->sq_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
	ASSERT(sq->sq_outer == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
	ASSERT(sq->sq_onext == NULL && sq->sq_oprev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
	 * Create syncqs based on qflag and sqtype. Set the SQ_TYPES_IN_FLAGS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
	 * bits in sq_flag based on the sqtype.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
	ASSERT((sq->sq_flags & ~SQ_TYPES_IN_FLAGS) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
	rq->q_syncq = wq->q_syncq = sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
	sq->sq_type = sqtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
	sq->sq_flags = (sqtype & SQ_TYPES_IN_FLAGS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
	 *  We are making sq_svcflags zero,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
	 *  resetting SQ_DISABLED in case it was set by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
	 *  wait_svc() in the munlink path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
	ASSERT((sq->sq_svcflags & SQ_SERVICE) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
	sq->sq_svcflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
	 * We need to acquire the lock here for the mlink and munlink case,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
	 * where canputnext, backenable, etc can access the q_flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
	if (lock_needed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
		mutex_enter(QLOCK(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
		rq->q_flag = (rq->q_flag & ~QMT_TYPEMASK) | QWANTR | qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
		mutex_exit(QLOCK(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
		mutex_enter(QLOCK(wq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
		wq->q_flag = (wq->q_flag & ~QMT_TYPEMASK) | QWANTR | qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
		mutex_exit(QLOCK(wq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
		rq->q_flag = (rq->q_flag & ~QMT_TYPEMASK) | QWANTR | qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
		wq->q_flag = (wq->q_flag & ~QMT_TYPEMASK) | QWANTR | qflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
	if (qflag & QPERQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
		/* Allocate a separate syncq for the write side */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
		sq = new_syncq();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
		sq->sq_type = rq->q_syncq->sq_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
		sq->sq_flags = rq->q_syncq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
		ASSERT(sq->sq_outer == NULL && sq->sq_onext == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
		    sq->sq_oprev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
		wq->q_syncq = sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
	if (qflag & QPERMOD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
		sq = dmp->dm_sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
		 * Assert that we do have an inner perimeter syncq and that it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
		 * does not have an outer perimeter associated with it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
		ASSERT(sq->sq_outer == NULL && sq->sq_onext == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
		    sq->sq_oprev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
		rq->q_syncq = wq->q_syncq = sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
	if (qflag & QMTOUTPERIM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
		outer = dmp->dm_sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
		ASSERT(outer->sq_outer == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
		outer_insert(outer, rq->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
		if (wq->q_syncq != rq->q_syncq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
			outer_insert(outer, wq->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
	ASSERT((rq->q_syncq->sq_flags & SQ_TYPES_IN_FLAGS) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
		(rq->q_syncq->sq_type & SQ_TYPES_IN_FLAGS));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2615
	ASSERT((wq->q_syncq->sq_flags & SQ_TYPES_IN_FLAGS) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2616
		(wq->q_syncq->sq_type & SQ_TYPES_IN_FLAGS));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
	ASSERT((rq->q_flag & QMT_TYPEMASK) == (qflag & QMT_TYPEMASK));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2620
	 * Initialize struio() types.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2621
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2622
	rq->q_struiot =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
	    (rq->q_flag & QSYNCSTR) ? rinit->qi_struiot : STRUIOT_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
	wq->q_struiot =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
	    (wq->q_flag & QSYNCSTR) ? winit->qi_struiot : STRUIOT_NONE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
perdm_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
hold_dm(struct streamtab *str, uint32_t qflag, uint32_t sqtype)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
	syncq_t	*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
	perdm_t	**pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
	perdm_t	*p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
	perdm_t	*dmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2636
	ASSERT(str != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
	ASSERT(qflag & (QPERMOD | QMTOUTPERIM));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
	rw_enter(&perdm_rwlock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
	for (p = perdm_list; p != NULL; p = p->dm_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
		if (p->dm_str == str) {	/* found one */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
			atomic_add_32(&(p->dm_ref), 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
			rw_exit(&perdm_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
			return (p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2646
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2647
	rw_exit(&perdm_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2649
	sq = new_syncq();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2650
	if (qflag & QPERMOD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2651
		sq->sq_type = sqtype | SQ_PERMOD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2652
		sq->sq_flags = sqtype & SQ_TYPES_IN_FLAGS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2653
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2654
		ASSERT(qflag & QMTOUTPERIM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2655
		sq->sq_onext = sq->sq_oprev = sq;
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
	dmp = kmem_alloc(sizeof (perdm_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2659
	dmp->dm_sq = sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2660
	dmp->dm_str = str;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2661
	dmp->dm_ref = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2662
	dmp->dm_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2663
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2664
	rw_enter(&perdm_rwlock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2665
	for (pp = &perdm_list; (p = *pp) != NULL; pp = &(p->dm_next)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2666
		if (p->dm_str == str) {	/* already present */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2667
			p->dm_ref++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2668
			rw_exit(&perdm_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2669
			free_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2670
			kmem_free(dmp, sizeof (perdm_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2671
			return (p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2672
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2673
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
	*pp = dmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
	rw_exit(&perdm_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
	return (dmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
rele_dm(perdm_t *dmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
	perdm_t **pp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
	perdm_t *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
	rw_enter(&perdm_rwlock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
	ASSERT(dmp->dm_ref > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
	if (--dmp->dm_ref > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
		rw_exit(&perdm_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
	for (pp = &perdm_list; (p = *pp) != NULL; pp = &(p->dm_next))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
		if (p == dmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
	ASSERT(p == dmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
	*pp = p->dm_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
	rw_exit(&perdm_rwlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
	 * Wait for any background processing that relies on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
	 * syncq to complete before it is freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
	wait_sq_svc(p->dm_sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
	free_syncq(p->dm_sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
	kmem_free(p, sizeof (perdm_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
 * Make a protocol message given control and data buffers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
 * n.b., this can block; be careful of what locks you hold when calling it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
 * If sd_maxblk is less than *iosize this routine can fail part way through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
 * (due to an allocation failure). In this case on return *iosize will contain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
 * the amount that was consumed. Otherwise *iosize will not be modified
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
 * i.e. it will contain the amount that was consumed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2720
strmakemsg(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2721
	struct strbuf *mctl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2722
	ssize_t *iosize,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2723
	struct uio *uiop,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2724
	stdata_t *stp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2725
	int32_t flag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2726
	mblk_t **mpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2727
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2728
	mblk_t *mpctl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2729
	mblk_t *mpdata = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2730
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2732
	ASSERT(uiop != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2733
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2734
	*mpp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2735
	/* Create control part, if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2736
	if ((mctl != NULL) && (mctl->len >= 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
		error = strmakectl(mctl, flag, uiop->uio_fmode, &mpctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2738
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2739
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2740
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2741
	/* Create data part, if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2742
	if (*iosize >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2743
		error = strmakedata(iosize, uiop, stp, flag, &mpdata);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2744
		if (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2745
			freemsg(mpctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2746
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2747
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2748
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2749
	if (mpctl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2750
		if (mpdata != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2751
			linkb(mpctl, mpdata);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2752
		*mpp = mpctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2753
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2754
		*mpp = mpdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2755
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2756
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2757
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2759
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2760
 * Make the control part of a protocol message given a control buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2761
 * n.b., this can block; be careful of what locks you hold when calling it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2762
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2763
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2764
strmakectl(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2765
	struct strbuf *mctl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2766
	int32_t flag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2767
	int32_t fflag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2768
	mblk_t **mpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2769
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2770
	mblk_t *bp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2771
	unsigned char msgtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2772
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2774
	*mpp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2775
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2776
	 * Create control part of message, if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2777
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2778
	if ((mctl != NULL) && (mctl->len >= 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2779
		caddr_t base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2780
		int ctlcount;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2781
		int allocsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2782
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2783
		if (flag & RS_HIPRI)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2784
			msgtype = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2785
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2786
			msgtype = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
		ctlcount = mctl->len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2789
		base = mctl->buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
		 * Give modules a better chance to reuse M_PROTO/M_PCPROTO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
		 * blocks by increasing the size to something more usable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
		allocsz = MAX(ctlcount, 64);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2797
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2798
		 * Range checking has already been done; simply try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2799
		 * to allocate a message block for the ctl part.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2800
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
		while (!(bp = allocb(allocsz, BPRI_MED))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
			if (fflag & (FNDELAY|FNONBLOCK))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
				return (EAGAIN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
			if (error = strwaitbuf(allocsz, BPRI_MED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
		bp->b_datap->db_type = msgtype;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
		if (copyin(base, bp->b_wptr, ctlcount)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
			freeb(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2811
			return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
		bp->b_wptr += ctlcount;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
	*mpp = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2819
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
 * Make a protocol message given data buffers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
 * n.b., this can block; be careful of what locks you hold when calling it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
 * If sd_maxblk is less than *iosize this routine can fail part way through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
 * (due to an allocation failure). In this case on return *iosize will contain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
 * the amount that was consumed. Otherwise *iosize will not be modified
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
 * i.e. it will contain the amount that was consumed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
strmakedata(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
	ssize_t   *iosize,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
	struct uio *uiop,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
	stdata_t *stp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
	int32_t flag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2834
	mblk_t **mpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2835
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2836
	mblk_t *mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
	int wroff = (int)stp->sd_wroff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
	ssize_t maxblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
	ssize_t count = *iosize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
	cred_t *cr = CRED();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
	*mpp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
	if (count < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
	maxblk = stp->sd_maxblk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
	if (maxblk == INFPSZ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
		maxblk = count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
	 * Create data part of message, if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
		ssize_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
		dblk_t  *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
		ASSERT(uiop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2861
		size = MIN(count, maxblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2863
		while ((bp = allocb_cred(size + wroff, cr)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
			error = EAGAIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
			if ((uiop->uio_fmode & (FNDELAY|FNONBLOCK)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
			    (error = strwaitbuf(size + wroff, BPRI_MED)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
				if (count == *iosize) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
					*iosize -= count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
					*mpp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2875
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2876
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2877
		dp = bp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2878
		dp->db_cpid = curproc->p_pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2879
		ASSERT(wroff <= dp->db_lim - bp->b_wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
		bp->b_wptr = bp->b_rptr = bp->b_rptr + wroff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2881
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2882
		if (flag & STRUIO_POSTPONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2883
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2884
			 * Setup the stream uio portion of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2885
			 * dblk for subsequent use by struioget().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2886
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2887
			dp->db_struioflag = STRUIO_SPEC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2888
			dp->db_cksumstart = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2889
			dp->db_cksumstuff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2890
			dp->db_cksumend = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2891
			*(long long *)dp->db_struioun.data = 0ll;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2892
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2893
			if (stp->sd_copyflag & STRCOPYCACHED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2894
				uiop->uio_extflg |= UIO_COPY_CACHED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2895
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2896
			if (size != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2897
				error = uiomove(bp->b_wptr, size, UIO_WRITE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2898
				    uiop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2899
				if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
					freeb(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
		bp->b_wptr += size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
		count -= size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
		if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
			mp = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2913
			linkb(mp, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
	} while (count > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
	*mpp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
 * Wait for a buffer to become available. Return non-zero errno
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
 * if not able to wait, 0 if buffer is probably there.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
strwaitbuf(size_t size, int pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
	bufcall_id_t id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
	mutex_enter(&bcall_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
	if ((id = bufcall(size, pri, (void (*)(void *))cv_broadcast,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
	    &ttoproc(curthread)->p_flag_cv)) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
		mutex_exit(&bcall_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
		return (ENOSR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
	if (!cv_wait_sig(&(ttoproc(curthread)->p_flag_cv), &bcall_monitor)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
		unbufcall(id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2937
		mutex_exit(&bcall_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2938
		return (EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2939
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
	unbufcall(id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2941
	mutex_exit(&bcall_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2942
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2943
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
 * This function waits for a read or write event to happen on a stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
 * fmode can specify FNDELAY and/or FNONBLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
 * The timeout is in ms with -1 meaning infinite.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
 * The flag values work as follows:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2950
 *	READWAIT	Check for read side errors, send M_READ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
 *	GETWAIT		Check for read side errors, no M_READ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
 *	WRITEWAIT	Check for write side errors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
 *	NOINTR		Do not return error if nonblocking or timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
 * 	STR_NOERROR	Ignore all errors except STPLEX.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
 *	STR_NOSIG	Ignore/hold signals during the duration of the call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
 *	STR_PEEK	Pass through the strgeterr().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2957
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2958
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2959
strwaitq(stdata_t *stp, int flag, ssize_t count, int fmode, clock_t timout,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2960
    int *done)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2961
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2962
	int slpflg, errs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2963
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2964
	kcondvar_t *sleepon;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2965
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2966
	ssize_t *rd_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2967
	clock_t rval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2968
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2969
	ASSERT(MUTEX_HELD(&stp->sd_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2970
	if ((flag & READWAIT) || (flag & GETWAIT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2971
		slpflg = RSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2972
		sleepon = &_RD(stp->sd_wrq)->q_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2973
		errs = STRDERR|STPLEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2974
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2975
		slpflg = WSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2976
		sleepon = &stp->sd_wrq->q_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2977
		errs = STWRERR|STRHUP|STPLEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2978
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2979
	if (flag & STR_NOERROR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2980
		errs = STPLEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2982
	if (stp->sd_wakeq & slpflg) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2983
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2984
		 * A strwakeq() is pending, no need to sleep.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2985
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2986
		stp->sd_wakeq &= ~slpflg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2987
		*done = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2988
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2989
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2991
	if (fmode & (FNDELAY|FNONBLOCK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2992
		if (!(flag & NOINTR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2993
			error = EAGAIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2994
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2995
			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2996
		*done = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2997
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2998
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2999
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3000
	if (stp->sd_flag & errs) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3001
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3002
		 * Check for errors before going to sleep since the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3003
		 * caller might not have checked this while holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3004
		 * sd_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3005
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3006
		error = strgeterr(stp, errs, (flag & STR_PEEK));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3007
		if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3008
			*done = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3009
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3010
		}
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
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3014
	 * If any module downstream has requested read notification
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3015
	 * by setting SNDMREAD flag using M_SETOPTS, send a message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3016
	 * down stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3017
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3018
	if ((flag & READWAIT) && (stp->sd_flag & SNDMREAD)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3019
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3020
		if (!(mp = allocb_wait(sizeof (ssize_t), BPRI_MED,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3021
		    (flag & STR_NOSIG), &error))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3022
			mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3023
			*done = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3024
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3025
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3026
		mp->b_datap->db_type = M_READ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3027
		rd_count = (ssize_t *)mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3028
		*rd_count = count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3029
		mp->b_wptr += sizeof (ssize_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3030
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3031
		 * Send the number of bytes requested by the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3032
		 * read as the argument to M_READ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3033
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3034
		stream_willservice(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3035
		putnext(stp->sd_wrq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3036
		stream_runservice(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3037
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3039
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3040
		 * If any data arrived due to inline processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3041
		 * of putnext(), don't sleep.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3042
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3043
		if (_RD(stp->sd_wrq)->q_first != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3044
			*done = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3045
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3046
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3047
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3049
	stp->sd_flag |= slpflg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3050
	TRACE_5(TR_FAC_STREAMS_FR, TR_STRWAITQ_WAIT2,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3051
		"strwaitq sleeps (2):%p, %X, %lX, %X, %p",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3052
		stp, flag, count, fmode, done);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3053
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3054
	rval = str_cv_wait(sleepon, &stp->sd_lock, timout, flag & STR_NOSIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3055
	if (rval > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3056
		/* EMPTY */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3057
		TRACE_5(TR_FAC_STREAMS_FR, TR_STRWAITQ_WAKE2,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3058
			"strwaitq awakes(2):%X, %X, %X, %X, %X",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3059
			stp, flag, count, fmode, done);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3060
	} else if (rval == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3061
		TRACE_5(TR_FAC_STREAMS_FR, TR_STRWAITQ_INTR2,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3062
			"strwaitq interrupt #2:%p, %X, %lX, %X, %p",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3063
			stp, flag, count, fmode, done);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3064
		stp->sd_flag &= ~slpflg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3065
		cv_broadcast(sleepon);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3066
		if (!(flag & NOINTR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3067
			error = EINTR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3068
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3069
			error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3070
		*done = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3071
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3072
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3073
		/* timeout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3074
		TRACE_5(TR_FAC_STREAMS_FR, TR_STRWAITQ_TIME,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3075
			"strwaitq timeout:%p, %X, %lX, %X, %p",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3076
			stp, flag, count, fmode, done);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3077
		*done = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3078
		if (!(flag & NOINTR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3079
			return (ETIME);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3080
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3081
			return (0);
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
	 * If the caller implements delayed errors (i.e. queued after data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3085
	 * we can not check for errors here since data as well as an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3086
	 * error might have arrived at the stream head. We return to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3087
	 * have the caller check the read queue before checking for errors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3088
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3089
	if ((stp->sd_flag & errs) && !(flag & STR_DELAYERR)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3090
		error = strgeterr(stp, errs, (flag & STR_PEEK));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3091
		if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3092
			*done = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3093
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3094
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3095
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3096
	*done = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3097
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3098
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3100
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3101
 * Perform job control discipline access checks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3102
 * Return 0 for success and the errno for failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3103
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3105
#define	cantsend(p, t, sig) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3106
	(sigismember(&(p)->p_ignore, sig) || signal_is_blocked((t), sig))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3108
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3109
straccess(struct stdata *stp, enum jcaccess mode)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3110
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3111
	extern kcondvar_t lbolt_cv;	/* XXX: should be in a header file */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3112
	kthread_t *t = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3113
	proc_t *p = ttoproc(t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3114
	sess_t *sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3116
	if (stp->sd_sidp == NULL || stp->sd_vnode->v_type == VFIFO)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3117
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3119
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3120
	sp = p->p_sessp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3121
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3122
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3123
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3124
		 * If this is not the calling process's controlling terminal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3125
		 * or if the calling process is already in the foreground
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3126
		 * then allow access.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3127
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3128
		if (sp->s_dev != stp->sd_vnode->v_rdev ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3129
		    p->p_pgidp == stp->sd_pgidp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3130
			mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3131
			return (0);
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
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3135
		 * Check to see if controlling terminal has been deallocated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3136
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3137
		if (sp->s_vp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3138
			if (!cantsend(p, t, SIGHUP))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3139
				sigtoproc(p, t, SIGHUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3140
			mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3141
			return (EIO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3142
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3144
		if (mode == JCGETP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3145
			mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3146
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3147
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3148
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3149
		if (mode == JCREAD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3150
			if (p->p_detached || cantsend(p, t, SIGTTIN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3151
				mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3152
				return (EIO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3153
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3154
			mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3155
			pgsignal(p->p_pgidp, SIGTTIN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3156
			mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3157
		} else {  /* mode == JCWRITE or JCSETP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3158
			if ((mode == JCWRITE && !(stp->sd_flag & STRTOSTOP)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3159
			    cantsend(p, t, SIGTTOU)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3160
				mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3161
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3162
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3163
			if (p->p_detached) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3164
				mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3165
				return (EIO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3166
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3167
			mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3168
			pgsignal(p->p_pgidp, SIGTTOU);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3169
			mutex_enter(&p->p_lock);
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
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3173
		 * We call cv_wait_sig_swap() to cause the appropriate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3174
		 * action for the jobcontrol signal to take place.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3175
		 * If the signal is being caught, we will take the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3176
		 * EINTR error return.  Otherwise, the default action
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3177
		 * of causing the process to stop will take place.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3178
		 * In this case, we rely on the periodic cv_broadcast() on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3179
		 * &lbolt_cv to wake us up to loop around and test again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3180
		 * We can't get here if the signal is ignored or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3181
		 * if the current thread is blocking the signal.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3182
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3183
		if (!cv_wait_sig_swap(&lbolt_cv, &p->p_lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3184
			mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3185
			return (EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3186
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3187
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3188
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3190
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3191
 * Return size of message of block type (bp->b_datap->db_type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3192
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3193
size_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3194
xmsgsize(mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3195
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3196
	unsigned char type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3197
	size_t count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3199
	type = bp->b_datap->db_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3200
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3201
	for (; bp; bp = bp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3202
		if (type != bp->b_datap->db_type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3203
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3204
		ASSERT(bp->b_wptr >= bp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3205
		count += bp->b_wptr - bp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3206
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3207
	return (count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3208
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3210
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3211
 * Allocate a stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3212
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3213
struct stdata *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3214
shalloc(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3215
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3216
	stdata_t *stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3218
	stp = kmem_cache_alloc(stream_head_cache, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3220
	stp->sd_wrq = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3221
	stp->sd_strtab = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3222
	stp->sd_iocid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3223
	stp->sd_mate = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3224
	stp->sd_freezer = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3225
	stp->sd_refcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3226
	stp->sd_wakeq = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3227
	stp->sd_anchor = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3228
	stp->sd_struiowrq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3229
	stp->sd_struiordq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3230
	stp->sd_struiodnak = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3231
	stp->sd_struionak = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3232
#ifdef C2_AUDIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3233
	stp->sd_t_audit_data = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3234
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3235
	stp->sd_rput_opt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3236
	stp->sd_wput_opt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3237
	stp->sd_read_opt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3238
	stp->sd_rprotofunc = strrput_proto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3239
	stp->sd_rmiscfunc = strrput_misc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3240
	stp->sd_rderrfunc = stp->sd_wrerrfunc = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3241
	stp->sd_ciputctrl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3242
	stp->sd_nciputctrl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3243
	stp->sd_qhead = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3244
	stp->sd_qtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3245
	stp->sd_servid = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3246
	stp->sd_nqueues = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3247
	stp->sd_svcflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3248
	stp->sd_copyflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3249
	return (stp);
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3253
 * Free a stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3254
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3255
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3256
shfree(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3257
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3258
	ASSERT(MUTEX_NOT_HELD(&stp->sd_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3259
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3260
	stp->sd_wrq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3261
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3262
	mutex_enter(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3263
	while (stp->sd_svcflags & STRS_SCHEDULED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3264
		STRSTAT(strwaits);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3265
		cv_wait(&stp->sd_qcv, &stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3266
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3267
	mutex_exit(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3269
	if (stp->sd_ciputctrl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3270
		ASSERT(stp->sd_nciputctrl == n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3271
		SUMCHECK_CIPUTCTRL_COUNTS(stp->sd_ciputctrl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3272
		    stp->sd_nciputctrl, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3273
		ASSERT(ciputctrl_cache != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3274
		kmem_cache_free(ciputctrl_cache, stp->sd_ciputctrl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3275
		stp->sd_ciputctrl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3276
		stp->sd_nciputctrl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3277
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3278
	ASSERT(stp->sd_qhead == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3279
	ASSERT(stp->sd_qtail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3280
	ASSERT(stp->sd_nqueues == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3281
	kmem_cache_free(stream_head_cache, stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3282
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3284
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3285
 * Allocate a pair of queues and a syncq for the pair
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3286
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3287
queue_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3288
allocq(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3289
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3290
	queinfo_t *qip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3291
	queue_t *qp, *wqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3292
	syncq_t	*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3294
	qip = kmem_cache_alloc(queue_cache, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3296
	qp = &qip->qu_rqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3297
	wqp = &qip->qu_wqueue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3298
	sq = &qip->qu_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3300
	qp->q_last	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3301
	qp->q_next	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3302
	qp->q_ptr	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3303
	qp->q_flag	= QUSE | QREADR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3304
	qp->q_bandp	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3305
	qp->q_stream	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3306
	qp->q_syncq	= sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3307
	qp->q_nband	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3308
	qp->q_nfsrv	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3309
	qp->q_draining	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3310
	qp->q_syncqmsgs	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3311
	qp->q_spri	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3312
	qp->q_qtstamp	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3313
	qp->q_sqtstamp	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3314
	qp->q_fp	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3315
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3316
	wqp->q_last	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3317
	wqp->q_next	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3318
	wqp->q_ptr	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3319
	wqp->q_flag	= QUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3320
	wqp->q_bandp	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3321
	wqp->q_stream	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3322
	wqp->q_syncq	= sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3323
	wqp->q_nband	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3324
	wqp->q_nfsrv	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3325
	wqp->q_draining	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3326
	wqp->q_syncqmsgs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3327
	wqp->q_qtstamp	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3328
	wqp->q_sqtstamp	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3329
	wqp->q_spri	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3330
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3331
	sq->sq_count	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3332
	sq->sq_rmqcount	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3333
	sq->sq_flags	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3334
	sq->sq_type	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3335
	sq->sq_callbflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3336
	sq->sq_cancelid	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3337
	sq->sq_ciputctrl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3338
	sq->sq_nciputctrl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3339
	sq->sq_needexcl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3340
	sq->sq_svcflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3341
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3342
	return (qp);
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3346
 * Free a pair of queues and the "attached" syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3347
 * Discard any messages left on the syncq(s), remove the syncq(s) from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3348
 * outer perimeter, and free the syncq(s) if they are not the "attached" syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3349
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3350
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3351
freeq(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3352
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3353
	qband_t *qbp, *nqbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3354
	syncq_t *sq, *outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3355
	queue_t *wqp = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3357
	ASSERT(qp->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3358
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3359
	(void) flush_syncq(qp->q_syncq, qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3360
	(void) flush_syncq(wqp->q_syncq, wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3361
	ASSERT(qp->q_syncqmsgs == 0 && wqp->q_syncqmsgs == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3362
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3363
	outer = qp->q_syncq->sq_outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3364
	if (outer != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3365
		outer_remove(outer, qp->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3366
		if (wqp->q_syncq != qp->q_syncq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3367
			outer_remove(outer, wqp->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3368
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3369
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3370
	 * Free any syncqs that are outside what allocq returned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3371
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3372
	if (qp->q_syncq != SQ(qp) && !(qp->q_flag & QPERMOD))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3373
		free_syncq(qp->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3374
	if (qp->q_syncq != wqp->q_syncq && wqp->q_syncq != SQ(qp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3375
		free_syncq(wqp->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3376
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3377
	ASSERT((qp->q_sqflags & (Q_SQQUEUED | Q_SQDRAINING)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3378
	ASSERT((wqp->q_sqflags & (Q_SQQUEUED | Q_SQDRAINING)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3379
	ASSERT(MUTEX_NOT_HELD(QLOCK(qp)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3380
	ASSERT(MUTEX_NOT_HELD(QLOCK(wqp)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3381
	sq = SQ(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3382
	ASSERT(MUTEX_NOT_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3383
	ASSERT(sq->sq_head == NULL && sq->sq_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3384
	ASSERT(sq->sq_outer == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3385
	ASSERT(sq->sq_onext == NULL && sq->sq_oprev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3386
	ASSERT(sq->sq_callbpend == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3387
	ASSERT(sq->sq_needexcl == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3389
	if (sq->sq_ciputctrl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3390
		ASSERT(sq->sq_nciputctrl == n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3391
		SUMCHECK_CIPUTCTRL_COUNTS(sq->sq_ciputctrl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3392
		    sq->sq_nciputctrl, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3393
		ASSERT(ciputctrl_cache != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3394
		kmem_cache_free(ciputctrl_cache, sq->sq_ciputctrl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3395
		sq->sq_ciputctrl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3396
		sq->sq_nciputctrl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3397
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3399
	ASSERT(qp->q_first == NULL && wqp->q_first == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3400
	ASSERT(qp->q_count == 0 && wqp->q_count == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3401
	ASSERT(qp->q_mblkcnt == 0 && wqp->q_mblkcnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3403
	qp->q_flag &= ~QUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3404
	wqp->q_flag &= ~QUSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3405
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3406
	/* NOTE: Uncomment the assert below once bugid 1159635 is fixed. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3407
	/* ASSERT((qp->q_flag & QWANTW) == 0 && (wqp->q_flag & QWANTW) == 0); */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3409
	qbp = qp->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3410
	while (qbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3411
		nqbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3412
		freeband(qbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3413
		qbp = nqbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3414
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3415
	qbp = wqp->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3416
	while (qbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3417
		nqbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3418
		freeband(qbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3419
		qbp = nqbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3420
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3421
	kmem_cache_free(queue_cache, qp);
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3425
 * Allocate a qband structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3426
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3427
qband_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3428
allocband(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3429
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3430
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3432
	qbp = kmem_cache_alloc(qband_cache, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3433
	if (qbp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3434
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3436
	qbp->qb_next	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3437
	qbp->qb_count	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3438
	qbp->qb_mblkcnt	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3439
	qbp->qb_first	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3440
	qbp->qb_last	= NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3441
	qbp->qb_flag	= 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3443
	return (qbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3444
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3446
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3447
 * Free a qband structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3448
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3449
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3450
freeband(qband_t *qbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3451
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3452
	kmem_cache_free(qband_cache, qbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3453
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3454
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3455
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3456
 * Just like putnextctl(9F), except that allocb_wait() is used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3457
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3458
 * Consolidation Private, and of course only callable from the stream head or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3459
 * routines that may block.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3460
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3461
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3462
putnextctl_wait(queue_t *q, int type)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3463
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3464
	mblk_t *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3465
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3467
	if ((datamsg(type) && (type != M_DELAY)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3468
	    (bp = allocb_wait(0, BPRI_HI, 0, &error)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3469
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3471
	bp->b_datap->db_type = (unsigned char)type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3472
	putnext(q, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3473
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3474
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3475
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3476
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3477
 * run any possible bufcalls.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3478
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3479
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3480
runbufcalls(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3481
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3482
	strbufcall_t *bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3484
	mutex_enter(&bcall_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3485
	mutex_enter(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3487
	if (strbcalls.bc_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3488
		size_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3489
		int nevent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3491
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3492
		 * count how many events are on the list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3493
		 * now so we can check to avoid looping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3494
		 * in low memory situations
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3495
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3496
		nevent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3497
		for (bcp = strbcalls.bc_head; bcp; bcp = bcp->bc_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3498
			nevent++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3500
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3501
		 * get estimate of available memory from kmem_avail().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3502
		 * awake all bufcall functions waiting for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3503
		 * memory whose request could be satisfied
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3504
		 * by 'count' memory and let 'em fight for it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3505
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3506
		count = kmem_avail();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3507
		while ((bcp = strbcalls.bc_head) != NULL && nevent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3508
			STRSTAT(bufcalls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3509
			--nevent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3510
			if (bcp->bc_size <= count) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3511
				bcp->bc_executor = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3512
				mutex_exit(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3513
				(*bcp->bc_func)(bcp->bc_arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3514
				mutex_enter(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3515
				bcp->bc_executor = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3516
				cv_broadcast(&bcall_cv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3517
				strbcalls.bc_head = bcp->bc_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3518
				kmem_free(bcp, sizeof (strbufcall_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3519
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3520
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3521
				 * too big, try again later - note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3522
				 * that nevent was decremented above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3523
				 * so we won't retry this one on this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3524
				 * iteration of the loop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3525
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3526
				if (bcp->bc_next != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3527
					strbcalls.bc_head = bcp->bc_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3528
					bcp->bc_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3529
					strbcalls.bc_tail->bc_next = bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3530
					strbcalls.bc_tail = bcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3531
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3532
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3533
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3534
		if (strbcalls.bc_head == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3535
			strbcalls.bc_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3536
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3538
	mutex_exit(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3539
	mutex_exit(&bcall_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3540
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3543
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3544
 * actually run queue's service routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3545
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3546
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3547
runservice(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3548
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3549
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3550
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3551
	ASSERT(q->q_qinfo->qi_srvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3552
again:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3553
	entersq(q->q_syncq, SQ_SVC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3554
	TRACE_1(TR_FAC_STREAMS_FR, TR_QRUNSERVICE_START,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3555
		"runservice starts:%p", q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3557
	if (!(q->q_flag & QWCLOSE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3558
		(*q->q_qinfo->qi_srvp)(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3560
	TRACE_1(TR_FAC_STREAMS_FR, TR_QRUNSERVICE_END,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3561
		"runservice ends:(%p)", q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3563
	leavesq(q->q_syncq, SQ_SVC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3565
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3566
	if (q->q_flag & QENAB) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3567
		q->q_flag &= ~QENAB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3568
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3569
		goto again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3570
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3571
	q->q_flag &= ~QINSERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3572
	q->q_flag &= ~QBACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3573
	for (qbp = q->q_bandp; qbp; qbp = qbp->qb_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3574
		qbp->qb_flag &= ~QB_BACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3575
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3576
	 * Wakeup thread waiting for the service procedure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3577
	 * to be run (strclose and qdetach).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3578
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3579
	cv_broadcast(&q->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3581
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3582
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3584
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3585
 * Background processing of bufcalls.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3586
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3587
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3588
streams_bufcall_service(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3589
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3590
	callb_cpr_t	cprinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3592
	CALLB_CPR_INIT(&cprinfo, &strbcall_lock, callb_generic_cpr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3593
	    "streams_bufcall_service");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3595
	mutex_enter(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3597
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3598
		if (strbcalls.bc_head != NULL && kmem_avail() > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3599
			mutex_exit(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3600
			runbufcalls();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3601
			mutex_enter(&strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3602
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3603
		if (strbcalls.bc_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3604
			clock_t wt, tick;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3605
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3606
			STRSTAT(bcwaits);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3607
			/* Wait for memory to become available */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3608
			CALLB_CPR_SAFE_BEGIN(&cprinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3609
			tick = SEC_TO_TICK(60);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3610
			time_to_wait(&wt, tick);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3611
			(void) cv_timedwait(&memavail_cv, &strbcall_lock, wt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3612
			CALLB_CPR_SAFE_END(&cprinfo, &strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3613
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3615
		/* Wait for new work to arrive */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3616
		if (strbcalls.bc_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3617
			CALLB_CPR_SAFE_BEGIN(&cprinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3618
			cv_wait(&strbcall_cv, &strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3619
			CALLB_CPR_SAFE_END(&cprinfo, &strbcall_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3620
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3621
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3622
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3624
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3625
 * Background processing of streams background tasks which failed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3626
 * taskq_dispatch.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3627
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3628
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3629
streams_qbkgrnd_service(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3630
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3631
	callb_cpr_t cprinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3632
	queue_t *q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3634
	CALLB_CPR_INIT(&cprinfo, &service_queue, callb_generic_cpr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3635
	    "streams_bkgrnd_service");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3636
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3637
	mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3639
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3640
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3641
		 * Wait for work to arrive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3642
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3643
		while ((freebs_list == NULL) && (qhead == NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3644
			CALLB_CPR_SAFE_BEGIN(&cprinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3645
			cv_wait(&services_to_run, &service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3646
			CALLB_CPR_SAFE_END(&cprinfo, &service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3647
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3648
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3649
		 * Handle all pending freebs requests to free memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3650
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3651
		while (freebs_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3652
			mblk_t *mp = freebs_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3653
			freebs_list = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3654
			mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3655
			mblk_free(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3656
			mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3657
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3658
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3659
		 * Run pending queues.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3660
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3661
		while (qhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3662
			DQ(q, qhead, qtail, q_link);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3663
			ASSERT(q != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3664
			mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3665
			queue_service(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3666
			mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3667
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3668
		ASSERT(qhead == NULL && qtail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3669
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3670
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3671
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3672
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3673
 * Background processing of streams background tasks which failed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3674
 * taskq_dispatch.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3675
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3676
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3677
streams_sqbkgrnd_service(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3678
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3679
	callb_cpr_t cprinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3680
	syncq_t *sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3682
	CALLB_CPR_INIT(&cprinfo, &service_queue, callb_generic_cpr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3683
	    "streams_sqbkgrnd_service");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3685
	mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3687
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3688
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3689
		 * Wait for work to arrive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3690
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3691
		while (sqhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3692
			CALLB_CPR_SAFE_BEGIN(&cprinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3693
			cv_wait(&syncqs_to_run, &service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3694
			CALLB_CPR_SAFE_END(&cprinfo, &service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3695
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3696
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3697
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3698
		 * Run pending syncqs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3699
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3700
		while (sqhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3701
			DQ(sq, sqhead, sqtail, sq_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3702
			ASSERT(sq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3703
			ASSERT(sq->sq_svcflags & SQ_BGTHREAD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3704
			mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3705
			syncq_service(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3706
			mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3707
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3708
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3709
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3711
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3712
 * Disable the syncq and wait for background syncq processing to complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3713
 * If the syncq is placed on the sqhead/sqtail queue, try to remove it from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3714
 * list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3715
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3716
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3717
wait_sq_svc(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3718
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3719
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3720
	sq->sq_svcflags |= SQ_DISABLED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3721
	if (sq->sq_svcflags & SQ_BGTHREAD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3722
		syncq_t *sq_chase;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3723
		syncq_t *sq_curr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3724
		int removed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3726
		ASSERT(sq->sq_servcount == 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3727
		mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3728
		RMQ(sq, sqhead, sqtail, sq_next, sq_chase, sq_curr, removed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3729
		mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3730
		if (removed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3731
			sq->sq_svcflags &= ~SQ_BGTHREAD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3732
			sq->sq_servcount = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3733
			STRSTAT(sqremoved);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3734
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3735
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3736
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3737
	while (sq->sq_servcount != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3738
		sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3739
		cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3740
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3741
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3742
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3743
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3745
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3746
 * Put a syncq on the list of syncq's to be serviced by the sqthread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3747
 * Add the argument to the end of the sqhead list and set the flag
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3748
 * indicating this syncq has been enabled.  If it has already been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3749
 * enabled, don't do anything.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3750
 * This routine assumes that SQLOCK is held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3751
 * NOTE that the lock order is to have the SQLOCK first,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3752
 * so if the service_syncq lock is held, we need to release it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3753
 * before aquiring the SQLOCK (mostly relevant for the background
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3754
 * thread, and this seems to be common among the STREAMS global locks).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3755
 * Note the the sq_svcflags are protected by the SQLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3756
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3757
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3758
sqenable(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3759
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3760
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3761
	 * This is probably not important except for where I believe it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3762
	 * is being called.  At that point, it should be held (and it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3763
	 * is a pain to release it just for this routine, so don't do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3764
	 * it).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3765
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3766
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3767
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3768
	IMPLY(sq->sq_servcount == 0, sq->sq_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3769
	IMPLY(sq->sq_next != NULL, sq->sq_svcflags & SQ_BGTHREAD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3771
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3772
	 * Do not put on list if background thread is scheduled or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3773
	 * syncq is disabled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3774
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3775
	if (sq->sq_svcflags & (SQ_DISABLED | SQ_BGTHREAD))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3776
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3777
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3778
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3779
	 * Check whether we should enable sq at all.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3780
	 * Non PERMOD syncqs may be drained by at most one thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3781
	 * PERMOD syncqs may be drained by several threads but we limit the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3782
	 * total amount to the lesser of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3783
	 *	Number of queues on the squeue and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3784
	 *	Number of CPUs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3785
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3786
	if (sq->sq_servcount != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3787
		if (((sq->sq_type & SQ_PERMOD) == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3788
		    (sq->sq_servcount >= MIN(sq->sq_nqueues, ncpus_online))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3789
			STRSTAT(sqtoomany);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3790
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3791
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3792
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3793
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3794
	sq->sq_tstamp = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3795
	STRSTAT(sqenables);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3796
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3797
	/* Attempt a taskq dispatch */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3798
	sq->sq_servid = (void *)taskq_dispatch(streams_taskq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3799
	    (task_func_t *)syncq_service, sq, TQ_NOSLEEP | TQ_NOQUEUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3800
	if (sq->sq_servid != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3801
		sq->sq_servcount++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3802
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3803
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3805
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3806
	 * This taskq dispatch failed, but a previous one may have succeeded.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3807
	 * Don't try to schedule on the background thread whilst there is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3808
	 * outstanding taskq processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3809
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3810
	if (sq->sq_servcount != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3811
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3812
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3813
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3814
	 * System is low on resources and can't perform a non-sleeping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3815
	 * dispatch. Schedule the syncq for a background thread and mark the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3816
	 * syncq to avoid any further taskq dispatch attempts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3817
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3818
	mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3819
	STRSTAT(taskqfails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3820
	ENQUEUE(sq, sqhead, sqtail, sq_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3821
	sq->sq_svcflags |= SQ_BGTHREAD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3822
	sq->sq_servcount = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3823
	cv_signal(&syncqs_to_run);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3824
	mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3825
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3827
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3828
 * Note: fifo_close() depends on the mblk_t on the queue being freed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3829
 * asynchronously. The asynchronous freeing of messages breaks the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3830
 * recursive call chain of fifo_close() while there are I_SENDFD type of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3831
 * messages refering other file pointers on the queue. Then when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3832
 * closing pipes it can avoid stack overflow in case of daisy-chained
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3833
 * pipes, and also avoid deadlock in case of fifonode_t pairs (which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3834
 * share the same fifolock_t).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3835
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3836
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3837
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3838
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3839
freebs_enqueue(mblk_t *mp, dblk_t *dbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3840
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3841
	ASSERT(dbp->db_mblk == mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3843
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3844
	 * Check data sanity. The dblock should have non-empty free function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3845
	 * It is better to panic here then later when the dblock is freed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3846
	 * asynchronously when the context is lost.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3847
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3848
	if (dbp->db_frtnp->free_func == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3849
		panic("freebs_enqueue: dblock %p has a NULL free callback",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3850
		    (void *) dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3851
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3853
	STRSTAT(freebs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3854
	if (taskq_dispatch(streams_taskq, (task_func_t *)mblk_free, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3855
	    TQ_NOSLEEP) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3856
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3857
		 * System is low on resources and can't perform a non-sleeping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3858
		 * dispatch. Schedule for a background thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3859
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3860
		mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3861
		STRSTAT(taskqfails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3862
		mp->b_next = freebs_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3863
		freebs_list = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3864
		cv_signal(&services_to_run);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3865
		mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3866
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3867
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3868
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3869
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3870
 * Set the QBACK or QB_BACK flag in the given queue for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3871
 * the given priority band.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3872
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3873
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3874
setqback(queue_t *q, unsigned char pri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3875
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3876
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3877
	qband_t *qbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3878
	qband_t **qbpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3879
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3880
	ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3881
	if (pri != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3882
		if (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3883
			qbpp = &q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3884
			while (*qbpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3885
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3886
			while (pri > q->q_nband) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3887
				if ((*qbpp = allocband()) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3888
					cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3889
					    "setqback: can't allocate qband\n");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3890
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3891
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3892
				(*qbpp)->qb_hiwat = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3893
				(*qbpp)->qb_lowat = q->q_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3894
				q->q_nband++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3895
				qbpp = &(*qbpp)->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3896
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3897
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3898
		qbp = q->q_bandp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3899
		i = pri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3900
		while (--i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3901
			qbp = qbp->qb_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3902
		qbp->qb_flag |= QB_BACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3903
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3904
		q->q_flag |= QBACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3905
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3906
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3908
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3909
strcopyin(void *from, void *to, size_t len, int copyflag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3910
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3911
	if (copyflag & U_TO_K) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3912
		ASSERT((copyflag & K_TO_K) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3913
		if (copyin(from, to, len))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3914
			return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3915
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3916
		ASSERT(copyflag & K_TO_K);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3917
		bcopy(from, to, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3918
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3919
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3920
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3922
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3923
strcopyout(void *from, void *to, size_t len, int copyflag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3924
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3925
	if (copyflag & U_TO_K) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3926
		if (copyout(from, to, len))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3927
			return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3928
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3929
		ASSERT(copyflag & K_TO_K);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3930
		bcopy(from, to, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3931
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3932
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3933
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3935
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3936
 * strsignal_nolock() posts a signal to the process(es) at the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3937
 * It assumes that the stream head lock is already held, whereas strsignal()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3938
 * acquires the lock first.  This routine was created because a few callers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3939
 * release the stream head lock before calling only to re-acquire it after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3940
 * it returns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3941
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3942
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3943
strsignal_nolock(stdata_t *stp, int sig, int32_t band)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3944
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3945
	ASSERT(MUTEX_HELD(&stp->sd_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3946
	switch (sig) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3947
	case SIGPOLL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3948
		if (stp->sd_sigflags & S_MSG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3949
			strsendsig(stp->sd_siglist, S_MSG, (uchar_t)band, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3950
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3951
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3952
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3953
		if (stp->sd_pgidp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3954
			pgsignal(stp->sd_pgidp, sig);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3955
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3956
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3957
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3958
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3960
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3961
strsignal(stdata_t *stp, int sig, int32_t band)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3962
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3963
	TRACE_3(TR_FAC_STREAMS_FR, TR_SENDSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3964
		"strsignal:%p, %X, %X", stp, sig, band);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3966
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3967
	switch (sig) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3968
	case SIGPOLL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3969
		if (stp->sd_sigflags & S_MSG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3970
			strsendsig(stp->sd_siglist, S_MSG, (uchar_t)band, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3971
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3973
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3974
		if (stp->sd_pgidp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3975
			pgsignal(stp->sd_pgidp, sig);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3976
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3977
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3978
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3979
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3980
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3982
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3983
strhup(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3984
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3985
	pollwakeup(&stp->sd_pollist, POLLHUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3986
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3987
	if (stp->sd_sigflags & S_HANGUP)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3988
		strsendsig(stp->sd_siglist, S_HANGUP, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3989
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3990
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3991
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3992
void
560
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  3993
stralloctty(stdata_t *stp)
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  3994
{
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  3995
	proc_t *p = curproc;
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  3996
	sess_t *sp = p->p_sessp;
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  3997
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3998
	mutex_enter(&stp->sd_lock);
560
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  3999
	/*
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4000
	 * No need to hold the session lock or do a TTY_HOLD() because
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4001
	 * this is the only thread that can be the session leader and not
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4002
	 * have a controlling tty.
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4003
	 */
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4004
	if ((stp->sd_flag &
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4005
	    (STRHUP|STRDERR|STWRERR|STPLEX|STRISTTY)) == STRISTTY &&
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4006
	    stp->sd_sidp == NULL &&		/* not allocated as ctty */
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4007
	    sp->s_sidp == p->p_pidp &&		/* session leader */
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4008
	    sp->s_flag != SESS_CLOSE &&		/* session is not closing */
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4009
	    sp->s_vp == NULL) {			/* without ctty */
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4010
		ASSERT(stp->sd_pgidp == NULL);
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4011
		alloctty(p, makectty(stp->sd_vnode));
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4012
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4013
		mutex_enter(&pidlock);
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4014
		stp->sd_sidp = sp->s_sidp;
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4015
		stp->sd_pgidp = sp->s_sidp;
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4016
		PID_HOLD(stp->sd_pgidp);
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4017
		PID_HOLD(stp->sd_sidp);
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4018
		mutex_exit(&pidlock);
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4019
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4020
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4021
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4023
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4024
strfreectty(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4025
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4026
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4027
	pgsignal(stp->sd_pgidp, SIGHUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4028
	mutex_enter(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4029
	PID_RELE(stp->sd_pgidp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4030
	PID_RELE(stp->sd_sidp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4031
	stp->sd_pgidp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4032
	stp->sd_sidp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4033
	mutex_exit(&pidlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4034
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4035
	if (!(stp->sd_flag & STRHUP))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4036
		strhup(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4037
}
560
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4038
/*
fab7db0411ac 6322179 strfreectty() passed a stream that was not yet a ctty
meem
parents: 235
diff changeset
  4039
 * Backenable the first queue upstream from `q' with a service procedure.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4040
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4041
void
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4042
backenable(queue_t *q, uchar_t pri)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4043
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4044
	queue_t	*nq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4045
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4046
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4047
	 * our presence might not prevent other modules in our own
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4048
	 * stream from popping/pushing since the caller of getq might not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4049
	 * have a claim on the queue (some drivers do a getq on somebody
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4050
	 * else's queue - they know that the queue itself is not going away
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4051
	 * but the framework has to guarantee q_next in that stream.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4052
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4053
	claimstr(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4054
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4055
	/* find nearest back queue with service proc */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4056
	for (nq = backq(q); nq && !nq->q_qinfo->qi_srvp; nq = backq(nq)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4057
		ASSERT(STRMATED(q->q_stream) || STREAM(q) == STREAM(nq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4058
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4060
	if (nq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4061
		kthread_t *freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4062
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4063
		 * backenable can be called either with no locks held
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4064
		 * or with the stream frozen (the latter occurs when a module
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4065
		 * calls rmvq with the stream frozen.) If the stream is frozen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4066
		 * by the caller the caller will hold all qlocks in the stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4067
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4068
		freezer = STREAM(q)->sd_freezer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4069
		if (freezer != curthread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4070
			mutex_enter(QLOCK(nq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4071
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4072
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4073
		else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4074
			ASSERT(frozenstr(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4075
			ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4076
			ASSERT(MUTEX_HELD(QLOCK(nq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4077
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4078
#endif
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4079
		setqback(nq, pri);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4080
		qenable_locked(nq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4081
		if (freezer != curthread)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4082
			mutex_exit(QLOCK(nq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4083
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4084
	releasestr(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4085
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4087
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4088
 * Return the appropriate errno when one of flags_to_check is set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4089
 * in sd_flags. Uses the exported error routines if they are set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4090
 * Will return 0 if non error is set (or if the exported error routines
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4091
 * do not return an error).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4092
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4093
 * If there is both a read and write error to check we prefer the read error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4094
 * Also, give preference to recorded errno's over the error functions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4095
 * The flags that are handled are:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4096
 *	STPLEX		return EINVAL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4097
 *	STRDERR		return sd_rerror (and clear if STRDERRNONPERSIST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4098
 *	STWRERR		return sd_werror (and clear if STWRERRNONPERSIST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4099
 *	STRHUP		return sd_werror
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4100
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4101
 * If the caller indicates that the operation is a peek a nonpersistent error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4102
 * is not cleared.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4103
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4104
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4105
strgeterr(stdata_t *stp, int32_t flags_to_check, int ispeek)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4106
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4107
	int32_t sd_flag = stp->sd_flag & flags_to_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4108
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4110
	ASSERT(MUTEX_HELD(&stp->sd_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4111
	ASSERT((flags_to_check & ~(STRDERR|STWRERR|STRHUP|STPLEX)) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4112
	if (sd_flag & STPLEX)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4113
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4114
	else if (sd_flag & STRDERR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4115
		error = stp->sd_rerror;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4116
		if ((stp->sd_flag & STRDERRNONPERSIST) && !ispeek) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4117
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4118
			 * Read errors are non-persistent i.e. discarded once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4119
			 * returned to a non-peeking caller,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4120
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4121
			stp->sd_rerror = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4122
			stp->sd_flag &= ~STRDERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4123
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4124
		if (error == 0 && stp->sd_rderrfunc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4125
			int clearerr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4127
			error = (*stp->sd_rderrfunc)(stp->sd_vnode, ispeek,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4128
						&clearerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4129
			if (clearerr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4130
				stp->sd_flag &= ~STRDERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4131
				stp->sd_rderrfunc = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4132
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4133
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4134
	} else if (sd_flag & STWRERR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4135
		error = stp->sd_werror;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4136
		if ((stp->sd_flag & STWRERRNONPERSIST) && !ispeek) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4137
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4138
			 * Write errors are non-persistent i.e. discarded once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4139
			 * returned to a non-peeking caller,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4140
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4141
			stp->sd_werror = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4142
			stp->sd_flag &= ~STWRERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4143
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4144
		if (error == 0 && stp->sd_wrerrfunc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4145
			int clearerr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4147
			error = (*stp->sd_wrerrfunc)(stp->sd_vnode, ispeek,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4148
						&clearerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4149
			if (clearerr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4150
				stp->sd_flag &= ~STWRERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4151
				stp->sd_wrerrfunc = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4152
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4153
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4154
	} else if (sd_flag & STRHUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4155
		/* sd_werror set when STRHUP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4156
		error = stp->sd_werror;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4157
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4158
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4159
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4162
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4163
 * single-thread open/close/push/pop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4164
 * for twisted streams also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4165
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4166
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4167
strstartplumb(stdata_t *stp, int flag, int cmd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4168
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4169
	int waited = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4170
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4172
	if (STRMATED(stp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4173
		struct stdata *stmatep = stp->sd_mate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4175
		STRLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4176
		while (waited) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4177
			waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4178
			while (stmatep->sd_flag & (STWOPEN|STRCLOSE|STRPLUMB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4179
				if ((cmd == I_POP) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4180
				    (flag & (FNDELAY|FNONBLOCK))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4181
					STRUNLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4182
					return (EAGAIN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4183
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4184
				waited = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4185
				mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4186
				if (!cv_wait_sig(&stmatep->sd_monitor,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4187
				    &stmatep->sd_lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4188
					mutex_exit(&stmatep->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4189
					return (EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4190
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4191
				mutex_exit(&stmatep->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4192
				STRLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4193
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4194
			while (stp->sd_flag & (STWOPEN|STRCLOSE|STRPLUMB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4195
				if ((cmd == I_POP) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4196
					(flag & (FNDELAY|FNONBLOCK))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4197
					STRUNLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4198
					return (EAGAIN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4199
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4200
				waited = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4201
				mutex_exit(&stmatep->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4202
				if (!cv_wait_sig(&stp->sd_monitor,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4203
				    &stp->sd_lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4204
					mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4205
					return (EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4206
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4207
				mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4208
				STRLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4209
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4210
			if (stp->sd_flag & (STRDERR|STWRERR|STRHUP|STPLEX)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4211
				error = strgeterr(stp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4212
					STRDERR|STWRERR|STRHUP|STPLEX, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4213
				if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4214
					STRUNLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4215
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4216
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4217
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4218
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4219
		stp->sd_flag |= STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4220
		STRUNLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4221
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4222
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4223
		while (stp->sd_flag & (STWOPEN|STRCLOSE|STRPLUMB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4224
			if (((cmd == I_POP) || (cmd == _I_REMOVE)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4225
			    (flag & (FNDELAY|FNONBLOCK))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4226
				mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4227
				return (EAGAIN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4228
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4229
			if (!cv_wait_sig(&stp->sd_monitor, &stp->sd_lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4230
				mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4231
				return (EINTR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4232
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4233
			if (stp->sd_flag & (STRDERR|STWRERR|STRHUP|STPLEX)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4234
				error = strgeterr(stp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4235
					STRDERR|STWRERR|STRHUP|STPLEX, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4236
				if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4237
					mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4238
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4239
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4240
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4241
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4242
		stp->sd_flag |= STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4243
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4244
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4245
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4246
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4248
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4249
 * Complete the plumbing operation associated with stream `stp'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4250
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4251
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4252
strendplumb(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4253
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4254
	ASSERT(MUTEX_HELD(&stp->sd_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4255
	ASSERT(stp->sd_flag & STRPLUMB);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4256
	stp->sd_flag &= ~STRPLUMB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4257
	cv_broadcast(&stp->sd_monitor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4258
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4259
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4260
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4261
 * This describes how the STREAMS framework handles synchronization
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4262
 * during open/push and close/pop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4263
 * The key interfaces for open and close are qprocson and qprocsoff,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4264
 * respectively. While the close case in general is harder both open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4265
 * have close have significant similarities.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4266
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4267
 * During close the STREAMS framework has to both ensure that there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4268
 * are no stale references to the queue pair (and syncq) that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4269
 * are being closed and also provide the guarantees that are documented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4270
 * in qprocsoff(9F).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4271
 * If there are stale references to the queue that is closing it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4272
 * result in kernel memory corruption or kernel panics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4273
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4274
 * Note that is it up to the module/driver to ensure that it itself
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4275
 * does not have any stale references to the closing queues once its close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4276
 * routine returns. This includes:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4277
 *  - Cancelling any timeout/bufcall/qtimeout/qbufcall callback routines
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4278
 *    associated with the queues. For timeout and bufcall callbacks the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4279
 *    module/driver also has to ensure (or wait for) any callbacks that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4280
 *    are in progress.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4281
 *  - If the module/driver is using esballoc it has to ensure that any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4282
 *    esballoc free functions do not refer to a queue that has closed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4283
 *    (Note that in general the close routine can not wait for the esballoc'ed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4284
 *    messages to be freed since that can cause a deadlock.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4285
 *  - Cancelling any interrupts that refer to the closing queues and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4286
 *    also ensuring that there are no interrupts in progress that will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4287
 *    refer to the closing queues once the close routine returns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4288
 *  - For multiplexors removing any driver global state that refers to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4289
 *    the closing queue and also ensuring that there are no threads in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4290
 *    the multiplexor that has picked up a queue pointer but not yet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4291
 *    finished using it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4292
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4293
 * In addition, a driver/module can only reference the q_next pointer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4294
 * in its open, close, put, or service procedures or in a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4295
 * qtimeout/qbufcall callback procedure executing "on" the correct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4296
 * stream. Thus it can not reference the q_next pointer in an interrupt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4297
 * routine or a timeout, bufcall or esballoc callback routine. Likewise
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4298
 * it can not reference q_next of a different queue e.g. in a mux that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4299
 * passes messages from one queues put/service procedure to another queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4300
 * In all the cases when the driver/module can not access the q_next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4301
 * field it must use the *next* versions e.g. canputnext instead of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4302
 * canput(q->q_next) and putnextctl instead of putctl(q->q_next, ...).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4303
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4304
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4305
 * Assuming that the driver/module conforms to the above constraints
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4306
 * the STREAMS framework has to avoid stale references to q_next for all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4307
 * the framework internal cases which include (but are not limited to):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4308
 *  - Threads in canput/canputnext/backenable and elsewhere that are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4309
 *    walking q_next.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4310
 *  - Messages on a syncq that have a reference to the queue through b_queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4311
 *  - Messages on an outer perimeter (syncq) that have a reference to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4312
 *    queue through b_queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4313
 *  - Threads that use q_nfsrv (e.g. canput) to find a queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4314
 *    Note that only canput and bcanput use q_nfsrv without any locking.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4315
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4316
 * The STREAMS framework providing the qprocsoff(9F) guarantees means that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4317
 * after qprocsoff returns, the framework has to ensure that no threads can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4318
 * enter the put or service routines for the closing read or write-side queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4319
 * In addition to preventing "direct" entry into the put procedures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4320
 * the framework also has to prevent messages being drained from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4321
 * the syncq or the outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4322
 * XXX Note that currently qdetach does relies on D_MTOCEXCL as the only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4323
 * mechanism to prevent qwriter(PERIM_OUTER) from running after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4324
 * qprocsoff has returned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4325
 * Note that if a module/driver uses put(9F) on one of its own queues
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4326
 * it is up to the module/driver to ensure that the put() doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4327
 * get called when the queue is closing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4328
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4329
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4330
 * The framework aspects of the above "contract" is implemented by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4331
 * qprocsoff, removeq, and strlock:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4332
 *  - qprocsoff (disable_svc) sets QWCLOSE to prevent runservice from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4333
 *    entering the service procedures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4334
 *  - strlock acquires the sd_lock and sd_reflock to prevent putnext,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4335
 *    canputnext, backenable etc from dereferencing the q_next that will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4336
 *    soon change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4337
 *  - strlock waits for sd_refcnt to be zero to wait for e.g. any canputnext
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4338
 *    or other q_next walker that uses claimstr/releasestr to finish.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4339
 *  - optionally for every syncq in the stream strlock acquires all the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4340
 *    sq_lock's and waits for all sq_counts to drop to a value that indicates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4341
 *    that no thread executes in the put or service procedures and that no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4342
 *    thread is draining into the module/driver. This ensures that no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4343
 *    open, close, put, service, or qtimeout/qbufcall callback procedure is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4344
 *    currently executing hence no such thread can end up with the old stale
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4345
 *    q_next value and no canput/backenable can have the old stale
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4346
 *    q_nfsrv/q_next.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4347
 *  - qdetach (wait_svc) makes sure that any scheduled or running threads
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4348
 *    have either finished or observed the QWCLOSE flag and gone away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4349
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4352
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4353
 * Get all the locks necessary to change q_next.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4354
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4355
 * Wait for sd_refcnt to reach 0 and, if sqlist is present, wait for  the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4356
 * sq_count of each syncq in the list to drop to sq_rmqcount, indicating that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4357
 * the only threads inside the sqncq are threads currently calling removeq().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4358
 * Since threads calling removeq() are in the process of removing their queues
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4359
 * from the stream, we do not need to worry about them accessing a stale q_next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4360
 * pointer and thus we do not need to wait for them to exit (in fact, waiting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4361
 * for them can cause deadlock).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4362
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4363
 * This routine is subject to starvation since it does not set any flag to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4364
 * prevent threads from entering a module in the stream(i.e. sq_count can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4365
 * increase on some syncq while it is waiting on some other syncq.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4366
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4367
 * Assumes that only one thread attempts to call strlock for a given
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4368
 * stream. If this is not the case the two threads would deadlock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4369
 * This assumption is guaranteed since strlock is only called by insertq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4370
 * and removeq and streams plumbing changes are single-threaded for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4371
 * a given stream using the STWOPEN, STRCLOSE, and STRPLUMB flags.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4372
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4373
 * For pipes, it is not difficult to atomically designate a pair of streams
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4374
 * to be mated. Once mated atomically by the framework the twisted pair remain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4375
 * configured that way until dismantled atomically by the framework.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4376
 * When plumbing takes place on a twisted stream it is necessary to ensure that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4377
 * this operation is done exclusively on the twisted stream since two such
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4378
 * operations, each initiated on different ends of the pipe will deadlock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4379
 * waiting for each other to complete.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4380
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4381
 * On entry, no locks should be held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4382
 * The locks acquired and held by strlock depends on a few factors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4383
 * - If sqlist is non-NULL all the syncq locks in the sqlist will be acquired
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4384
 *   and held on exit and all sq_count are at an acceptable level.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4385
 * - In all cases, sd_lock and sd_reflock are acquired and held on exit with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4386
 *   sd_refcnt being zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4387
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4389
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4390
strlock(struct stdata *stp, sqlist_t *sqlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4391
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4392
	syncql_t *sql, *sql2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4393
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4394
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4395
	 * Wait for any claimstr to go away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4396
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4397
	if (STRMATED(stp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4398
		struct stdata *stp1, *stp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4400
		STRLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4401
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4402
		 * Note that the selection of locking order is not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4403
		 * important, just that they are always aquired in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4404
		 * the same order.  To assure this, we choose this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4405
		 * order based on the value of the pointer, and since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4406
		 * the pointer will not change for the life of this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4407
		 * pair, we will always grab the locks in the same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4408
		 * order (and hence, prevent deadlocks).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4409
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4410
		if (&(stp->sd_lock) > &((stp->sd_mate)->sd_lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4411
			stp1 = stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4412
			stp2 = stp->sd_mate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4413
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4414
			stp2 = stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4415
			stp1 = stp->sd_mate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4416
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4417
		mutex_enter(&stp1->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4418
		if (stp1->sd_refcnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4419
			STRUNLOCKMATES(stp);
166
519e5268bee7 4657000 releasestr() should only wakeup waiters when sq_refcnt is zero.
xy158873
parents: 0
diff changeset
  4420
			cv_wait(&stp1->sd_refmonitor, &stp1->sd_reflock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4421
			mutex_exit(&stp1->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4422
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4423
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4424
		mutex_enter(&stp2->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4425
		if (stp2->sd_refcnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4426
			STRUNLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4427
			mutex_exit(&stp1->sd_reflock);
166
519e5268bee7 4657000 releasestr() should only wakeup waiters when sq_refcnt is zero.
xy158873
parents: 0
diff changeset
  4428
			cv_wait(&stp2->sd_refmonitor, &stp2->sd_reflock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4429
			mutex_exit(&stp2->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4430
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4431
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4432
		STREAM_PUTLOCKS_ENTER(stp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4433
		STREAM_PUTLOCKS_ENTER(stp2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4434
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4435
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4436
		mutex_enter(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4437
		while (stp->sd_refcnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4438
			mutex_exit(&stp->sd_lock);
166
519e5268bee7 4657000 releasestr() should only wakeup waiters when sq_refcnt is zero.
xy158873
parents: 0
diff changeset
  4439
			cv_wait(&stp->sd_refmonitor, &stp->sd_reflock);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4440
			if (mutex_tryenter(&stp->sd_lock) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4441
				mutex_exit(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4442
				mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4443
				mutex_enter(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4444
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4445
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4446
		STREAM_PUTLOCKS_ENTER(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4447
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4449
	if (sqlist == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4450
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4452
	for (sql = sqlist->sqlist_head; sql; sql = sql->sql_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4453
		syncq_t *sq = sql->sql_sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4454
		uint16_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4456
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4457
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4458
		ASSERT(sq->sq_rmqcount <= count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4459
		SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4460
		SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4461
		if (count == sq->sq_rmqcount)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4462
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4464
		/* Failed - drop all locks that we have acquired so far */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4465
		if (STRMATED(stp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4466
			STREAM_PUTLOCKS_EXIT(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4467
			STREAM_PUTLOCKS_EXIT(stp->sd_mate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4468
			STRUNLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4469
			mutex_exit(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4470
			mutex_exit(&stp->sd_mate->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4471
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4472
			STREAM_PUTLOCKS_EXIT(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4473
			mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4474
			mutex_exit(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4475
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4476
		for (sql2 = sqlist->sqlist_head; sql2 != sql;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4477
		    sql2 = sql2->sql_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4478
			SQ_PUTLOCKS_EXIT(sql2->sql_sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4479
			mutex_exit(SQLOCK(sql2->sql_sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4480
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4481
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4482
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4483
		 * The wait loop below may starve when there are many threads
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4484
		 * claiming the syncq. This is especially a problem with permod
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4485
		 * syncqs (IP). To lessen the impact of the problem we increment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4486
		 * sq_needexcl and clear fastbits so that putnexts will slow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4487
		 * down and call sqenable instead of draining right away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4488
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4489
		sq->sq_needexcl++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4490
		SQ_PUTCOUNT_CLRFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4491
		while (count > sq->sq_rmqcount) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4492
			sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4493
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4494
			cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4495
			count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4496
			SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4497
			SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4498
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4499
		sq->sq_needexcl--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4500
		if (sq->sq_needexcl == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4501
			SQ_PUTCOUNT_SETFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4502
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4503
		ASSERT(count == sq->sq_rmqcount);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4504
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4505
		goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4506
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4507
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4509
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4510
 * Drop all the locks that strlock acquired.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4511
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4512
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4513
strunlock(struct stdata *stp, sqlist_t *sqlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4514
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4515
	syncql_t *sql;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4517
	if (STRMATED(stp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4518
		STREAM_PUTLOCKS_EXIT(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4519
		STREAM_PUTLOCKS_EXIT(stp->sd_mate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4520
		STRUNLOCKMATES(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4521
		mutex_exit(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4522
		mutex_exit(&stp->sd_mate->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4523
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4524
		STREAM_PUTLOCKS_EXIT(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4525
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4526
		mutex_exit(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4527
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4529
	if (sqlist == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4530
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4532
	for (sql = sqlist->sqlist_head; sql; sql = sql->sql_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4533
		SQ_PUTLOCKS_EXIT(sql->sql_sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4534
		mutex_exit(SQLOCK(sql->sql_sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4535
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4536
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4537
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4538
/*
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4539
 * When the module has service procedure, we need check if the next
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4540
 * module which has service procedure is in flow control to trigger
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4541
 * the backenable.
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4542
 */
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4543
static void
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4544
backenable_insertedq(queue_t *q)
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4545
{
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4546
	qband_t	*qbp;
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4547
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4548
	claimstr(q);
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4549
	if (q->q_qinfo->qi_srvp != NULL && q->q_next != NULL) {
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4550
		if (q->q_next->q_nfsrv->q_flag & QWANTW)
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4551
			backenable(q, 0);
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4552
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4553
		qbp = q->q_next->q_nfsrv->q_bandp;
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4554
		for (; qbp != NULL; qbp = qbp->qb_next)
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4555
			if ((qbp->qb_flag & QB_WANTW) && qbp->qb_first != NULL)
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4556
				backenable(q, qbp->qb_first->b_band);
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4557
	}
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4558
	releasestr(q);
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4559
}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4561
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4562
 * Given two read queues, insert a new single one after another.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4563
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4564
 * This routine acquires all the necessary locks in order to change
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4565
 * q_next and related pointer using strlock().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4566
 * It depends on the stream head ensuring that there are no concurrent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4567
 * insertq or removeq on the same stream. The stream head ensures this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4568
 * using the flags STWOPEN, STRCLOSE, and STRPLUMB.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4569
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4570
 * Note that no syncq locks are held during the q_next change. This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4571
 * applied to all streams since, unlike removeq, there is no problem of stale
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4572
 * pointers when adding a module to the stream. Thus drivers/modules that do a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4573
 * canput(rq->q_next) would never get a closed/freed queue pointer even if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4574
 * applied this optimization to all streams.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4575
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4576
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4577
insertq(struct stdata *stp, queue_t *new)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4578
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4579
	queue_t	*after;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4580
	queue_t *wafter;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4581
	queue_t *wnew = _WR(new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4582
	boolean_t have_fifo = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4584
	if (new->q_flag & _QINSERTING) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4585
		ASSERT(stp->sd_vnode->v_type != VFIFO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4586
		after = new->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4587
		wafter = _WR(new->q_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4588
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4589
		after = _RD(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4590
		wafter = stp->sd_wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4591
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4593
	TRACE_2(TR_FAC_STREAMS_FR, TR_INSERTQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4594
		"insertq:%p, %p", after, new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4595
	ASSERT(after->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4596
	ASSERT(new->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4598
	strlock(stp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4599
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4600
	/* Do we have a FIFO? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4601
	if (wafter->q_next == after) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4602
		have_fifo = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4603
		wnew->q_next = new;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4604
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4605
		wnew->q_next = wafter->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4606
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4607
	new->q_next = after;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4609
	set_nfsrv_ptr(new, wnew, after, wafter);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4610
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4611
	 * set_nfsrv_ptr() needs to know if this is an insertion or not,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4612
	 * so only reset this flag after calling it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4613
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4614
	new->q_flag &= ~_QINSERTING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4616
	if (have_fifo) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4617
		wafter->q_next = wnew;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4618
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4619
		if (wafter->q_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4620
			_OTHERQ(wafter->q_next)->q_next = new;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4621
		wafter->q_next = wnew;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4622
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4624
	set_qend(new);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4625
	/* The QEND flag might have to be updated for the upstream guy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4626
	set_qend(after);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4628
	ASSERT(_SAMESTR(new) == O_SAMESTR(new));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4629
	ASSERT(_SAMESTR(wnew) == O_SAMESTR(wnew));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4630
	ASSERT(_SAMESTR(after) == O_SAMESTR(after));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4631
	ASSERT(_SAMESTR(wafter) == O_SAMESTR(wafter));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4632
	strsetuio(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4634
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4635
	 * If this was a module insertion, bump the push count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4636
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4637
	if (!(new->q_flag & QISDRV))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4638
		stp->sd_pushcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4640
	strunlock(stp, NULL);
235
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4641
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4642
	/* check if the write Q needs backenable */
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4643
	backenable_insertedq(wnew);
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4644
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4645
	/* check if the read Q needs backenable */
e87a1ba1f4a2 6233064 svc.startd is wedged trying to talk to the system console
micheng
parents: 166
diff changeset
  4646
	backenable_insertedq(new);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4647
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4649
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4650
 * Given a read queue, unlink it from any neighbors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4651
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4652
 * This routine acquires all the necessary locks in order to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4653
 * change q_next and related pointers and also guard against
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4654
 * stale references (e.g. through q_next) to the queue that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4655
 * is being removed. It also plays part of the role in ensuring
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4656
 * that the module's/driver's put procedure doesn't get called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4657
 * after qprocsoff returns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4658
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4659
 * Removeq depends on the stream head ensuring that there are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4660
 * no concurrent insertq or removeq on the same stream. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4661
 * stream head ensures this using the flags STWOPEN, STRCLOSE and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4662
 * STRPLUMB.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4663
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4664
 * The set of locks needed to remove the queue is different in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4665
 * different cases:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4666
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4667
 * Acquire sd_lock, sd_reflock, and all the syncq locks in the stream after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4668
 * waiting for the syncq reference count to drop to 0 indicating that no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4669
 * non-close threads are present anywhere in the stream. This ensures that any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4670
 * module/driver can reference q_next in its open, close, put, or service
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4671
 * procedures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4672
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4673
 * The sq_rmqcount counter tracks the number of threads inside removeq().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4674
 * strlock() ensures that there is either no threads executing inside perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4675
 * or there is only a thread calling qprocsoff().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4676
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4677
 * strlock() compares the value of sq_count with the number of threads inside
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4678
 * removeq() and waits until sq_count is equal to sq_rmqcount. We need to wakeup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4679
 * any threads waiting in strlock() when the sq_rmqcount increases.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4680
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4682
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4683
removeq(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4684
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4685
	queue_t *wqp = _WR(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4686
	struct stdata *stp = STREAM(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4687
	sqlist_t *sqlist = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4688
	boolean_t isdriver;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4689
	int moved;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4690
	syncq_t *sq = qp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4691
	syncq_t *wsq = wqp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4692
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4693
	ASSERT(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4695
	TRACE_2(TR_FAC_STREAMS_FR, TR_REMOVEQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4696
		"removeq:%p %p", qp, wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4697
	ASSERT(qp->q_flag&QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4699
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4700
	 * For queues using Synchronous streams, we must wait for all threads in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4701
	 * rwnext() to drain out before proceeding.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4702
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4703
	if (qp->q_flag & QSYNCSTR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4704
		/* First, we need wakeup any threads blocked in rwnext() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4705
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4706
		if (sq->sq_flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4707
			sq->sq_flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4708
			cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4709
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4710
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4712
		if (wsq != sq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4713
			mutex_enter(SQLOCK(wsq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4714
			if (wsq->sq_flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4715
				wsq->sq_flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4716
				cv_broadcast(&wsq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4717
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4718
			mutex_exit(SQLOCK(wsq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4719
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4721
		mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4722
		while (qp->q_rwcnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4723
			qp->q_flag |= QWANTRMQSYNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4724
			cv_wait(&qp->q_wait, QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4725
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4726
		mutex_exit(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4727
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4728
		mutex_enter(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4729
		while (wqp->q_rwcnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4730
			wqp->q_flag |= QWANTRMQSYNC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4731
			cv_wait(&wqp->q_wait, QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4732
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4733
		mutex_exit(QLOCK(wqp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4734
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4735
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4736
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4737
	sq->sq_rmqcount++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4738
	if (sq->sq_flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4739
		sq->sq_flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4740
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4741
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4742
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4744
	isdriver = (qp->q_flag & QISDRV);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4745
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4746
	sqlist = sqlist_build(qp, stp, STRMATED(stp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4747
	strlock(stp, sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4748
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4749
	reset_nfsrv_ptr(qp, wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4751
	ASSERT(wqp->q_next == NULL || backq(qp)->q_next == qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4752
	ASSERT(qp->q_next == NULL || backq(wqp)->q_next == wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4753
	/* Do we have a FIFO? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4754
	if (wqp->q_next == qp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4755
		stp->sd_wrq->q_next = _RD(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4756
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4757
		if (wqp->q_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4758
			backq(qp)->q_next = qp->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4759
		if (qp->q_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4760
			backq(wqp)->q_next = wqp->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4761
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4762
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4763
	/* The QEND flag might have to be updated for the upstream guy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4764
	if (qp->q_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4765
		set_qend(qp->q_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4767
	ASSERT(_SAMESTR(stp->sd_wrq) == O_SAMESTR(stp->sd_wrq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4768
	ASSERT(_SAMESTR(_RD(stp->sd_wrq)) == O_SAMESTR(_RD(stp->sd_wrq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4769
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4770
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4771
	 * Move any messages destined for the put procedures to the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4772
	 * syncq in line. Otherwise free them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4773
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4774
	moved = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4775
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4776
	 * Quick check to see whether there are any messages or events.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4777
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4778
	if (qp->q_syncqmsgs != 0 || (qp->q_syncq->sq_flags & SQ_EVENTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4779
		moved += propagate_syncq(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4780
	if (wqp->q_syncqmsgs != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4781
	    (wqp->q_syncq->sq_flags & SQ_EVENTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4782
		moved += propagate_syncq(wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4784
	strsetuio(stp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4786
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4787
	 * If this was a module removal, decrement the push count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4788
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4789
	if (!isdriver)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4790
		stp->sd_pushcnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4791
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4792
	strunlock(stp, sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4793
	sqlist_free(sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4795
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4796
	 * Make sure any messages that were propagated are drained.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4797
	 * Also clear any QFULL bit caused by messages that were propagated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4798
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4800
	if (qp->q_next != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4801
		clr_qfull(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4802
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4803
		 * For the driver calling qprocsoff, propagate_syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4804
		 * frees all the messages instead of putting it in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4805
		 * the stream head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4806
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4807
		if (!isdriver && (moved > 0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4808
			emptysq(qp->q_next->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4809
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4810
	if (wqp->q_next != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4811
		clr_qfull(wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4812
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4813
		 * We come here for any pop of a module except for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4814
		 * case of driver being removed. We don't call emptysq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4815
		 * if we did not move any messages. This will avoid holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4816
		 * PERMOD syncq locks in emptysq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4817
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4818
		if (moved > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4819
			emptysq(wqp->q_next->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4820
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4821
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4822
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4823
	sq->sq_rmqcount--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4824
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4825
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4827
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4828
 * Prevent further entry by setting a flag (like SQ_FROZEN, SQ_BLOCKED or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4829
 * SQ_WRITER) on a syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4830
 * If maxcnt is not -1 it assumes that caller has "maxcnt" claim(s) on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4831
 * sync queue and waits until sq_count reaches maxcnt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4832
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4833
 * if maxcnt is -1 there's no need to grab sq_putlocks since the caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4834
 * does not care about putnext threads that are in the middle of calling put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4835
 * entry points.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4836
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4837
 * This routine is used for both inner and outer syncqs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4838
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4839
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4840
blocksq(syncq_t *sq, ushort_t flag, int maxcnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4841
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4842
	uint16_t count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4844
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4845
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4846
	 * Wait for SQ_FROZEN/SQ_BLOCKED to be reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4847
	 * SQ_FROZEN will be set if there is a frozen stream that has a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4848
	 * queue which also refers to this "shared" syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4849
	 * SQ_BLOCKED will be set if there is "off" queue which also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4850
	 * refers to this "shared" syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4851
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4852
	if (maxcnt != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4853
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4854
		SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4855
		SQ_PUTCOUNT_CLRFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4856
		SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4857
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4858
	sq->sq_needexcl++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4859
	ASSERT(sq->sq_needexcl != 0);	/* wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4861
	while ((sq->sq_flags & flag) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4862
	    (maxcnt != -1 && count > (unsigned)maxcnt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4863
		sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4864
		if (maxcnt != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4865
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4866
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4867
		cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4868
		if (maxcnt != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4869
			count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4870
			SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4871
			SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4872
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4873
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4874
	sq->sq_needexcl--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4875
	sq->sq_flags |= flag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4876
	ASSERT(maxcnt == -1 || count == maxcnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4877
	if (maxcnt != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4878
		if (sq->sq_needexcl == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4879
			SQ_PUTCOUNT_SETFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4880
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4881
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4882
	} else if (sq->sq_needexcl == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4883
		SQ_PUTCOUNT_SETFAST(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4884
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4886
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4887
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4888
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4889
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4890
 * Reset a flag that was set with blocksq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4891
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4892
 * Can not use this routine to reset SQ_WRITER.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4893
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4894
 * If "isouter" is set then the syncq is assumed to be an outer perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4895
 * and drain_syncq is not called. Instead we rely on the qwriter_outer thread
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4896
 * to handle the queued qwriter operations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4897
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4898
 * no need to grab sq_putlocks here. See comment in strsubr.h that explains when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4899
 * sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4900
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4901
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4902
unblocksq(syncq_t *sq, uint16_t resetflag, int isouter)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4903
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4904
	uint16_t flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4906
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4907
	ASSERT(resetflag != SQ_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4908
	ASSERT(sq->sq_flags & resetflag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4909
	flags = sq->sq_flags & ~resetflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4910
	sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4911
	if (flags & (SQ_QUEUED | SQ_WANTWAKEUP)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4912
		if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4913
			flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4914
			cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4915
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4916
		sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4917
		if ((flags & SQ_QUEUED) && !(flags & (SQ_STAYAWAY|SQ_EXCL))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4918
			if (!isouter) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4919
				/* drain_syncq drops SQLOCK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4920
				drain_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4921
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4922
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4923
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4924
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4925
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4926
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4928
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4929
 * Reset a flag that was set with blocksq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4930
 * Does not drain the syncq. Use emptysq() for that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4931
 * Returns 1 if SQ_QUEUED is set. Otherwise 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4932
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4933
 * no need to grab sq_putlocks here. See comment in strsubr.h that explains when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4934
 * sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4935
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4936
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4937
dropsq(syncq_t *sq, uint16_t resetflag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4938
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4939
	uint16_t flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4941
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4942
	ASSERT(sq->sq_flags & resetflag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4943
	flags = sq->sq_flags & ~resetflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4944
	if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4945
		flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4946
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4947
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4948
	sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4949
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4950
	if (flags & SQ_QUEUED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4951
		return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4952
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4953
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4955
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4956
 * Empty all the messages on a syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4957
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4958
 * no need to grab sq_putlocks here. See comment in strsubr.h that explains when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4959
 * sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4960
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4961
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4962
emptysq(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4963
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4964
	uint16_t flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4966
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4967
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4968
	if ((flags & SQ_QUEUED) && !(flags & (SQ_STAYAWAY|SQ_EXCL))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4969
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4970
		 * To prevent potential recursive invocation of drain_syncq we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4971
		 * do not call drain_syncq if count is non-zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4972
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4973
		if (sq->sq_count == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4974
			/* drain_syncq() drops SQLOCK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4975
			drain_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4976
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4977
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4978
			sqenable(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4979
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4980
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4981
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4983
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4984
 * Ordered insert while removing duplicates.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4985
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4986
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4987
sqlist_insert(sqlist_t *sqlist, syncq_t *sqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4988
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4989
	syncql_t *sqlp, **prev_sqlpp, *new_sqlp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4991
	prev_sqlpp = &sqlist->sqlist_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4992
	while ((sqlp = *prev_sqlpp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4993
		if (sqlp->sql_sq >= sqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4994
			if (sqlp->sql_sq == sqp)	/* duplicate */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4995
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4996
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4997
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4998
		prev_sqlpp = &sqlp->sql_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4999
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5000
	new_sqlp = &sqlist->sqlist_array[sqlist->sqlist_index++];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5001
	ASSERT((char *)new_sqlp < (char *)sqlist + sqlist->sqlist_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5002
	new_sqlp->sql_next = sqlp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5003
	new_sqlp->sql_sq = sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5004
	*prev_sqlpp = new_sqlp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5005
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5007
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5008
 * Walk the write side queues until we hit either the driver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5009
 * or a twist in the stream (_SAMESTR will return false in both
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5010
 * these cases) then turn around and walk the read side queues
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5011
 * back up to the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5012
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5013
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5014
sqlist_insertall(sqlist_t *sqlist, queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5015
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5016
	while (q != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5017
		sqlist_insert(sqlist, q->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5019
		if (_SAMESTR(q))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5020
			q = q->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5021
		else if (!(q->q_flag & QREADR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5022
			q = _RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5023
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5024
			q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5025
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5026
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5027
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5028
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5029
 * Allocate and build a list of all syncqs in a stream and the syncq(s)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5030
 * associated with the "q" parameter. The resulting list is sorted in a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5031
 * canonical order and is free of duplicates.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5032
 * Assumes the passed queue is a _RD(q).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5033
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5034
static sqlist_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5035
sqlist_build(queue_t *q, struct stdata *stp, boolean_t do_twist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5036
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5037
	sqlist_t *sqlist = sqlist_alloc(stp, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5039
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5040
	 * start with the current queue/qpair
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5041
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5042
	ASSERT(q->q_flag & QREADR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5043
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5044
	sqlist_insert(sqlist, q->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5045
	sqlist_insert(sqlist, _WR(q)->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5046
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5047
	sqlist_insertall(sqlist, stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5048
	if (do_twist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5049
		sqlist_insertall(sqlist, stp->sd_mate->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5051
	return (sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5052
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5053
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5054
static sqlist_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5055
sqlist_alloc(struct stdata *stp, int kmflag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5056
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5057
	size_t sqlist_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5058
	sqlist_t *sqlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5060
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5061
	 * Allocate 2 syncql_t's for each pushed module. Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5062
	 * the sqlist_t structure already has 4 syncql_t's built in:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5063
	 * 2 for the stream head, and 2 for the driver/other stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5064
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5065
	sqlist_size = 2 * sizeof (syncql_t) * stp->sd_pushcnt +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5066
		sizeof (sqlist_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5067
	if (STRMATED(stp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5068
		sqlist_size += 2 * sizeof (syncql_t) * stp->sd_mate->sd_pushcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5069
	sqlist = kmem_alloc(sqlist_size, kmflag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5070
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5071
	sqlist->sqlist_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5072
	sqlist->sqlist_size = sqlist_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5073
	sqlist->sqlist_index = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5075
	return (sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5076
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5078
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5079
 * Free the list created by sqlist_alloc()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5080
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5081
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5082
sqlist_free(sqlist_t *sqlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5083
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5084
	kmem_free(sqlist, sqlist->sqlist_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5085
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5087
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5088
 * Prevent any new entries into any syncq in this stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5089
 * Used by freezestr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5090
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5091
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5092
strblock(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5093
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5094
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5095
	syncql_t	*sql;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5096
	sqlist_t	*sqlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5097
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5098
	q = _RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5100
	stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5101
	ASSERT(stp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5103
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5104
	 * Get a sorted list with all the duplicates removed containing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5105
	 * all the syncqs referenced by this stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5106
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5107
	sqlist = sqlist_build(q, stp, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5108
	for (sql = sqlist->sqlist_head; sql != NULL; sql = sql->sql_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5109
		blocksq(sql->sql_sq, SQ_FROZEN, -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5110
	sqlist_free(sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5111
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5113
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5114
 * Release the block on new entries into this stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5115
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5116
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5117
strunblock(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5118
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5119
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5120
	syncql_t	*sql;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5121
	sqlist_t	*sqlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5122
	int		drain_needed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5124
	q = _RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5125
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5126
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5127
	 * Get a sorted list with all the duplicates removed containing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5128
	 * all the syncqs referenced by this stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5129
	 * Have to drop the SQ_FROZEN flag on all the syncqs before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5130
	 * starting to drain them; otherwise the draining might
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5131
	 * cause a freezestr in some module on the stream (which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5132
	 * would deadlock.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5133
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5134
	stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5135
	ASSERT(stp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5136
	sqlist = sqlist_build(q, stp, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5137
	drain_needed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5138
	for (sql = sqlist->sqlist_head; sql != NULL; sql = sql->sql_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5139
		drain_needed += dropsq(sql->sql_sq, SQ_FROZEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5140
	if (drain_needed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5141
		for (sql = sqlist->sqlist_head; sql != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5142
		    sql = sql->sql_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5143
			emptysq(sql->sql_sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5144
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5145
	sqlist_free(sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5146
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5148
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5149
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5150
qprocsareon(queue_t *rq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5151
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5152
	if (rq->q_next == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5153
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5154
	return (_WR(rq->q_next)->q_next == _WR(rq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5155
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5156
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5157
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5158
qclaimed(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5159
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5160
	uint_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5162
	count = q->q_syncq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5163
	SUM_SQ_PUTCOUNTS(q->q_syncq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5164
	return (count != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5165
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5166
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5167
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5168
 * Check if anyone has frozen this stream with freezestr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5169
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5170
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5171
frozenstr(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5172
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5173
	return ((q->q_syncq->sq_flags & SQ_FROZEN) != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5174
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5175
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5177
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5178
 * Enter a queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5179
 * Obsoleted interface. Should not be used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5180
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5181
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5182
enterq(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5183
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5184
	entersq(q->q_syncq, SQ_CALLBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5185
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5187
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5188
leaveq(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5189
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5190
	leavesq(q->q_syncq, SQ_CALLBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5191
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5192
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5193
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5194
 * Enter a perimeter. c_inner and c_outer specifies which concurrency bits
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5195
 * to check.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5196
 * Wait if SQ_QUEUED is set to preserve ordering between messages and qwriter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5197
 * calls and the running of open, close and service procedures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5198
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5199
 * if c_inner bit is set no need to grab sq_putlocks since we don't care
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5200
 * if other threads have entered or are entering put entry point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5201
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5202
 * if c_inner bit is set it might have been posible to use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5203
 * sq_putlocks/sq_putcounts instead of SQLOCK/sq_count (e.g. to optimize
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5204
 * open/close path for IP) but since the count may need to be decremented in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5205
 * qwait() we wouldn't know which counter to decrement. Currently counter is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5206
 * selected by current cpu_seqid and current CPU can change at any moment. XXX
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5207
 * in the future we might use curthread id bits to select the counter and this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5208
 * would stay constant across routine calls.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5209
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5210
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5211
entersq(syncq_t *sq, int entrypoint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5212
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5213
	uint16_t	count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5214
	uint16_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5215
	uint16_t	waitflags = SQ_STAYAWAY | SQ_EVENTS | SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5216
	uint16_t	type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5217
	uint_t		c_inner = entrypoint & SQ_CI;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5218
	uint_t		c_outer = entrypoint & SQ_CO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5220
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5221
	 * Increment ref count to keep closes out of this queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5222
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5223
	ASSERT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5224
	ASSERT(c_inner && c_outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5225
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5226
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5227
	type = sq->sq_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5228
	if (!(type & c_inner)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5229
		/* Make sure all putcounts now use slowlock. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5230
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5231
		SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5232
		SQ_PUTCOUNT_CLRFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5233
		SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5234
		sq->sq_needexcl++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5235
		ASSERT(sq->sq_needexcl != 0);	/* wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5236
		waitflags |= SQ_MESSAGES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5237
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5238
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5239
	 * Wait until we can enter the inner perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5240
	 * If we want exclusive access we wait until sq_count is 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5241
	 * We have to do this before entering the outer perimeter in order
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5242
	 * to preserve put/close message ordering.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5243
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5244
	while ((flags & waitflags) || (!(type & c_inner) && count != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5245
		sq->sq_flags = flags | SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5246
		if (!(type & c_inner)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5247
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5248
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5249
		cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5250
		if (!(type & c_inner)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5251
			count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5252
			SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5253
			SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5254
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5255
		flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5256
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5258
	if (!(type & c_inner)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5259
		ASSERT(sq->sq_needexcl > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5260
		sq->sq_needexcl--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5261
		if (sq->sq_needexcl == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5262
			SQ_PUTCOUNT_SETFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5263
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5264
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5266
	/* Check if we need to enter the outer perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5267
	if (!(type & c_outer)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5268
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5269
		 * We have to enter the outer perimeter exclusively before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5270
		 * we can increment sq_count to avoid deadlock. This implies
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5271
		 * that we have to re-check sq_flags and sq_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5272
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5273
		 * is it possible to have c_inner set when c_outer is not set?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5274
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5275
		if (!(type & c_inner)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5276
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5277
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5278
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5279
		outer_enter(sq->sq_outer, SQ_GOAWAY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5280
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5281
		flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5282
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5283
		 * there should be no need to recheck sq_putcounts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5284
		 * because outer_enter() has already waited for them to clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5285
		 * after setting SQ_WRITER.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5286
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5287
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5288
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5289
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5290
		 * SUMCHECK_SQ_PUTCOUNTS should return the sum instead
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5291
		 * of doing an ASSERT internally. Others should do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5292
		 * something like
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5293
		 *	 ASSERT(SUMCHECK_SQ_PUTCOUNTS(sq) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5294
		 * without the need to #ifdef DEBUG it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5295
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5296
		SUMCHECK_SQ_PUTCOUNTS(sq, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5297
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5298
		while ((flags & (SQ_EXCL|SQ_BLOCKED|SQ_FROZEN)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5299
		    (!(type & c_inner) && count != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5300
			sq->sq_flags = flags | SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5301
			cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5302
			count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5303
			flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5304
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5305
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5307
	sq->sq_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5308
	ASSERT(sq->sq_count != 0);	/* Wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5309
	if (!(type & c_inner)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5310
		/* Exclusive entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5311
		ASSERT(sq->sq_count == 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5312
		sq->sq_flags |= SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5313
		if (type & c_outer) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5314
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5315
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5316
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5317
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5318
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5320
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5321
 * leave a syncq. announce to framework that closes may proceed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5322
 * c_inner and c_outer specifies which concurrency bits
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5323
 * to check.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5324
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5325
 * must never be called from driver or module put entry point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5326
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5327
 * no need to grab sq_putlocks here. See comment in strsubr.h that explains when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5328
 * sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5329
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5330
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5331
leavesq(syncq_t *sq, int entrypoint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5332
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5333
	uint16_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5334
	uint16_t	type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5335
	uint_t		c_outer = entrypoint & SQ_CO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5336
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5337
	uint_t		c_inner = entrypoint & SQ_CI;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5338
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5339
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5340
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5341
	 * decrement ref count, drain the syncq if possible, and wake up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5342
	 * any waiting close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5343
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5344
	ASSERT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5345
	ASSERT(c_inner && c_outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5346
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5347
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5348
	type = sq->sq_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5349
	if (flags & (SQ_QUEUED|SQ_WANTWAKEUP|SQ_WANTEXWAKEUP)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5351
		if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5352
			flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5353
			cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5354
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5355
		if (flags & SQ_WANTEXWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5356
			flags &= ~SQ_WANTEXWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5357
			cv_broadcast(&sq->sq_exitwait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5358
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5360
		if ((flags & SQ_QUEUED) && !(flags & SQ_STAYAWAY)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5361
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5362
			 * The syncq needs to be drained. "Exit" the syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5363
			 * before calling drain_syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5364
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5365
			ASSERT(sq->sq_count != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5366
			sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5367
			ASSERT((flags & SQ_EXCL) || (type & c_inner));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5368
			sq->sq_flags = flags & ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5369
			drain_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5370
			ASSERT(MUTEX_NOT_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5371
			/* Check if we need to exit the outer perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5372
			/* XXX will this ever be true? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5373
			if (!(type & c_outer))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5374
				outer_exit(sq->sq_outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5375
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5376
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5377
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5378
	ASSERT(sq->sq_count != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5379
	sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5380
	ASSERT((flags & SQ_EXCL) || (type & c_inner));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5381
	sq->sq_flags = flags & ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5382
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5384
	/* Check if we need to exit the outer perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5385
	if (!(sq->sq_type & c_outer))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5386
		outer_exit(sq->sq_outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5387
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5389
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5390
 * Prevent q_next from changing in this stream by incrementing sq_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5391
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5392
 * no need to grab sq_putlocks here. See comment in strsubr.h that explains when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5393
 * sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5394
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5395
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5396
claimq(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5397
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5398
	syncq_t	*sq = qp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5400
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5401
	sq->sq_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5402
	ASSERT(sq->sq_count != 0);	/* Wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5403
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5404
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5405
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5406
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5407
 * Undo claimq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5408
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5409
 * no need to grab sq_putlocks here. See comment in strsubr.h that explains when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5410
 * sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5411
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5412
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5413
releaseq(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5414
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5415
	syncq_t	*sq = qp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5416
	uint16_t flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5418
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5419
	ASSERT(sq->sq_count > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5420
	sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5422
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5423
	if (flags & (SQ_WANTWAKEUP|SQ_QUEUED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5424
		if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5425
			flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5426
			cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5427
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5428
		sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5429
		if ((flags & SQ_QUEUED) && !(flags & (SQ_STAYAWAY|SQ_EXCL))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5430
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5431
			 * To prevent potential recursive invocation of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5432
			 * drain_syncq we do not call drain_syncq if count is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5433
			 * non-zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5434
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5435
			if (sq->sq_count == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5436
				drain_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5437
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5438
			} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5439
				sqenable(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5440
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5441
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5442
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5443
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5445
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5446
 * Prevent q_next from changing in this stream by incrementing sd_refcnt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5447
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5448
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5449
claimstr(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5450
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5451
	struct stdata *stp = STREAM(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5453
	mutex_enter(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5454
	stp->sd_refcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5455
	ASSERT(stp->sd_refcnt != 0);	/* Wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5456
	mutex_exit(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5457
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5459
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5460
 * Undo claimstr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5461
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5462
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5463
releasestr(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5464
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5465
	struct stdata *stp = STREAM(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5467
	mutex_enter(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5468
	ASSERT(stp->sd_refcnt != 0);
166
519e5268bee7 4657000 releasestr() should only wakeup waiters when sq_refcnt is zero.
xy158873
parents: 0
diff changeset
  5469
	if (--stp->sd_refcnt == 0)
519e5268bee7 4657000 releasestr() should only wakeup waiters when sq_refcnt is zero.
xy158873
parents: 0
diff changeset
  5470
		cv_broadcast(&stp->sd_refmonitor);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5471
	mutex_exit(&stp->sd_reflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5472
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5474
static syncq_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5475
new_syncq(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5476
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5477
	return (kmem_cache_alloc(syncq_cache, KM_SLEEP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5478
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5480
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5481
free_syncq(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5482
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5483
	ASSERT(sq->sq_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5484
	ASSERT(sq->sq_outer == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5485
	ASSERT(sq->sq_callbpend == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5486
	ASSERT((sq->sq_onext == NULL && sq->sq_oprev == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5487
	    (sq->sq_onext == sq && sq->sq_oprev == sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5489
	if (sq->sq_ciputctrl != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5490
		ASSERT(sq->sq_nciputctrl == n_ciputctrl - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5491
		SUMCHECK_CIPUTCTRL_COUNTS(sq->sq_ciputctrl,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5492
		    sq->sq_nciputctrl, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5493
		ASSERT(ciputctrl_cache != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5494
		kmem_cache_free(ciputctrl_cache, sq->sq_ciputctrl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5495
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5497
	sq->sq_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5498
	sq->sq_evhead = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5499
	sq->sq_evtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5500
	sq->sq_ciputctrl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5501
	sq->sq_nciputctrl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5502
	sq->sq_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5503
	sq->sq_rmqcount = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5504
	sq->sq_callbflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5505
	sq->sq_cancelid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5506
	sq->sq_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5507
	sq->sq_needexcl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5508
	sq->sq_svcflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5509
	sq->sq_nqueues = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5510
	sq->sq_pri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5511
	sq->sq_onext = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5512
	sq->sq_oprev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5513
	sq->sq_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5514
	sq->sq_type = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5515
	sq->sq_servcount = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5517
	kmem_cache_free(syncq_cache, sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5518
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5520
/* Outer perimeter code */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5522
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5523
 * The outer syncq uses the fields and flags in the syncq slightly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5524
 * differently from the inner syncqs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5525
 *	sq_count	Incremented when there are pending or running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5526
 *			writers at the outer perimeter to prevent the set of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5527
 *			inner syncqs that belong to the outer perimeter from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5528
 *			changing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5529
 *	sq_head/tail	List of deferred qwriter(OUTER) operations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5530
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5531
 *	SQ_BLOCKED	Set to prevent traversing of sq_next,sq_prev while
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5532
 *			inner syncqs are added to or removed from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5533
 *			outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5534
 *	SQ_QUEUED	sq_head/tail has messages or eventsqueued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5535
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5536
 *	SQ_WRITER	A thread is currently traversing all the inner syncqs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5537
 *			setting the SQ_WRITER flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5538
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5540
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5541
 * Get write access at the outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5542
 * Note that read access is done by entersq, putnext, and put by simply
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5543
 * incrementing sq_count in the inner syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5544
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5545
 * Waits until "flags" is no longer set in the outer to prevent multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5546
 * threads from having write access at the same time. SQ_WRITER has to be part
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5547
 * of "flags".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5548
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5549
 * Increases sq_count on the outer syncq to keep away outer_insert/remove
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5550
 * until the outer_exit is finished.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5551
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5552
 * outer_enter is vulnerable to starvation since it does not prevent new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5553
 * threads from entering the inner syncqs while it is waiting for sq_count to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5554
 * go to zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5555
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5556
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5557
outer_enter(syncq_t *outer, uint16_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5558
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5559
	syncq_t	*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5560
	int	wait_needed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5561
	uint16_t	count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5563
	ASSERT(outer->sq_outer == NULL && outer->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5564
	    outer->sq_oprev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5565
	ASSERT(flags & SQ_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5567
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5568
	mutex_enter(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5569
	while (outer->sq_flags & flags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5570
		outer->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5571
		cv_wait(&outer->sq_wait, SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5572
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5574
	ASSERT(!(outer->sq_flags & SQ_WRITER));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5575
	outer->sq_flags |= SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5576
	outer->sq_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5577
	ASSERT(outer->sq_count != 0);	/* wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5578
	wait_needed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5579
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5580
	 * Set SQ_WRITER on all the inner syncqs while holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5581
	 * the SQLOCK on the outer syncq. This ensures that the changing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5582
	 * of SQ_WRITER is atomic under the outer SQLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5583
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5584
	for (sq = outer->sq_onext; sq != outer; sq = sq->sq_onext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5585
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5586
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5587
		SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5588
		sq->sq_flags |= SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5589
		SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5590
		if (count != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5591
			wait_needed = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5592
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5593
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5594
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5595
	mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5597
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5598
	 * Get everybody out of the syncqs sequentially.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5599
	 * Note that we don't actually need to aqiure the PUTLOCKS, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5600
	 * we have already cleared the fastbit, and set QWRITER.  By
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5601
	 * definition, the count can not increase since putnext will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5602
	 * take the slowlock path (and the purpose of aquiring the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5603
	 * putlocks was to make sure it didn't increase while we were
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5604
	 * waiting).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5605
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5606
	 * Note that we still aquire the PUTLOCKS to be safe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5607
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5608
	if (wait_needed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5609
		for (sq = outer->sq_onext; sq != outer; sq = sq->sq_onext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5610
			mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5611
			count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5612
			SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5613
			SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5614
			while (count != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5615
				sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5616
				SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5617
				cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5618
				count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5619
				SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5620
				SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5621
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5622
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5623
			mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5624
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5625
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5626
		 * Verify that none of the flags got set while we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5627
		 * were waiting for the sq_counts to drop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5628
		 * If this happens we exit and retry entering the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5629
		 * outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5630
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5631
		mutex_enter(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5632
		if (outer->sq_flags & (flags & ~SQ_WRITER)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5633
			mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5634
			outer_exit(outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5635
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5636
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5637
		mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5638
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5639
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5641
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5642
 * Drop the write access at the outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5643
 * Read access is dropped implicitly (by putnext, put, and leavesq) by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5644
 * decrementing sq_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5645
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5646
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5647
outer_exit(syncq_t *outer)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5648
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5649
	syncq_t	*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5650
	int	 drain_needed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5651
	uint16_t flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5653
	ASSERT(outer->sq_outer == NULL && outer->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5654
	    outer->sq_oprev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5655
	ASSERT(MUTEX_NOT_HELD(SQLOCK(outer)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5656
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5657
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5658
	 * Atomically (from the perspective of threads calling become_writer)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5659
	 * drop the write access at the outer perimeter by holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5660
	 * SQLOCK(outer) across all the dropsq calls and the resetting of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5661
	 * SQ_WRITER.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5662
	 * This defines a locking order between the outer perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5663
	 * SQLOCK and the inner perimeter SQLOCKs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5664
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5665
	mutex_enter(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5666
	flags = outer->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5667
	ASSERT(outer->sq_flags & SQ_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5668
	if (flags & SQ_QUEUED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5669
		write_now(outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5670
		flags = outer->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5671
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5672
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5673
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5674
	 * sq_onext is stable since sq_count has not yet been decreased.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5675
	 * Reset the SQ_WRITER flags in all syncqs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5676
	 * After dropping SQ_WRITER on the outer syncq we empty all the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5677
	 * inner syncqs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5678
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5679
	drain_needed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5680
	for (sq = outer->sq_onext; sq != outer; sq = sq->sq_onext)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5681
		drain_needed += dropsq(sq, SQ_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5682
	ASSERT(!(outer->sq_flags & SQ_QUEUED));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5683
	flags &= ~SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5684
	if (drain_needed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5685
		outer->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5686
		mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5687
		for (sq = outer->sq_onext; sq != outer; sq = sq->sq_onext)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5688
			emptysq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5689
		mutex_enter(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5690
		flags = outer->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5691
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5692
	if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5693
		flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5694
		cv_broadcast(&outer->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5695
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5696
	outer->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5697
	ASSERT(outer->sq_count > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5698
	outer->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5699
	mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5700
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5702
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5703
 * Add another syncq to an outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5704
 * Block out all other access to the outer perimeter while it is being
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5705
 * changed using blocksq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5706
 * Assumes that the caller has *not* done an outer_enter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5707
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5708
 * Vulnerable to starvation in blocksq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5709
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5710
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5711
outer_insert(syncq_t *outer, syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5712
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5713
	ASSERT(outer->sq_outer == NULL && outer->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5714
	    outer->sq_oprev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5715
	ASSERT(sq->sq_outer == NULL && sq->sq_onext == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5716
	    sq->sq_oprev == NULL);	/* Can't be in an outer perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5718
	/* Get exclusive access to the outer perimeter list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5719
	blocksq(outer, SQ_BLOCKED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5720
	ASSERT(outer->sq_flags & SQ_BLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5721
	ASSERT(!(outer->sq_flags & SQ_WRITER));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5723
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5724
	sq->sq_outer = outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5725
	outer->sq_onext->sq_oprev = sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5726
	sq->sq_onext = outer->sq_onext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5727
	outer->sq_onext = sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5728
	sq->sq_oprev = outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5729
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5730
	unblocksq(outer, SQ_BLOCKED, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5731
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5733
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5734
 * Remove a syncq from an outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5735
 * Block out all other access to the outer perimeter while it is being
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5736
 * changed using blocksq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5737
 * Assumes that the caller has *not* done an outer_enter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5738
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5739
 * Vulnerable to starvation in blocksq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5740
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5741
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5742
outer_remove(syncq_t *outer, syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5743
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5744
	ASSERT(outer->sq_outer == NULL && outer->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5745
	    outer->sq_oprev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5746
	ASSERT(sq->sq_outer == outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5748
	/* Get exclusive access to the outer perimeter list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5749
	blocksq(outer, SQ_BLOCKED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5750
	ASSERT(outer->sq_flags & SQ_BLOCKED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5751
	ASSERT(!(outer->sq_flags & SQ_WRITER));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5753
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5754
	sq->sq_outer = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5755
	sq->sq_onext->sq_oprev = sq->sq_oprev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5756
	sq->sq_oprev->sq_onext = sq->sq_onext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5757
	sq->sq_oprev = sq->sq_onext = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5758
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5759
	unblocksq(outer, SQ_BLOCKED, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5760
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5762
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5763
 * Queue a deferred qwriter(OUTER) callback for this outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5764
 * If this is the first callback for this outer perimeter then add
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5765
 * this outer perimeter to the list of outer perimeters that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5766
 * the qwriter_outer_thread will process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5767
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5768
 * Increments sq_count in the outer syncq to prevent the membership
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5769
 * of the outer perimeter (in terms of inner syncqs) to change while
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5770
 * the callback is pending.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5771
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5772
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5773
queue_writer(syncq_t *outer, void (*func)(), queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5774
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5775
	ASSERT(MUTEX_HELD(SQLOCK(outer)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5777
	mp->b_prev = (mblk_t *)func;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5778
	mp->b_queue = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5779
	mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5780
	outer->sq_count++;	/* Decremented when dequeued */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5781
	ASSERT(outer->sq_count != 0);	/* Wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5782
	if (outer->sq_evhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5783
		/* First message. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5784
		outer->sq_evhead = outer->sq_evtail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5785
		outer->sq_flags |= SQ_EVENTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5786
		mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5787
		STRSTAT(qwr_outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5788
		(void) taskq_dispatch(streams_taskq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5789
		    (task_func_t *)qwriter_outer_service, outer, TQ_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5790
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5791
		ASSERT(outer->sq_flags & SQ_EVENTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5792
		outer->sq_evtail->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5793
		outer->sq_evtail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5794
		mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5795
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5796
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5798
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5799
 * Try and upgrade to write access at the outer perimeter. If this can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5800
 * not be done without blocking then queue the callback to be done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5801
 * by the qwriter_outer_thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5802
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5803
 * This routine can only be called from put or service procedures plus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5804
 * asynchronous callback routines that have properly entered to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5805
 * queue (with entersq.) Thus qwriter(OUTER) assumes the caller has one claim
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5806
 * on the syncq associated with q.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5807
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5808
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5809
qwriter_outer(queue_t *q, mblk_t *mp, void (*func)())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5810
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5811
	syncq_t	*osq, *sq, *outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5812
	int	failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5813
	uint16_t flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5815
	osq = q->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5816
	outer = osq->sq_outer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5817
	if (outer == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5818
		panic("qwriter(PERIM_OUTER): no outer perimeter");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5819
	ASSERT(outer->sq_outer == NULL && outer->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5820
	    outer->sq_oprev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5821
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5822
	mutex_enter(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5823
	flags = outer->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5824
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5825
	 * If some thread is traversing sq_next, or if we are blocked by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5826
	 * outer_insert or outer_remove, or if the we already have queued
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5827
	 * callbacks, then queue this callback for later processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5828
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5829
	 * Also queue the qwriter for an interrupt thread in order
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5830
	 * to reduce the time spent running at high IPL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5831
	 * to identify there are events.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5832
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5833
	if ((flags & SQ_GOAWAY) || (curthread->t_pri >= kpreemptpri)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5834
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5835
		 * Queue the become_writer request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5836
		 * The queueing is atomic under SQLOCK(outer) in order
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5837
		 * to synchronize with outer_exit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5838
		 * queue_writer will drop the outer SQLOCK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5839
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5840
		if (flags & SQ_BLOCKED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5841
			/* Must set SQ_WRITER on inner perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5842
			mutex_enter(SQLOCK(osq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5843
			osq->sq_flags |= SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5844
			mutex_exit(SQLOCK(osq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5845
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5846
			if (!(flags & SQ_WRITER)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5847
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5848
				 * The outer could have been SQ_BLOCKED thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5849
				 * SQ_WRITER might not be set on the inner.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5850
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5851
				mutex_enter(SQLOCK(osq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5852
				osq->sq_flags |= SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5853
				mutex_exit(SQLOCK(osq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5854
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5855
			ASSERT(osq->sq_flags & SQ_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5856
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5857
		queue_writer(outer, func, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5858
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5859
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5860
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5861
	 * We are half-way to exclusive access to the outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5862
	 * Prevent any outer_enter, qwriter(OUTER), or outer_insert/remove
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5863
	 * while the inner syncqs are traversed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5864
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5865
	outer->sq_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5866
	ASSERT(outer->sq_count != 0);	/* wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5867
	flags |= SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5868
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5869
	 * Check if we can run the function immediately. Mark all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5870
	 * syncqs with the writer flag to prevent new entries into
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5871
	 * put and service procedures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5872
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5873
	 * Set SQ_WRITER on all the inner syncqs while holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5874
	 * the SQLOCK on the outer syncq. This ensures that the changing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5875
	 * of SQ_WRITER is atomic under the outer SQLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5876
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5877
	failed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5878
	for (sq = outer->sq_onext; sq != outer; sq = sq->sq_onext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5879
		uint16_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5880
		uint_t	maxcnt = (sq == osq) ? 1 : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5881
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5882
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5883
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5884
		SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5885
		SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5886
		if (sq->sq_count > maxcnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5887
			failed = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5888
		sq->sq_flags |= SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5889
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5890
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5891
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5892
	if (failed) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5893
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5894
		 * Some other thread has a read claim on the outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5895
		 * Queue the callback for deferred processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5896
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5897
		 * queue_writer will set SQ_QUEUED before we drop SQ_WRITER
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5898
		 * so that other qwriter(OUTER) calls will queue their
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5899
		 * callbacks as well. queue_writer increments sq_count so we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5900
		 * decrement to compensate for the our increment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5901
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5902
		 * Dropping SQ_WRITER enables the writer thread to work
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5903
		 * on this outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5904
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5905
		outer->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5906
		queue_writer(outer, func, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5907
		/* queue_writer dropper the lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5908
		mutex_enter(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5909
		ASSERT(outer->sq_count > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5910
		outer->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5911
		ASSERT(outer->sq_flags & SQ_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5912
		flags = outer->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5913
		flags &= ~SQ_WRITER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5914
		if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5915
			flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5916
			cv_broadcast(&outer->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5917
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5918
		outer->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5919
		mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5920
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5921
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5922
		outer->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5923
		mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5924
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5925
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5926
	/* Can run it immediately */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5927
	(*func)(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5929
	outer_exit(outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5930
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5931
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5932
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5933
 * Dequeue all writer callbacks from the outer perimeter and run them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5934
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5935
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5936
write_now(syncq_t *outer)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5937
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5938
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5939
	queue_t		*q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5940
	void	(*func)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5942
	ASSERT(MUTEX_HELD(SQLOCK(outer)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5943
	ASSERT(outer->sq_outer == NULL && outer->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5944
	    outer->sq_oprev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5945
	while ((mp = outer->sq_evhead) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5946
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5947
		 * queues cannot be placed on the queuelist on the outer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5948
		 * perimiter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5949
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5950
		ASSERT(!(outer->sq_flags & SQ_MESSAGES));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5951
		ASSERT((outer->sq_flags & SQ_EVENTS));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5952
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5953
		outer->sq_evhead = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5954
		if (outer->sq_evhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5955
			outer->sq_evtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5956
			outer->sq_flags &= ~SQ_EVENTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5957
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5958
		ASSERT(outer->sq_count != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5959
		outer->sq_count--;	/* Incremented when enqueued. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5960
		mutex_exit(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5961
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5962
		 * Drop the message if the queue is closing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5963
		 * Make sure that the queue is "claimed" when the callback
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5964
		 * is run in order to satisfy various ASSERTs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5965
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5966
		q = mp->b_queue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5967
		func = (void (*)())mp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5968
		ASSERT(func != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5969
		mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5970
		if (q->q_flag & QWCLOSE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5971
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5972
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5973
			claimq(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5974
			(*func)(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5975
			releaseq(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5976
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5977
		mutex_enter(SQLOCK(outer));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5978
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5979
	ASSERT(MUTEX_HELD(SQLOCK(outer)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5980
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5982
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5983
 * The list of messages on the inner syncq is effectively hashed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5984
 * by destination queue.  These destination queues are doubly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5985
 * linked lists (hopefully) in priority order.  Messages are then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5986
 * put on the queue referenced by the q_sqhead/q_sqtail elements.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5987
 * Additional messages are linked together by the b_next/b_prev
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5988
 * elements in the mblk, with (similar to putq()) the first message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5989
 * having a NULL b_prev and the last message having a NULL b_next.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5990
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5991
 * Events, such as qwriter callbacks, are put onto a list in FIFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5992
 * order referenced by sq_evhead, and sq_evtail.  This is a singly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5993
 * linked list, and messages here MUST be processed in the order queued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5994
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5996
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5997
 * Run the events on the syncq event list (sq_evhead).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5998
 * Assumes there is only one claim on the syncq, it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5999
 * already exclusive (SQ_EXCL set), and the SQLOCK held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6000
 * Messages here are processed in order, with the SQ_EXCL bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6001
 * held all the way through till the last message is processed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6002
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6003
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6004
sq_run_events(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6005
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6006
	mblk_t		*bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6007
	queue_t		*qp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6008
	uint16_t	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6009
	void		(*func)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6011
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6012
	ASSERT((sq->sq_outer == NULL && sq->sq_onext == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6013
		sq->sq_oprev == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6014
		(sq->sq_outer != NULL && sq->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6015
		sq->sq_oprev != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6017
	ASSERT(flags & SQ_EXCL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6018
	ASSERT(sq->sq_count == 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6020
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6021
	 * We need to process all of the events on this list.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6022
	 * is possible that new events will be added while we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6023
	 * away processing a callback, so on every loop, we start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6024
	 * back at the beginning of the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6025
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6026
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6027
	 * We have to reaccess sq_evhead since there is a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6028
	 * possibility of a new entry while we were running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6029
	 * the callback.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6030
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6031
	for (bp = sq->sq_evhead; bp != NULL; bp = sq->sq_evhead) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6032
		ASSERT(bp->b_queue->q_syncq == sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6033
		ASSERT(sq->sq_flags & SQ_EVENTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6035
		qp = bp->b_queue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6036
		func = (void (*)())bp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6037
		ASSERT(func != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6039
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6040
		 * Messages from the event queue must be taken off in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6041
		 * FIFO order.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6042
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6043
		ASSERT(sq->sq_evhead == bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6044
		sq->sq_evhead = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6045
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6046
		if (bp->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6047
			/* Deleting last */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6048
			ASSERT(sq->sq_evtail == bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6049
			sq->sq_evtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6050
			sq->sq_flags &= ~SQ_EVENTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6051
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6052
		bp->b_prev = bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6053
		ASSERT(bp->b_datap->db_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6054
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6055
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6057
		(*func)(qp, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6059
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6060
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6061
		 * re-read the flags, since they could have changed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6062
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6063
		flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6064
		ASSERT(flags & SQ_EXCL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6065
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6066
	ASSERT(sq->sq_evhead == NULL && sq->sq_evtail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6067
	ASSERT(!(sq->sq_flags & SQ_EVENTS));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6069
	if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6070
		flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6071
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6072
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6073
	if (flags & SQ_WANTEXWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6074
		flags &= ~SQ_WANTEXWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6075
		cv_broadcast(&sq->sq_exitwait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6076
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6077
	sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6078
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6079
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6080
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6081
 * Put messages on the event list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6082
 * If we can go exclusive now, do so and process the event list, otherwise
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6083
 * let the last claim service this list (or wake the sqthread).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6084
 * This procedure assumes SQLOCK is held.  To run the event list, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6085
 * must be called with no claims.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6086
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6087
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6088
sqfill_events(syncq_t *sq, queue_t *q, mblk_t *mp, void (*func)())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6089
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6090
	uint16_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6091
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6092
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6093
	ASSERT(func != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6094
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6095
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6096
	 * This is a callback.  Add it to the list of callbacks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6097
	 * and see about upgrading.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6098
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6099
	mp->b_prev = (mblk_t *)func;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6100
	mp->b_queue = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6101
	mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6102
	if (sq->sq_evhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6103
		sq->sq_evhead = sq->sq_evtail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6104
		sq->sq_flags |= SQ_EVENTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6105
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6106
		ASSERT(sq->sq_evtail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6107
		ASSERT(sq->sq_evtail->b_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6108
		ASSERT(sq->sq_flags & SQ_EVENTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6109
		sq->sq_evtail->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6110
		sq->sq_evtail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6111
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6112
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6113
	 * We have set SQ_EVENTS, so threads will have to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6114
	 * unwind out of the perimiter, and new entries will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6115
	 * not grab a putlock.  But we still need to know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6116
	 * how many threads have already made a claim to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6117
	 * syncq, so grab the putlocks, and sum the counts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6118
	 * If there are no claims on the syncq, we can upgrade
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6119
	 * to exclusive, and run the event list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6120
	 * NOTE: We hold the SQLOCK, so we can just grab the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6121
	 * putlocks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6122
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6123
	count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6124
	SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6125
	SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6126
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6127
	 * We have no claim, so we need to check if there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6128
	 * are no others, then we can upgrade.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6129
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6130
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6131
	 * There are currently no claims on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6132
	 * the syncq by this thread (at least on this entry). The thread who has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6133
	 * the claim should drain syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6134
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6135
	if (count > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6136
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6137
		 * Can't upgrade - other threads inside.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6138
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6139
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6140
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6141
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6142
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6143
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6144
	 * Need to set SQ_EXCL and make a claim on the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6145
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6146
	ASSERT((sq->sq_flags & SQ_EXCL) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6147
	sq->sq_flags |= SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6148
	ASSERT(sq->sq_count == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6149
	sq->sq_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6150
	SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6152
	/* Process the events list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6153
	sq_run_events(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6155
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6156
	 * Release our claim...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6157
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6158
	sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6159
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6160
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6161
	 * And release SQ_EXCL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6162
	 * We don't need to acquire the putlocks to release
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6163
	 * SQ_EXCL, since we are exclusive, and hold the SQLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6164
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6165
	sq->sq_flags &= ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6166
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6167
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6168
	 * sq_run_events should have released SQ_EXCL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6169
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6170
	ASSERT(!(sq->sq_flags & SQ_EXCL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6172
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6173
	 * If anything happened while we were running the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6174
	 * events (or was there before), we need to process
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6175
	 * them now.  We shouldn't be exclusive sine we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6176
	 * released the perimiter above (plus, we asserted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6177
	 * for it).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6178
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6179
	if (!(sq->sq_flags & SQ_STAYAWAY) && (sq->sq_flags & SQ_QUEUED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6180
		drain_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6181
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6182
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6183
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6185
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6186
 * Perform delayed processing. The caller has to make sure that it is safe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6187
 * to enter the syncq (e.g. by checking that none of the SQ_STAYAWAY bits are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6188
 * set.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6189
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6190
 * Assume that the caller has NO claims on the syncq.  However, a claim
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6191
 * on the syncq does not indicate that a thread is draining the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6192
 * There may be more claims on the syncq than there are threads draining
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6193
 * (i.e.  #_threads_draining <= sq_count)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6194
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6195
 * drain_syncq has to terminate when one of the SQ_STAYAWAY bits gets set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6196
 * in order to preserve qwriter(OUTER) ordering constraints.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6197
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6198
 * sq_putcount only needs to be checked when dispatching the queued
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6199
 * writer call for CIPUT sync queue, but this is handled in sq_run_events.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6200
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6201
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6202
drain_syncq(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6203
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6204
	queue_t		*qp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6205
	uint16_t	count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6206
	uint16_t	type = sq->sq_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6207
	uint16_t	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6208
	boolean_t	bg_service = sq->sq_svcflags & SQ_SERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6210
	TRACE_1(TR_FAC_STREAMS_FR, TR_DRAIN_SYNCQ_START,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6211
		"drain_syncq start:%p", sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6212
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6213
	ASSERT((sq->sq_outer == NULL && sq->sq_onext == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6214
		sq->sq_oprev == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6215
		(sq->sq_outer != NULL && sq->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6216
		sq->sq_oprev != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6218
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6219
	 * Drop SQ_SERVICE flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6220
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6221
	if (bg_service)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6222
		sq->sq_svcflags &= ~SQ_SERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6224
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6225
	 * If SQ_EXCL is set, someone else is processing this syncq - let him
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6226
	 * finish the job.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6227
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6228
	if (flags & SQ_EXCL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6229
		if (bg_service) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6230
			ASSERT(sq->sq_servcount != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6231
			sq->sq_servcount--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6232
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6233
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6234
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6235
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6237
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6238
	 * This routine can be called by a background thread if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6239
	 * it was scheduled by a hi-priority thread.  SO, if there are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6240
	 * NOT messages queued, return (remember, we have the SQLOCK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6241
	 * and it cannot change until we release it). Wakeup any waiters also.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6242
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6243
	if (!(flags & SQ_QUEUED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6244
		if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6245
			flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6246
			cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6247
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6248
		if (flags & SQ_WANTEXWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6249
			flags &= ~SQ_WANTEXWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6250
			cv_broadcast(&sq->sq_exitwait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6251
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6252
		sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6253
		if (bg_service) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6254
			ASSERT(sq->sq_servcount != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6255
			sq->sq_servcount--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6256
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6257
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6258
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6259
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6261
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6262
	 * If this is not a concurrent put perimiter, we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6263
	 * become exclusive to drain.  Also, if not CIPUT, we would
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6264
	 * not have acquired a putlock, so we don't need to check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6265
	 * the putcounts.  If not entering with a claim, we test
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6266
	 * for sq_count == 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6267
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6268
	type = sq->sq_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6269
	if (!(type & SQ_CIPUT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6270
		if (sq->sq_count > 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6271
			if (bg_service) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6272
				ASSERT(sq->sq_servcount != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6273
				sq->sq_servcount--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6274
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6275
			mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6276
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6277
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6278
		sq->sq_flags |= SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6279
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6281
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6282
	 * This is where we make a claim to the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6283
	 * This can either be done by incrementing a putlock, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6284
	 * the sq_count.  But since we already have the SQLOCK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6285
	 * here, we just bump the sq_count.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6286
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6287
	 * Note that after we make a claim, we need to let the code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6288
	 * fall through to the end of this routine to clean itself
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6289
	 * up.  A return in the while loop will put the syncq in a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6290
	 * very bad state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6291
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6292
	sq->sq_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6293
	ASSERT(sq->sq_count != 0);	/* wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6295
	while ((flags = sq->sq_flags) & SQ_QUEUED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6296
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6297
		 * If we are told to stayaway or went exclusive,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6298
		 * we are done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6299
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6300
		if (flags & (SQ_STAYAWAY)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6301
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6302
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6303
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6304
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6305
		 * If there are events to run, do so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6306
		 * We have one claim to the syncq, so if there are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6307
		 * more than one, other threads are running.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6308
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6309
		if (sq->sq_evhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6310
			ASSERT(sq->sq_flags & SQ_EVENTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6311
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6312
			count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6313
			SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6314
			SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6315
			if (count > 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6316
				SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6317
				/* Can't upgrade - other threads inside */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6318
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6319
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6320
			ASSERT((flags & SQ_EXCL) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6321
			sq->sq_flags = flags | SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6322
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6323
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6324
			 * we have the only claim, run the events,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6325
			 * sq_run_events will clear the SQ_EXCL flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6326
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6327
			sq_run_events(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6329
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6330
			 * If this is a CIPUT perimiter, we need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6331
			 * to drop the SQ_EXCL flag so we can properly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6332
			 * continue draining the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6333
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6334
			if (type & SQ_CIPUT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6335
				ASSERT(sq->sq_flags & SQ_EXCL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6336
				sq->sq_flags &= ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6337
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6339
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6340
			 * And go back to the beginning just in case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6341
			 * anything changed while we were away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6342
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6343
			ASSERT((sq->sq_flags & SQ_EXCL) || (type & SQ_CIPUT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6344
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6345
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6347
		ASSERT(sq->sq_evhead == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6348
		ASSERT(!(sq->sq_flags & SQ_EVENTS));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6349
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6350
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6351
		 * Find the queue that is not draining.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6352
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6353
		 * q_draining is protected by QLOCK which we do not hold.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6354
		 * But if it was set, then a thread was draining, and if it gets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6355
		 * cleared, then it was because the thread has successfully
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6356
		 * drained the syncq, or a GOAWAY state occured. For the GOAWAY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6357
		 * state to happen, a thread needs the SQLOCK which we hold, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6358
		 * if there was such a flag, we whould have already seen it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6359
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6361
		for (qp = sq->sq_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6362
		    qp != NULL && (qp->q_draining ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6363
			(qp->q_sqflags & Q_SQDRAINING));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6364
		    qp = qp->q_sqnext)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6365
			;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6367
		if (qp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6368
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6370
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6371
		 * We have a queue to work on, and we hold the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6372
		 * SQLOCK and one claim, call qdrain_syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6373
		 * This means we need to release the SQLOCK and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6374
		 * aquire the QLOCK (OK since we have a claim).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6375
		 * Note that qdrain_syncq will actually dequeue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6376
		 * this queue from the sq_head list when it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6377
		 * convinced all the work is done and release
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6378
		 * the QLOCK before returning.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6379
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6380
		qp->q_sqflags |= Q_SQDRAINING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6381
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6382
		mutex_enter(QLOCK(qp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6383
		qdrain_syncq(sq, qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6384
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6386
		/* The queue is drained */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6387
		ASSERT(qp->q_sqflags & Q_SQDRAINING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6388
		qp->q_sqflags &= ~Q_SQDRAINING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6389
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6390
		 * NOTE: After this point qp should not be used since it may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6391
		 * closed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6392
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6393
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6395
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6396
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6397
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6398
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6399
	 * sq->sq_head cannot change because we hold the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6400
	 * sqlock. However, a thread CAN decide that it is no longer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6401
	 * going to drain that queue.  However, this should be due to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6402
	 * a GOAWAY state, and we should see that here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6403
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6404
	 * This loop is not very efficient. One solution may be adding a second
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6405
	 * pointer to the "draining" queue, but it is difficult to do when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6406
	 * queues are inserted in the middle due to priority ordering. Another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6407
	 * possibility is to yank the queue out of the sq list and put it onto
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6408
	 * the "draining list" and then put it back if it can't be drained.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6409
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6411
	ASSERT((sq->sq_head == NULL) || (flags & SQ_GOAWAY) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6412
		(type & SQ_CI) || sq->sq_head->q_draining);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6414
	/* Drop SQ_EXCL for non-CIPUT perimiters */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6415
	if (!(type & SQ_CIPUT))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6416
		flags &= ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6417
	ASSERT((flags & SQ_EXCL) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6419
	/* Wake up any waiters. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6420
	if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6421
		flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6422
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6423
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6424
	if (flags & SQ_WANTEXWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6425
		flags &= ~SQ_WANTEXWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6426
		cv_broadcast(&sq->sq_exitwait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6427
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6428
	sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6430
	ASSERT(sq->sq_count != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6431
	/* Release our claim. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6432
	sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6434
	if (bg_service) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6435
		ASSERT(sq->sq_servcount != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6436
		sq->sq_servcount--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6437
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6439
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6441
	TRACE_1(TR_FAC_STREAMS_FR, TR_DRAIN_SYNCQ_END,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6442
		"drain_syncq end:%p", sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6443
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6446
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6447
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6448
 * qdrain_syncq can be called (currently) from only one of two places:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6449
 *	drain_syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6450
 * 	putnext  (or some variation of it).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6451
 * and eventually
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6452
 * 	qwait(_sig)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6453
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6454
 * If called from drain_syncq, we found it in the list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6455
 * of queue's needing service, so there is work to be done (or it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6456
 * wouldn't be on the list).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6457
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6458
 * If called from some putnext variation, it was because the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6459
 * perimiter is open, but messages are blocking a putnext and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6460
 * there is not a thread working on it.  Now a thread could start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6461
 * working on it while we are getting ready to do so ourself, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6462
 * the thread would set the q_draining flag, and we can spin out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6463
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6464
 * As for qwait(_sig), I think I shall let it continue to call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6465
 * drain_syncq directly (after all, it will get here eventually).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6466
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6467
 * qdrain_syncq has to terminate when:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6468
 * - one of the SQ_STAYAWAY bits gets set to preserve qwriter(OUTER) ordering
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6469
 * - SQ_EVENTS gets set to preserve qwriter(INNER) ordering
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6470
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6471
 * ASSUMES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6472
 *	One claim
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6473
 * 	QLOCK held
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6474
 * 	SQLOCK not held
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6475
 *	Will release QLOCK before returning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6476
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6477
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6478
qdrain_syncq(syncq_t *sq, queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6479
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6480
	mblk_t		*bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6481
	boolean_t	do_clr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6482
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6483
	uint16_t	count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6484
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6486
	TRACE_1(TR_FAC_STREAMS_FR, TR_DRAIN_SYNCQ_START,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6487
		"drain_syncq start:%p", sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6488
	ASSERT(q->q_syncq == sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6489
	ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6490
	ASSERT(MUTEX_NOT_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6491
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6492
	 * For non-CIPUT perimiters, we should be called with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6493
	 * exclusive bit set already.  For non-CIPUT perimiters we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6494
	 * will be doing a concurrent drain, so it better not be set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6495
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6496
	ASSERT((sq->sq_flags & (SQ_EXCL|SQ_CIPUT)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6497
	ASSERT(!((sq->sq_type & SQ_CIPUT) && (sq->sq_flags & SQ_EXCL)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6498
	ASSERT((sq->sq_type & SQ_CIPUT) || (sq->sq_flags & SQ_EXCL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6499
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6500
	 * All outer pointers are set, or none of them are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6501
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6502
	ASSERT((sq->sq_outer == NULL && sq->sq_onext == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6503
		sq->sq_oprev == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6504
		(sq->sq_outer != NULL && sq->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6505
		sq->sq_oprev != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6506
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6507
	count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6508
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6509
	 * This is OK without the putlocks, because we have one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6510
	 * claim either from the sq_count, or a putcount.  We could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6511
	 * get an erroneous value from other counts, but ours won't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6512
	 * change, so one way or another, we will have at least a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6513
	 * value of one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6514
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6515
	SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6516
	ASSERT(count >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6517
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6519
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6520
	 * The first thing to do here, is find out if a thread is already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6521
	 * draining this queue or the queue is closing. If so, we are done,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6522
	 * just return. Also, if there are no messages, we are done as well.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6523
	 * Note that we check the q_sqhead since there is s window of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6524
	 * opportunity for us to enter here because Q_SQQUEUED was set, but is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6525
	 * not anymore.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6526
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6527
	if (q->q_draining || (q->q_sqhead == NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6528
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6529
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6530
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6532
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6533
	 * If the perimiter is exclusive, there is nothing we can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6534
	 * do right now, go away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6535
	 * Note that there is nothing to prevent this case from changing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6536
	 * right after this check, but the spin-out will catch it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6537
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6539
	/* Tell other threads that we are draining this queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6540
	q->q_draining = 1;	/* Protected by QLOCK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6542
	for (bp = q->q_sqhead; bp != NULL; bp = q->q_sqhead) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6544
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6545
		 * Because we can enter this routine just because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6546
		 * a putnext is blocked, we need to spin out if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6547
		 * the perimiter wants to go exclusive as well
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6548
		 * as just blocked. We need to spin out also if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6549
		 * events are queued on the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6550
		 * Don't check for SQ_EXCL, because non-CIPUT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6551
		 * perimiters would set it, and it can't become
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6552
		 * exclusive while we hold a claim.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6553
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6554
		if (sq->sq_flags & (SQ_STAYAWAY | SQ_EVENTS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6555
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6556
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6557
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6558
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6559
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6560
		 * Since we are in qdrain_syncq, we already know the queue,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6561
		 * but for sanity, we want to check this against the qp that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6562
		 * was passed in by bp->b_queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6563
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6565
		ASSERT(bp->b_queue == q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6566
		ASSERT(bp->b_queue->q_syncq == sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6567
		bp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6569
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6570
		 * We would have the following check in the DEBUG code:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6571
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6572
		 * if (bp->b_prev != NULL)  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6573
		 *	ASSERT(bp->b_prev == (void (*)())q->q_qinfo->qi_putp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6574
		 * }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6575
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6576
		 * This can't be done, however, since IP modifies qinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6577
		 * structure at run-time (switching between IPv4 qinfo and IPv6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6578
		 * qinfo), invalidating the check.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6579
		 * So the assignment to func is left here, but the ASSERT itself
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6580
		 * is removed until the whole issue is resolved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6581
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6582
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6583
		ASSERT(q->q_sqhead == bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6584
		q->q_sqhead = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6585
		bp->b_prev = bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6586
		ASSERT(q->q_syncqmsgs > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6587
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6588
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6589
		ASSERT(bp->b_datap->db_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6590
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6591
		(void) (*q->q_qinfo->qi_putp)(q, bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6593
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6594
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6595
		 * We should decrement q_syncqmsgs only after executing the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6596
		 * put procedure to avoid a possible race with putnext().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6597
		 * In putnext() though it sees Q_SQQUEUED is set, there is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6598
		 * an optimization which allows putnext to call the put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6599
		 * procedure directly if (q_syncqmsgs == 0) and thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6600
		 * a message reodering could otherwise occur.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6601
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6602
		q->q_syncqmsgs--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6603
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6604
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6605
		 * Clear QFULL in the next service procedure queue if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6606
		 * this is the last message destined to that queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6607
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6608
		 * It would make better sense to have some sort of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6609
		 * tunable for the low water mark, but these symantics
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6610
		 * are not yet defined.  So, alas, we use a constant.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6611
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6612
		do_clr = (q->q_syncqmsgs == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6613
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6615
		if (do_clr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6616
			clr_qfull(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6618
		mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6619
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6620
		 * Always clear SQ_EXCL when CIPUT in order to handle
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6621
		 * qwriter(INNER).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6622
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6623
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6624
		 * The putp() can call qwriter and get exclusive access
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6625
		 * IFF this is the only claim.  So, we need to test for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6626
		 * this possibility so we can aquire the mutex and clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6627
		 * the bit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6628
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6629
		if ((sq->sq_type & SQ_CIPUT) && (sq->sq_flags & SQ_EXCL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6630
			mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6631
			sq->sq_flags &= ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6632
			mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6633
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6634
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6636
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6637
	 * We should either have no queues on the syncq, or we were
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6638
	 * told to goaway by a waiter (which we will wake up at the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6639
	 * end of this function).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6640
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6641
	ASSERT((q->q_sqhead == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6642
	    (sq->sq_flags & (SQ_STAYAWAY | SQ_EVENTS)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6644
	ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6645
	ASSERT(MUTEX_NOT_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6647
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6648
	 * Remove the q from the syncq list if all the messages are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6649
	 * drained.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6650
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6651
	if (q->q_sqhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6652
		mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6653
		if (q->q_sqflags & Q_SQQUEUED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6654
			SQRM_Q(sq, q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6655
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6656
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6657
		 * Since the queue is removed from the list, reset its priority.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6658
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6659
		q->q_spri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6660
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6662
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6663
	 * Remember, the q_draining flag is used to let another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6664
	 * thread know that there is a thread currently draining
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6665
	 * the messages for a queue.  Since we are now done with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6666
	 * this queue (even if there may be messages still there),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6667
	 * we need to clear this flag so some thread will work
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6668
	 * on it if needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6669
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6670
	ASSERT(q->q_draining);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6671
	q->q_draining = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6672
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6673
	/* called with a claim, so OK to drop all locks. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6674
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6676
	TRACE_1(TR_FAC_STREAMS_FR, TR_DRAIN_SYNCQ_END,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6677
		"drain_syncq end:%p", sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6678
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6679
/* END OF QDRAIN_SYNCQ  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6680
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6682
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6683
 * This is the mate to qdrain_syncq, except that it is putting the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6684
 * message onto the the queue instead draining.  Since the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6685
 * message is destined for the queue that is selected, there is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6686
 * no need to identify the function because the message is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6687
 * intended for the put routine for the queue.  But this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6688
 * routine will do it anyway just in case (but only for debug kernels).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6689
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6690
 * After the message is enqueued on the syncq, it calls putnext_tail()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6691
 * which will schedule a background thread to actually process the message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6692
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6693
 * Assumes that there is a claim on the syncq (sq->sq_count > 0) and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6694
 * SQLOCK(sq) and QLOCK(q) are not held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6695
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6696
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6697
qfill_syncq(syncq_t *sq, queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6698
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6699
	queue_t		*fq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6701
	ASSERT(MUTEX_NOT_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6702
	ASSERT(MUTEX_NOT_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6703
	ASSERT(sq->sq_count > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6704
	ASSERT(q->q_syncq == sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6705
	ASSERT((sq->sq_outer == NULL && sq->sq_onext == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6706
		sq->sq_oprev == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6707
		(sq->sq_outer != NULL && sq->sq_onext != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6708
		sq->sq_oprev != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6710
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6712
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6713
	 * Set QFULL in next service procedure queue (that cares) if not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6714
	 * already set and if there are already more messages on the syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6715
	 * than sq_max_size.  If sq_max_size is 0, no flow control will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6716
	 * asserted on any syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6717
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6718
	 * The fq here is the next queue with a service procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6719
	 * This is where we would fail canputnext, so this is where we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6720
	 * need to set QFULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6721
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6722
	 * LOCKING HIERARCHY: In the case when fq != q we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6723
	 *  a) Take QLOCK(fq) to set QFULL flag and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6724
	 *  b) Take sd_reflock in the case of the hot stream to update
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6725
	 *  	sd_refcnt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6726
	 * We already have QLOCK at this point. To avoid cross-locks with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6727
	 * freezestr() which grabs all QLOCKs and with strlock() which grabs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6728
	 * both SQLOCK and sd_reflock, we need to drop respective locks first.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6729
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6730
	if ((sq_max_size != 0) && (!(q->q_nfsrv->q_flag & QFULL)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6731
	    (q->q_syncqmsgs > sq_max_size)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6732
		if ((fq = q->q_nfsrv) == q) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6733
			fq->q_flag |= QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6734
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6735
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6736
			mutex_enter(QLOCK(fq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6737
			fq->q_flag |= QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6738
			mutex_exit(QLOCK(fq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6739
			mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6740
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6741
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6743
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6744
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6745
	 * This is used for debug in the qfill_syncq/qdrain_syncq case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6746
	 * to trace the queue that the message is intended for.  Note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6747
	 * that the original use was to identify the queue and function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6748
	 * to call on the drain.  In the new syncq, we have the context
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6749
	 * of the queue that we are draining, so call it's putproc and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6750
	 * don't rely on the saved values.  But for debug this is still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6751
	 * usefull information.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6752
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6753
	mp->b_prev = (mblk_t *)q->q_qinfo->qi_putp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6754
	mp->b_queue = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6755
	mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6756
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6757
	ASSERT(q->q_syncq == sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6758
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6759
	 * Enqueue the message on the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6760
	 * SQPUT_MP() accesses q_syncqmsgs.  We are already holding QLOCK to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6761
	 * protect it.  So its ok to acquire SQLOCK after SQPUT_MP().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6762
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6763
	SQPUT_MP(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6764
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6766
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6767
	 * And queue on syncq for scheduling, if not already queued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6768
	 * Note that we need the SQLOCK for this, and for testing flags
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6769
	 * at the end to see if we will drain.  So grab it now, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6770
	 * release it before we call qdrain_syncq or return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6771
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6772
	if (!(q->q_sqflags & Q_SQQUEUED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6773
		q->q_spri = curthread->t_pri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6774
		SQPUT_Q(sq, q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6775
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6776
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6777
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6778
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6779
		 * All of these conditions MUST be true!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6780
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6781
		ASSERT(sq->sq_tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6782
		if (sq->sq_tail == sq->sq_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6783
			ASSERT((q->q_sqprev == NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6784
			    (q->q_sqnext == NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6785
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6786
			ASSERT((q->q_sqprev != NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6787
			    (q->q_sqnext != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6788
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6789
		ASSERT(sq->sq_flags & SQ_QUEUED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6790
		ASSERT(q->q_syncqmsgs != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6791
		ASSERT(q->q_sqflags & Q_SQQUEUED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6792
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6793
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6794
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6795
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6796
	 * SQLOCK is still held, so sq_count can be safely decremented.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6797
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6798
	sq->sq_count--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6800
	putnext_tail(sq, q, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6801
	/* Should not reference sq or q after this point. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6802
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6804
/*  End of qfill_syncq  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6805
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6806
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6807
 * Remove all messages from a syncq (if qp is NULL) or remove all messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6808
 * that would be put into qp by drain_syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6809
 * Used when deleting the syncq (qp == NULL) or when detaching
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6810
 * a queue (qp != NULL).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6811
 * Return non-zero if one or more messages were freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6812
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6813
 * no need to grab sq_putlocks here. See comment in strsubr.h that explains when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6814
 * sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6815
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6816
 * NOTE: This function assumes that it is called from the close() context and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6817
 * that all the queues in the syncq are going aay. For this reason it doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6818
 * acquire QLOCK for modifying q_sqhead/q_sqtail fields. This assumption is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6819
 * currently valid, but it is useful to rethink this function to behave properly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6820
 * in other cases.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6821
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6822
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6823
flush_syncq(syncq_t *sq, queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6824
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6825
	mblk_t		*bp, *mp_head, *mp_next, *mp_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6826
	queue_t		*q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6827
	int		ret = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6829
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6831
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6832
	 * Before we leave, we need to make sure there are no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6833
	 * events listed for this queue.  All events for this queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6834
	 * will just be freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6835
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6836
	if (qp != NULL && sq->sq_evhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6837
		ASSERT(sq->sq_flags & SQ_EVENTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6838
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6839
		mp_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6840
		for (bp = sq->sq_evhead; bp != NULL; bp = mp_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6841
			mp_next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6842
			if (bp->b_queue == qp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6843
				/* Delete this message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6844
				if (mp_prev != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6845
					mp_prev->b_next = mp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6846
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6847
					 * Update sq_evtail if the last element
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6848
					 * is removed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6849
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6850
					if (bp == sq->sq_evtail) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6851
						ASSERT(mp_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6852
						sq->sq_evtail = mp_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6853
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6854
				} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6855
					sq->sq_evhead = mp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6856
				if (sq->sq_evhead == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6857
					sq->sq_flags &= ~SQ_EVENTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6858
				bp->b_prev = bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6859
				freemsg(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6860
				ret++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6861
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6862
				mp_prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6863
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6864
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6865
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6866
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6867
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6868
	 * Walk sq_head and:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6869
	 *	- match qp if qp is set, remove it's messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6870
	 *	- all if qp is not set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6871
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6872
	q = sq->sq_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6873
	while (q != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6874
		ASSERT(q->q_syncq == sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6875
		if ((qp == NULL) || (qp == q)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6876
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6877
			 * Yank the messages as a list off the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6878
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6879
			mp_head = q->q_sqhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6880
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6881
			 * We do not have QLOCK(q) here (which is safe due to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6882
			 * assumptions mentioned above). To obtain the lock we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6883
			 * need to release SQLOCK which may allow lots of things
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6884
			 * to change upon us. This place requires more analysis.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6885
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6886
			q->q_sqhead = q->q_sqtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6887
			ASSERT(mp_head->b_queue &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6888
			    mp_head->b_queue->q_syncq == sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6890
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6891
			 * Free each of the messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6892
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6893
			for (bp = mp_head; bp != NULL; bp = mp_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6894
				mp_next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6895
				bp->b_prev = bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6896
				freemsg(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6897
				ret++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6898
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6899
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6900
			 * Now remove the queue from the syncq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6901
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6902
			ASSERT(q->q_sqflags & Q_SQQUEUED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6903
			SQRM_Q(sq, q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6904
			q->q_spri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6905
			q->q_syncqmsgs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6907
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6908
			 * If qp was specified, we are done with it and are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6909
			 * going to drop SQLOCK(sq) and return. We wakeup syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6910
			 * waiters while we still have the SQLOCK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6911
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6912
			if ((qp != NULL) && (sq->sq_flags & SQ_WANTWAKEUP)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6913
				sq->sq_flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6914
				cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6915
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6916
			/* Drop SQLOCK across clr_qfull */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6917
			mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6919
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6920
			 * We avoid doing the test that drain_syncq does and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6921
			 * unconditionally clear qfull for every flushed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6922
			 * message. Since flush_syncq is only called during
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6923
			 * close this should not be a problem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6924
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6925
			clr_qfull(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6926
			if (qp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6927
				return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6928
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6929
				mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6930
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6931
				 * The head was removed by SQRM_Q above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6932
				 * reread the new head and flush it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6933
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6934
				q = sq->sq_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6935
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6936
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6937
			q = q->q_sqnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6938
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6939
		ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6940
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6942
	if (sq->sq_flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6943
		sq->sq_flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6944
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6945
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6947
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6948
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6949
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6951
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6952
 * Propagate all messages from a syncq to the next syncq that are associated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6953
 * with the specified queue. If the queue is attached to a driver or if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6954
 * messages have been added due to a qwriter(PERIM_INNER), free the messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6955
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6956
 * Assumes that the stream is strlock()'ed. We don't come here if there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6957
 * are no messages to propagate.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6958
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6959
 * NOTE : If the queue is attached to a driver, all the messages are freed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6960
 * as there is no point in propagating the messages from the driver syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6961
 * to the closing stream head which will in turn get freed later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6962
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6963
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6964
propagate_syncq(queue_t *qp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6965
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6966
	mblk_t		*bp, *head, *tail, *prev, *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6967
	syncq_t 	*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6968
	queue_t		*nqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6969
	syncq_t		*nsq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6970
	boolean_t	isdriver;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6971
	int 		moved = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6972
	uint16_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6973
	pri_t		priority = curthread->t_pri;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6974
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6975
	void		(*func)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6976
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6978
	sq = qp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6979
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6980
	/* debug macro */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6981
	SQ_PUTLOCKS_HELD(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6982
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6983
	 * As entersq() does not increment the sq_count for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6984
	 * the write side, check sq_count for non-QPERQ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6985
	 * perimeters alone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6986
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6987
	ASSERT((qp->q_flag & QPERQ) || (sq->sq_count >= 1));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6989
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6990
	 * propagate_syncq() can be called because of either messages on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6991
	 * queue syncq or because on events on the queue syncq. Do actual
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6992
	 * message propagations if there are any messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6993
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6994
	if (qp->q_syncqmsgs) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6995
		isdriver = (qp->q_flag & QISDRV);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6996
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6997
		if (!isdriver) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6998
			nqp = qp->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6999
			nsq = nqp->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7000
			ASSERT(MUTEX_HELD(SQLOCK(nsq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7001
			/* debug macro */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7002
			SQ_PUTLOCKS_HELD(nsq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7003
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7004
			func = (void (*)())nqp->q_qinfo->qi_putp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7005
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7006
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7007
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7008
		SQRM_Q(sq, qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7009
		priority = MAX(qp->q_spri, priority);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7010
		qp->q_spri = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7011
		head = qp->q_sqhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7012
		tail = qp->q_sqtail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7013
		qp->q_sqhead = qp->q_sqtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7014
		qp->q_syncqmsgs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7016
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7017
		 * Walk the list of messages, and free them if this is a driver,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7018
		 * otherwise reset the b_prev and b_queue value to the new putp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7019
		 * Afterward, we will just add the head to the end of the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7020
		 * syncq, and point the tail to the end of this one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7021
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7023
		for (bp = head; bp != NULL; bp = next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7024
			next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7025
			if (isdriver) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7026
				bp->b_prev = bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7027
				freemsg(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7028
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7029
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7030
			/* Change the q values for this message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7031
			bp->b_queue = nqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7032
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7033
			bp->b_prev = (mblk_t *)func;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7034
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7035
			moved++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7036
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7037
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7038
		 * Attach list of messages to the end of the new queue (if there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7039
		 * is a list of messages).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7040
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7042
		if (!isdriver && head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7043
			ASSERT(tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7044
			if (nqp->q_sqhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7045
				nqp->q_sqhead = head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7046
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7047
				ASSERT(nqp->q_sqtail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7048
				nqp->q_sqtail->b_next = head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7049
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7050
			nqp->q_sqtail = tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7051
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7052
			 * When messages are moved from high priority queue to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7053
			 * another queue, the destination queue priority is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7054
			 * upgraded.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7055
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7057
			if (priority > nqp->q_spri)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7058
				nqp->q_spri = priority;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7060
			SQPUT_Q(nsq, nqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7062
			nqp->q_syncqmsgs += moved;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7063
			ASSERT(nqp->q_syncqmsgs != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7064
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7065
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7066
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7067
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7068
	 * Before we leave, we need to make sure there are no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7069
	 * events listed for this queue.  All events for this queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7070
	 * will just be freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7071
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7072
	if (sq->sq_evhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7073
		ASSERT(sq->sq_flags & SQ_EVENTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7074
		prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7075
		for (bp = sq->sq_evhead; bp != NULL; bp = next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7076
			next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7077
			if (bp->b_queue == qp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7078
				/* Delete this message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7079
				if (prev != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7080
					prev->b_next = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7081
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7082
					 * Update sq_evtail if the last element
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7083
					 * is removed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7084
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7085
					if (bp == sq->sq_evtail) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7086
						ASSERT(next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7087
						sq->sq_evtail = prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7088
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7089
				} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7090
					sq->sq_evhead = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7091
				if (sq->sq_evhead == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7092
					sq->sq_flags &= ~SQ_EVENTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7093
				bp->b_prev = bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7094
				freemsg(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7095
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7096
				prev = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7097
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7098
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7099
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7101
	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7103
	/* Wake up any waiter before leaving. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7104
	if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7105
		flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7106
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7107
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7108
	sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7110
	return (moved);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7111
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7113
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7114
 * Try and upgrade to exclusive access at the inner perimeter. If this can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7115
 * not be done without blocking then request will be queued on the syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7116
 * and drain_syncq will run it later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7117
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7118
 * This routine can only be called from put or service procedures plus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7119
 * asynchronous callback routines that have properly entered to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7120
 * queue (with entersq.) Thus qwriter_inner assumes the caller has one claim
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7121
 * on the syncq associated with q.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7122
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7123
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7124
qwriter_inner(queue_t *q, mblk_t *mp, void (*func)())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7125
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7126
	syncq_t	*sq = q->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7127
	uint16_t count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7129
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7130
	count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7131
	SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7132
	SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7133
	ASSERT(count >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7134
	ASSERT(sq->sq_type & (SQ_CIPUT|SQ_CISVC));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7136
	if (count == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7137
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7138
		 * Can upgrade. This case also handles nested qwriter calls
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7139
		 * (when the qwriter callback function calls qwriter). In that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7140
		 * case SQ_EXCL is already set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7141
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7142
		sq->sq_flags |= SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7143
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7144
		mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7145
		(*func)(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7146
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7147
		 * Assumes that leavesq, putnext, and drain_syncq will reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7148
		 * SQ_EXCL for SQ_CIPUT/SQ_CISVC queues. We leave SQ_EXCL on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7149
		 * until putnext, leavesq, or drain_syncq drops it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7150
		 * That way we handle nested qwriter(INNER) without dropping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7151
		 * SQ_EXCL until the outermost qwriter callback routine is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7152
		 * done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7153
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7154
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7155
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7156
	SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7157
	sqfill_events(sq, q, mp, func);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7158
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7159
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7160
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7161
 * Synchronous callback support functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7162
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7163
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7164
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7165
 * Allocate a callback parameter structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7166
 * Assumes that caller initializes the flags and the id.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7167
 * Acquires SQLOCK(sq) if non-NULL is returned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7168
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7169
callbparams_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7170
callbparams_alloc(syncq_t *sq, void (*func)(void *), void *arg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7171
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7172
	callbparams_t *cbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7173
	size_t size = sizeof (callbparams_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7175
	cbp = kmem_alloc(size, kmflags & ~KM_PANIC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7177
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7178
	 * Only try tryhard allocation if the caller is ready to panic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7179
	 * Otherwise just fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7180
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7181
	if (cbp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7182
		if (kmflags & KM_PANIC)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7183
			cbp = kmem_alloc_tryhard(sizeof (callbparams_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7184
			    &size, kmflags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7185
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7186
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7187
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7189
	ASSERT(size >= sizeof (callbparams_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7190
	cbp->cbp_size = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7191
	cbp->cbp_sq = sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7192
	cbp->cbp_func = func;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7193
	cbp->cbp_arg = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7194
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7195
	cbp->cbp_next = sq->sq_callbpend;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7196
	sq->sq_callbpend = cbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7197
	return (cbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7198
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7200
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7201
callbparams_free(syncq_t *sq, callbparams_t *cbp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7202
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7203
	callbparams_t **pp, *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7204
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7205
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7207
	for (pp = &sq->sq_callbpend; (p = *pp) != NULL; pp = &p->cbp_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7208
		if (p == cbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7209
			*pp = p->cbp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7210
			kmem_free(p, p->cbp_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7211
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7212
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7213
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7214
	(void) (STRLOG(0, 0, 0, SL_CONSOLE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7215
	    "callbparams_free: not found\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7216
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7218
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7219
callbparams_free_id(syncq_t *sq, callbparams_id_t id, int32_t flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7220
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7221
	callbparams_t **pp, *p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7223
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7224
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7225
	for (pp = &sq->sq_callbpend; (p = *pp) != NULL; pp = &p->cbp_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7226
		if (p->cbp_id == id && p->cbp_flags == flag) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7227
			*pp = p->cbp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7228
			kmem_free(p, p->cbp_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7229
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7230
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7231
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7232
	(void) (STRLOG(0, 0, 0, SL_CONSOLE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7233
	    "callbparams_free_id: not found\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7234
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7235
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7236
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7237
 * Callback wrapper function used by once-only callbacks that can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7238
 * cancelled (qtimeout and qbufcall)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7239
 * Contains inline version of entersq(sq, SQ_CALLBACK) that can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7240
 * cancelled by the qun* functions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7241
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7242
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7243
qcallbwrapper(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7244
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7245
	callbparams_t *cbp = arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7246
	syncq_t	*sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7247
	uint16_t count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7248
	uint16_t waitflags = SQ_STAYAWAY | SQ_EVENTS | SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7249
	uint16_t type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7251
	sq = cbp->cbp_sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7252
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7253
	type = sq->sq_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7254
	if (!(type & SQ_CICB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7255
		count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7256
		SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7257
		SQ_PUTCOUNT_CLRFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7258
		SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7259
		sq->sq_needexcl++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7260
		ASSERT(sq->sq_needexcl != 0);	/* wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7261
		waitflags |= SQ_MESSAGES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7262
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7263
	/* Can not handle exlusive entry at outer perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7264
	ASSERT(type & SQ_COCB);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7266
	while ((sq->sq_flags & waitflags) || (!(type & SQ_CICB) &&count != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7267
		if ((sq->sq_callbflags & cbp->cbp_flags) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7268
		    (sq->sq_cancelid == cbp->cbp_id)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7269
			/* timeout has been cancelled */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7270
			sq->sq_callbflags |= SQ_CALLB_BYPASSED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7271
			callbparams_free(sq, cbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7272
			if (!(type & SQ_CICB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7273
				ASSERT(sq->sq_needexcl > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7274
				sq->sq_needexcl--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7275
				if (sq->sq_needexcl == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7276
					SQ_PUTCOUNT_SETFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7277
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7278
				SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7279
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7280
			mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7281
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7282
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7283
		sq->sq_flags |= SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7284
		if (!(type & SQ_CICB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7285
			SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7286
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7287
		cv_wait(&sq->sq_wait, SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7288
		if (!(type & SQ_CICB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7289
			count = sq->sq_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7290
			SQ_PUTLOCKS_ENTER(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7291
			SUM_SQ_PUTCOUNTS(sq, count);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7292
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7293
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7295
	sq->sq_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7296
	ASSERT(sq->sq_count != 0);	/* Wraparound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7297
	if (!(type & SQ_CICB)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7298
		ASSERT(count == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7299
		sq->sq_flags |= SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7300
		ASSERT(sq->sq_needexcl > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7301
		sq->sq_needexcl--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7302
		if (sq->sq_needexcl == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7303
			SQ_PUTCOUNT_SETFAST_LOCKED(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7304
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7305
		SQ_PUTLOCKS_EXIT(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7306
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7308
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7309
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7310
	cbp->cbp_func(cbp->cbp_arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7311
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7312
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7313
	 * We drop the lock only for leavesq to re-acquire it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7314
	 * Possible optimization is inline of leavesq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7315
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7316
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7317
	callbparams_free(sq, cbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7318
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7319
	leavesq(sq, SQ_CALLBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7320
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7322
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7323
 * no need to grab sq_putlocks here. See comment in strsubr.h that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7324
 * explains when sq_putlocks are used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7325
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7326
 * sq_count (or one of the sq_putcounts) has already been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7327
 * decremented by the caller, and if SQ_QUEUED, we need to call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7328
 * drain_syncq (the global syncq drain).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7329
 * If putnext_tail is called with the SQ_EXCL bit set, we are in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7330
 * one of two states, non-CIPUT perimiter, and we need to clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7331
 * it, or we went exclusive in the put procedure.  In any case,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7332
 * we want to clear the bit now, and it is probably easier to do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7333
 * this at the beginning of this function (remember, we hold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7334
 * the SQLOCK).  Lastly, if there are other messages queued
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7335
 * on the syncq (and not for our destination), enable the syncq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7336
 * for background work.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7337
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7339
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7340
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7341
putnext_tail(syncq_t *sq, queue_t *qp, uint32_t passflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7342
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7343
	uint16_t	flags = sq->sq_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7345
	ASSERT(MUTEX_HELD(SQLOCK(sq)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7346
	ASSERT(MUTEX_NOT_HELD(QLOCK(qp)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7347
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7348
	/* Clear SQ_EXCL if set in passflags */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7349
	if (passflags & SQ_EXCL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7350
		flags &= ~SQ_EXCL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7351
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7352
	if (flags & SQ_WANTWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7353
		flags &= ~SQ_WANTWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7354
		cv_broadcast(&sq->sq_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7355
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7356
	if (flags & SQ_WANTEXWAKEUP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7357
		flags &= ~SQ_WANTEXWAKEUP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7358
		cv_broadcast(&sq->sq_exitwait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7359
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7360
	sq->sq_flags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7361
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7362
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7363
	 * We have cleared SQ_EXCL if we were asked to, and started
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7364
	 * the wakeup process for waiters.  If there are no writers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7365
	 * then we need to drain the syncq if we were told to, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7366
	 * enable the background thread to do it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7367
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7368
	if (!(flags & (SQ_STAYAWAY|SQ_EXCL))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7369
		if ((passflags & SQ_QUEUED) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7370
		    (sq->sq_svcflags & SQ_DISABLED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7371
			/* drain_syncq will take care of events in the list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7372
			drain_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7373
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7374
		} else if (flags & SQ_QUEUED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7375
			sqenable(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7376
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7377
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7378
	/* Drop the SQLOCK on exit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7379
	mutex_exit(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7380
	TRACE_3(TR_FAC_STREAMS_FR, TR_PUTNEXT_END,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7381
		"putnext_end:(%p, %p, %p) done", NULL, qp, sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7382
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7384
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7385
set_qend(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7386
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7387
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7388
	if (!O_SAMESTR(q))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7389
		q->q_flag |= QEND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7390
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7391
		q->q_flag &= ~QEND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7392
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7393
	q = _OTHERQ(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7394
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7395
	if (!O_SAMESTR(q))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7396
		q->q_flag |= QEND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7397
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7398
		q->q_flag &= ~QEND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7399
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7400
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7403
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7404
clr_qfull(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7405
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7406
	queue_t	*oq = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7408
	q = q->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7409
	/* Fast check if there is any work to do before getting the lock. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7410
	if ((q->q_flag & (QFULL|QWANTW)) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7411
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7412
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7414
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7415
	 * Do not reset QFULL (and backenable) if the q_count is the reason
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7416
	 * for QFULL being set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7417
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7418
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7419
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7420
	 * If both q_count and q_mblkcnt are less than the hiwat mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7421
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7422
	if ((q->q_count < q->q_hiwat) && (q->q_mblkcnt < q->q_hiwat)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7423
		q->q_flag &= ~QFULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7424
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7425
		 * A little more confusing, how about this way:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7426
		 * if someone wants to write,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7427
		 * AND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7428
		 *    both counts are less than the lowat mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7429
		 *    OR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7430
		 *    the lowat mark is zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7431
		 * THEN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7432
		 * backenable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7433
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7434
		if ((q->q_flag & QWANTW) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7435
		    (((q->q_count < q->q_lowat) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7436
		    (q->q_mblkcnt < q->q_lowat)) || q->q_lowat == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7437
			q->q_flag &= ~QWANTW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7438
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7439
			backenable(oq, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7440
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7441
			mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7442
	} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7443
		mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7444
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7446
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7447
 * Set the forward service procedure pointer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7448
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7449
 * Called at insert-time to cache a queue's next forward service procedure in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7450
 * q_nfsrv; used by canput() and canputnext().  If the queue to be inserted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7451
 * has a service procedure then q_nfsrv points to itself.  If the queue to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7452
 * inserted does not have a service procedure, then q_nfsrv points to the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7453
 * queue forward that has a service procedure.  If the queue is at the logical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7454
 * end of the stream (driver for write side, stream head for the read side)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7455
 * and does not have a service procedure, then q_nfsrv also points to itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7456
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7457
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7458
set_nfsrv_ptr(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7459
	queue_t  *rnew,		/* read queue pointer to new module */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7460
	queue_t  *wnew,		/* write queue pointer to new module */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7461
	queue_t  *prev_rq,	/* read queue pointer to the module above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7462
	queue_t  *prev_wq)	/* write queue pointer to the module above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7463
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7464
	queue_t *qp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7466
	if (prev_wq->q_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7467
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7468
		 * Insert the driver, initialize the driver and stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7469
		 * In this case, prev_rq/prev_wq should be the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7470
		 * _I_INSERT does not allow inserting a driver.  Make sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7471
		 * that it is not an insertion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7472
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7473
		ASSERT(!(rnew->q_flag & _QINSERTING));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7474
		wnew->q_nfsrv = wnew;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7475
		if (rnew->q_qinfo->qi_srvp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7476
			rnew->q_nfsrv = rnew;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7477
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7478
			rnew->q_nfsrv = prev_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7479
		prev_rq->q_nfsrv = prev_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7480
		prev_wq->q_nfsrv = prev_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7481
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7482
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7483
		 * set up read side q_nfsrv pointer.  This MUST be done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7484
		 * before setting the write side, because the setting of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7485
		 * the write side for a fifo may depend on it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7486
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7487
		 * Suppose we have a fifo that only has pipemod pushed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7488
		 * pipemod has no read or write service procedures, so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7489
		 * nfsrv for both pipemod queues points to prev_rq (the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7490
		 * stream read head).  Now push bufmod (which has only a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7491
		 * read service procedure).  Doing the write side first,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7492
		 * wnew->q_nfsrv is set to pipemod's writeq nfsrv, which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7493
		 * is WRONG; the next queue forward from wnew with a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7494
		 * service procedure will be rnew, not the stream read head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7495
		 * Since the downstream queue (which in the case of a fifo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7496
		 * is the read queue rnew) can affect upstream queues, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7497
		 * needs to be done first.  Setting up the read side first
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7498
		 * sets nfsrv for both pipemod queues to rnew and then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7499
		 * when the write side is set up, wnew-q_nfsrv will also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7500
		 * point to rnew.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7501
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7502
		if (rnew->q_qinfo->qi_srvp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7503
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7504
			 * use _OTHERQ() because, if this is a pipe, next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7505
			 * module may have been pushed from other end and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7506
			 * q_next could be a read queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7507
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7508
			qp = _OTHERQ(prev_wq->q_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7509
			while (qp && qp->q_nfsrv != qp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7510
				qp->q_nfsrv = rnew;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7511
				qp = backq(qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7512
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7513
			rnew->q_nfsrv = rnew;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7514
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7515
			rnew->q_nfsrv = prev_rq->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7517
		/* set up write side q_nfsrv pointer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7518
		if (wnew->q_qinfo->qi_srvp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7519
			wnew->q_nfsrv = wnew;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7521
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7522
			 * For insertion, need to update nfsrv of the modules
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7523
			 * above which do not have a service routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7524
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7525
			if (rnew->q_flag & _QINSERTING) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7526
				for (qp = prev_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7527
				    qp != NULL && qp->q_nfsrv != qp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7528
				    qp = backq(qp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7529
					qp->q_nfsrv = wnew->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7530
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7531
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7532
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7533
			if (prev_wq->q_next == prev_rq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7534
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7535
				 * Since prev_wq/prev_rq are the middle of a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7536
				 * fifo, wnew/rnew will also be the middle of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7537
				 * a fifo and wnew's nfsrv is same as rnew's.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7538
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7539
				wnew->q_nfsrv = rnew->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7540
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7541
				wnew->q_nfsrv = prev_wq->q_next->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7542
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7543
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7544
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7546
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7547
 * Reset the forward service procedure pointer; called at remove-time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7548
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7549
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7550
reset_nfsrv_ptr(queue_t *rqp, queue_t *wqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7551
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7552
	queue_t *tmp_qp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7554
	/* Reset the write side q_nfsrv pointer for _I_REMOVE */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7555
	if ((rqp->q_flag & _QREMOVING) && (wqp->q_qinfo->qi_srvp != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7556
		for (tmp_qp = backq(wqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7557
		    tmp_qp != NULL && tmp_qp->q_nfsrv == wqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7558
		    tmp_qp = backq(tmp_qp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7559
			tmp_qp->q_nfsrv = wqp->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7560
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7561
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7563
	/* reset the read side q_nfsrv pointer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7564
	if (rqp->q_qinfo->qi_srvp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7565
		if (wqp->q_next) {	/* non-driver case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7566
			tmp_qp = _OTHERQ(wqp->q_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7567
			while (tmp_qp && tmp_qp->q_nfsrv == rqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7568
				/* Note that rqp->q_next cannot be NULL */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7569
				ASSERT(rqp->q_next != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7570
				tmp_qp->q_nfsrv = rqp->q_next->q_nfsrv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7571
				tmp_qp = backq(tmp_qp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7572
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7573
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7574
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7575
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7577
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7578
 * This routine should be called after all stream geometry changes to update
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7579
 * the stream head cached struio() rd/wr queue pointers. Note must be called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7580
 * with the streamlock()ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7581
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7582
 * Note: only enables Synchronous STREAMS for a side of a Stream which has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7583
 *	 an explicit synchronous barrier module queue. That is, a queue that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7584
 *	 has specified a struio() type.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7585
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7586
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7587
strsetuio(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7588
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7589
	queue_t *wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7590
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7591
	if (stp->sd_flag & STPLEX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7592
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7593
		 * Not stremahead, but a mux, so no Synchronous STREAMS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7594
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7595
		stp->sd_struiowrq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7596
		stp->sd_struiordq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7597
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7598
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7599
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7600
	 * Scan the write queue(s) while synchronous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7601
	 * until we find a qinfo uio type specified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7602
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7603
	wrq = stp->sd_wrq->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7604
	while (wrq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7605
		if (wrq->q_struiot == STRUIOT_NONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7606
			wrq = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7607
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7608
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7609
		if (wrq->q_struiot != STRUIOT_DONTCARE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7610
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7611
		if (! _SAMESTR(wrq)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7612
			wrq = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7613
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7614
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7615
		wrq = wrq->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7616
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7617
	stp->sd_struiowrq = wrq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7618
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7619
	 * Scan the read queue(s) while synchronous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7620
	 * until we find a qinfo uio type specified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7621
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7622
	wrq = stp->sd_wrq->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7623
	while (wrq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7624
		if (_RD(wrq)->q_struiot == STRUIOT_NONE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7625
			wrq = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7626
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7627
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7628
		if (_RD(wrq)->q_struiot != STRUIOT_DONTCARE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7629
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7630
		if (! _SAMESTR(wrq)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7631
			wrq = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7632
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7633
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7634
		wrq = wrq->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7635
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7636
	stp->sd_struiordq = wrq ? _RD(wrq) : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7637
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7639
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7640
 * pass_wput, unblocks the passthru queues, so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7641
 * messages can arrive at muxs lower read queue, before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7642
 * I_LINK/I_UNLINK is acked/nacked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7643
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7644
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7645
pass_wput(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7646
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7647
	syncq_t *sq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7649
	sq = _RD(q)->q_syncq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7650
	if (sq->sq_flags & SQ_BLOCKED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7651
		unblocksq(sq, SQ_BLOCKED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7652
	putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7653
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7655
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7656
 * Set up queues for the link/unlink.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7657
 * Create a new queue and block it and then insert it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7658
 * below the stream head on the lower stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7659
 * This prevents any messages from arriving during the setq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7660
 * as well as while the mux is processing the LINK/I_UNLINK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7661
 * The blocked passq is unblocked once the LINK/I_UNLINK has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7662
 * been acked or nacked or if a message is generated and sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7663
 * down muxs write put procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7664
 * see pass_wput().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7665
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7666
 * After the new queue is inserted, all messages coming from below are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7667
 * blocked. The call to strlock will ensure that all activity in the stream head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7668
 * read queue syncq is stopped (sq_count drops to zero).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7669
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7670
static queue_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7671
link_addpassthru(stdata_t *stpdown)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7672
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7673
	queue_t *passq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7674
	sqlist_t sqlist;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7676
	passq = allocq();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7677
	STREAM(passq) = STREAM(_WR(passq)) = stpdown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7678
	/* setq might sleep in allocator - avoid holding locks. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7679
	setq(passq, &passthru_rinit, &passthru_winit, NULL, QPERQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7680
	    SQ_CI|SQ_CO, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7681
	claimq(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7682
	blocksq(passq->q_syncq, SQ_BLOCKED, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7683
	insertq(STREAM(passq), passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7685
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7686
	 * Use strlock() to wait for the stream head sq_count to drop to zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7687
	 * since we are going to change q_ptr in the stream head.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7688
	 * insertq() doesn't wait for any syncq counts to drop to zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7689
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7690
	sqlist.sqlist_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7691
	sqlist.sqlist_index = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7692
	sqlist.sqlist_size = sizeof (sqlist_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7693
	sqlist_insert(&sqlist, _RD(stpdown->sd_wrq)->q_syncq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7694
	strlock(stpdown, &sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7695
	strunlock(stpdown, &sqlist);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7696
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7697
	releaseq(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7698
	return (passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7699
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7701
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7702
 * Let messages flow up into the mux by removing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7703
 * the passq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7704
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7705
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7706
link_rempassthru(queue_t *passq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7707
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7708
	claimq(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7709
	removeq(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7710
	releaseq(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7711
	freeq(passq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7712
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7713
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7714
/*
577
65796fd3c2db 4790586 bogus coding in kstrputmsg()
meem
parents: 560
diff changeset
  7715
 * Wait for the condition variable pointed to by `cvp' to be signaled,
65796fd3c2db 4790586 bogus coding in kstrputmsg()
meem
parents: 560
diff changeset
  7716
 * or for `tim' milliseconds to elapse, whichever comes first.  If `tim'
65796fd3c2db 4790586 bogus coding in kstrputmsg()
meem
parents: 560
diff changeset
  7717
 * is negative, then there is no time limit.  If `nosigs' is non-zero,
65796fd3c2db 4790586 bogus coding in kstrputmsg()
meem
parents: 560
diff changeset
  7718
 * then the wait will be non-interruptible.
65796fd3c2db 4790586 bogus coding in kstrputmsg()
meem
parents: 560
diff changeset
  7719
 *
65796fd3c2db 4790586 bogus coding in kstrputmsg()
meem
parents: 560
diff changeset
  7720
 * Returns >0 if signaled, 0 if interrupted, or -1 upon timeout.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7721
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7722
clock_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7723
str_cv_wait(kcondvar_t *cvp, kmutex_t *mp, clock_t tim, int nosigs)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7724
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7725
	clock_t ret, now, tick;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7726
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7727
	if (tim < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7728
		if (nosigs) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7729
			cv_wait(cvp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7730
			ret = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7731
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7732
			ret = cv_wait_sig(cvp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7733
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7734
	} else if (tim > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7735
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7736
		 * convert milliseconds to clock ticks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7737
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7738
		tick = MSEC_TO_TICK_ROUNDUP(tim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7739
		time_to_wait(&now, tick);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7740
		if (nosigs) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7741
			ret = cv_timedwait(cvp, mp, now);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7742
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7743
			ret = cv_timedwait_sig(cvp, mp, now);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7744
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7745
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7746
		ret = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7747
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7748
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7749
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7751
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7752
 * Wait until the stream head can determine if it is at the mark but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7753
 * don't wait forever to prevent a race condition between the "mark" state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7754
 * in the stream head and any mark state in the caller/user of this routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7755
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7756
 * This is used by sockets and for a socket it would be incorrect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7757
 * to return a failure for SIOCATMARK when there is no data in the receive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7758
 * queue and the marked urgent data is traveling up the stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7759
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7760
 * This routine waits until the mark is known by waiting for one of these
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7761
 * three events:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7762
 *	The stream head read queue becoming non-empty (including an EOF)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7763
 *	The STRATMARK flag being set. (Due to a MSGMARKNEXT message.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7764
 *	The STRNOTATMARK flag being set (which indicates that the transport
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7765
 *	has sent a MSGNOTMARKNEXT message to indicate that it is not at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7766
 *	the mark).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7767
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7768
 * The routine returns 1 if the stream is at the mark; 0 if it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7769
 * be determined that the stream is not at the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7770
 * If the wait times out and it can't determine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7771
 * whether or not the stream might be at the mark the routine will return -1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7772
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7773
 * Note: This routine should only be used when a mark is pending i.e.,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7774
 * in the socket case the SIGURG has been posted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7775
 * Note2: This can not wakeup just because synchronous streams indicate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7776
 * that data is available since it is not possible to use the synchronous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7777
 * streams interfaces to determine the b_flag value for the data queued below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7778
 * the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7779
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7780
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7781
strwaitmark(vnode_t *vp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7782
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7783
	struct stdata *stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7784
	queue_t *rq = _RD(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7785
	int mark;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7786
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7787
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7788
	while (rq->q_first == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7789
	    !(stp->sd_flag & (STRATMARK|STRNOTATMARK|STREOF))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7790
		stp->sd_flag |= RSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7791
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7792
		/* Wait for 100 milliseconds for any state change. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7793
		if (str_cv_wait(&rq->q_wait, &stp->sd_lock, 100, 1) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7794
			mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7795
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7796
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7797
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7798
	if (stp->sd_flag & STRATMARK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7799
		mark = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7800
	else if (rq->q_first != NULL && (rq->q_first->b_flag & MSGMARK))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7801
		mark = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7802
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7803
		mark = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7805
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7806
	return (mark);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7807
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7808
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7809
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7810
 * Set a read side error. If persist is set change the socket error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7811
 * to persistent. If errfunc is set install the function as the exported
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7812
 * error handler.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7813
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7814
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7815
strsetrerror(vnode_t *vp, int error, int persist, errfunc_t errfunc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7816
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7817
	struct stdata *stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7818
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7819
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7820
	stp->sd_rerror = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7821
	if (error == 0 && errfunc == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7822
		stp->sd_flag &= ~STRDERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7823
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7824
		stp->sd_flag |= STRDERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7825
	if (persist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7826
		stp->sd_flag &= ~STRDERRNONPERSIST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7827
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7828
		stp->sd_flag |= STRDERRNONPERSIST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7830
	stp->sd_rderrfunc = errfunc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7831
	if (error != 0 || errfunc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7832
		cv_broadcast(&_RD(stp->sd_wrq)->q_wait);	/* readers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7833
		cv_broadcast(&stp->sd_wrq->q_wait);		/* writers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7834
		cv_broadcast(&stp->sd_monitor);			/* ioctllers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7836
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7837
		pollwakeup(&stp->sd_pollist, POLLERR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7838
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7839
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7840
		if (stp->sd_sigflags & S_ERROR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7841
			strsendsig(stp->sd_siglist, S_ERROR, 0, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7842
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7843
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7844
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7846
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7847
 * Set a write side error. If persist is set change the socket error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7848
 * to persistent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7849
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7850
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7851
strsetwerror(vnode_t *vp, int error, int persist, errfunc_t errfunc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7852
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7853
	struct stdata *stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7854
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7855
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7856
	stp->sd_werror = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7857
	if (error == 0 && errfunc == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7858
		stp->sd_flag &= ~STWRERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7859
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7860
		stp->sd_flag |= STWRERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7861
	if (persist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7862
		stp->sd_flag &= ~STWRERRNONPERSIST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7863
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7864
		stp->sd_flag |= STWRERRNONPERSIST;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7865
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7866
	stp->sd_wrerrfunc = errfunc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7867
	if (error != 0 || errfunc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7868
		cv_broadcast(&_RD(stp->sd_wrq)->q_wait);	/* readers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7869
		cv_broadcast(&stp->sd_wrq->q_wait);		/* writers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7870
		cv_broadcast(&stp->sd_monitor);			/* ioctllers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7872
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7873
		pollwakeup(&stp->sd_pollist, POLLERR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7874
		mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7875
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7876
		if (stp->sd_sigflags & S_ERROR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7877
			strsendsig(stp->sd_siglist, S_ERROR, 0, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7878
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7879
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7880
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7881
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7882
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7883
 * Make the stream return 0 (EOF) when all data has been read.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7884
 * No effect on write side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7885
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7886
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7887
strseteof(vnode_t *vp, int eof)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7888
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7889
	struct stdata *stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7891
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7892
	if (!eof) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7893
		stp->sd_flag &= ~STREOF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7894
		mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7895
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7896
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7897
	stp->sd_flag |= STREOF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7898
	if (stp->sd_flag & RSLEEP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7899
		stp->sd_flag &= ~RSLEEP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7900
		cv_broadcast(&_RD(stp->sd_wrq)->q_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7901
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7902
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7903
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7904
	pollwakeup(&stp->sd_pollist, POLLIN|POLLRDNORM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7905
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7907
	if (stp->sd_sigflags & (S_INPUT|S_RDNORM))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7908
		strsendsig(stp->sd_siglist, S_INPUT|S_RDNORM, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7909
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7910
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7912
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7913
strflushrq(vnode_t *vp, int flag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7914
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7915
	struct stdata *stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7916
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7917
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7918
	flushq(_RD(stp->sd_wrq), flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7919
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7920
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7922
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7923
strsetrputhooks(vnode_t *vp, uint_t flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7924
		msgfunc_t protofunc, msgfunc_t miscfunc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7925
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7926
	struct stdata *stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7928
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7930
	if (protofunc == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7931
		stp->sd_rprotofunc = strrput_proto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7932
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7933
		stp->sd_rprotofunc = protofunc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7935
	if (miscfunc == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7936
		stp->sd_rmiscfunc = strrput_misc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7937
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7938
		stp->sd_rmiscfunc = miscfunc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7940
	if (flags & SH_CONSOL_DATA)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7941
		stp->sd_rput_opt |= SR_CONSOL_DATA;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7942
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7943
		stp->sd_rput_opt &= ~SR_CONSOL_DATA;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7945
	if (flags & SH_SIGALLDATA)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7946
		stp->sd_rput_opt |= SR_SIGALLDATA;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7947
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7948
		stp->sd_rput_opt &= ~SR_SIGALLDATA;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7949
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7950
	if (flags & SH_IGN_ZEROLEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7951
		stp->sd_rput_opt |= SR_IGN_ZEROLEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7952
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7953
		stp->sd_rput_opt &= ~SR_IGN_ZEROLEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7955
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7956
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7957
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7958
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7959
strsetwputhooks(vnode_t *vp, uint_t flags, clock_t closetime)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7960
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7961
	struct stdata *stp = vp->v_stream;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7963
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7964
	stp->sd_closetime = closetime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7966
	if (flags & SH_SIGPIPE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7967
		stp->sd_wput_opt |= SW_SIGPIPE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7968
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7969
		stp->sd_wput_opt &= ~SW_SIGPIPE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7970
	if (flags & SH_RECHECK_ERR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7971
		stp->sd_wput_opt |= SW_RECHECK_ERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7972
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7973
		stp->sd_wput_opt &= ~SW_RECHECK_ERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7975
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7976
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7978
/* Used within framework when the queue is already locked */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7979
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7980
qenable_locked(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7981
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7982
	stdata_t *stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7983
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7984
	ASSERT(MUTEX_HELD(QLOCK(q)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7985
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7986
	if (!q->q_qinfo->qi_srvp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7987
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7989
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7990
	 * Do not place on run queue if already enabled or closing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7991
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7992
	if (q->q_flag & (QWCLOSE|QENAB))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7993
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7995
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7996
	 * mark queue enabled and place on run list if it is not already being
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7997
	 * serviced. If it is serviced, the runservice() function will detect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7998
	 * that QENAB is set and call service procedure before clearing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7999
	 * QINSERVICE flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8000
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8001
	q->q_flag |= QENAB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8002
	if (q->q_flag & QINSERVICE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8003
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8004
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8005
	/* Record the time of qenable */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8006
	q->q_qtstamp = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8007
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8008
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8009
	 * Put the queue in the stp list and schedule it for background
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8010
	 * processing if it is not already scheduled or if stream head does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8011
	 * intent to process it in the foreground later by setting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8012
	 * STRS_WILLSERVICE flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8013
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8014
	mutex_enter(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8015
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8016
	 * If there are already something on the list, stp flags should show
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8017
	 * intention to drain it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8018
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8019
	IMPLY(STREAM_NEEDSERVICE(stp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8020
	    (stp->sd_svcflags & (STRS_WILLSERVICE | STRS_SCHEDULED)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8022
	ENQUEUE(q, stp->sd_qhead, stp->sd_qtail, q_link);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8023
	stp->sd_nqueues++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8025
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8026
	 * If no one will drain this stream we are the first producer and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8027
	 * need to schedule it for background thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8028
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8029
	if (!(stp->sd_svcflags & (STRS_WILLSERVICE | STRS_SCHEDULED))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8030
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8031
		 * No one will service this stream later, so we have to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8032
		 * schedule it now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8033
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8034
		STRSTAT(stenables);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8035
		stp->sd_svcflags |= STRS_SCHEDULED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8036
		stp->sd_servid = (void *)taskq_dispatch(streams_taskq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8037
		    (task_func_t *)stream_service, stp, TQ_NOSLEEP|TQ_NOQUEUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8039
		if (stp->sd_servid == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8040
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8041
			 * Task queue failed so fail over to the backup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8042
			 * servicing thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8043
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8044
			STRSTAT(taskqfails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8045
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8046
			 * It is safe to clear STRS_SCHEDULED flag because it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8047
			 * was set by this thread above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8048
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8049
			stp->sd_svcflags &= ~STRS_SCHEDULED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8051
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8052
			 * Failover scheduling is protected by service_queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8053
			 * lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8054
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8055
			mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8056
			ASSERT((stp->sd_qhead == q) && (stp->sd_qtail == q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8057
			ASSERT(q->q_link == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8058
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8059
			 * Append the queue to qhead/qtail list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8060
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8061
			if (qhead == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8062
				qhead = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8063
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8064
				qtail->q_link = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8065
			qtail = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8066
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8067
			 * Clear stp queue list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8068
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8069
			stp->sd_qhead = stp->sd_qtail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8070
			stp->sd_nqueues = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8071
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8072
			 * Wakeup background queue processing thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8073
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8074
			cv_signal(&services_to_run);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8075
			mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8076
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8077
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8078
	mutex_exit(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8079
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8081
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8082
queue_service(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8083
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8084
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8085
	 * The queue in the list should have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8086
	 * QENAB flag set and should not have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8087
	 * QINSERVICE flag set. QINSERVICE is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8088
	 * set when the queue is dequeued and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8089
	 * qenable_locked doesn't enqueue a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8090
	 * queue with QINSERVICE set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8091
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8093
	ASSERT(!(q->q_flag & QINSERVICE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8094
	ASSERT((q->q_flag & QENAB));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8095
	mutex_enter(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8096
	q->q_flag &= ~QENAB;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8097
	q->q_flag |= QINSERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8098
	mutex_exit(QLOCK(q));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8099
	runservice(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8100
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8102
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8103
syncq_service(syncq_t *sq)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8104
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8105
	STRSTAT(syncqservice);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8106
	mutex_enter(SQLOCK(sq));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8107
	ASSERT(!(sq->sq_svcflags & SQ_SERVICE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8108
	ASSERT(sq->sq_servcount != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8109
	ASSERT(sq->sq_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8111
	/* if we came here from the background thread, clear the flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8112
	if (sq->sq_svcflags & SQ_BGTHREAD)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8113
		sq->sq_svcflags &= ~SQ_BGTHREAD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8115
	/* let drain_syncq know that it's being called in the background */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8116
	sq->sq_svcflags |= SQ_SERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8117
	drain_syncq(sq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8118
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8120
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8121
qwriter_outer_service(syncq_t *outer)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8122
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8123
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8124
	 * Note that SQ_WRITER is used on the outer perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8125
	 * to signal that a qwriter(OUTER) is either investigating
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8126
	 * running or that it is actually running a function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8127
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8128
	outer_enter(outer, SQ_BLOCKED|SQ_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8130
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8131
	 * All inner syncq are empty and have SQ_WRITER set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8132
	 * to block entering the outer perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8133
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8134
	 * We do not need to explicitly call write_now since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8135
	 * outer_exit does it for us.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8136
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8137
	outer_exit(outer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8138
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8140
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8141
mblk_free(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8142
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8143
	dblk_t *dbp = mp->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8144
	frtn_t *frp = dbp->db_frtnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8145
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8146
	mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8147
	if (dbp->db_fthdr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8148
		str_ftfree(dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8150
	ASSERT(dbp->db_fthdr == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8151
	frp->free_func(frp->free_arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8152
	ASSERT(dbp->db_mblk == mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8154
	if (dbp->db_credp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8155
		crfree(dbp->db_credp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8156
		dbp->db_credp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8157
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8158
	dbp->db_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8159
	dbp->db_struioflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8160
	dbp->db_struioun.cksum.flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8162
	kmem_cache_free(dbp->db_cache, dbp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8163
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8165
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8166
 * Background processing of the stream queue list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8167
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8168
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8169
stream_service(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8170
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8171
	queue_t *q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8173
	mutex_enter(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8175
	STR_SERVICE(stp, q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8177
	stp->sd_svcflags &= ~STRS_SCHEDULED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8178
	stp->sd_servid = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8179
	cv_signal(&stp->sd_qcv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8180
	mutex_exit(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8181
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8183
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8184
 * Foreground processing of the stream queue list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8185
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8186
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8187
stream_runservice(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8188
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8189
	queue_t *q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8190
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8191
	mutex_enter(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8192
	STRSTAT(rservice);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8193
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8194
	 * We are going to drain this stream queue list, so qenable_locked will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8195
	 * not schedule it until we finish.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8196
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8197
	stp->sd_svcflags |= STRS_WILLSERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8199
	STR_SERVICE(stp, q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8200
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8201
	stp->sd_svcflags &= ~STRS_WILLSERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8202
	mutex_exit(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8203
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8204
	 * Help backup background thread to drain the qhead/qtail list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8205
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8206
	while (qhead != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8207
		STRSTAT(qhelps);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8208
		mutex_enter(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8209
		DQ(q, qhead, qtail, q_link);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8210
		mutex_exit(&service_queue);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8211
		if (q != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8212
			queue_service(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8213
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8214
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8216
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8217
stream_willservice(stdata_t *stp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8218
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8219
	mutex_enter(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8220
	stp->sd_svcflags |= STRS_WILLSERVICE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8221
	mutex_exit(&stp->sd_qlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8222
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8224
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8225
 * Replace the cred currently in the mblk with a different one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8226
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8227
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8228
mblk_setcred(mblk_t *mp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8229
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8230
	cred_t *ocr = DB_CRED(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8232
	ASSERT(cr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8233
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8234
	if (cr != ocr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8235
		crhold(mp->b_datap->db_credp = cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8236
		if (ocr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8237
			crfree(ocr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8238
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8239
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8241
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8242
hcksum_assoc(mblk_t *mp,  multidata_t *mmd, pdesc_t *pd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8243
    uint32_t start, uint32_t stuff, uint32_t end, uint32_t value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8244
    uint32_t flags, int km_flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8245
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8246
	int rc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8248
	ASSERT(DB_TYPE(mp) == M_DATA || DB_TYPE(mp) == M_MULTIDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8249
	if (mp->b_datap->db_type == M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8250
		/* Associate values for M_DATA type */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8251
		DB_CKSUMSTART(mp) = (intptr_t)start;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8252
		DB_CKSUMSTUFF(mp) = (intptr_t)stuff;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8253
		DB_CKSUMEND(mp) = (intptr_t)end;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8254
		DB_CKSUMFLAGS(mp) = flags;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8255
		DB_CKSUM16(mp) = (uint16_t)value;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8257
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8258
		pattrinfo_t pa_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8259
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8260
		ASSERT(mmd != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8261
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8262
		pa_info.type = PATTR_HCKSUM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8263
		pa_info.len = sizeof (pattr_hcksum_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8264
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8265
		if (mmd_addpattr(mmd, pd, &pa_info, B_TRUE, km_flags) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8266
			pattr_hcksum_t *hck = (pattr_hcksum_t *)pa_info.buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8268
			hck->hcksum_start_offset = start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8269
			hck->hcksum_stuff_offset = stuff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8270
			hck->hcksum_end_offset = end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8271
			hck->hcksum_cksum_val.inet_cksum = (uint16_t)value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8272
			hck->hcksum_flags = flags;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8273
		} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8274
			rc = -1;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8275
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8276
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8277
	return (rc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8278
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8280
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8281
hcksum_retrieve(mblk_t *mp, multidata_t *mmd, pdesc_t *pd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8282
    uint32_t *start, uint32_t *stuff, uint32_t *end,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8283
    uint32_t *value, uint32_t *flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8284
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8285
	ASSERT(DB_TYPE(mp) == M_DATA || DB_TYPE(mp) == M_MULTIDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8286
	if (mp->b_datap->db_type == M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8287
		if (flags != NULL) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8288
			*flags = DB_CKSUMFLAGS(mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8289
			if (*flags & HCK_PARTIALCKSUM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8290
				if (start != NULL)
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8291
					*start = (uint32_t)DB_CKSUMSTART(mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8292
				if (stuff != NULL)
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8293
					*stuff = (uint32_t)DB_CKSUMSTUFF(mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8294
				if (end != NULL)
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8295
					*end = (uint32_t)DB_CKSUMEND(mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8296
				if (value != NULL)
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 577
diff changeset
  8297
					*value = (uint32_t)DB_CKSUM16(mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8298
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8299
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8300
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8301
		pattrinfo_t hck_attr = {PATTR_HCKSUM};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8303
		ASSERT(mmd != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8305
		/* get hardware checksum attribute */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8306
		if (mmd_getpattr(mmd, pd, &hck_attr) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8307
			pattr_hcksum_t *hck = (pattr_hcksum_t *)hck_attr.buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8309
			ASSERT(hck_attr.len >= sizeof (pattr_hcksum_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8310
			if (flags != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8311
				*flags = hck->hcksum_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8312
			if (start != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8313
				*start = hck->hcksum_start_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8314
			if (stuff != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8315
				*stuff = hck->hcksum_stuff_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8316
			if (end != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8317
				*end = hck->hcksum_end_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8318
			if (value != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8319
				*value = (uint32_t)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8320
				    hck->hcksum_cksum_val.inet_cksum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8321
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8322
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8323
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8324
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8325
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8326
 * Checksum buffer *bp for len bytes with psum partial checksum,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8327
 * or 0 if none, and return the 16 bit partial checksum.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8328
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8329
unsigned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8330
bcksum(uchar_t *bp, int len, unsigned int psum)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8331
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8332
	int odd = len & 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8333
	extern unsigned int ip_ocsum();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8334
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8335
	if (((intptr_t)bp & 1) == 0 && !odd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8336
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8337
		 * Bp is 16 bit aligned and len is multiple of 16 bit word.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8338
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8339
		return (ip_ocsum((ushort_t *)bp, len >> 1, psum));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8340
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8341
	if (((intptr_t)bp & 1) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8342
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8343
		 * Bp isn't 16 bit aligned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8344
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8345
		unsigned int tsum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8347
#ifdef _LITTLE_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8348
		psum += *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8349
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8350
		psum += *bp << 8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8351
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8352
		len--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8353
		bp++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8354
		tsum = ip_ocsum((ushort_t *)bp, len >> 1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8355
		psum += (tsum << 8) & 0xffff | (tsum >> 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8356
		if (len & 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8357
			bp += len - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8358
#ifdef _LITTLE_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8359
			psum += *bp << 8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8360
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8361
			psum += *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8362
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8363
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8364
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8365
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8366
		 * Bp is 16 bit aligned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8367
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8368
		psum = ip_ocsum((ushort_t *)bp, len >> 1, psum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8369
		if (odd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8370
			bp += len - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8371
#ifdef _LITTLE_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8372
			psum += *bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8373
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8374
			psum += *bp << 8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8375
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8376
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8377
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8378
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8379
	 * Normalize psum to 16 bits before returning the new partial
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8380
	 * checksum. The max psum value before normalization is 0x3FDFE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8381
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8382
	return ((psum >> 16) + (psum & 0xFFFF));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8383
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8385
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8386
is_vmloaned_mblk(mblk_t *mp, multidata_t *mmd, pdesc_t *pd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8387
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8388
	boolean_t rc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8390
	ASSERT(DB_TYPE(mp) == M_DATA || DB_TYPE(mp) == M_MULTIDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8391
	if (DB_TYPE(mp) == M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8392
		rc = (((mp)->b_datap->db_struioflag & STRUIO_ZC) != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8393
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8394
		pattrinfo_t zcopy_attr = {PATTR_ZCOPY};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8396
		ASSERT(mmd != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8397
		rc = (mmd_getpattr(mmd, pd, &zcopy_attr) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8398
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8399
	return (rc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8400
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8402
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8403
freemsgchain(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8404
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8405
	mblk_t	*next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8407
	while (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8408
		next = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8409
		mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8411
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8412
		mp = next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8413
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8414
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8416
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8417
copymsgchain(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8418
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8419
	mblk_t	*nmp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8420
	mblk_t	**nmpp = &nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8422
	for (; mp != NULL; mp = mp->b_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8423
		if ((*nmpp = copymsg(mp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8424
			freemsgchain(nmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8425
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8426
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8428
		nmpp = &((*nmpp)->b_next);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8429
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8431
	return (nmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8432
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8434
/* NOTE: Do not add code after this point. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8435
#undef QLOCK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8437
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8438
 * replacement for QLOCK macro for those that can't use it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8439
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8440
kmutex_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8441
QLOCK(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8442
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8443
	return (&(q)->q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8444
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8446
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8447
 * Dummy runqueues/queuerun functions functions for backwards compatibility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8448
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8449
#undef runqueues
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8450
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8451
runqueues(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8452
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8453
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8454
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8455
#undef queuerun
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8456
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8457
queuerun(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8458
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8459
}