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