1 
2 /*
3  * Copyright (C) Texas Instruments - http://www.ti.com/
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 #include "perf.h"
22 #include "perf_config.h"
23 
24 #define PERF_MAX_LOG_LENGTH (sizeof(unsigned long) * 8)
25 
26 /* ============================================================================
27    PERF LOG Methods
28 ============================================================================ */
29 
30 /* Effects: flush log */
__PERF_LOG_flush(PERF_LOG_Private * me)31 void __PERF_LOG_flush(PERF_LOG_Private *me)
32 {
33     /* only flush if we collected data */
34     if (me->puPtr > me->puBuffer)
35     {
36 		/* open file if we have not yet opened it */
37 		if (!me->fOut) me->fOut = fopen(me->fOutFile, "wb");
38 
39 		if (me->fOut)
40 		{
41 			fwrite(me->puBuffer, me->puPtr - me->puBuffer, sizeof(*me->puPtr),
42 				   me->fOut);
43 			me->uBufferCount++;
44 		}
45 
46 		/* reset pointer to start of buffer */
47 		me->puPtr = me->puBuffer;
48     }
49 }
50 
51 /** The Done method is called at the end of the UC test or UI
52 *   application.
53 *   @param phObject
54 *       Pointer to a handle to the PERF object, which will be
55 *       deleted and set to NULL upon completion.
56 *  */
57 
__PERF_LOG_done(PERF_Private * perf)58 void __PERF_LOG_done(PERF_Private *perf)
59 {
60     PERF_LOG_Private *me = perf->pLog;
61 
62     if (me)
63     {
64         /* if we could allocate a buffer, we can log the completion */
65         if (me->puBuffer && me->fOutFile)
66         {
67             __PERF_log1(perf, PERF_LOG_Done);
68 
69             __PERF_LOG_flush(me);   /* flush log */
70         }
71 
72         /* free buffer */
73         if (me->puBuffer) free(me->puBuffer);
74         me->puBuffer = NULL;
75 
76         /* free file name string */
77         if (me->fOutFile) free(me->fOutFile);
78         me->fOutFile = NULL;
79 
80         /* close file */
81         if (me->fOut) fclose(me->fOut);
82         me->fOut = NULL;
83 
84         fprintf(stderr,
85                 "PERF Instrumentation [%c%c%c%c %05ld-%08lx] produced"
86                 " %ld buffers\n",
87                 PERF_FOUR_CHARS(perf->ulID), perf->ulPID,
88                 (unsigned long) perf,
89                 me->uBufferCount);
90 
91         /* delete LOG private structure */
92         free(me);
93         perf->pLog = NULL;
94     }
95 }
96 
97 /* Effects: creates LOG private object and logs initial block of information */
__PERF_LOG_create(PERF_Private * perf,PERF_Config * config,PERF_MODULETYPE eModule)98 PERF_LOG_Private *__PERF_LOG_create(PERF_Private *perf,
99                                     PERF_Config *config,
100                                     PERF_MODULETYPE eModule)
101 {
102     PERF_LOG_Private *me =
103         perf->pLog = (PERF_LOG_Private *) malloc (sizeof (PERF_LOG_Private));
104 
105     if (me)
106     {
107         me->fOut = NULL;
108         me->uBufferCount = 0;
109         me->uBufSize = config->buffer_size;
110 
111         /* limit buffer size to allow at least one log creation */
112         if (me->uBufSize < PERF_MAX_LOG_LENGTH)
113         {
114             me->uBufSize = PERF_MAX_LOG_LENGTH;
115         }
116 
117         me->puBuffer =
118         (unsigned long *) malloc (sizeof (unsigned long) * me->uBufSize);
119         me->fOutFile = (char *) malloc (strlen(config->trace_file) + 34);
120         if (me->puBuffer && me->fOutFile)
121         {
122             perf->uMode |= PERF_Mode_Log; /* we are logging */
123 
124             me->puPtr = me->puBuffer;   /* start at beginning of buffer */
125             me->puEnd = me->puBuffer + me->uBufSize - PERF_MAX_LOG_LENGTH;
126 
127             sprintf(me->fOutFile, "%s-%05lu-%08lx-%c%c%c%c.trace",
128                     config->trace_file, perf->ulPID, (unsigned long) perf,
129                     PERF_FOUR_CHARS(perf->ulID));
130 
131             /* for delayed open we don't try to open the file until we need to
132                save a buffer into it */
133             if (!config->delayed_open)
134             {
135                 me->fOut = fopen(me->fOutFile, "ab");
136             }
137             else
138             {
139                 me->fOut = NULL;
140             }
141             /* save initial data to the log */
142 
143             *me->puPtr++ = (unsigned long) eModule; /* module ID */
144             *me->puPtr++ = perf->ulID;  /* ID */
145             *me->puPtr++ = perf->ulPID; /* process ID */
146 
147             /* original tempTime stamp */
148             *me->puPtr++ = TIME_SECONDS(perf->time);
149             *me->puPtr++ = TIME_MICROSECONDS(perf->time);
150         }
151 
152 		/* if some allocation or opening failed, delete object */
153 		if (!me->puBuffer || !me->fOutFile || (!config->delayed_open && !me->fOut))
154         {
155 			perf->uMode &= ~PERF_Mode_Log; /* delete logging flag */
156             __PERF_LOG_done(perf);
157         }
158     }
159 
160     /* it may have been deleted already, so we read it again */
161     return(perf->pLog);
162 }
163 
164 /* Effects: appends tempTime stamp to log */
__PERF_LOG_log_common(PERF_Private * perf,unsigned long * time_loc)165 void __PERF_LOG_log_common(PERF_Private *perf, unsigned long *time_loc)
166 {
167     unsigned long delta = 0;
168     PERF_LOG_Private *me = perf->pLog; /* get LOG private object */
169 
170     /* get tempTime of from last tempTime stamp */
171     TIME_GET(perf->tempTime);
172     delta = TIME_DELTA(perf->tempTime, perf->time);
173 
174     *time_loc = delta;   /* save time stamp */
175 
176     /* save tempTime stamp as last tempTime stamp */
177     TIME_COPY(perf->time, perf->tempTime);
178 
179     /* flush if we reached end of the buffer */
180     if (me->puPtr > me->puEnd) __PERF_LOG_flush(me);
181 }
182 
183