* Extract uma(9) statistics from the running kernel, and store all memory * type information in the passed list. For each type, check the list for an * existing entry with the right name/allocator -- if present, update that * entry. Otherwise, add a new entry. On error, the entire list will be * cleared, as entries will be in an inconsistent state. * * To reduce the level of work for a li
| 82 | * each entry before adding it. |
| 83 | */ |
| 84 | int |
| 85 | memstat_sysctl_uma(struct memory_type_list *list, int flags) |
| 86 | { |
| 87 | struct uma_stream_header *ushp; |
| 88 | struct uma_type_header *uthp; |
| 89 | struct uma_percpu_stat *upsp; |
| 90 | struct memory_type *mtp; |
| 91 | int count, hint_dontsearch, i, j, maxcpus, maxid; |
| 92 | char *buffer, *p; |
| 93 | size_t size; |
| 94 | |
| 95 | hint_dontsearch = LIST_EMPTY(&list->mtl_list); |
| 96 | |
| 97 | /* |
| 98 | * Query the number of CPUs, number of malloc types so that we can |
| 99 | * guess an initial buffer size. We loop until we succeed or really |
| 100 | * fail. Note that the value of maxcpus we query using sysctl is not |
| 101 | * the version we use when processing the real data -- that is read |
| 102 | * from the header. |
| 103 | */ |
| 104 | retry: |
| 105 | size = sizeof(maxid); |
| 106 | if (sysctlbyname("kern.smp.maxid", &maxid, &size, NULL, 0) < 0) { |
| 107 | if (errno == EACCES || errno == EPERM) |
| 108 | list->mtl_error = MEMSTAT_ERROR_PERMISSION; |
| 109 | else |
| 110 | list->mtl_error = MEMSTAT_ERROR_DATAERROR; |
| 111 | return (-1); |
| 112 | } |
| 113 | if (size != sizeof(maxid)) { |
| 114 | list->mtl_error = MEMSTAT_ERROR_DATAERROR; |
| 115 | return (-1); |
| 116 | } |
| 117 | |
| 118 | size = sizeof(count); |
| 119 | if (sysctlbyname("vm.zone_count", &count, &size, NULL, 0) < 0) { |
| 120 | if (errno == EACCES || errno == EPERM) |
| 121 | list->mtl_error = MEMSTAT_ERROR_PERMISSION; |
| 122 | else |
| 123 | list->mtl_error = MEMSTAT_ERROR_VERSION; |
| 124 | return (-1); |
| 125 | } |
| 126 | if (size != sizeof(count)) { |
| 127 | list->mtl_error = MEMSTAT_ERROR_DATAERROR; |
| 128 | return (-1); |
| 129 | } |
| 130 | |
| 131 | size = sizeof(*uthp) + count * (sizeof(*uthp) + sizeof(*upsp) * |
| 132 | (maxid + 1)); |
| 133 | |
| 134 | buffer = malloc(size); |
| 135 | if (buffer == NULL) { |
| 136 | list->mtl_error = MEMSTAT_ERROR_NOMEMORY; |
| 137 | return (-1); |
| 138 | } |
| 139 | |
| 140 | if (sysctlbyname("vm.zone_stats", buffer, &size, NULL, 0) < 0) { |
| 141 | /* |
no test coverage detected