- Fixed a missing include on some machines
[dyninst.git] / rtinst / src / RTlinux.c
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /************************************************************************
43  * RTlinux.c: clock access functions for linux-2.0.x
44 ************************************************************************/
45
46 #include <signal.h>
47 //#include <sys/ucontext.h>
48 #include <sys/times.h>
49 #include <sys/resource.h>
50 #include <assert.h>
51 #include <sys/syscall.h>
52 #include <asm/unistd.h>
53
54 #include <sys/procfs.h> /* /proc PIOCUSAGE */
55 #include <stdio.h>
56 #include <fcntl.h> /* O_RDONLY */
57 #include <sigcontext.h>
58 #include <unistd.h> /* getpid() */
59 #include <sys/ptrace.h>
60
61 #include "rtinst/h/rtinst.h"
62
63 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
64 #include <thread.h>
65 #endif
66
67 /*extern int    gettimeofday(struct timeval *, struct timezone *);*/
68 extern void perror(const char *);
69
70 \f
71
72
73 /************************************************************************
74  * symbolic constants.
75 ************************************************************************/
76
77 static const double NANO_PER_USEC = 1.0e3;
78 static const double MILLION       = 1.0e6;
79
80
81 \f
82
83 static int procfd = -1;
84
85 void DYNINSTgetCPUtimeInitialize(void) {
86   /* This stuff is done just once */
87   /*char str[20];
88
89     sprintf(str, "/proc/%d", (int)getpid()); */
90    /* have to use syscall here for applications that have their own
91       versions of open, poll...In these cases there is no guarentee that
92       things have been initialized so that the application's version of
93       open can be used when this open call occurs (in DYNINSTinit)
94    */
95   /*procfd = _syscall2(SYS_open,str, O_RDONLY);
96     if (procfd < 0) {
97       fprintf(stderr, "open of /proc failed in DYNINSTgetCPUtimeInitialize\n");
98       perror("open");
99       abort();
100     } */
101 }
102
103
104 /************************************************************************
105  * void DYNINSTos_init(void)
106  *
107  * os initialization function
108 ************************************************************************/
109
110 void
111 DYNINSTos_init(int calledByFork, int calledByAttach) {
112   /*
113     Install trap handler.
114     This is currently being used only on the x86 platform.
115     Of course, under Linux, this currently means always - DAN
116   */
117
118   void DYNINSTtrapHandler(int sig, struct sigcontext uap );
119   struct sigaction act;
120
121   act.sa_handler = (void(*)(int))DYNINSTtrapHandler;
122   act.sa_flags = 0;
123   sigfillset(&act.sa_mask);
124   if (sigaction(SIGTRAP, &act, 0) != 0) {
125     perror("sigaction(SIGTRAP)");
126     assert(0);
127     abort();
128   }
129
130   ptrace( PTRACE_TRACEME, 0, 0, 0 );
131
132   /* It is necessary to call DYNINSTgetCPUtimeInitialize here to make sure
133      that it is called again for a child process during a fork - naim */
134   //DYNINSTgetCPUtimeInitialize();
135 }
136
137
138 \f
139
140
141 /************************************************************************
142  * time64 DYNINSTgetCPUtime(void)
143  *
144  * get the total CPU time used for "an" LWP of the monitored process.
145  * this functions needs to be rewritten if a per-thread CPU time is
146  * required.  time for a specific LWP can be obtained via the "/proc"
147  * filesystem.
148  * return value is in usec units.
149  *
150  * XXXX - This should really return time in native units and use normalize.
151  *      conversion to float and division are way too expensive to
152  *      do everytime we want to read a clock (slows this down 2x) -
153  *      jkh 3/9/95
154 ************************************************************************/
155
156
157 static unsigned long long div1000(unsigned long long in) {
158    /* Divides by 1000 without an integer division instruction or library call, both of
159     * which are slow.
160     * We do only shifts, adds, and subtracts.
161     *
162     * We divide by 1000 in this way:
163     * multiply by 1/1000, or multiply by (1/1000)*2^30 and then right-shift by 30.
164     * So what is 1/1000 * 2^30?
165     * It is 1,073,742.   (actually this is rounded)
166     * So we can multiply by 1,073,742 and then right-shift by 30 (neat, eh?)
167     *
168     * Now for multiplying by 1,073,742...
169     * 1,073,742 = (1,048,576 + 16384 + 8192 + 512 + 64 + 8 + 4 + 2)
170     * or, slightly optimized:
171     * = (1,048,576 + 16384 + 8192 + 512 + 64 + 16 - 2)
172     * for a total of 8 shifts and 6 add/subs, or 14 operations.
173     *
174     */
175
176    unsigned long long temp = in << 20; /* multiply by 1,048,576 */
177    /* beware of overflow; left shift by 20 is quite a lot.
178       If you know that the input fits in 32 bits (4 billion) then
179       no problem.  But if it's much bigger then start worrying...
180    */
181
182    temp += in << 14; /* 16384 */
183    temp += in << 13; /* 8192  */
184    temp += in << 9;  /* 512   */
185    temp += in << 6;  /* 64    */
186    temp += in << 4;  /* 16    */
187    temp -= in >> 2;  /* 2     */
188
189    return (temp >> 30); /* divide by 2^30 */
190 }
191
192 static unsigned long long divMillion(unsigned long long in) {
193    /* Divides by 1,000,000 without an integer division instruction or library call,
194     * both of which are slow.
195     * We do only shifts, adds, and subtracts.
196     *
197     * We divide by 1,000,000 in this way:
198     * multiply by 1/1,000,000, or multiply by (1/1,000,000)*2^30 and then right-shift
199     * by 30.  So what is 1/1,000,000 * 2^30?
200     * It is 1,074.   (actually this is rounded)
201     * So we can multiply by 1,074 and then right-shift by 30 (neat, eh?)
202     *
203     * Now for multiplying by 1,074
204     * 1,074 = (1024 + 32 + 16 + 2)
205     * for a total of 4 shifts and 4 add/subs, or 8 operations.
206     *
207     * Note: compare with div1000 -- it's cheaper to divide by a million than
208     *       by a thousand (!)
209     *
210     */
211
212    unsigned long long temp = in << 10; /* multiply by 1024 */
213    /* beware of overflow...if the input arg uses more than 52 bits
214       than start worrying about whether (in << 10) plus the smaller additions
215       we're gonna do next will fit in 64...
216    */
217
218    temp += in << 5; /* 32 */
219    temp += in << 4; /* 16 */
220    temp += in << 1; /* 2  */
221
222    return (temp >> 30); /* divide by 2^30 */
223 }
224
225 static unsigned long long mulMillion(unsigned long long in) {
226    unsigned long long result = in;
227
228    /* multiply by 125 by multiplying by 128 and subtracting 3x */
229    result = (result << 7) - result - result - result;
230
231    /* multiply by 125 again, for a total of 15625x */
232    result = (result << 7) - result - result - result;
233
234    /* multiply by 64, for a total of 1,000,000x */
235    result <<= 6;
236
237    /* cost was: 3 shifts and 6 subtracts
238     * cost of calling mul1000(mul1000()) would be: 6 shifts and 4 subtracts
239     *
240     * Another algorithm is to multiply by 2^6 and then 5^6.
241     * The former is super-cheap (one shift); the latter is more expensive.
242     * 5^6 = 15625 = 16384 - 512 - 256 + 8 + 1
243     * so multiplying by 5^6 means 4 shift operations and 4 add/sub ops
244     * so multiplying by 1000000 means 5 shift operations and 4 add/sub ops.
245     * That may or may not be cheaper than what we're doing (3 shifts; 6 subtracts);
246     * I'm not sure.  --ari
247     */
248
249    return result;
250 }
251
252 static unsigned long long mul10000(unsigned long long in) {
253    unsigned long long result = in;
254
255    /* multiply by 125 by multiplying by 128 and subtracting 3x */
256    result = (result << 7) - result - result - result;
257
258    /* multiply by 5 by multiplying by 4 and adding,
259       for a total of 625x */
260    result = (result << 2) + result;
261
262    /* multiply by 16, for a total of 10,000x */
263    result <<= 4;
264
265    /* cost was: 3 shifts and 4 add/subtracts
266     */
267
268    return result;
269 }
270
271 time64
272 DYNINSTgetCPUtime(void) {
273   static time64 previous=0;
274
275 /* gethrvtime()/1000 doesn't work right any more with shm sampling because it
276  * returns values that are out of sync with /proc's PIOCUSAGE, so when a fudge
277  * factor needs to be added by paradynd's shm sampling of an active timer,
278  * things don't work.  getrusage() does seem to work okay, but we'd like to not use
279  * getrusage() because it's obsolete in solaris and slower; so we use /proc PIOCUSAGE...
280  *
281  * This is too bad; we'd prefer the (presumably fast) gethrvtime().  But, again,
282  * it simply won't work with shm sampling.  If you are thinking of changing things
283  * back to gethrvtime(), please check with me first. --ari
284  *
285  * Some day........in an ideal world, we'll use the %TICK register......
286  */
287
288 /* Well, I guess we'll use times() in Linux for now.  Project for the future:
289  * write high-performance linux kernel timers which keep track of more exact
290  * process times.  Presumedly, something similar to gethrvtime (and gethrtime)
291  * in addition to something for the daemon to use on the inferior.
292  * I'll just base these kernel functions on the TICK register (or equivalent),
293  * and we'll have nearly an ideal world :) - DAN
294  */
295
296 /*     time64 now = (time64)gethrvtime()/(time64)1000; */
297   //assert( CLK_TCK == 100 );
298   struct tms ptime;
299   time64 now;
300   if( times( &ptime ) == -1 ) {
301     perror( "process::DYNINSTgetCPUtime" );
302     return 0;
303   }
304   now = mul10000( ptime.tms_stime + ptime.tms_utime );
305   
306   assert( now >= previous );
307   previous = now;
308   return now;
309 }
310 \f
311
312
313 /************************************************************************
314  * time64 DYNINSTgetWalltime(void)
315  *
316  * get the total walltime used by the monitored process.
317  * return value is in usec units.
318 ************************************************************************/
319
320 time64
321 DYNINSTgetWalltime(void) {
322   static time64 previous=0;
323   time64 now;
324
325   while (1) {
326     struct timeval tv;
327     if (gettimeofday(&tv,NULL) == -1) {
328         perror("gettimeofday");
329         assert(0);
330         abort();
331     }
332
333     now = mulMillion(tv.tv_sec) + tv.tv_usec;
334     /*    now = (time64)tv.tv_sec*(time64)1000000 + (time64)tv.tv_usec; */
335
336     if (now < previous) continue;
337     previous = now;
338     return(now);
339   }
340 }
341
342 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
343 extern unsigned DYNINST_hash_lookup(unsigned key);
344 extern unsigned DYNINST_initialize_done;
345 extern void DYNINST_initialize_hash(unsigned total);
346 extern void DYNINST_initialize_free(unsigned total);
347 extern unsigned DYNINST_hash_insert(unsigned k);
348
349 int DYNINSTthreadSelf(void) {
350   return(thr_self());
351 }
352
353 int DYNINSTthreadPos(void) {
354   if (initialize_done) {
355     return(DYNINST_hash_lookup(DYNINSTthreadSelf()));
356   } else {
357     DYNINST_initialize_free(MAX_NUMBER_OF_THREADS);
358     DYNINST_initialize_hash(MAX_NUMBER_OF_THREADS);
359     DYNINST_initialize_done=1;
360     return(DYNINST_hash_insert(DYNINSTthreadSelf()));
361   }
362 }
363 #endif
364
365
366 /****************************************************************************
367    The trap handler. Currently being used only on x86 platform.
368
369    Traps are used when we can't insert a jump at a point. The trap
370    handler looks up the address of the base tramp for the point that
371    uses the trap, and set the pc to this base tramp.
372    The paradynd is responsible for updating the tramp table when it
373    inserts instrumentation.
374 *****************************************************************************/
375
376 trampTableEntry DYNINSTtrampTable[TRAMPTABLESZ];
377 unsigned DYNINSTtotalTraps = 0;
378
379 static unsigned lookup(unsigned key) {
380     unsigned u;
381     unsigned k;
382     for (u = HASH1(key); 1; u = (u + HASH2(key)) % TRAMPTABLESZ) {
383       k = DYNINSTtrampTable[u].key;
384       if (k == 0)
385         return 0;
386       else if (k == key)
387         return DYNINSTtrampTable[u].val;
388     }
389     /* not reached */
390     assert(0);
391     abort();
392 }
393
394 void DYNINSTtrapHandler(int sig, struct sigcontext uap ) {
395     unsigned pc = uap.eip;
396     unsigned nextpc = lookup(pc);
397
398     if (!nextpc) {
399       /* kludge: maybe the PC was not automatically adjusted after the trap */
400       /* this happens for a forked process */
401       pc--;
402       nextpc = lookup(pc);
403     }
404
405     if (nextpc) {
406                 /* WARNING -- Remove before using in real use, it could KILL anything
407                    that instruments libc */
408                 /*fprintf( stderr, "DYNINST trap %#.8x -> %#.8x\n", pc, nextpc );*/
409       uap.eip = nextpc;
410     } else {
411       assert(0);
412       abort();
413     }
414     DYNINSTtotalTraps++;
415 }
416
417
418