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 */
|