1 /*
2 * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
9 */
10
11
12 #include "pool.h"
13 #include "threading.h"
14 #include "util.h"
15 #include <stddef.h>
16 #include <stdio.h>
17
18 #define ASSERT_TRUE(p) \
19 do { \
20 if (!(p)) { \
21 return 1; \
22 } \
23 } while (0)
24 #define ASSERT_FALSE(p) ASSERT_TRUE(!(p))
25 #define ASSERT_EQ(lhs, rhs) ASSERT_TRUE((lhs) == (rhs))
26
27 struct data {
28 pthread_mutex_t mutex;
29 unsigned data[16];
30 size_t i;
31 };
32
fn(void * opaque)33 void fn(void *opaque) {
34 struct data *data = (struct data *)opaque;
35 pthread_mutex_lock(&data->mutex);
36 data->data[data->i] = data->i;
37 ++data->i;
38 pthread_mutex_unlock(&data->mutex);
39 }
40
testOrder(size_t numThreads,size_t queueSize)41 int testOrder(size_t numThreads, size_t queueSize) {
42 struct data data;
43 POOL_ctx *ctx = POOL_create(numThreads, queueSize);
44 ASSERT_TRUE(ctx);
45 data.i = 0;
46 pthread_mutex_init(&data.mutex, NULL);
47 {
48 size_t i;
49 for (i = 0; i < 16; ++i) {
50 POOL_add(ctx, &fn, &data);
51 }
52 }
53 POOL_free(ctx);
54 ASSERT_EQ(16, data.i);
55 {
56 size_t i;
57 for (i = 0; i < data.i; ++i) {
58 ASSERT_EQ(i, data.data[i]);
59 }
60 }
61 pthread_mutex_destroy(&data.mutex);
62 return 0;
63 }
64
waitFn(void * opaque)65 void waitFn(void *opaque) {
66 (void)opaque;
67 UTIL_sleepMilli(1);
68 }
69
70 /* Tests for deadlock */
testWait(size_t numThreads,size_t queueSize)71 int testWait(size_t numThreads, size_t queueSize) {
72 struct data data;
73 POOL_ctx *ctx = POOL_create(numThreads, queueSize);
74 ASSERT_TRUE(ctx);
75 {
76 size_t i;
77 for (i = 0; i < 16; ++i) {
78 POOL_add(ctx, &waitFn, &data);
79 }
80 }
81 POOL_free(ctx);
82 return 0;
83 }
84
main(int argc,const char ** argv)85 int main(int argc, const char **argv) {
86 size_t numThreads;
87 for (numThreads = 1; numThreads <= 4; ++numThreads) {
88 size_t queueSize;
89 for (queueSize = 0; queueSize <= 2; ++queueSize) {
90 if (testOrder(numThreads, queueSize)) {
91 printf("FAIL: testOrder\n");
92 return 1;
93 }
94 if (testWait(numThreads, queueSize)) {
95 printf("FAIL: testWait\n");
96 return 1;
97 }
98 }
99 }
100 printf("PASS: testOrder\n");
101 (void)argc;
102 (void)argv;
103 return (POOL_create(0, 1)) ? printf("FAIL: testInvalid\n"), 1
104 : printf("PASS: testInvalid\n"), 0;
105 return 0;
106 }
107