summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/strft.h
blob: 150bbf01f56cb76676dcf44ff4ee6e6710de1191 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_STRFT_H
#define	_SYS_STRFT_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * The flow trace subsystem is used to trace the flow of STREAMS messages
 * through a stream.
 *
 * WARNING: this is a private subsystem and subject to change at any time!
 */

#include <sys/time.h>
#include <sys/types.h>
#include <sys/stream.h>

/*
 * Some evnt defines, values 0..N are reserved for internal use,
 * (N+1)..0x1FFF are available for arbitrary module/drvier use,
 * 0x8000 (RD/WR q marker) and 0x4000 (thread cs marker) are or'ed
 * flag bits reserved for internal use.
 */
#define	FTEV_MASK	0x1FFF
#define	FTEV_ISWR	0x8000
#define	FTEV_CS		0x4000
#define	FTEV_PS		0x2000

#define	FTEV_QMASK	0x1F00

#define	FTEV_ALLOCMASK	0x1FF8
#define	FTEV_ALLOCB	0x0000
#define	FTEV_ESBALLOC	0x0001
#define	FTEV_DESBALLOC	0x0002
#define	FTEV_ESBALLOCA	0x0003
#define	FTEV_DESBALLOCA	0x0004
#define	FTEV_ALLOCBIG	0x0005
#define	FTEV_ALLOCBW	0x0006
#define	FTEV_BCALLOCB	0x0007
#define	FTEV_FREEB	0x0008
#define	FTEV_DUPB	0x0009
#define	FTEV_COPYB	0x000A

#define	FTEV_CALLER	0x000F

#define	FTEV_PUT	0x0100
#define	FTEV_PUTQ	0x0105
#define	FTEV_GETQ	0x0106
#define	FTEV_RMVQ	0x0107
#define	FTEV_INSQ	0x0108
#define	FTEV_PUTBQ	0x0109
#define	FTEV_FLUSHQ	0x010A
#define	FTEV_PUTNEXT	0x010D
#define	FTEV_RWNEXT	0x010E

#define	FTBLK_EVNTS	9
#define	FTSTK_DEPTH	15

/*
 * Stack information for each flow trace event; recorded when str_ftstack
 * is non-zero.
 */
typedef struct ftstk {
	uint_t		fs_depth;
	pc_t		fs_stk[FTSTK_DEPTH];
} ftstk_t;

/*
 * Data structure that contains the timestamp, module/driver name, next
 * module/driver name, optional callstack, event and event data (not certain
 * as to its use yet: RSF).  There is one per event.  Every time str_ftevent()
 * is called, one of the indices is filled in with this data.
 */
typedef struct ftevnt {
	hrtime_t	ts;		/* event timestamp, per gethrtime() */
	char 		*mid;		/* module/driver name */
	char		*midnext; 	/* next module/driver name */
	ushort_t 	evnt;		/* FTEV_* value above */
	ushort_t 	data;		/* event data */
	ftstk_t		*stk;		/* optional event callstack */
} ftevnt_t;

/*
 * A linked list of ftevnt arrays.
 */
typedef struct ftblk {
	struct ftblk *nxt;	/* next ftblk (or NULL if none) */
	int ix;			/* index of next free ev[] */
	struct ftevnt ev[FTBLK_EVNTS];
} ftblk_t;

/*
 * The flow trace header (start of event list).  It consists of the
 *      current writable block (tail)
 *      a hash value (for recovering trace information)
 *      The last thread to process an event
 *      The last cpu to process an event
 *      The start of the list
 * This structure is attached to a dblk, and traces a message through
 * a flow.
 */
typedef struct fthdr {
	struct ftblk *tail;
	uint_t hash;		/* accumulated hash value (sum of mid's) */
	void *thread;
	int cpu_seqid;
	struct ftblk first;
} fthdr_t;

#ifdef _KERNEL

struct datab;

extern void str_ftevent(fthdr_t *, void *, ushort_t, ushort_t);
extern void str_ftfree(struct datab *);
extern int str_ftnever, str_ftstack;

/*
 * Allocate flow-trace information and record an allocation event.
 */
#define	STR_FTALLOC(hpp, e, d) {					\
	if (str_ftnever == 0) {						\
		fthdr_t *_hp = *(hpp);					\
									\
		ASSERT(_hp == NULL);					\
		_hp = kmem_cache_alloc(fthdr_cache, KM_NOSLEEP);	\
		if ((*hpp = _hp) != NULL) {				\
			_hp->tail = &_hp->first;			\
			_hp->hash = 0;					\
			_hp->thread = curthread;			\
			_hp->cpu_seqid = CPU->cpu_seqid;		\
			_hp->first.nxt = NULL;				\
			_hp->first.ix = 0;				\
			str_ftevent(_hp, caller(), (e), (d));		\
		}							\
	}								\
}

/*
 * Add a flow-trace event to the passed-in mblk_t and any other mblk_t's
 * chained off of b_cont.
 */
#define	STR_FTEVENT_MSG(mp, p, e, d) {					\
	if (str_ftnever == 0) {						\
		mblk_t *_mp;						\
		fthdr_t *_hp;						\
									\
		for (_mp = (mp); _mp != NULL; _mp = _mp->b_cont) {	\
			if ((_hp = DB_FTHDR(_mp)) != NULL)		\
				str_ftevent(_hp, (p), (e), (d));	\
		}							\
	}								\
}

/*
 * Add a flow-trace event to *just* the passed-in mblk_t.
 */
#define	STR_FTEVENT_MBLK(mp, p, e, d) {					\
	if (str_ftnever == 0) {						\
		fthdr_t *_hp;						\
									\
		if ((mp) != NULL && ((_hp = DB_FTHDR(mp)) != NULL)) 	\
			str_ftevent(_hp, (p), (e), (d));		\
	}								\
}

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_STRFT_H */