4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
31 #include <sys/types.h>
32 #include <sys/regset.h>
33 #include <sys/frame.h>
34 #include <sys/procfs.h>
44 const char *d_symname
;
53 static Elist
*bindto_list
= NULL
;
54 static Elist
*bindfrom_list
= NULL
;
56 static int initialized
;
57 extern long long gethrvtime();
59 static const char *progname
;
60 static long long starts
[1000];
61 static long long accounted
[1000]; /* time accounted for */
62 static int counter
= 0;
64 static float total_time
= 0.0;
65 static List
*list_head
= NULL
;
72 list_insert(d_entry
*dep
)
78 if ((new_list
= malloc(sizeof (List
))) == NULL
) {
79 (void) printf("libperfcnt.so: malloc failed - "
80 "can't print summary\n");
83 new_list
->l_dep
= dep
;
85 if (list_head
== NULL
) {
87 new_list
->l_next
= NULL
;
90 for (cur
= list_head
, prev
= NULL
;
91 (cur
&& (cur
->l_dep
->d_time
< dep
->d_time
));
92 prev
= cur
, cur
= cur
->l_next
)
95 * insert at head of list
98 new_list
->l_next
= list_head
;
102 prev
->l_next
= new_list
;
103 new_list
->l_next
= cur
;
107 la_version(uint_t version
)
112 if (version
> LAV_CURRENT
)
113 (void) fprintf(stderr
, "perfcnt.so.1: unexpected version: %d\n",
116 (void) sprintf(buffer
, "/proc/%d", (int)getpid());
117 if ((fd
= open(buffer
, O_RDWR
)) >= 0) {
118 long state
= PR_MSACCT
;
119 if (ioctl(fd
, PIOCSET
, &state
) == -1)
125 tbl
= make_hash(213);
127 build_env_list(&bindto_list
, (const char *)"PERFCNT_BINDTO");
128 build_env_list(&bindto_list
, (const char *)"PERFCNT_BINDFROM");
131 * Initalize iset to the full set of signals to be masked durring
134 (void) sigfillset(&iset
);
136 return (LAV_CURRENT
);
142 la_objopen(Link_map
*lmp
, Lmid_t lmid
, uintptr_t *cookie
)
144 static int first
= 1;
148 progname
= lmp
->l_name
;
152 if (bindto_list
== NULL
)
153 flags
= LA_FLG_BINDTO
;
155 if (check_list(bindto_list
, lmp
->l_name
))
156 flags
= LA_FLG_BINDTO
;
158 if (bindfrom_list
== NULL
)
159 flags
|= LA_FLG_BINDFROM
;
161 if (check_list(bindfrom_list
, lmp
->l_name
))
162 flags
|= LA_FLG_BINDFROM
;
169 #if defined(__sparcv9)
171 la_sparcv9_pltenter(Elf64_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
172 uintptr_t *defcookie
, La_sparcv9_regs
*regset
, uint_t
*sb_flags
,
173 const char *sym_name
)
174 #elif defined(__sparc)
176 la_sparcv8_pltenter(Elf32_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
177 uintptr_t *defcookie
, La_sparcv8_regs
*regset
, uint_t
*sb_flags
)
178 #elif defined(__amd64)
180 la_amd64_pltenter(Elf64_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
181 uintptr_t *defcookie
, La_amd64_regs
*regset
, uint_t
*sb_flags
,
182 const char *sym_name
)
183 #elif defined(__i386)
185 la_i86_pltenter(Elf32_Sym
*symp
, uint_t symndx
, uintptr_t *refcooke
,
186 uintptr_t *defcook
, La_i86_regs
*regset
, uint_t
*sb_flags
)
189 accounted
[counter
] = 0;
190 starts
[counter
] = gethrvtime();
192 return (symp
->st_value
);
201 la_pltexit64(Elf64_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
202 uintptr_t *defcookie
, uintptr_t retval
, const char *sym_name
)
205 la_pltexit(Elf32_Sym
*symp
, uint_t symndx
, uintptr_t *refcookie
,
206 uintptr_t *defcookie
, uintptr_t retval
)
213 const char *sym_name
= (const char *)symp
->st_name
;
216 (void) sigprocmask(SIG_BLOCK
, &iset
, &oset
);
219 time_used
= gethrvtime() - starts
[counter
];
221 dep
= (d_entry
**)get_hash(tbl
, (char *)sym_name
);
223 char *ptr
= malloc(sizeof (d_entry
));
225 (*dep
) = (d_entry
*)ptr
;
227 (*dep
)->d_time
= 0.0;
228 (*dep
)->d_symname
= sym_name
;
232 accounted
[counter
- 1] += time_used
;
235 (*dep
)->d_time
+= (double)((time_used
- accounted
[counter
]) / 1.0e9
);
237 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
244 scanlist(d_entry
*dep
, void *food
, char *name
)
246 total_time
+= dep
->d_time
;
250 #pragma fini(cleanup)
255 (void) operate_hash(tbl
, scanlist
, NULL
);
256 (void) printf("\n\nPerf Counts for: %s\n\n", progname
);
257 (void) printf("%20s\tc_count\t tim\t\tavg. tim\ttot. %%\n",
259 (void) printf("--------------------------------------------------"
260 "-------------------\n");
261 for (cur
= list_head
; cur
; cur
= cur
->l_next
) {
262 d_entry
*dep
= cur
->l_dep
;
263 float tim
= dep
->d_time
* 1000000;
265 (void) printf("%20s\t%d\t%8.2f\t%8.2f\t%2.2f%%\n",
266 dep
->d_symname
, dep
->d_count
, tim
, tim
/ dep
->d_count
,
267 ((dep
->d_time
/ total_time
) * 100.0));
269 (void) printf("--------------------------------------------------"
270 "-------------------\n");
271 (void) printf("\t\t\t\t\t\tTotal Time: %8.2f\n",
272 total_time
* 1000000);