6 * Copyright (C) 2005-2013 Team XBMC
9 * This Program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with XBMC; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
25 #include "XMemUtils.h"
27 #if defined(TARGET_DARWIN)
28 #include <mach/mach.h>
32 #define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1))
34 // aligned memory allocation.
35 // in order to do so - we alloc extra space and store the original allocation in it (so that we can free later on).
36 // the returned address will be the nearest alligned address within the space allocated.
37 void *_aligned_malloc(size_t s, size_t alignTo) {
39 char *pFull = (char*)malloc(s + alignTo + sizeof(char *));
40 char *pAlligned = (char *)ALIGN(((unsigned long)pFull + sizeof(char *)), alignTo);
42 *(char **)(pAlligned - sizeof(char*)) = pFull;
47 void _aligned_free(void *p) {
51 char *pFull = *(char **)(((char *)p) - sizeof(char *));
55 #ifndef TARGET_WINDOWS
57 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN) && !defined(TARGET_FREEBSD)
58 static FILE* procMeminfoFP = NULL;
61 void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
66 memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
67 lpBuffer->dwLength = sizeof(MEMORYSTATUSEX);
69 #if defined(TARGET_DARWIN)
71 size_t len = sizeof physmem;
72 int mib[2] = { CTL_HW, HW_MEMSIZE };
73 size_t miblen = sizeof(mib) / sizeof(mib[0]);
75 // Total physical memory.
76 if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
77 lpBuffer->ullTotalPhys = physmem;
80 mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE;
81 struct xsw_usage swap;
82 len = sizeof(struct xsw_usage);
83 if (sysctl(mib, miblen, &swap, &len, NULL, 0) == 0)
85 lpBuffer->ullAvailPageFile = swap.xsu_avail;
86 lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
90 mach_port_t stat_port = mach_host_self();
91 vm_statistics_data_t vm_stat;
92 mach_msg_type_number_t count = sizeof(vm_stat) / sizeof(natural_t);
93 if (host_statistics(stat_port, HOST_VM_INFO, (host_info_t)&vm_stat, &count) == 0)
97 mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
99 if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
101 uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
103 lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
104 lpBuffer->ullAvailVirtual = lpBuffer->ullAvailPhys; // FIXME.
107 #elif defined(TARGET_FREEBSD)
108 /* sysctl hw.physmem */
109 size_t physmem = 0, mem_free = 0, pagesize = 0, swap_free = 0;
110 size_t mem_avail = 0, mem_inactive = 0, mem_cache = 0, len = 0;
113 len = sizeof(physmem);
114 if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
115 lpBuffer->ullTotalPhys = physmem;
116 lpBuffer->ullTotalVirtual = physmem;
119 len = sizeof(pagesize);
120 if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
123 len = sizeof(mem_inactive);
124 if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
125 mem_inactive *= pagesize;
127 len = sizeof(mem_cache);
128 if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
129 mem_cache *= pagesize;
131 len = sizeof(mem_free);
132 if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
133 mem_free *= pagesize;
135 /* mem_avail = mem_inactive + mem_cache + mem_free */
136 lpBuffer->ullAvailPhys = mem_inactive + mem_cache + mem_free;
137 lpBuffer->ullAvailVirtual = mem_inactive + mem_cache + mem_free;
139 if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
140 lpBuffer->ullAvailPageFile = swap_free * pagesize;
145 if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
149 memset(&info, 0, sizeof(struct sysinfo));
150 info.mem_unit = 4096;
151 while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
153 if (strncmp("MemTotal:", name, 9) == 0)
154 info.totalram = val/4;
155 else if (strncmp("MemFree:", name, 8) == 0)
156 info.freeram = val/4;
157 else if (strncmp("Buffers:", name, 8) == 0)
158 info.bufferram += val/4;
159 else if (strncmp("Cached:", name, 7) == 0)
160 info.bufferram += val/4;
161 else if (strncmp("SwapTotal:", name, 10) == 0)
162 info.totalswap = val/4;
163 else if (strncmp("SwapFree:", name, 9) == 0)
164 info.freeswap = val/4;
165 else if (strncmp("HighTotal:", name, 10) == 0)
166 info.totalhigh = val/4;
167 else if (strncmp("HighFree:", name, 9) == 0)
168 info.freehigh = val/4;
170 rewind(procMeminfoFP);
171 fflush(procMeminfoFP);
173 lpBuffer->dwLength = sizeof(MEMORYSTATUSEX);
174 lpBuffer->ullAvailPageFile = (info.freeswap * info.mem_unit);
175 lpBuffer->ullAvailPhys = ((info.freeram + info.bufferram) * info.mem_unit);
176 lpBuffer->ullAvailVirtual = ((info.freeram + info.bufferram) * info.mem_unit);
177 lpBuffer->ullTotalPhys = (info.totalram * info.mem_unit);
178 lpBuffer->ullTotalVirtual = (info.totalram * info.mem_unit);