VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTSemEvent.cpp@ 95595

Last change on this file since 95595 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 17.2 KB
Line 
1/* $Id: tstRTSemEvent.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT Testcase - Multiple Release Event Semaphores.
4 */
5
6/*
7 * Copyright (C) 2009-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/semaphore.h>
32
33#include <iprt/asm.h>
34#include <iprt/assert.h>
35#include <iprt/errcore.h>
36#include <iprt/rand.h>
37#include <iprt/stream.h>
38#include <iprt/string.h>
39#include <iprt/test.h>
40#include <iprt/thread.h>
41#include <iprt/time.h>
42
43
44/*********************************************************************************************************************************
45* Global Variables *
46*********************************************************************************************************************************/
47/** The test handle. */
48static RTTEST g_hTest;
49/** Use to stop test loops. */
50static volatile bool g_fStop = false;
51
52
53
54/*********************************************************************************************************************************
55* Benchmark #1: Two thread pinging each other on two event sempahores. *
56*********************************************************************************************************************************/
57/** Pair of event semphores for the first benchmark test. */
58static RTSEMEVENT g_ahEvtBench1[2];
59static uint64_t g_uTimeoutBench1;
60static uint64_t g_fWaitBench1;
61static uint64_t volatile g_cBench1Iterations;
62
63
64static DECLCALLBACK(int) bench1Thread(RTTHREAD hThreadSelf, void *pvUser)
65{
66 uintptr_t const idxThread = (uintptr_t)pvUser;
67 RT_NOREF(hThreadSelf);
68
69 uint64_t cIterations = 0;
70 for (;; cIterations++)
71 {
72 int rc = RTSemEventWaitEx(g_ahEvtBench1[idxThread], g_fWaitBench1, g_uTimeoutBench1);
73 if (RT_SUCCESS(rc))
74 RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_ahEvtBench1[(idxThread + 1) & 1]), VINF_SUCCESS);
75 else if ( rc == VERR_TIMEOUT
76 && g_uTimeoutBench1 == 0
77 && (g_fWaitBench1 & RTSEMWAIT_FLAGS_RELATIVE) )
78 { /* likely */ }
79 else
80 RTTestFailed(g_hTest, "rc=%Rrc g_fWaitBench1=%#x g_uTimeoutBench1=%#RX64 (now=%#RX64)",
81 rc, g_fWaitBench1, g_uTimeoutBench1, RTTimeSystemNanoTS());
82 if (g_fStop)
83 {
84 RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_ahEvtBench1[(idxThread + 1) & 1]), VINF_SUCCESS);
85 break;
86 }
87 }
88
89 if (idxThread == 0)
90 g_cBench1Iterations = cIterations;
91 return VINF_SUCCESS;
92}
93
94
95static void bench1(const char *pszTest, uint32_t fFlags, uint64_t uTimeout)
96{
97 RTTestISub(pszTest);
98
99 /*
100 * Create the two threads and make the wait on one another's sempahore.
101 */
102 g_fStop = false;
103 g_uTimeoutBench1 = uTimeout;
104 g_fWaitBench1 = fFlags;
105
106 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&g_ahEvtBench1[0]), VINF_SUCCESS);
107 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&g_ahEvtBench1[1]), VINF_SUCCESS);
108
109 RTTHREAD hThread1;
110 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, bench1Thread, (void *)0, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "bench1t1"), VINF_SUCCESS);
111 RTTHREAD hThread2;
112 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, bench1Thread, (void *)1, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "bench1t2"), VINF_SUCCESS);
113 RTThreadSleep(256);
114
115 /*
116 * Kick off the first thread and wait for 5 seconds before stopping them
117 * and seeing how many iterations they managed to perform.
118 */
119 uint64_t const nsStart = RTTimeNanoTS();
120 RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[0]), VINF_SUCCESS);
121 RTThreadSleep(RT_MS_5SEC);
122
123 ASMAtomicWriteBool(&g_fStop, true);
124 uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart;
125
126 RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[0]), VINF_SUCCESS); /* paranoia */
127 RTTESTI_CHECK_RC(RTThreadWait(hThread1, RT_MS_5SEC, NULL), VINF_SUCCESS);
128 RTTESTI_CHECK_RC(RTSemEventSignal(g_ahEvtBench1[1]), VINF_SUCCESS);
129 RTTESTI_CHECK_RC(RTThreadWait(hThread2, RT_MS_5SEC, NULL), VINF_SUCCESS);
130
131 RTTESTI_CHECK_RC(RTSemEventDestroy(g_ahEvtBench1[0]), VINF_SUCCESS);
132 RTTESTI_CHECK_RC(RTSemEventDestroy(g_ahEvtBench1[1]), VINF_SUCCESS);
133
134 /*
135 * Report the result.
136 */
137 uint64_t cIterations = g_cBench1Iterations;
138 RTTestValue(g_hTest, "Throughput", cIterations * RT_NS_1SEC / cNsElapsed, RTTESTUNIT_OCCURRENCES_PER_SEC);
139 RTTestValue(g_hTest, "Roundtrip", cNsElapsed / RT_MAX(cIterations, 1), RTTESTUNIT_NS_PER_OCCURRENCE);
140}
141
142
143/*********************************************************************************************************************************
144* Test #1: Simple setup checking wakup order of two waiting thread. *
145*********************************************************************************************************************************/
146
147static DECLCALLBACK(int) test1Thread(RTTHREAD hThreadSelf, void *pvUser)
148{
149 RTSEMEVENT hSem = *(PRTSEMEVENT)pvUser;
150 RTTEST_CHECK_RC(g_hTest, RTThreadUserSignal(hThreadSelf), VINF_SUCCESS);
151 RTTEST_CHECK_RC(g_hTest, RTSemEventWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS);
152 return VINF_SUCCESS;
153}
154
155
156static void test1(void)
157{
158 RTTestISub("Three threads");
159
160 /*
161 * Create the threads and let them block on the event semaphore one
162 * after the other.
163 */
164 RTSEMEVENT hSem;
165 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
166
167 RTTHREAD hThread1;
168 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, test1Thread, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1t1"), VINF_SUCCESS);
169 RTTESTI_CHECK_RC_RETV(RTThreadUserWait(hThread1, RT_MS_30SEC), VINF_SUCCESS);
170 RTThreadSleep(256);
171
172 RTTHREAD hThread2;
173 RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, test1Thread, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1t2"), VINF_SUCCESS);
174 RTTESTI_CHECK_RC_RETV(RTThreadUserWait(hThread2, RT_MS_30SEC), VINF_SUCCESS);
175 RTThreadSleep(256);
176
177 /* Signal once, hopefully waking up thread1: */
178 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
179 RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS);
180
181 /* Signal once more, hopefully waking up thread2: */
182 RTTESTI_CHECK_RC(RTSemEventSignal(hSem), VINF_SUCCESS);
183 RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS);
184
185 RTTESTI_CHECK_RC(RTSemEventDestroy(hSem), VINF_SUCCESS);
186}
187
188
189/*********************************************************************************************************************************
190* Basic tests *
191*********************************************************************************************************************************/
192
193/**
194 * Just do a number of short waits and calculate min, max and average.
195 */
196static void resolution(void)
197{
198 RTTestISub("Timeout resolution");
199
200 RTSEMEVENT hSem;
201 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
202
203 uint64_t cNsMin = UINT64_MAX;
204 uint64_t cNsMax = 0;
205 uint64_t cNsTotal = 0;
206 uint32_t cLoops;
207 for (cLoops = 0; cLoops < 256; cLoops++)
208 {
209 uint64_t const nsStart = RTTimeNanoTS();
210 int rc = RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS, RT_NS_1US);
211 uint64_t const cNsElapsed = RTTimeNanoTS() - nsStart;
212 RTTESTI_CHECK_RC(rc, VERR_TIMEOUT);
213 cNsTotal += cNsElapsed;
214 if (cNsElapsed < cNsMin)
215 cNsMin = cNsElapsed;
216 if (cNsElapsed > cNsMax)
217 cNsMax = cNsElapsed;
218 }
219
220 RTTestIValue("min", cNsMin, RTTESTUNIT_NS);
221 RTTestIValue("max", cNsMax, RTTESTUNIT_NS);
222 RTTestIValue("average", cNsTotal / cLoops, RTTESTUNIT_NS);
223 RTTestIValue("RTSemEventGetResolution", RTSemEventGetResolution(), RTTESTUNIT_NS);
224
225 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
226}
227
228
229
230static void testBasicsWaitTimeout(RTSEMEVENT hSem, unsigned i)
231{
232 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VERR_TIMEOUT);
233#if 0
234 RTTESTI_CHECK_RC_RETV(RTSemEventWaitNoResume(hSem, 0), VERR_TIMEOUT);
235#else
236 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
237 0), VERR_TIMEOUT);
238 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
239 RTTimeSystemNanoTS() + 1000*i), VERR_TIMEOUT);
240 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
241 RTTimeNanoTS() + 1000*i), VERR_TIMEOUT);
242 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE,
243 0), VERR_TIMEOUT);
244#endif
245}
246
247
248static void testBasics(void)
249{
250 RTTestISub("Basics");
251
252 RTSEMEVENT hSem;
253 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
254
255 /* The semaphore is created in a non-signalled state. */
256 testBasicsWaitTimeout(hSem, 0);
257 testBasicsWaitTimeout(hSem, 1);
258 if (RTTestIErrorCount())
259 return;
260
261 /* When signalling the semaphore, only the next waiter call shall
262 success, all subsequent ones should timeout as above. */
263 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
264 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 0), VINF_SUCCESS);
265 testBasicsWaitTimeout(hSem, 0);
266 if (RTTestIErrorCount())
267 return;
268
269 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
270 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, 2), VINF_SUCCESS);
271 testBasicsWaitTimeout(hSem, 2);
272
273 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
274 RTTESTI_CHECK_RC_RETV(RTSemEventWait(hSem, RT_INDEFINITE_WAIT), VINF_SUCCESS);
275 testBasicsWaitTimeout(hSem, 1);
276
277 if (RTTestIErrorCount())
278 return;
279
280 /* Now do all the event wait ex variations: */
281 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
282 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
283 0),
284 VINF_SUCCESS);
285 testBasicsWaitTimeout(hSem, 1);
286
287 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
288 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
289 testBasicsWaitTimeout(hSem, 1);
290
291 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
292 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0), VINF_SUCCESS);
293 testBasicsWaitTimeout(hSem, 1);
294
295 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
296 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
297 RTTimeSystemNanoTS() + RT_NS_1US), VINF_SUCCESS);
298 testBasicsWaitTimeout(hSem, 1);
299
300 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
301 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
302 RTTimeNanoTS() + RT_NS_1US), VINF_SUCCESS);
303 testBasicsWaitTimeout(hSem, 0);
304
305 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
306 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
307 RTTimeNanoTS() + RT_NS_1HOUR), VINF_SUCCESS);
308 testBasicsWaitTimeout(hSem, 0);
309
310 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
311 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
312 0), VINF_SUCCESS);
313 testBasicsWaitTimeout(hSem, 1);
314
315 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
316 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
317 _1G), VINF_SUCCESS);
318 testBasicsWaitTimeout(hSem, 1);
319
320 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
321 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
322 UINT64_MAX), VINF_SUCCESS);
323
324 testBasicsWaitTimeout(hSem, 10);
325
326 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
327 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
328 RTTimeSystemMilliTS() + RT_MS_1SEC), VINF_SUCCESS);
329 testBasicsWaitTimeout(hSem, 1);
330
331 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
332 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
333 RTTimeMilliTS() + RT_MS_1SEC), VINF_SUCCESS);
334 testBasicsWaitTimeout(hSem, 1);
335
336 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
337 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
338 0), VINF_SUCCESS);
339 testBasicsWaitTimeout(hSem, 0);
340
341 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
342 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
343 _1M), VINF_SUCCESS);
344 testBasicsWaitTimeout(hSem, 1);
345
346 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
347 RTTESTI_CHECK_RC_RETV(RTSemEventWaitEx(hSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_ABSOLUTE,
348 UINT64_MAX), VINF_SUCCESS);
349 testBasicsWaitTimeout(hSem, 1);
350
351 /* Destroy it. */
352 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
353 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(NIL_RTSEMEVENT), VINF_SUCCESS);
354
355 /* Whether it is signalled or not used shouldn't matter. */
356 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
357 RTTESTI_CHECK_RC_RETV(RTSemEventSignal(hSem), VINF_SUCCESS);
358 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
359
360 RTTESTI_CHECK_RC_RETV(RTSemEventCreate(&hSem), VINF_SUCCESS);
361 RTTESTI_CHECK_RC_RETV(RTSemEventDestroy(hSem), VINF_SUCCESS);
362
363 RTTestISubDone();
364}
365
366
367int main(int argc, char **argv)
368{
369 RT_NOREF_PV(argc); RT_NOREF_PV(argv);
370
371 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTSemEvent", &g_hTest);
372 if (rcExit != RTEXITCODE_SUCCESS)
373 return rcExit;
374
375 testBasics();
376 if (!RTTestErrorCount(g_hTest))
377 {
378 test1();
379 resolution();
380 }
381 if (!RTTestErrorCount(g_hTest))
382 {
383 bench1("Benchmark: Ping Pong, spin", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_MILLISECS | RTSEMWAIT_FLAGS_RELATIVE,
384 0);
385 bench1("Benchmark: Ping Pong, indefinite", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE,
386 0);
387 bench1("Benchmark: Ping Pong, absolute", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_ABSOLUTE,
388 RTTimeSystemNanoTS() + RT_NS_1HOUR);
389 bench1("Benchmark: Ping Pong, relative", RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
390 RT_NS_1HOUR);
391 bench1("Benchmark: Ping Pong, relative, resume", RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE,
392 RT_NS_1HOUR);
393 }
394
395 return RTTestSummaryAndDestroy(g_hTest);
396}
397
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette