1 #ifndef _CPU_USAGE_MAC_H_
2 #define _CPU_USAGE_MAC_H_
3 
4 #include <sys/resource.h>
5 
6 #include <mach/mach.h>
7 #include <mach/processor_info.h>
8 #include <mach/mach_host.h>
9 
10 
11 class ESCpuUsage
12 {
13 	Base::CTimer	m_Timer;
14 	fp8				m_LastCPUCheckTime;
15 
16 	fp8  m_LastESTime;
17 
18 	processor_info_array_t m_lastProcessorInfo;
19 	mach_msg_type_number_t m_lastNumProcessorInfo;
20 
21 
22 public:
ESCpuUsage()23 	ESCpuUsage(): m_LastCPUCheckTime(0)
24 	{
25 		m_Timer.Reset();
26 		m_LastCPUCheckTime = m_Timer.Time();
27 
28 		struct rusage r_usage;
29 		if (!getrusage(RUSAGE_SELF, &r_usage)) {
30 
31 				m_LastESTime = (fp8)r_usage.ru_utime.tv_sec + (fp8)r_usage.ru_utime.tv_usec * 1e-6;
32 
33 				m_LastESTime += (fp8)r_usage.ru_stime.tv_sec + (fp8)r_usage.ru_stime.tv_usec * 1e-6;
34 
35 		}
36 
37 		processor_info_array_t processorInfo;
38 		mach_msg_type_number_t numProcessorInfo;
39 		natural_t numProcessors = 0U;
40 
41 		kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numProcessors, &processorInfo, &numProcessorInfo);
42 		if(err == KERN_SUCCESS)
43 		{
44 			m_lastProcessorInfo = processorInfo;
45 			m_lastNumProcessorInfo = numProcessorInfo;
46 		}
47 		else
48 		{
49 			m_lastProcessorInfo = NULL;
50 			m_lastNumProcessorInfo = 0;
51 		}
52 
53 	}
54 
~ESCpuUsage()55 	virtual ~ESCpuUsage()
56 	{
57 		if(m_lastProcessorInfo)
58 		{
59 			size_t lastProcessorInfoSize = sizeof(integer_t) * m_lastNumProcessorInfo;
60 			vm_deallocate(mach_task_self(), (vm_address_t)m_lastProcessorInfo, lastProcessorInfoSize);
61 		}
62 	}
63 
GetCpuUsage(int & _total,int & _es)64 	bool GetCpuUsage(int &_total, int &_es)
65 	{
66 		struct rusage r_usage;
67 
68 		fp8 newtime = m_Timer.Time();
69 
70 		fp8 period =  newtime - m_LastCPUCheckTime;
71 		if (period > 0.)
72 		{
73 			if (!getrusage(RUSAGE_SELF, &r_usage))
74 			{
75 
76 				fp8 utime = (fp8)r_usage.ru_utime.tv_sec + (fp8)r_usage.ru_utime.tv_usec * 1e-6;
77 
78 				utime += (fp8)r_usage.ru_stime.tv_sec + (fp8)r_usage.ru_stime.tv_usec * 1e-6;
79 
80 				_es = int ( ( utime - m_LastESTime ) * 100. / period );
81 
82 				m_LastESTime = utime;
83 			}
84 
85 			processor_info_array_t processorInfo;
86 			mach_msg_type_number_t numProcessorInfo;
87 			natural_t numProcessors = 0U;
88 
89 			kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numProcessors, &processorInfo, &numProcessorInfo);
90 			if(err == KERN_SUCCESS)
91 			{
92 				float accInUse = 0.0f, accTotal = 0.0f;
93 
94 				for(unsigned i = 0U; i < numProcessors; ++i)
95 				{
96 					float inUse, total;
97 
98 					if(m_lastProcessorInfo)
99 					{
100 						inUse = (
101 						  (processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER]   - m_lastProcessorInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER])
102 						+ (processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] - m_lastProcessorInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM])
103 						+ (processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE]   - m_lastProcessorInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE])
104 						);
105 
106 						total = inUse + (processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE] - m_lastProcessorInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]);
107 					} else {
108 						inUse = processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] + processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] + processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE];
109 						total = inUse + processorInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE];
110 					}
111 
112 					accInUse += inUse;
113 					accTotal += total;
114 				}
115 
116 				_total = static_cast<int>((fp8)accInUse * 100. / (fp8)accTotal);
117 
118 				_es /= numProcessors;
119 
120 				if(m_lastProcessorInfo)
121 				{
122 					size_t lastProcessorInfoSize = sizeof(integer_t) * m_lastNumProcessorInfo;
123 					vm_deallocate(mach_task_self(), (vm_address_t)m_lastProcessorInfo, lastProcessorInfoSize);
124 				}
125 
126 				m_lastProcessorInfo = processorInfo;
127 				m_lastNumProcessorInfo = numProcessorInfo;
128 			}
129 		}
130 		else
131 		{
132 			_es = 0;
133 			_total = 0;
134 		}
135 
136 		_es = ::Base::Math::Clamped(_es, 0, 100);
137 		_total = ::Base::Math::Clamped(_total, 0, 100);
138 
139 		m_LastCPUCheckTime = newtime;
140 
141 		return true;
142 	}
143 
144 };
145 
146 #endif
147