1/*
2 * Copyright (c) 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24cc alloccount.c -o alloccount -Wall -framework IOKit
25 */
26
27#include <sysexits.h>
28#include <malloc/malloc.h>
29#include <CoreFoundation/CoreFoundation.h>
30#include <IOKit/IOKitLib.h>
31#include <IOKit/IOKitKeys.h>
32
33/*********************************************************************
34*********************************************************************/
35static Boolean printNumber(
36    CFDictionaryRef dict,
37    CFStringRef     name,
38    char         ** nameCString)
39{
40    int           result     = FALSE;
41    CFIndex       nameLength = 0;
42    static char * nameBuffer = NULL;  // free if nameCString is NULL
43    CFNumberRef   num        = NULL;  // do not release
44    SInt32	      num32      = 0;
45    Boolean       gotName    = FALSE;
46    Boolean       gotNum     = FALSE;
47
48   /* Note that errors displaying the name and value are not considered
49    * fatal and do not affect the exit status of the program.
50    */
51    num = (CFNumberRef)CFDictionaryGetValue(dict, name);
52    if (num) {
53        nameLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name),
54            kCFStringEncodingUTF8);
55        if (!nameCString || !*nameCString) {
56            nameBuffer = (char *)malloc((1 + nameLength) * sizeof(char));
57        } else if ((1 + nameLength) > malloc_size(nameBuffer)) {
58            nameBuffer = (char *)realloc(*nameCString,
59                (1 + nameLength) * sizeof(char));
60        }
61        if (nameBuffer) {
62            gotName = CFStringGetCString(name, nameBuffer, 1 + nameLength,
63                kCFStringEncodingUTF8);
64        } else {
65            fprintf(stderr, "Memory allocation failure.\n");
66            goto finish;
67        }
68        printf("%22s = ", gotName ? nameBuffer : "??");
69
70        if (CFNumberGetTypeID() == CFGetTypeID(num)) {
71            gotNum = CFNumberGetValue(num, kCFNumberSInt32Type, &num32);
72        }
73        if (gotNum) {
74            printf("0x%08lx = %4lu K\n",
75                   (unsigned long)num32,
76                   (unsigned long)(num32 / 1024));
77        } else {
78            printf("?? (error reading/converting value)\n");
79        }
80    }
81
82    result = TRUE;
83
84finish:
85    if (nameCString) {
86        *nameCString = nameBuffer;
87    } else {
88        if (nameBuffer) free(nameBuffer);
89    }
90    return result;
91}
92
93/*********************************************************************
94*********************************************************************/
95int main(int argc, char ** argv)
96{
97    int                  result      = EX_OSERR;
98    io_registry_entry_t  root        = IO_OBJECT_NULL;  // must IOObjectRelease()
99    CFDictionaryRef 	 rootProps   = NULL;            // must release
100    CFDictionaryRef 	 allocInfo   = NULL;            // do not release
101    kern_return_t        status      = KERN_FAILURE;
102    char               * nameCString = NULL;            // must free
103
104    // Obtain the registry root entry.
105
106    root = IORegistryGetRootEntry(kIOMasterPortDefault);
107    if (!root) {
108        fprintf(stderr, "Error: Can't get registry root.\n");
109        goto finish;
110    }
111
112    status = IORegistryEntryCreateCFProperties(root,
113        (CFMutableDictionaryRef *)&rootProps,
114        kCFAllocatorDefault, kNilOptions );
115    if (KERN_SUCCESS != status) {
116        fprintf(stderr, "Error: Can't read registry root properties.\n");
117        goto finish;
118    }
119    if (CFDictionaryGetTypeID() != CFGetTypeID(rootProps)) {
120        fprintf(stderr, "Error: Registry root properties not a dictionary.\n");
121        goto finish;
122    }
123
124    allocInfo = (CFDictionaryRef)CFDictionaryGetValue(rootProps,
125        CFSTR(kIOKitDiagnosticsKey));
126    if (!allocInfo) {
127        fprintf(stderr, "Error: Allocation information missing.\n");
128        goto finish;
129    }
130    if (CFDictionaryGetTypeID() != CFGetTypeID(allocInfo)) {
131        fprintf(stderr, "Error: Allocation information not a dictionary.\n");
132        goto finish;
133    }
134
135    if (!(printNumber(allocInfo, CFSTR("Instance allocation"),  &nameCString)  &&
136          printNumber(allocInfo, CFSTR("Container allocation"), &nameCString) &&
137          printNumber(allocInfo, CFSTR("IOMalloc allocation"),  &nameCString)  &&
138          printNumber(allocInfo, CFSTR("Pageable allocation"),  &nameCString) )) {
139
140          goto finish;
141    }
142
143    result = EX_OK;
144
145finish:
146    if (nameCString)            free(nameCString);
147    if (rootProps)              CFRelease(rootProps);
148    if (root != IO_OBJECT_NULL) IOObjectRelease(root);
149
150    return result;
151}
152
153