Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib: add Dhrystone benchmark test

When working on SoC bring-up, (a full) userspace may not be available,
making it hard to benchmark the CPU performance of the system under
development. Still, one may want to have a rough idea of the (relative)
performance of one or more CPU cores, especially when working on e.g. the
clock driver that controls the CPU core clock(s).

Hence make the classical Dhrystone 2.1 benchmark available as a Linux
kernel test module, based on[1].

When built-in, this benchmark can be run without any userspace present.

Parallel runs (run on multiple CPU cores) are supported, just kick the
"run" file multiple times.

Note that the actual figures depend on the configuration options that
control compiler optimization (e.g. CONFIG_CC_OPTIMIZE_FOR_SIZE vs.
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE), and on the compiler options used when
building the kernel in general. Hence numbers may differ from those
obtained by running similar benchmarks in userspace.

[1] https://github.com/qris/dhrystone-deb.git

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lkml.kernel.org/r/4d07ad990740a5f1e426ce4566fb514f60ec9bdd.1670509558.git.geert+renesas@glider.be
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Brendan Higgins <brendanhiggins@google.com>
Cc: David Gow <davidgow@google.com>
[geert+renesas@glider.be: fix uninitialized use of ret]
Link: https://lkml.kernel.org/r/alpine.DEB.2.22.394.2212190857310.137329@ramsan.of.borg
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Geert Uytterhoeven and committed by
Andrew Morton
d5528cc1 88ad32a7

