1*10673SKrishnendu.Sadhukhan@Sun.COM /*
2*10673SKrishnendu.Sadhukhan@Sun.COM * CDDL HEADER START
3*10673SKrishnendu.Sadhukhan@Sun.COM *
4*10673SKrishnendu.Sadhukhan@Sun.COM * The contents of this file are subject to the terms of the
5*10673SKrishnendu.Sadhukhan@Sun.COM * Common Development and Distribution License (the "License").
6*10673SKrishnendu.Sadhukhan@Sun.COM * You may not use this file except in compliance with the License.
7*10673SKrishnendu.Sadhukhan@Sun.COM *
8*10673SKrishnendu.Sadhukhan@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10673SKrishnendu.Sadhukhan@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*10673SKrishnendu.Sadhukhan@Sun.COM * See the License for the specific language governing permissions
11*10673SKrishnendu.Sadhukhan@Sun.COM * and limitations under the License.
12*10673SKrishnendu.Sadhukhan@Sun.COM *
13*10673SKrishnendu.Sadhukhan@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*10673SKrishnendu.Sadhukhan@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10673SKrishnendu.Sadhukhan@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*10673SKrishnendu.Sadhukhan@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*10673SKrishnendu.Sadhukhan@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*10673SKrishnendu.Sadhukhan@Sun.COM *
19*10673SKrishnendu.Sadhukhan@Sun.COM * CDDL HEADER END
20*10673SKrishnendu.Sadhukhan@Sun.COM */
21*10673SKrishnendu.Sadhukhan@Sun.COM /*
22*10673SKrishnendu.Sadhukhan@Sun.COM * Copyright (c) 2008-2009, Intel Corporation.
23*10673SKrishnendu.Sadhukhan@Sun.COM * All Rights Reserved.
24*10673SKrishnendu.Sadhukhan@Sun.COM */
25*10673SKrishnendu.Sadhukhan@Sun.COM
26*10673SKrishnendu.Sadhukhan@Sun.COM #include <stdlib.h>
27*10673SKrishnendu.Sadhukhan@Sun.COM #include <string.h>
28*10673SKrishnendu.Sadhukhan@Sun.COM #include <memory.h>
29*10673SKrishnendu.Sadhukhan@Sun.COM #include <stdio.h>
30*10673SKrishnendu.Sadhukhan@Sun.COM #include <ctype.h>
31*10673SKrishnendu.Sadhukhan@Sun.COM
32*10673SKrishnendu.Sadhukhan@Sun.COM #include "latencytop.h"
33*10673SKrishnendu.Sadhukhan@Sun.COM
34*10673SKrishnendu.Sadhukhan@Sun.COM /*
35*10673SKrishnendu.Sadhukhan@Sun.COM * Structure that holds detail of a cause.
36*10673SKrishnendu.Sadhukhan@Sun.COM */
37*10673SKrishnendu.Sadhukhan@Sun.COM typedef struct {
38*10673SKrishnendu.Sadhukhan@Sun.COM int lt_c_cause_id;
39*10673SKrishnendu.Sadhukhan@Sun.COM int lt_c_flags;
40*10673SKrishnendu.Sadhukhan@Sun.COM char *lt_c_name;
41*10673SKrishnendu.Sadhukhan@Sun.COM } lt_cause_t;
42*10673SKrishnendu.Sadhukhan@Sun.COM
43*10673SKrishnendu.Sadhukhan@Sun.COM /*
44*10673SKrishnendu.Sadhukhan@Sun.COM * Structure that represents a matched cause.
45*10673SKrishnendu.Sadhukhan@Sun.COM */
46*10673SKrishnendu.Sadhukhan@Sun.COM typedef struct {
47*10673SKrishnendu.Sadhukhan@Sun.COM int lt_mt_priority;
48*10673SKrishnendu.Sadhukhan@Sun.COM int lt_mt_cause_id;
49*10673SKrishnendu.Sadhukhan@Sun.COM } lt_match_t;
50*10673SKrishnendu.Sadhukhan@Sun.COM
51*10673SKrishnendu.Sadhukhan@Sun.COM /* All lt_cause_t that are created. */
52*10673SKrishnendu.Sadhukhan@Sun.COM static GHashTable *cause_lookup = NULL;
53*10673SKrishnendu.Sadhukhan@Sun.COM static GPtrArray *causes_array = NULL;
54*10673SKrishnendu.Sadhukhan@Sun.COM static int causes_array_len = 0;
55*10673SKrishnendu.Sadhukhan@Sun.COM
56*10673SKrishnendu.Sadhukhan@Sun.COM /*
57*10673SKrishnendu.Sadhukhan@Sun.COM * This hash table maps a symbol to a cause.
58*10673SKrishnendu.Sadhukhan@Sun.COM * key is of type "char *" and value is of type "lt_match_t *".
59*10673SKrishnendu.Sadhukhan@Sun.COM */
60*10673SKrishnendu.Sadhukhan@Sun.COM static GHashTable *symbol_lookup_table = NULL;
61*10673SKrishnendu.Sadhukhan@Sun.COM
62*10673SKrishnendu.Sadhukhan@Sun.COM /*
63*10673SKrishnendu.Sadhukhan@Sun.COM * The dtrace translation rules we get from the script
64*10673SKrishnendu.Sadhukhan@Sun.COM */
65*10673SKrishnendu.Sadhukhan@Sun.COM char *dtrans = NULL;
66*10673SKrishnendu.Sadhukhan@Sun.COM
67*10673SKrishnendu.Sadhukhan@Sun.COM /*
68*10673SKrishnendu.Sadhukhan@Sun.COM * These structures are only used inside .trans parser.
69*10673SKrishnendu.Sadhukhan@Sun.COM */
70*10673SKrishnendu.Sadhukhan@Sun.COM typedef struct {
71*10673SKrishnendu.Sadhukhan@Sun.COM int lt_dm_priority;
72*10673SKrishnendu.Sadhukhan@Sun.COM char *lt_dm_macro;
73*10673SKrishnendu.Sadhukhan@Sun.COM } lt_dmacro_t;
74*10673SKrishnendu.Sadhukhan@Sun.COM
75*10673SKrishnendu.Sadhukhan@Sun.COM typedef struct {
76*10673SKrishnendu.Sadhukhan@Sun.COM GSequence *lt_pr_cmd_disable;
77*10673SKrishnendu.Sadhukhan@Sun.COM GHashTable *lt_pr_dmacro;
78*10673SKrishnendu.Sadhukhan@Sun.COM } lt_parser_t;
79*10673SKrishnendu.Sadhukhan@Sun.COM
80*10673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */
81*10673SKrishnendu.Sadhukhan@Sun.COM static void
free_cause(lt_cause_t * cause,void * user)82*10673SKrishnendu.Sadhukhan@Sun.COM free_cause(lt_cause_t *cause, void *user)
83*10673SKrishnendu.Sadhukhan@Sun.COM {
84*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(cause != NULL && cause->lt_c_name != NULL);
85*10673SKrishnendu.Sadhukhan@Sun.COM
86*10673SKrishnendu.Sadhukhan@Sun.COM free(cause->lt_c_name);
87*10673SKrishnendu.Sadhukhan@Sun.COM free(cause);
88*10673SKrishnendu.Sadhukhan@Sun.COM }
89*10673SKrishnendu.Sadhukhan@Sun.COM
90*10673SKrishnendu.Sadhukhan@Sun.COM static void
free_dmacro(lt_dmacro_t * d)91*10673SKrishnendu.Sadhukhan@Sun.COM free_dmacro(lt_dmacro_t *d)
92*10673SKrishnendu.Sadhukhan@Sun.COM {
93*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(d->lt_dm_macro != NULL);
94*10673SKrishnendu.Sadhukhan@Sun.COM free(d->lt_dm_macro);
95*10673SKrishnendu.Sadhukhan@Sun.COM free(d);
96*10673SKrishnendu.Sadhukhan@Sun.COM }
97*10673SKrishnendu.Sadhukhan@Sun.COM
98*10673SKrishnendu.Sadhukhan@Sun.COM /*
99*10673SKrishnendu.Sadhukhan@Sun.COM * Add a cause.
100*10673SKrishnendu.Sadhukhan@Sun.COM */
101*10673SKrishnendu.Sadhukhan@Sun.COM static lt_cause_t *
new_cause(char * name,int flags)102*10673SKrishnendu.Sadhukhan@Sun.COM new_cause(char *name, int flags)
103*10673SKrishnendu.Sadhukhan@Sun.COM {
104*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *entry;
105*10673SKrishnendu.Sadhukhan@Sun.COM
106*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(name != NULL);
107*10673SKrishnendu.Sadhukhan@Sun.COM
108*10673SKrishnendu.Sadhukhan@Sun.COM entry = (lt_cause_t *)lt_malloc(sizeof (lt_cause_t));
109*10673SKrishnendu.Sadhukhan@Sun.COM entry->lt_c_flags = flags;
110*10673SKrishnendu.Sadhukhan@Sun.COM entry->lt_c_name = name;
111*10673SKrishnendu.Sadhukhan@Sun.COM entry->lt_c_cause_id = causes_array_len;
112*10673SKrishnendu.Sadhukhan@Sun.COM
113*10673SKrishnendu.Sadhukhan@Sun.COM g_ptr_array_add(causes_array, entry);
114*10673SKrishnendu.Sadhukhan@Sun.COM ++causes_array_len;
115*10673SKrishnendu.Sadhukhan@Sun.COM
116*10673SKrishnendu.Sadhukhan@Sun.COM return (entry);
117*10673SKrishnendu.Sadhukhan@Sun.COM }
118*10673SKrishnendu.Sadhukhan@Sun.COM
119*10673SKrishnendu.Sadhukhan@Sun.COM /*
120*10673SKrishnendu.Sadhukhan@Sun.COM * Set a cause to "disabled" state.
121*10673SKrishnendu.Sadhukhan@Sun.COM */
122*10673SKrishnendu.Sadhukhan@Sun.COM static void
disable_cause(char * cause_str,GHashTable * cause_table)123*10673SKrishnendu.Sadhukhan@Sun.COM disable_cause(char *cause_str, GHashTable *cause_table)
124*10673SKrishnendu.Sadhukhan@Sun.COM {
125*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *cause;
126*10673SKrishnendu.Sadhukhan@Sun.COM
127*10673SKrishnendu.Sadhukhan@Sun.COM cause = (lt_cause_t *)g_hash_table_lookup(cause_table, cause_str);
128*10673SKrishnendu.Sadhukhan@Sun.COM
129*10673SKrishnendu.Sadhukhan@Sun.COM if (cause != NULL) {
130*10673SKrishnendu.Sadhukhan@Sun.COM cause->lt_c_flags |= CAUSE_FLAG_DISABLED;
131*10673SKrishnendu.Sadhukhan@Sun.COM }
132*10673SKrishnendu.Sadhukhan@Sun.COM }
133*10673SKrishnendu.Sadhukhan@Sun.COM
134*10673SKrishnendu.Sadhukhan@Sun.COM /*
135*10673SKrishnendu.Sadhukhan@Sun.COM * Helper functions that reads a line from a character array.
136*10673SKrishnendu.Sadhukhan@Sun.COM */
137*10673SKrishnendu.Sadhukhan@Sun.COM static int
read_line_from_mem(const char * mem,int mem_len,char * line,int line_len,int * index)138*10673SKrishnendu.Sadhukhan@Sun.COM read_line_from_mem(const char *mem, int mem_len, char *line, int line_len,
139*10673SKrishnendu.Sadhukhan@Sun.COM int *index)
140*10673SKrishnendu.Sadhukhan@Sun.COM {
141*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(mem != NULL && line != NULL && index != NULL);
142*10673SKrishnendu.Sadhukhan@Sun.COM
143*10673SKrishnendu.Sadhukhan@Sun.COM if (line_len <= 0 || mem_len <= 0) {
144*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
145*10673SKrishnendu.Sadhukhan@Sun.COM }
146*10673SKrishnendu.Sadhukhan@Sun.COM
147*10673SKrishnendu.Sadhukhan@Sun.COM if (*index >= mem_len) {
148*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
149*10673SKrishnendu.Sadhukhan@Sun.COM }
150*10673SKrishnendu.Sadhukhan@Sun.COM
151*10673SKrishnendu.Sadhukhan@Sun.COM while (line_len > 1 && *index < mem_len) {
152*10673SKrishnendu.Sadhukhan@Sun.COM *line = mem[(*index)++];
153*10673SKrishnendu.Sadhukhan@Sun.COM --line_len;
154*10673SKrishnendu.Sadhukhan@Sun.COM ++line;
155*10673SKrishnendu.Sadhukhan@Sun.COM
156*10673SKrishnendu.Sadhukhan@Sun.COM if (*(line-1) == '\r' || *(line-1) == '\n') {
157*10673SKrishnendu.Sadhukhan@Sun.COM break;
158*10673SKrishnendu.Sadhukhan@Sun.COM }
159*10673SKrishnendu.Sadhukhan@Sun.COM }
160*10673SKrishnendu.Sadhukhan@Sun.COM *line = '\0';
161*10673SKrishnendu.Sadhukhan@Sun.COM
162*10673SKrishnendu.Sadhukhan@Sun.COM return (1);
163*10673SKrishnendu.Sadhukhan@Sun.COM }
164*10673SKrishnendu.Sadhukhan@Sun.COM
165*10673SKrishnendu.Sadhukhan@Sun.COM /*
166*10673SKrishnendu.Sadhukhan@Sun.COM * Parse special command from configuration file. Special command
167*10673SKrishnendu.Sadhukhan@Sun.COM * has the following format :
168*10673SKrishnendu.Sadhukhan@Sun.COM
169*10673SKrishnendu.Sadhukhan@Sun.COM * disable_cause <cause name>
170*10673SKrishnendu.Sadhukhan@Sun.COM */
171*10673SKrishnendu.Sadhukhan@Sun.COM static int
parse_config_cmd(char * begin,lt_parser_t * parser)172*10673SKrishnendu.Sadhukhan@Sun.COM parse_config_cmd(char *begin, lt_parser_t *parser)
173*10673SKrishnendu.Sadhukhan@Sun.COM {
174*10673SKrishnendu.Sadhukhan@Sun.COM char *tmp;
175*10673SKrishnendu.Sadhukhan@Sun.COM char old_chr = 0;
176*10673SKrishnendu.Sadhukhan@Sun.COM
177*10673SKrishnendu.Sadhukhan@Sun.COM /*
178*10673SKrishnendu.Sadhukhan@Sun.COM * disable_cause FSFlush Daemon
179*10673SKrishnendu.Sadhukhan@Sun.COM * ^
180*10673SKrishnendu.Sadhukhan@Sun.COM */
181*10673SKrishnendu.Sadhukhan@Sun.COM if (*begin == '\0') {
182*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
183*10673SKrishnendu.Sadhukhan@Sun.COM }
184*10673SKrishnendu.Sadhukhan@Sun.COM
185*10673SKrishnendu.Sadhukhan@Sun.COM for (tmp = begin;
186*10673SKrishnendu.Sadhukhan@Sun.COM *tmp != '\0' && !isspace(*tmp);
187*10673SKrishnendu.Sadhukhan@Sun.COM ++tmp) {
188*10673SKrishnendu.Sadhukhan@Sun.COM }
189*10673SKrishnendu.Sadhukhan@Sun.COM old_chr = *tmp;
190*10673SKrishnendu.Sadhukhan@Sun.COM *tmp = '\0';
191*10673SKrishnendu.Sadhukhan@Sun.COM
192*10673SKrishnendu.Sadhukhan@Sun.COM if (strcmp("disable_cause", begin) == 0) {
193*10673SKrishnendu.Sadhukhan@Sun.COM if (old_chr == '\0') {
194*10673SKrishnendu.Sadhukhan@Sun.COM /* Must have an argument */
195*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
196*10673SKrishnendu.Sadhukhan@Sun.COM "Invalid command format: %s\n",
197*10673SKrishnendu.Sadhukhan@Sun.COM begin);
198*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
199*10673SKrishnendu.Sadhukhan@Sun.COM }
200*10673SKrishnendu.Sadhukhan@Sun.COM
201*10673SKrishnendu.Sadhukhan@Sun.COM begin = tmp+1;
202*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
203*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
204*10673SKrishnendu.Sadhukhan@Sun.COM }
205*10673SKrishnendu.Sadhukhan@Sun.COM
206*10673SKrishnendu.Sadhukhan@Sun.COM g_sequence_append(parser->lt_pr_cmd_disable,
207*10673SKrishnendu.Sadhukhan@Sun.COM lt_strdup(begin));
208*10673SKrishnendu.Sadhukhan@Sun.COM } else {
209*10673SKrishnendu.Sadhukhan@Sun.COM *tmp = old_chr;
210*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
211*10673SKrishnendu.Sadhukhan@Sun.COM "Unknown command: %s\n", begin);
212*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
213*10673SKrishnendu.Sadhukhan@Sun.COM }
214*10673SKrishnendu.Sadhukhan@Sun.COM
215*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
216*10673SKrishnendu.Sadhukhan@Sun.COM }
217*10673SKrishnendu.Sadhukhan@Sun.COM
218*10673SKrishnendu.Sadhukhan@Sun.COM /*
219*10673SKrishnendu.Sadhukhan@Sun.COM * Parse symbol translation from configuration file. Symbol translation
220*10673SKrishnendu.Sadhukhan@Sun.COM * has the following format :
221*10673SKrishnendu.Sadhukhan@Sun.COM *
222*10673SKrishnendu.Sadhukhan@Sun.COM * <priority> <symbol name> <cause>
223*10673SKrishnendu.Sadhukhan@Sun.COM *
224*10673SKrishnendu.Sadhukhan@Sun.COM * Finally check if that cause has already been mapped.
225*10673SKrishnendu.Sadhukhan@Sun.COM */
226*10673SKrishnendu.Sadhukhan@Sun.COM static int
parse_sym_trans(char * begin)227*10673SKrishnendu.Sadhukhan@Sun.COM parse_sym_trans(char *begin)
228*10673SKrishnendu.Sadhukhan@Sun.COM {
229*10673SKrishnendu.Sadhukhan@Sun.COM int priority = 0;
230*10673SKrishnendu.Sadhukhan@Sun.COM char *match;
231*10673SKrishnendu.Sadhukhan@Sun.COM char *match_dup;
232*10673SKrishnendu.Sadhukhan@Sun.COM char *cause_str;
233*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *cause;
234*10673SKrishnendu.Sadhukhan@Sun.COM lt_match_t *match_entry;
235*10673SKrishnendu.Sadhukhan@Sun.COM char *tmp;
236*10673SKrishnendu.Sadhukhan@Sun.COM
237*10673SKrishnendu.Sadhukhan@Sun.COM /*
238*10673SKrishnendu.Sadhukhan@Sun.COM * 10 genunix`pread Syscall pread
239*10673SKrishnendu.Sadhukhan@Sun.COM * ^
240*10673SKrishnendu.Sadhukhan@Sun.COM */
241*10673SKrishnendu.Sadhukhan@Sun.COM priority = strtol(begin, &tmp, 10);
242*10673SKrishnendu.Sadhukhan@Sun.COM
243*10673SKrishnendu.Sadhukhan@Sun.COM if (tmp == begin || priority == 0) {
244*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
245*10673SKrishnendu.Sadhukhan@Sun.COM }
246*10673SKrishnendu.Sadhukhan@Sun.COM
247*10673SKrishnendu.Sadhukhan@Sun.COM begin = tmp;
248*10673SKrishnendu.Sadhukhan@Sun.COM
249*10673SKrishnendu.Sadhukhan@Sun.COM /*
250*10673SKrishnendu.Sadhukhan@Sun.COM * 10 genunix`pread Syscall pread
251*10673SKrishnendu.Sadhukhan@Sun.COM * --^
252*10673SKrishnendu.Sadhukhan@Sun.COM */
253*10673SKrishnendu.Sadhukhan@Sun.COM
254*10673SKrishnendu.Sadhukhan@Sun.COM if (!isspace(*begin)) {
255*10673SKrishnendu.Sadhukhan@Sun.COM /* At least one space char after <priority> */
256*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
257*10673SKrishnendu.Sadhukhan@Sun.COM }
258*10673SKrishnendu.Sadhukhan@Sun.COM
259*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
260*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
261*10673SKrishnendu.Sadhukhan@Sun.COM }
262*10673SKrishnendu.Sadhukhan@Sun.COM
263*10673SKrishnendu.Sadhukhan@Sun.COM if (*begin == 0) {
264*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
265*10673SKrishnendu.Sadhukhan@Sun.COM }
266*10673SKrishnendu.Sadhukhan@Sun.COM
267*10673SKrishnendu.Sadhukhan@Sun.COM /*
268*10673SKrishnendu.Sadhukhan@Sun.COM * 10 genunix`pread Syscall pread
269*10673SKrishnendu.Sadhukhan@Sun.COM * -----^
270*10673SKrishnendu.Sadhukhan@Sun.COM */
271*10673SKrishnendu.Sadhukhan@Sun.COM for (tmp = begin;
272*10673SKrishnendu.Sadhukhan@Sun.COM *tmp != '\0' && !isspace(*tmp);
273*10673SKrishnendu.Sadhukhan@Sun.COM ++tmp) {
274*10673SKrishnendu.Sadhukhan@Sun.COM }
275*10673SKrishnendu.Sadhukhan@Sun.COM
276*10673SKrishnendu.Sadhukhan@Sun.COM if (*tmp == '\0') {
277*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
278*10673SKrishnendu.Sadhukhan@Sun.COM }
279*10673SKrishnendu.Sadhukhan@Sun.COM
280*10673SKrishnendu.Sadhukhan@Sun.COM *tmp = '\0';
281*10673SKrishnendu.Sadhukhan@Sun.COM match = begin;
282*10673SKrishnendu.Sadhukhan@Sun.COM
283*10673SKrishnendu.Sadhukhan@Sun.COM /* Check if we have mapped this function before. */
284*10673SKrishnendu.Sadhukhan@Sun.COM match_entry = (lt_match_t *)
285*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_lookup(symbol_lookup_table, match);
286*10673SKrishnendu.Sadhukhan@Sun.COM
287*10673SKrishnendu.Sadhukhan@Sun.COM if (match_entry != NULL &&
288*10673SKrishnendu.Sadhukhan@Sun.COM HIGHER_PRIORITY(match_entry->lt_mt_priority, priority)) {
289*10673SKrishnendu.Sadhukhan@Sun.COM /* We already have a higher entry. Ignore this. */
290*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
291*10673SKrishnendu.Sadhukhan@Sun.COM }
292*10673SKrishnendu.Sadhukhan@Sun.COM
293*10673SKrishnendu.Sadhukhan@Sun.COM begin = tmp + 1;
294*10673SKrishnendu.Sadhukhan@Sun.COM
295*10673SKrishnendu.Sadhukhan@Sun.COM /*
296*10673SKrishnendu.Sadhukhan@Sun.COM * 10 genunix`pread Syscall pread
297*10673SKrishnendu.Sadhukhan@Sun.COM * -------------------------------------^
298*10673SKrishnendu.Sadhukhan@Sun.COM */
299*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
300*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
301*10673SKrishnendu.Sadhukhan@Sun.COM }
302*10673SKrishnendu.Sadhukhan@Sun.COM
303*10673SKrishnendu.Sadhukhan@Sun.COM if (*begin == 0) {
304*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
305*10673SKrishnendu.Sadhukhan@Sun.COM }
306*10673SKrishnendu.Sadhukhan@Sun.COM
307*10673SKrishnendu.Sadhukhan@Sun.COM cause_str = begin;
308*10673SKrishnendu.Sadhukhan@Sun.COM
309*10673SKrishnendu.Sadhukhan@Sun.COM /* Check if we have mapped this cause before. */
310*10673SKrishnendu.Sadhukhan@Sun.COM cause = (lt_cause_t *)
311*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_lookup(cause_lookup, cause_str);
312*10673SKrishnendu.Sadhukhan@Sun.COM
313*10673SKrishnendu.Sadhukhan@Sun.COM if (cause == NULL) {
314*10673SKrishnendu.Sadhukhan@Sun.COM char *cause_dup = lt_strdup(cause_str);
315*10673SKrishnendu.Sadhukhan@Sun.COM cause = new_cause(cause_dup, 0);
316*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_insert(cause_lookup, cause_dup, cause);
317*10673SKrishnendu.Sadhukhan@Sun.COM }
318*10673SKrishnendu.Sadhukhan@Sun.COM
319*10673SKrishnendu.Sadhukhan@Sun.COM match_entry = (lt_match_t *)lt_malloc(sizeof (lt_match_t));
320*10673SKrishnendu.Sadhukhan@Sun.COM match_entry->lt_mt_priority = priority;
321*10673SKrishnendu.Sadhukhan@Sun.COM match_entry->lt_mt_cause_id = cause->lt_c_cause_id;
322*10673SKrishnendu.Sadhukhan@Sun.COM match_dup = lt_strdup(match);
323*10673SKrishnendu.Sadhukhan@Sun.COM
324*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_insert(symbol_lookup_table, match_dup,
325*10673SKrishnendu.Sadhukhan@Sun.COM match_entry);
326*10673SKrishnendu.Sadhukhan@Sun.COM
327*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
328*10673SKrishnendu.Sadhukhan@Sun.COM }
329*10673SKrishnendu.Sadhukhan@Sun.COM
330*10673SKrishnendu.Sadhukhan@Sun.COM /*
331*10673SKrishnendu.Sadhukhan@Sun.COM * Parse D macro. D macros have the following format :
332*10673SKrishnendu.Sadhukhan@Sun.COM *
333*10673SKrishnendu.Sadhukhan@Sun.COM * <priority> <entry probe> <return probe> <cause>
334*10673SKrishnendu.Sadhukhan@Sun.COM *
335*10673SKrishnendu.Sadhukhan@Sun.COM * Finally check if that cause has already been mapped.
336*10673SKrishnendu.Sadhukhan@Sun.COM */
337*10673SKrishnendu.Sadhukhan@Sun.COM static int
parse_dmacro(char * begin,lt_parser_t * parser)338*10673SKrishnendu.Sadhukhan@Sun.COM parse_dmacro(char *begin, lt_parser_t *parser)
339*10673SKrishnendu.Sadhukhan@Sun.COM {
340*10673SKrishnendu.Sadhukhan@Sun.COM int priority = 0;
341*10673SKrishnendu.Sadhukhan@Sun.COM char *entryprobe;
342*10673SKrishnendu.Sadhukhan@Sun.COM char *returnprobe;
343*10673SKrishnendu.Sadhukhan@Sun.COM char *cause_str;
344*10673SKrishnendu.Sadhukhan@Sun.COM char buf[512];
345*10673SKrishnendu.Sadhukhan@Sun.COM char probepair[512];
346*10673SKrishnendu.Sadhukhan@Sun.COM char *tmp = NULL;
347*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *cause;
348*10673SKrishnendu.Sadhukhan@Sun.COM lt_dmacro_t *dmacro;
349*10673SKrishnendu.Sadhukhan@Sun.COM
350*10673SKrishnendu.Sadhukhan@Sun.COM /*
351*10673SKrishnendu.Sadhukhan@Sun.COM * 10 syscall::pread:entry syscall::pread:return Syscall pread
352*10673SKrishnendu.Sadhukhan@Sun.COM * ^
353*10673SKrishnendu.Sadhukhan@Sun.COM */
354*10673SKrishnendu.Sadhukhan@Sun.COM priority = strtol(begin, &tmp, 10);
355*10673SKrishnendu.Sadhukhan@Sun.COM
356*10673SKrishnendu.Sadhukhan@Sun.COM if (tmp == begin || priority == 0) {
357*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
358*10673SKrishnendu.Sadhukhan@Sun.COM }
359*10673SKrishnendu.Sadhukhan@Sun.COM
360*10673SKrishnendu.Sadhukhan@Sun.COM begin = tmp;
361*10673SKrishnendu.Sadhukhan@Sun.COM
362*10673SKrishnendu.Sadhukhan@Sun.COM /*
363*10673SKrishnendu.Sadhukhan@Sun.COM * 10 syscall::pread:entry syscall::pread:return Syscall pread
364*10673SKrishnendu.Sadhukhan@Sun.COM * --^
365*10673SKrishnendu.Sadhukhan@Sun.COM */
366*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
367*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
368*10673SKrishnendu.Sadhukhan@Sun.COM }
369*10673SKrishnendu.Sadhukhan@Sun.COM
370*10673SKrishnendu.Sadhukhan@Sun.COM if (*begin == 0) {
371*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
372*10673SKrishnendu.Sadhukhan@Sun.COM }
373*10673SKrishnendu.Sadhukhan@Sun.COM
374*10673SKrishnendu.Sadhukhan@Sun.COM /*
375*10673SKrishnendu.Sadhukhan@Sun.COM * 10 syscall::pread:entry syscall::pread:return Syscall pread
376*10673SKrishnendu.Sadhukhan@Sun.COM * -----^
377*10673SKrishnendu.Sadhukhan@Sun.COM */
378*10673SKrishnendu.Sadhukhan@Sun.COM for (tmp = begin;
379*10673SKrishnendu.Sadhukhan@Sun.COM *tmp != '\0' && !isspace(*tmp);
380*10673SKrishnendu.Sadhukhan@Sun.COM ++tmp) {
381*10673SKrishnendu.Sadhukhan@Sun.COM }
382*10673SKrishnendu.Sadhukhan@Sun.COM
383*10673SKrishnendu.Sadhukhan@Sun.COM if (*tmp == '\0') {
384*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
385*10673SKrishnendu.Sadhukhan@Sun.COM }
386*10673SKrishnendu.Sadhukhan@Sun.COM
387*10673SKrishnendu.Sadhukhan@Sun.COM *tmp = '\0';
388*10673SKrishnendu.Sadhukhan@Sun.COM entryprobe = begin;
389*10673SKrishnendu.Sadhukhan@Sun.COM begin = tmp + 1;
390*10673SKrishnendu.Sadhukhan@Sun.COM
391*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
392*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
393*10673SKrishnendu.Sadhukhan@Sun.COM }
394*10673SKrishnendu.Sadhukhan@Sun.COM
395*10673SKrishnendu.Sadhukhan@Sun.COM /*
396*10673SKrishnendu.Sadhukhan@Sun.COM * 10 syscall::pread:entry syscall::pread:return Syscall pread
397*10673SKrishnendu.Sadhukhan@Sun.COM * -----------------------------^
398*10673SKrishnendu.Sadhukhan@Sun.COM */
399*10673SKrishnendu.Sadhukhan@Sun.COM for (tmp = begin;
400*10673SKrishnendu.Sadhukhan@Sun.COM *tmp != '\0' && !isspace(*tmp);
401*10673SKrishnendu.Sadhukhan@Sun.COM ++tmp) {
402*10673SKrishnendu.Sadhukhan@Sun.COM }
403*10673SKrishnendu.Sadhukhan@Sun.COM
404*10673SKrishnendu.Sadhukhan@Sun.COM if (*tmp == '\0') {
405*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
406*10673SKrishnendu.Sadhukhan@Sun.COM }
407*10673SKrishnendu.Sadhukhan@Sun.COM
408*10673SKrishnendu.Sadhukhan@Sun.COM *tmp = '\0';
409*10673SKrishnendu.Sadhukhan@Sun.COM returnprobe = begin;
410*10673SKrishnendu.Sadhukhan@Sun.COM begin = tmp + 1;
411*10673SKrishnendu.Sadhukhan@Sun.COM
412*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
413*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
414*10673SKrishnendu.Sadhukhan@Sun.COM }
415*10673SKrishnendu.Sadhukhan@Sun.COM
416*10673SKrishnendu.Sadhukhan@Sun.COM /*
417*10673SKrishnendu.Sadhukhan@Sun.COM * 10 syscall::pread:entry syscall::pread:return Syscall pread
418*10673SKrishnendu.Sadhukhan@Sun.COM * -----------------------------------------------------^
419*10673SKrishnendu.Sadhukhan@Sun.COM */
420*10673SKrishnendu.Sadhukhan@Sun.COM if (*begin == 0) {
421*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
422*10673SKrishnendu.Sadhukhan@Sun.COM }
423*10673SKrishnendu.Sadhukhan@Sun.COM
424*10673SKrishnendu.Sadhukhan@Sun.COM cause_str = begin;
425*10673SKrishnendu.Sadhukhan@Sun.COM
426*10673SKrishnendu.Sadhukhan@Sun.COM dmacro = NULL;
427*10673SKrishnendu.Sadhukhan@Sun.COM
428*10673SKrishnendu.Sadhukhan@Sun.COM /* Check if we have mapped this cause before. */
429*10673SKrishnendu.Sadhukhan@Sun.COM cause = (lt_cause_t *)
430*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_lookup(cause_lookup, cause_str);
431*10673SKrishnendu.Sadhukhan@Sun.COM
432*10673SKrishnendu.Sadhukhan@Sun.COM if (cause == NULL) {
433*10673SKrishnendu.Sadhukhan@Sun.COM char *cause_dup = lt_strdup(cause_str);
434*10673SKrishnendu.Sadhukhan@Sun.COM cause = new_cause(cause_dup, 0);
435*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_insert(cause_lookup, cause_dup, cause);
436*10673SKrishnendu.Sadhukhan@Sun.COM }
437*10673SKrishnendu.Sadhukhan@Sun.COM
438*10673SKrishnendu.Sadhukhan@Sun.COM (void) snprintf(buf, sizeof (buf), "\nTRANSLATE(%s, %s, \"%s\", %d)\n",
439*10673SKrishnendu.Sadhukhan@Sun.COM entryprobe, returnprobe, cause_str, priority);
440*10673SKrishnendu.Sadhukhan@Sun.COM
441*10673SKrishnendu.Sadhukhan@Sun.COM (void) snprintf(probepair, sizeof (probepair), "%s %s", entryprobe,
442*10673SKrishnendu.Sadhukhan@Sun.COM returnprobe);
443*10673SKrishnendu.Sadhukhan@Sun.COM
444*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(cause != NULL);
445*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(parser->lt_pr_dmacro != NULL);
446*10673SKrishnendu.Sadhukhan@Sun.COM
447*10673SKrishnendu.Sadhukhan@Sun.COM dmacro = g_hash_table_lookup(parser->lt_pr_dmacro, probepair);
448*10673SKrishnendu.Sadhukhan@Sun.COM
449*10673SKrishnendu.Sadhukhan@Sun.COM if (dmacro == NULL) {
450*10673SKrishnendu.Sadhukhan@Sun.COM dmacro = (lt_dmacro_t *)lt_malloc(sizeof (lt_dmacro_t));
451*10673SKrishnendu.Sadhukhan@Sun.COM dmacro->lt_dm_priority = priority;
452*10673SKrishnendu.Sadhukhan@Sun.COM dmacro->lt_dm_macro = lt_strdup(buf);
453*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_insert(parser->lt_pr_dmacro, lt_strdup(probepair),
454*10673SKrishnendu.Sadhukhan@Sun.COM dmacro);
455*10673SKrishnendu.Sadhukhan@Sun.COM } else if (dmacro->lt_dm_priority < priority) {
456*10673SKrishnendu.Sadhukhan@Sun.COM free(dmacro->lt_dm_macro);
457*10673SKrishnendu.Sadhukhan@Sun.COM dmacro->lt_dm_priority = priority;
458*10673SKrishnendu.Sadhukhan@Sun.COM dmacro->lt_dm_macro = lt_strdup(buf);
459*10673SKrishnendu.Sadhukhan@Sun.COM }
460*10673SKrishnendu.Sadhukhan@Sun.COM
461*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
462*10673SKrishnendu.Sadhukhan@Sun.COM }
463*10673SKrishnendu.Sadhukhan@Sun.COM
464*10673SKrishnendu.Sadhukhan@Sun.COM /*
465*10673SKrishnendu.Sadhukhan@Sun.COM * Helper function to collect TRANSLATE() macros.
466*10673SKrishnendu.Sadhukhan@Sun.COM */
467*10673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */
468*10673SKrishnendu.Sadhukhan@Sun.COM static void
genscript(void * key,lt_dmacro_t * dmacro,GString * str)469*10673SKrishnendu.Sadhukhan@Sun.COM genscript(void *key, lt_dmacro_t *dmacro, GString *str)
470*10673SKrishnendu.Sadhukhan@Sun.COM {
471*10673SKrishnendu.Sadhukhan@Sun.COM g_string_append(str, dmacro->lt_dm_macro);
472*10673SKrishnendu.Sadhukhan@Sun.COM }
473*10673SKrishnendu.Sadhukhan@Sun.COM
474*10673SKrishnendu.Sadhukhan@Sun.COM /*
475*10673SKrishnendu.Sadhukhan@Sun.COM * Main logic that parses translation rules one line at a time,
476*10673SKrishnendu.Sadhukhan@Sun.COM * and creates a lookup table from it. The syntax for the translation
477*10673SKrishnendu.Sadhukhan@Sun.COM * is as follows :
478*10673SKrishnendu.Sadhukhan@Sun.COM *
479*10673SKrishnendu.Sadhukhan@Sun.COM * # <--- comment
480*10673SKrishnendu.Sadhukhan@Sun.COM * D <D macro rule> <--- D macro
481*10673SKrishnendu.Sadhukhan@Sun.COM * S <Symbol translation> <--- Symbols
482*10673SKrishnendu.Sadhukhan@Sun.COM * disable_cause <cause> <--- special command
483*10673SKrishnendu.Sadhukhan@Sun.COM */
484*10673SKrishnendu.Sadhukhan@Sun.COM static int
parse_config(const char * work,int work_len)485*10673SKrishnendu.Sadhukhan@Sun.COM parse_config(const char *work, int work_len)
486*10673SKrishnendu.Sadhukhan@Sun.COM {
487*10673SKrishnendu.Sadhukhan@Sun.COM char line[256];
488*10673SKrishnendu.Sadhukhan@Sun.COM int len;
489*10673SKrishnendu.Sadhukhan@Sun.COM char *begin, *end;
490*10673SKrishnendu.Sadhukhan@Sun.COM int current = 0;
491*10673SKrishnendu.Sadhukhan@Sun.COM lt_parser_t parser;
492*10673SKrishnendu.Sadhukhan@Sun.COM int ret = 0;
493*10673SKrishnendu.Sadhukhan@Sun.COM char flag;
494*10673SKrishnendu.Sadhukhan@Sun.COM GString *script;
495*10673SKrishnendu.Sadhukhan@Sun.COM
496*10673SKrishnendu.Sadhukhan@Sun.COM cause_lookup = g_hash_table_new(g_str_hash, g_str_equal);
497*10673SKrishnendu.Sadhukhan@Sun.COM lt_check_null(cause_lookup);
498*10673SKrishnendu.Sadhukhan@Sun.COM
499*10673SKrishnendu.Sadhukhan@Sun.COM parser.lt_pr_cmd_disable = g_sequence_new((GDestroyNotify)free);
500*10673SKrishnendu.Sadhukhan@Sun.COM lt_check_null(parser.lt_pr_cmd_disable);
501*10673SKrishnendu.Sadhukhan@Sun.COM
502*10673SKrishnendu.Sadhukhan@Sun.COM parser.lt_pr_dmacro = g_hash_table_new_full(g_str_hash,
503*10673SKrishnendu.Sadhukhan@Sun.COM g_str_equal, (GDestroyNotify)free, (GDestroyNotify)free_dmacro);
504*10673SKrishnendu.Sadhukhan@Sun.COM lt_check_null(parser.lt_pr_dmacro);
505*10673SKrishnendu.Sadhukhan@Sun.COM
506*10673SKrishnendu.Sadhukhan@Sun.COM while (read_line_from_mem(work, work_len, line, sizeof (line),
507*10673SKrishnendu.Sadhukhan@Sun.COM ¤t)) {
508*10673SKrishnendu.Sadhukhan@Sun.COM len = strlen(line);
509*10673SKrishnendu.Sadhukhan@Sun.COM
510*10673SKrishnendu.Sadhukhan@Sun.COM if (line[len-1] != '\n' && line[len-1] != '\r' &&
511*10673SKrishnendu.Sadhukhan@Sun.COM current < work_len) {
512*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Configuration line too long.\n");
513*10673SKrishnendu.Sadhukhan@Sun.COM goto err;
514*10673SKrishnendu.Sadhukhan@Sun.COM }
515*10673SKrishnendu.Sadhukhan@Sun.COM
516*10673SKrishnendu.Sadhukhan@Sun.COM begin = line;
517*10673SKrishnendu.Sadhukhan@Sun.COM
518*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
519*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
520*10673SKrishnendu.Sadhukhan@Sun.COM }
521*10673SKrishnendu.Sadhukhan@Sun.COM
522*10673SKrishnendu.Sadhukhan@Sun.COM if (*begin == '\0') {
523*10673SKrishnendu.Sadhukhan@Sun.COM /* Ignore empty line */
524*10673SKrishnendu.Sadhukhan@Sun.COM continue;
525*10673SKrishnendu.Sadhukhan@Sun.COM }
526*10673SKrishnendu.Sadhukhan@Sun.COM
527*10673SKrishnendu.Sadhukhan@Sun.COM /* Delete trailing spaces. */
528*10673SKrishnendu.Sadhukhan@Sun.COM end = begin + strlen(begin) - 1;
529*10673SKrishnendu.Sadhukhan@Sun.COM
530*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*end)) {
531*10673SKrishnendu.Sadhukhan@Sun.COM --end;
532*10673SKrishnendu.Sadhukhan@Sun.COM }
533*10673SKrishnendu.Sadhukhan@Sun.COM
534*10673SKrishnendu.Sadhukhan@Sun.COM end[1] = '\0';
535*10673SKrishnendu.Sadhukhan@Sun.COM
536*10673SKrishnendu.Sadhukhan@Sun.COM flag = *begin;
537*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
538*10673SKrishnendu.Sadhukhan@Sun.COM
539*10673SKrishnendu.Sadhukhan@Sun.COM switch (flag) {
540*10673SKrishnendu.Sadhukhan@Sun.COM case '#':
541*10673SKrishnendu.Sadhukhan@Sun.COM ret = 0;
542*10673SKrishnendu.Sadhukhan@Sun.COM break;
543*10673SKrishnendu.Sadhukhan@Sun.COM case ';':
544*10673SKrishnendu.Sadhukhan@Sun.COM ret = parse_config_cmd(begin, &parser);
545*10673SKrishnendu.Sadhukhan@Sun.COM break;
546*10673SKrishnendu.Sadhukhan@Sun.COM case 'D':
547*10673SKrishnendu.Sadhukhan@Sun.COM case 'd':
548*10673SKrishnendu.Sadhukhan@Sun.COM if (!isspace(*begin)) {
549*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
550*10673SKrishnendu.Sadhukhan@Sun.COM "No space after flag char: %s\n", line);
551*10673SKrishnendu.Sadhukhan@Sun.COM }
552*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
553*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
554*10673SKrishnendu.Sadhukhan@Sun.COM }
555*10673SKrishnendu.Sadhukhan@Sun.COM ret = parse_dmacro(begin, &parser);
556*10673SKrishnendu.Sadhukhan@Sun.COM break;
557*10673SKrishnendu.Sadhukhan@Sun.COM case 'S':
558*10673SKrishnendu.Sadhukhan@Sun.COM case 's':
559*10673SKrishnendu.Sadhukhan@Sun.COM if (!isspace(*begin)) {
560*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
561*10673SKrishnendu.Sadhukhan@Sun.COM "No space after flag char: %s\n", line);
562*10673SKrishnendu.Sadhukhan@Sun.COM }
563*10673SKrishnendu.Sadhukhan@Sun.COM while (isspace(*begin)) {
564*10673SKrishnendu.Sadhukhan@Sun.COM ++begin;
565*10673SKrishnendu.Sadhukhan@Sun.COM }
566*10673SKrishnendu.Sadhukhan@Sun.COM ret = parse_sym_trans(begin);
567*10673SKrishnendu.Sadhukhan@Sun.COM break;
568*10673SKrishnendu.Sadhukhan@Sun.COM default:
569*10673SKrishnendu.Sadhukhan@Sun.COM ret = -1;
570*10673SKrishnendu.Sadhukhan@Sun.COM break;
571*10673SKrishnendu.Sadhukhan@Sun.COM }
572*10673SKrishnendu.Sadhukhan@Sun.COM
573*10673SKrishnendu.Sadhukhan@Sun.COM if (ret != 0) {
574*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
575*10673SKrishnendu.Sadhukhan@Sun.COM "Invalid configuration line: %s\n", line);
576*10673SKrishnendu.Sadhukhan@Sun.COM goto err;
577*10673SKrishnendu.Sadhukhan@Sun.COM }
578*10673SKrishnendu.Sadhukhan@Sun.COM }
579*10673SKrishnendu.Sadhukhan@Sun.COM
580*10673SKrishnendu.Sadhukhan@Sun.COM script = g_string_new(NULL);
581*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_foreach(parser.lt_pr_dmacro, (GHFunc)genscript, script);
582*10673SKrishnendu.Sadhukhan@Sun.COM dtrans = g_string_free(script, FALSE);
583*10673SKrishnendu.Sadhukhan@Sun.COM
584*10673SKrishnendu.Sadhukhan@Sun.COM if (dtrans != NULL && strlen(dtrans) == 0) {
585*10673SKrishnendu.Sadhukhan@Sun.COM free(dtrans);
586*10673SKrishnendu.Sadhukhan@Sun.COM dtrans = NULL;
587*10673SKrishnendu.Sadhukhan@Sun.COM }
588*10673SKrishnendu.Sadhukhan@Sun.COM
589*10673SKrishnendu.Sadhukhan@Sun.COM g_sequence_foreach(parser.lt_pr_cmd_disable, (GFunc)disable_cause,
590*10673SKrishnendu.Sadhukhan@Sun.COM cause_lookup);
591*10673SKrishnendu.Sadhukhan@Sun.COM g_sequence_free(parser.lt_pr_cmd_disable);
592*10673SKrishnendu.Sadhukhan@Sun.COM
593*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
594*10673SKrishnendu.Sadhukhan@Sun.COM
595*10673SKrishnendu.Sadhukhan@Sun.COM err:
596*10673SKrishnendu.Sadhukhan@Sun.COM g_sequence_free(parser.lt_pr_cmd_disable);
597*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_destroy(parser.lt_pr_dmacro);
598*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
599*10673SKrishnendu.Sadhukhan@Sun.COM
600*10673SKrishnendu.Sadhukhan@Sun.COM }
601*10673SKrishnendu.Sadhukhan@Sun.COM
602*10673SKrishnendu.Sadhukhan@Sun.COM /*
603*10673SKrishnendu.Sadhukhan@Sun.COM * Init function, called when latencytop starts.
604*10673SKrishnendu.Sadhukhan@Sun.COM * It loads translation rules from the configuration file. The configuration
605*10673SKrishnendu.Sadhukhan@Sun.COM * file defines some causes and symbols that match those causes.
606*10673SKrishnendu.Sadhukhan@Sun.COM */
607*10673SKrishnendu.Sadhukhan@Sun.COM int
lt_table_init(void)608*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_init(void)
609*10673SKrishnendu.Sadhukhan@Sun.COM {
610*10673SKrishnendu.Sadhukhan@Sun.COM char *config_loaded = NULL;
611*10673SKrishnendu.Sadhukhan@Sun.COM int config_loaded_len = 0;
612*10673SKrishnendu.Sadhukhan@Sun.COM const char *work = NULL;
613*10673SKrishnendu.Sadhukhan@Sun.COM int work_len = 0;
614*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *cause;
615*10673SKrishnendu.Sadhukhan@Sun.COM
616*10673SKrishnendu.Sadhukhan@Sun.COM #ifdef EMBED_CONFIGS
617*10673SKrishnendu.Sadhukhan@Sun.COM work = &latencytop_trans_start;
618*10673SKrishnendu.Sadhukhan@Sun.COM work_len = (int)(&latencytop_trans_end - &latencytop_trans_start);
619*10673SKrishnendu.Sadhukhan@Sun.COM #endif
620*10673SKrishnendu.Sadhukhan@Sun.COM
621*10673SKrishnendu.Sadhukhan@Sun.COM if (g_config.lt_cfg_config_name != NULL) {
622*10673SKrishnendu.Sadhukhan@Sun.COM FILE *fp;
623*10673SKrishnendu.Sadhukhan@Sun.COM fp = fopen(g_config.lt_cfg_config_name, "r");
624*10673SKrishnendu.Sadhukhan@Sun.COM
625*10673SKrishnendu.Sadhukhan@Sun.COM if (NULL == fp) {
626*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
627*10673SKrishnendu.Sadhukhan@Sun.COM "Unable to open configuration file.\n");
628*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
629*10673SKrishnendu.Sadhukhan@Sun.COM }
630*10673SKrishnendu.Sadhukhan@Sun.COM
631*10673SKrishnendu.Sadhukhan@Sun.COM (void) fseek(fp, 0, SEEK_END);
632*10673SKrishnendu.Sadhukhan@Sun.COM config_loaded_len = (int)ftell(fp);
633*10673SKrishnendu.Sadhukhan@Sun.COM config_loaded = (char *)lt_malloc(config_loaded_len);
634*10673SKrishnendu.Sadhukhan@Sun.COM (void) fseek(fp, 0, SEEK_SET);
635*10673SKrishnendu.Sadhukhan@Sun.COM
636*10673SKrishnendu.Sadhukhan@Sun.COM /* A zero-byte translation is valid */
637*10673SKrishnendu.Sadhukhan@Sun.COM if (config_loaded_len != 0 &&
638*10673SKrishnendu.Sadhukhan@Sun.COM fread(config_loaded, config_loaded_len, 1, fp) == 0) {
639*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
640*10673SKrishnendu.Sadhukhan@Sun.COM "Unable to read configuration file.\n");
641*10673SKrishnendu.Sadhukhan@Sun.COM (void) fclose(fp);
642*10673SKrishnendu.Sadhukhan@Sun.COM free(config_loaded);
643*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
644*10673SKrishnendu.Sadhukhan@Sun.COM }
645*10673SKrishnendu.Sadhukhan@Sun.COM
646*10673SKrishnendu.Sadhukhan@Sun.COM (void) fclose(fp);
647*10673SKrishnendu.Sadhukhan@Sun.COM (void) printf("Loaded configuration from %s\n",
648*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_config_name);
649*10673SKrishnendu.Sadhukhan@Sun.COM
650*10673SKrishnendu.Sadhukhan@Sun.COM work = config_loaded;
651*10673SKrishnendu.Sadhukhan@Sun.COM work_len = config_loaded_len;
652*10673SKrishnendu.Sadhukhan@Sun.COM }
653*10673SKrishnendu.Sadhukhan@Sun.COM
654*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_deinit();
655*10673SKrishnendu.Sadhukhan@Sun.COM causes_array = g_ptr_array_new();
656*10673SKrishnendu.Sadhukhan@Sun.COM lt_check_null(causes_array);
657*10673SKrishnendu.Sadhukhan@Sun.COM
658*10673SKrishnendu.Sadhukhan@Sun.COM /* 0 is not used, but it is kept as a place for bugs etc. */
659*10673SKrishnendu.Sadhukhan@Sun.COM cause = new_cause(lt_strdup("Nothing"), CAUSE_FLAG_DISABLED);
660*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(cause->lt_c_cause_id == INVALID_CAUSE);
661*10673SKrishnendu.Sadhukhan@Sun.COM
662*10673SKrishnendu.Sadhukhan@Sun.COM symbol_lookup_table = g_hash_table_new_full(
663*10673SKrishnendu.Sadhukhan@Sun.COM g_str_hash, g_str_equal,
664*10673SKrishnendu.Sadhukhan@Sun.COM (GDestroyNotify)free, (GDestroyNotify)free);
665*10673SKrishnendu.Sadhukhan@Sun.COM lt_check_null(symbol_lookup_table);
666*10673SKrishnendu.Sadhukhan@Sun.COM
667*10673SKrishnendu.Sadhukhan@Sun.COM if (work_len != 0 && parse_config(work, work_len) != 0) {
668*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
669*10673SKrishnendu.Sadhukhan@Sun.COM }
670*10673SKrishnendu.Sadhukhan@Sun.COM
671*10673SKrishnendu.Sadhukhan@Sun.COM if (config_loaded != NULL) {
672*10673SKrishnendu.Sadhukhan@Sun.COM free(config_loaded);
673*10673SKrishnendu.Sadhukhan@Sun.COM }
674*10673SKrishnendu.Sadhukhan@Sun.COM
675*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
676*10673SKrishnendu.Sadhukhan@Sun.COM }
677*10673SKrishnendu.Sadhukhan@Sun.COM
678*10673SKrishnendu.Sadhukhan@Sun.COM /*
679*10673SKrishnendu.Sadhukhan@Sun.COM * Some causes, such as "lock spinning", do not have stack trace. Names
680*10673SKrishnendu.Sadhukhan@Sun.COM * of such causes are explicitly specified in the D script.
681*10673SKrishnendu.Sadhukhan@Sun.COM * This function resolves such causes and dynamically adds them
682*10673SKrishnendu.Sadhukhan@Sun.COM * to the global tables when they are found first. If auto_create is set
683*10673SKrishnendu.Sadhukhan@Sun.COM * to TRUE, the entry will be created if it is not found.
684*10673SKrishnendu.Sadhukhan@Sun.COM * Return cause_id of the cause.
685*10673SKrishnendu.Sadhukhan@Sun.COM */
686*10673SKrishnendu.Sadhukhan@Sun.COM int
lt_table_cause_from_name(char * name,int auto_create,int flags)687*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_cause_from_name(char *name, int auto_create, int flags)
688*10673SKrishnendu.Sadhukhan@Sun.COM {
689*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *cause = NULL;
690*10673SKrishnendu.Sadhukhan@Sun.COM
691*10673SKrishnendu.Sadhukhan@Sun.COM if (cause_lookup == NULL) {
692*10673SKrishnendu.Sadhukhan@Sun.COM cause_lookup = g_hash_table_new(g_str_hash, g_str_equal);
693*10673SKrishnendu.Sadhukhan@Sun.COM lt_check_null(cause_lookup);
694*10673SKrishnendu.Sadhukhan@Sun.COM } else {
695*10673SKrishnendu.Sadhukhan@Sun.COM cause = (lt_cause_t *)
696*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_lookup(cause_lookup, name);
697*10673SKrishnendu.Sadhukhan@Sun.COM }
698*10673SKrishnendu.Sadhukhan@Sun.COM
699*10673SKrishnendu.Sadhukhan@Sun.COM if (cause == NULL && auto_create) {
700*10673SKrishnendu.Sadhukhan@Sun.COM char *cause_dup;
701*10673SKrishnendu.Sadhukhan@Sun.COM
702*10673SKrishnendu.Sadhukhan@Sun.COM if (name[0] == '#') {
703*10673SKrishnendu.Sadhukhan@Sun.COM flags |= CAUSE_FLAG_HIDE_IN_SUMMARY;
704*10673SKrishnendu.Sadhukhan@Sun.COM }
705*10673SKrishnendu.Sadhukhan@Sun.COM
706*10673SKrishnendu.Sadhukhan@Sun.COM cause_dup = lt_strdup(name);
707*10673SKrishnendu.Sadhukhan@Sun.COM cause = new_cause(cause_dup, flags);
708*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_insert(cause_lookup, cause_dup, cause);
709*10673SKrishnendu.Sadhukhan@Sun.COM }
710*10673SKrishnendu.Sadhukhan@Sun.COM
711*10673SKrishnendu.Sadhukhan@Sun.COM return (cause == NULL ? INVALID_CAUSE : cause->lt_c_cause_id);
712*10673SKrishnendu.Sadhukhan@Sun.COM }
713*10673SKrishnendu.Sadhukhan@Sun.COM
714*10673SKrishnendu.Sadhukhan@Sun.COM /*
715*10673SKrishnendu.Sadhukhan@Sun.COM * Try to map a symbol on stack to a known cause.
716*10673SKrishnendu.Sadhukhan@Sun.COM * module_func has the format "module_name`function_name".
717*10673SKrishnendu.Sadhukhan@Sun.COM * cause_id and priority will be set if a cause is found.
718*10673SKrishnendu.Sadhukhan@Sun.COM * If cause is found return 1, otherwise return 0.
719*10673SKrishnendu.Sadhukhan@Sun.COM */
720*10673SKrishnendu.Sadhukhan@Sun.COM int
lt_table_cause_from_stack(const char * module_func,int * cause_id,int * priority)721*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_cause_from_stack(const char *module_func, int *cause_id, int *priority)
722*10673SKrishnendu.Sadhukhan@Sun.COM {
723*10673SKrishnendu.Sadhukhan@Sun.COM lt_match_t *match;
724*10673SKrishnendu.Sadhukhan@Sun.COM
725*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(module_func != NULL && cause_id != NULL && priority != NULL);
726*10673SKrishnendu.Sadhukhan@Sun.COM
727*10673SKrishnendu.Sadhukhan@Sun.COM if (symbol_lookup_table == NULL) {
728*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
729*10673SKrishnendu.Sadhukhan@Sun.COM }
730*10673SKrishnendu.Sadhukhan@Sun.COM
731*10673SKrishnendu.Sadhukhan@Sun.COM match = (lt_match_t *)
732*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_lookup(symbol_lookup_table, module_func);
733*10673SKrishnendu.Sadhukhan@Sun.COM
734*10673SKrishnendu.Sadhukhan@Sun.COM if (match == NULL) {
735*10673SKrishnendu.Sadhukhan@Sun.COM char *func = strchr(module_func, '`');
736*10673SKrishnendu.Sadhukhan@Sun.COM
737*10673SKrishnendu.Sadhukhan@Sun.COM if (func != NULL) {
738*10673SKrishnendu.Sadhukhan@Sun.COM match = (lt_match_t *)
739*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_lookup(symbol_lookup_table, func);
740*10673SKrishnendu.Sadhukhan@Sun.COM }
741*10673SKrishnendu.Sadhukhan@Sun.COM }
742*10673SKrishnendu.Sadhukhan@Sun.COM
743*10673SKrishnendu.Sadhukhan@Sun.COM if (match == NULL) {
744*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
745*10673SKrishnendu.Sadhukhan@Sun.COM } else {
746*10673SKrishnendu.Sadhukhan@Sun.COM *cause_id = match->lt_mt_cause_id;
747*10673SKrishnendu.Sadhukhan@Sun.COM *priority = match->lt_mt_priority;
748*10673SKrishnendu.Sadhukhan@Sun.COM return (1);
749*10673SKrishnendu.Sadhukhan@Sun.COM }
750*10673SKrishnendu.Sadhukhan@Sun.COM }
751*10673SKrishnendu.Sadhukhan@Sun.COM
752*10673SKrishnendu.Sadhukhan@Sun.COM /*
753*10673SKrishnendu.Sadhukhan@Sun.COM * Get the display name of a cause. cause_id must be valid,
754*10673SKrishnendu.Sadhukhan@Sun.COM * it is usually returned from lt_table_cause_from_stack() or
755*10673SKrishnendu.Sadhukhan@Sun.COM * lt_table_cause_from_name().
756*10673SKrishnendu.Sadhukhan@Sun.COM */
757*10673SKrishnendu.Sadhukhan@Sun.COM const char *
lt_table_get_cause_name(int cause_id)758*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_get_cause_name(int cause_id)
759*10673SKrishnendu.Sadhukhan@Sun.COM {
760*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *cause;
761*10673SKrishnendu.Sadhukhan@Sun.COM
762*10673SKrishnendu.Sadhukhan@Sun.COM if (cause_id < 0 || cause_id >= causes_array_len) {
763*10673SKrishnendu.Sadhukhan@Sun.COM return (NULL);
764*10673SKrishnendu.Sadhukhan@Sun.COM }
765*10673SKrishnendu.Sadhukhan@Sun.COM
766*10673SKrishnendu.Sadhukhan@Sun.COM cause = (lt_cause_t *)g_ptr_array_index(causes_array, cause_id);
767*10673SKrishnendu.Sadhukhan@Sun.COM
768*10673SKrishnendu.Sadhukhan@Sun.COM if (cause == NULL) {
769*10673SKrishnendu.Sadhukhan@Sun.COM return (NULL);
770*10673SKrishnendu.Sadhukhan@Sun.COM } else {
771*10673SKrishnendu.Sadhukhan@Sun.COM return (cause->lt_c_name);
772*10673SKrishnendu.Sadhukhan@Sun.COM }
773*10673SKrishnendu.Sadhukhan@Sun.COM }
774*10673SKrishnendu.Sadhukhan@Sun.COM
775*10673SKrishnendu.Sadhukhan@Sun.COM /*
776*10673SKrishnendu.Sadhukhan@Sun.COM * Check cause flag.
777*10673SKrishnendu.Sadhukhan@Sun.COM * If CAUSE_ALL_FLAGS is passed in, all flags are returned.
778*10673SKrishnendu.Sadhukhan@Sun.COM */
779*10673SKrishnendu.Sadhukhan@Sun.COM int
lt_table_get_cause_flag(int cause_id,int flag)780*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_get_cause_flag(int cause_id, int flag)
781*10673SKrishnendu.Sadhukhan@Sun.COM {
782*10673SKrishnendu.Sadhukhan@Sun.COM lt_cause_t *cause;
783*10673SKrishnendu.Sadhukhan@Sun.COM
784*10673SKrishnendu.Sadhukhan@Sun.COM if (cause_id < 0 || cause_id >= causes_array_len) {
785*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
786*10673SKrishnendu.Sadhukhan@Sun.COM }
787*10673SKrishnendu.Sadhukhan@Sun.COM
788*10673SKrishnendu.Sadhukhan@Sun.COM cause = (lt_cause_t *)g_ptr_array_index(causes_array, cause_id);
789*10673SKrishnendu.Sadhukhan@Sun.COM
790*10673SKrishnendu.Sadhukhan@Sun.COM if (cause == NULL) {
791*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
792*10673SKrishnendu.Sadhukhan@Sun.COM } else {
793*10673SKrishnendu.Sadhukhan@Sun.COM return (cause->lt_c_flags & flag);
794*10673SKrishnendu.Sadhukhan@Sun.COM }
795*10673SKrishnendu.Sadhukhan@Sun.COM }
796*10673SKrishnendu.Sadhukhan@Sun.COM
797*10673SKrishnendu.Sadhukhan@Sun.COM /*
798*10673SKrishnendu.Sadhukhan@Sun.COM * Append macros to D script, if any.
799*10673SKrishnendu.Sadhukhan@Sun.COM */
800*10673SKrishnendu.Sadhukhan@Sun.COM int
lt_table_append_trans(FILE * fp)801*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_append_trans(FILE *fp)
802*10673SKrishnendu.Sadhukhan@Sun.COM {
803*10673SKrishnendu.Sadhukhan@Sun.COM if (dtrans != NULL) {
804*10673SKrishnendu.Sadhukhan@Sun.COM if (fwrite(dtrans, strlen(dtrans), 1, fp) != 1) {
805*10673SKrishnendu.Sadhukhan@Sun.COM return (-1);
806*10673SKrishnendu.Sadhukhan@Sun.COM }
807*10673SKrishnendu.Sadhukhan@Sun.COM }
808*10673SKrishnendu.Sadhukhan@Sun.COM
809*10673SKrishnendu.Sadhukhan@Sun.COM return (0);
810*10673SKrishnendu.Sadhukhan@Sun.COM }
811*10673SKrishnendu.Sadhukhan@Sun.COM
812*10673SKrishnendu.Sadhukhan@Sun.COM /*
813*10673SKrishnendu.Sadhukhan@Sun.COM * Clean up function.
814*10673SKrishnendu.Sadhukhan@Sun.COM * Free the resources used for symbol table (symbols, causes etc.).
815*10673SKrishnendu.Sadhukhan@Sun.COM */
816*10673SKrishnendu.Sadhukhan@Sun.COM void
lt_table_deinit(void)817*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_deinit(void)
818*10673SKrishnendu.Sadhukhan@Sun.COM {
819*10673SKrishnendu.Sadhukhan@Sun.COM if (symbol_lookup_table != NULL) {
820*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_destroy(symbol_lookup_table);
821*10673SKrishnendu.Sadhukhan@Sun.COM symbol_lookup_table = NULL;
822*10673SKrishnendu.Sadhukhan@Sun.COM }
823*10673SKrishnendu.Sadhukhan@Sun.COM
824*10673SKrishnendu.Sadhukhan@Sun.COM if (cause_lookup != NULL) {
825*10673SKrishnendu.Sadhukhan@Sun.COM g_hash_table_destroy(cause_lookup);
826*10673SKrishnendu.Sadhukhan@Sun.COM cause_lookup = NULL;
827*10673SKrishnendu.Sadhukhan@Sun.COM }
828*10673SKrishnendu.Sadhukhan@Sun.COM
829*10673SKrishnendu.Sadhukhan@Sun.COM if (causes_array != NULL) {
830*10673SKrishnendu.Sadhukhan@Sun.COM g_ptr_array_foreach(causes_array, (GFunc)free_cause, NULL);
831*10673SKrishnendu.Sadhukhan@Sun.COM g_ptr_array_free(causes_array, TRUE);
832*10673SKrishnendu.Sadhukhan@Sun.COM causes_array = NULL;
833*10673SKrishnendu.Sadhukhan@Sun.COM causes_array_len = 0;
834*10673SKrishnendu.Sadhukhan@Sun.COM }
835*10673SKrishnendu.Sadhukhan@Sun.COM
836*10673SKrishnendu.Sadhukhan@Sun.COM if (dtrans != NULL) {
837*10673SKrishnendu.Sadhukhan@Sun.COM g_free(dtrans);
838*10673SKrishnendu.Sadhukhan@Sun.COM dtrans = NULL;
839*10673SKrishnendu.Sadhukhan@Sun.COM }
840*10673SKrishnendu.Sadhukhan@Sun.COM }
841