1 /*
2 Copyright (c) 2009-2012, Intel Corporation
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 */
13 //
14 // asynchonous CPU conters
15 //
16 // contact: Thomas Willhalm
17
18 #ifndef CPUASYNCHCOUNTER_HEADER
19 #define CPUASYNCHCOUNTER_HEADER
20
21
22 /*! \file cpuasynchcounter.h
23 \brief Implementation of a POSIX thread that periodically saves the current state of counters and exposes them to other threads
24 */
25
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include "cpucounters.h"
29
30 #define DELAY 1 // in seconds
31
32 using namespace pcm;
33
34 void * UpdateCounters(void *);
35
36 class AsynchronCounterState {
37 PCM * m;
38
39 CoreCounterState * cstates1, * cstates2;
40 SocketCounterState * skstates1, * skstates2;
41 SystemCounterState sstate1, sstate2;
42
43 pthread_t UpdateThread;
44 pthread_mutex_t CounterMutex;
45
46 friend void * UpdateCounters(void *);
47
48 AsynchronCounterState(const AsynchronCounterState &) = delete;
49 const AsynchronCounterState & operator = (const AsynchronCounterState &) = delete;
50
51 public:
AsynchronCounterState()52 AsynchronCounterState()
53 {
54 m = PCM::getInstance();
55 PCM::ErrorCode status = m->program();
56 if (status != PCM::Success)
57 {
58 std::cerr << "\nCannot access CPU counters. Try to run pcm.x 1 to check the PMU access status.\n\n";
59 exit(-1);
60 }
61
62 cstates1 = new CoreCounterState[m->getNumCores()];
63 cstates2 = new CoreCounterState[m->getNumCores()];
64 skstates1 = new SocketCounterState[m->getNumSockets()];
65 skstates2 = new SocketCounterState[m->getNumSockets()];
66
67 for (uint32 i = 0; i < m->getNumCores(); ++i) {
68 cstates1[i] = getCoreCounterState(i);
69 cstates2[i] = getCoreCounterState(i);
70 }
71
72 for (uint32 i = 0; i < m->getNumSockets(); ++i) {
73 skstates1[i] = getSocketCounterState(i);
74 skstates2[i] = getSocketCounterState(i);
75 }
76
77 pthread_mutex_init(&CounterMutex, NULL);
78 pthread_create(&UpdateThread, NULL, UpdateCounters, this);
79 }
~AsynchronCounterState()80 ~AsynchronCounterState()
81 {
82 pthread_cancel(UpdateThread);
83 pthread_mutex_destroy(&CounterMutex);
84 m->cleanup();
85 delete[] cstates1;
86 delete[] cstates2;
87 delete[] skstates1;
88 delete[] skstates2;
89 }
90
getNumCores()91 uint32 getNumCores()
92 { return m->getNumCores(); }
93
getNumSockets()94 uint32 getNumSockets()
95 { return m->getNumSockets(); }
96
getQPILinksPerSocket()97 uint32 getQPILinksPerSocket()
98 {
99 return m->getQPILinksPerSocket();
100 }
101
getSocketId(uint32 c)102 uint32 getSocketId(uint32 c)
103 {
104 return m->getSocketId(c);
105 }
106
107 template <typename T, T func(CoreCounterState const &)>
get(uint32 core)108 T get(uint32 core)
109 {
110 pthread_mutex_lock(&CounterMutex);
111 T value = func(cstates2[core]);
112 pthread_mutex_unlock(&CounterMutex);
113 return value;
114 }
115 template <typename T, T func(CoreCounterState const &, CoreCounterState const &)>
get(uint32 core)116 T get(uint32 core)
117 {
118 pthread_mutex_lock(&CounterMutex);
119 T value = func(cstates1[core], cstates2[core]);
120 pthread_mutex_unlock(&CounterMutex);
121 return value;
122 }
123
124 template <typename T, T func(int, CoreCounterState const &, CoreCounterState const &)>
get(int param,uint32 core)125 T get(int param, uint32 core)
126 {
127 pthread_mutex_lock(&CounterMutex);
128 T value = func(param, cstates1[core], cstates2[core]);
129 pthread_mutex_unlock(&CounterMutex);
130 return value;
131 }
132
133 template <typename T, T func(SocketCounterState const &)>
getSocket(uint32 socket)134 T getSocket(uint32 socket)
135 {
136 pthread_mutex_lock(&CounterMutex);
137 T value = func(skstates2[socket]);
138 pthread_mutex_unlock(&CounterMutex);
139 return value;
140 }
141
142 template <typename T, T func(SocketCounterState const &, SocketCounterState const &)>
getSocket(uint32 socket)143 T getSocket(uint32 socket)
144 {
145 pthread_mutex_lock(&CounterMutex);
146 T value = func(skstates1[socket], skstates2[socket]);
147 pthread_mutex_unlock(&CounterMutex);
148 return value;
149 }
150
151 template <typename T, T func(int, SocketCounterState const &, SocketCounterState const &)>
getSocket(int param,uint32 socket)152 T getSocket(int param, uint32 socket)
153 {
154 pthread_mutex_lock(&CounterMutex);
155 T value = func(param, skstates1[socket], skstates2[socket]);
156 pthread_mutex_unlock(&CounterMutex);
157 return value;
158 }
159
160 template <typename T, T func(uint32, uint32, SystemCounterState const &, SystemCounterState const &)>
getSocket(uint32 socket,uint32 param)161 T getSocket(uint32 socket, uint32 param)
162 {
163 pthread_mutex_lock(&CounterMutex);
164 T value = func(socket, param, sstate1, sstate2);
165 pthread_mutex_unlock(&CounterMutex);
166 return value;
167 }
168
169 template <typename T, T func(SystemCounterState const &, SystemCounterState const &)>
getSystem()170 T getSystem()
171 {
172 pthread_mutex_lock(&CounterMutex);
173 T value = func(sstate1, sstate2);
174 pthread_mutex_unlock(&CounterMutex);
175 return value;
176 }
177
178 template <typename T, T func(int, SystemCounterState const &, SystemCounterState const &)>
getSystem(int param)179 T getSystem(int param)
180 {
181 pthread_mutex_lock(&CounterMutex);
182 T value = func(param, sstate1, sstate2);
183 pthread_mutex_unlock(&CounterMutex);
184 return value;
185 }
186 };
187
UpdateCounters(void * state)188 void * UpdateCounters(void * state)
189 {
190 AsynchronCounterState * s = (AsynchronCounterState *)state;
191
192 while (true) {
193 pthread_mutex_lock(&(s->CounterMutex));
194 for (uint32 core = 0; core < s->m->getNumCores(); ++core) {
195 s->cstates1[core] = std::move(s->cstates2[core]);
196 s->cstates2[core] = s->m->getCoreCounterState(core);
197 }
198
199 for (uint32 socket = 0; socket < s->m->getNumSockets(); ++socket) {
200 s->skstates1[socket] = std::move(s->skstates2[socket]);
201 s->skstates2[socket] = s->m->getSocketCounterState(socket);
202 }
203
204 s->sstate1 = std::move(s->sstate2);
205 s->sstate2 = s->m->getSystemCounterState();
206
207 pthread_mutex_unlock(&(s->CounterMutex));
208 sleep(1);
209 }
210 return NULL;
211 }
212
213 #endif
214