]> git.cworth.org Git - apitrace/blob - trace_local_writer.cpp
Merge branch 'master' into compression
[apitrace] / trace_local_writer.cpp
1 /**************************************************************************
2  *
3  * Copyright 2007-2011 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "os.hpp"
34 #include "trace_file.hpp"
35 #include "trace_writer.hpp"
36 #include "trace_format.hpp"
37
38
39 namespace Trace {
40
41
42 static void exceptionCallback(void)
43 {
44     OS::DebugMessage("apitrace: flushing trace due to an exception\n");
45     localWriter.flush();
46 }
47
48
49 LocalWriter::LocalWriter() :
50     acquired(0)
51 {}
52
53 LocalWriter::~LocalWriter()
54 {
55     OS::ResetExceptionCallback();
56 }
57
58 void
59 LocalWriter::open(void) {
60
61     static unsigned dwCounter = 0;
62
63     const char *szExtension = "trace";
64     char szFileName[PATH_MAX];
65     const char *lpFileName;
66
67     lpFileName = getenv("TRACE_FILE");
68     if (lpFileName) {
69         strncpy(szFileName, lpFileName, PATH_MAX);
70     }
71     else {
72         char szProcessName[PATH_MAX];
73         char szCurrentDir[PATH_MAX];
74         OS::GetProcessName(szProcessName, PATH_MAX);
75         OS::GetCurrentDir(szCurrentDir, PATH_MAX);
76
77         for (;;) {
78             FILE *file;
79
80             if (dwCounter)
81                 snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
82             else
83                 snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
84
85             file = fopen(szFileName, "rb");
86             if (file == NULL)
87                 break;
88
89             fclose(file);
90
91             ++dwCounter;
92         }
93     }
94
95     OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
96
97     Writer::open(szFileName);
98
99     OS::SetExceptionCallback(exceptionCallback);
100
101 #if 0
102     // For debugging the exception handler
103     *((int *)0) = 0;
104 #endif
105 }
106
107 unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
108     OS::AcquireMutex();
109     ++acquired;
110
111     if (!m_file->isOpened()) {
112         open();
113     }
114
115     return Writer::beginEnter(sig);
116 }
117
118 void LocalWriter::endEnter(void) {
119     Writer::endEnter();
120     --acquired;
121     OS::ReleaseMutex();
122 }
123
124 void LocalWriter::beginLeave(unsigned call) {
125     OS::AcquireMutex();
126     ++acquired;
127     Writer::beginLeave(call);
128 }
129
130 void LocalWriter::endLeave(void) {
131     Writer::endLeave();
132     --acquired;
133     OS::ReleaseMutex();
134 }
135
136 void LocalWriter::flush(void) {
137     /*
138      * Do nothing if the mutex is already acquired (e.g., if a segfault happen
139      * while writing the file) to prevent dead-lock.
140      */
141
142     if (!acquired) {
143         OS::AcquireMutex();
144         if (m_file->isOpened()) {
145             m_file->flush();
146         }
147         OS::ReleaseMutex();
148     }
149 }
150
151
152 LocalWriter localWriter;
153
154
155 } /* namespace Trace */
156