diff options
author | Ron Yorston <rmy@pobox.com> | 2021-02-18 15:27:44 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-02-18 15:47:47 +0000 |
commit | 2b8770720868c750ad8609df4041337eb2c6cf71 (patch) | |
tree | 85aff1e2b748d0e75ee5dbe82bc574bb2a5a9c1b | |
parent | 2d20b9d88c4fc91637babaafa4a60dd7943e03a7 (diff) | |
download | busybox-w32-2b8770720868c750ad8609df4041337eb2c6cf71.tar.gz busybox-w32-2b8770720868c750ad8609df4041337eb2c6cf71.tar.bz2 busybox-w32-2b8770720868c750ad8609df4041337eb2c6cf71.zip |
free: implement sysinfo(2) and enable free(1)
This is an experimental implementation of sysinfo(2)/free(1).
It uses the WIN32 API GlobalMemoryStatusEx() to obtain information
about memory.
It seems that the 'total pagefile' value includes total RAM as well
as pagefile and 'available pagefile' includes available RAM. So the
RAM values are deducted.
I've no idea what corresponds to Linux buffers and cache.
-rw-r--r-- | configs/mingw32_defconfig | 2 | ||||
-rw-r--r-- | configs/mingw64_defconfig | 2 | ||||
-rw-r--r-- | include/mingw.h | 22 | ||||
-rw-r--r-- | procps/free.c | 15 | ||||
-rw-r--r-- | win32/mingw.c | 24 |
5 files changed, 63 insertions, 2 deletions
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index 7108c2dda..8c0e2ed42 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -1035,7 +1035,7 @@ CONFIG_FEATURE_MIME_CHARSET="" | |||
1035 | # | 1035 | # |
1036 | # Process Utilities | 1036 | # Process Utilities |
1037 | # | 1037 | # |
1038 | # CONFIG_FREE is not set | 1038 | CONFIG_FREE=y |
1039 | # CONFIG_FUSER is not set | 1039 | # CONFIG_FUSER is not set |
1040 | # CONFIG_IOSTAT is not set | 1040 | # CONFIG_IOSTAT is not set |
1041 | CONFIG_KILL=y | 1041 | CONFIG_KILL=y |
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index 0cb4f4a3e..89167b998 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -1035,7 +1035,7 @@ CONFIG_FEATURE_MIME_CHARSET="" | |||
1035 | # | 1035 | # |
1036 | # Process Utilities | 1036 | # Process Utilities |
1037 | # | 1037 | # |
1038 | # CONFIG_FREE is not set | 1038 | CONFIG_FREE=y |
1039 | # CONFIG_FUSER is not set | 1039 | # CONFIG_FUSER is not set |
1040 | # CONFIG_IOSTAT is not set | 1040 | # CONFIG_IOSTAT is not set |
1041 | CONFIG_KILL=y | 1041 | CONFIG_KILL=y |
diff --git a/include/mingw.h b/include/mingw.h index f16d086e2..c2a8b61bf 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -349,6 +349,28 @@ int mingw_fstat(int fd, struct mingw_stat *buf); | |||
349 | #define fstat mingw_fstat | 349 | #define fstat mingw_fstat |
350 | 350 | ||
351 | /* | 351 | /* |
352 | * sys/sysinfo.h | ||
353 | */ | ||
354 | struct sysinfo { | ||
355 | long uptime; /* Seconds since boot */ | ||
356 | unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ | ||
357 | unsigned long totalram; /* Total usable main memory size */ | ||
358 | unsigned long freeram; /* Available memory size */ | ||
359 | unsigned long sharedram; /* Amount of shared memory */ | ||
360 | unsigned long bufferram; /* Memory used by buffers */ | ||
361 | unsigned long totalswap; /* Total swap space size */ | ||
362 | unsigned long freeswap; /* Swap space still available */ | ||
363 | unsigned short procs; /* Number of current processes */ | ||
364 | unsigned long totalhigh; /* Total high memory size */ | ||
365 | unsigned long freehigh; /* Available high memory size */ | ||
366 | unsigned int mem_unit; /* Memory unit size in bytes */ | ||
367 | char _f[20-2*sizeof(long)-sizeof(int)]; | ||
368 | /* Padding to 64 bytes */ | ||
369 | }; | ||
370 | |||
371 | int sysinfo(struct sysinfo *info); | ||
372 | |||
373 | /* | ||
352 | * sys/sysmacros.h | 374 | * sys/sysmacros.h |
353 | */ | 375 | */ |
354 | #define makedev(a,b) 0*(a)*(b) /* avoid unused warning */ | 376 | #define makedev(a,b) 0*(a)*(b) /* avoid unused warning */ |
diff --git a/procps/free.c b/procps/free.c index 0adef501f..142786083 100644 --- a/procps/free.c +++ b/procps/free.c | |||
@@ -52,6 +52,7 @@ static unsigned long long scale(struct globals *g, unsigned long d) | |||
52 | return ((unsigned long long)d * g->mem_unit) >> G_unit_steps; | 52 | return ((unsigned long long)d * g->mem_unit) >> G_unit_steps; |
53 | } | 53 | } |
54 | 54 | ||
55 | #if !ENABLE_PLATFORM_MINGW32 | ||
55 | /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ | 56 | /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ |
56 | static NOINLINE unsigned int parse_meminfo(struct globals *g) | 57 | static NOINLINE unsigned int parse_meminfo(struct globals *g) |
57 | { | 58 | { |
@@ -78,6 +79,14 @@ static NOINLINE unsigned int parse_meminfo(struct globals *g) | |||
78 | 79 | ||
79 | return seen_cached_and_available_and_reclaimable == 0; | 80 | return seen_cached_and_available_and_reclaimable == 0; |
80 | } | 81 | } |
82 | #else | ||
83 | static NOINLINE unsigned int parse_meminfo(struct globals *g) | ||
84 | { | ||
85 | g->cached_kb = g->available_kb = g->reclaimable_kb = 0; | ||
86 | |||
87 | return 1; | ||
88 | } | ||
89 | #endif | ||
81 | 90 | ||
82 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 91 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
83 | int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | 92 | int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) |
@@ -135,9 +144,15 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
135 | } | 144 | } |
136 | #endif | 145 | #endif |
137 | 146 | ||
147 | #if !ENABLE_PLATFORM_MINGW32 | ||
138 | #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" | 148 | #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" |
139 | #define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) | 149 | #define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) |
140 | #define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) | 150 | #define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) |
151 | #else | ||
152 | #define FIELDS_6 "%12I64u %11I64u %11I64u %11I64u %11I64u %11I64u\n" | ||
153 | #define FIELDS_3 (FIELDS_6 + 7 + 8 + 8) | ||
154 | #define FIELDS_2 (FIELDS_6 + 8 + 8 + 8 + 8) | ||
155 | #endif | ||
141 | 156 | ||
142 | printf(FIELDS_6, | 157 | printf(FIELDS_6, |
143 | scale(&G, info.totalram), //total | 158 | scale(&G, info.totalram), //total |
diff --git a/win32/mingw.c b/win32/mingw.c index 75635fdf1..48d2eefa7 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1368,6 +1368,30 @@ int mingw_unlink(const char *pathname) | |||
1368 | return ret; | 1368 | return ret; |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | int sysinfo(struct sysinfo *info) | ||
1372 | { | ||
1373 | DECLARE_PROC_ADDR(BOOL, GlobalMemoryStatusEx, LPMEMORYSTATUSEX); | ||
1374 | MEMORYSTATUSEX mem; | ||
1375 | |||
1376 | memset((void *)info, 0, sizeof(struct sysinfo)); | ||
1377 | |||
1378 | if (!INIT_PROC_ADDR(kernel32.dll, GlobalMemoryStatusEx)) { | ||
1379 | return -1; | ||
1380 | } | ||
1381 | |||
1382 | mem.dwLength = sizeof(MEMORYSTATUSEX); | ||
1383 | if (!GlobalMemoryStatusEx(&mem)) | ||
1384 | return -1; | ||
1385 | |||
1386 | info->mem_unit = 1; | ||
1387 | info->totalram = mem.ullTotalPhys; | ||
1388 | info->freeram = mem.ullAvailPhys; | ||
1389 | info->totalswap = mem.ullTotalPageFile - mem.ullTotalPhys; | ||
1390 | info->freeswap = mem.ullAvailPageFile - mem.ullAvailPhys; | ||
1391 | |||
1392 | return 0; | ||
1393 | } | ||
1394 | |||
1371 | #undef strftime | 1395 | #undef strftime |
1372 | size_t mingw_strftime(char *buf, size_t max, const char *format, const struct tm *tm) | 1396 | size_t mingw_strftime(char *buf, size_t max, const char *format, const struct tm *tm) |
1373 | { | 1397 | { |