├── .gitignore ├── BUGS ├── CHANGELOG ├── COPYING ├── Makefile ├── README ├── README.tests ├── conf-cc ├── conf-ld ├── extra-libs.sh ├── find-systype.sh ├── make-compile.sh ├── make-load.sh ├── make-makelib.sh ├── memtester.8 ├── memtester.c ├── memtester.h ├── output.c ├── output.h ├── sizes.h ├── tests.c ├── tests.h ├── trycpp.c ├── types.h └── warn-auto.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | auto-ccld.sh 3 | compile 4 | extra-libs 5 | find-systype 6 | load 7 | make-compile 8 | make-load 9 | memtester 10 | systype 11 | -------------------------------------------------------------------------------- /BUGS: -------------------------------------------------------------------------------- 1 | * On some platforms, a few of the initial output messages don't format 2 | correctly, due to %llu or %tx not being a supported printf format. This 3 | is harmless. 4 | 5 | If you spot any other bugs in the software or documentation, please ensure 6 | you're using the latest version from http://pyropus.ca/software/memtester/ , 7 | then email me at so that I can correct it. 8 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | Version 4.5.1 2 | 30 May 2021 3 | -documentation-only update. 4 | -add note to README about build problem with Tru64, with workaround. 5 | Thanks: Víctor Ostorga. 6 | 7 | Version 4.5.0 8 | 20 September 2020 9 | -add note to README about problems with HP/UX prior to v.11. Change code 10 | so that buffer still gets aligned even if you comment out the use of mlock() 11 | on such a platform. Thanks: Keith Monahan. 12 | -fix clear-buffer using incorrect param, causing spurious test failures. 13 | Thanks: Debin Dong. 14 | -fix shell-ism in Makefile. Thanks: Fabrice Fontaine. 15 | 16 | Version 4.3.0 17 | 9 June 2012 18 | -add ability to mmap a device other than /dev/mem, enabling easier testing 19 | of memory for hardware engineers et al if their system's kernel exports the 20 | memory they're interested in via /dev/mydevice or similar. Thanks: 21 | Jean-Noël Avila. 22 | -add ability to run only specified tests by setting the environment 23 | variable MEMTESTER_TEST_MASK to a bitmask of the indexes of the tests to be 24 | run. Thanks: Ian Alexander. 25 | 26 | Version 4.2.2 27 | 22 July 2011 28 | -add progress message for one more errno value (EAGAIN) in response to failed 29 | mlock; BSDs use this to indicate the lock failed due to being over a system 30 | or process limit, much like ENOMEM. 31 | 32 | Version 4.2.1 33 | 3 October 2010 34 | -fix offsets/addresses were not being reported correctly in test failure 35 | messages. Thanks: Anton Sergeev. 36 | 37 | Version 4.2.0 38 | 30 July 2010 39 | -define _FILE_OFFSET_BITS to 64 by default in conf-cc, which causes some 40 | 32-bit systems with larger-than-32-bit address spaces to have a 64-bit off_t, 41 | allowing testing of larger chunks of memory. Thanks to Steven A. Falco for 42 | the suggestion. Let me know if this definition causes problems for anyone. 43 | -add tests of 8-bit-wide and 16-bit-wide random writes, to enable verifying 44 | the correct operation of hardware. Thanks: Dick Hollenbeck. If these tests 45 | trigger unaligned access problems on your platform, you can eliminate these 46 | tests by removing the -DTEST_NARROW_WRITES definition from the conf-cc file. 47 | 48 | Version 4.1.3 49 | 28 February 2010 50 | -fix 64-bit data patterns with some versions of gcc. Thanks: Tony Battersby. 51 | -clarify `make install` in readme. Thanks: Marc Lobelle. 52 | 53 | Version 4.1.2 54 | 28 July 2009 55 | -fix portability issue with MAP_LOCKED flag. Thanks: Scott Haneda. 56 | -remove debugging output accidentally left in v.4.1.0. 57 | -cleanups 58 | 59 | Version 4.1.1 60 | 24 July 2009 61 | 62 | -memtester.h was missing from the 4.1.0 tarball; release update to fix that. 63 | Thanks: Owen Leonard. 64 | 65 | Version 4.1.0 66 | 23 July 2009 67 | 68 | -added the ability to test a specific physical region of memory (by mmap'ing 69 | /dev/mem) with the new -p option, which takes a hex starting address as a 70 | value. This is mostly of use to developers trying to verify memory or I/O 71 | mapped devices (on an embedded system, for instance). Thanks: Allon Stern. 72 | -re-add the ability to set a suffix on the memory to allocate: "3G", "128K", etc, 73 | mostly for use with the above new feature, where the "memory" to be tested is 74 | less than a megabyte, but also useful for users wanting to test many gigabytes; 75 | you no longer have to do the conversion-to-megs in your head. 76 | -documentation updates and clarifications. 77 | 78 | Version 4.0.8 79 | 21 November 2007 80 | 81 | -add a startup check for amount of memory being greater than the possible 82 | address space; prevents user confusion on 32-bit systems that use addressing 83 | tricks to have >4GB total system memory. Thanks: Michael Kelly. 84 | -documentation updates 85 | 86 | Version 4.0.7 87 | 13 May 2007 88 | 89 | -fix a bug in the align-to-page logic which may have prevented memtester 90 | from mlock()ing the memory it was trying to test on some systems. 91 | Thanks: Baif Chen. 92 | 93 | Version 4.0.6 94 | 15 November 2006 95 | 96 | -test algorithm improvement: the walking 0 bits test was only walking 97 | the 0 bit in one direction, instead of walking it up and back down 98 | the line the way it was intended to. Thanks: Tim Rule. 99 | -formatting cleanups. 100 | 101 | Version 4.0.5 102 | 10 March 2005 103 | 104 | -change to the method of allocating and locking memory; if we get EPERM 105 | when trying to mlock(), reset the amount of memory desired to the original 106 | amount and try again without mlock(). The reason for this is that on many 107 | systems, mlock() won't return EPERM until after having returned ENOMEM for 108 | a larger amount. The new behaviour allows processes without mlock privileges 109 | to still test the fully-specified amount or as much memory as can be 110 | allocated. Thanks for the suggestion and testing to Dan Bradley. 111 | 112 | Version 4.0.4 113 | 26 August 2004 114 | 115 | -make memtester's exit code meaningful. See the manpage for its meaning. 116 | Thanks to Wurzel Parsons-Keir, who sent a patch for the code, so I only had 117 | to document it. 118 | 119 | Version 4.0.3 120 | 10 August 2004 121 | 122 | -small changes to enable building with dietlibc and a few other environments 123 | that don't even attempt to provide the various Posix definitions. 124 | -cosmetic fixes to output. 125 | -restore the reduce-and-retry loop of memory locking from version 2. 126 | 127 | Version 4.0.2 128 | 9 August 2004 129 | 130 | -add manpage 131 | 132 | Version 4.0.1 133 | 8 August 2004 134 | 135 | -fix cosmetic bugs in output 136 | 137 | Version 4.0.0 138 | 7 August 2004 139 | 140 | -rewrite to clean up the code (previously an ugly hack), for 64-bit 141 | cleanliness 142 | -change build system to build on (hopefully) any platform. Previous 143 | versions required hackery on some systems. 144 | 145 | Version 3 not publicly released. 146 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 19yy 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) 19yy name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for memtester by Charles Cazabon. 3 | # 4 | # Copyright (C) 1999 Simon Kirby. 5 | # Copyright (C) 1999-2020 Charles Cazabon. 6 | # Licensed under the GNU General Public License version 2. See the file 7 | # COPYING for details. 8 | # 9 | 10 | # You don't need to edit these; change the contents of the conf-cc and conf-ld 11 | # files if you need to change the compile/link commands. See the README for 12 | # more information. 13 | CC = $(shell head -n 1 conf-cc) 14 | LD = $(shell head -n 1 conf-ld) 15 | 16 | SOURCES = memtester.c tests.c output.c 17 | OBJECTS = $(SOURCES:.c=.o) 18 | HEADERS = memtester.h 19 | TARGETS = *.o compile load auto-ccld.sh find-systype make-compile make-load systype extra-libs 20 | INSTALLPATH = /usr/local 21 | 22 | # 23 | # Targets 24 | # 25 | all: memtester 26 | 27 | install: all 28 | mkdir -m 755 -p $(INSTALLPATH)/bin 29 | install -m 755 memtester $(INSTALLPATH)/bin/ 30 | mkdir -m 755 -p $(INSTALLPATH)/man/man8 31 | gzip -c memtester.8 >memtester.8.gz ; install -m 644 memtester.8.gz $(INSTALLPATH)/man/man8/ 32 | 33 | auto-ccld.sh: \ 34 | conf-cc conf-ld warn-auto.sh 35 | ( cat warn-auto.sh; \ 36 | echo CC=\'`head -1 conf-cc`\'; \ 37 | echo LD=\'`head -1 conf-ld`\' \ 38 | ) > auto-ccld.sh 39 | 40 | compile: \ 41 | make-compile warn-auto.sh systype 42 | ( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \ 43 | compile 44 | chmod 755 compile 45 | 46 | find-systype: \ 47 | find-systype.sh auto-ccld.sh 48 | cat auto-ccld.sh find-systype.sh > find-systype 49 | chmod 755 find-systype 50 | 51 | make-compile: \ 52 | make-compile.sh auto-ccld.sh 53 | cat auto-ccld.sh make-compile.sh > make-compile 54 | chmod 755 make-compile 55 | 56 | make-load: \ 57 | make-load.sh auto-ccld.sh 58 | cat auto-ccld.sh make-load.sh > make-load 59 | chmod 755 make-load 60 | 61 | systype: \ 62 | find-systype trycpp.c 63 | ./find-systype > systype 64 | 65 | extra-libs: \ 66 | extra-libs.sh systype 67 | ./extra-libs.sh "`cat systype`" >extra-libs 68 | 69 | load: \ 70 | make-load warn-auto.sh systype 71 | ( cat warn-auto.sh; ./make-load "`cat systype`" ) > load 72 | chmod 755 load 73 | 74 | clean: 75 | rm -f memtester $(TARGETS) $(OBJECTS) core 76 | 77 | memtester: \ 78 | $(OBJECTS) memtester.c tests.h tests.c tests.h conf-cc Makefile load extra-libs 79 | ./load memtester tests.o output.o `cat extra-libs` 80 | 81 | memtester.o: memtester.c tests.h conf-cc Makefile compile 82 | ./compile memtester.c 83 | 84 | tests.o: tests.c tests.h conf-cc Makefile compile 85 | ./compile tests.c 86 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | memtester 2 | 3 | Utility to test for faulty memory subsystem. 4 | 5 | by Charles Cazabon 6 | 7 | Copyright 1999 Simon Kirby. 8 | Version 2 Copyright 1999 Charles Cazabon. 9 | Version 3 not publicly released. 10 | Version 4 rewrite: 11 | Copyright 2004-2020 Charles Cazabon. 12 | Licensed under the terms of the GNU General Public License version 2 (only). 13 | See the file COPYING for details. 14 | 15 | 16 | About memtester 17 | 18 | memtester is a utility for testing the memory subsystem in a computer to 19 | determine if it is faulty. The original source was by Simon Kirby 20 | . I have by this time completely rewritten the 21 | original source, and added many additional tests to help catch 22 | borderline memory. I also rewrote the original tests (which catch 23 | mainly memory bits which are stuck permanently high or low) so that 24 | they run approximately an order of magnitude faster. 25 | 26 | The version 4 rewrite was mainly to accomplish three things: 27 | 28 | (1) the previous code was basically a hack, and was ugly. 29 | (2) to make the code more portable. The previous version required some 30 | hackery to compile on some systems. 31 | (3) to make the code fully 64-bit aware. The previous version worked 32 | on 64-bit systems, but did not fully stress the memory subsystems 33 | on them -- this version should be better at stress-testing 64-bit 34 | systems. 35 | 36 | Building memtester 37 | 38 | memtester is currently only distributed in source-code form. Building 39 | it, however, is simple -- just type `make`. There's no `configure` script 40 | or anything like that. 41 | 42 | If you have a really strange system/toolchain, you might need to edit the 43 | conf-cc or conf-ld files, but try to build it without changes first. 44 | For example, if you want to cross-compile with `armgcc`, you would edit 45 | conf-cc and conf-ld to use `armgcc` instead of `cc`. You can also change 46 | the contents of these files for other reasons; for example, if your 47 | compiler isn't in your PATH, you could change it to use `/path/to/cc` or 48 | similar. 49 | 50 | You can run the resulting binary from anywhere, but if you want to install 51 | it and the manpage to /usr/local/, `make install` will do that. Edit 52 | INSTALLPATH in the makefile if you prefer a different location. 53 | 54 | I've successfully built and run memtester 4 on the following systems: 55 | 56 | HP Tru64 Unix 4.0g (Alpha) 57 | HP Tru64 Unix 5.1b (Alpha) 58 | HP-UX 11i 11.11 (PA-RISC) 59 | HP-UX 11i 11.23 (64-bit Itanium) 60 | Debian GNU/Linux 3.0 (various) 61 | other 32-bit Linux (RedHat, SuSE, Ubuntu, etc) (various) 62 | RedHat Enterprise Linux/CentOS (64-bit AMD Opteron) 63 | FreeBSD 4.9 (32-bit Intel) 64 | FreeBSD 5.1 (64-bit Alpha) 65 | NetBSD 1.6 (32-bit Intel) 66 | Darwin (OS X) 7.5.0 (32-bit PowerPC) 67 | OS X Leopard/Panther/whatever -- 32- or 64-bit, PPC or x86 68 | 69 | It should, however, work on other Unix-like systems -- I simply don't 70 | have access to systems running Solaris, AIX, etc. at the moment. 71 | If you have trouble building memtester on your system, please report it 72 | to me so I can fix this. 73 | 74 | Using memtester 75 | 76 | Usage is simple for the basic case. As root, run the resulting memtester 77 | binary with the following commandline: 78 | 79 | memtester [runs] 80 | 81 | where is the amount of memory to test, in megabytes by default. 82 | You can optionally include a suffix of B, K, M, or G (for bytes, 83 | kilobytes, megabytes, and gigabytes respectively). 84 | [runs] is an optional limit to the number of runs through all tests. 85 | 86 | An optional "-p physaddr" argument available to cause memtester to test 87 | memory starting at a specific physical memory address (by mmap(2)ing 88 | a device file representing physical memory (/dev/mem by default, but can 89 | be specified with the "-d device" option) starting at an offset of 90 | `physaddr`, which is given in hex). 91 | 92 | Note: the memory specified will be overwritten during testing; you 93 | therefore *cannot* specify a region belonging to the kernel or other 94 | applications without causing the other process or entire system to 95 | crash). If you use this option, it is up to you to ensure the specified 96 | memory is safe to overwrite. That makes this option mostly of use for 97 | testing memory-mapped I/O devices and similar. Thanks to Allon Stern 98 | for the idea behind this feature. For example, if you want to test a 99 | bank of RAM or device which is 64kbytes in size and starts at physical 100 | address 0x0C0000 through the normal /dev/mem, you would run memtester as 101 | follows: 102 | 103 | memtester -p 0x0c0000 64k [runs] 104 | 105 | If instead that device presented its memory as /dev/foodev at offset 106 | 0, you would run memtester instead as follows: 107 | 108 | memtester -p 0 -d /dev/foodev 64k [runs] 109 | 110 | Note that the "-d" option can only be specified in combination with "-p". 111 | 112 | memtester must run as user root so that it can lock its pages into 113 | memory. If memtester fails to lock its pages, it will issue a warning and 114 | continue regardless. Testing without the memory being locked is generally 115 | very slow and not particularly accurate, as you'll end up testing the same 116 | memory over and over as the system swaps the larger region. 117 | 118 | Current Version 119 | 120 | The current version of memtester should be available at 121 | http://pyropus.ca/software/memtester/ 122 | 123 | Questions, comments, and feature requests should be 124 | directed to me at . Read BUGS to report 125 | bugs found in memtester. 126 | 127 | Platform Compatibility Notes 128 | 129 | As mentioned, memtester v4 was tested with a wide variety of Unix- and 130 | Unix-like systems. However, at least two issues with ancient HP/UX 131 | versions, and one with Tru64, have come up since. 132 | 133 | HP/UX versions prior to v11 do not support mlock() and will fail with an 134 | invalid syscall error at runtime. If you're building on HP/UX v10.20 or 135 | similar, change `int do_mlock = 1` around line 128 of memtester.c to 136 | `int do_mlock = 0` and rebuild. 137 | They also are missing strtoull() from C99. To fix this build error, 138 | add `#define strtoull __strtoull` to the top of memtester.c; this should 139 | at least work with a GCC toolchain. 140 | 141 | Tru64 is missing strtoull() from C99. To fix this build error when using 142 | cc, add `#define strtoull strtoul` to the top of memtester.c; this is 143 | safe because long on Tru64 is 64-bits. This build problem could be dealt 144 | with automatically, but I don't particularly want to invest the necessary 145 | time, because Tru64 went out of support in 2012. In addition, I no longer 146 | have access to a build machine for testing on this platform. 147 | 148 | 149 | -------------------------------------------------------------------------------- /README.tests: -------------------------------------------------------------------------------- 1 | About the Tests 2 | --------------- 3 | 4 | The following tests are from the original version, updated simply for speed 5 | and rewritten to fit the new framework of the program. These tests will 6 | mainly catch memory errors due to bad bits which are permanently stuck high 7 | or low: 8 | Random value 9 | XOR comparison 10 | SUB comparison 11 | MUL comparison 12 | DIV comparison 13 | OR comparison 14 | AND comparison 15 | 16 | The following tests were implemented by me, and will do a slightly better job 17 | of catching flaky bits, which may or may not hold a true value: 18 | Sequential Increment 19 | Block Sequential 20 | Solid Bits 21 | 22 | The remaining tests were also implemented by me, and are designed to catch 23 | bad bits which are dependent on the current values of surrounding bits in either 24 | the same word32, or in the preceding and succeeding word32s. 25 | Bit Flip 26 | Checkerboard 27 | Walking Ones 28 | Walking Zeroes 29 | Bit Spread 30 | 31 | There is also a test (Stuck Address) which is run first. It determines if the 32 | memory locations the program attempts to access are addressed properly or not. 33 | If this test reports errors, there is almost certainly a problem somewhere in 34 | the memory subsystem. Results from the rest of the tests cannot be considered 35 | accurate if this test fails: 36 | Stuck Address 37 | 38 | Usage information is summarized in the file README, and in the man page. 39 | -------------------------------------------------------------------------------- /conf-cc: -------------------------------------------------------------------------------- 1 | cc -O2 -DPOSIX -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64 -DTEST_NARROW_WRITES -c 2 | 3 | This will be used to compile .c files. 4 | -------------------------------------------------------------------------------- /conf-ld: -------------------------------------------------------------------------------- 1 | cc -s 2 | 3 | This will be used to link .o files into an executable. 4 | -------------------------------------------------------------------------------- /extra-libs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | case "$1" in 4 | osf1-*) 5 | # OSF/1 (Tru64) needs /usr/lib/librt.a for mlock() 6 | echo /usr/lib/librt.a 7 | ;; 8 | unix_sv*) ;; 9 | irix64-*) ;; 10 | irix-*) ;; 11 | dgux-*) ;; 12 | hp-ux-*) ;; 13 | sco*) ;; 14 | *) 15 | ;; 16 | esac 17 | -------------------------------------------------------------------------------- /find-systype.sh: -------------------------------------------------------------------------------- 1 | # oper-:arch-:syst-:chip-:kern- 2 | # oper = operating system type; e.g., sunos-4.1.4 3 | # arch = machine language; e.g., sparc 4 | # syst = which binaries can run; e.g., sun4 5 | # chip = chip model; e.g., micro-2-80 6 | # kern = kernel version; e.g., sun4m 7 | # dependence: arch --- chip 8 | # \ \ 9 | # oper --- syst --- kern 10 | # so, for example, syst is interpreted in light of oper, but chip is not. 11 | # anyway, no slashes, no extra colons, no uppercase letters. 12 | # the point of the extra -'s is to ease parsing: can add hierarchies later. 13 | # e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, 14 | # and i386-486 (486s do have more instructions, you know) as well as i386. 15 | # the idea here is to include ALL useful available information. 16 | 17 | exec 2>/dev/null 18 | sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" 19 | if [ x"$sys" != x ] 20 | then 21 | unamer="`uname -r | tr /: ..`" 22 | unamem="`uname -m | tr /: ..`" 23 | unamev="`uname -v | tr /: ..`" 24 | 25 | case "$sys" in 26 | bsd.os) 27 | # in bsd 4.4, uname -v does not have useful info. 28 | # in bsd 4.4, uname -m is arch, not chip. 29 | oper="$sys-$unamer" 30 | arch="$unamem" 31 | syst="" 32 | chip="`sysctl -n hw.model`" 33 | kern="" 34 | ;; 35 | freebsd) 36 | # see above about bsd 4.4 37 | oper="$sys-$unamer" 38 | arch="$unamem" 39 | syst="" 40 | chip="`sysctl -n hw.model`" # hopefully 41 | kern="" 42 | ;; 43 | netbsd) 44 | # see above about bsd 4.4 45 | oper="$sys-$unamer" 46 | arch="$unamem" 47 | syst="" 48 | chip="`sysctl -n hw.model`" # hopefully 49 | kern="" 50 | ;; 51 | linux) 52 | # as in bsd 4.4, uname -v does not have useful info. 53 | oper="$sys-$unamer" 54 | syst="" 55 | chip="$unamem" 56 | kern="" 57 | case "$chip" in 58 | i386|i486|i586|i686) 59 | arch="i386" 60 | ;; 61 | alpha) 62 | arch="alpha" 63 | ;; 64 | esac 65 | ;; 66 | aix) 67 | # naturally IBM has to get uname -r and uname -v backwards. dorks. 68 | oper="$sys-$unamev-$unamer" 69 | arch="`arch | tr /: ..`" 70 | syst="" 71 | chip="$unamem" 72 | kern="" 73 | ;; 74 | sunos) 75 | oper="$sys-$unamer-$unamev" 76 | arch="`(uname -p || mach) | tr /: ..`" 77 | syst="`arch | tr /: ..`" 78 | chip="$unamem" # this is wrong; is there any way to get the real info? 79 | kern="`arch -k | tr /: ..`" 80 | ;; 81 | unix_sv) 82 | oper="$sys-$unamer-$unamev" 83 | arch="`uname -m`" 84 | syst="" 85 | chip="$unamem" 86 | kern="" 87 | ;; 88 | *) 89 | oper="$sys-$unamer-$unamev" 90 | arch="`arch | tr /: ..`" 91 | syst="" 92 | chip="$unamem" 93 | kern="" 94 | ;; 95 | esac 96 | else 97 | $CC -c trycpp.c 98 | $LD -o trycpp trycpp.o 99 | case `./trycpp` in 100 | nextstep) 101 | oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" 102 | arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" 103 | syst="" 104 | chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" 105 | kern="" 106 | ;; 107 | *) 108 | oper="unknown" 109 | arch="" 110 | syst="" 111 | chip="" 112 | kern="" 113 | ;; 114 | esac 115 | rm -f trycpp.o trycpp 116 | fi 117 | 118 | case "$chip" in 119 | 80486) 120 | # let's try to be consistent here. (BSD/OS) 121 | chip=i486 122 | ;; 123 | i486DX) 124 | # respect the hyphen hierarchy. (FreeBSD) 125 | chip=i486-dx 126 | ;; 127 | i486.DX2) 128 | # respect the hyphen hierarchy. (FreeBSD) 129 | chip=i486-dx2 130 | ;; 131 | Intel.586) 132 | # no, you nitwits, there is no such chip. (NeXTStep) 133 | chip=pentium 134 | ;; 135 | i586) 136 | # no, you nitwits, there is no such chip. (Linux) 137 | chip=pentium 138 | ;; 139 | i686) 140 | # STOP SAYING THAT! (Linux) 141 | chip=ppro 142 | esac 143 | 144 | echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' 145 | -------------------------------------------------------------------------------- /make-compile.sh: -------------------------------------------------------------------------------- 1 | echo exec "$CC" -c '${1+"$@"}' 2 | -------------------------------------------------------------------------------- /make-load.sh: -------------------------------------------------------------------------------- 1 | echo 'main="$1"; shift' 2 | echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}' 3 | -------------------------------------------------------------------------------- /make-makelib.sh: -------------------------------------------------------------------------------- 1 | echo 'main="$1"; shift' 2 | echo 'rm -f "$main"' 3 | echo 'ar cr "$main" ${1+"$@"}' 4 | 5 | case "$1" in 6 | sunos-5.*) ;; 7 | unix_sv*) ;; 8 | irix64-*) ;; 9 | irix-*) ;; 10 | dgux-*) ;; 11 | hp-ux-*) ;; 12 | sco*) ;; 13 | *) 14 | echo 'ranlib "$main"' 15 | ;; 16 | esac 17 | -------------------------------------------------------------------------------- /memtester.8: -------------------------------------------------------------------------------- 1 | .TH memtester "8" "September 2020" "memtester 4" "Maintenance Commands" 2 | .SH NAME 3 | memtester \- stress test to find memory subsystem faults. 4 | .SH SYNOPSIS 5 | .B memtester 6 | [\f -p PHYSADDR\fR [\f -d DEVICE\fR]] 7 | <\fIMEMORY\fR> 8 | [\fIITERATIONS\fR] 9 | .SH DESCRIPTION 10 | .\" Add any additional description here 11 | .PP 12 | memtester is an effective userspace tester for stress-testing the memory 13 | subsystem. It is very effective at finding intermittent and non-deterministic 14 | faults. Note that problems in other hardware areas (overheating CPU, 15 | out-of-specification power supply, etc.) can cause intermittent memory faults, 16 | so it is still up to you to determine where the fault lies through normal 17 | hardware diagnostic procedures; memtester just helps you determine whether 18 | a problem exists. 19 | .PP 20 | memtester will malloc(3) the amount of memory specified, if possible. If 21 | this fails, it will decrease the amount of memory requested until it succeeds. 22 | It will then attempt to mlock(3) this memory; if it cannot do so, testing 23 | will be slower and much less effective. Run memtester as root so that it 24 | can mlock the memory it tests. 25 | .PP 26 | Note that the maximum amount of memory that memtester can test will be less 27 | than the total amount of memory installed in the system; the operating system, 28 | libraries, and other system limits take some of the available memory. 29 | memtester is also limited to the amount of memory available to a single 30 | process; for example, on 32-bit machines with more than 4GB of memory, 31 | memtester is still limited to less than 4GB. 32 | .PP 33 | Note that it is up to you to know how much memory you can safely allocate 34 | for testing. If you attempt to allocate more memory than is available, 35 | memtester should figure that out, reduce the amount slightly, and try again. 36 | However, this can lead to memtester successfully allocating and mlocking 37 | essentially all free memory on the system -- if other programs are running, 38 | this can lead to excessive swapping and slowing the system down to the point 39 | that it is difficult to use. If the system allows allocation of more memory 40 | than is actually available (overcommit), it may lead to a deadlock, where 41 | the system halts. If the system has an out-of-memory process killer (like 42 | Linux), memtester or another process may be killed by the OOM killer. 43 | .PP 44 | So choose wisely. 45 | .PP 46 | .SH OPTIONS 47 | .TP 48 | \f -p PHYSADDR\fR 49 | tells memtester to test a specific region of memory starting at physical 50 | address PHYSADDR (given in hex), by mmap(2)ing a device specified by the 51 | -d option (below, or /dev/mem by default). This is mostly of use to hardware 52 | developers, for testing memory-mapped I/O devices and similar. 53 | Note that the memory region will be overwritten during testing, so it is not 54 | safe to specify memory which is allocated for the system or for other 55 | applications; doing so will cause them to crash. If you absolutely must test 56 | a particular region of actual physical memory, arrange to have that memory 57 | allocated by your test software, and hold it in this allocated state, then 58 | run memtester on it with this option. 59 | .TP 60 | \fIMEMORY\fR 61 | the amount of memory to allocate and test, in megabytes by default. You can 62 | include a suffix of B, K, M, or G to indicate bytes, kilobytes, megabytes, or 63 | gigabytes respectively. 64 | .TP 65 | \fIITERATIONS\fR 66 | (optional) number of loops to iterate through. Default is infinite. 67 | .SH ENVIRONMENT 68 | .PP 69 | If the environment variable MEMTESTER_TEST_MASK is set, memtester treats the 70 | value as a bitmask of which tests (other than the stuck address test) to run. 71 | The value can be specified in decimal, in octal (with a leading 0), or in 72 | hexadecimal (with a leading 0x). The specific bit values corresponding to 73 | particular tests may change from release to release; consult the list of tests 74 | in the source for the appropriate index values for the version of memtester you 75 | are running. Note that skipping some tests will reduce the time it takes for 76 | memtester to run, but also reduce memtester's effectiveness. 77 | .SH NOTE 78 | .PP 79 | memtester must be run with root privileges to mlock(3) its pages. Testing 80 | memory without locking the pages in place is mostly pointless and slow. 81 | .SH EXIT CODE 82 | .PP 83 | memtester's exit code is 0 when everything works properly. Otherwise, 84 | it is the logical OR of the following values: 85 | .TP 86 | \f0x01 87 | error allocating or locking memory, or invocation error 88 | .TP 89 | \f0x02 90 | error during stuck address test 91 | .TP 92 | \f0x04 93 | error during one of the other tests 94 | .SH AUTHOR 95 | Written by Charles Cazabon. 96 | .SH "REPORTING BUGS" 97 | Report bugs to . 98 | .PP 99 | .SH COPYRIGHT 100 | Copyright \(co 2001-2020 Charles Cazabon 101 | .br 102 | This is free software; see the file COPYING for copying conditions. There is NO 103 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 104 | -------------------------------------------------------------------------------- /memtester.c: -------------------------------------------------------------------------------- 1 | /* 2 | * memtester version 4 3 | * 4 | * Very simple but very effective user-space memory tester. 5 | * Originally by Simon Kirby 6 | * Version 2 by Charles Cazabon 7 | * Version 3 not publicly released. 8 | * Version 4 rewrite: 9 | * Copyright (C) 2004-2020 Charles Cazabon 10 | * Licensed under the terms of the GNU General Public License version 2 (only). 11 | * See the file COPYING for details. 12 | * 13 | */ 14 | 15 | #define __version__ "4.5.1" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "types.h" 29 | #include "sizes.h" 30 | #include "tests.h" 31 | #include "output.h" 32 | 33 | #define EXIT_FAIL_NONSTARTER 0x01 34 | #define EXIT_FAIL_ADDRESSLINES 0x02 35 | #define EXIT_FAIL_OTHERTEST 0x04 36 | 37 | struct test tests[] = { 38 | { "Random Value", test_random_value }, 39 | { "Compare XOR", test_xor_comparison }, 40 | { "Compare SUB", test_sub_comparison }, 41 | { "Compare MUL", test_mul_comparison }, 42 | { "Compare DIV",test_div_comparison }, 43 | { "Compare OR", test_or_comparison }, 44 | { "Compare AND", test_and_comparison }, 45 | { "Sequential Increment", test_seqinc_comparison }, 46 | { "Solid Bits", test_solidbits_comparison }, 47 | { "Block Sequential", test_blockseq_comparison }, 48 | { "Checkerboard", test_checkerboard_comparison }, 49 | { "Bit Spread", test_bitspread_comparison }, 50 | { "Bit Flip", test_bitflip_comparison }, 51 | { "Walking Ones", test_walkbits1_comparison }, 52 | { "Walking Zeroes", test_walkbits0_comparison }, 53 | #ifdef TEST_NARROW_WRITES 54 | { "8-bit Writes", test_8bit_wide_random }, 55 | { "16-bit Writes", test_16bit_wide_random }, 56 | #endif 57 | { NULL, NULL } 58 | }; 59 | 60 | /* Sanity checks and portability helper macros. */ 61 | #ifdef _SC_VERSION 62 | void check_posix_system(void) { 63 | if (sysconf(_SC_VERSION) < 198808L) { 64 | fprintf(stderr, "A POSIX system is required. Don't be surprised if " 65 | "this craps out.\n"); 66 | fprintf(stderr, "_SC_VERSION is %lu\n", sysconf(_SC_VERSION)); 67 | } 68 | } 69 | #else 70 | #define check_posix_system() 71 | #endif 72 | 73 | #ifdef _SC_PAGE_SIZE 74 | int memtester_pagesize(void) { 75 | int pagesize = sysconf(_SC_PAGE_SIZE); 76 | if (pagesize == -1) { 77 | perror("get page size failed"); 78 | exit(EXIT_FAIL_NONSTARTER); 79 | } 80 | printf("pagesize is %ld\n", (long) pagesize); 81 | return pagesize; 82 | } 83 | #else 84 | int memtester_pagesize(void) { 85 | printf("sysconf(_SC_PAGE_SIZE) not supported; using pagesize of 8192\n"); 86 | return 8192; 87 | } 88 | #endif 89 | 90 | /* Some systems don't define MAP_LOCKED. Define it to 0 here 91 | so it's just a no-op when ORed with other constants. */ 92 | #ifndef MAP_LOCKED 93 | #define MAP_LOCKED 0 94 | #endif 95 | 96 | /* Function declarations */ 97 | void usage(char *me); 98 | 99 | /* Global vars - so tests have access to this information */ 100 | int use_phys = 0; 101 | off_t physaddrbase = 0; 102 | 103 | /* Function definitions */ 104 | void usage(char *me) { 105 | fprintf(stderr, "\n" 106 | "Usage: %s [-p physaddrbase [-d device] [-u]] [B|K|M|G] [loops]\n", 107 | me); 108 | exit(EXIT_FAIL_NONSTARTER); 109 | } 110 | 111 | int main(int argc, char **argv) { 112 | ul loops, loop, i; 113 | size_t pagesize, wantraw, wantmb, wantbytes, wantbytes_orig, bufsize, 114 | halflen, count; 115 | char *memsuffix, *addrsuffix, *loopsuffix; 116 | ptrdiff_t pagesizemask; 117 | void volatile *buf, *aligned; 118 | ulv *bufa, *bufb; 119 | int do_mlock = 1, done_mem = 0; 120 | int exit_code = 0; 121 | int memfd, opt, memshift; 122 | size_t maxbytes = -1; /* addressable memory, in bytes */ 123 | size_t maxmb = (maxbytes >> 20) + 1; /* addressable memory, in MB */ 124 | /* Device to mmap memory from with -p, default is normal core */ 125 | char *device_name = "/dev/mem"; 126 | struct stat statbuf; 127 | int device_specified = 0; 128 | char *env_testmask = 0; 129 | ul testmask = 0; 130 | int o_flags = O_RDWR | O_SYNC; 131 | 132 | out_initialize(); 133 | 134 | printf("memtester version " __version__ " (%d-bit)\n", UL_LEN); 135 | printf("Copyright (C) 2001-2020 Charles Cazabon.\n"); 136 | printf("Licensed under the GNU General Public License version 2 (only).\n"); 137 | printf("\n"); 138 | check_posix_system(); 139 | pagesize = memtester_pagesize(); 140 | pagesizemask = (ptrdiff_t) ~(pagesize - 1); 141 | printf("pagesizemask is 0x%tx\n", pagesizemask); 142 | 143 | /* If MEMTESTER_TEST_MASK is set, we use its value as a mask of which 144 | tests we run. 145 | */ 146 | if (env_testmask = getenv("MEMTESTER_TEST_MASK")) { 147 | errno = 0; 148 | testmask = strtoul(env_testmask, 0, 0); 149 | if (errno) { 150 | fprintf(stderr, "error parsing MEMTESTER_TEST_MASK %s: %s\n", 151 | env_testmask, strerror(errno)); 152 | usage(argv[0]); /* doesn't return */ 153 | } 154 | printf("using testmask 0x%lx\n", testmask); 155 | } 156 | 157 | while ((opt = getopt(argc, argv, "p:d:u")) != -1) { 158 | switch (opt) { 159 | case 'p': 160 | errno = 0; 161 | physaddrbase = (off_t) strtoull(optarg, &addrsuffix, 16); 162 | if (errno != 0) { 163 | fprintf(stderr, 164 | "failed to parse physaddrbase arg; should be hex " 165 | "address (0x123...)\n"); 166 | usage(argv[0]); /* doesn't return */ 167 | } 168 | if (*addrsuffix != '\0') { 169 | /* got an invalid character in the address */ 170 | fprintf(stderr, 171 | "failed to parse physaddrbase arg; should be hex " 172 | "address (0x123...)\n"); 173 | usage(argv[0]); /* doesn't return */ 174 | } 175 | if (physaddrbase & (pagesize - 1)) { 176 | fprintf(stderr, 177 | "bad physaddrbase arg; does not start on page " 178 | "boundary\n"); 179 | usage(argv[0]); /* doesn't return */ 180 | } 181 | /* okay, got address */ 182 | use_phys = 1; 183 | break; 184 | case 'd': 185 | if (stat(optarg,&statbuf)) { 186 | fprintf(stderr, "can not use %s as device: %s\n", optarg, 187 | strerror(errno)); 188 | usage(argv[0]); /* doesn't return */ 189 | } else { 190 | if (!S_ISCHR(statbuf.st_mode)) { 191 | fprintf(stderr, "can not mmap non-char device %s\n", 192 | optarg); 193 | usage(argv[0]); /* doesn't return */ 194 | } else { 195 | device_name = optarg; 196 | device_specified = 1; 197 | } 198 | } 199 | break; 200 | case 'u': 201 | o_flags &= ~O_SYNC; 202 | break; 203 | default: /* '?' */ 204 | usage(argv[0]); /* doesn't return */ 205 | } 206 | } 207 | 208 | if (device_specified && !use_phys) { 209 | fprintf(stderr, 210 | "for mem device, physaddrbase (-p) must be specified\n"); 211 | usage(argv[0]); /* doesn't return */ 212 | } 213 | 214 | if (optind >= argc) { 215 | fprintf(stderr, "need memory argument, in MB\n"); 216 | usage(argv[0]); /* doesn't return */ 217 | } 218 | 219 | errno = 0; 220 | wantraw = (size_t) strtoul(argv[optind], &memsuffix, 0); 221 | if (errno != 0) { 222 | fprintf(stderr, "failed to parse memory argument"); 223 | usage(argv[0]); /* doesn't return */ 224 | } 225 | switch (*memsuffix) { 226 | case 'G': 227 | case 'g': 228 | memshift = 30; /* gigabytes */ 229 | break; 230 | case 'M': 231 | case 'm': 232 | memshift = 20; /* megabytes */ 233 | break; 234 | case 'K': 235 | case 'k': 236 | memshift = 10; /* kilobytes */ 237 | break; 238 | case 'B': 239 | case 'b': 240 | memshift = 0; /* bytes*/ 241 | break; 242 | case '\0': /* no suffix */ 243 | memshift = 20; /* megabytes */ 244 | break; 245 | default: 246 | /* bad suffix */ 247 | usage(argv[0]); /* doesn't return */ 248 | } 249 | wantbytes_orig = wantbytes = ((size_t) wantraw << memshift); 250 | wantmb = (wantbytes_orig >> 20); 251 | optind++; 252 | if (wantmb > maxmb) { 253 | fprintf(stderr, "This system can only address %llu MB.\n", (ull) maxmb); 254 | exit(EXIT_FAIL_NONSTARTER); 255 | } 256 | if (wantbytes < pagesize) { 257 | fprintf(stderr, "bytes %ld < pagesize %ld -- memory argument too large?\n", 258 | wantbytes, pagesize); 259 | exit(EXIT_FAIL_NONSTARTER); 260 | } 261 | 262 | if (optind >= argc) { 263 | loops = 0; 264 | } else { 265 | errno = 0; 266 | loops = strtoul(argv[optind], &loopsuffix, 0); 267 | if (errno != 0) { 268 | fprintf(stderr, "failed to parse number of loops"); 269 | usage(argv[0]); /* doesn't return */ 270 | } 271 | if (*loopsuffix != '\0') { 272 | fprintf(stderr, "loop suffix %c\n", *loopsuffix); 273 | usage(argv[0]); /* doesn't return */ 274 | } 275 | } 276 | 277 | printf("want %lluMB (%llu bytes)\n", (ull) wantmb, (ull) wantbytes); 278 | buf = NULL; 279 | 280 | if (use_phys) { 281 | memfd = open(device_name, o_flags); 282 | if (memfd == -1) { 283 | fprintf(stderr, "failed to open %s for physical memory: %s\n", 284 | device_name, strerror(errno)); 285 | exit(EXIT_FAIL_NONSTARTER); 286 | } 287 | buf = (void volatile *) mmap(0, wantbytes, PROT_READ | PROT_WRITE, 288 | MAP_SHARED | MAP_LOCKED, memfd, 289 | physaddrbase); 290 | if (buf == MAP_FAILED) { 291 | fprintf(stderr, "failed to mmap %s for physical memory: %s\n", 292 | device_name, strerror(errno)); 293 | exit(EXIT_FAIL_NONSTARTER); 294 | } 295 | 296 | if (mlock((void *) buf, wantbytes) < 0) { 297 | fprintf(stderr, "failed to mlock mmap'ed space\n"); 298 | do_mlock = 0; 299 | } 300 | 301 | bufsize = wantbytes; /* accept no less */ 302 | aligned = buf; 303 | done_mem = 1; 304 | } 305 | 306 | while (!done_mem) { 307 | while (!buf && wantbytes) { 308 | buf = (void volatile *) malloc(wantbytes); 309 | if (!buf) wantbytes -= pagesize; 310 | } 311 | bufsize = wantbytes; 312 | printf("got %lluMB (%llu bytes)", (ull) wantbytes >> 20, 313 | (ull) wantbytes); 314 | fflush(stdout); 315 | if (do_mlock) { 316 | printf(", trying mlock ..."); 317 | fflush(stdout); 318 | if ((size_t) buf % pagesize) { 319 | /* printf("aligning to page -- was 0x%tx\n", buf); */ 320 | aligned = (void volatile *) ((size_t) buf & pagesizemask) + pagesize; 321 | /* printf(" now 0x%tx -- lost %d bytes\n", aligned, 322 | * (size_t) aligned - (size_t) buf); 323 | */ 324 | bufsize -= ((size_t) aligned - (size_t) buf); 325 | } else { 326 | aligned = buf; 327 | } 328 | /* Try mlock */ 329 | if (mlock((void *) aligned, bufsize) < 0) { 330 | switch(errno) { 331 | case EAGAIN: /* BSDs */ 332 | printf("over system/pre-process limit, reducing...\n"); 333 | free((void *) buf); 334 | buf = NULL; 335 | wantbytes -= pagesize; 336 | break; 337 | case ENOMEM: 338 | printf("too many pages, reducing...\n"); 339 | free((void *) buf); 340 | buf = NULL; 341 | wantbytes -= pagesize; 342 | break; 343 | case EPERM: 344 | printf("insufficient permission.\n"); 345 | printf("Trying again, unlocked:\n"); 346 | do_mlock = 0; 347 | free((void *) buf); 348 | buf = NULL; 349 | wantbytes = wantbytes_orig; 350 | break; 351 | default: 352 | printf("failed for unknown reason.\n"); 353 | do_mlock = 0; 354 | done_mem = 1; 355 | } 356 | } else { 357 | printf("locked.\n"); 358 | done_mem = 1; 359 | } 360 | } else { 361 | done_mem = 1; 362 | printf("\n"); 363 | } 364 | } 365 | 366 | if (!do_mlock) fprintf(stderr, "Continuing with unlocked memory; testing " 367 | "will be slower and less reliable.\n"); 368 | 369 | /* Do alighnment here as well, as some cases won't trigger above if you 370 | define out the use of mlock() (cough HP/UX 10 cough). */ 371 | if ((size_t) buf % pagesize) { 372 | /* printf("aligning to page -- was 0x%tx\n", buf); */ 373 | aligned = (void volatile *) ((size_t) buf & pagesizemask) + pagesize; 374 | /* printf(" now 0x%tx -- lost %d bytes\n", aligned, 375 | * (size_t) aligned - (size_t) buf); 376 | */ 377 | bufsize -= ((size_t) aligned - (size_t) buf); 378 | } else { 379 | aligned = buf; 380 | } 381 | 382 | halflen = bufsize / 2; 383 | count = halflen / sizeof(ul); 384 | bufa = (ulv *) aligned; 385 | bufb = (ulv *) ((size_t) aligned + halflen); 386 | 387 | for(loop=1; ((!loops) || loop <= loops); loop++) { 388 | printf("Loop %lu", loop); 389 | if (loops) { 390 | printf("/%lu", loops); 391 | } 392 | printf(":\n"); 393 | printf(" %-20s: ", "Stuck Address"); 394 | fflush(stdout); 395 | if (!test_stuck_address(aligned, bufsize / sizeof(ul))) { 396 | printf("ok\n"); 397 | } else { 398 | exit_code |= EXIT_FAIL_ADDRESSLINES; 399 | } 400 | for (i=0;;i++) { 401 | if (!tests[i].name) break; 402 | /* If using a custom testmask, only run this test if the 403 | bit corresponding to this test was set by the user. 404 | */ 405 | if (testmask && (!((1 << i) & testmask))) { 406 | continue; 407 | } 408 | printf(" %-20s: ", tests[i].name); 409 | fflush(stdout); 410 | if (!tests[i].fp(bufa, bufb, count)) { 411 | printf("ok\n"); 412 | } else { 413 | exit_code |= EXIT_FAIL_OTHERTEST; 414 | } 415 | fflush(stdout); 416 | /* clear buffer */ 417 | memset((void *) buf, 255, wantbytes); 418 | } 419 | printf("\n"); 420 | fflush(stdout); 421 | } 422 | if (do_mlock) munlock((void *) aligned, bufsize); 423 | printf("Done.\n"); 424 | fflush(stdout); 425 | exit(exit_code); 426 | } 427 | -------------------------------------------------------------------------------- /memtester.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Very simple (yet, for some reason, very effective) memory tester. 3 | * Originally by Simon Kirby 4 | * Version 2 by Charles Cazabon 5 | * Version 3 not publicly released. 6 | * Version 4 rewrite: 7 | * Copyright (C) 2004-2020 Charles Cazabon 8 | * Licensed under the terms of the GNU General Public License version 2 (only). 9 | * See the file COPYING for details. 10 | * 11 | * This file contains the declarations for external variables from the main file. 12 | * See other comments in that file. 13 | * 14 | */ 15 | 16 | #include 17 | 18 | /* extern declarations. */ 19 | 20 | extern int use_phys; 21 | extern off_t physaddrbase; 22 | -------------------------------------------------------------------------------- /output.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2022 Luca Ceresoli 4 | * 5 | * Output routines to conditionally show testing status. 6 | * 7 | * out_initialize() must be called at program startup and disabled status 8 | * output if stdout is not a tty. The other functions print test progress, 9 | * but only if on a tty. 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | #include "output.h" 16 | 17 | static int show_progress = 1; 18 | static int wheel_pos; 19 | 20 | void out_initialize() 21 | { 22 | show_progress = isatty(STDOUT_FILENO); 23 | } 24 | 25 | void out_test_start() 26 | { 27 | if (show_progress) { 28 | printf(" "); 29 | fflush(stdout); 30 | } 31 | } 32 | 33 | void out_test_setting(unsigned int j) 34 | { 35 | if (show_progress) { 36 | printf("\b\b\b\b\b\b\b\b\b\b\b"); 37 | printf("setting %3u", j); 38 | fflush(stdout); 39 | } 40 | } 41 | 42 | void out_test_testing(unsigned int j) 43 | { 44 | if (show_progress) { 45 | printf("\b\b\b\b\b\b\b\b\b\b\b"); 46 | printf("testing %3u", j); 47 | fflush(stdout); 48 | } 49 | } 50 | 51 | void out_test_end() 52 | { 53 | if (show_progress) { 54 | printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 55 | fflush(stdout); 56 | } 57 | } 58 | 59 | void out_wheel_start() 60 | { 61 | if (show_progress) { 62 | putchar(' '); 63 | fflush(stdout); 64 | wheel_pos = 0; 65 | } 66 | } 67 | 68 | void out_wheel_advance(unsigned int i) 69 | { 70 | static const unsigned int wheel_often = 2500; 71 | static const unsigned int n_chars = 4; 72 | char wheel_char[4] = {'-', '\\', '|', '/'}; 73 | 74 | if (show_progress) { 75 | if (!(i % wheel_often)) { 76 | putchar('\b'); 77 | putchar(wheel_char[++wheel_pos % n_chars]); 78 | fflush(stdout); 79 | } 80 | } 81 | } 82 | 83 | void out_wheel_end() 84 | { 85 | if (show_progress) { 86 | printf("\b \b"); 87 | fflush(stdout); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /output.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (C) 2022 Luca Ceresoli 4 | * 5 | * Output routines to conditionally show testing status. 6 | */ 7 | 8 | #ifndef _OUTPUT_H_ 9 | #define _OUTPUT_H_ 10 | 11 | void out_initialize(); 12 | 13 | void out_test_start(); 14 | void out_test_setting(); 15 | void out_test_testing(); 16 | void out_test_end(); 17 | 18 | void out_wheel_start(); 19 | void out_wheel_advance(); 20 | void out_wheel_end(); 21 | 22 | #endif // _OUTPUT_H_ 23 | -------------------------------------------------------------------------------- /sizes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Very simple but very effective user-space memory tester. 3 | * Originally by Simon Kirby 4 | * Version 2 by Charles Cazabon 5 | * Version 3 not publicly released. 6 | * Version 4 rewrite: 7 | * Copyright (C) 2004-2012 Charles Cazabon 8 | * Licensed under the terms of the GNU General Public License version 2 (only). 9 | * See the file COPYING for details. 10 | * 11 | * This file contains some macro definitions for handling 32/64 bit platforms. 12 | * 13 | */ 14 | 15 | #include 16 | 17 | #define rand32() ((unsigned int) rand() | ( (unsigned int) rand() << 16)) 18 | 19 | #if (ULONG_MAX == 4294967295UL) 20 | #define rand_ul() rand32() 21 | #define UL_ONEBITS 0xffffffff 22 | #define UL_LEN 32 23 | #define CHECKERBOARD1 0x55555555 24 | #define CHECKERBOARD2 0xaaaaaaaa 25 | #define UL_BYTE(x) ((x | x << 8 | x << 16 | x << 24)) 26 | #elif (ULONG_MAX == 18446744073709551615ULL) 27 | #define rand64() (((ul) rand32()) << 32 | ((ul) rand32())) 28 | #define rand_ul() rand64() 29 | #define UL_ONEBITS 0xffffffffffffffffUL 30 | #define UL_LEN 64 31 | #define CHECKERBOARD1 0x5555555555555555 32 | #define CHECKERBOARD2 0xaaaaaaaaaaaaaaaa 33 | #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)) 34 | #else 35 | #error long on this platform is not 32 or 64 bits 36 | #endif 37 | -------------------------------------------------------------------------------- /tests.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Very simple but very effective user-space memory tester. 3 | * Originally by Simon Kirby 4 | * Version 2 by Charles Cazabon 5 | * Version 3 not publicly released. 6 | * Version 4 rewrite: 7 | * Copyright (C) 2004-2020 Charles Cazabon 8 | * Licensed under the terms of the GNU General Public License version 2 (only). 9 | * See the file COPYING for details. 10 | * 11 | * This file contains the functions for the actual tests, called from the 12 | * main routine in memtester.c. See other comments in that file. 13 | * 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "types.h" 22 | #include "sizes.h" 23 | #include "memtester.h" 24 | #include "output.h" 25 | 26 | #define ONE 0x00000001L 27 | 28 | union { 29 | unsigned char bytes[UL_LEN/8]; 30 | ul val; 31 | } mword8; 32 | 33 | union { 34 | unsigned short u16s[UL_LEN/16]; 35 | ul val; 36 | } mword16; 37 | 38 | /* Function definitions. */ 39 | 40 | int compare_regions(ulv *bufa, ulv *bufb, size_t count) { 41 | int r = 0; 42 | size_t i; 43 | ulv *p1 = bufa; 44 | ulv *p2 = bufb; 45 | off_t physaddr; 46 | 47 | for (i = 0; i < count; i++, p1++, p2++) { 48 | if (*p1 != *p2) { 49 | if (use_phys) { 50 | physaddr = physaddrbase + (i * sizeof(ul)); 51 | fprintf(stderr, 52 | "FAILURE: 0x%08lx != 0x%08lx at physical address " 53 | "0x%08lx.\n", 54 | (ul) *p1, (ul) *p2, physaddr); 55 | } else { 56 | fprintf(stderr, 57 | "FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n", 58 | (ul) *p1, (ul) *p2, (ul) (i * sizeof(ul))); 59 | } 60 | /* printf("Skipping to next test..."); */ 61 | r = -1; 62 | } 63 | } 64 | return r; 65 | } 66 | 67 | int test_stuck_address(ulv *bufa, size_t count) { 68 | ulv *p1 = bufa; 69 | unsigned int j; 70 | size_t i; 71 | off_t physaddr; 72 | 73 | out_test_start(); 74 | for (j = 0; j < 16; j++) { 75 | p1 = (ulv *) bufa; 76 | out_test_setting(j); 77 | for (i = 0; i < count; i++) { 78 | *p1 = ((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1); 79 | *p1++; 80 | } 81 | out_test_testing(j); 82 | p1 = (ulv *) bufa; 83 | for (i = 0; i < count; i++, p1++) { 84 | if (*p1 != (((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1))) { 85 | if (use_phys) { 86 | physaddr = physaddrbase + (i * sizeof(ul)); 87 | fprintf(stderr, 88 | "FAILURE: possible bad address line at physical " 89 | "address 0x%08lx.\n", 90 | physaddr); 91 | } else { 92 | fprintf(stderr, 93 | "FAILURE: possible bad address line at offset " 94 | "0x%08lx.\n", 95 | (ul) (i * sizeof(ul))); 96 | } 97 | printf("Skipping to next test...\n"); 98 | fflush(stdout); 99 | return -1; 100 | } 101 | } 102 | } 103 | out_test_end(); 104 | return 0; 105 | } 106 | 107 | int test_random_value(ulv *bufa, ulv *bufb, size_t count) { 108 | ulv *p1 = bufa; 109 | ulv *p2 = bufb; 110 | size_t i; 111 | 112 | out_wheel_start(); 113 | for (i = 0; i < count; i++) { 114 | *p1++ = *p2++ = rand_ul(); 115 | out_wheel_advance(i); 116 | } 117 | out_wheel_end(); 118 | return compare_regions(bufa, bufb, count); 119 | } 120 | 121 | int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count) { 122 | ulv *p1 = bufa; 123 | ulv *p2 = bufb; 124 | size_t i; 125 | ul q = rand_ul(); 126 | 127 | for (i = 0; i < count; i++) { 128 | *p1++ ^= q; 129 | *p2++ ^= q; 130 | } 131 | return compare_regions(bufa, bufb, count); 132 | } 133 | 134 | int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count) { 135 | ulv *p1 = bufa; 136 | ulv *p2 = bufb; 137 | size_t i; 138 | ul q = rand_ul(); 139 | 140 | for (i = 0; i < count; i++) { 141 | *p1++ -= q; 142 | *p2++ -= q; 143 | } 144 | return compare_regions(bufa, bufb, count); 145 | } 146 | 147 | int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count) { 148 | ulv *p1 = bufa; 149 | ulv *p2 = bufb; 150 | size_t i; 151 | ul q = rand_ul(); 152 | 153 | for (i = 0; i < count; i++) { 154 | *p1++ *= q; 155 | *p2++ *= q; 156 | } 157 | return compare_regions(bufa, bufb, count); 158 | } 159 | 160 | int test_div_comparison(ulv *bufa, ulv *bufb, size_t count) { 161 | ulv *p1 = bufa; 162 | ulv *p2 = bufb; 163 | size_t i; 164 | ul q = rand_ul(); 165 | 166 | for (i = 0; i < count; i++) { 167 | if (!q) { 168 | q++; 169 | } 170 | *p1++ /= q; 171 | *p2++ /= q; 172 | } 173 | return compare_regions(bufa, bufb, count); 174 | } 175 | 176 | int test_or_comparison(ulv *bufa, ulv *bufb, size_t count) { 177 | ulv *p1 = bufa; 178 | ulv *p2 = bufb; 179 | size_t i; 180 | ul q = rand_ul(); 181 | 182 | for (i = 0; i < count; i++) { 183 | *p1++ |= q; 184 | *p2++ |= q; 185 | } 186 | return compare_regions(bufa, bufb, count); 187 | } 188 | 189 | int test_and_comparison(ulv *bufa, ulv *bufb, size_t count) { 190 | ulv *p1 = bufa; 191 | ulv *p2 = bufb; 192 | size_t i; 193 | ul q = rand_ul(); 194 | 195 | for (i = 0; i < count; i++) { 196 | *p1++ &= q; 197 | *p2++ &= q; 198 | } 199 | return compare_regions(bufa, bufb, count); 200 | } 201 | 202 | int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) { 203 | ulv *p1 = bufa; 204 | ulv *p2 = bufb; 205 | size_t i; 206 | ul q = rand_ul(); 207 | 208 | for (i = 0; i < count; i++) { 209 | *p1++ = *p2++ = (i + q); 210 | } 211 | return compare_regions(bufa, bufb, count); 212 | } 213 | 214 | int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) { 215 | ulv *p1 = bufa; 216 | ulv *p2 = bufb; 217 | unsigned int j; 218 | ul q; 219 | size_t i; 220 | 221 | out_test_start(); 222 | for (j = 0; j < 64; j++) { 223 | q = (j % 2) == 0 ? UL_ONEBITS : 0; 224 | out_test_setting(j); 225 | p1 = (ulv *) bufa; 226 | p2 = (ulv *) bufb; 227 | for (i = 0; i < count; i++) { 228 | *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; 229 | } 230 | out_test_testing(j); 231 | if (compare_regions(bufa, bufb, count)) { 232 | return -1; 233 | } 234 | } 235 | out_test_end(); 236 | return 0; 237 | } 238 | 239 | int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) { 240 | ulv *p1 = bufa; 241 | ulv *p2 = bufb; 242 | unsigned int j; 243 | ul q; 244 | size_t i; 245 | 246 | out_test_start(); 247 | for (j = 0; j < 64; j++) { 248 | q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2; 249 | out_test_setting(j); 250 | p1 = (ulv *) bufa; 251 | p2 = (ulv *) bufb; 252 | for (i = 0; i < count; i++) { 253 | *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; 254 | } 255 | out_test_testing(j); 256 | if (compare_regions(bufa, bufb, count)) { 257 | return -1; 258 | } 259 | } 260 | out_test_end(); 261 | return 0; 262 | } 263 | 264 | int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) { 265 | ulv *p1 = bufa; 266 | ulv *p2 = bufb; 267 | unsigned int j; 268 | size_t i; 269 | 270 | out_test_start(); 271 | for (j = 0; j < 256; j++) { 272 | p1 = (ulv *) bufa; 273 | p2 = (ulv *) bufb; 274 | out_test_setting(j); 275 | for (i = 0; i < count; i++) { 276 | *p1++ = *p2++ = (ul) UL_BYTE(j); 277 | } 278 | out_test_testing(j); 279 | if (compare_regions(bufa, bufb, count)) { 280 | return -1; 281 | } 282 | } 283 | out_test_end(); 284 | return 0; 285 | } 286 | 287 | int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count) { 288 | ulv *p1 = bufa; 289 | ulv *p2 = bufb; 290 | unsigned int j; 291 | size_t i; 292 | 293 | out_test_start(); 294 | for (j = 0; j < UL_LEN * 2; j++) { 295 | p1 = (ulv *) bufa; 296 | p2 = (ulv *) bufb; 297 | out_test_setting(j); 298 | for (i = 0; i < count; i++) { 299 | if (j < UL_LEN) { /* Walk it up. */ 300 | *p1++ = *p2++ = ONE << j; 301 | } else { /* Walk it back down. */ 302 | *p1++ = *p2++ = ONE << (UL_LEN * 2 - j - 1); 303 | } 304 | } 305 | out_test_testing(j); 306 | if (compare_regions(bufa, bufb, count)) { 307 | return -1; 308 | } 309 | } 310 | out_test_end(); 311 | return 0; 312 | } 313 | 314 | int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) { 315 | ulv *p1 = bufa; 316 | ulv *p2 = bufb; 317 | unsigned int j; 318 | size_t i; 319 | 320 | out_test_start(); 321 | for (j = 0; j < UL_LEN * 2; j++) { 322 | p1 = (ulv *) bufa; 323 | p2 = (ulv *) bufb; 324 | out_test_setting(j); 325 | for (i = 0; i < count; i++) { 326 | if (j < UL_LEN) { /* Walk it up. */ 327 | *p1++ = *p2++ = UL_ONEBITS ^ (ONE << j); 328 | } else { /* Walk it back down. */ 329 | *p1++ = *p2++ = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1)); 330 | } 331 | } 332 | out_test_testing(j); 333 | if (compare_regions(bufa, bufb, count)) { 334 | return -1; 335 | } 336 | } 337 | out_test_end(); 338 | return 0; 339 | } 340 | 341 | int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) { 342 | ulv *p1 = bufa; 343 | ulv *p2 = bufb; 344 | unsigned int j; 345 | size_t i; 346 | 347 | out_test_start(); 348 | for (j = 0; j < UL_LEN * 2; j++) { 349 | p1 = (ulv *) bufa; 350 | p2 = (ulv *) bufb; 351 | out_test_setting(j); 352 | for (i = 0; i < count; i++) { 353 | if (j < UL_LEN) { /* Walk it up. */ 354 | *p1++ = *p2++ = (i % 2 == 0) 355 | ? (ONE << j) | (ONE << (j + 2)) 356 | : UL_ONEBITS ^ ((ONE << j) 357 | | (ONE << (j + 2))); 358 | } else { /* Walk it back down. */ 359 | *p1++ = *p2++ = (i % 2 == 0) 360 | ? (ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 + 1 - j)) 361 | : UL_ONEBITS ^ (ONE << (UL_LEN * 2 - 1 - j) 362 | | (ONE << (UL_LEN * 2 + 1 - j))); 363 | } 364 | } 365 | out_test_testing(j); 366 | if (compare_regions(bufa, bufb, count)) { 367 | return -1; 368 | } 369 | } 370 | out_test_end(); 371 | return 0; 372 | } 373 | 374 | int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) { 375 | ulv *p1 = bufa; 376 | ulv *p2 = bufb; 377 | unsigned int j, k; 378 | ul q; 379 | size_t i; 380 | 381 | out_test_start(); 382 | for (k = 0; k < UL_LEN; k++) { 383 | q = ONE << k; 384 | for (j = 0; j < 8; j++) { 385 | q = ~q; 386 | out_test_setting(k * 8 + j); 387 | p1 = (ulv *) bufa; 388 | p2 = (ulv *) bufb; 389 | for (i = 0; i < count; i++) { 390 | *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; 391 | } 392 | out_test_testing(k * 8 + j); 393 | fflush(stdout); 394 | if (compare_regions(bufa, bufb, count)) { 395 | return -1; 396 | } 397 | } 398 | } 399 | out_test_end(); 400 | return 0; 401 | } 402 | 403 | #ifdef TEST_NARROW_WRITES 404 | int test_8bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { 405 | u8v *p1, *t; 406 | ulv *p2; 407 | int attempt; 408 | unsigned int b; 409 | size_t i; 410 | 411 | out_wheel_start(); 412 | for (attempt = 0; attempt < 2; attempt++) { 413 | if (attempt & 1) { 414 | p1 = (u8v *) bufa; 415 | p2 = bufb; 416 | } else { 417 | p1 = (u8v *) bufb; 418 | p2 = bufa; 419 | } 420 | for (i = 0; i < count; i++) { 421 | t = mword8.bytes; 422 | *p2++ = mword8.val = rand_ul(); 423 | for (b=0; b < UL_LEN/8; b++) { 424 | *p1++ = *t++; 425 | } 426 | out_wheel_advance(i); 427 | } 428 | if (compare_regions(bufa, bufb, count)) { 429 | return -1; 430 | } 431 | } 432 | out_wheel_end(); 433 | return 0; 434 | } 435 | 436 | int test_16bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { 437 | u16v *p1, *t; 438 | ulv *p2; 439 | int attempt; 440 | unsigned int b; 441 | size_t i; 442 | 443 | out_wheel_start(); 444 | for (attempt = 0; attempt < 2; attempt++) { 445 | if (attempt & 1) { 446 | p1 = (u16v *) bufa; 447 | p2 = bufb; 448 | } else { 449 | p1 = (u16v *) bufb; 450 | p2 = bufa; 451 | } 452 | for (i = 0; i < count; i++) { 453 | t = mword16.u16s; 454 | *p2++ = mword16.val = rand_ul(); 455 | for (b = 0; b < UL_LEN/16; b++) { 456 | *p1++ = *t++; 457 | } 458 | out_wheel_advance(i); 459 | } 460 | if (compare_regions(bufa, bufb, count)) { 461 | return -1; 462 | } 463 | } 464 | out_wheel_end(); 465 | return 0; 466 | } 467 | #endif 468 | -------------------------------------------------------------------------------- /tests.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Very simple yet very effective memory tester. 3 | * Originally by Simon Kirby 4 | * Version 2 by Charles Cazabon 5 | * Version 3 not publicly released. 6 | * Version 4 rewrite: 7 | * Copyright (C) 2004-2020 Charles Cazabon 8 | * Licensed under the terms of the GNU General Public License version 2 (only). 9 | * See the file COPYING for details. 10 | * 11 | * This file contains the declarations for the functions for the actual tests, 12 | * called from the main routine in memtester.c. See other comments in that 13 | * file. 14 | * 15 | */ 16 | 17 | /* Function declaration. */ 18 | 19 | int test_stuck_address(unsigned long volatile *bufa, size_t count); 20 | int test_random_value(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 21 | int test_xor_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 22 | int test_sub_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 23 | int test_mul_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 24 | int test_div_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 25 | int test_or_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 26 | int test_and_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 27 | int test_seqinc_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 28 | int test_solidbits_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 29 | int test_checkerboard_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 30 | int test_blockseq_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 31 | int test_walkbits0_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 32 | int test_walkbits1_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 33 | int test_bitspread_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 34 | int test_bitflip_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 35 | #ifdef TEST_NARROW_WRITES 36 | int test_8bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 37 | int test_16bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count); 38 | #endif 39 | -------------------------------------------------------------------------------- /trycpp.c: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | #ifdef NeXT 4 | printf("nextstep\n"); exit(0); 5 | #endif 6 | printf("unknown\n"); exit(0); 7 | } 8 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Very simple but very effective user-space memory tester. 3 | * Originally by Simon Kirby 4 | * Version 2 by Charles Cazabon 5 | * Version 3 not publicly released. 6 | * Version 4 rewrite: 7 | * Copyright (C) 2004-2020 Charles Cazabon 8 | * Licensed under the terms of the GNU General Public License version 2 (only). 9 | * See the file COPYING for details. 10 | * 11 | * This file contains typedefs, structure, and union definitions. 12 | * 13 | */ 14 | 15 | #include "sizes.h" 16 | 17 | typedef unsigned long ul; 18 | typedef unsigned long long ull; 19 | typedef unsigned long volatile ulv; 20 | typedef unsigned char volatile u8v; 21 | typedef unsigned short volatile u16v; 22 | 23 | struct test { 24 | char *name; 25 | int (*fp)(); 26 | }; 27 | -------------------------------------------------------------------------------- /warn-auto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # WARNING: This file was auto-generated. Do not edit! 3 | --------------------------------------------------------------------------------