Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5191 serge 1
/* Calculate the size of physical memory.
2
   Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
3
 
4
   This program is free software; you can redistribute it and/or modify
5
   it under the terms of the GNU General Public License as published by
6
   the Free Software Foundation; either version 2, or (at your option)
7
   any later version.
8
 
9
   This program is distributed in the hope that it will be useful,
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
   GNU General Public License for more details.
13
 
14
   You should have received a copy of the GNU General Public License
15
   along with this program; if not, write to the Free Software Foundation,
16
   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
17
 
18
/* Written by Paul Eggert.  */
19
 
20
#if HAVE_CONFIG_H
21
# include 
22
#endif
23
 
24
#if HAVE_UNISTD_H
25
# include 
26
#endif
27
 
28
#if HAVE_SYS_PSTAT_H
29
# include 
30
#endif
31
 
32
#if HAVE_SYS_SYSMP_H
33
# include 
34
#endif
35
 
36
#if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
37
# include 
38
# include 
39
#endif
40
 
41
#if HAVE_SYS_TABLE_H
42
# include 
43
#endif
44
 
45
#include 
46
 
47
#if HAVE_SYS_PARAM_H
48
# include 
49
#endif
50
 
51
#if HAVE_SYS_SYSCTL_H
52
# include 
53
#endif
54
 
55
#if HAVE_SYS_SYSTEMCFG_H
56
# include 
57
#endif
58
 
59
#ifdef _WIN32
60
# define WIN32_LEAN_AND_MEAN
61
# include 
62
/*  MEMORYSTATUSEX is missing from older windows headers, so define
63
    a local replacement.  */
64
typedef struct
65
{
66
  DWORD dwLength;
67
  DWORD dwMemoryLoad;
68
  DWORDLONG ullTotalPhys;
69
  DWORDLONG ullAvailPhys;
70
  DWORDLONG ullTotalPageFile;
71
  DWORDLONG ullAvailPageFile;
72
  DWORDLONG ullTotalVirtual;
73
  DWORDLONG ullAvailVirtual;
74
  DWORDLONG ullAvailExtendedVirtual;
75
} lMEMORYSTATUSEX;
76
typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
77
#endif
78
 
79
#include "libiberty.h"
80
 
81
/* Return the total amount of physical memory.  */
82
double
83
physmem_total (void)
84
{
85
#if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
86
  { /* This works on linux-gnu, solaris2 and cygwin.  */
87
    double pages = sysconf (_SC_PHYS_PAGES);
88
    double pagesize = sysconf (_SC_PAGESIZE);
89
    if (0 <= pages && 0 <= pagesize)
90
      return pages * pagesize;
91
  }
92
#endif
93
 
94
#if HAVE_PSTAT_GETSTATIC
95
  { /* This works on hpux11.  */
96
    struct pst_static pss;
97
    if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0))
98
      {
99
	double pages = pss.physical_memory;
100
	double pagesize = pss.page_size;
101
	if (0 <= pages && 0 <= pagesize)
102
	  return pages * pagesize;
103
      }
104
  }
105
#endif
106
 
107
#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
108
  { /* This works on irix6. */
109
    struct rminfo realmem;
110
    if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
111
      {
112
	double pagesize = sysconf (_SC_PAGESIZE);
113
	double pages = realmem.physmem;
114
	if (0 <= pages && 0 <= pagesize)
115
	  return pages * pagesize;
116
      }
117
  }
118
#endif
119
 
120
#if HAVE_GETSYSINFO && defined GSI_PHYSMEM
121
  { /* This works on Tru64 UNIX V4/5.  */
122
    int physmem;
123
 
124
    if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
125
		    NULL, NULL, NULL) == 1)
126
      {
127
	double kbytes = physmem;
128
 
129
	if (0 <= kbytes)
130
	  return kbytes * 1024.0;
131
      }
132
  }
133
#endif
134
 
135
#if HAVE_SYSCTL && defined HW_PHYSMEM
136
  { /* This works on *bsd and darwin.  */
137
    unsigned int physmem;
138
    size_t len = sizeof physmem;
139
    static int mib[2] = { CTL_HW, HW_PHYSMEM };
140
 
141
    if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0
142
	&& len == sizeof (physmem))
143
      return (double) physmem;
144
  }
145
#endif
146
 
147
#if HAVE__SYSTEM_CONFIGURATION
148
  /* This works on AIX 4.3.3+.  */
149
  return _system_configuration.physmem;
150
#endif
151
 
