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 */
31void __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
58void __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 */
98PERF_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 */
165void __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