xref: /aosp_15_r20/external/libusb/tests/stress_mt.c (revision 86b64dcb59b3a0b37502ecd56e119234366a6f7e)
1*86b64dcbSAndroid Build Coastguard Worker /*
2*86b64dcbSAndroid Build Coastguard Worker  * libusb multi-thread test program
3*86b64dcbSAndroid Build Coastguard Worker  * Copyright 2022-2023 Tormod Volden
4*86b64dcbSAndroid Build Coastguard Worker  *
5*86b64dcbSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
6*86b64dcbSAndroid Build Coastguard Worker  * modify it under the terms of the GNU Lesser General Public
7*86b64dcbSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation; either
8*86b64dcbSAndroid Build Coastguard Worker  * version 2.1 of the License, or (at your option) any later version.
9*86b64dcbSAndroid Build Coastguard Worker  *
10*86b64dcbSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
11*86b64dcbSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*86b64dcbSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*86b64dcbSAndroid Build Coastguard Worker  * Lesser General Public License for more details.
14*86b64dcbSAndroid Build Coastguard Worker  *
15*86b64dcbSAndroid Build Coastguard Worker  * You should have received a copy of the GNU Lesser General Public
16*86b64dcbSAndroid Build Coastguard Worker  * License along with this library; if not, write to the Free Software
17*86b64dcbSAndroid Build Coastguard Worker  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*86b64dcbSAndroid Build Coastguard Worker  */
19*86b64dcbSAndroid Build Coastguard Worker 
20*86b64dcbSAndroid Build Coastguard Worker #include <config.h>
21*86b64dcbSAndroid Build Coastguard Worker 
22*86b64dcbSAndroid Build Coastguard Worker #include <libusb.h>
23*86b64dcbSAndroid Build Coastguard Worker #include <stdio.h>
24*86b64dcbSAndroid Build Coastguard Worker #include <stdbool.h>
25*86b64dcbSAndroid Build Coastguard Worker 
26*86b64dcbSAndroid Build Coastguard Worker #if defined(PLATFORM_POSIX)
27*86b64dcbSAndroid Build Coastguard Worker 
28*86b64dcbSAndroid Build Coastguard Worker #include <pthread.h>
29*86b64dcbSAndroid Build Coastguard Worker typedef pthread_t thread_t;
30*86b64dcbSAndroid Build Coastguard Worker typedef void * thread_return_t;
31*86b64dcbSAndroid Build Coastguard Worker #define THREAD_RETURN_VALUE NULL
32*86b64dcbSAndroid Build Coastguard Worker #define THREAD_CALL_TYPE
33*86b64dcbSAndroid Build Coastguard Worker 
thread_create(thread_t * thread,thread_return_t (* thread_entry)(void * arg),void * arg)34*86b64dcbSAndroid Build Coastguard Worker static inline int thread_create(thread_t *thread,
35*86b64dcbSAndroid Build Coastguard Worker 	thread_return_t (*thread_entry)(void *arg), void *arg)
36*86b64dcbSAndroid Build Coastguard Worker {
37*86b64dcbSAndroid Build Coastguard Worker 	return pthread_create(thread, NULL, thread_entry, arg) == 0 ? 0 : -1;
38*86b64dcbSAndroid Build Coastguard Worker }
39*86b64dcbSAndroid Build Coastguard Worker 
thread_join(thread_t thread)40*86b64dcbSAndroid Build Coastguard Worker static inline void thread_join(thread_t thread)
41*86b64dcbSAndroid Build Coastguard Worker {
42*86b64dcbSAndroid Build Coastguard Worker 	(void)pthread_join(thread, NULL);
43*86b64dcbSAndroid Build Coastguard Worker }
44*86b64dcbSAndroid Build Coastguard Worker 
45*86b64dcbSAndroid Build Coastguard Worker #include <stdatomic.h>
46*86b64dcbSAndroid Build Coastguard Worker 
47*86b64dcbSAndroid Build Coastguard Worker #elif defined(PLATFORM_WINDOWS)
48*86b64dcbSAndroid Build Coastguard Worker 
49*86b64dcbSAndroid Build Coastguard Worker typedef HANDLE thread_t;
50*86b64dcbSAndroid Build Coastguard Worker #define THREAD_RETURN_VALUE 0
51*86b64dcbSAndroid Build Coastguard Worker #define THREAD_CALL_TYPE __stdcall
52*86b64dcbSAndroid Build Coastguard Worker 
53*86b64dcbSAndroid Build Coastguard Worker #if defined(__CYGWIN__)
54*86b64dcbSAndroid Build Coastguard Worker typedef DWORD thread_return_t;
55*86b64dcbSAndroid Build Coastguard Worker #else
56*86b64dcbSAndroid Build Coastguard Worker #include <process.h>
57*86b64dcbSAndroid Build Coastguard Worker typedef unsigned thread_return_t;
58*86b64dcbSAndroid Build Coastguard Worker #endif
59*86b64dcbSAndroid Build Coastguard Worker 
thread_create(thread_t * thread,thread_return_t (__stdcall * thread_entry)(void * arg),void * arg)60*86b64dcbSAndroid Build Coastguard Worker static inline int thread_create(thread_t *thread,
61*86b64dcbSAndroid Build Coastguard Worker 	thread_return_t (__stdcall *thread_entry)(void *arg), void *arg)
62*86b64dcbSAndroid Build Coastguard Worker {
63*86b64dcbSAndroid Build Coastguard Worker #if defined(__CYGWIN__)
64*86b64dcbSAndroid Build Coastguard Worker 	*thread = CreateThread(NULL, 0, thread_entry, arg, 0, NULL);
65*86b64dcbSAndroid Build Coastguard Worker #else
66*86b64dcbSAndroid Build Coastguard Worker 	*thread = (HANDLE)_beginthreadex(NULL, 0, thread_entry, arg, 0, NULL);
67*86b64dcbSAndroid Build Coastguard Worker #endif
68*86b64dcbSAndroid Build Coastguard Worker 	return *thread != NULL ? 0 : -1;
69*86b64dcbSAndroid Build Coastguard Worker }
70*86b64dcbSAndroid Build Coastguard Worker 
thread_join(thread_t thread)71*86b64dcbSAndroid Build Coastguard Worker static inline void thread_join(thread_t thread)
72*86b64dcbSAndroid Build Coastguard Worker {
73*86b64dcbSAndroid Build Coastguard Worker 	(void)WaitForSingleObject(thread, INFINITE);
74*86b64dcbSAndroid Build Coastguard Worker 	(void)CloseHandle(thread);
75*86b64dcbSAndroid Build Coastguard Worker }
76*86b64dcbSAndroid Build Coastguard Worker 
77*86b64dcbSAndroid Build Coastguard Worker typedef volatile LONG atomic_bool;
78*86b64dcbSAndroid Build Coastguard Worker 
79*86b64dcbSAndroid Build Coastguard Worker #define atomic_exchange InterlockedExchange
80*86b64dcbSAndroid Build Coastguard Worker #endif /* PLATFORM_WINDOWS */
81*86b64dcbSAndroid Build Coastguard Worker 
82*86b64dcbSAndroid Build Coastguard Worker /* Test that creates and destroys contexts repeatedly */
83*86b64dcbSAndroid Build Coastguard Worker 
84*86b64dcbSAndroid Build Coastguard Worker #define NTHREADS 8
85*86b64dcbSAndroid Build Coastguard Worker #define ITERS 64
86*86b64dcbSAndroid Build Coastguard Worker #define MAX_DEVCOUNT 128
87*86b64dcbSAndroid Build Coastguard Worker 
88*86b64dcbSAndroid Build Coastguard Worker struct thread_info {
89*86b64dcbSAndroid Build Coastguard Worker 	int number;
90*86b64dcbSAndroid Build Coastguard Worker 	int enumerate;
91*86b64dcbSAndroid Build Coastguard Worker 	ssize_t devcount;
92*86b64dcbSAndroid Build Coastguard Worker 	int err;
93*86b64dcbSAndroid Build Coastguard Worker 	int iteration;
94*86b64dcbSAndroid Build Coastguard Worker } tinfo[NTHREADS];
95*86b64dcbSAndroid Build Coastguard Worker 
96*86b64dcbSAndroid Build Coastguard Worker atomic_bool no_access[MAX_DEVCOUNT];
97*86b64dcbSAndroid Build Coastguard Worker 
98*86b64dcbSAndroid Build Coastguard Worker /* Function called by backend during device initialization to convert
99*86b64dcbSAndroid Build Coastguard Worker  * multi-byte fields in the device descriptor to host-endian format.
100*86b64dcbSAndroid Build Coastguard Worker  * Copied from libusbi.h as we want test to be realistic and not depend on internals.
101*86b64dcbSAndroid Build Coastguard Worker  */
usbi_localize_device_descriptor(struct libusb_device_descriptor * desc)102*86b64dcbSAndroid Build Coastguard Worker static inline void usbi_localize_device_descriptor(struct libusb_device_descriptor *desc)
103*86b64dcbSAndroid Build Coastguard Worker {
104*86b64dcbSAndroid Build Coastguard Worker 	desc->bcdUSB = libusb_le16_to_cpu(desc->bcdUSB);
105*86b64dcbSAndroid Build Coastguard Worker 	desc->idVendor = libusb_le16_to_cpu(desc->idVendor);
106*86b64dcbSAndroid Build Coastguard Worker 	desc->idProduct = libusb_le16_to_cpu(desc->idProduct);
107*86b64dcbSAndroid Build Coastguard Worker 	desc->bcdDevice = libusb_le16_to_cpu(desc->bcdDevice);
108*86b64dcbSAndroid Build Coastguard Worker }
109*86b64dcbSAndroid Build Coastguard Worker 
init_and_exit(void * arg)110*86b64dcbSAndroid Build Coastguard Worker static thread_return_t THREAD_CALL_TYPE init_and_exit(void * arg)
111*86b64dcbSAndroid Build Coastguard Worker {
112*86b64dcbSAndroid Build Coastguard Worker 	struct thread_info *ti = (struct thread_info *) arg;
113*86b64dcbSAndroid Build Coastguard Worker 
114*86b64dcbSAndroid Build Coastguard Worker 	for (ti->iteration = 0; ti->iteration < ITERS && !ti->err; ti->iteration++) {
115*86b64dcbSAndroid Build Coastguard Worker 		libusb_context *ctx = NULL;
116*86b64dcbSAndroid Build Coastguard Worker 
117*86b64dcbSAndroid Build Coastguard Worker 		ti->err = libusb_init_context(&ctx, /*options=*/NULL, /*num_options=*/0);
118*86b64dcbSAndroid Build Coastguard Worker 		if (ti->err != 0) {
119*86b64dcbSAndroid Build Coastguard Worker 			break;
120*86b64dcbSAndroid Build Coastguard Worker 		}
121*86b64dcbSAndroid Build Coastguard Worker 		if (ti->enumerate) {
122*86b64dcbSAndroid Build Coastguard Worker 			libusb_device **devs;
123*86b64dcbSAndroid Build Coastguard Worker 			ti->devcount = libusb_get_device_list(ctx, &devs);
124*86b64dcbSAndroid Build Coastguard Worker 			if (ti->devcount < 0) {
125*86b64dcbSAndroid Build Coastguard Worker 				ti->err = (int)ti->devcount;
126*86b64dcbSAndroid Build Coastguard Worker 				break;
127*86b64dcbSAndroid Build Coastguard Worker 			}
128*86b64dcbSAndroid Build Coastguard Worker 			for (int i = 0; i < ti->devcount && ti->err == 0; i++) {
129*86b64dcbSAndroid Build Coastguard Worker 				libusb_device *dev = devs[i];
130*86b64dcbSAndroid Build Coastguard Worker 				struct libusb_device_descriptor desc;
131*86b64dcbSAndroid Build Coastguard Worker 				ti->err = libusb_get_device_descriptor(dev, &desc);
132*86b64dcbSAndroid Build Coastguard Worker 				if (ti->err != 0) {
133*86b64dcbSAndroid Build Coastguard Worker 					break;
134*86b64dcbSAndroid Build Coastguard Worker 				}
135*86b64dcbSAndroid Build Coastguard Worker 				if (no_access[i]) {
136*86b64dcbSAndroid Build Coastguard Worker 					continue;
137*86b64dcbSAndroid Build Coastguard Worker 				}
138*86b64dcbSAndroid Build Coastguard Worker 				libusb_device_handle *dev_handle;
139*86b64dcbSAndroid Build Coastguard Worker 				int open_err = libusb_open(dev, &dev_handle);
140*86b64dcbSAndroid Build Coastguard Worker 				if (open_err == LIBUSB_ERROR_ACCESS
141*86b64dcbSAndroid Build Coastguard Worker #if defined(PLATFORM_WINDOWS)
142*86b64dcbSAndroid Build Coastguard Worker 				    || open_err == LIBUSB_ERROR_NOT_SUPPORTED
143*86b64dcbSAndroid Build Coastguard Worker 				    || open_err == LIBUSB_ERROR_NOT_FOUND
144*86b64dcbSAndroid Build Coastguard Worker #endif
145*86b64dcbSAndroid Build Coastguard Worker 						) {
146*86b64dcbSAndroid Build Coastguard Worker 					/* Use atomic swap to ensure we print warning only once across all threads.
147*86b64dcbSAndroid Build Coastguard Worker 					   This is a warning and not a hard error because it should be fine to run tests
148*86b64dcbSAndroid Build Coastguard Worker 					   even if we don't have access to some devices. */
149*86b64dcbSAndroid Build Coastguard Worker 					if (!atomic_exchange(&no_access[i], true)) {
150*86b64dcbSAndroid Build Coastguard Worker 						fprintf(stderr, "No access to device %04x:%04x, skipping transfer tests.\n", desc.idVendor, desc.idProduct);
151*86b64dcbSAndroid Build Coastguard Worker 					}
152*86b64dcbSAndroid Build Coastguard Worker 					continue;
153*86b64dcbSAndroid Build Coastguard Worker 				}
154*86b64dcbSAndroid Build Coastguard Worker 				if (open_err != 0) {
155*86b64dcbSAndroid Build Coastguard Worker 					ti->err = open_err;
156*86b64dcbSAndroid Build Coastguard Worker 					break;
157*86b64dcbSAndroid Build Coastguard Worker 				}
158*86b64dcbSAndroid Build Coastguard Worker 				/* Request raw descriptor via control transfer.
159*86b64dcbSAndroid Build Coastguard Worker 				   This tests opening, transferring and closing from multiple threads in parallel. */
160*86b64dcbSAndroid Build Coastguard Worker 				struct libusb_device_descriptor raw_desc;
161*86b64dcbSAndroid Build Coastguard Worker 				int raw_desc_len = libusb_get_descriptor(dev_handle, LIBUSB_DT_DEVICE, 0, (unsigned char *)&raw_desc, sizeof(raw_desc));
162*86b64dcbSAndroid Build Coastguard Worker 				if (raw_desc_len < 0) {
163*86b64dcbSAndroid Build Coastguard Worker 					ti->err = raw_desc_len;
164*86b64dcbSAndroid Build Coastguard Worker 					goto close;
165*86b64dcbSAndroid Build Coastguard Worker 				}
166*86b64dcbSAndroid Build Coastguard Worker 				if (raw_desc_len != sizeof(raw_desc)) {
167*86b64dcbSAndroid Build Coastguard Worker 					fprintf(stderr, "Thread %d: device %d: unexpected raw descriptor length %d\n",
168*86b64dcbSAndroid Build Coastguard Worker 						ti->number, i, raw_desc_len);
169*86b64dcbSAndroid Build Coastguard Worker 					ti->err = LIBUSB_ERROR_OTHER;
170*86b64dcbSAndroid Build Coastguard Worker 					goto close;
171*86b64dcbSAndroid Build Coastguard Worker 				}
172*86b64dcbSAndroid Build Coastguard Worker 				usbi_localize_device_descriptor(&raw_desc);
173*86b64dcbSAndroid Build Coastguard Worker #define ASSERT_EQ(field) if (raw_desc.field != desc.field) { \
174*86b64dcbSAndroid Build Coastguard Worker 	fprintf(stderr, "Thread %d: device %d: mismatch in field " #field ": %d != %d\n", \
175*86b64dcbSAndroid Build Coastguard Worker 		ti->number, i, raw_desc.field, desc.field); \
176*86b64dcbSAndroid Build Coastguard Worker 		ti->err = LIBUSB_ERROR_OTHER; \
177*86b64dcbSAndroid Build Coastguard Worker 		goto close; \
178*86b64dcbSAndroid Build Coastguard Worker }
179*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bLength);
180*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bDescriptorType);
181*86b64dcbSAndroid Build Coastguard Worker #if !defined(PLATFORM_WINDOWS)
182*86b64dcbSAndroid Build Coastguard Worker 				/* these are hardcoded by the winusbx HID backend */
183*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bcdUSB);
184*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bDeviceClass);
185*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bDeviceSubClass);
186*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bDeviceProtocol);
187*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bMaxPacketSize0);
188*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bcdDevice);
189*86b64dcbSAndroid Build Coastguard Worker #endif
190*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(idVendor);
191*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(idProduct);
192*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(iManufacturer);
193*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(iProduct);
194*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(iSerialNumber);
195*86b64dcbSAndroid Build Coastguard Worker 				ASSERT_EQ(bNumConfigurations);
196*86b64dcbSAndroid Build Coastguard Worker 			close:
197*86b64dcbSAndroid Build Coastguard Worker 				libusb_close(dev_handle);
198*86b64dcbSAndroid Build Coastguard Worker 			}
199*86b64dcbSAndroid Build Coastguard Worker 			libusb_free_device_list(devs, 1);
200*86b64dcbSAndroid Build Coastguard Worker 		}
201*86b64dcbSAndroid Build Coastguard Worker 
202*86b64dcbSAndroid Build Coastguard Worker 		libusb_exit(ctx);
203*86b64dcbSAndroid Build Coastguard Worker 	}
204*86b64dcbSAndroid Build Coastguard Worker 	return (thread_return_t) THREAD_RETURN_VALUE;
205*86b64dcbSAndroid Build Coastguard Worker }
206*86b64dcbSAndroid Build Coastguard Worker 
test_multi_init(int enumerate)207*86b64dcbSAndroid Build Coastguard Worker static int test_multi_init(int enumerate)
208*86b64dcbSAndroid Build Coastguard Worker {
209*86b64dcbSAndroid Build Coastguard Worker 	thread_t threadId[NTHREADS];
210*86b64dcbSAndroid Build Coastguard Worker 	int errs = 0;
211*86b64dcbSAndroid Build Coastguard Worker 	int t, i;
212*86b64dcbSAndroid Build Coastguard Worker 	ssize_t last_devcount = 0;
213*86b64dcbSAndroid Build Coastguard Worker 	int devcount_mismatch = 0;
214*86b64dcbSAndroid Build Coastguard Worker 	int access_failures = 0;
215*86b64dcbSAndroid Build Coastguard Worker 
216*86b64dcbSAndroid Build Coastguard Worker 	printf("Starting %d threads\n", NTHREADS);
217*86b64dcbSAndroid Build Coastguard Worker 	for (t = 0; t < NTHREADS; t++) {
218*86b64dcbSAndroid Build Coastguard Worker 		tinfo[t].err = 0;
219*86b64dcbSAndroid Build Coastguard Worker 		tinfo[t].number = t;
220*86b64dcbSAndroid Build Coastguard Worker 		tinfo[t].enumerate = enumerate;
221*86b64dcbSAndroid Build Coastguard Worker 		thread_create(&threadId[t], &init_and_exit, (void *) &tinfo[t]);
222*86b64dcbSAndroid Build Coastguard Worker 	}
223*86b64dcbSAndroid Build Coastguard Worker 
224*86b64dcbSAndroid Build Coastguard Worker 	for (t = 0; t < NTHREADS; t++) {
225*86b64dcbSAndroid Build Coastguard Worker 		thread_join(threadId[t]);
226*86b64dcbSAndroid Build Coastguard Worker 		if (tinfo[t].err) {
227*86b64dcbSAndroid Build Coastguard Worker 			errs++;
228*86b64dcbSAndroid Build Coastguard Worker 			fprintf(stderr,
229*86b64dcbSAndroid Build Coastguard Worker 				"Thread %d failed (iteration %d): %s\n",
230*86b64dcbSAndroid Build Coastguard Worker 				tinfo[t].number,
231*86b64dcbSAndroid Build Coastguard Worker 				tinfo[t].iteration,
232*86b64dcbSAndroid Build Coastguard Worker 				libusb_error_name(tinfo[t].err));
233*86b64dcbSAndroid Build Coastguard Worker 		} else if (enumerate) {
234*86b64dcbSAndroid Build Coastguard Worker 			if (t > 0 && tinfo[t].devcount != last_devcount) {
235*86b64dcbSAndroid Build Coastguard Worker 				devcount_mismatch++;
236*86b64dcbSAndroid Build Coastguard Worker 				printf("Device count mismatch: Thread %d discovered %ld devices instead of %ld\n",
237*86b64dcbSAndroid Build Coastguard Worker 				       tinfo[t].number,
238*86b64dcbSAndroid Build Coastguard Worker 				       (long int) tinfo[t].devcount,
239*86b64dcbSAndroid Build Coastguard Worker 				       (long int) last_devcount);
240*86b64dcbSAndroid Build Coastguard Worker 			}
241*86b64dcbSAndroid Build Coastguard Worker 			last_devcount = tinfo[t].devcount;
242*86b64dcbSAndroid Build Coastguard Worker 		}
243*86b64dcbSAndroid Build Coastguard Worker 	}
244*86b64dcbSAndroid Build Coastguard Worker 
245*86b64dcbSAndroid Build Coastguard Worker 	for (i = 0; i < MAX_DEVCOUNT; i++)
246*86b64dcbSAndroid Build Coastguard Worker 		if (no_access[i])
247*86b64dcbSAndroid Build Coastguard Worker 			access_failures++;
248*86b64dcbSAndroid Build Coastguard Worker 
249*86b64dcbSAndroid Build Coastguard Worker 	if (enumerate && !devcount_mismatch)
250*86b64dcbSAndroid Build Coastguard Worker 		printf("All threads discovered %ld devices (%i not opened)\n",
251*86b64dcbSAndroid Build Coastguard Worker 		       (long int) last_devcount, access_failures);
252*86b64dcbSAndroid Build Coastguard Worker 
253*86b64dcbSAndroid Build Coastguard Worker 	return errs + devcount_mismatch;
254*86b64dcbSAndroid Build Coastguard Worker }
255*86b64dcbSAndroid Build Coastguard Worker 
main(void)256*86b64dcbSAndroid Build Coastguard Worker int main(void)
257*86b64dcbSAndroid Build Coastguard Worker {
258*86b64dcbSAndroid Build Coastguard Worker 	int errs = 0;
259*86b64dcbSAndroid Build Coastguard Worker 
260*86b64dcbSAndroid Build Coastguard Worker 	printf("Running multithreaded init/exit test...\n");
261*86b64dcbSAndroid Build Coastguard Worker 	errs += test_multi_init(0);
262*86b64dcbSAndroid Build Coastguard Worker 	printf("Running multithreaded init/exit test with enumeration...\n");
263*86b64dcbSAndroid Build Coastguard Worker 	errs += test_multi_init(1);
264*86b64dcbSAndroid Build Coastguard Worker 	printf("All done, %d errors\n", errs);
265*86b64dcbSAndroid Build Coastguard Worker 
266*86b64dcbSAndroid Build Coastguard Worker 	return errs != 0;
267*86b64dcbSAndroid Build Coastguard Worker }
268