taskpaper. trying to undo attempted proj rename.
[cpuHistory.git] / CPUInfo.m
blob4f82f75bc37959801821a1c78a8d63e21922c751
1 /*
2  *      CPU Mon
3  *      Christopher Bowns, 2008
4  */
5 //  CPUInfo.m
6 //  CPU Usage
7 //
8 //  Created by Peter Hosey on 2006-06-21.
9 //  Copyright 2006 Peter Hosey. All rights reserved.
11 //  Modified by Christopher Bowns, starting 2008-1-1.
13 #ifndef NSLOG_DEBUG
14 #define NSLOG_DEBUG
15 #endif
17 #import "CPUInfo.h"
19 #include <sys/types.h>
20 //sqrtf, ceilf
21 #include <math.h>
22 //sysctl and its parameters
23 #include <sys/sysctl.h>
24 //errno, strerror
25 #include <sys/errno.h>
26 #include <string.h>
28 @implementation CPUInfo
31         Accomplishes:
32                 inits cpudata, inptr, outptr
33                 retrieves lastProcessorInfo for refresh method to go to town.
34         
35         if cannot get processor info, returns nil.
37 - (CPUInfo *) initWithCapacity:(unsigned)numItems
39         
40         /*
41                 from CPU usage
42         */      
43         //We could get the number of processors the same way that we get the CPU usage info, but that allocates memory.
44 /*      enum { miblen = 2U };
45         int mib[miblen] = { CTL_HW, HW_NCPU };
46         size_t sizeOfNumCPUs = sizeof(numCPUs);
47         int status = sysctl(mib, miblen,
48                    &numCPUs, &sizeOfNumCPUs,
49 */                 /*newp*/ // NULL, /*newlen*/ 0U);
50 //      if(status != 0) {
51                 numCPUs = 1; // TODO we're going to assume one CPU for the moment.
52 //              NSLog(@"%s error status, assuming one CPU", _cmd);
53 //      }
54         
55         
56         
57         
58         
59         
60         self = [super init];
61         
62         size = numItems;
63         cpudata = calloc(numItems, sizeof(CPUData));
64         if (cpudata == NULL) {
65                 NSLog (@"%s Failed to allocate buffer for CPUInfo", _cmd);
66                 return (nil);
67         }
68         // Set up our data structure ptrs
69         inptr = 0;
70         outptr = -1;
71         
72         // set the lastProcessorInfo array so we can get to work when we call refresh:
73         natural_t numProcessors_nobodyCares = 0U;
74         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);
75         if(err != KERN_SUCCESS) {
76                 NSLog(@"%s failed to get cpu statistics", _cmd);
77                 
78                 // if we can't get this info, then we're toast. Exit gracefully.
79                 return (nil);
80         }
81         
82         return (self);
87         Assumptions:
88                 init has run.
89                 lastProcessorInfo and numLastProcessorInfo contain valid data from prior refresh of CPU info
90         Accomplishes:
91                 retrieves current data
92                 calculates avg cpu load over last period
93                 updates cpudata array with info
94                 deallocates old numLastProcInfo and lastProcessorInfo and set ptrs to new data
96 - (void)refresh
98         processor_info_array_t processorInfo;
99         natural_t numProcessors_nobodyCares = 0U;
100         mach_msg_type_number_t numProcessorInfo;
102         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);
103         if(err != KERN_SUCCESS) {
104                 NSLog(@"%s failed to get cpu statistics", _cmd);
105         }
106         
107         /*
108                 TODO make this multicore. First, we're gonna need a multicore machine to test it on.
109         */
110         // for(unsigned i = 0U; i < numCPUs; ++i)
111         
112         unsigned int inUse, total, user, sys, nice, idle;
113                 
114         user = processorInfo[CPU_STATE_USER] - lastProcessorInfo[CPU_STATE_USER];
115         sys = processorInfo[CPU_STATE_SYSTEM] - lastProcessorInfo[CPU_STATE_SYSTEM];
116         nice = processorInfo[CPU_STATE_NICE] - lastProcessorInfo[CPU_STATE_NICE];
117         idle = processorInfo[CPU_STATE_IDLE] - lastProcessorInfo[CPU_STATE_IDLE];
119         inUse = user + sys + nice;
120         total = inUse + idle;
121         
122         cpudata[inptr].user = (double)user / (double)total;
123         cpudata[inptr].sys = (double)sys / (double)total;
124         cpudata[inptr].nice = (double)nice / (double)total;
125         cpudata[inptr].idle = (double)idle / (double)total;
126         
127         
128         // deallocate the last one, since we don't want memory leaks.
129         /*
130                 TODO refresh: test in Shark / malloc debug: this DOES leak if we take this dealloc out, right?
131         */
132         if(lastProcessorInfo) {
133                 size_t lastProcessorInfoSize = sizeof(integer_t) * numLastProcessorInfo;
134                 vm_deallocate(mach_task_self(), (vm_address_t)lastProcessorInfo, lastProcessorInfoSize);
135         }
137         lastProcessorInfo = processorInfo;
138         numLastProcessorInfo = numProcessorInfo;
139         
140         if (++inptr >= size) // advance our data ptr
141                 inptr = 0;
145 - (void)startIterate
147         outptr = inptr;
151 - (BOOL)getNext:(CPUDataPtr)ptr
153         if (outptr == -1)
154                 return (FALSE);
155         *ptr = cpudata[outptr++];
156         if (outptr >= size)
157                 outptr = 0;
158         if (outptr == inptr)
159                 outptr = -1;
160         return (TRUE);
164 - (void)getCurrent:(CPUDataPtr)ptr
166         *ptr = cpudata[inptr ? inptr - 1 : size - 1];
170 - (void)getLast:(CPUDataPtr)ptr
172         *ptr = cpudata[inptr > 1 ? inptr - 2 : size + inptr - 2];
176 - (int)getSize
178         return (size);
181 @end