+938
+35
lib/Kconfig.debug
··· 2079 2079 2080 2080 if RUNTIME_TESTING_MENU 2081 2081 2082 + config TEST_DHRY 2083 + tristate "Dhrystone benchmark test" 2084 + help 2085 + Enable this to include the Dhrystone 2.1 benchmark. This test 2086 + calculates the number of Dhrystones per second, and the number of 2087 + DMIPS (Dhrystone MIPS) obtained when the Dhrystone score is divided 2088 + by 1757 (the number of Dhrystones per second obtained on the VAX 2089 + 11/780, nominally a 1 MIPS machine). 2090 + 2091 + To run the benchmark, it needs to be enabled explicitly, either from 2092 + the kernel command line (when built-in), or from userspace (when 2093 + built-in or modular. 2094 + 2095 + Run once during kernel boot: 2096 + 2097 + test_dhry.run 2098 + 2099 + Set number of iterations from kernel command line: 2100 + 2101 + test_dhry.iterations=<n> 2102 + 2103 + Set number of iterations from userspace: 2104 + 2105 + echo <n> > /sys/module/test_dhry/parameters/iterations 2106 + 2107 + Trigger manual run from userspace: 2108 + 2109 + echo y > /sys/module/test_dhry/parameters/run 2110 + 2111 + If the number of iterations is <= 0, the test will devise a suitable 2112 + number of iterations (test runs for at least 2s) automatically. 2113 + This process takes ca. 4s. 2114 + 2115 + If unsure, say N. 2116 + 2082 2117 config LKDTM 2083 2118 tristate "Linux Kernel Dump Test Tool Module" 2084 2119 depends on DEBUG_FS
+2
lib/Makefile
··· 57 57 obj-y += kstrtox.o 58 58 obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o 59 59 obj-$(CONFIG_TEST_BPF) += test_bpf.o 60 + test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o 61 + obj-$(CONFIG_TEST_DHRY) += test_dhry.o 60 62 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o 61 63 obj-$(CONFIG_TEST_BITOPS) += test_bitops.o 62 64 CFLAGS_test_bitops.o += -Werror
+358
lib/dhry.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + **************************************************************************** 4 + * 5 + * "DHRYSTONE" Benchmark Program 6 + * ----------------------------- 7 + * 8 + * Version: C, Version 2.1 9 + * 10 + * File: dhry.h (part 1 of 3) 11 + * 12 + * Date: May 25, 1988 13 + * 14 + * Author: Reinhold P. Weicker 15 + * Siemens AG, AUT E 51 16 + * Postfach 3220 17 + * 8520 Erlangen 18 + * Germany (West) 19 + * Phone: [+49]-9131-7-20330 20 + * (8-17 Central European Time) 21 + * Usenet: ..!mcsun!unido!estevax!weicker 22 + * 23 + * Original Version (in Ada) published in 24 + * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), 25 + * pp. 1013 - 1030, together with the statistics 26 + * on which the distribution of statements etc. is based. 27 + * 28 + * In this C version, the following C library functions are used: 29 + * - strcpy, strcmp (inside the measurement loop) 30 + * - printf, scanf (outside the measurement loop) 31 + * In addition, Berkeley UNIX system calls "times ()" or "time ()" 32 + * are used for execution time measurement. For measurements 33 + * on other systems, these calls have to be changed. 34 + * 35 + * Collection of Results: 36 + * Reinhold Weicker (address see above) and 37 + * 38 + * Rick Richardson 39 + * PC Research. Inc. 40 + * 94 Apple Orchard Drive 41 + * Tinton Falls, NJ 07724 42 + * Phone: (201) 389-8963 (9-17 EST) 43 + * Usenet: ...!uunet!pcrat!rick 44 + * 45 + * Please send results to Rick Richardson and/or Reinhold Weicker. 46 + * Complete information should be given on hardware and software used. 47 + * Hardware information includes: Machine type, CPU, type and size 48 + * of caches; for microprocessors: clock frequency, memory speed 49 + * (number of wait states). 50 + * Software information includes: Compiler (and runtime library) 51 + * manufacturer and version, compilation switches, OS version. 52 + * The Operating System version may give an indication about the 53 + * compiler; Dhrystone itself performs no OS calls in the measurement loop. 54 + * 55 + * The complete output generated by the program should be mailed 56 + * such that at least some checks for correctness can be made. 57 + * 58 + *************************************************************************** 59 + * 60 + * History: This version C/2.1 has been made for two reasons: 61 + * 62 + * 1) There is an obvious need for a common C version of 63 + * Dhrystone, since C is at present the most popular system 64 + * programming language for the class of processors 65 + * (microcomputers, minicomputers) where Dhrystone is used most. 66 + * There should be, as far as possible, only one C version of 67 + * Dhrystone such that results can be compared without 68 + * restrictions. In the past, the C versions distributed 69 + * by Rick Richardson (Version 1.1) and by Reinhold Weicker 70 + * had small (though not significant) differences. 71 + * 72 + * 2) As far as it is possible without changes to the Dhrystone 73 + * statistics, optimizing compilers should be prevented from 74 + * removing significant statements. 75 + * 76 + * This C version has been developed in cooperation with 77 + * Rick Richardson (Tinton Falls, NJ), it incorporates many 78 + * ideas from the "Version 1.1" distributed previously by 79 + * him over the UNIX network Usenet. 80 + * I also thank Chaim Benedelac (National Semiconductor), 81 + * David Ditzel (SUN), Earl Killian and John Mashey (MIPS), 82 + * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) 83 + * for their help with comments on earlier versions of the 84 + * benchmark. 85 + * 86 + * Changes: In the initialization part, this version follows mostly 87 + * Rick Richardson's version distributed via Usenet, not the 88 + * version distributed earlier via floppy disk by Reinhold Weicker. 89 + * As a concession to older compilers, names have been made 90 + * unique within the first 8 characters. 91 + * Inside the measurement loop, this version follows the 92 + * version previously distributed by Reinhold Weicker. 93 + * 94 + * At several places in the benchmark, code has been added, 95 + * but within the measurement loop only in branches that 96 + * are not executed. The intention is that optimizing compilers 97 + * should be prevented from moving code out of the measurement 98 + * loop, or from removing code altogether. Since the statements 99 + * that are executed within the measurement loop have NOT been 100 + * changed, the numbers defining the "Dhrystone distribution" 101 + * (distribution of statements, operand types and locality) 102 + * still hold. Except for sophisticated optimizing compilers, 103 + * execution times for this version should be the same as 104 + * for previous versions. 105 + * 106 + * Since it has proven difficult to subtract the time for the 107 + * measurement loop overhead in a correct way, the loop check 108 + * has been made a part of the benchmark. This does have 109 + * an impact - though a very minor one - on the distribution 110 + * statistics which have been updated for this version. 111 + * 112 + * All changes within the measurement loop are described 113 + * and discussed in the companion paper "Rationale for 114 + * Dhrystone version 2". 115 + * 116 + * Because of the self-imposed limitation that the order and 117 + * distribution of the executed statements should not be 118 + * changed, there are still cases where optimizing compilers 119 + * may not generate code for some statements. To a certain 120 + * degree, this is unavoidable for small synthetic benchmarks. 121 + * Users of the benchmark are advised to check code listings 122 + * whether code is generated for all statements of Dhrystone. 123 + * 124 + * Version 2.1 is identical to version 2.0 distributed via 125 + * the UNIX network Usenet in March 1988 except that it corrects 126 + * some minor deficiencies that were found by users of version 2.0. 127 + * The only change within the measurement loop is that a 128 + * non-executed "else" part was added to the "if" statement in 129 + * Func_3, and a non-executed "else" part removed from Proc_3. 130 + * 131 + *************************************************************************** 132 + * 133 + * Compilation model and measurement (IMPORTANT): 134 + * 135 + * This C version of Dhrystone consists of three files: 136 + * - dhry.h (this file, containing global definitions and comments) 137 + * - dhry_1.c (containing the code corresponding to Ada package Pack_1) 138 + * - dhry_2.c (containing the code corresponding to Ada package Pack_2) 139 + * 140 + * The following "ground rules" apply for measurements: 141 + * - Separate compilation 142 + * - No procedure merging 143 + * - Otherwise, compiler optimizations are allowed but should be indicated 144 + * - Default results are those without register declarations 145 + * See the companion paper "Rationale for Dhrystone Version 2" for a more 146 + * detailed discussion of these ground rules. 147 + * 148 + * For 16-Bit processors (e.g. 80186, 80286), times for all compilation 149 + * models ("small", "medium", "large" etc.) should be given if possible, 150 + * together with a definition of these models for the compiler system used. 151 + * 152 + ************************************************************************** 153 + * 154 + * Dhrystone (C version) statistics: 155 + * 156 + * [Comment from the first distribution, updated for version 2. 157 + * Note that because of language differences, the numbers are slightly 158 + * different from the Ada version.] 159 + * 160 + * The following program contains statements of a high level programming 161 + * language (here: C) in a distribution considered representative: 162 + * 163 + * assignments 52 (51.0 %) 164 + * control statements 33 (32.4 %) 165 + * procedure, function calls 17 (16.7 %) 166 + * 167 + * 103 statements are dynamically executed. The program is balanced with 168 + * respect to the three aspects: 169 + * 170 + * - statement type 171 + * - operand type 172 + * - operand locality 173 + * operand global, local, parameter, or constant. 174 + * 175 + * The combination of these three aspects is balanced only approximately. 176 + * 177 + * 1. Statement Type: 178 + * ----------------- number 179 + * 180 + * V1 = V2 9 181 + * (incl. V1 = F(..) 182 + * V = Constant 12 183 + * Assignment, 7 184 + * with array element 185 + * Assignment, 6 186 + * with record component 187 + * -- 188 + * 34 34 189 + * 190 + * X = Y +|-|"&&"|"|" Z 5 191 + * X = Y +|-|"==" Constant 6 192 + * X = X +|- 1 3 193 + * X = Y *|/ Z 2 194 + * X = Expression, 1 195 + * two operators 196 + * X = Expression, 1 197 + * three operators 198 + * -- 199 + * 18 18 200 + * 201 + * if .... 14 202 + * with "else" 7 203 + * without "else" 7 204 + * executed 3 205 + * not executed 4 206 + * for ... 7 | counted every time 207 + * while ... 4 | the loop condition 208 + * do ... while 1 | is evaluated 209 + * switch ... 1 210 + * break 1 211 + * declaration with 1 212 + * initialization 213 + * -- 214 + * 34 34 215 + * 216 + * P (...) procedure call 11 217 + * user procedure 10 218 + * library procedure 1 219 + * X = F (...) 220 + * function call 6 221 + * user function 5 222 + * library function 1 223 + * -- 224 + * 17 17 225 + * --- 226 + * 103 227 + * 228 + * The average number of parameters in procedure or function calls 229 + * is 1.82 (not counting the function values as implicit parameters). 230 + * 231 + * 232 + * 2. Operators 233 + * ------------ 234 + * number approximate 235 + * percentage 236 + * 237 + * Arithmetic 32 50.8 238 + * 239 + * + 21 33.3 240 + * - 7 11.1 241 + * * 3 4.8 242 + * / (int div) 1 1.6 243 + * 244 + * Comparison 27 42.8 245 + * 246 + * == 9 14.3 247 + * /= 4 6.3 248 + * > 1 1.6 249 + * < 3 4.8 250 + * >= 1 1.6 251 + * <= 9 14.3 252 + * 253 + * Logic 4 6.3 254 + * 255 + * && (AND-THEN) 1 1.6 256 + * | (OR) 1 1.6 257 + * ! (NOT) 2 3.2 258 + * 259 + * -- ----- 260 + * 63 100.1 261 + * 262 + * 263 + * 3. Operand Type (counted once per operand reference): 264 + * --------------- 265 + * number approximate 266 + * percentage 267 + * 268 + * Integer 175 72.3 % 269 + * Character 45 18.6 % 270 + * Pointer 12 5.0 % 271 + * String30 6 2.5 % 272 + * Array 2 0.8 % 273 + * Record 2 0.8 % 274 + * --- ------- 275 + * 242 100.0 % 276 + * 277 + * When there is an access path leading to the final operand (e.g. a record 278 + * component), only the final data type on the access path is counted. 279 + * 280 + * 281 + * 4. Operand Locality: 282 + * ------------------- 283 + * number approximate 284 + * percentage 285 + * 286 + * local variable 114 47.1 % 287 + * global variable 22 9.1 % 288 + * parameter 45 18.6 % 289 + * value 23 9.5 % 290 + * reference 22 9.1 % 291 + * function result 6 2.5 % 292 + * constant 55 22.7 % 293 + * --- ------- 294 + * 242 100.0 % 295 + * 296 + * 297 + * The program does not compute anything meaningful, but it is syntactically 298 + * and semantically correct. All variables have a value assigned to them 299 + * before they are used as a source operand. 300 + * 301 + * There has been no explicit effort to account for the effects of a 302 + * cache, or to balance the use of long or short displacements for code or 303 + * data. 304 + * 305 + *************************************************************************** 306 + */ 307 + 308 + typedef enum { 309 + Ident_1, 310 + Ident_2, 311 + Ident_3, 312 + Ident_4, 313 + Ident_5 314 + } Enumeration; /* for boolean and enumeration types in Ada, Pascal */ 315 + 316 + /* General definitions: */ 317 + 318 + typedef int One_Thirty; 319 + typedef int One_Fifty; 320 + typedef char Capital_Letter; 321 + typedef int Boolean; 322 + typedef char Str_30[31]; 323 + typedef int Arr_1_Dim[50]; 324 + typedef int Arr_2_Dim[50][50]; 325 + 326 + typedef struct record { 327 + struct record *Ptr_Comp; 328 + Enumeration Discr; 329 + union { 330 + struct { 331 + Enumeration Enum_Comp; 332 + int Int_Comp; 333 + char Str_Comp[31]; 334 + } var_1; 335 + struct { 336 + Enumeration E_Comp_2; 337 + char Str_2_Comp[31]; 338 + } var_2; 339 + struct { 340 + char Ch_1_Comp; 341 + char Ch_2_Comp; 342 + } var_3; 343 + } variant; 344 + } Rec_Type, *Rec_Pointer; 345 + 346 + 347 + extern int Int_Glob; 348 + extern char Ch_1_Glob; 349 + 350 + void Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par); 351 + void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, 352 + One_Fifty *Int_Par_Ref); 353 + void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, 354 + int Int_1_Par_Val, int Int_2_Par_Val); 355 + Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val); 356 + Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref); 357 + 358 + int dhry(int n);
+283
lib/dhry_1.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + /* 3 + **************************************************************************** 4 + * 5 + * "DHRYSTONE" Benchmark Program 6 + * ----------------------------- 7 + * 8 + * Version: C, Version 2.1 9 + * 10 + * File: dhry_1.c (part 2 of 3) 11 + * 12 + * Date: May 25, 1988 13 + * 14 + * Author: Reinhold P. Weicker 15 + * 16 + **************************************************************************** 17 + */ 18 + 19 + #include "dhry.h" 20 + 21 + #include <linux/ktime.h> 22 + #include <linux/slab.h> 23 + #include <linux/string.h> 24 + 25 + /* Global Variables: */ 26 + 27 + int Int_Glob; 28 + char Ch_1_Glob; 29 + 30 + static Rec_Pointer Ptr_Glob, Next_Ptr_Glob; 31 + static Boolean Bool_Glob; 32 + static char Ch_2_Glob; 33 + static int Arr_1_Glob[50]; 34 + static int Arr_2_Glob[50][50]; 35 + 36 + static void Proc_3(Rec_Pointer *Ptr_Ref_Par) 37 + /******************/ 38 + /* executed once */ 39 + /* Ptr_Ref_Par becomes Ptr_Glob */ 40 + { 41 + if (Ptr_Glob) { 42 + /* then, executed */ 43 + *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; 44 + } 45 + Proc_7(10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); 46 + } /* Proc_3 */ 47 + 48 + 49 + static void Proc_1(Rec_Pointer Ptr_Val_Par) 50 + /******************/ 51 + /* executed once */ 52 + { 53 + Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; 54 + /* == Ptr_Glob_Next */ 55 + /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ 56 + /* corresponds to "rename" in Ada, "with" in Pascal */ 57 + 58 + *Ptr_Val_Par->Ptr_Comp = *Ptr_Glob; 59 + Ptr_Val_Par->variant.var_1.Int_Comp = 5; 60 + Next_Record->variant.var_1.Int_Comp = 61 + Ptr_Val_Par->variant.var_1.Int_Comp; 62 + Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; 63 + Proc_3(&Next_Record->Ptr_Comp); 64 + /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp == Ptr_Glob->Ptr_Comp */ 65 + if (Next_Record->Discr == Ident_1) { 66 + /* then, executed */ 67 + Next_Record->variant.var_1.Int_Comp = 6; 68 + Proc_6(Ptr_Val_Par->variant.var_1.Enum_Comp, 69 + &Next_Record->variant.var_1.Enum_Comp); 70 + Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; 71 + Proc_7(Next_Record->variant.var_1.Int_Comp, 10, 72 + &Next_Record->variant.var_1.Int_Comp); 73 + } else { 74 + /* not executed */ 75 + *Ptr_Val_Par = *Ptr_Val_Par->Ptr_Comp; 76 + } 77 + } /* Proc_1 */ 78 + 79 + 80 + static void Proc_2(One_Fifty *Int_Par_Ref) 81 + /******************/ 82 + /* executed once */ 83 + /* *Int_Par_Ref == 1, becomes 4 */ 84 + { 85 + One_Fifty Int_Loc; 86 + Enumeration Enum_Loc; 87 + 88 + Int_Loc = *Int_Par_Ref + 10; 89 + do { 90 + /* executed once */ 91 + if (Ch_1_Glob == 'A') { 92 + /* then, executed */ 93 + Int_Loc -= 1; 94 + *Int_Par_Ref = Int_Loc - Int_Glob; 95 + Enum_Loc = Ident_1; 96 + } /* if */ 97 + } while (Enum_Loc != Ident_1); /* true */ 98 + } /* Proc_2 */ 99 + 100 + 101 + static void Proc_4(void) 102 + /*******/ 103 + /* executed once */ 104 + { 105 + Boolean Bool_Loc; 106 + 107 + Bool_Loc = Ch_1_Glob == 'A'; 108 + Bool_Glob = Bool_Loc | Bool_Glob; 109 + Ch_2_Glob = 'B'; 110 + } /* Proc_4 */ 111 + 112 + 113 + static void Proc_5(void) 114 + /*******/ 115 + /* executed once */ 116 + { 117 + Ch_1_Glob = 'A'; 118 + Bool_Glob = false; 119 + } /* Proc_5 */ 120 + 121 + 122 + int dhry(int n) 123 + /*****/ 124 + 125 + /* main program, corresponds to procedures */ 126 + /* Main and Proc_0 in the Ada version */ 127 + { 128 + One_Fifty Int_1_Loc; 129 + One_Fifty Int_2_Loc; 130 + One_Fifty Int_3_Loc; 131 + char Ch_Index; 132 + Enumeration Enum_Loc; 133 + Str_30 Str_1_Loc; 134 + Str_30 Str_2_Loc; 135 + int Run_Index; 136 + int Number_Of_Runs; 137 + ktime_t Begin_Time, End_Time; 138 + u32 User_Time; 139 + 140 + /* Initializations */ 141 + 142 + Next_Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL); 143 + Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL); 144 + 145 + Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; 146 + Ptr_Glob->Discr = Ident_1; 147 + Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; 148 + Ptr_Glob->variant.var_1.Int_Comp = 40; 149 + strcpy(Ptr_Glob->variant.var_1.Str_Comp, 150 + "DHRYSTONE PROGRAM, SOME STRING"); 151 + strcpy(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); 152 + 153 + Arr_2_Glob[8][7] = 10; 154 + /* Was missing in published program. Without this statement, */ 155 + /* Arr_2_Glob[8][7] would have an undefined value. */ 156 + /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ 157 + /* overflow may occur for this array element. */ 158 + 159 + pr_debug("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); 160 + 161 + Number_Of_Runs = n; 162 + 163 + pr_debug("Execution starts, %d runs through Dhrystone\n", 164 + Number_Of_Runs); 165 + 166 + /***************/ 167 + /* Start timer */ 168 + /***************/ 169 + 170 + Begin_Time = ktime_get(); 171 + 172 + for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) { 173 + Proc_5(); 174 + Proc_4(); 175 + /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ 176 + Int_1_Loc = 2; 177 + Int_2_Loc = 3; 178 + strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); 179 + Enum_Loc = Ident_2; 180 + Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc); 181 + /* Bool_Glob == 1 */ 182 + while (Int_1_Loc < Int_2_Loc) { 183 + /* loop body executed once */ 184 + Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; 185 + /* Int_3_Loc == 7 */ 186 + Proc_7(Int_1_Loc, Int_2_Loc, &Int_3_Loc); 187 + /* Int_3_Loc == 7 */ 188 + Int_1_Loc += 1; 189 + } /* while */ 190 + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 191 + Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); 192 + /* Int_Glob == 5 */ 193 + Proc_1(Ptr_Glob); 194 + for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) { 195 + /* loop body executed twice */ 196 + if (Enum_Loc == Func_1(Ch_Index, 'C')) { 197 + /* then, not executed */ 198 + Proc_6(Ident_1, &Enum_Loc); 199 + strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); 200 + Int_2_Loc = Run_Index; 201 + Int_Glob = Run_Index; 202 + } 203 + } 204 + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 205 + Int_2_Loc = Int_2_Loc * Int_1_Loc; 206 + Int_1_Loc = Int_2_Loc / Int_3_Loc; 207 + Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; 208 + /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ 209 + Proc_2(&Int_1_Loc); 210 + /* Int_1_Loc == 5 */ 211 + 212 + } /* loop "for Run_Index" */ 213 + 214 + /**************/ 215 + /* Stop timer */ 216 + /**************/ 217 + 218 + End_Time = ktime_get(); 219 + 220 + #define dhry_assert_int_eq(val, expected) \ 221 + if (val != expected) \ 222 + pr_err("%s: %d (FAIL, expected %d)\n", #val, val, \ 223 + expected); \ 224 + else \ 225 + pr_debug("%s: %d (OK)\n", #val, val) 226 + 227 + #define dhry_assert_char_eq(val, expected) \ 228 + if (val != expected) \ 229 + pr_err("%s: %c (FAIL, expected %c)\n", #val, val, \ 230 + expected); \ 231 + else \ 232 + pr_debug("%s: %c (OK)\n", #val, val) 233 + 234 + #define dhry_assert_string_eq(val, expected) \ 235 + if (strcmp(val, expected)) \ 236 + pr_err("%s: %s (FAIL, expected %s)\n", #val, val, \ 237 + expected); \ 238 + else \ 239 + pr_debug("%s: %s (OK)\n", #val, val) 240 + 241 + pr_debug("Execution ends\n"); 242 + pr_debug("Final values of the variables used in the benchmark:\n"); 243 + dhry_assert_int_eq(Int_Glob, 5); 244 + dhry_assert_int_eq(Bool_Glob, 1); 245 + dhry_assert_char_eq(Ch_1_Glob, 'A'); 246 + dhry_assert_char_eq(Ch_2_Glob, 'B'); 247 + dhry_assert_int_eq(Arr_1_Glob[8], 7); 248 + dhry_assert_int_eq(Arr_2_Glob[8][7], Number_Of_Runs + 10); 249 + pr_debug("Ptr_Comp: %px\n", Ptr_Glob->Ptr_Comp); 250 + dhry_assert_int_eq(Ptr_Glob->Discr, 0); 251 + dhry_assert_int_eq(Ptr_Glob->variant.var_1.Enum_Comp, 2); 252 + dhry_assert_int_eq(Ptr_Glob->variant.var_1.Int_Comp, 17); 253 + dhry_assert_string_eq(Ptr_Glob->variant.var_1.Str_Comp, 254 + "DHRYSTONE PROGRAM, SOME STRING"); 255 + if (Next_Ptr_Glob->Ptr_Comp != Ptr_Glob->Ptr_Comp) 256 + pr_err("Next_Ptr_Glob->Ptr_Comp: %px (expected %px)\n", 257 + Next_Ptr_Glob->Ptr_Comp, Ptr_Glob->Ptr_Comp); 258 + else 259 + pr_debug("Next_Ptr_Glob->Ptr_Comp: %px\n", 260 + Next_Ptr_Glob->Ptr_Comp); 261 + dhry_assert_int_eq(Next_Ptr_Glob->Discr, 0); 262 + dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Enum_Comp, 1); 263 + dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Int_Comp, 18); 264 + dhry_assert_string_eq(Next_Ptr_Glob->variant.var_1.Str_Comp, 265 + "DHRYSTONE PROGRAM, SOME STRING"); 266 + dhry_assert_int_eq(Int_1_Loc, 5); 267 + dhry_assert_int_eq(Int_2_Loc, 13); 268 + dhry_assert_int_eq(Int_3_Loc, 7); 269 + dhry_assert_int_eq(Enum_Loc, 1); 270 + dhry_assert_string_eq(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); 271 + dhry_assert_string_eq(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); 272 + 273 + User_Time = ktime_to_ms(ktime_sub(End_Time, Begin_Time)); 274 + 275 + kfree(Ptr_Glob); 276 + kfree(Next_Ptr_Glob); 277 + 278 + /* Measurements should last at least 2 seconds */ 279 + if (User_Time < 2 * MSEC_PER_SEC) 280 + return -EAGAIN; 281 + 282 + return div_u64(mul_u32_u32(MSEC_PER_SEC, Number_Of_Runs), User_Time); 283 + }
+175
lib/dhry_2.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + /* 3 + **************************************************************************** 4 + * 5 + * "DHRYSTONE" Benchmark Program 6 + * ----------------------------- 7 + * 8 + * Version: C, Version 2.1 9 + * 10 + * File: dhry_2.c (part 3 of 3) 11 + * 12 + * Date: May 25, 1988 13 + * 14 + * Author: Reinhold P. Weicker 15 + * 16 + **************************************************************************** 17 + */ 18 + 19 + #include "dhry.h" 20 + 21 + #include <linux/string.h> 22 + 23 + 24 + static Boolean Func_3(Enumeration Enum_Par_Val) 25 + /***************************/ 26 + /* executed once */ 27 + /* Enum_Par_Val == Ident_3 */ 28 + { 29 + Enumeration Enum_Loc; 30 + 31 + Enum_Loc = Enum_Par_Val; 32 + if (Enum_Loc == Ident_3) { 33 + /* then, executed */ 34 + return true; 35 + } else { 36 + /* not executed */ 37 + return false; 38 + } 39 + } /* Func_3 */ 40 + 41 + 42 + void Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par) 43 + /*********************************/ 44 + /* executed once */ 45 + /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ 46 + { 47 + *Enum_Ref_Par = Enum_Val_Par; 48 + if (!Func_3(Enum_Val_Par)) { 49 + /* then, not executed */ 50 + *Enum_Ref_Par = Ident_4; 51 + } 52 + switch (Enum_Val_Par) { 53 + case Ident_1: 54 + *Enum_Ref_Par = Ident_1; 55 + break; 56 + case Ident_2: 57 + if (Int_Glob > 100) { 58 + /* then */ 59 + *Enum_Ref_Par = Ident_1; 60 + } else { 61 + *Enum_Ref_Par = Ident_4; 62 + } 63 + break; 64 + case Ident_3: /* executed */ 65 + *Enum_Ref_Par = Ident_2; 66 + break; 67 + case Ident_4: 68 + break; 69 + case Ident_5: 70 + *Enum_Ref_Par = Ident_3; 71 + break; 72 + } /* switch */ 73 + } /* Proc_6 */ 74 + 75 + 76 + void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref) 77 + /**********************************************/ 78 + /* executed three times */ 79 + /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ 80 + /* Int_Par_Ref becomes 7 */ 81 + /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ 82 + /* Int_Par_Ref becomes 17 */ 83 + /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ 84 + /* Int_Par_Ref becomes 18 */ 85 + { 86 + One_Fifty Int_Loc; 87 + 88 + Int_Loc = Int_1_Par_Val + 2; 89 + *Int_Par_Ref = Int_2_Par_Val + Int_Loc; 90 + } /* Proc_7 */ 91 + 92 + 93 + void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val) 94 + /*********************************************************************/ 95 + /* executed once */ 96 + /* Int_Par_Val_1 == 3 */ 97 + /* Int_Par_Val_2 == 7 */ 98 + { 99 + One_Fifty Int_Index; 100 + One_Fifty Int_Loc; 101 + 102 + Int_Loc = Int_1_Par_Val + 5; 103 + Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val; 104 + Arr_1_Par_Ref[Int_Loc+1] = Arr_1_Par_Ref[Int_Loc]; 105 + Arr_1_Par_Ref[Int_Loc+30] = Int_Loc; 106 + for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) 107 + Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc; 108 + Arr_2_Par_Ref[Int_Loc][Int_Loc-1] += 1; 109 + Arr_2_Par_Ref[Int_Loc+20][Int_Loc] = Arr_1_Par_Ref[Int_Loc]; 110 + Int_Glob = 5; 111 + } /* Proc_8 */ 112 + 113 + 114 + Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val) 115 + /*************************************************/ 116 + /* executed three times */ 117 + /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ 118 + /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ 119 + /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ 120 + { 121 + Capital_Letter Ch_1_Loc; 122 + Capital_Letter Ch_2_Loc; 123 + 124 + Ch_1_Loc = Ch_1_Par_Val; 125 + Ch_2_Loc = Ch_1_Loc; 126 + if (Ch_2_Loc != Ch_2_Par_Val) { 127 + /* then, executed */ 128 + return Ident_1; 129 + } else { 130 + /* not executed */ 131 + Ch_1_Glob = Ch_1_Loc; 132 + return Ident_2; 133 + } 134 + } /* Func_1 */ 135 + 136 + 137 + Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref) 138 + /*************************************************/ 139 + /* executed once */ 140 + /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ 141 + /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ 142 + { 143 + One_Thirty Int_Loc; 144 + Capital_Letter Ch_Loc; 145 + 146 + Int_Loc = 2; 147 + while (Int_Loc <= 2) { 148 + /* loop body executed once */ 149 + if (Func_1(Str_1_Par_Ref[Int_Loc], 150 + Str_2_Par_Ref[Int_Loc+1]) == Ident_1) { 151 + /* then, executed */ 152 + Ch_Loc = 'A'; 153 + Int_Loc += 1; 154 + } 155 + } /* if, while */ 156 + if (Ch_Loc >= 'W' && Ch_Loc < 'Z') { 157 + /* then, not executed */ 158 + Int_Loc = 7; 159 + } 160 + if (Ch_Loc == 'R') { 161 + /* then, not executed */ 162 + return true; 163 + } else { 164 + /* executed */ 165 + if (strcmp(Str_1_Par_Ref, Str_2_Par_Ref) > 0) { 166 + /* then, not executed */ 167 + Int_Loc += 7; 168 + Int_Glob = Int_Loc; 169 + return true; 170 + } else { 171 + /* executed */ 172 + return false; 173 + } 174 + } /* if Ch_Loc */ 175 + } /* Func_2 */
+85
lib/dhry_run.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Dhrystone benchmark test module 4 + * 5 + * Copyright (C) 2022 Glider bv 6 + */ 7 + 8 + #include "dhry.h" 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/moduleparam.h> 13 + #include <linux/mutex.h> 14 + #include <linux/smp.h> 15 + 16 + #define DHRY_VAX 1757 17 + 18 + static int dhry_run_set(const char *val, const struct kernel_param *kp); 19 + static const struct kernel_param_ops run_ops = { 20 + .flags = KERNEL_PARAM_OPS_FL_NOARG, 21 + .set = dhry_run_set, 22 + }; 23 + static bool dhry_run; 24 + module_param_cb(run, &run_ops, &dhry_run, 0200); 25 + MODULE_PARM_DESC(run, "Run the test (default: false)"); 26 + 27 + static int iterations = -1; 28 + module_param(iterations, int, 0644); 29 + MODULE_PARM_DESC(iterations, 30 + "Number of iterations through the benchmark (default: auto)"); 31 + 32 + static void dhry_benchmark(void) 33 + { 34 + int i, n; 35 + 36 + if (iterations > 0) { 37 + n = dhry(iterations); 38 + goto report; 39 + } 40 + 41 + for (i = DHRY_VAX; i > 0; i <<= 1) { 42 + n = dhry(i); 43 + if (n != -EAGAIN) 44 + break; 45 + } 46 + 47 + report: 48 + if (n >= 0) 49 + pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n", 50 + smp_processor_id(), n, n / DHRY_VAX); 51 + else if (n == -EAGAIN) 52 + pr_err("Please increase the number of iterations\n"); 53 + else 54 + pr_err("Dhrystone benchmark failed error %pe\n", ERR_PTR(n)); 55 + } 56 + 57 + static int dhry_run_set(const char *val, const struct kernel_param *kp) 58 + { 59 + int ret; 60 + 61 + if (val) { 62 + ret = param_set_bool(val, kp); 63 + if (ret) 64 + return ret; 65 + } else { 66 + dhry_run = true; 67 + } 68 + 69 + if (dhry_run && system_state == SYSTEM_RUNNING) 70 + dhry_benchmark(); 71 + 72 + return 0; 73 + } 74 + 75 + static int __init dhry_init(void) 76 + { 77 + if (dhry_run) 78 + dhry_benchmark(); 79 + 80 + return 0; 81 + } 82 + module_init(dhry_init); 83 + 84 + MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>"); 85 + MODULE_LICENSE("GPL");