OLD | NEW |
| (Empty) |
1 /*- | |
2 * Copyright 2009 Colin Percival | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * | |
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
24 * SUCH DAMAGE. | |
25 * | |
26 * This file was originally written by Colin Percival as part of the Tarsnap | |
27 * online backup system. | |
28 */ | |
29 #include "scrypt_platform.h" | |
30 | |
31 #include <sys/time.h> | |
32 | |
33 #include <stdint.h> | |
34 #include <stdio.h> | |
35 #include <time.h> | |
36 | |
37 #include "crypto_scrypt.h" | |
38 | |
39 #include "scryptenc_cpuperf.h" | |
40 | |
41 #ifdef HAVE_CLOCK_GETTIME | |
42 | |
43 static clock_t clocktouse; | |
44 | |
45 static int | |
46 getclockres(double * resd) | |
47 { | |
48 struct timespec res; | |
49 | |
50 /* | |
51 * Try clocks in order of preference until we find one which works. | |
52 * (We assume that if clock_getres works, clock_gettime will, too.) | |
53 * The use of if/else/if/else/if/else rather than if/elif/elif/else | |
54 * is ugly but legal, and allows us to #ifdef things appropriately. | |
55 */ | |
56 #ifdef CLOCK_VIRTUAL | |
57 if (clock_getres(CLOCK_VIRTUAL, &res) == 0) | |
58 clocktouse = CLOCK_VIRTUAL; | |
59 else | |
60 #endif | |
61 #ifdef CLOCK_MONOTONIC | |
62 if (clock_getres(CLOCK_MONOTONIC, &res) == 0) | |
63 clocktouse = CLOCK_MONOTONIC; | |
64 else | |
65 #endif | |
66 if (clock_getres(CLOCK_REALTIME, &res) == 0) | |
67 clocktouse = CLOCK_REALTIME; | |
68 else | |
69 return (-1); | |
70 | |
71 /* Convert clock resolution to a double. */ | |
72 *resd = res.tv_sec + res.tv_nsec * 0.000000001; | |
73 | |
74 return (0); | |
75 } | |
76 | |
77 static int | |
78 getclocktime(struct timespec * ts) | |
79 { | |
80 | |
81 if (clock_gettime(clocktouse, ts)) | |
82 return (-1); | |
83 | |
84 return (0); | |
85 } | |
86 | |
87 #else | |
88 static int | |
89 getclockres(double * resd) | |
90 { | |
91 | |
92 *resd = 1.0 / CLOCKS_PER_SEC; | |
93 | |
94 return (0); | |
95 } | |
96 | |
97 static int | |
98 getclocktime(struct timespec * ts) | |
99 { | |
100 struct timeval tv; | |
101 | |
102 if (gettimeofday(&tv, NULL)) | |
103 return (-1); | |
104 ts->tv_sec = tv.tv_sec; | |
105 ts->tv_nsec = tv.tv_usec * 1000; | |
106 | |
107 return (0); | |
108 } | |
109 #endif | |
110 | |
111 static int | |
112 getclockdiff(struct timespec * st, double * diffd) | |
113 { | |
114 struct timespec en; | |
115 | |
116 if (getclocktime(&en)) | |
117 return (1); | |
118 *diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 + | |
119 (en.tv_sec - st->tv_sec); | |
120 | |
121 return (0); | |
122 } | |
123 | |
124 /** | |
125 * scryptenc_cpuperf(opps): | |
126 * Estimate the number of salsa20/8 cores which can be executed per second, | |
127 * and return the value via opps. | |
128 */ | |
129 int | |
130 scryptenc_cpuperf(double * opps) | |
131 { | |
132 struct timespec st; | |
133 double resd, diffd; | |
134 uint64_t i = 0; | |
135 | |
136 /* Get the clock resolution. */ | |
137 if (getclockres(&resd)) | |
138 return (2); | |
139 | |
140 #ifdef DEBUG | |
141 fprintf(stderr, "Clock resolution is %f\n", resd); | |
142 #endif | |
143 | |
144 /* Loop until the clock ticks. */ | |
145 if (getclocktime(&st)) | |
146 return (2); | |
147 do { | |
148 /* Do an scrypt. */ | |
149 if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0)) | |
150 return (3); | |
151 | |
152 /* Has the clock ticked? */ | |
153 if (getclockdiff(&st, &diffd)) | |
154 return (2); | |
155 if (diffd > 0) | |
156 break; | |
157 } while (1); | |
158 | |
159 /* Could how many scryps we can do before the next tick. */ | |
160 if (getclocktime(&st)) | |
161 return (2); | |
162 do { | |
163 /* Do an scrypt. */ | |
164 if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0)) | |
165 return (3); | |
166 | |
167 /* We invoked the salsa20/8 core 512 times. */ | |
168 i += 512; | |
169 | |
170 /* Check if we have looped for long enough. */ | |
171 if (getclockdiff(&st, &diffd)) | |
172 return (2); | |
173 if (diffd > resd) | |
174 break; | |
175 } while (1); | |
176 | |
177 #ifdef DEBUG | |
178 fprintf(stderr, "%ju salsa20/8 cores performed in %f seconds\n", | |
179 (uintmax_t)i, diffd); | |
180 #endif | |
181 | |
182 /* We can do approximately i salsa20/8 cores per diffd seconds. */ | |
183 *opps = i / diffd; | |
184 return (0); | |
185 } | |
OLD | NEW |