Merge pull request #5039 from CEikermann/patch-1
[vuplus_xbmc] / xbmc / linux / XMemUtils.cpp
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4
5 /*
6  *      Copyright (C) 2005-2013 Team XBMC
7  *      http://xbmc.org
8  *
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)
12  *  any later version.
13  *
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.
18  *
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/>.
22  *
23  */
24
25 #include "XMemUtils.h"
26
27 #if defined(TARGET_DARWIN)
28 #include <mach/mach.h>
29 #endif
30
31 #undef ALIGN
32 #define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1))
33
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) {
38
39   char *pFull = (char*)malloc(s + alignTo + sizeof(char *));
40   char *pAlligned = (char *)ALIGN(((unsigned long)pFull + sizeof(char *)), alignTo);
41
42   *(char **)(pAlligned - sizeof(char*)) = pFull;
43
44   return(pAlligned);
45 }
46
47 void _aligned_free(void *p) {
48   if (!p)
49     return;
50
51   char *pFull = *(char **)(((char *)p) - sizeof(char *));
52   free(pFull);
53 }
54
55 #ifndef TARGET_WINDOWS
56
57 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN) && !defined(TARGET_FREEBSD)
58 static FILE* procMeminfoFP = NULL;
59 #endif
60
61 void GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
62 {
63   if (!lpBuffer)
64     return;
65
66   memset(lpBuffer, 0, sizeof(MEMORYSTATUSEX));
67   lpBuffer->dwLength = sizeof(MEMORYSTATUSEX);
68
69 #if defined(TARGET_DARWIN)
70   uint64_t physmem;
71   size_t len = sizeof physmem;
72   int mib[2] = { CTL_HW, HW_MEMSIZE };
73   size_t miblen = sizeof(mib) / sizeof(mib[0]);
74
75   // Total physical memory.
76   if (sysctl(mib, miblen, &physmem, &len, NULL, 0) == 0 && len == sizeof (physmem))
77       lpBuffer->ullTotalPhys = physmem;
78
79   // Virtual memory.
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)
84   {
85       lpBuffer->ullAvailPageFile = swap.xsu_avail;
86       lpBuffer->ullTotalVirtual = lpBuffer->ullTotalPhys + swap.xsu_total;
87   }
88
89   // In use.
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)
94   {
95       // Find page size.
96       int pageSize;
97       mib[0] = CTL_HW; mib[1] = HW_PAGESIZE;
98       len = sizeof(int);
99       if (sysctl(mib, miblen, &pageSize, &len, NULL, 0) == 0)
100       {
101           uint64_t used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pageSize;
102
103           lpBuffer->ullAvailPhys = lpBuffer->ullTotalPhys - used;
104           lpBuffer->ullAvailVirtual  = lpBuffer->ullAvailPhys; // FIXME.
105       }
106   }
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;
111
112   /* physmem */
113   len = sizeof(physmem);
114   if (sysctlbyname("hw.physmem", &physmem, &len, NULL, 0) == 0) {
115     lpBuffer->ullTotalPhys = physmem;
116     lpBuffer->ullTotalVirtual = physmem;
117   }
118   /* pagesize */
119   len = sizeof(pagesize);
120   if (sysctlbyname("hw.pagesize", &pagesize, &len, NULL, 0) != 0)
121     pagesize = 4096;
122   /* mem_inactive */
123   len = sizeof(mem_inactive);
124   if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &len, NULL, 0) == 0)
125     mem_inactive *= pagesize;
126   /* mem_cache */
127   len = sizeof(mem_cache);
128   if (sysctlbyname("vm.stats.vm.v_cache_count", &mem_cache, &len, NULL, 0) == 0)
129     mem_cache *= pagesize;
130   /* mem_free */
131   len = sizeof(mem_free);
132   if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &len, NULL, 0) == 0)
133     mem_free *= pagesize;
134
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;
138
139   if (sysctlbyname("vm.stats.vm.v_swappgsout", &swap_free, &len, NULL, 0) == 0)
140     lpBuffer->ullAvailPageFile = swap_free * pagesize;
141 #else
142   struct sysinfo info;
143   char name[32];
144   unsigned val;
145   if (!procMeminfoFP && (procMeminfoFP = fopen("/proc/meminfo", "r")) == NULL)
146     sysinfo(&info);
147   else
148   {
149     memset(&info, 0, sizeof(struct sysinfo));
150     info.mem_unit = 4096;
151     while (fscanf(procMeminfoFP, "%31s %u%*[^\n]\n", name, &val) != EOF)
152     {
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;
169     }
170     rewind(procMeminfoFP);
171     fflush(procMeminfoFP);
172   }
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);
179 #endif
180 }
181
182 #endif
183