C:Avail - FLUSH should now handle systems with >2G of memory
[AROS.git] / workbench / c / Avail.c
blobf2e4e98ea4750e6a931a11dc3cb74d3e0416cbd2
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Avail CLI command
6 Lang: English
7 */
9 /******************************************************************************
12 NAME
14 Avail [CHIP | FAST | TOTAL | FLUSH] [H | HUMAN]
16 SYNOPSIS
18 CHIP/S, FAST/S, TOTAL/S, FLUSH/S, H=HUMAN/S
20 LOCATION
24 FUNCTION
26 Give a summary of the memory usage and availability in the system.
27 To free up unused memory that still may be allocated (libraries,
28 devices, fonts and such present in memory but whcih are currently
29 not in use), use the FLUSH option.
31 INPUTS
33 CHIP -- show only "chip" memory
34 FAST -- show only "fast" memory
35 TOTAL -- show information on memory regardless of type
36 FLUSH -- remove unnecessary things residing in memory
37 HUMAN -- display more human-readable values (gigabytes as "G",
38 megabytes as "M", kilobytes as "K")
40 RESULT
42 NOTES
44 "Chip" and "fast" memory are associated with the Amiga computer
45 and may not be applicable on your hardware platform.
47 EXAMPLE
49 BUGS
51 SEE ALSO
53 INTERNALS
55 HISTORY
57 ******************************************************************************/
59 #include <exec/execbase.h>
60 #include <exec/memory.h>
61 #include <proto/exec.h>
62 #include <dos/dos.h>
63 #include <proto/dos.h>
64 #include <utility/tagitem.h>
65 #include <string.h>
67 const TEXT version[] = "$VER: Avail 42.1 (8.12.2007)\n";
70 #define ARG_TEMPLATE "CHIP/S,FAST/S,TOTAL/S,FLUSH/S,H=HUMAN/S"
72 enum
74 ARG_CHIP = 0,
75 ARG_FAST,
76 ARG_TOTAL,
77 ARG_FLUSH,
78 ARG_HUMAN,
79 NOOFARGS
82 LONG printm(CONST_STRPTR head, ULONG *array, LONG num);
84 int __nocommandline = 1;
86 BOOL aHuman;
88 /* Allocate all memory (even for >2G systems), then free it.
89 * This will force all expungable items out of memory
91 static void FlushMem(struct ExecBase *SysBase)
93 APTR Mem;
95 Mem = AllocMem(0x7ffffff0, MEMF_PUBLIC);
96 if (Mem) {
97 FlushMem(SysBase);
98 FreeMem(Mem, 0x7ffffff0);
102 int main(void)
104 IPTR args[NOOFARGS] = { (IPTR)FALSE,
105 (IPTR)FALSE,
106 (IPTR)FALSE,
107 (IPTR)FALSE,
108 (IPTR)FALSE };
109 struct RDArgs *rda;
110 LONG error = 0;
111 BOOL bPrintErr = TRUE;
112 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
114 if (rda != NULL)
116 UWORD typeCount = 0;
117 BOOL aChip = (BOOL)args[ARG_CHIP];
118 BOOL aFast = (BOOL)args[ARG_FAST];
119 BOOL aTotal = (BOOL)args[ARG_TOTAL];
120 BOOL aFlush = (BOOL)args[ARG_FLUSH];
121 aHuman = (BOOL)args[ARG_HUMAN];
123 if (aChip)
125 typeCount++;
127 if (aFast)
129 typeCount++;
131 if (aTotal)
133 typeCount++;
136 ULONG chip[4], fast[4], total[4];
138 if (typeCount > 1)
140 FPuts(Output(), "Only one of CHIP, FAST or TOTAL allowed\n");
141 bPrintErr = FALSE;
142 FreeArgs(rda);
144 return RETURN_FAIL;
146 else
148 if (aFlush)
150 FlushMem(SysBase);
153 if(aChip)
156 chip[0] = AvailMem(MEMF_CHIP);
158 if (printm(NULL, chip, 1) < 0)
160 error = RETURN_ERROR;
163 else if(aFast)
165 fast[0] = AvailMem(MEMF_FAST);
167 if (printm(NULL, fast, 1) < 0)
169 error = RETURN_ERROR;
172 else if (aTotal)
174 total[0] = AvailMem(MEMF_ANY);
176 if (printm(NULL, total, 1) < 0)
178 error = RETURN_ERROR;
181 else
183 Forbid();
185 chip[0] = AvailMem(MEMF_CHIP);
186 chip[2] = AvailMem(MEMF_CHIP | MEMF_TOTAL);
187 chip[3] = AvailMem(MEMF_CHIP | MEMF_LARGEST);
188 chip[1] = chip[2] - chip[0];
189 fast[0] = AvailMem(MEMF_FAST);
190 fast[2] = AvailMem(MEMF_FAST | MEMF_TOTAL);
191 fast[3] = AvailMem(MEMF_FAST | MEMF_LARGEST);
192 fast[1] = fast[2] - fast[0];
193 total[0] = AvailMem(MEMF_ANY);
194 total[2] = AvailMem(MEMF_ANY | MEMF_TOTAL);
195 total[3] = AvailMem(MEMF_ANY | MEMF_LARGEST);
196 total[1] = total[2] - total[0];
198 Permit();
200 if (PutStr("Type Available In-Use Maximum Largest\n") < 0 ||
201 printm("chip", chip, 4) < 0 ||
202 printm("fast", fast, 4) < 0 ||
203 printm("total", total, 4) < 0)
205 error = RETURN_ERROR;
210 FreeArgs(rda);
212 else
214 error = RETURN_FAIL;
217 if(error != RETURN_OK && bPrintErr)
219 PrintFault(IoErr(), "Avail");
222 return error;
225 static
226 void fmtlarge(UBYTE *buf, ULONG num)
228 UQUAD d;
229 UBYTE ch;
230 struct
232 ULONG val;
233 LONG dec;
234 } array =
236 num,
240 if (num >= 1073741824)
242 array.val = num >> 30;
243 d = ((UQUAD)num * 10 + 536870912) / 1073741824;
244 array.dec = d % 10;
245 ch = 'G';
247 else if (num >= 1048576)
249 array.val = num >> 20;
250 d = ((UQUAD)num * 10 + 524288) / 1048576;
251 array.dec = d % 10;
252 ch = 'M';
254 else if (num >= 1024)
256 array.val = num >> 10;
257 d = (num * 10 + 512) / 1024;
258 array.dec = d % 10;
259 ch = 'K';
261 else
263 array.val = num;
264 array.dec = 0;
265 d = 0;
266 ch = 'B';
269 if (!array.dec && (d > array.val * 10))
271 array.val++;
274 RawDoFmt(array.dec ? "%lu.%lu" : "%lu", &array, NULL, buf);
275 while (*buf) { buf++; }
276 *buf++ = ch;
277 *buf = '\0';
280 LONG printm(CONST_STRPTR head, ULONG *array, LONG num)
282 LONG res = -1;
283 CONST_STRPTR fmt;
284 UBYTE buf[10];
286 if (head)
288 LONG len = 16 - strlen(head);
289 RawDoFmt(aHuman ? "%%%lds" : "%%%ldlu", &len, NULL, buf);
290 fmt = buf;
291 PutStr(head);
293 else
295 fmt = aHuman ? "%9s" : "%9lu";
298 if (aHuman)
300 if (num == 1)
302 fmtlarge(buf, *array);
303 res = PutStr(buf);
305 else
307 while (num--)
309 UBYTE tmp[10];
311 fmtlarge(tmp, *array);
312 res = Printf(fmt, (IPTR) tmp);
313 if (res < 0)
314 break;
316 fmt = " %9s";
317 array++;
321 else
323 if (num == 1)
325 res = VPrintf("%lu", (IPTR *)array);
327 else
329 while (num--)
331 res = VPrintf(fmt, (IPTR *)array);
332 if (res < 0)
333 break;
335 fmt = " %9lu";
336 array++;
340 PutStr("\n");
342 return res;