>From 1eccf56a49bc0aa3f167a0fce1a65c91a92ed468 Mon Sep 17 00:00:00 2001
From: Assaf Gordon
Date: Thu, 30 Aug 2012 11:21:57 -0400
Subject: [PATCH] physmem: A new program to report mem information.
---
src/Makefile.am | 2 +
src/physmem.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 217 insertions(+), 0 deletions(-)
create mode 100644 src/physmem.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 896c902..ae0c20c7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,6 +90,7 @@ EXTRA_PROGRAMS = \
od \
paste \
pathchk \
+ physmem \
pr \
printenv \
printf \
@@ -198,6 +199,7 @@ chroot_LDADD = $(LDADD)
cksum_LDADD = $(LDADD)
comm_LDADD = $(LDADD)
nproc_LDADD = $(LDADD)
+physmem_LDADD = $(LDADD)
cp_LDADD = $(LDADD)
csplit_LDADD = $(LDADD)
cut_LDADD = $(LDADD)
diff --git a/src/physmem.c b/src/physmem.c
new file mode 100644
index 0000000..b990503
--- /dev/null
+++ b/src/physmem.c
@@ -0,0 +1,215 @@
+/* physmem - report the total/available/recommended memory
+ Copyright (C) 2009-2012 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+/* Written by Assaf Gordon. */
+
+#include
+#include
+#include
+#include
+
+#include "system.h"
+#include "error.h"
+#include "xstrtol.h"
+#include "physmem.h"
+#include "human.h"
+
+#ifndef RLIMIT_DATA
+struct rlimit { size_t rlim_cur; };
+# define getrlimit(Resource, Rlp) (-1)
+#endif
+
+/* The official name of this program (e.g., no 'g' prefix). */
+#define PROGRAM_NAME "physmem"
+
+#define AUTHORS proper_name ("Assaf Gordon")
+
+/* Human-readable options for output. */
+static int human_output_opts;
+
+enum memory_report_type
+ {
+ total, /* default */
+ available,
+ recommended
+ };
+
+static enum memory_report_type memory_report_type = total;
+
+/* For long options that have no equivalent short option, use a
+ non-character as a pseudo short option, starting with CHAR_MAX + 1. */
+enum
+{
+ HUMAN_SI_OPTION= CHAR_MAX + 1
+};
+
+static struct option const longopts[] =
+{
+ {"total", no_argument, NULL, 't'},
+ {"available", no_argument, NULL, 'a'},
+ {"recommended", no_argument, NULL, 'r'},
+ {"human", no_argument, NULL, 'h'},
+ {"si", no_argument, NULL, HUMAN_SI_OPTION},
+ {GETOPT_HELP_OPTION_DECL},
+ {GETOPT_VERSION_OPTION_DECL},
+ {NULL, 0, NULL, 0}
+};
+
+/* Return the default sort size.
+ FIXME: this function was copied from sort.c .
+ extract it to a separate module.
+ */
+static size_t
+default_sort_size (void)
+{
+ /* Let SIZE be MEM, but no more than the maximum object size,
+ total memory, or system resource limits. Don't bother to check
+ for values like RLIM_INFINITY since in practice they are not much
+ less than SIZE_MAX. */
+ size_t size = SIZE_MAX;
+ struct rlimit rlimit;
+ if (getrlimit (RLIMIT_DATA, &rlimit) == 0 && rlimit.rlim_cur < size)
+ size = rlimit.rlim_cur;
+#ifdef RLIMIT_AS
+ if (getrlimit (RLIMIT_AS, &rlimit) == 0 && rlimit.rlim_cur < size)
+ size = rlimit.rlim_cur;
+#endif
+
+ /* Leave a large safety margin for the above limits, as failure can
+ occur when they are exceeded. */
+ size /= 2;
+
+#ifdef RLIMIT_RSS
+ /* Leave a 1/16 margin for RSS to leave room for code, stack, etc.
+ Exceeding RSS is not fatal, but can be quite slow. */
+ if (getrlimit (RLIMIT_RSS, &rlimit) == 0 && rlimit.rlim_cur / 16 * 15 < size)
+ size = rlimit.rlim_cur / 16 * 15;
+#endif
+
+ /* Let MEM be available memory or 1/8 of total memory, whichever
+ is greater. */
+ double avail = physmem_available ();
+ double total = physmem_total ();
+ double mem = MAX (avail, total / 8);
+
+ /* Leave a 1/4 margin for physical memory. */
+ if (total * 0.75 < size)
+ size = total * 0.75;
+
+ /* Return the minimum of MEM and SIZE, but no less than
+ MIN_SORT_SIZE. Avoid the MIN macro here, as it is not quite
+ right when only one argument is floating point. */
+ if (mem < size)
+ size = mem;
+ return size;
+}
+
+void
+usage (int status)
+{
+ if (status != EXIT_SUCCESS)
+ emit_try_help ();
+ else
+ {
+ printf (_("Usage: %s [OPTION]...\n"), program_name);
+ fputs (_("\
+Prints information about physical memory.\n\
+\n\
+"), stdout);
+ fputs (_("\
+ -t, --total print the total physical memory.\n\
+ -a, --available print the available physical memory.\n\
+ -r, --recommended print a safe recommended amount of useable memory.\n\
+ -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
+ --si like -h, but use powers of 1000 not 1024\n\
+"), stdout);
+
+ fputs (HELP_OPTION_DESCRIPTION, stdout);
+ fputs (VERSION_OPTION_DESCRIPTION, stdout);
+ emit_ancillary_info ();
+ }
+ exit (status);
+}
+
+int
+main (int argc, char **argv)
+{
+ size_t memory =0 ;
+ initialize_main (&argc, &argv);
+ set_program_name (argv[0]);
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ atexit (close_stdout);
+
+ while (1)
+ {
+ int c = getopt_long (argc, argv, "thar", longopts, NULL);
+ if (c == -1)
+ break;
+ switch (c)
+ {
+ case_GETOPT_HELP_CHAR;
+
+ case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
+
+ case 't':
+ memory_report_type = total;
+ break;
+
+ case 'a':
+ memory_report_type = available;
+ break;
+
+ case 'r':
+ memory_report_type = recommended;
+ break;
+
+ case 'h':
+ human_output_opts = human_autoscale | human_SI | human_base_1024;
+ break;
+
+ case HUMAN_SI_OPTION:
+ human_output_opts = human_autoscale | human_SI;
+ break;
+
+ default:
+ usage (EXIT_FAILURE);
+ }
+ }
+
+ switch(memory_report_type)
+ {
+ case total:
+ memory = physmem_total();
+ break;
+
+ case available:
+ memory = physmem_available();
+ break;
+
+ case recommended:
+ memory = default_sort_size();
+ break;
+ }
+
+ char buf[LONGEST_HUMAN_READABLE + 1];
+ fputs (human_readable (memory, buf, human_output_opts,1,1),stdout);
+ fputs("\n", stdout);
+
+ exit (EXIT_SUCCESS);
+}
--
1.7.7.4