diff options
author | Amit Pundir <amit.pundir@linaro.org> | 2012-03-21 15:02:31 +0530 |
---|---|---|
committer | Amit Pundir <amit.pundir@linaro.org> | 2012-03-21 15:02:31 +0530 |
commit | 97eef362f41427f7d5a05dea534e7f2a4fe11df6 (patch) | |
tree | bbdd16e929902494f57ce118aee0de6aeda1fae1 | |
download | memtester-97eef362f41427f7d5a05dea534e7f2a4fe11df6.tar.gz |
memtester-4.2.2 hosted on http://pyropus.ca/software/memtester/
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
-rw-r--r-- | BUGS | 7 | ||||
-rw-r--r-- | CHANGELOG | 120 | ||||
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | Makefile | 84 | ||||
-rw-r--r-- | README | 115 | ||||
-rw-r--r-- | README.tests | 38 | ||||
-rw-r--r-- | conf-cc | 3 | ||||
-rw-r--r-- | conf-ld | 3 | ||||
-rwxr-xr-x | extra-libs.sh | 16 | ||||
-rwxr-xr-x | find-systype.sh | 144 | ||||
-rwxr-xr-x | make-compile.sh | 1 | ||||
-rwxr-xr-x | make-load.sh | 2 | ||||
-rwxr-xr-x | make-makelib.sh | 16 | ||||
-rw-r--r-- | memtester.8 | 92 | ||||
-rw-r--r-- | memtester.c | 350 | ||||
-rw-r--r-- | memtester.h | 22 | ||||
-rw-r--r-- | sizes.h | 38 | ||||
-rw-r--r-- | tests.c | 525 | ||||
-rw-r--r-- | tests.h | 39 | ||||
-rw-r--r-- | trycpp.c | 7 | ||||
-rw-r--r-- | types.h | 36 | ||||
-rwxr-xr-x | warn-auto.sh | 2 |
22 files changed, 2000 insertions, 0 deletions
@@ -0,0 +1,7 @@ +* On some platforms, a few of the initial output messages don't format
+ correctly, due to %llu or %tx not being a supported printf format. This
+ is harmless.
+
+If you spot any other bugs in the software or documentation, please ensure
+you're using the latest version from http://pyropus.ca/software/memtester/ ,
+then email me at <charlesc-memtest-bugs@pyropus.ca> so that I can correct it.
diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..987f36a --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,120 @@ +Version 4.2.2 +22 July 2011 + -add progress message for one more errno value (EAGAIN) in response to failed + mlock; BSDs use this to indicate the lock failed due to being over a system + or process limit, much like ENOMEM. + + Version 4.2.1 +3 October 2010 + -fix offsets/addresses were not being reported correctly in test failure + messages. Thanks: Anton Sergeev. + +Version 4.2.0 +30 July 2010 + -define _FILE_OFFSET_BITS to 64 by default in conf-cc, which causes some + 32-bit systems with larger-than-32-bit address spaces to have a 64-bit off_t, + allowing testing of larger chunks of memory. Thanks to Steven A. Falco for + the suggestion. Let me know if this definition causes problems for anyone. + -add tests of 8-bit-wide and 16-bit-wide random writes, to enable verifying + the correct operation of hardware. Thanks: Dick Hollenbeck. If these tests + trigger unaligned access problems on your platform, you can eliminate these + tests by removing the -DTEST_NARROW_WRITES definition from the conf-cc file. + +Version 4.1.3 +28 February 2010 + -fix 64-bit data patterns with some versions of gcc. Thanks: Tony Battersby. + -clarify `make install` in readme. Thanks: Marc Lobelle. + +Version 4.1.2 +28 July 2009 + -fix portability issue with MAP_LOCKED flag. Thanks: Scott Haneda. + -remove debugging output accidentally left in v.4.1.0. + -cleanups + +Version 4.1.1 +24 July 2009 + + -memtester.h was missing from the 4.1.0 tarball; release update to fix that. + Thanks: Owen Leonard. + +Version 4.1.0 +23 July 2009 + + -added the ability to test a specific physical region of memory (by mmap'ing + /dev/mem) with the new -p option, which takes a hex starting address as a + value. This is mostly of use to developers trying to verify memory or I/O + mapped devices (on an embedded system, for instance). Thanks: Allon Stern. + -re-add the ability to set a suffix on the memory to allocate: "3G", "128K", etc, + mostly for use with the above new feature, where the "memory" to be tested is + less than a megabyte, but also useful for users wanting to test many gigabytes; + you no longer have to do the conversion-to-megs in your head. + -documentation updates and clarifications. + +Version 4.0.8 +21 November 2007 + + -add a startup check for amount of memory being greater than the possible + address space; prevents user confusion on 32-bit systems that use addressing + tricks to have >4GB total system memory. Thanks: Michael Kelly. + -documentation updates + +Version 4.0.7 +13 May 2007 + + -fix a bug in the align-to-page logic which may have prevented memtester + from mlock()ing the memory it was trying to test on some systems. + Thanks: Baif Chen. + +Version 4.0.6 +15 November 2006 + + -test algorithm improvement: the walking 0 bits test was only walking + the 0 bit in one direction, instead of walking it up and back down + the line the way it was intended to. Thanks: Tim Rule. + -formatting cleanups. + +Version 4.0.5 +10 March 2005 + + -change to the method of allocating and locking memory; if we get EPERM + when trying to mlock(), reset the amount of memory desired to the original + amount and try again without mlock(). The reason for this is that on many + systems, mlock() won't return EPERM until after having returned ENOMEM for + a larger amount. The new behaviour allows processes without mlock privileges + to still test the fully-specified amount or as much memory as can be + allocated. Thanks for the suggestion and testing to Dan Bradley. + +Version 4.0.4 +26 August 2004 + + -make memtester's exit code meaningful. See the manpage for its meaning. + Thanks to Wurzel Parsons-Keir, who sent a patch for the code, so I only had + to document it. + +Version 4.0.3 +10 August 2004 + + -small changes to enable building with dietlibc and a few other environments + that don't even attempt to provide the various Posix definitions. + -cosmetic fixes to output. + -restore the reduce-and-retry loop of memory locking from version 2. + +Version 4.0.2 +9 August 2004 + + -add manpage + +Version 4.0.1 +8 August 2004 + + -fix cosmetic bugs in output + +Version 4.0.0 +7 August 2004 + + -rewrite to clean up the code (previously an ugly hack), for 64-bit + cleanliness + -change build system to build on (hopefully) any platform. Previous + versions required hackery on some systems. + +Version 3 not publicly released. @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a271bf5 --- /dev/null +++ b/Makefile @@ -0,0 +1,84 @@ +# +# Makefile for memtester by Charles Cazabon. +# +# Copyright (C) 1999 Simon Kirby. +# Copyright (C) 1999-2009 Charles Cazabon. +# Licensed under the GNU General Public License version 2. See the file +# COPYING for details. +# + +# You don't need to edit these; change the contents of the conf-cc and conf-ld +# files if you need to change the compile/link commands. See the README for +# more information. +CC = $(shell head -n 1 conf-cc) +LD = $(shell head -n 1 conf-ld) + +SOURCES = memtester.c tests.c +OBJECTS = $(SOURCES:.c=.o) +HEADERS = memtester.h +TARGETS = *.o compile load auto-ccld.sh find-systype make-compile make-load systype extra-libs +INSTALLPATH = /usr/local + +# +# Targets +# +all: memtester + +install: all + mkdir -m 755 -p $(INSTALLPATH)/{bin,man/man8} + install -m 755 memtester $(INSTALLPATH)/bin/ + gzip -c memtester.8 >memtester.8.gz ; install -m 644 memtester.8.gz $(INSTALLPATH)/man/man8/ + +auto-ccld.sh: \ +conf-cc conf-ld warn-auto.sh + ( cat warn-auto.sh; \ + echo CC=\'`head -1 conf-cc`\'; \ + echo LD=\'`head -1 conf-ld`\' \ + ) > auto-ccld.sh + +compile: \ +make-compile warn-auto.sh systype + ( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \ + compile + chmod 755 compile + +find-systype: \ +find-systype.sh auto-ccld.sh + cat auto-ccld.sh find-systype.sh > find-systype + chmod 755 find-systype + +make-compile: \ +make-compile.sh auto-ccld.sh + cat auto-ccld.sh make-compile.sh > make-compile + chmod 755 make-compile + +make-load: \ +make-load.sh auto-ccld.sh + cat auto-ccld.sh make-load.sh > make-load + chmod 755 make-load + +systype: \ +find-systype trycpp.c + ./find-systype > systype + +extra-libs: \ +extra-libs.sh systype + ./extra-libs.sh "`cat systype`" >extra-libs + +load: \ +make-load warn-auto.sh systype + ( cat warn-auto.sh; ./make-load "`cat systype`" ) > load + chmod 755 load + +clean: + rm -f memtester $(TARGETS) $(OBJECTS) core + +memtester: \ +$(OBJECTS) memtester.c tests.h tests.c tests.h conf-cc Makefile load extra-libs + ./load memtester tests.o `cat extra-libs` + +memtester.o: memtester.c tests.h conf-cc Makefile compile + ./compile memtester.c + +tests.o: tests.c tests.h conf-cc Makefile compile + ./compile tests.c @@ -0,0 +1,115 @@ + memtester + + Utility to test for faulty memory subsystem. + + by Charles Cazabon <charlesc-memtester@pyropus.ca> + + Copyright 1999 Simon Kirby. + Version 2 Copyright 1999 Charles Cazabon. + Version 3 not publicly released. + Version 4 rewrite: + Copyright 2004-2010 Charles Cazabon. + Licensed under the terms of the GNU General Public License version 2 (only). + See the file COPYING for details. + + + About memtester + + memtester is a utility for testing the memory subsystem in a computer to + determine if it is faulty. The original source was by Simon Kirby + <sim@stormix.com>. I have by this time completely rewritten the + original source, and added many additional tests to help catch + borderline memory. I also rewrote the original tests (which catch + mainly memory bits which are stuck permanently high or low) so that + they run approximately an order of magnitude faster. + + The version 4 rewrite was mainly to accomplish three things: + + (1) the previous code was basically a hack, and was ugly. + (2) to make the code more portable. The previous version required some + hackery to compile on some systems. + (3) to make the code fully 64-bit aware. The previous version worked + on 64-bit systems, but did not fully stress the memory subsystems + on them -- this version should be better at stress-testing 64-bit + systems. + + Building memtester + + memtester is currently only distributed in source-code form. Building + it, however, is simple -- just type `make`. There's no `configure` script + or anything like that. + + If you have a really strange system/toolchain, you might need to edit the + conf-cc or conf-ld files, but try to build it without changes first. + For example, if you want to cross-compile with `armgcc`, you would edit + conf-cc and conf-ld to use `armgcc` instead of `cc`. You can also change + the contents of these files for other reasons; for example, if your + compiler isn't in your PATH, you could change it to use `/path/to/cc` or + similar. + + You can run the resulting binary from anywhere, but if you want to install + it and the manpage to /usr/local/, `make install` will do that. Edit + INSTALLPATH in the makefile if you prefer a different location. + + I've successfully built and run memtester 4 on the following systems: + + HP Tru64 Unix 4.0g (Alpha) + HP Tru64 Unix 5.1b (Alpha) + HP-UX 11i 11.11 (PA-RISC) + HP-UX 11i 11.23 (64-bit Itanium) + Debian GNU/Linux 3.0 (various) + other 32-bit Linux (RedHat, SuSE, Ubuntu, etc) (various) + RedHat Enterprise Linux/CentOS (64-bit AMD Opteron) + FreeBSD 4.9 (32-bit Intel) + FreeBSD 5.1 (64-bit Alpha) + NetBSD 1.6 (32-bit Intel) + Darwin (OS X) 7.5.0 (32-bit PowerPC) + OS X Leopard/Panther/whatever -- 32- or 64-bit, PPC or x86 + + It should, however, work on other Unix-like systems -- I simply don't + have access to systems running Solaris, AIX, etc. at the moment. + If you have trouble building memtester on your system, please report it + to me so I can fix this. + + Using memtester + + Usage is simple for the basic case. As root, run the resulting memtester + binary with the following commandline: + + memtester <memory> [runs] + + where <memory> is the amount of memory to test, in megabytes by default. + You can optionally include a suffix of B, K, M, or G (for bytes, + kilobytes, megabytes, and gigabytes respectively). + [runs] is an optional limit to the number of runs through all tests. + + An optional "-p physaddr" argument available to cause memtester to test + memory starting at a specific physical memory address (by mmap'ing + /dev/mem starting at an offset of `physaddr`, which is given in hex). + Note: the memory specified will be overwritten during testing; you + therefore *cannot* specify a region belonging to the kernel or other + applications without causing the other process or entire system to + crash). If you use this option, it is up to you to ensure the specified + memory is safe to overwrite. That makes this option mostly of use for + testing memory-mapped I/O devices and similar. Thanks to Allon Stern + for the idea behind this feature. For example, if you want to test a + bank of RAM or device which is 64kbytes in size and starts at physical + address 0x0C0000, you would run memtester as follows: + + memtester -p 0x0c0000 64k [runs] + + memtester must run as user root so that it can lock its pages into + memory. If memtester fails to lock its pages, it will issue a warning and + continue regardless. Testing without the memory being locked is generally + very slow and not particularly accurate, as you'll end up testing the same + memory over and over as the system swaps the larger region. + + Current Version + + The current version of memtester should be available at + http://pyropus.ca/software/memtester/ + + Questions, comments, and feature requests should be + directed to me at <charlesc-memtester@pyropus.ca>. Read BUGS to report + bugs found in memtester. + diff --git a/README.tests b/README.tests new file mode 100644 index 0000000..fd35b57 --- /dev/null +++ b/README.tests @@ -0,0 +1,38 @@ +About the Tests +--------------- + +The following tests are from the original version, updated simply for speed +and rewritten to fit the new framework of the program. These tests will +mainly catch memory errors due to bad bits which are permanently stuck high +or low: + Random value + XOR comparison + SUB comparison + MUL comparison + DIV comparison + OR comparison + AND comparison + +The following tests were implemented by me, and will do a slightly better job +of catching flaky bits, which may or may not hold a true value: + Sequential Increment + Block Sequential + Solid Bits + +The remaining tests were also implemented by me, and are designed to catch +bad bits which are dependent on the current values of surrounding bits in either +the same word32, or in the preceding and succeeding word32s. + Bit Flip + Checkerboard + Walking Ones + Walking Zeroes + Bit Spread + +There is also a test (Stuck Address) which is run first. It determines if the +memory locations the program attempts to access are addressed properly or not. +If this test reports errors, there is almost certainly a problem somewhere in +the memory subsystem. Results from the rest of the tests cannot be considered +accurate if this test fails: + Stuck Address + +Usage information is summarized in the file README, and in the man page. @@ -0,0 +1,3 @@ +cc -O2 -DPOSIX -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64 -DTEST_NARROW_WRITES -c + +This will be used to compile .c files. @@ -0,0 +1,3 @@ +cc -s + +This will be used to link .o files into an executable. diff --git a/extra-libs.sh b/extra-libs.sh new file mode 100755 index 0000000..d1bc718 --- /dev/null +++ b/extra-libs.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +case "$1" in +osf1-*) + # OSF/1 (Tru64) needs /usr/lib/librt.a for mlock() + echo /usr/lib/librt.a + ;; +unix_sv*) ;; +irix64-*) ;; +irix-*) ;; +dgux-*) ;; +hp-ux-*) ;; +sco*) ;; +*) + ;; +esac diff --git a/find-systype.sh b/find-systype.sh new file mode 100755 index 0000000..16266d3 --- /dev/null +++ b/find-systype.sh @@ -0,0 +1,144 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null +sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" + kern="" + ;; + freebsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + netbsd) + # see above about bsd 4.4 + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + $CC -c trycpp.c + $LD -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro +esac + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' diff --git a/make-compile.sh b/make-compile.sh new file mode 100755 index 0000000..a1eb501 --- /dev/null +++ b/make-compile.sh @@ -0,0 +1 @@ +echo exec "$CC" -c '${1+"$@"}' diff --git a/make-load.sh b/make-load.sh new file mode 100755 index 0000000..de07d2e --- /dev/null +++ b/make-load.sh @@ -0,0 +1,2 @@ +echo 'main="$1"; shift' +echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}' diff --git a/make-makelib.sh b/make-makelib.sh new file mode 100755 index 0000000..d6b7c8c --- /dev/null +++ b/make-makelib.sh @@ -0,0 +1,16 @@ +echo 'main="$1"; shift' +echo 'rm -f "$main"' +echo 'ar cr "$main" ${1+"$@"}' + +case "$1" in +sunos-5.*) ;; +unix_sv*) ;; +irix64-*) ;; +irix-*) ;; +dgux-*) ;; +hp-ux-*) ;; +sco*) ;; +*) + echo 'ranlib "$main"' + ;; +esac diff --git a/memtester.8 b/memtester.8 new file mode 100644 index 0000000..974ecd5 --- /dev/null +++ b/memtester.8 @@ -0,0 +1,92 @@ +.TH memtester "8" "July 2009" "memtester 4" "Maintenance Commands" +.SH NAME +memtester \- stress test to find memory subsystem faults. +.SH SYNOPSIS +.B memtester +[\f -p PHYSADDR\fR] +<\fIMEMORY\fR> +[\fIITERATIONS\fR] +.SH DESCRIPTION +.\" Add any additional description here +.PP +memtester is an effective userspace tester for stress-testing the memory +subsystem. It is very effective at finding intermittent and non-deterministic +faults. Note that problems in other hardware areas (overheating CPU, +out-of-specification power supply, etc.) can cause intermittent memory faults, +so it is still up to you to determine where the fault lies through normal +hardware diagnostic procedures; memtester just helps you determine whether +a problem exists. +.PP +memtester will malloc(3) the amount of memory specified, if possible. If +this fails, it will decrease the amount of memory requested until it succeeds. +It will then attempt to mlock(3) this memory; if it cannot do so, testing +will be slower and much less effective. Run memtester as root so that it +can mlock the memory it tests. +.PP +Note that the maximum amount of memory that memtester can test will be less +than the total amount of memory installed in the system; the operating system, +libraries, and other system limits take some of the available memory. +memtester is also limited to the amount of memory available to a single +process; for example, on 32-bit machines with more than 4GB of memory, +memtester is still limited to less than 4GB. +.PP +Note that it is up to you to know how much memory you can safely allocate +for testing. If you attempt to allocate more memory than is available, +memtester should figure that out, reduce the amount slightly, and try again. +However, this can lead to memtester successfully allocating and mlocking +essentially all free memory on the system -- if other programs are running, +this can lead to excessive swapping and slowing the system down to the point +that it is difficult to use. If the system allows allocation of more memory +than is actually available (overcommit), it may lead to a deadlock, where +the system halts. If the system has an out-of-memory process killer (like +Linux), memtester or another process may be killed by the OOM killer. +.PP +So choose wisely. +.PP +.SH OPTIONS +.TP +\f -p PHYSADDR\fR +tells memtester to test a specific region of memory starting at physical +address PHYSADDR (given in hex), by mmap(2)ing /dev/mem. This is mostly of +use to hardware developers, for testing memory-mapped I/O devices and similar. +Note that the memory region will be overwritten during testing, so it is not +safe to specify memory which is allocated for the system or for other +applications; doing so will cause them to crash. If you absolutely must test +a particular region of actual physical memory, arrange to have that memory +allocated by your test software, and hold it in this allocated state, then +run memtester on it with this option. +.TP +\fIMEMORY\fR +the amount of memory to allocate and test, in megabytes by default. You can +include a suffix of B, K, M, or G to indicate bytes, kilobytes, megabytes, or +gigabytes respectively. +.TP +\fIITERATIONS\fR +(optional) number of loops to iterate through. Default is infinite. +.SH NOTE +.PP +memtester must be run with root privileges to mlock(3) its pages. Testing +memory without locking the pages in place is mostly pointless and slow. +.SH EXIT CODE +.PP +memtester's exit code is 0 when everything works properly. Otherwise, +it is the logical OR of the following values: +.TP +\f0x01 +error allocating or locking memory, or invocation error +.TP +\f0x02 +error during stuck address test +.TP +\f0x04 +error during one of the other tests +.SH AUTHOR +Written by Charles Cazabon. +.SH "REPORTING BUGS" +Report bugs to <charlesc-memtester-bugs@pyropus.ca>. +.PP +.SH COPYRIGHT +Copyright \(co 2009 Charles Cazabon +.br +This is free software; see the file COPYING for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/memtester.c b/memtester.c new file mode 100644 index 0000000..c6ca59c --- /dev/null +++ b/memtester.c @@ -0,0 +1,350 @@ +/* + * memtester version 4 + * + * Very simple but very effective user-space memory tester. + * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> + * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca> + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + */ + +#define __version__ "4.2.2" + +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include "types.h" +#include "sizes.h" +#include "tests.h" + +#define EXIT_FAIL_NONSTARTER 0x01 +#define EXIT_FAIL_ADDRESSLINES 0x02 +#define EXIT_FAIL_OTHERTEST 0x04 + +struct test tests[] = { + { "Random Value", test_random_value }, + { "Compare XOR", test_xor_comparison }, + { "Compare SUB", test_sub_comparison }, + { "Compare MUL", test_mul_comparison }, + { "Compare DIV",test_div_comparison }, + { "Compare OR", test_or_comparison }, + { "Compare AND", test_and_comparison }, + { "Sequential Increment", test_seqinc_comparison }, + { "Solid Bits", test_solidbits_comparison }, + { "Block Sequential", test_blockseq_comparison }, + { "Checkerboard", test_checkerboard_comparison }, + { "Bit Spread", test_bitspread_comparison }, + { "Bit Flip", test_bitflip_comparison }, + { "Walking Ones", test_walkbits1_comparison }, + { "Walking Zeroes", test_walkbits0_comparison }, +#ifdef TEST_NARROW_WRITES + { "8-bit Writes", test_8bit_wide_random }, + { "16-bit Writes", test_16bit_wide_random }, +#endif + { NULL, NULL } +}; + +/* Sanity checks and portability helper macros. */ +#ifdef _SC_VERSION +void check_posix_system(void) { + if (sysconf(_SC_VERSION) < 198808L) { + fprintf(stderr, "A POSIX system is required. Don't be surprised if " + "this craps out.\n"); + fprintf(stderr, "_SC_VERSION is %lu\n", sysconf(_SC_VERSION)); + } +} +#else +#define check_posix_system() +#endif + +#ifdef _SC_PAGE_SIZE +int memtester_pagesize(void) { + int pagesize = sysconf(_SC_PAGE_SIZE); + if (pagesize == -1) { + perror("get page size failed"); + exit(EXIT_FAIL_NONSTARTER); + } + printf("pagesize is %ld\n", (long) pagesize); + return pagesize; +} +#else +int memtester_pagesize(void) { + printf("sysconf(_SC_PAGE_SIZE) not supported; using pagesize of 8192\n"); + return 8192; +} +#endif + +/* Some systems don't define MAP_LOCKED. Define it to 0 here + so it's just a no-op when ORed with other constants. */ +#ifndef MAP_LOCKED + #define MAP_LOCKED 0 +#endif + +/* Function declarations */ +void usage(char *me); + +/* Global vars - so tests have access to this information */ +int use_phys = 0; +off_t physaddrbase = 0; + +/* Function definitions */ +void usage(char *me) { + fprintf(stderr, "\nUsage: %s [-p physaddrbase] <mem>[B|K|M|G] [loops]\n", me); + exit(EXIT_FAIL_NONSTARTER); +} + +int main(int argc, char **argv) { + ul loops, loop, i; + size_t pagesize, wantraw, wantmb, wantbytes, wantbytes_orig, bufsize, + halflen, count; + char *memsuffix, *addrsuffix, *loopsuffix; + ptrdiff_t pagesizemask; + void volatile *buf, *aligned; + ulv *bufa, *bufb; + int do_mlock = 1, done_mem = 0; + int exit_code = 0; + int memfd, opt, memshift; + size_t maxbytes = -1; /* addressable memory, in bytes */ + size_t maxmb = (maxbytes >> 20) + 1; /* addressable memory, in MB */ + + printf("memtester version " __version__ " (%d-bit)\n", UL_LEN); + printf("Copyright (C) 2010 Charles Cazabon.\n"); + printf("Licensed under the GNU General Public License version 2 (only).\n"); + printf("\n"); + check_posix_system(); + pagesize = memtester_pagesize(); + pagesizemask = (ptrdiff_t) ~(pagesize - 1); + printf("pagesizemask is 0x%tx\n", pagesizemask); + + while ((opt = getopt(argc, argv, "p:")) != -1) { + switch (opt) { + case 'p': + errno = 0; + physaddrbase = (off_t) strtoull(optarg, &addrsuffix, 16); + if (errno != 0) { + fprintf(stderr, + "failed to parse physaddrbase arg; should be hex " + "address (0x123...)\n"); + usage(argv[0]); /* doesn't return */ + } + if (*addrsuffix != '\0') { + /* got an invalid character in the address */ + fprintf(stderr, + "failed to parse physaddrbase arg; should be hex " + "address (0x123...)\n"); + usage(argv[0]); /* doesn't return */ + } + if (physaddrbase & (pagesize - 1)) { + fprintf(stderr, + "bad physaddrbase arg; does not start on page " + "boundary\n"); + usage(argv[0]); /* doesn't return */ + } + /* okay, got address */ + use_phys = 1; + break; + default: /* '?' */ + usage(argv[0]); /* doesn't return */ + } + } + + if (optind >= argc) { + fprintf(stderr, "need memory argument, in MB\n"); + usage(argv[0]); /* doesn't return */ + } + + errno = 0; + wantraw = (size_t) strtoul(argv[optind], &memsuffix, 0); + if (errno != 0) { + fprintf(stderr, "failed to parse memory argument"); + usage(argv[0]); /* doesn't return */ + } + switch (*memsuffix) { + case 'G': + case 'g': + memshift = 30; /* gigabytes */ + break; + case 'M': + case 'm': + memshift = 20; /* megabytes */ + break; + case 'K': + case 'k': + memshift = 10; /* kilobytes */ + break; + case 'B': + case 'b': + memshift = 0; /* bytes*/ + break; + case '\0': /* no suffix */ + memshift = 20; /* megabytes */ + break; + default: + /* bad suffix */ + usage(argv[0]); /* doesn't return */ + } + wantbytes_orig = wantbytes = ((size_t) wantraw << memshift); + wantmb = (wantbytes_orig >> 20); + optind++; + if (wantmb > maxmb) { + fprintf(stderr, "This system can only address %llu MB.\n", (ull) maxmb); + exit(EXIT_FAIL_NONSTARTER); + } + if (wantbytes < pagesize) { + fprintf(stderr, "bytes %ld < pagesize %ld -- memory argument too large?\n", + wantbytes, pagesize); + exit(EXIT_FAIL_NONSTARTER); + } + + if (optind >= argc) { + loops = 0; + } else { + errno = 0; + loops = strtoul(argv[optind], &loopsuffix, 0); + if (errno != 0) { + fprintf(stderr, "failed to parse number of loops"); + usage(argv[0]); /* doesn't return */ + } + if (*loopsuffix != '\0') { + fprintf(stderr, "loop suffix %c\n", *loopsuffix); + usage(argv[0]); /* doesn't return */ + } + } + + printf("want %lluMB (%llu bytes)\n", (ull) wantmb, (ull) wantbytes); + buf = NULL; + + if (use_phys) { + memfd = open("/dev/mem", O_RDWR | O_SYNC); + if (memfd == -1) { + perror("failed to open /dev/mem for physical memory"); + exit(EXIT_FAIL_NONSTARTER); + } + buf = (void volatile *) mmap(0, wantbytes, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_LOCKED, memfd, + physaddrbase); + if (buf == MAP_FAILED) { + perror("failed to mmap /dev/mem for physical memory"); + exit(EXIT_FAIL_NONSTARTER); + } + + if (mlock((void *) buf, wantbytes) < 0) { + fprintf(stderr, "failed to mlock mmap'ed space\n"); + do_mlock = 0; + } + + bufsize = wantbytes; /* accept no less */ + aligned = buf; + done_mem = 1; + } + + while (!done_mem) { + while (!buf && wantbytes) { + buf = (void volatile *) malloc(wantbytes); + if (!buf) wantbytes -= pagesize; + } + bufsize = wantbytes; + printf("got %lluMB (%llu bytes)", (ull) wantbytes >> 20, + (ull) wantbytes); + fflush(stdout); + if (do_mlock) { + printf(", trying mlock ..."); + fflush(stdout); + if ((size_t) buf % pagesize) { + /* printf("aligning to page -- was 0x%tx\n", buf); */ + aligned = (void volatile *) ((size_t) buf & pagesizemask) + pagesize; + /* printf(" now 0x%tx -- lost %d bytes\n", aligned, + * (size_t) aligned - (size_t) buf); + */ + bufsize -= ((size_t) aligned - (size_t) buf); + } else { + aligned = buf; + } + /* Try mlock */ + if (mlock((void *) aligned, bufsize) < 0) { + switch(errno) { + case EAGAIN: /* BSDs */ + printf("over system/pre-process limit, reducing...\n"); + free((void *) buf); + buf = NULL; + wantbytes -= pagesize; + break; + case ENOMEM: + printf("too many pages, reducing...\n"); + free((void *) buf); + buf = NULL; + wantbytes -= pagesize; + break; + case EPERM: + printf("insufficient permission.\n"); + printf("Trying again, unlocked:\n"); + do_mlock = 0; + free((void *) buf); + buf = NULL; + wantbytes = wantbytes_orig; + break; + default: + printf("failed for unknown reason.\n"); + do_mlock = 0; + done_mem = 1; + } + } else { + printf("locked.\n"); + done_mem = 1; + } + } else { + done_mem = 1; + printf("\n"); + } + } + + if (!do_mlock) fprintf(stderr, "Continuing with unlocked memory; testing " + "will be slower and less reliable.\n"); + + halflen = bufsize / 2; + count = halflen / sizeof(ul); + bufa = (ulv *) aligned; + bufb = (ulv *) ((size_t) aligned + halflen); + + for(loop=1; ((!loops) || loop <= loops); loop++) { + printf("Loop %lu", loop); + if (loops) { + printf("/%lu", loops); + } + printf(":\n"); + printf(" %-20s: ", "Stuck Address"); + fflush(stdout); + if (!test_stuck_address(aligned, bufsize / sizeof(ul))) { + printf("ok\n"); + } else { + exit_code |= EXIT_FAIL_ADDRESSLINES; + } + for (i=0;;i++) { + if (!tests[i].name) break; + printf(" %-20s: ", tests[i].name); + if (!tests[i].fp(bufa, bufb, count)) { + printf("ok\n"); + } else { + exit_code |= EXIT_FAIL_OTHERTEST; + } + fflush(stdout); + } + printf("\n"); + fflush(stdout); + } + if (do_mlock) munlock((void *) aligned, bufsize); + printf("Done.\n"); + fflush(stdout); + exit(exit_code); +} diff --git a/memtester.h b/memtester.h new file mode 100644 index 0000000..b7e7079 --- /dev/null +++ b/memtester.h @@ -0,0 +1,22 @@ +/* + * Very simple (yet, for some reason, very effective) memory tester. + * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> + * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca> + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains the declarations for external variables from the main file. + * See other comments in that file. + * + */ + +#include <sys/types.h> + +/* extern declarations. */ + +extern int use_phys; +extern off_t physaddrbase; + @@ -0,0 +1,38 @@ +/* + * Very simple but very effective user-space memory tester. + * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> + * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca> + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains some macro definitions for handling 32/64 bit platforms. + * + */ + +#include <limits.h> + +#define rand32() ((unsigned int) rand() | ( (unsigned int) rand() << 16)) + +#if (ULONG_MAX == 4294967295UL) + #define rand_ul() rand32() + #define UL_ONEBITS 0xffffffff + #define UL_LEN 32 + #define CHECKERBOARD1 0x55555555 + #define CHECKERBOARD2 0xaaaaaaaa + #define UL_BYTE(x) ((x | x << 8 | x << 16 | x << 24)) +#elif (ULONG_MAX == 18446744073709551615ULL) + #define rand64() (((ul) rand32()) << 32 | ((ul) rand32())) + #define rand_ul() rand64() + #define UL_ONEBITS 0xffffffffffffffffUL + #define UL_LEN 64 + #define CHECKERBOARD1 0x5555555555555555 + #define CHECKERBOARD2 0xaaaaaaaaaaaaaaaa + #define UL_BYTE(x) (((ul)x | (ul)x<<8 | (ul)x<<16 | (ul)x<<24 | (ul)x<<32 | (ul)x<<40 | (ul)x<<48 | (ul)x<<56)) +#else + #error long on this platform is not 32 or 64 bits +#endif + + @@ -0,0 +1,525 @@ +/* + * Very simple but very effective user-space memory tester. + * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> + * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca> + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains the functions for the actual tests, called from the + * main routine in memtester.c. See other comments in that file. + * + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> + +#include "types.h" +#include "sizes.h" +#include "memtester.h" + +char progress[] = "-\\|/"; +#define PROGRESSLEN 4 +#define PROGRESSOFTEN 2500 +#define ONE 0x00000001L + +/* Function definitions. */ + +int compare_regions(ulv *bufa, ulv *bufb, size_t count) { + int r = 0; + size_t i; + ulv *p1 = bufa; + ulv *p2 = bufb; + off_t physaddr; + + for (i = 0; i < count; i++, p1++, p2++) { + if (*p1 != *p2) { + if (use_phys) { + physaddr = physaddrbase + (i * sizeof(ul)); + fprintf(stderr, + "FAILURE: 0x%08lx != 0x%08lx at physical address " + "0x%08lx.\n", + (ul) *p1, (ul) *p2, physaddr); + } else { + fprintf(stderr, + "FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n", + (ul) *p1, (ul) *p2, (ul) (i * sizeof(ul))); + } + /* printf("Skipping to next test..."); */ + r = -1; + } + } + return r; +} + +int test_stuck_address(ulv *bufa, size_t count) { + ulv *p1 = bufa; + unsigned int j; + size_t i; + off_t physaddr; + + printf(" "); + fflush(stdout); + for (j = 0; j < 16; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + printf("setting %3u", j); + fflush(stdout); + for (i = 0; i < count; i++) { + *p1 = ((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1); + *p1++; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + fflush(stdout); + p1 = (ulv *) bufa; + for (i = 0; i < count; i++, p1++) { + if (*p1 != (((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1))) { + if (use_phys) { + physaddr = physaddrbase + (i * sizeof(ul)); + fprintf(stderr, + "FAILURE: possible bad address line at physical " + "address 0x%08lx.\n", + physaddr); + } else { + fprintf(stderr, + "FAILURE: possible bad address line at offset " + "0x%08lx.\n", + (ul) (i * sizeof(ul))); + } + printf("Skipping to next test...\n"); + fflush(stdout); + return -1; + } + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +int test_random_value(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + ul j = 0; + size_t i; + + putchar(' '); + fflush(stdout); + for (i = 0; i < count; i++) { + *p1++ = *p2++ = rand_ul(); + if (!(i % PROGRESSOFTEN)) { + putchar('\b'); + putchar(progress[++j % PROGRESSLEN]); + fflush(stdout); + } + } + printf("\b \b"); + fflush(stdout); + return compare_regions(bufa, bufb, count); +} + +int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ ^= q; + *p2++ ^= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ -= q; + *p2++ -= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ *= q; + *p2++ *= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_div_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + if (!q) { + q++; + } + *p1++ /= q; + *p2++ /= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_or_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ |= q; + *p2++ |= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_and_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ &= q; + *p2++ &= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i + q); + } + return compare_regions(bufa, bufb, count); +} + +int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + ul q; + size_t i; + + printf(" "); + fflush(stdout); + for (j = 0; j < 64; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + q = (j % 2) == 0 ? UL_ONEBITS : 0; + printf("setting %3u", j); + fflush(stdout); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + fflush(stdout); + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + ul q; + size_t i; + + printf(" "); + fflush(stdout); + for (j = 0; j < 64; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2; + printf("setting %3u", j); + fflush(stdout); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + fflush(stdout); + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + + printf(" "); + fflush(stdout); + for (j = 0; j < 256; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + fflush(stdout); + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (ul) UL_BYTE(j); + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + fflush(stdout); + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + + printf(" "); + fflush(stdout); + for (j = 0; j < UL_LEN * 2; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + fflush(stdout); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + *p1++ = *p2++ = ONE << j; + } else { /* Walk it back down. */ + *p1++ = *p2++ = ONE << (UL_LEN * 2 - j - 1); + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + fflush(stdout); + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + + printf(" "); + fflush(stdout); + for (j = 0; j < UL_LEN * 2; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + fflush(stdout); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + *p1++ = *p2++ = UL_ONEBITS ^ (ONE << j); + } else { /* Walk it back down. */ + *p1++ = *p2++ = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1)); + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + fflush(stdout); + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + + printf(" "); + fflush(stdout); + for (j = 0; j < UL_LEN * 2; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + fflush(stdout); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + *p1++ = *p2++ = (i % 2 == 0) + ? (ONE << j) | (ONE << (j + 2)) + : UL_ONEBITS ^ ((ONE << j) + | (ONE << (j + 2))); + } else { /* Walk it back down. */ + *p1++ = *p2++ = (i % 2 == 0) + ? (ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 + 1 - j)) + : UL_ONEBITS ^ (ONE << (UL_LEN * 2 - 1 - j) + | (ONE << (UL_LEN * 2 + 1 - j))); + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + fflush(stdout); + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j, k; + ul q; + size_t i; + + printf(" "); + fflush(stdout); + for (k = 0; k < UL_LEN; k++) { + q = ONE << k; + for (j = 0; j < 8; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + q = ~q; + printf("setting %3u", k * 8 + j); + fflush(stdout); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", k * 8 + j); + fflush(stdout); + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + return 0; +} + +#ifdef TEST_NARROW_WRITES +int test_8bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { + u8v *p1, *t; + ulv *p2; + int attempt; + unsigned int b, j = 0; + size_t i; + + putchar(' '); + fflush(stdout); + for (attempt = 0; attempt < 2; attempt++) { + if (attempt & 1) { + p1 = (u8v *) bufa; + p2 = bufb; + } else { + p1 = (u8v *) bufb; + p2 = bufa; + } + for (i = 0; i < count; i++) { + t = mword8.bytes; + *p2++ = mword8.val = rand_ul(); + for (b=0; b < UL_LEN/8; b++) { + *p1++ = *t++; + } + if (!(i % PROGRESSOFTEN)) { + putchar('\b'); + putchar(progress[++j % PROGRESSLEN]); + fflush(stdout); + } + } + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b \b"); + fflush(stdout); + return 0; +} + +int test_16bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { + u16v *p1, *t; + ulv *p2; + int attempt; + unsigned int b, j = 0; + size_t i; + + putchar( ' ' ); + fflush( stdout ); + for (attempt = 0; attempt < 2; attempt++) { + if (attempt & 1) { + p1 = (u16v *) bufa; + p2 = bufb; + } else { + p1 = (u16v *) bufb; + p2 = bufa; + } + for (i = 0; i < count; i++) { + t = mword16.u16s; + *p2++ = mword16.val = rand_ul(); + for (b = 0; b < UL_LEN/16; b++) { + *p1++ = *t++; + } + if (!(i % PROGRESSOFTEN)) { + putchar('\b'); + putchar(progress[++j % PROGRESSLEN]); + fflush(stdout); + } + } + if (compare_regions(bufa, bufb, count)) { + return -1; + } + } + printf("\b \b"); + fflush(stdout); + return 0; +} +#endif @@ -0,0 +1,39 @@ +/* + * Very simple yet very effective memory tester. + * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> + * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca> + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains the declarations for the functions for the actual tests, + * called from the main routine in memtester.c. See other comments in that + * file. + * + */ + +/* Function declaration. */ + +int test_stuck_address(unsigned long volatile *bufa, size_t count); +int test_random_value(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_xor_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_sub_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_mul_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_div_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_or_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_and_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_seqinc_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_solidbits_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_checkerboard_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_blockseq_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_walkbits0_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_walkbits1_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_bitspread_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_bitflip_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +#ifdef TEST_NARROW_WRITES +int test_8bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +int test_16bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); +#endif + diff --git a/trycpp.c b/trycpp.c new file mode 100644 index 0000000..d7d83ad --- /dev/null +++ b/trycpp.c @@ -0,0 +1,7 @@ +void main() +{ +#ifdef NeXT + printf("nextstep\n"); exit(0); +#endif + printf("unknown\n"); exit(0); +} @@ -0,0 +1,36 @@ +/* + * Very simple but very effective user-space memory tester. + * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> + * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca> + * Licensed under the terms of the GNU General Public License version 2 (only). + * See the file COPYING for details. + * + * This file contains typedefs, structure, and union definitions. + * + */ + +#include "sizes.h" + +typedef unsigned long ul; +typedef unsigned long long ull; +typedef unsigned long volatile ulv; +typedef unsigned char volatile u8v; +typedef unsigned short volatile u16v; + +struct test { + char *name; + int (*fp)(); +}; + +union { + unsigned char bytes[UL_LEN/8]; + ul val; +} mword8; + +union { + unsigned short u16s[UL_LEN/16]; + ul val; +} mword16; diff --git a/warn-auto.sh b/warn-auto.sh new file mode 100755 index 0000000..36d2313 --- /dev/null +++ b/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! |