5 // Created by Peter Hosey on 2006-06-21.
6 // Copyright 2006 Peter Hosey. All rights reserved.
8 // Modified by Christopher Bowns, starting 2007-1-1.
16 #include <sys/types.h>
19 //sysctl and its parameters
20 #include <sys/sysctl.h>
22 #include <sys/errno.h>
25 @implementation CPUInfo
29 inits cpudata, inptr, outptr
30 retrieves lastProcessorInfo for refresh method to go to town.
32 if cannot get processor info, returns nil.
34 - (CPUInfo *) initWithCapacity:(unsigned)numItems
40 //We could get the number of processors the same way that we get the CPU usage info, but that allocates memory.
41 /* enum { miblen = 2U };
42 int mib[miblen] = { CTL_HW, HW_NCPU };
43 size_t sizeOfNumCPUs = sizeof(numCPUs);
44 int status = sysctl(mib, miblen,
45 &numCPUs, &sizeOfNumCPUs,
46 */ /*newp*/ // NULL, /*newlen*/ 0U);
48 numCPUs = 1; // TODO we're going to assume one CPU for the moment.
49 // NSLog(@"%s error status, assuming one CPU", _cmd);
60 cpudata = calloc(numItems, sizeof(CPUData));
61 if (cpudata == NULL) {
62 NSLog (@"%s Failed to allocate buffer for CPUInfo", _cmd);
65 // Set up our data structure ptrs
69 // set the lastProcessorInfo array so we can get to work when we call refresh:
70 natural_t numProcessors_nobodyCares = 0U;
71 kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, (natural_t *)&numProcessors_nobodyCares, (processor_info_array_t *)&lastProcessorInfo, (mach_msg_type_number_t *)&numLastProcessorInfo);
72 if(err != KERN_SUCCESS) {
73 NSLog(@"%s failed to get cpu statistics", _cmd);
75 // if we can't get this info, then we're toast. Exit gracefully.
86 lastProcessorInfo and numLastProcessorInfo contain valid data from prior refresh of CPU info
88 retrieves current data
89 calculates avg cpu load over last period
90 updates cpudata array with info
91 deallocates old numLastProcInfo and lastProcessorInfo and set ptrs to new data
95 processor_info_array_t processorInfo;
96 natural_t numProcessors_nobodyCares = 0U;
97 mach_msg_type_number_t numProcessorInfo;
99 kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, (natural_t *)&numProcessors_nobodyCares, (processor_info_array_t *)&processorInfo, (mach_msg_type_number_t *)&numProcessorInfo);
100 if(err != KERN_SUCCESS) {
101 NSLog(@"%s failed to get cpu statistics", _cmd);
105 TODO make this multicore. First, we're gonna need a multicore machine to test it on.
107 // for(unsigned i = 0U; i < numCPUs; ++i)
109 unsigned int inUse, total, user, sys, nice, idle;
111 user = processorInfo[CPU_STATE_USER] - lastProcessorInfo[CPU_STATE_USER];
112 sys = processorInfo[CPU_STATE_SYSTEM] - lastProcessorInfo[CPU_STATE_SYSTEM];
113 nice = processorInfo[CPU_STATE_NICE] - lastProcessorInfo[CPU_STATE_NICE];
114 idle = processorInfo[CPU_STATE_IDLE] - lastProcessorInfo[CPU_STATE_IDLE];
116 inUse = user + sys + nice;
117 total = inUse + idle;
119 cpudata[inptr].user = (double)user / (double)total;
120 cpudata[inptr].sys = (double)sys / (double)total;
121 cpudata[inptr].nice = (double)nice / (double)total;
122 cpudata[inptr].idle = (double)idle / (double)total;
125 // deallocate the last one, since we don't want memory leaks.
127 TODO refresh: test in Shark / malloc debug: this DOES leak if we take this dealloc out, right?
129 if(lastProcessorInfo) {
130 size_t lastProcessorInfoSize = sizeof(integer_t) * numLastProcessorInfo;
131 vm_deallocate(mach_task_self(), (vm_address_t)lastProcessorInfo, lastProcessorInfoSize);
134 lastProcessorInfo = processorInfo;
135 numLastProcessorInfo = numProcessorInfo;
137 if (++inptr >= size) // advance our data ptr
148 - (BOOL)getNext:(CPUDataPtr)ptr
152 *ptr = cpudata[outptr++];
161 - (void)getCurrent:(CPUDataPtr)ptr
163 *ptr = cpudata[inptr ? inptr - 1 : size - 1];
167 - (void)getLast:(CPUDataPtr)ptr
169 *ptr = cpudata[inptr > 1 ? inptr - 2 : size + inptr - 2];