152
#if defined _WIN32
153
  { /* this works on windows */
154
    PFN_MS_EX pfnex;
155
    HMODULE h = GetModuleHandle ("kernel32.dll");
156
 
157
    if (!h)
158
      return 0.0;
159
 
160
    /*  Use GlobalMemoryStatusEx if available.  */
161
    if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
162
      {
163
	lMEMORYSTATUSEX lms_ex;
164
	lms_ex.dwLength = sizeof lms_ex;
165
	if (!pfnex (&lms_ex))
166
	  return 0.0;
167
	return (double) lms_ex.ullTotalPhys;
168
      }
169
 
170
    /*  Fall back to GlobalMemoryStatus which is always available.
171
        but returns wrong results for physical memory > 4GB.  */
172
    else
173
      {
174
	MEMORYSTATUS ms;
175
	GlobalMemoryStatus (&ms);
176
	return (double) ms.dwTotalPhys;
177
      }
178
  }
179
#endif
180
 
181
  /* Return 0 if we can't determine the value.  */
182
  return 0;
183
}
184
 
185
/* Return the amount of physical memory available.  */
186
double
187
physmem_available (void)
188
{
189
#if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
190
  { /* This works on linux-gnu, solaris2 and cygwin.  */
191
    double pages = sysconf (_SC_AVPHYS_PAGES);
192
    double pagesize = sysconf (_SC_PAGESIZE);
193
    if (0 <= pages && 0 <= pagesize)
194
      return pages * pagesize;
195
  }
196
#endif
197
 
198
#if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
199
  { /* This works on hpux11.  */
200
    struct pst_static pss;
201
    struct pst_dynamic psd;
202
    if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)
203
	&& 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0))
204
      {
205
	double pages = psd.psd_free;
206
	double pagesize = pss.page_size;
207
	if (0 <= pages && 0 <= pagesize)
208
	  return pages * pagesize;
209
      }
210
  }
211
#endif
212
 
213
#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
214
  { /* This works on irix6. */
215
    struct rminfo realmem;
216
    if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
217
      {
218
	double pagesize = sysconf (_SC_PAGESIZE);
219
	double pages = realmem.availrmem;
220
	if (0 <= pages && 0 <= pagesize)
221
	  return pages * pagesize;
222
      }
223
  }
224
#endif
225
 
226
#if HAVE_TABLE && defined TBL_VMSTATS
227
  { /* This works on Tru64 UNIX V4/5.  */
228
    struct tbl_vmstats vmstats;
229
 
230
    if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
231
      {
232
	double pages = vmstats.free_count;
233
	double pagesize = vmstats.pagesize;
234
 
235
	if (0 <= pages && 0 <= pagesize)
236
	  return pages * pagesize;
237
      }
238
  }
239
#endif
240
 
241
#if HAVE_SYSCTL && defined HW_USERMEM
242
  { /* This works on *bsd and darwin.  */
243
    unsigned int usermem;
244
    size_t len = sizeof usermem;
245
    static int mib[2] = { CTL_HW, HW_USERMEM };
246
 
247
    if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0
248
	&& len == sizeof (usermem))
249
      return (double) usermem;
250
  }
251
#endif
252
 
253
#if defined _WIN32
254
  { /* this works on windows */
255
    PFN_MS_EX pfnex;
256
    HMODULE h = GetModuleHandle ("kernel32.dll");
257
 
258
    if (!h)
259
      return 0.0;
260
 
261
    /*  Use GlobalMemoryStatusEx if available.  */
262
    if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
263
      {
264
	lMEMORYSTATUSEX lms_ex;
265
	lms_ex.dwLength = sizeof lms_ex;
266
	if (!pfnex (&lms_ex))
267
	  return 0.0;
268
	return (double) lms_ex.ullAvailPhys;
269
      }
270
 
271
    /*  Fall back to GlobalMemoryStatus which is always available.
272
        but returns wrong results for physical memory > 4GB  */
273
    else
274
      {
275
	MEMORYSTATUS ms;
276
	GlobalMemoryStatus (&ms);
277
	return (double) ms.dwAvailPhys;
278
      }
279
  }
280
#endif
281
 
282
  /* Guess 25% of physical memory.  */
283
  return physmem_total () / 4;
284
}
285
 
286
 
287
#if DEBUG
288
 
289
# include 
290
# include 
291
 
292
int
293
main (void)
294
{
295
  printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
296
  exit (0);
297
}
298
 
299
#endif /* DEBUG */
300
 
301
/*
302
Local Variables:
303
compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c"
304
End:
305
*/