Compare commits
2077
Commits
3.0.1
...
win-2.8.19-pre1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69ff2feb70 | ||
|
|
bc2ce9d6e0 | ||
|
|
8d5716c03e | ||
|
|
a87bca3e7b | ||
|
|
a659c7c13a | ||
|
|
1ba3989480 | ||
|
|
5c3f6b9d1f | ||
|
|
c94db2ba38 | ||
|
|
3b1d4ec032 | ||
|
|
902b877dc0 | ||
|
|
02d465c8fe | ||
|
|
4d8f4262a4 | ||
|
|
d4fc65309d | ||
|
|
e47e460f1f | ||
|
|
5509c141f8 | ||
|
|
7de1ef773e | ||
|
|
e945a546af | ||
|
|
d81c38316b | ||
|
|
dba57ea910 | ||
|
|
888ea17548 | ||
|
|
86ebc139c2 | ||
|
|
3d73f088e1 | ||
|
|
76d53a6770 | ||
|
|
4848cf9335 | ||
|
|
d2f584fa53 | ||
|
|
2ed3f09cc3 | ||
|
|
77b997d429 | ||
|
|
d409371193 | ||
|
|
23b96c02a5 | ||
|
|
a47a042ea6 | ||
|
|
b5737d2d19 | ||
|
|
a598e0894b | ||
|
|
7d480abab4 | ||
|
|
2f3c860979 | ||
|
|
0c211a1953 | ||
|
|
08e4226e59 | ||
|
|
7827f41357 | ||
|
|
d6ada4d1a8 | ||
|
|
7c671c09a1 | ||
|
|
d56ef62983 | ||
|
|
f60c8c0999 | ||
|
|
04231cb7d7 | ||
|
|
6e0277769d | ||
|
|
42695fdfe6 | ||
|
|
164ad2ead1 | ||
|
|
0e40124d0f | ||
|
|
d0cc96f053 | ||
|
|
a81043959a | ||
|
|
f0c00a14ed | ||
|
|
3ac62dff23 | ||
|
|
60c09dcf09 | ||
|
|
e689e93663 | ||
|
|
01854f87e8 | ||
|
|
e305df099a | ||
|
|
9854d03fad | ||
|
|
5ddf56f9b1 | ||
|
|
b19e745780 | ||
|
|
ce96069676 | ||
|
|
ead8e31b28 | ||
|
|
5d8c88fdc1 | ||
|
|
381863be5c | ||
|
|
a7b58f1569 | ||
|
|
56e1861398 | ||
|
|
e2983dd03f | ||
|
|
2828bbd511 | ||
|
|
1e501d9fd6 | ||
|
|
eb88474985 | ||
|
|
d9326cb83d | ||
|
|
011cfdfb6b | ||
|
|
c0266d87ae | ||
|
|
a5fcf44fcc | ||
|
|
ec1ab0f18b | ||
|
|
9acbc2cc68 | ||
|
|
0287e7da15 | ||
|
|
47406f9591 | ||
|
|
eb67ca0f00 | ||
|
|
bb9ad32cb0 | ||
|
|
a37f8ec8b4 | ||
|
|
b2509d7759 | ||
|
|
9b7a190c82 | ||
|
|
49629a2e34 | ||
|
|
081eeb9f6b | ||
|
|
72ea77af0b | ||
|
|
16319c69b1 | ||
|
|
bafd3f646f | ||
|
|
f71c4d54d1 | ||
|
|
4b520177b3 | ||
|
|
7e8a471baf | ||
|
|
d57ed95222 | ||
|
|
7d32dfc69f | ||
|
|
7728ee809d | ||
|
|
7cffd74b38 | ||
|
|
eff8fb6f39 | ||
|
|
c38bb5b2ea | ||
|
|
348c4f6ce3 | ||
|
|
a7d0137075 | ||
|
|
23bf435f54 | ||
|
|
9a521e6c74 | ||
|
|
9588973fda | ||
|
|
8a618971bd | ||
|
|
b794b94797 | ||
|
|
3f1f29fdf3 | ||
|
|
dbc6e9a1ef | ||
|
|
adf55b2337 | ||
|
|
89f82a25e1 | ||
|
|
583a762cd9 | ||
|
|
31b0e13268 | ||
|
|
d403e4ae63 | ||
|
|
2f0b58e4ed | ||
|
|
82bfae5b70 | ||
|
|
132c108f17 | ||
|
|
e82ec2c5d8 | ||
|
|
2ed67e4a9e | ||
|
|
51864fcdd7 | ||
|
|
1b4cadb664 | ||
|
|
38dee9dc51 | ||
|
|
5d295fea12 | ||
|
|
aef4c60c78 | ||
|
|
81abd1e178 | ||
|
|
1e633f21c5 | ||
|
|
ff8a3baaf7 | ||
|
|
29fa2f09a4 | ||
|
|
063be1b6be | ||
|
|
7c6644442b | ||
|
|
b6203138d3 | ||
|
|
85b15acb44 | ||
|
|
09fc0fbbe4 | ||
|
|
03b36eef72 | ||
|
|
e1ccd7243f | ||
|
|
364aeed96d | ||
|
|
a7a2f69bdb | ||
|
|
1adc4a7888 | ||
|
|
c3375fbdff | ||
|
|
c4d32c03d0 | ||
|
|
919a4c3126 | ||
|
|
8a1d16fe5c | ||
|
|
e0ffc863c6 | ||
|
|
22e6f434f8 | ||
|
|
3101760937 | ||
|
|
d3005539c5 | ||
|
|
3c99e429cf | ||
|
|
55597bbd67 | ||
|
|
a5044c254d | ||
|
|
33daf8e9a9 | ||
|
|
b72422e100 | ||
|
|
6cdd38f947 | ||
|
|
6b64fa49f8 | ||
|
|
fc9bce45c5 | ||
|
|
575e293ddd | ||
|
|
d05fcaffa0 | ||
|
|
a99d187bc4 | ||
|
|
904bd0400c | ||
|
|
18d1138e75 | ||
|
|
450fd83a9a | ||
|
|
bd27d3bd9b | ||
|
|
04b6945ebc | ||
|
|
a9e3429538 | ||
|
|
51cac40c73 | ||
|
|
96898fa51c | ||
|
|
ade6c5e782 | ||
|
|
cf143b571e | ||
|
|
c7b6d311df | ||
|
|
18534064c9 | ||
|
|
a69534967b | ||
|
|
5e38bc389c | ||
|
|
01f7db608d | ||
|
|
9faeff0215 | ||
|
|
fbd9dc6039 | ||
|
|
915c0dd656 | ||
|
|
551ffc486c | ||
|
|
78dca8977f | ||
|
|
a6695e341b | ||
|
|
9fe4429a09 | ||
|
|
6fbcb19275 | ||
|
|
8375a6d0aa | ||
|
|
55024e9a9a | ||
|
|
3cc31da349 | ||
|
|
8c3507aa8f | ||
|
|
9f3abf436b | ||
|
|
874c21d801 | ||
|
|
ff47d5ebf6 | ||
|
|
b3fdddfd1f | ||
|
|
670084b724 | ||
|
|
03a5c0ecb5 | ||
|
|
683cf5b872 | ||
|
|
94f7979414 | ||
|
|
537f3053fa | ||
|
|
763d7b7c6a | ||
|
|
69a5ea090a | ||
|
|
b001508333 | ||
|
|
0c3a93b8a2 | ||
|
|
c9c6ac2056 | ||
|
|
1688851b13 | ||
|
|
667e2991dc | ||
|
|
4284b07220 | ||
|
|
a2119ce3a5 | ||
|
|
8bea36f67b | ||
|
|
e5328c06b4 | ||
|
|
0e03891633 | ||
|
|
92e96ad66b | ||
|
|
db6e874a25 | ||
|
|
dd36f18c76 | ||
|
|
d1f89bdc2b | ||
|
|
59ad68ca4f | ||
|
|
95f845b691 | ||
|
|
8fb8a474fd | ||
|
|
85b3db4065 | ||
|
|
3a706ba792 | ||
|
|
97fdcd8746 | ||
|
|
45fac9481a | ||
|
|
c3eac3ddff | ||
|
|
fdcadd16c6 | ||
|
|
ac48aada30 | ||
|
|
abe29c83e6 | ||
|
|
8fcce90b25 | ||
|
|
4ac8472cac | ||
|
|
f7b5e2d11e | ||
|
|
32a94beca4 | ||
|
|
f862e5ddfa | ||
|
|
32168a5e8a | ||
|
|
4bf7c5d0f8 | ||
|
|
33b37b1400 | ||
|
|
ae2cd2e16f | ||
|
|
8c0743d80e | ||
|
|
ef12b4c3eb | ||
|
|
1580a378b8 | ||
|
|
467848460a | ||
|
|
5e707c66dd | ||
|
|
65d47452f8 | ||
|
|
09757420a4 | ||
|
|
134345e332 | ||
|
|
f89a7bbe11 | ||
|
|
dbcf381099 | ||
|
|
6bc74b4393 | ||
|
|
1aff711d90 | ||
|
|
866f6bcc80 | ||
|
|
29ed617ac4 | ||
|
|
a43e45e391 | ||
|
|
25a4699a9e | ||
|
|
09a3976478 | ||
|
|
60c748628b | ||
|
|
96614f5866 | ||
|
|
d1df50ad59 | ||
|
|
282c6106ce | ||
|
|
25b5abe8cf | ||
|
|
a7c46df612 | ||
|
|
8dbd0134e5 | ||
|
|
0c8999dfeb | ||
|
|
0f9ab49d58 | ||
|
|
4be50f7fbb | ||
|
|
8fc2247c9b | ||
|
|
ebd25710dd | ||
|
|
524b2626f7 | ||
|
|
78bde472c0 | ||
|
|
07b2779bff | ||
|
|
4024220fe6 | ||
|
|
50669f7b66 | ||
|
|
9b53f79e00 | ||
|
|
9840df7bad | ||
|
|
b5dc2c5b91 | ||
|
|
cbd1607c6a | ||
|
|
9a039f76c2 | ||
|
|
28b54b5d94 | ||
|
|
ff6aee6fa3 | ||
|
|
79afb8e15e | ||
|
|
6f4ce3f83e | ||
|
|
c3358cc869 | ||
|
|
36f30412b5 | ||
|
|
16cefcf0b5 | ||
|
|
6d364f41ce | ||
|
|
31e9621f06 | ||
|
|
8d28cf7542 | ||
|
|
33018d61a5 | ||
|
|
96f3fc015a | ||
|
|
f52ce3c2c7 | ||
|
|
94e40d1034 | ||
|
|
8cb1d65616 | ||
|
|
c6c93699cc | ||
|
|
ff58d5a380 | ||
|
|
eb7b3427e7 | ||
|
|
4d7b3815d5 | ||
|
|
9fa51dd4d1 | ||
|
|
fb12b5738d | ||
|
|
d558af8e6f | ||
|
|
e426e77896 | ||
|
|
8a44e10848 | ||
|
|
9e191b4b58 | ||
|
|
dbc7669fff | ||
|
|
5e05dad83a | ||
|
|
0bfdd4bb49 | ||
|
|
098bb97703 | ||
|
|
316e1db970 | ||
|
|
c8a6cd94b3 | ||
|
|
192b285b14 | ||
|
|
d47adb19ac | ||
|
|
7b11dfe05e | ||
|
|
156029b336 | ||
|
|
06e9b3cad8 | ||
|
|
ab5f20d19c | ||
|
|
70e39481ab | ||
|
|
294bcfc4d2 | ||
|
|
b7a045d747 | ||
|
|
4e71fc1c6f | ||
|
|
4df3af4e6e | ||
|
|
0c29cadd46 | ||
|
|
3df2ab673c | ||
|
|
c970507478 | ||
|
|
bb10ad9c13 | ||
|
|
c785d4cccc | ||
|
|
e1fd73f634 | ||
|
|
315536d012 | ||
|
|
f0e67afd94 | ||
|
|
128f5b53de | ||
|
|
1f3c097b1c | ||
|
|
e4db34e97c | ||
|
|
f9765990b2 | ||
|
|
54ca682887 | ||
|
|
95d880a7bf | ||
|
|
2e581217d9 | ||
|
|
121a9a3579 | ||
|
|
3dd113bf33 | ||
|
|
3e8f5113fa | ||
|
|
c145854bac | ||
|
|
65dbb3546a | ||
|
|
4c68319370 | ||
|
|
f3eab7a9b4 | ||
|
|
f3c4111edd | ||
|
|
07b4d33734 | ||
|
|
58fb90fdac | ||
|
|
c005315a64 | ||
|
|
e81b51ad8c | ||
|
|
8cc912db43 | ||
|
|
e905588062 | ||
|
|
b38996aab1 | ||
|
|
062564c261 | ||
|
|
d20d89e630 | ||
|
|
dc1c91a8bf | ||
|
|
350792bd72 | ||
|
|
ed95915d33 | ||
|
|
34afc91030 | ||
|
|
35a62f7408 | ||
|
|
855c97ce1b | ||
|
|
3cb03b68a4 | ||
|
|
e400ae60f5 | ||
|
|
a57eb3272d | ||
|
|
72c84acc99 | ||
|
|
58ecc0bd68 | ||
|
|
88a62862d3 | ||
|
|
deb9d5cb66 | ||
|
|
2f2985275b | ||
|
|
52c98f5cb8 | ||
|
|
9613f9a2a6 | ||
|
|
0baab66d16 | ||
|
|
96e0be50bb | ||
|
|
670cf9598e | ||
|
|
41d7c90417 | ||
|
|
63feb93a9f | ||
|
|
0a6649a7c0 | ||
|
|
53377f8c6d | ||
|
|
f3efd529df | ||
|
|
fdc5dbd5b1 | ||
|
|
afe949efcb | ||
|
|
1066fed769 | ||
|
|
cd4f0dc775 | ||
|
|
58fea46976 | ||
|
|
ff3ca17bac | ||
|
|
04749ee015 | ||
|
|
60ff8095d6 | ||
|
|
e9cd75dcd1 | ||
|
|
a4d22bfa8c | ||
|
|
8b9aa92123 | ||
|
|
084073fced | ||
|
|
4600a06960 | ||
|
|
ac6b656fd6 | ||
|
|
b6e7f2d45e | ||
|
|
a14400a858 | ||
|
|
32ebb3e651 | ||
|
|
5d16a838db | ||
|
|
d3c2918434 | ||
|
|
95f492ee57 | ||
|
|
364464e790 | ||
|
|
8066334986 | ||
|
|
e59eef246b | ||
|
|
a8ecd3f040 | ||
|
|
6ee25dc439 | ||
|
|
ed705f4789 | ||
|
|
9a5408f23e | ||
|
|
061fd99767 | ||
|
|
2b805ce119 | ||
|
|
8c460a2872 | ||
|
|
7d0992dad6 | ||
|
|
674194ad42 | ||
|
|
61d9a73d87 | ||
|
|
09dc6dadc1 | ||
|
|
cad13223f0 | ||
|
|
b6a26b52bf | ||
|
|
8060de98f8 | ||
|
|
41a15205b6 | ||
|
|
d8d415e717 | ||
|
|
52189cb9c3 | ||
|
|
4acc3daa92 | ||
|
|
3a915ace44 | ||
|
|
ebc62a6f35 | ||
|
|
a0e0fba7fa | ||
|
|
411b6e9119 | ||
|
|
2355ae9bc6 | ||
|
|
fd2faee5de | ||
|
|
93ee0f2666 | ||
|
|
9b883974af | ||
|
|
7665cc67b3 | ||
|
|
1267e28edc | ||
|
|
2cff0c041f | ||
|
|
9a39db3bb6 | ||
|
|
b0964b7dd9 | ||
|
|
eef369b66a | ||
|
|
f392c7737c | ||
|
|
d178cd03ed | ||
|
|
1b044af402 | ||
|
|
56f504cb48 | ||
|
|
e5de315940 | ||
|
|
258f3cd360 | ||
|
|
ca6b95dfdd | ||
|
|
721a9a2467 | ||
|
|
0713fce727 | ||
|
|
b0f3922383 | ||
|
|
a3b0dbccf5 | ||
|
|
ba76daa42e | ||
|
|
c83b639b45 | ||
|
|
0df1ab8c74 | ||
|
|
8f774ee7ca | ||
|
|
2af2414344 | ||
|
|
b4f9761d85 | ||
|
|
6ab4775a2a | ||
|
|
b98ee12f61 | ||
|
|
3783d90e53 | ||
|
|
e3112bed8d | ||
|
|
ca941f6c0b | ||
|
|
15a236015f | ||
|
|
d0c274bbf3 | ||
|
|
987a47b823 | ||
|
|
430bec3461 | ||
|
|
3a30be51aa | ||
|
|
42504169c7 | ||
|
|
26359d570b | ||
|
|
768994b683 | ||
|
|
d623ca7e56 | ||
|
|
228bf0350e | ||
|
|
803462c2c9 | ||
|
|
21fafdc620 | ||
|
|
d4051d4c38 | ||
|
|
1c0c42e668 | ||
|
|
88606c1277 | ||
|
|
4f0e17fb35 | ||
|
|
75266018ee | ||
|
|
edc41baca5 | ||
|
|
a4dd5cba88 | ||
|
|
e97604ce63 | ||
|
|
1a14eba2d5 | ||
|
|
f482349707 | ||
|
|
f3d3c606f1 | ||
|
|
4113473997 | ||
|
|
e8669ca8a7 | ||
|
|
d491a479bc | ||
|
|
d575f7a147 | ||
|
|
6d2fddd2a3 | ||
|
|
ad935769ae | ||
|
|
43278af63e | ||
|
|
1c3b70c971 | ||
|
|
3ee3c4bdaf | ||
|
|
f441b8d0f2 | ||
|
|
3203e2dcdd | ||
|
|
6e478ec890 | ||
|
|
c0eaac9572 | ||
|
|
23011dea1f | ||
|
|
6ae4c1fcbc | ||
|
|
ed1e8ac956 | ||
|
|
991653211b | ||
|
|
1fd9047397 | ||
|
|
13d8b2b096 | ||
|
|
909d1883e7 | ||
|
|
01eaf183b3 | ||
|
|
176d1cd04b | ||
|
|
80b96bc4a7 | ||
|
|
093eab56de | ||
|
|
32971f6251 | ||
|
|
87516f1a4d | ||
|
|
1b5524f697 | ||
|
|
8237d88f48 | ||
|
|
6938a3d58f | ||
|
|
08ea98c9e9 | ||
|
|
3a1a0c3240 | ||
|
|
d70281575c | ||
|
|
67e350367d | ||
|
|
feb6c2884a | ||
|
|
9f871c4ec5 | ||
|
|
de0a37aa76 | ||
|
|
a2ef6a4fdc | ||
|
|
b06de30dd7 | ||
|
|
e9d0d86dbf | ||
|
|
96b5dc0b98 | ||
|
|
3d2af57974 | ||
|
|
35252037fd | ||
|
|
662f505727 | ||
|
|
de7ebf83e1 | ||
|
|
91dcc5b12f | ||
|
|
26375709c5 | ||
|
|
cbd76db6a3 | ||
|
|
c5ee48a9d9 | ||
|
|
be145453c6 | ||
|
|
115782b1d7 | ||
|
|
2cd20d3c4c | ||
|
|
3f5cd0c660 | ||
|
|
f0eca148ff | ||
|
|
d25fd8be64 | ||
|
|
4a26648a22 | ||
|
|
3fc22561e7 | ||
|
|
ea0af9ace3 | ||
|
|
019e6f1889 | ||
|
|
e674609fcb | ||
|
|
ff367b50e5 | ||
|
|
9c9aef24a2 | ||
|
|
11f89497b4 | ||
|
|
d975bb587f | ||
|
|
71dfb87f76 | ||
|
|
f2e59eae44 | ||
|
|
469b7c5168 | ||
|
|
614fcd491e | ||
|
|
08da2b79fc | ||
|
|
5a0bab2a8f | ||
|
|
05563310f4 | ||
|
|
e77a3e40f2 | ||
|
|
c4b2a7a7f4 | ||
|
|
ee682c4c48 | ||
|
|
9ef8ef410b | ||
|
|
91e05e1618 | ||
|
|
68a4bf70e0 | ||
|
|
21e328a6d7 | ||
|
|
4244aa29f9 | ||
|
|
4cd11077d2 | ||
|
|
08183cfef5 | ||
|
|
d428569d13 | ||
|
|
2d1e35a58a | ||
|
|
29c7d1974b | ||
|
|
023f2f7a10 | ||
|
|
91391760ca | ||
|
|
5d87160f8a | ||
|
|
a18e7afbe8 | ||
|
|
5c86d9e7b0 | ||
|
|
0e0ddcc4fa | ||
|
|
533235f7e3 | ||
|
|
f12fb49bb2 | ||
|
|
a3e2adc0ae | ||
|
|
eaa73ef73a | ||
|
|
95de3eaea0 | ||
|
|
c277169ed7 | ||
|
|
b6ca71a40a | ||
|
|
8b39fee4c8 | ||
|
|
c1ddead779 | ||
|
|
0a7ba6faef | ||
|
|
8e889728bf | ||
|
|
aadd513160 | ||
|
|
e5e5facba1 | ||
|
|
88847a216f | ||
|
|
21c97e71cd | ||
|
|
ed96e115d0 | ||
|
|
93c75f1bf4 | ||
|
|
2b1385b9ec | ||
|
|
12d1d18b59 | ||
|
|
a10bfded15 | ||
|
|
ee764b0f8d | ||
|
|
091f5677a0 | ||
|
|
a97675923d | ||
|
|
faa7f259cc | ||
|
|
8ae6887091 | ||
|
|
bdd8701c60 | ||
|
|
b3baa51403 | ||
|
|
348d5ea246 | ||
|
|
ba0dc0be2c | ||
|
|
c2cd48718d | ||
|
|
ff551fad24 | ||
|
|
e08100a9ba | ||
|
|
23acae6e1c | ||
|
|
e3773b0a0e | ||
|
|
badf23f57b | ||
|
|
6e71459c73 | ||
|
|
2ee2bec2d6 | ||
|
|
1e90c0066c | ||
|
|
be7eef911b | ||
|
|
f2e707b679 | ||
|
|
be7fe2b92b | ||
|
|
39dd1f648d | ||
|
|
f07b1514bb | ||
|
|
32e9996846 | ||
|
|
9faa80ee8c | ||
|
|
aad5959ddc | ||
|
|
d6ce659ffd | ||
|
|
c3df5965f3 | ||
|
|
9e178afae9 | ||
|
|
1c795db9d0 | ||
|
|
7f30998432 | ||
|
|
430d0ade75 | ||
|
|
83650a72a1 | ||
|
|
3afd25ecc7 | ||
|
|
0ffd5e4a30 | ||
|
|
ca6973d3b6 | ||
|
|
2500f2a334 | ||
|
|
42592a7faa | ||
|
|
3035075b2c | ||
|
|
959d0f012a | ||
|
|
ac29bb2ae4 | ||
|
|
2a91f548c4 | ||
|
|
3f159bbd44 | ||
|
|
a18e880bf1 | ||
|
|
00409d8742 | ||
|
|
de3f821af6 | ||
|
|
02d88fb201 | ||
|
|
a7f2df706e | ||
|
|
884dd54bbc | ||
|
|
3cd77a5cb5 | ||
|
|
bcfdbf7bcc | ||
|
|
765cdbe670 | ||
|
|
631e8e1afb | ||
|
|
959c9d3469 | ||
|
|
2d29a8f207 | ||
|
|
34250336c1 | ||
|
|
9651d90354 | ||
|
|
6eb1ec2217 | ||
|
|
e2a48cd715 | ||
|
|
0df3c6b4b4 | ||
|
|
8b9a8a0a41 | ||
|
|
c3c91f5ab0 | ||
|
|
ddbdd3b0df | ||
|
|
d2e59c2715 | ||
|
|
99fc582f8c | ||
|
|
3580bb485a | ||
|
|
c3510af1c0 | ||
|
|
771f8ad0e7 | ||
|
|
3ce742d1d5 | ||
|
|
b59585396b | ||
|
|
6826af1b50 | ||
|
|
611372fa97 | ||
|
|
3bd3240660 | ||
|
|
79349affd5 | ||
|
|
80dec5e4df | ||
|
|
a2ec9a9068 | ||
|
|
88c6c669c3 | ||
|
|
6182dad37c | ||
|
|
4ebc7e3738 | ||
|
|
72257f4b87 | ||
|
|
7054f2a029 | ||
|
|
7a20f09647 | ||
|
|
f5b410a52e | ||
|
|
4c0e75ed8b | ||
|
|
8d0309eebf | ||
|
|
001775f5fb | ||
|
|
c68189a19f | ||
|
|
ff8c81873a | ||
|
|
e3b71a1c02 | ||
|
|
0937377aa2 | ||
|
|
686839b477 | ||
|
|
6d0e408a27 | ||
|
|
ba2edc4191 | ||
|
|
9c2063fb8f | ||
|
|
ffa8f479a5 | ||
|
|
42091a79bb | ||
|
|
38241c4b1e | ||
|
|
16ca1634ae | ||
|
|
decf224e85 | ||
|
|
9de0755869 | ||
|
|
a31a0b4336 | ||
|
|
6b0e36ffc6 | ||
|
|
bd48ff69b0 | ||
|
|
3703112671 | ||
|
|
ccd2c18c1c | ||
|
|
daa5d2a6c9 | ||
|
|
ca0720b694 | ||
|
|
ffe742f92a | ||
|
|
6fb9e2d717 | ||
|
|
53f0c8f6e2 | ||
|
|
eb9e1526e6 | ||
|
|
a6970570e3 | ||
|
|
fe0ab7d234 | ||
|
|
0080e0fc70 | ||
|
|
464fef9bf8 | ||
|
|
aab16ead92 | ||
|
|
86afc0706d | ||
|
|
55b8f6ec1c | ||
|
|
647a261465 | ||
|
|
9c66cd91be | ||
|
|
6991792943 | ||
|
|
7d65b7199a | ||
|
|
c19cfde65d | ||
|
|
55f4b20f31 | ||
|
|
1606978a0b | ||
|
|
6200191943 | ||
|
|
2af2173a60 | ||
|
|
1dc1e31c2b | ||
|
|
b132121a71 | ||
|
|
d1d706c923 | ||
|
|
c99cd2fd40 | ||
|
|
f33d4a6c24 | ||
|
|
c2d99d49b5 | ||
|
|
e40f8378bd | ||
|
|
a0335e18ba | ||
|
|
950cb76e7b | ||
|
|
42e3630d77 | ||
|
|
1892b56224 | ||
|
|
2c8036f7b2 | ||
|
|
3294f74fef | ||
|
|
82d2e295b8 | ||
|
|
a3eb3f9c3b | ||
|
|
30a92b6c76 | ||
|
|
c1cc28f230 | ||
|
|
d79f9ebdb5 | ||
|
|
25e2791ec3 | ||
|
|
c955b47d62 | ||
|
|
bfe4c560e6 | ||
|
|
580ed0768f | ||
|
|
411ef3f609 | ||
|
|
30a26d36ab | ||
|
|
d90e3e3a70 | ||
|
|
89d95ec2e7 | ||
|
|
65194d11c3 | ||
|
|
16c2189d4e | ||
|
|
1b2bcd4210 | ||
|
|
6ec3dc2c42 | ||
|
|
02ae6cb01a | ||
|
|
fe05112029 | ||
|
|
cf76fdd04f | ||
|
|
9e34e296cf | ||
|
|
dfacfafc2a | ||
|
|
2fab983c69 | ||
|
|
a6d560db64 | ||
|
|
3f16fee39a | ||
|
|
e8e2ac072c | ||
|
|
85fa77e02e | ||
|
|
2d48d7c2fc | ||
|
|
6e6106797e | ||
|
|
96162c0c58 | ||
|
|
39eacde136 | ||
|
|
28aa15a6ea | ||
|
|
3917224f7c | ||
|
|
001ab29915 | ||
|
|
d31a394148 | ||
|
|
d83ab8f9d4 | ||
|
|
1dfab3d107 | ||
|
|
aee165e084 | ||
|
|
73b290cc5b | ||
|
|
3ced78dc6c | ||
|
|
f5245a44e4 | ||
|
|
6441a41f94 | ||
|
|
05dde71919 | ||
|
|
c499d82f28 | ||
|
|
c01aff1234 | ||
|
|
56cb037a86 | ||
|
|
d4edf63bc4 | ||
|
|
722d4f0c41 | ||
|
|
b26660e130 | ||
|
|
ac5fd5a519 | ||
|
|
890559ea1c | ||
|
|
208eb29003 | ||
|
|
905c55d5ae | ||
|
|
1b345ec3f0 | ||
|
|
bdd9804c42 | ||
|
|
92258f87ba | ||
|
|
351e790032 | ||
|
|
f71c7de88e | ||
|
|
0886c98fef | ||
|
|
4237f14a8a | ||
|
|
5efee4f0bb | ||
|
|
8d9e238a20 | ||
|
|
a695b4e4a4 | ||
|
|
1d4d9e7b14 | ||
|
|
85492dcfef | ||
|
|
eb10bb31ac | ||
|
|
ebdb37cea7 | ||
|
|
9b73a274ac | ||
|
|
96973a7c33 | ||
|
|
fadbbdd3f4 | ||
|
|
8c87102147 | ||
|
|
4e45ebf5a1 | ||
|
|
e4ac644fc1 | ||
|
|
688d32e16b | ||
|
|
3e4968339b | ||
|
|
4bbb8e6bce | ||
|
|
2959371b3f | ||
|
|
301a0cfc69 | ||
|
|
4e809a9a19 | ||
|
|
2277ed0ea8 | ||
|
|
62cc0e320d | ||
|
|
ddcf160309 | ||
|
|
c5bc592650 | ||
|
|
5201ca0ca1 | ||
|
|
3da5cbe5bb | ||
|
|
0be31e2d22 | ||
|
|
66304fb122 | ||
|
|
1406112ec4 | ||
|
|
917b851491 | ||
|
|
8dda9dbef0 | ||
|
|
f0652c37a5 | ||
|
|
4440406bb5 | ||
|
|
8812fe61bd | ||
|
|
66b7f8a044 | ||
|
|
a2c9d38a9f | ||
|
|
89a731b3aa | ||
|
|
e1f312e547 | ||
|
|
e35841ce76 | ||
|
|
ecfefde760 | ||
|
|
6daa29da46 | ||
|
|
43503ae5d6 | ||
|
|
b9c84d4aef | ||
|
|
248e916550 | ||
|
|
ce6c1f08b0 | ||
|
|
f00034a438 | ||
|
|
60a82ae058 | ||
|
|
8b3daf2bb8 | ||
|
|
93581da537 | ||
|
|
d30d0c6a31 | ||
|
|
d401022d14 | ||
|
|
4ea91aadfb | ||
|
|
71f7eb2590 | ||
|
|
df00b6ac05 | ||
|
|
b8db8a0c48 | ||
|
|
8ed0b49525 | ||
|
|
560e548dc6 | ||
|
|
0ca750d94a | ||
|
|
1f9580c125 | ||
|
|
bb207007ca | ||
|
|
b7dc3204a6 | ||
|
|
2e0ba7bb5b | ||
|
|
52cf0975c7 | ||
|
|
6bcc370c9d | ||
|
|
ea2bffa030 | ||
|
|
0d7366c329 | ||
|
|
bca65866ff | ||
|
|
e4c51759f5 | ||
|
|
8a47dc3ca5 | ||
|
|
e12c4cdf15 | ||
|
|
c32ccaa868 | ||
|
|
51f71e2d8e | ||
|
|
05d219a6fa | ||
|
|
2a1a31ca9d | ||
|
|
418d3d358a | ||
|
|
4d88ec9886 | ||
|
|
663850ea73 | ||
|
|
f5a1b485c3 | ||
|
|
78b051a8be | ||
|
|
1849e30c7a | ||
|
|
bddf4ac4da | ||
|
|
5decabc2c7 | ||
|
|
c53e73573c | ||
|
|
449d6623ab | ||
|
|
bf22d5646d | ||
|
|
0a1a236e3e | ||
|
|
27d06111db | ||
|
|
5b7c16137d | ||
|
|
d07d4a876c | ||
|
|
9d1997706c | ||
|
|
5e2bb3e678 | ||
|
|
4ad219adc8 | ||
|
|
c6db326d1d | ||
|
|
4456ee1173 | ||
|
|
5fa937d956 | ||
|
|
9ba9d78ada | ||
|
|
d33f3689d7 | ||
|
|
fb8a480f54 | ||
|
|
d62bbfda16 | ||
|
|
090bcc946f | ||
|
|
ddd529bc3b | ||
|
|
673c42bb4e | ||
|
|
33f6f35f34 | ||
|
|
8eb1cb3b52 | ||
|
|
993e0ede76 | ||
|
|
2507e366b2 | ||
|
|
f9e9448a5b | ||
|
|
45c60a903a | ||
|
|
5e75e681fe | ||
|
|
8995634014 | ||
|
|
9a8ae5a553 | ||
|
|
0ff078d8d0 | ||
|
|
25ba2e9607 | ||
|
|
563d6b3f98 | ||
|
|
b6610a569d | ||
|
|
26cf5c8ac6 | ||
|
|
303cc97ff9 | ||
|
|
75bf5a4a4a | ||
|
|
8d0083ba25 | ||
|
|
fba0b23e72 | ||
|
|
dceaca1f69 | ||
|
|
bf307cfb4d | ||
|
|
4f9d30b33b | ||
|
|
b67f39da09 | ||
|
|
4c53178c6c | ||
|
|
7f6743a581 | ||
|
|
edae78999c | ||
|
|
3d7263aa41 | ||
|
|
333453646c | ||
|
|
4d650a3baa | ||
|
|
dd0ac4ac72 | ||
|
|
75347ada7f | ||
|
|
83333b08d0 | ||
|
|
50d140e90b | ||
|
|
2eb8a46061 | ||
|
|
a46f841df3 | ||
|
|
7da645073b | ||
|
|
926e5283c6 | ||
|
|
e5c577e679 | ||
|
|
dd239c37db | ||
|
|
c61cc761d5 | ||
|
|
d13635b2a9 | ||
|
|
d240202261 | ||
|
|
e83741746c | ||
|
|
4e6d34bd2c | ||
|
|
f75fccafe7 | ||
|
|
312ca4dacc | ||
|
|
c84275ee60 | ||
|
|
0b2639123b | ||
|
|
750b007d7c | ||
|
|
4bd1dd1c53 | ||
|
|
46e2f3468c | ||
|
|
87098a39f0 | ||
|
|
9ecd819ecb | ||
|
|
eeb8cb3305 | ||
|
|
c517f72343 | ||
|
|
812f76a850 | ||
|
|
fc93198ff9 | ||
|
|
44b3684633 | ||
|
|
6d0400f569 | ||
|
|
1bbce5bf01 | ||
|
|
679dc8b09d | ||
|
|
3e1fc6278d | ||
|
|
9a9c0cfaa6 | ||
|
|
93d924ff1c | ||
|
|
a52909c5f2 | ||
|
|
8c3e197040 | ||
|
|
04b1fb0b1a | ||
|
|
0b9853ecdc | ||
|
|
737062745d | ||
|
|
66b03c1a40 | ||
|
|
8ba31c218b | ||
|
|
ccaba966bc | ||
|
|
3c4497e83c | ||
|
|
e15ba6a697 | ||
|
|
1a6abe7d79 | ||
|
|
0eeb0a0782 | ||
|
|
64c8de8657 | ||
|
|
782f9cacaf | ||
|
|
7dbc0a63f5 | ||
|
|
612dbb2a91 | ||
|
|
4ccf807abc | ||
|
|
e98d82c639 | ||
|
|
be19e5450c | ||
|
|
8c551d65a1 | ||
|
|
9577fed8a3 | ||
|
|
fc10fb17da | ||
|
|
b02ef3d59a | ||
|
|
1a1dc3de38 | ||
|
|
9f0e52a13d | ||
|
|
f7604b4c07 | ||
|
|
1569326277 | ||
|
|
9f20780de6 | ||
|
|
2488257ad8 | ||
|
|
6593f33222 | ||
|
|
48acc675dd | ||
|
|
447c2787a0 | ||
|
|
eba4775b5d | ||
|
|
b95c6ed7b7 | ||
|
|
663d79c0d5 | ||
|
|
b72985d7f7 | ||
|
|
fe7f96f18c | ||
|
|
be2ef1b59f | ||
|
|
14e809d0f7 | ||
|
|
e0f78cd084 | ||
|
|
98682cd178 | ||
|
|
68b911478f | ||
|
|
7d30b3121d | ||
|
|
875bc51909 | ||
|
|
59cdeb4e89 | ||
|
|
c874e39c45 | ||
|
|
1767998751 | ||
|
|
97810c45e8 | ||
|
|
f7f97bf730 | ||
|
|
3a66e0c157 | ||
|
|
060d56e7eb | ||
|
|
162acd8ac2 | ||
|
|
406be0ea28 | ||
|
|
4b615eea8f | ||
|
|
54a5a7dff8 | ||
|
|
bebbc7f9f7 | ||
|
|
736e343509 | ||
|
|
6710555bc8 | ||
|
|
59b30b327d | ||
|
|
3d3e350b12 | ||
|
|
3cc7d486bc | ||
|
|
06455014aa | ||
|
|
141f30f421 | ||
|
|
3032831099 | ||
|
|
c53cab5dde | ||
|
|
ab6f4195dd | ||
|
|
13e879c9cf | ||
|
|
9ea69a58ac | ||
|
|
bd1962acc4 | ||
|
|
02617b6e92 | ||
|
|
e2162fc107 | ||
|
|
bb2df795e0 | ||
|
|
35816a2e4d | ||
|
|
1cc7e646af | ||
|
|
24ecabc995 | ||
|
|
17785f40b5 | ||
|
|
7f063b1c8c | ||
|
|
9e62d9e79c | ||
|
|
1a06bbe430 | ||
|
|
0880bec4e2 | ||
|
|
1d659784f4 | ||
|
|
854b8be616 | ||
|
|
5fa5153bf5 | ||
|
|
108c6e6734 | ||
|
|
21da9b06a4 | ||
|
|
907e06cd61 | ||
|
|
b44f1589a4 | ||
|
|
d1c1f62ed5 | ||
|
|
8cdaf604ce | ||
|
|
33409b4c6c | ||
|
|
fd22106a98 | ||
|
|
8c4ff679fe | ||
|
|
0dd95e23ab | ||
|
|
07f2edf5e3 | ||
|
|
9546f7846b | ||
|
|
37e9d78774 | ||
|
|
8dc2d3096d | ||
|
|
5fbc129b4e | ||
|
|
e1f6d21cdf | ||
|
|
508d3c1bb7 | ||
|
|
df0c96002d | ||
|
|
d7fa6d9aba | ||
|
|
c8c1006cf4 | ||
|
|
81f614ef6f | ||
|
|
7071e9d599 | ||
|
|
20c506f432 | ||
|
|
de48871570 | ||
|
|
3561ada2db | ||
|
|
af967ff9cb | ||
|
|
2d55f1ca7f | ||
|
|
9a0f27a5d0 | ||
|
|
c713b1ebdd | ||
|
|
56ce068664 | ||
|
|
23acf93f97 | ||
|
|
0ea9a20d47 | ||
|
|
752b1fca90 | ||
|
|
3e62d7c308 | ||
|
|
a57294b339 | ||
|
|
facc5c0661 | ||
|
|
79a1d335c8 | ||
|
|
0f32c37fc9 | ||
|
|
df21771c69 | ||
|
|
f05b1f6889 | ||
|
|
9c3e6c3aa0 | ||
|
|
9df63fcabf | ||
|
|
f5903846bc | ||
|
|
bd6327855b | ||
|
|
2c94d80f58 | ||
|
|
778f753deb | ||
|
|
6c2b34a465 | ||
|
|
0a4656d63f | ||
|
|
7c861340b1 | ||
|
|
2c018b14fb | ||
|
|
6a88a84ec7 | ||
|
|
5621272575 | ||
|
|
009515f914 | ||
|
|
837817b2b7 | ||
|
|
bd353d9a3c | ||
|
|
c7da5fc6c1 | ||
|
|
8368550733 | ||
|
|
3ad87c652b | ||
|
|
05379f49ee | ||
|
|
706056ca16 | ||
|
|
14a1cba3e3 | ||
|
|
004f00bfa4 | ||
|
|
45d4e06e93 | ||
|
|
3eab283b65 | ||
|
|
0e72cc601f | ||
|
|
689829f2e1 | ||
|
|
4fe67cc103 | ||
|
|
a256b83448 | ||
|
|
a79862de2a | ||
|
|
bcc7965931 | ||
|
|
46c1bafeab | ||
|
|
151ad68540 | ||
|
|
fa48b1fa32 | ||
|
|
31d0f34100 | ||
|
|
00c8cfef74 | ||
|
|
8686a70303 | ||
|
|
d54e373b84 | ||
|
|
500155b91b | ||
|
|
cc94697284 | ||
|
|
f8e43aba78 | ||
|
|
13f7ade551 | ||
|
|
78644f5e3e | ||
|
|
aea8020554 | ||
|
|
c3e1724a57 | ||
|
|
f899ab55ca | ||
|
|
a1d37ba469 | ||
|
|
57c8e026b9 | ||
|
|
3339a22399 | ||
|
|
aa392e3fb7 | ||
|
|
2d92308f38 | ||
|
|
eff7cdfad0 | ||
|
|
b4554da5fd | ||
|
|
aedf3bfcd1 | ||
|
|
fe7c28cc50 | ||
|
|
e4b13e5eb0 | ||
|
|
17dd06cc97 | ||
|
|
0929eec2f7 | ||
|
|
1e6147fada | ||
|
|
5180055384 | ||
|
|
b1f0b92f2d | ||
|
|
c84e5ba84d | ||
|
|
3a5ee522b5 | ||
|
|
8f77c71751 | ||
|
|
22c2b323da | ||
|
|
96418fd48e | ||
|
|
1f42527c58 | ||
|
|
89cae3d62e | ||
|
|
cb85f493cb | ||
|
|
896c1e659f | ||
|
|
19c476f4ce | ||
|
|
239f5233d5 | ||
|
|
097dd94bb4 | ||
|
|
07b031839a | ||
|
|
c179bcfd66 | ||
|
|
a6a8aebec9 | ||
|
|
81eed0db38 | ||
|
|
e955536015 | ||
|
|
47bbccf9be | ||
|
|
11d870bd55 | ||
|
|
f3b44f291d | ||
|
|
5d0ad2f983 | ||
|
|
349f6349be | ||
|
|
5b19e9d433 | ||
|
|
3cb3714e99 | ||
|
|
a50635bb6c | ||
|
|
2e449d42e0 | ||
|
|
9f6f436a51 | ||
|
|
112e763618 | ||
|
|
fe04710908 | ||
|
|
98757b4a6e | ||
|
|
18fabeb264 | ||
|
|
d8fcbb6645 | ||
|
|
1bcbb7a90c | ||
|
|
1e23848ed3 | ||
|
|
076f6395b9 | ||
|
|
4cfd70e903 | ||
|
|
98d0abcecd | ||
|
|
8669e70921 | ||
|
|
9e089e7c5d | ||
|
|
cdf801d92e | ||
|
|
3472d045d8 | ||
|
|
da18366609 | ||
|
|
4fa68b2815 | ||
|
|
a7451c1b6d | ||
|
|
2e75d3947c | ||
|
|
b5423b099c | ||
|
|
1e7949227c | ||
|
|
0d8f254359 | ||
|
|
5938126c98 | ||
|
|
d3bf85423a | ||
|
|
47620a3186 | ||
|
|
fd8a6ae7a6 | ||
|
|
f638236902 | ||
|
|
71795d4e7e | ||
|
|
d37d006cd2 | ||
|
|
57e2b23dfb | ||
|
|
39d57c057f | ||
|
|
f1151f869e | ||
|
|
fefa14914e | ||
|
|
77ddec8582 | ||
|
|
4b2e374e4a | ||
|
|
3570411def | ||
|
|
68d72aa5b1 | ||
|
|
30836721f2 | ||
|
|
920ab4c926 | ||
|
|
aee5ee70fa | ||
|
|
e50f2c93bc | ||
|
|
d36dc1fc82 | ||
|
|
855ff8df9f | ||
|
|
33c5f0a243 | ||
|
|
323e5e2058 | ||
|
|
fc022ca300 | ||
|
|
00063bea33 | ||
|
|
6dabd34ad0 | ||
|
|
14857decfa | ||
|
|
2150cfebb7 | ||
|
|
3e3501262b | ||
|
|
24b3799238 | ||
|
|
2f6560f351 | ||
|
|
847a40805f | ||
|
|
aaf5623535 | ||
|
|
25a3ad7f74 | ||
|
|
028fdbb70b | ||
|
|
8090c37f71 | ||
|
|
75dc48f04a | ||
|
|
0a0fd37e5b | ||
|
|
7bfbc38068 | ||
|
|
bb0d0fd479 | ||
|
|
cdf79c063f | ||
|
|
7cca200603 | ||
|
|
29308077a8 | ||
|
|
9faa6b9dc3 | ||
|
|
b0e0f3c5b2 | ||
|
|
4e2b97bb89 | ||
|
|
d34c1ac208 | ||
|
|
b7233f40fb | ||
|
|
8450d6e24d | ||
|
|
545fe0c318 | ||
|
|
9d894b1b8c | ||
|
|
8328d993e1 | ||
|
|
aeab473dfb | ||
|
|
a8f1474dfd | ||
|
|
72d3fbea65 | ||
|
|
3642557ae6 | ||
|
|
30f3ae03a5 | ||
|
|
f27896a17d | ||
|
|
9a7b09ed35 | ||
|
|
90c3a14ac0 | ||
|
|
f2f2b4eb9d | ||
|
|
252f0b6556 | ||
|
|
9af8125c7d | ||
|
|
ee92c043fc | ||
|
|
be8d5fd954 | ||
|
|
8e63fd0734 | ||
|
|
86147afd08 | ||
|
|
449ec38fe4 | ||
|
|
bf8e078aa2 | ||
|
|
b3fbc84cc1 | ||
|
|
1cf839a216 | ||
|
|
e34f00842f | ||
|
|
a73da27853 | ||
|
|
b435817b17 | ||
|
|
054632f551 | ||
|
|
d34c623e10 | ||
|
|
fe4b62fcaf | ||
|
|
971217c7b4 | ||
|
|
f5275da6e9 | ||
|
|
9a7ea3dae9 | ||
|
|
4333e6ce20 | ||
|
|
9d1bc3efcf | ||
|
|
d0d67f8d42 | ||
|
|
fc2587ec6e | ||
|
|
75fcf5c936 | ||
|
|
c64338aa8f | ||
|
|
889d39b5ba | ||
|
|
1b87b3ef38 | ||
|
|
2d497014ea | ||
|
|
75bf91abea | ||
|
|
308940aa2c | ||
|
|
45e6a4023a | ||
|
|
a74f8fe1ad | ||
|
|
0000d5334d | ||
|
|
146f1d7d86 | ||
|
|
1e77b77de4 | ||
|
|
0387f86947 | ||
|
|
7ae29d5d9e | ||
|
|
302b0a5c7b | ||
|
|
0b398b6ffa | ||
|
|
059018c4cd | ||
|
|
414d5db85c | ||
|
|
604efb02ab | ||
|
|
7d338fd982 | ||
|
|
2173f30836 | ||
|
|
901ceab20b | ||
|
|
b4ce02988c | ||
|
|
2a29cf430a | ||
|
|
c95a60960b | ||
|
|
e8cc959300 | ||
|
|
180cfaae8e | ||
|
|
417253afc3 | ||
|
|
8feb3d261a | ||
|
|
a461376ca9 | ||
|
|
8cf0b66606 | ||
|
|
cb8433f313 | ||
|
|
f62851aea9 | ||
|
|
91ef10ef45 | ||
|
|
973f793b04 | ||
|
|
7a5d3d91a1 | ||
|
|
d8dd70c2dd | ||
|
|
feffd5635b | ||
|
|
41babac68d | ||
|
|
cb55ad991b | ||
|
|
c847c73e78 | ||
|
|
2c93d34bde | ||
|
|
2865bb7f1f | ||
|
|
6251c3e66e | ||
|
|
3d93dffd5d | ||
|
|
71b442276f | ||
|
|
85671d0e3b | ||
|
|
6a947b1d54 | ||
|
|
736220b86f | ||
|
|
b05d2516fe | ||
|
|
b60465eb78 | ||
|
|
b37512a28f | ||
|
|
a94db7908a | ||
|
|
d96497961c | ||
|
|
4f38d03254 | ||
|
|
59ff2fe9a4 | ||
|
|
fb0d08e35f | ||
|
|
e7bcec829c | ||
|
|
4028a777b6 | ||
|
|
70845320cc | ||
|
|
395e6a5872 | ||
|
|
2b427a89fb | ||
|
|
34a57a5b52 | ||
|
|
d2ff5ed603 | ||
|
|
967ae8ca67 | ||
|
|
b06f13e7b7 | ||
|
|
c735116c87 | ||
|
|
8b41e19e47 | ||
|
|
9ca306d874 | ||
|
|
5276996cf1 | ||
|
|
cf7b2c329b | ||
|
|
e426ea5245 | ||
|
|
bac29c8b7c | ||
|
|
d0c9a2a767 | ||
|
|
a500c120ba | ||
|
|
4848af1b9e | ||
|
|
172eac504a | ||
|
|
3a865829a7 | ||
|
|
0e3baa5241 | ||
|
|
5bf9b53a83 | ||
|
|
42ba5d3788 | ||
|
|
0d7b10ee6e | ||
|
|
40861516ac | ||
|
|
92a7b0102c | ||
|
|
9f2e6ac0ed | ||
|
|
8d81e68d18 | ||
|
|
63978d338d | ||
|
|
d83d72f380 | ||
|
|
ed2d988192 | ||
|
|
d6b0c18c51 | ||
|
|
0bc7dbda1c | ||
|
|
034d94193d | ||
|
|
2094eb36e7 | ||
|
|
31844fe138 | ||
|
|
c72459bf18 | ||
|
|
ca0b1c2436 | ||
|
|
49eef7738e | ||
|
|
0c8690d46e | ||
|
|
7da5980848 | ||
|
|
062f60a36e | ||
|
|
cf8484b723 | ||
|
|
4243483d3e | ||
|
|
d785413d86 | ||
|
|
0c447d3506 | ||
|
|
24aa61785d | ||
|
|
e8a1a169dd | ||
|
|
dc0f13774b | ||
|
|
47911b8630 | ||
|
|
7ff729e192 | ||
|
|
02b9a72bae | ||
|
|
e6e07042a1 | ||
|
|
be832929c8 | ||
|
|
4de4080ea5 | ||
|
|
978185bf67 | ||
|
|
10d8e6a712 | ||
|
|
c6a9a20d3b | ||
|
|
61b1d6da18 | ||
|
|
7009ff98b8 | ||
|
|
1862239136 | ||
|
|
f8791a158b | ||
|
|
26319d08b5 | ||
|
|
fc78d978de | ||
|
|
6cb7860658 | ||
|
|
611dcb56ee | ||
|
|
889b017403 | ||
|
|
d1369c3d9f | ||
|
|
a452b54849 | ||
|
|
10c6195e3f | ||
|
|
2618101ad5 | ||
|
|
82516e8168 | ||
|
|
d91dfaf6dc | ||
|
|
150f7e43ca | ||
|
|
6818905406 | ||
|
|
ef1cf15c14 | ||
|
|
382420ec6e | ||
|
|
6b7562e204 | ||
|
|
dee8d84270 | ||
|
|
5576a28977 | ||
|
|
ec18d4bfba | ||
|
|
4f8b18f3dd | ||
|
|
58708fa65a | ||
|
|
c64255990e | ||
|
|
ba8367ee49 | ||
|
|
ba3c5494d8 | ||
|
|
684b61505a | ||
|
|
189e865c51 | ||
|
|
b9f8c2a5b0 | ||
|
|
67a745515d | ||
|
|
7b6fb960cc | ||
|
|
64b91c1493 | ||
|
|
edb3c10361 | ||
|
|
18d16f8592 | ||
|
|
b2e42a90d3 | ||
|
|
3a00520e5f | ||
|
|
378fcaad55 | ||
|
|
f93d9929d8 | ||
|
|
6589821035 | ||
|
|
48f4f77189 | ||
|
|
b3281e93c3 | ||
|
|
2677c97d39 | ||
|
|
1d426bf53b | ||
|
|
da2dd8991b | ||
|
|
13f84841b5 | ||
|
|
ef3a95fa6f | ||
|
|
665b819eb4 | ||
|
|
bb562a6414 | ||
|
|
e166abad10 | ||
|
|
8e7d962291 | ||
|
|
c5afbb6e2a | ||
|
|
7e7ee815b0 | ||
|
|
6a8288766c | ||
|
|
9afb7789b3 | ||
|
|
1a73260dce | ||
|
|
8abfe5fe8b | ||
|
|
a4bb4b29fb | ||
|
|
aa7f74c7e9 | ||
|
|
21822fd0e9 | ||
|
|
aec5ea5d07 | ||
|
|
2d24bf2f94 | ||
|
|
6ae8fb477a | ||
|
|
bc1b2e8f96 | ||
|
|
deccd104d8 | ||
|
|
e7a61d287e | ||
|
|
78bae8b078 | ||
|
|
bf6c5d960d | ||
|
|
95fc9cc0a6 | ||
|
|
5de5efa364 | ||
|
|
1f2d5941a1 | ||
|
|
60aa3a67e8 | ||
|
|
921aec17b6 | ||
|
|
e174290307 | ||
|
|
5bcfa2ebbc | ||
|
|
00a5e86e44 | ||
|
|
f72a3406a7 | ||
|
|
68532cf01e | ||
|
|
a70e3ffb16 | ||
|
|
a6f557657c | ||
|
|
5aeb1f71a3 | ||
|
|
a3273dbfa6 | ||
|
|
aadb8aaa08 | ||
|
|
e9318d92db | ||
|
|
df3b492045 | ||
|
|
803c5b140d | ||
|
|
e618eb4fb3 | ||
|
|
74373cd930 | ||
|
|
b5047d9b2f | ||
|
|
a74056f1e0 | ||
|
|
02cd545f7d | ||
|
|
b148513fec | ||
|
|
5e9e96999f | ||
|
|
d2a37badc2 | ||
|
|
0d8d7f106a | ||
|
|
438dfdd13d | ||
|
|
6f96ac1c1c | ||
|
|
f69b0a0db8 | ||
|
|
ac3100bc3b | ||
|
|
fedcd51185 | ||
|
|
ff56772115 | ||
|
|
964ee00de0 | ||
|
|
3b4c0d80d5 | ||
|
|
34b420dbf3 | ||
|
|
d96a66f531 | ||
|
|
31f0a6ec50 | ||
|
|
5fe2577a19 | ||
|
|
02ac84ddbd | ||
|
|
9854252798 | ||
|
|
45bfab8596 | ||
|
|
5a8cf340a4 | ||
|
|
0ae1a6b1c3 | ||
|
|
2b1398e870 | ||
|
|
5a4ef3e5b6 | ||
|
|
4fe7672dfc | ||
|
|
8529dd218f | ||
|
|
6726ea5b53 | ||
|
|
f5edd535d1 | ||
|
|
700e5eb4fc | ||
|
|
4d8655cfd3 | ||
|
|
01c21f9943 | ||
|
|
5a35e485f9 | ||
|
|
948fdb5f7d | ||
|
|
c970816e4d | ||
|
|
fe97d7b1db | ||
|
|
e88517ac30 | ||
|
|
2d89c53d0d | ||
|
|
0fe052efaa | ||
|
|
e1e8b1cd29 | ||
|
|
609a3ec1be | ||
|
|
0b50d1ce9a | ||
|
|
c7b9a57fb2 | ||
|
|
8a22934c68 | ||
|
|
b06b90b5d8 | ||
|
|
0a14a6542c | ||
|
|
2ed3fc1502 | ||
|
|
f2817cbd9e | ||
|
|
fcfdbda104 | ||
|
|
0d470b4c43 | ||
|
|
63ad0e8867 | ||
|
|
cc55a4525a | ||
|
|
d5d0b467db | ||
|
|
5eb0ec142d | ||
|
|
5f7dff4d16 | ||
|
|
1d80acae54 | ||
|
|
cf0191dc3c | ||
|
|
45b1b2f7ad | ||
|
|
14daa01c52 | ||
|
|
eb07793b59 | ||
|
|
22ccc6db0f | ||
|
|
f9a8b0eced | ||
|
|
6da090e916 | ||
|
|
d2a8bca82b | ||
|
|
1124cda37a | ||
|
|
e92edd3cee | ||
|
|
2543fa6476 | ||
|
|
8c0b9f778e | ||
|
|
63dc34bd01 | ||
|
|
44d0eac568 | ||
|
|
9ddd0f7796 | ||
|
|
57e411c687 | ||
|
|
8024de7eb0 | ||
|
|
ca8e7d4f8a | ||
|
|
664de412af | ||
|
|
d3cf778d82 | ||
|
|
9db8fbcfdd | ||
|
|
b9bc4f9132 | ||
|
|
6de052cd77 | ||
|
|
81af92b023 | ||
|
|
4ff138fbbe | ||
|
|
2825f21fd8 | ||
|
|
a64383c861 | ||
|
|
fdfb59beae | ||
|
|
dd2ce743ca | ||
|
|
6e64525cc2 | ||
|
|
212edbc409 | ||
|
|
153766e137 | ||
|
|
c17a7f6fbc | ||
|
|
bfad381f57 | ||
|
|
767a53aa84 | ||
|
|
3ff75e58e8 | ||
|
|
742e580f40 | ||
|
|
850117a8a5 | ||
|
|
1b0f244509 | ||
|
|
2f1318ab29 | ||
|
|
f6f43d7da0 | ||
|
|
580f65a50b | ||
|
|
a154908a8f | ||
|
|
635c532c89 | ||
|
|
39f0a33f78 | ||
|
|
da540228d8 | ||
|
|
9e5b70162c | ||
|
|
1e20c939fe | ||
|
|
d766907cfb | ||
|
|
dbde1d85ea | ||
|
|
560e049947 | ||
|
|
1caf09399e | ||
|
|
c2b43eac4f | ||
|
|
ff1e4d22a6 | ||
|
|
5e2aa2cafb | ||
|
|
a8f9cec16a | ||
|
|
aadcda9977 | ||
|
|
a732d86fe0 | ||
|
|
f2bc198d40 | ||
|
|
0f4dbd9a11 | ||
|
|
21159d53f5 | ||
|
|
c48584b85d | ||
|
|
52f6a1dc16 | ||
|
|
f9c1263f31 | ||
|
|
1b2ac3b206 | ||
|
|
c5f23ca79b | ||
|
|
7897e0a0d6 | ||
|
|
f31d10b9a6 | ||
|
|
786bd3938e | ||
|
|
27abaa238f | ||
|
|
aa9497fdb3 | ||
|
|
64ee9c861f | ||
|
|
78b175a241 | ||
|
|
14cc0045dc | ||
|
|
023cbc3787 | ||
|
|
b70b9c6027 | ||
|
|
46dc3fbb53 | ||
|
|
8a70007f9e | ||
|
|
e2e36cf19b | ||
|
|
414e06653c | ||
|
|
cefff3a1b3 | ||
|
|
6570d2f89e | ||
|
|
c1c3e9b756 | ||
|
|
1f8ad7ae55 | ||
|
|
858b5576ac | ||
|
|
4468ba2317 | ||
|
|
61fb0aacf5 | ||
|
|
d8a0fddd51 | ||
|
|
6fa2610ac9 | ||
|
|
886c9ecb7c | ||
|
|
a6d117b6c0 | ||
|
|
5207c03c49 | ||
|
|
8e0a9f6027 | ||
|
|
d64a9cf514 | ||
|
|
bbee226ecd | ||
|
|
d9301f05e2 | ||
|
|
17e31eb03a | ||
|
|
6c9897f6cf | ||
|
|
984f6edf0a | ||
|
|
a2b3fff235 | ||
|
|
124cb6dda1 | ||
|
|
e39735214d | ||
|
|
07a9f85405 | ||
|
|
fbf3e33d18 | ||
|
|
64e69c0d5f | ||
|
|
54b08c86a6 | ||
|
|
6bdcd50b56 | ||
|
|
cac49a9031 | ||
|
|
c1eda786d6 | ||
|
|
ccc974d90b | ||
|
|
2572bb13c6 | ||
|
|
ed70955510 | ||
|
|
e34c14df1a | ||
|
|
3b71404d70 | ||
|
|
cd99c14e38 | ||
|
|
b41f4e5a48 | ||
|
|
21b26915ce | ||
|
|
053f1f357d | ||
|
|
1f0d0b094a | ||
|
|
ccb500cf36 | ||
|
|
ed48550fe6 | ||
|
|
3ccfb5a4d6 | ||
|
|
d0570c9693 | ||
|
|
9120275dc9 | ||
|
|
cc85ed41df | ||
|
|
de00a5a092 | ||
|
|
2b45ef020c | ||
|
|
52bd3d8a39 | ||
|
|
37d978d9b4 | ||
|
|
41f0f927c9 | ||
|
|
ca9321afe2 | ||
|
|
a527235f33 | ||
|
|
53600e34db | ||
|
|
60f9dac672 | ||
|
|
dff1ec4a36 | ||
|
|
d4b5c4803b | ||
|
|
dd905417ec | ||
|
|
5ab4151d7f | ||
|
|
e95ca66320 | ||
|
|
c342b075df | ||
|
|
1d8af6074c | ||
|
|
1a706c729a | ||
|
|
681c191006 | ||
|
|
50c41de752 | ||
|
|
d85a09dfc6 | ||
|
|
26a48504cb | ||
|
|
ae3aeca828 | ||
|
|
388cc20418 | ||
|
|
5a8234d2c9 | ||
|
|
2861cd84f9 | ||
|
|
cda5c0ba06 | ||
|
|
8e30092f06 | ||
|
|
8ddb23b90c | ||
|
|
d288ee655f | ||
|
|
89514f80e9 | ||
|
|
46c5d39660 | ||
|
|
2b28ef0e61 | ||
|
|
3f006679b1 | ||
|
|
36f026a3a0 | ||
|
|
64be5e365a | ||
|
|
fecc8797c2 | ||
|
|
cc017c5839 | ||
|
|
d775b35715 | ||
|
|
b6ffa85f11 | ||
|
|
655e6838fb | ||
|
|
4917a6a8b3 | ||
|
|
ed44a74e72 | ||
|
|
428b706308 | ||
|
|
47ff443b53 | ||
|
|
4d9bd53530 | ||
|
|
9fab63b334 | ||
|
|
537235bbbb | ||
|
|
38272f961a | ||
|
|
6c7e957d17 | ||
|
|
6bd105032c | ||
|
|
72f42cf40c | ||
|
|
2a49aa1da2 | ||
|
|
24ee20e5ca | ||
|
|
5bf0997ff8 | ||
|
|
ec0f483de2 | ||
|
|
0dd6241314 | ||
|
|
3b1a41b172 | ||
|
|
9b3b110004 | ||
|
|
b25b0dc5f4 | ||
|
|
2b5fc529a4 | ||
|
|
be407c015c | ||
|
|
1eb9145089 | ||
|
|
f7b42b1749 | ||
|
|
5eec376c2f | ||
|
|
99d7dbe669 | ||
|
|
a61705dd95 | ||
|
|
16144589f2 | ||
|
|
a25b25f4ef | ||
|
|
ab55180883 | ||
|
|
a03c32702b | ||
|
|
2164523244 | ||
|
|
c3ff470889 | ||
|
|
0e25c0ccf4 | ||
|
|
f4eb4b3352 | ||
|
|
500dddc264 | ||
|
|
a6305f13d5 | ||
|
|
99c3338c23 | ||
|
|
05e06e1543 | ||
|
|
e2f2dab3ef | ||
|
|
e480c279bc | ||
|
|
0c19880ce6 | ||
|
|
2ba962714a | ||
|
|
151b606c11 | ||
|
|
f1466e11cd | ||
|
|
e061d797d7 | ||
|
|
04779bdfe1 | ||
|
|
e04be06e89 | ||
|
|
c4cbffa3a1 | ||
|
|
dfb7194cba | ||
|
|
b8ce9a84c5 | ||
|
|
1f8bd82332 | ||
|
|
ef792fc950 | ||
|
|
de499f7f7e | ||
|
|
b65f3c2176 | ||
|
|
161e137c55 | ||
|
|
d480b9ce7f | ||
|
|
fa23fc3363 | ||
|
|
fc0a0d4aa7 | ||
|
|
ea9bec50c6 | ||
|
|
26a340095d | ||
|
|
524b79d231 | ||
|
|
201ed6d42e | ||
|
|
7c9bfe1036 | ||
|
|
3da75e2ca4 | ||
|
|
e328e41a3a | ||
|
|
8a8e560b87 | ||
|
|
0d0975f2b6 | ||
|
|
af41f6cffb | ||
|
|
999fe0d352 | ||
|
|
f1057534e7 | ||
|
|
fcc8bf9974 | ||
|
|
374eed7d2a | ||
|
|
2085fdb1f4 | ||
|
|
f8a19e32e2 | ||
|
|
7c39b55d42 | ||
|
|
e47236d8d4 | ||
|
|
8ab7e998d1 | ||
|
|
e01a415d37 | ||
|
|
d26a8fb4db | ||
|
|
5b5eb192f5 | ||
|
|
120ba3922d | ||
|
|
2812b945f0 | ||
|
|
31fe053a62 | ||
|
|
dd94771578 | ||
|
|
8b6b1b27cc | ||
|
|
4403862623 | ||
|
|
174518ffb7 | ||
|
|
f444e2afdc | ||
|
|
b58f03a0e8 | ||
|
|
efb54f0593 | ||
|
|
58889867bb | ||
|
|
4c3d419013 | ||
|
|
0671d88cab | ||
|
|
5ddee9b7d5 | ||
|
|
fd2a8951bf | ||
|
|
42a239b888 | ||
|
|
851ac9d072 | ||
|
|
48d26a483d | ||
|
|
edfaa64f49 | ||
|
|
13732168a5 | ||
|
|
06bd3b9acd | ||
|
|
5de75120ba | ||
|
|
32095c4057 | ||
|
|
7fcba9fd9a | ||
|
|
2f44452612 | ||
|
|
89bf6f58fd | ||
|
|
013189e7db | ||
|
|
73d3e8751b | ||
|
|
628890e43e | ||
|
|
4c0c1fff5a | ||
|
|
f00b0844c9 | ||
|
|
889e443ce5 | ||
|
|
3bb3f12539 | ||
|
|
82675c86a6 | ||
|
|
8a8e01f4a7 | ||
|
|
d3d567428a | ||
|
|
dbd8c753c4 | ||
|
|
b3f28b90d2 | ||
|
|
4b3865cbdb | ||
|
|
0c9cf45270 | ||
|
|
6fe9c402a2 | ||
|
|
8361d6c406 | ||
|
|
e612508d38 | ||
|
|
1364395f18 | ||
|
|
0b8441c1b2 | ||
|
|
a85c89854f | ||
|
|
0ea1a9c452 | ||
|
|
1a3e9d951b | ||
|
|
3f12656781 | ||
|
|
591c9e6543 | ||
|
|
ebdcd723a7 | ||
|
|
8f0658cdd0 | ||
|
|
9a8d51add5 | ||
|
|
473f3090f2 | ||
|
|
69396249e5 | ||
|
|
6b4d92e21d | ||
|
|
8bbc0768b8 | ||
|
|
f0d962c0ec | ||
|
|
c19bfe9fcf | ||
|
|
e53a1fdd60 | ||
|
|
951213e2d2 | ||
|
|
d12a68d415 | ||
|
|
7ffa248c7c | ||
|
|
84ec6706cf | ||
|
|
1f40cdd0e5 | ||
|
|
4a789decaa | ||
|
|
bec74b1b9c | ||
|
|
edb952532d | ||
|
|
8152d0c046 | ||
|
|
9b6035bc7f | ||
|
|
27fc5bf582 | ||
|
|
dfa90b5969 | ||
|
|
a5a037bf81 | ||
|
|
4dada1b5bc | ||
|
|
afc6bd1b48 | ||
|
|
4934f93dfb | ||
|
|
14beba7868 | ||
|
|
404223547c | ||
|
|
d318803f94 | ||
|
|
72f30bcd30 | ||
|
|
2aa1efb8a5 | ||
|
|
e67d014d9a | ||
|
|
eee680541b | ||
|
|
a8a981a834 | ||
|
|
f7f2b2610e | ||
|
|
f078d5628d | ||
|
|
3a401464e9 | ||
|
|
064223107e | ||
|
|
25496f4700 | ||
|
|
346825c7ed | ||
|
|
dd4e8203b2 | ||
|
|
91d18504c2 | ||
|
|
f580a3e3a0 | ||
|
|
8afa5b7072 | ||
|
|
af2455be29 | ||
|
|
184b8e78c6 | ||
|
|
d23d73c746 | ||
|
|
0ef889274f | ||
|
|
1b1cf8e7bf | ||
|
|
7f10703b33 | ||
|
|
0cf10e8e86 | ||
|
|
9b43b1ef4d | ||
|
|
0b08d64882 | ||
|
|
96d9c6cb8b | ||
|
|
0f07781538 | ||
|
|
1858da2faa | ||
|
|
83b1092cf2 | ||
|
|
9311d2b527 | ||
|
|
8520066d7b | ||
|
|
8f984bef29 | ||
|
|
dd418873db | ||
|
|
b330de57ff | ||
|
|
18759c927a | ||
|
|
8b97442c20 | ||
|
|
7c5d96d98e | ||
|
|
603adb2b29 | ||
|
|
748f206e3d | ||
|
|
2c0aae760f | ||
|
|
b1aa7183d7 | ||
|
|
77a75fdef5 | ||
|
|
e69e76d442 | ||
|
|
9db4cea235 | ||
|
|
a28ab2a92b | ||
|
|
b1ee7da75a | ||
|
|
d7bad544dc | ||
|
|
8111a803cb | ||
|
|
c16bf717de | ||
|
|
12a042f863 | ||
|
|
717145c1a3 | ||
|
|
dcd4efe9ef | ||
|
|
62bfa66284 | ||
|
|
dd51571cc3 | ||
|
|
ad91404a32 | ||
|
|
9de5d4600a | ||
|
|
38b60dea54 | ||
|
|
69b30cfcb6 | ||
|
|
0a8a1e78dc | ||
|
|
537dafab84 | ||
|
|
7d6bf7956e | ||
|
|
e337b26050 | ||
|
|
590d55a206 | ||
|
|
c11a01a030 | ||
|
|
30e89410d4 | ||
|
|
abfd08f5ad | ||
|
|
ca577d162a | ||
|
|
d54943b76d | ||
|
|
c3312760fe | ||
|
|
1d82bbd432 | ||
|
|
0122cc4f42 | ||
|
|
e10768518c | ||
|
|
5c45ae1f7b | ||
|
|
7a2065ef33 | ||
|
|
eb624e3416 | ||
|
|
ff5e31f74b | ||
|
|
24982f2bbc | ||
|
|
60ef787efa | ||
|
|
bec200ec39 | ||
|
|
a00fcaa671 | ||
|
|
8d12645569 | ||
|
|
d00f51405b | ||
|
|
ae55245d1c | ||
|
|
212bb9ca2e | ||
|
|
727d6dd52a | ||
|
|
a1090c1193 | ||
|
|
68ee18558a | ||
|
|
96aeca4b9d | ||
|
|
d0cd262fdf | ||
|
|
864229585a | ||
|
|
3126e08757 | ||
|
|
61e8825e89 | ||
|
|
95bc195158 | ||
|
|
cb481f432a | ||
|
|
0b27a55f30 | ||
|
|
6cedb4d489 | ||
|
|
59333ffd37 | ||
|
|
9a2dd1eff9 | ||
|
|
c9853f537b | ||
|
|
d63a1716eb | ||
|
|
d2906893e8 | ||
|
|
97cab30993 | ||
|
|
6255a5ae66 | ||
|
|
e387dc52a0 | ||
|
|
3e6a4463e0 | ||
|
|
430602b26c | ||
|
|
236adc2809 | ||
|
|
d298825803 | ||
|
|
206568257a | ||
|
|
50fb330399 | ||
|
|
69ac4d063d | ||
|
|
b9cd703b5b | ||
|
|
79e3df9d72 | ||
|
|
d5ec389585 | ||
|
|
336ba6a152 | ||
|
|
ef278d110f | ||
|
|
de07849e0d | ||
|
|
e74bec56fa | ||
|
|
3ba5eab774 | ||
|
|
b9aa332843 | ||
|
|
3f64694e71 | ||
|
|
fdf8bd4025 | ||
|
|
e95740392b | ||
|
|
39d1e350d9 | ||
|
|
7f4f86f427 | ||
|
|
1bcb45d118 | ||
|
|
b4b923b04b | ||
|
|
bb99f42596 | ||
|
|
9ba4d5a3bb | ||
|
|
08211b25d3 | ||
|
|
55951f9005 | ||
|
|
2cf3f071a5 | ||
|
|
b162e6f133 | ||
|
|
4f0bd607d9 | ||
|
|
7dc1d2ba17 | ||
|
|
eb6bc2e047 | ||
|
|
3984108474 | ||
|
|
8d3f5ce9db | ||
|
|
8382453ecf | ||
|
|
a3ec16f0c2 | ||
|
|
3aad0de2e9 | ||
|
|
81a28fe131 | ||
|
|
b518a83525 | ||
|
|
9f899440d2 | ||
|
|
937abebbe1 | ||
|
|
c537980d98 | ||
|
|
c9adc81e2e | ||
|
|
b811b334ae | ||
|
|
4d57e44839 | ||
|
|
6c52d5ce27 | ||
|
|
09eb448746 | ||
|
|
fa2a27cfeb | ||
|
|
a5b75e9a86 | ||
|
|
df35d87336 | ||
|
|
3c413d59c8 | ||
|
|
e3fd3ccd72 | ||
|
|
fb8409a5c8 | ||
|
|
bde80cb28b | ||
|
|
fbce475270 | ||
|
|
31e2156c4b | ||
|
|
b739506936 | ||
|
|
37cc07dd41 | ||
|
|
285df7b0e0 | ||
|
|
8cf8974a03 | ||
|
|
bff31e129d | ||
|
|
179ee2db78 | ||
|
|
11dae1711f | ||
|
|
f08aa2bf48 | ||
|
|
fa34ba3908 | ||
|
|
4ccf671cc6 | ||
|
|
88bd32f1b7 | ||
|
|
ae15f75089 | ||
|
|
0f51e3c564 | ||
|
|
f1e38b352e | ||
|
|
ed4d4f1145 | ||
|
|
ee704a0ff1 | ||
|
|
2f2e6ad487 | ||
|
|
e51f7d2c17 | ||
|
|
be4f8cccaa | ||
|
|
f3e159bc93 | ||
|
|
dd896e1b8d | ||
|
|
59d884af8c | ||
|
|
e4cd5838fc | ||
|
|
1507be5b01 | ||
|
|
fc030ac7de | ||
|
|
085aaef325 | ||
|
|
92dd4e4301 | ||
|
|
56ff70f8e0 | ||
|
|
38d6976c03 | ||
|
|
efd412f908 | ||
|
|
9ea95e6c64 | ||
|
|
d0407c2d85 | ||
|
|
81f32c7b65 | ||
|
|
754643c1c7 | ||
|
|
0387e9c199 | ||
|
|
29e1976855 | ||
|
|
188a17ed56 | ||
|
|
9542d9d8d7 | ||
|
|
2d04eef425 | ||
|
|
925927fc8f | ||
|
|
27688de10e | ||
|
|
9b962d10a4 | ||
|
|
ab0603812d | ||
|
|
b64281cc0e | ||
|
|
52192552bd | ||
|
|
b54cdfb2b7 | ||
|
|
7b22c44ccd | ||
|
|
9aba884b34 | ||
|
|
3f7ad83398 | ||
|
|
38bb45223a | ||
|
|
054061685a | ||
|
|
7c1cec2525 | ||
|
|
0380c13bbe | ||
|
|
518e7202b2 | ||
|
|
f597910121 | ||
|
|
24b0942275 | ||
|
|
6e6bbac7a5 | ||
|
|
a7ef5ce1b0 | ||
|
|
ea693f0282 | ||
|
|
74760d3ccd | ||
|
|
32f62ed6d0 | ||
|
|
d4e6ce3e97 | ||
|
|
d605fdabfa | ||
|
|
f4df22d1c5 | ||
|
|
78d6a02b0c | ||
|
|
f1eaf57200 | ||
|
|
749817b7c3 | ||
|
|
9fa9ccb04e | ||
|
|
6934832e53 | ||
|
|
f9322fb8ed | ||
|
|
5e473cd8fd | ||
|
|
3e8fcb6d03 | ||
|
|
cfa4b57cb0 | ||
|
|
57a5e54ddc | ||
|
|
41e8e5cb8e | ||
|
|
56de4964ee | ||
|
|
a74ab6478c | ||
|
|
ee61a4b99e | ||
|
|
dfc2545470 | ||
|
|
b014c1f211 | ||
|
|
37180ed9cd | ||
|
|
7551f2a0b1 | ||
|
|
00b3336334 | ||
|
|
571e257db1 |
+45
-5
@@ -1,12 +1,13 @@
|
||||
.*.swp
|
||||
*.o
|
||||
*.rdb
|
||||
*.log
|
||||
redis-cli
|
||||
redis-server
|
||||
dump.rdb
|
||||
redis-benchmark
|
||||
redis-check-dump
|
||||
redis-check-aof
|
||||
redis-check-dump
|
||||
redis-cli
|
||||
redis-sentinel
|
||||
redis-server
|
||||
doc-tools
|
||||
release
|
||||
misc/*
|
||||
@@ -16,7 +17,6 @@ SHORT_TERM_TODO
|
||||
release.h
|
||||
src/transfer.sh
|
||||
src/configs
|
||||
src/redis-server.dSYM
|
||||
redis.ds
|
||||
src/redis.conf
|
||||
deps/lua/src/lua
|
||||
@@ -24,3 +24,43 @@ deps/lua/src/luac
|
||||
deps/lua/src/liblua.a
|
||||
.make-*
|
||||
.prerequisites
|
||||
*.dSYM
|
||||
*.user
|
||||
*.exe
|
||||
*.sdf
|
||||
*.suo
|
||||
msvs/Debug/
|
||||
msvs/Release/
|
||||
msvs/RedisBenchmark/Debug/
|
||||
msvs/RedisBenchmark/Release/
|
||||
msvs/RedisBenchmark/x64/
|
||||
msvs/RedisCheckAof/Debug/
|
||||
msvs/RedisCheckAof/Release/
|
||||
msvs/RedisCheckAof/x64/
|
||||
msvs/RedisCheckDump/Debug/
|
||||
msvs/RedisCheckDump/Release/
|
||||
msvs/RedisCheckDump/x64/
|
||||
msvs/RedisCli/Debug/
|
||||
msvs/RedisCli/Release/
|
||||
msvs/RedisCli/x64/
|
||||
msvs/hiredis/Debug/
|
||||
msvs/hiredis/Release/
|
||||
msvs/hiredis/x64/
|
||||
msvs/lua/lua/Debug/
|
||||
msvs/lua/lua/Release/
|
||||
msvs/lua/lua/x64/
|
||||
msvs/x64/
|
||||
msvs/ipch
|
||||
msvs/RedisServer.opensdf
|
||||
!msvs/RedisWaInst/bin/*
|
||||
!msvs/RedisWaInst/bin/Inst4WA/*
|
||||
!msvs/RedisWaInst/bin/RedisPkgBin/*
|
||||
msvs/RedisWAInst/src/RedisDeployCmdlets/bin/
|
||||
msvs/RedisWAInst/src/RedisDeployCmdlets/obj/
|
||||
msvs/RedisWAInst/src/RedisInstBin/
|
||||
msvs/RedisWAInst/src/RedisInstWA/app.config
|
||||
msvs/RedisWAInst/src/RedisInstWA/bin/
|
||||
msvs/RedisWAInst/src/RedisInstWA/obj/
|
||||
msvs/RedisWAInst/src/RedisServer/bin/
|
||||
msvs/RedisWAInst/src/RedisServer/obj/
|
||||
|
||||
|
||||
+590
-63
@@ -1,81 +1,608 @@
|
||||
Redis 2.6 release notes
|
||||
Redis 2.8 release notes
|
||||
=======================
|
||||
|
||||
Migrating from 2.4 to 2.6
|
||||
** IMPORTANT ** Check the 'Migrating from 2.6 to 2.8' section at the end of
|
||||
this file for information about what changed between 2.6 and
|
||||
2.8 and how this may affect your application.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Upgrade urgency levels:
|
||||
|
||||
LOW: No need to upgrade unless there are new features you want to use.
|
||||
MODERATE: Program an upgrade of the server, but it's not urgent.
|
||||
HIGH: There is a critical bug that may affect a subset of users. Upgrade!
|
||||
CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
--[ Redis 2.8.19 ] Release date: 16 Dec 2014
|
||||
|
||||
# UPGRADE URGENCY: LOW for both Redis and Sentinel. This release mostly
|
||||
fixes small issues.
|
||||
|
||||
02d465c Don't log admin commands in MONITOR. (antirez)
|
||||
4d8f426 List of commands flagged as admin commands modified. (antirez)
|
||||
e47e460 Lua cmsgpack lib updated to latest version. (antirez)
|
||||
5509c14 Add symlink to redis-sentinel during make install (Rhommel Lamas)
|
||||
7de1ef7 SORT: Don't sort Set elements if not needed. (antirez)
|
||||
e945a54 Fix zero-ordering SORT when called against lists (Matt Stancliff)
|
||||
d81c383 Update redis_init_script.tpl (Ben Dowling)
|
||||
dba57ea FIXED redis-benchmark's idle mode.With idle mode shouldn't create write event (zhanghailei)
|
||||
888ea17 zipmap.c: update comments above (Sun He)
|
||||
86ebc13 replaced // comments #2150 (Deepak Verma)
|
||||
3d73f08 redis-benchmark AUTH command to be discarded after the first send #2150 (azure provisioned user)
|
||||
76d53a6 sds.c: Correct two spelling mistakes in comments (Sun He)
|
||||
4848cf9 sds.c/sdscatvprintf: set va_end to finish va_list cpy (Sun He)
|
||||
d2f584f sds.c: Correct some comments (Sun He)
|
||||
2ed3f09 Update whatisdoing.sh (Serghei Iakovlev)
|
||||
77b997d Include stropts only if __sun is defined. (antirez)
|
||||
d409371 Fix implicit declaration of ioctl on Solaris (Jan-Erik Rediger)
|
||||
23b96c0 Silence _BSD_SOURCE warnings in glibc 2.20 and forward (Johan Bergström)
|
||||
a47a042 Mark whatisdoing.sh as deprecated in top-comment. (antirez)
|
||||
b5737d2 getting pid fixes (Serghei Iakovlev)
|
||||
a598e08 sparkline.c: AddSample skip Empty label (Sun He)
|
||||
7d480ab sparkline.c: mov label-ini into the AddSample Function (Sun He)
|
||||
2f3c860 Only ignore sigpipe in interactive mode (Jan-Erik Rediger)
|
||||
0c211a1 Simplify lua_cmsgpack macro and fix build on old Linux distros. (antirez)
|
||||
|
||||
--[ Redis 2.8.18 ] Release date: 4 Dec 2014
|
||||
|
||||
# UPGRADE URGENCY: LOW for both Redis and Sentinel. This release mostly
|
||||
adds new features to Redis, and contains non critical
|
||||
fixes.
|
||||
|
||||
* [FIX] Linenoise updated to be more VT100 compatible. (Salvatore Sanfilippo)
|
||||
* [FIX] A number of typos fixed inside comments. (Various authors)
|
||||
* [FIX] redis-cli no longer quits after long timeouts. (Matt Stancliff)
|
||||
* [FIX] Test framework improved to detect never terminating scripts, cleanup
|
||||
instances on crashes. (Salvatore Sanfilippo)
|
||||
* [FIX] PFCOUNT can be used on slaves now. (Salvatore Sanfilippo)
|
||||
* [FIX] ZSCAN no longer report very small scores as 0. (Matt Stancliff,
|
||||
Michael Grunder, Salvatore Sanfilippo)
|
||||
* [FIX] Don't show the ASCII logo if syslog is enabled. Redis is now
|
||||
an Enterprise Grade product. (Salvatore Sanfilippo)
|
||||
|
||||
* [NEW] EXPERIMENTAL: Diskless replication, for more info check the doc at
|
||||
http://redis.io/topics/replication. (Salvatore Sanfilippo).
|
||||
* [NEW] Transparent Huge Pages detection and reporting in logs and
|
||||
LATENCY DOCTOR output. (Salvatore Sanfilippo)
|
||||
* [NEW] Many Lua scripting enhancements: Bitops API, cjson upgrade and tests,
|
||||
cmsgpack upgrade. (Matt Stancliff)
|
||||
* [NEW] Total and instantaneous Network bandwidth tracking in INFO.
|
||||
* [NEW] DEBUG POPULATE two args form implemented (old form still works).
|
||||
The second argument is the key prefix. Default is "key:" (Salvatore
|
||||
Sanfilippo)
|
||||
* [NEW] Check that tcp-backlog is matched by /proc/sys/net/core/somaxconn, and
|
||||
warn about it if not. (Salvatore Sanfilippo)
|
||||
|
||||
--[ Redis 2.8.17 ] Release date: 19 Sep 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH for Redis Sentinel.
|
||||
LOW for Redis Server (unmodified compared to 2.8.16).
|
||||
|
||||
* [FIX] Resolved a memory leak in the hiredis library causing a memory leak
|
||||
in Redis Sentinel when a monitored instance or another Sentinel is
|
||||
unavailable. Every reconnection attempt will leak a small amount of
|
||||
memory, but in the long run the process can reach a considerable size.
|
||||
|
||||
--[ Redis 2.8.16 ] Release date: 16 Sep 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH for Redis if you are using 2.8.15 + AOF.
|
||||
LOW for Sentinel.
|
||||
|
||||
* [FIX] The ability to load truncated AOF files introduced with Redis 2.8.15
|
||||
contains a bug fixed in this release: after loading the file was not
|
||||
truncated to the last valid command, so the new commands are appended
|
||||
after a non well formed command. This means that:
|
||||
|
||||
1) The first AOF rewrite triggered by the server will automatically
|
||||
fix the problem.
|
||||
2) However, if the server is restarted before the rewrite, Redis may
|
||||
not be able to load the file and you need to manually fix it.
|
||||
|
||||
In order to fix a corrupted file you should start the redis-check-aof
|
||||
utility WITHOUT the --fix option, just to check the offset where the
|
||||
corruption is found. Around the offset reported by the check utility
|
||||
you'll find, inside your AOF file, a command which is not complete
|
||||
according to the Redis protocol. Just remove this incomplete command
|
||||
leafing the file unaltered before and after the offending command,
|
||||
and restart the server.
|
||||
|
||||
IMPORTANT #1: Redis 2.8.15 is the only stable version of Redis with
|
||||
this bug so probably no actual real-world problem happened since the
|
||||
problem is automatically fixed at the first automatic AOF rewrite.
|
||||
|
||||
IMPORTANT #2: Before upgrading to Redis 2.8.16, if you are using Redis
|
||||
2.8.15 with AOF enabled, make sure to trigger a manual AOF rewrite
|
||||
using the BGREWRITEAOF command.
|
||||
|
||||
* [FIX] SAVE is no longer propagated to AOF / slaves.
|
||||
|
||||
--[ Redis 2.8.15 ] Release date: 12 Sep 2014
|
||||
|
||||
# UPGRADE URGENCY: LOW for Redis, HIGH for Sentinel.
|
||||
|
||||
* [FIX] Sentinel critical bug fixed: the absolute majority was computed in a
|
||||
wrong way because of a programming error. Now the implementation does
|
||||
what the specification says and the majority to authorize a failover
|
||||
(that should not be confused with the ODOWN quorum) is the majority of
|
||||
*all* the Sentinels ever seen for a given master, regardless of their
|
||||
current state.
|
||||
* [FIX] GETRANGE test no longer fails for 32 bit builds (Matt Stancliff).
|
||||
* [FIX] Limit SCAN latency when the hash table is in an odd state (very few
|
||||
populted buckets because rehashing is in progress). (Xiaost and
|
||||
Salvatore Sanfilippo)
|
||||
|
||||
* [NEW] Redis is now able to load truncated AOF files without requiring a
|
||||
redis-check-aof utility run. The default now is to load truncated
|
||||
(but apparently not corrupted) AOFs, you can change this in redis.conf.
|
||||
(Salvatore Sanfilippo).
|
||||
* [NEW] Sentinel: ability to announce itself with an arbitrary IP/port to work
|
||||
in the context of natted networks. However this is probably still
|
||||
not enough since there is no equivalent mechanism for slaves listed
|
||||
in the master INFO output. (Dara Kong and Salvatore Sanfilippo)
|
||||
|
||||
--[ Redis 2.8.14 ] Release date: 1 Sep 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH for Lua scripting users, the server could crash because
|
||||
of a bug introduced in Redis 2.8.10, otherwise LOW.
|
||||
LOW for Redis Sentinel.
|
||||
|
||||
* [FIX] Don't prevent use of shared integers if maxmemory policy is non-LRU.
|
||||
(Salvatore Sanfilippo)
|
||||
* [FIX] Fail SYNC if background save child aborted due to a signal.
|
||||
(Yossi Gottlieb)
|
||||
* [FIX] Different small redis-cli fixes. (Dov Murik, Charsyam, cubicdaiya,
|
||||
Kashif Rasul, Jan-Erik Rediger, Matt Stancliff)
|
||||
* [FIX] AIX compilation fixes. (Siah Lyimo)
|
||||
* [FIX] A number of other smaller issues.
|
||||
* [FIX] Improved SIGINT handling (Matt Stancliff, Salvatore Sanfilippo)
|
||||
* [FIX] Use unsigned types in SDS header to raise limit to 4GB.
|
||||
(Matt Stancliff, Salvatore Sanfilippo)
|
||||
* [FIX] Handle signed/unsigned comparisons with more care around the code.
|
||||
(Salvatore Sanfilippo)
|
||||
* [FIX] Colorized test output fixed to don't change the background color.
|
||||
(Mariano Pérez Rodríguez)
|
||||
* [FIX] More Sentinel IPv6 fixes. (Eiichi Sato)
|
||||
* [FIX] Deny CLIENT command in scripts. (Matt Stancliff)
|
||||
* [FIX] Allow datasets with more than 2 billion of keys, initial work.
|
||||
* [FIX] Fix a Lua scripting crash by storing the length of the static
|
||||
argv when first allocated. (Paddy Byers)
|
||||
|
||||
* [NEW] Pub/Sub PING. (Salvatore Sanfilippo)
|
||||
* [NEW] Much faster ZUNIONSTORE. (Kyle Hubert, Salvatore Sanfilippo)
|
||||
* [NEW] Faster ll2string() implementation. (Salvatore Sanfilippo)
|
||||
* [NEW] **WARNING, minor API change**: PUBSUB NUMSUB: return type modified
|
||||
to integer. (Matt Stancliff)
|
||||
* [NEW] redis-benchmark support for AUTH. (CharSyam)
|
||||
|
||||
--[ Redis 2.8.13 ] Release date: 14 Jul 2014
|
||||
|
||||
# UPGRADE URGENCY: LOW for Redis and Sentinel, this is a features enhancement
|
||||
release mostly. Since this release introduces the latency
|
||||
monitoring feature, Redis 2.8 users experiencing latency
|
||||
issues are strongly encouraged to upgrade.
|
||||
|
||||
* [FIX] CLIENT KILL minor backward compatibility fixes. (Salvatore Sanfilippo)
|
||||
* [FIX] Enable HAVE_ATOMIC for PowerPC. (Matt Stancliff)
|
||||
* [FIX] More robust PSYNC and AOF rewrites tests. (Salvatore Sanfilippo)
|
||||
* [FIX] Solaris build fixed. (Matt Stancliff, Salvatore Sanfilippo)
|
||||
|
||||
* [NEW] The new latency monitoring feature, as documented at
|
||||
http://redis.io/topics/latency-monitor (Salvatore Sanfilippo)
|
||||
* [NEW] The COMMAND command, exposing the Redis command table
|
||||
as an API. (Matt Stancliff)
|
||||
* [NEW] Update used memory with C11 __atomic. (Matt Stancliff)
|
||||
|
||||
--[ Redis 2.8.12 ] Release date: 23 Jun 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH for Redis, CRITICAL for Sentinel.
|
||||
|
||||
# WARNING: This release contains a non backward compatible semantical change
|
||||
to Lua script that should affect an almost zero number of users.
|
||||
|
||||
* [FIX / BREAKS BACKWARD COMPATIBILITY] Using SELECT inside Lua scripts no
|
||||
longer makes the selected DB to be set in the calling client.
|
||||
So Lua can still use SELECT, but the client calling the script will
|
||||
remain set to the original DB. Thix fixes an issue with Redis
|
||||
replication of Lua scripts that called SELECT without reverting the
|
||||
selected DB to the original one. (Salvatore Sanfilippo)
|
||||
* [FIX] Sentinel failover was instalbe if the master was detected as available
|
||||
during the failover (especially during manual failovers) because
|
||||
of an implementation error (lack of checking of
|
||||
SRI_PROMOTED flag). (Salvatore Sanfilippo)
|
||||
* [FIX] Cancel SHUTDOWN if initial AOF is being written. (Matt Stancliff)
|
||||
* [FIX] Sentinel: bind source address for outcoming connections. (Matt
|
||||
Stancliff).
|
||||
* [FIX] Less timing sensitive Sentinel tests. (Salvatore Sanfilippo).
|
||||
|
||||
* [NEW] redis-cli --intrinsic-latency stopped with SIGINT still reports
|
||||
stats (Matt Stancliff)
|
||||
* [NEW] Sentinels broadcast an HELLO message ASAP after a failover in order to
|
||||
reach a consistent state faster (before it relied for periodic HELLO
|
||||
messages). (Salvatore Sanfilippo).
|
||||
* [NEW] Jemalloc updated to 3.6.0. (Salvatore Sanfilippo)
|
||||
* [NEW] CLIENT LIST speedup. (Salvatore Sanfilippo)
|
||||
* [NEW] CLIENT LIST new unique incremental ID to every client. (Salvatore
|
||||
Sanfilippo)
|
||||
* [NEW] ROLE command added. (Salvatore Sanfilippo)
|
||||
* [NEW] CLIENT KILL new form to kill by client type and ID (see doc at
|
||||
redis.io for more info). (Salvatore Sanfilippo)
|
||||
* [NEW] Sentinel now disconnects clients when instances are reconfigured
|
||||
(see http://redis.io/topics/sentinel-clients). (Salvatore Sanfilippo)
|
||||
* [NEW] Hiredis update to latest version. (Matt Stancliff)
|
||||
|
||||
--[ Redis 2.8.11 ] Release date: 11 Jun 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH if you use Lua scripting, LOW otherwise.
|
||||
|
||||
* [FIX] A previous fix for Lua -> Redis numerical precision enhancement
|
||||
introduced a new problem. In Redis 2.8.10 commands called from Lua
|
||||
passing a string that "looks like" a very large number, may actually
|
||||
use as argument the string converted as a float. This bug is now
|
||||
fixed.
|
||||
* [FIX] Now commands other than *PUSH* adding elements to a list will be able
|
||||
to awake clients blocked in a blocking POP operation.
|
||||
* [FIX] Cygwin compilation fixes.
|
||||
|
||||
--[ Redis 2.8.10 ] Release date: 5 Jun 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH if you use min-slaves-to-write option.
|
||||
|
||||
* [FIX] IMPORTANT! A min-slaves-to-write option active in a slave totally
|
||||
prevented the slave from acception the master stream of commands.
|
||||
This release includes testes for min-slaves-to-write, and a fix
|
||||
for this issue.
|
||||
* [FIX] Sometimes DEL returned 1 for already expired keys. Fixed.
|
||||
* [FIX] Fix test false positive because new osx 'leaks' output.
|
||||
* [FIX] PFCOUNT HLL cache invalidation fixed: no wrong value was reported
|
||||
but the cache was not used at all, leading to lower performances.
|
||||
* [FIX] Accept(2) multiple clients per readable-event invocation, and better
|
||||
processing of I/O while loading or busy running a timedout script.
|
||||
Basically now the LOADING / BUSY errors are reported at a decent
|
||||
speed.
|
||||
* [FIX] A softwaer watchdog crash fixed.
|
||||
* [FIX] Fixed a Lua -> Redis numerical precision loss.
|
||||
|
||||
* [NEW] Lua scripting engine speed improved.
|
||||
* [NEW] Sentinel generates one new event for humans to understand better
|
||||
what is happening during a failover: +config-update-from.
|
||||
Also the time at which a failover will be re-attempted is logged.
|
||||
|
||||
--[ Redis 2.8.9 ] Release date: 22 Apr 2014
|
||||
|
||||
# UPGRADE URGENCY: LOW, only new features introduced, no bugs fixed.
|
||||
|
||||
* [NEW] The HyperLogLog data structure. You can read more about it
|
||||
in this blog post. http://antirez.com/news/75
|
||||
* [NEW] The Sorted Set data type has now support for lexicographic range
|
||||
queries, check the new commands ZRANGEBYLEX, ZLEXCOUNT and
|
||||
ZREMRANGEBYLEX, which are documented at http://redis.io.
|
||||
|
||||
--[ Redis 2.8.8 ] Release date: 25 Mar 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH for Redis, LOW for Sentinel. There is a potentially
|
||||
critical bug fix causing data loss in Redis but it requires
|
||||
a combination of disk full and the use of the
|
||||
SHUTDOWN command.
|
||||
|
||||
* [FIX] Fixed data loss when SHUTDOWN was used with a disk full condition.
|
||||
* [FIX] Fixed a memory leak in the SORT syntax error processing.
|
||||
* [FIX] When Sentinel down-after-milliseconds parameter is modified at runtime
|
||||
now it gets propagated to all the slaves and sentinel instances
|
||||
of the master.
|
||||
* [FIX] `install_server.sh` script finally fixed.
|
||||
* [FIX] Different fixes to maxclients handling.
|
||||
|
||||
* [NEW] Sentinels are now able to send update messages in a peer-to-peer
|
||||
fashion even if no Redis instances are available. Now the Sentinel
|
||||
liveness property that the most updated configuration in a given
|
||||
partition is propagated to all the Sentinels is extended to partitions
|
||||
without reachable instances.
|
||||
* [NEW] Sentinel safety properties are now ensured in a crash-recovery system
|
||||
model since some state is persisted on disk before replying to other
|
||||
nodes, and reloaded at startup.
|
||||
* [NEW] Sentinel now uses CLIENT SETNAME so that it is easy to identify
|
||||
Sentinels using CLIENT LIST among other clients.
|
||||
* [NEW] Sentinel failure detection and reconnection code improved.
|
||||
* [NEW] Use all 24 bits (instead of 22) for the Redis objects LRU field.
|
||||
Note that the new LRU algorithm using eviction pools was not backported
|
||||
from unstable for safery / code maturity concerns.
|
||||
* [NEW] Majory speedup for the INFO command (it is now 6 times faster).
|
||||
* [NEW] More Sentinel unit tests.
|
||||
* [NEW] New command DEBUG ERROR returns the specified error. Example:
|
||||
DEBUG ERROR "LOADING database". This is handy to write Redis client
|
||||
libraries unit tests.
|
||||
* [NEW] redis-cli now supports multi-line editing via updated linenoise lib.
|
||||
|
||||
Thanks to Matt Stancliff and Jan-Erik Rediger for the work done in the context
|
||||
of this release.
|
||||
|
||||
--[ Redis 2.8.7 ] Release date: 5 Mar 2014
|
||||
|
||||
# UPGRADE URGENCY: LOW for Redis, LOW for Sentinel. However this release adds
|
||||
new features so users may want to upgrade in order to
|
||||
exploit the new functionalities.
|
||||
|
||||
* [FIX] Sometimes the absolute config file path was obtained in a wrong way.
|
||||
This happened when there was a "dir" directive inside the config file
|
||||
and at the same time the configuration file was given as a relative
|
||||
path to redis-server or redis-sentinel executables.
|
||||
* [FIX] redis-cli: Automatically enter --slave mode when SYNC or PSYNC are
|
||||
called during an interactive session.
|
||||
* [FIX] Sentinel "IDONTKNOW" error removed as it does not made sense with the
|
||||
new Sentinel design. This error was actually a fix for a design error
|
||||
in the first implementation of Sentinel.
|
||||
* [FIX] Sentinel: added a missing exit() call to abort after config file
|
||||
checks at startup. This error was introduced with an improvement in
|
||||
a previous 2.8 release.
|
||||
* [FIX] BITCOUNT: fixed unaligned access causing issues in sparc and other
|
||||
archs not capable of dealing with unaligned accesses. This also makes
|
||||
the code faster in archs where unaligned accesses are allowed.
|
||||
* [FIX] Sentinel: better nodes fail over start time desynchronization to avoid
|
||||
split-brain during the voting process needed to get authorization to
|
||||
fail over. This means the system is less likely to need to retry
|
||||
and will fail over faster. No changes in behavior / correctness.
|
||||
* [FIX] Force INFO used_memory_peak to match peak memory. This generated some
|
||||
confusion among users even if it was not an actual bug.
|
||||
|
||||
* [NEW] Sentinel unit tests and framework. More tests needed and units must
|
||||
be improved in order to have less false positives, but it is a start
|
||||
and features a debugging console that is useful to fix tests or to
|
||||
inspect bugs causing tests failures.
|
||||
* [NEW] New Sentinel events: +/-monitor and +set used to monitor when an
|
||||
instance to monitor is added or removed, or when a configuration
|
||||
is modified via SENTINEL SET.
|
||||
* [NEW] Redis-cli updated to use SCAN instead of random sampling via
|
||||
RANDOMKEY in order to implement --bigkeys feature. Moreover the
|
||||
implementation now supports pipelining and reports more information
|
||||
at the end of the scan. Much faster, much better. A special thank
|
||||
you to Michael Grunder for this improvement.
|
||||
* [NEW] redis-cli now supports a new --intrinsic-latency mode that is able
|
||||
to meter the latency of a system due to kernel / hypervisor.
|
||||
How to use it is explained at http://redis.io/topics/latency.
|
||||
* [NEW] New command BITPOS: find first bit set or clear in a bitmap.
|
||||
* [NEW] CONFIG REWRITE calls are now logged.
|
||||
|
||||
--[ Redis 2.8.6 ] Release date: 13 Feb 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH for Redis, LOW for Sentinel. Redis users using Lua
|
||||
scripts with EVALSHA and attached slaves and/or AOF
|
||||
persistence should consider upgrading ASAP.
|
||||
|
||||
* [FIX] Fixed an critical EVALSHA script cache bug: scripts executed may not
|
||||
propagate to AOF / Slaves correctly under certain conditions.
|
||||
See issue #1549 at Github for more information.
|
||||
* [FIX] Fixed multiple bugs resulting into closing the link with master or slave
|
||||
during replication without good reasons. This will result in useless
|
||||
resynchronizations, or infinite loops where the replication link can't
|
||||
be established.
|
||||
* [FIX] Don't count the time needed to populate the buffers of clients waiting
|
||||
in MONITOR mode when populating the Slow Log entries.
|
||||
|
||||
* [NEW] AOF write errors (like no space on device) no longer abort Redis if the
|
||||
fsync policy is none or every second. The database enters a read-only
|
||||
mode where every write is refused with an error. Normal operations are
|
||||
restored as soon as Redis is able to append again data to the AOF file.
|
||||
* [NEW] Sentinel now accepts SHUTDOWN command.
|
||||
|
||||
--[ Redis 2.8.5 ] Release date: 4 Feb 2014
|
||||
|
||||
# UPGRADE URGENCY: HIGH for Redis, LOW for Sentinel. Redis users using Lua
|
||||
scripts with expires, and Redis users relying on the
|
||||
ability of Redis to block writes on RDB saving errors
|
||||
should plan to upgrade ASAP.
|
||||
|
||||
* [FIX] Fixed a replication bug caused by Lua scripts + expired keys: keys could
|
||||
expire in the middle of scripts causing non-deterministic behavior.
|
||||
* [FIX] MISCONFIG error if condition fixed, the server was no longer able
|
||||
to stop writes on RDB misconfiguration after this error was introduced.
|
||||
* [FIX] REDIS_AOF_REWRITE_MIN_SIZE is now 64mb like example redis.conf default.
|
||||
* [FIX] Perform fflush() before fsync() in rio.c (bug without actual effects).
|
||||
* [FIX] Don't log MONITOR clients as disconnecting slaves.
|
||||
* [FIX] SENTINEL MASTER arity check fixed. Crashed the Sentinel instance when
|
||||
the command was given without arguments.
|
||||
|
||||
* [NEW] Allow CONFIG and SHUTDOWN while in stale-slave state.
|
||||
* [NEW] Support for configurable TCP listen(2) backlog size.
|
||||
* [NEW] redis-cli supports SCAN via the --scan and --pattern options.
|
||||
* [NEW] SENTINEL SET master quorum via runtime API implemented.
|
||||
|
||||
--[ Redis 2.8.4 ] Release date: 13 Jan 2014
|
||||
|
||||
# UPGRADE URGENCY: MODERATE for Redis and Sentinel.
|
||||
|
||||
* [FIX] Makefile compatibility with non common make variants improved.
|
||||
* [FIX] SDIFF crash in very unlikely to trigger state fixed.
|
||||
* [FIX] Config rewriting fixed: don't wipe options unknown to the rewrite
|
||||
process.
|
||||
* [FIX] Set TCP port to 0 works again to disable TCP networking.
|
||||
* [FIX] Fixed replication with old Redis instances as masters by not
|
||||
sending REPLCONF ACK to them.
|
||||
* [FIX] Fix keyspace notifications rewrite and CONFIG GET output.
|
||||
* [FIX] Fix RESTORE TTL handling in 32 bit systems (32 bit overflow).
|
||||
|
||||
* [NEW] Sentinel now has a run time configuration API.
|
||||
* [NEW] Log when we lost connection with master or slave.
|
||||
* [NEW] When instance is turned from slave to master now inherits the
|
||||
old master replication offset when possible. This improves the
|
||||
Sentinel failover procedure.
|
||||
|
||||
--[ Redis 2.8.3 ] Release date: 11 Dec 2013
|
||||
|
||||
# UPGRADE URGENCY: MODERATE for Redis, HIGH for Sentinel.
|
||||
|
||||
* [FIX] Sentinel instance role sampling fixed, the system is now more
|
||||
reliable during failover and when reconfiguring instances with
|
||||
non matching configuration.
|
||||
* [FIX] Inline requests are now handled even when terminated with just LF.
|
||||
* [FIX] Replication timeout handling greatly improved, now the slave is able
|
||||
to ping the master while removing the old data from memory, and while
|
||||
loading the new RDB file. This avoid false timeouts sensed by
|
||||
masters.
|
||||
* [FIX] Fixed a replication bug involving 32 bit instances and big datasets
|
||||
hard to compress that resulted into more than 2GB of RDB file sent.
|
||||
* [FIX] Return error for inline requests with unbalanced quotes.
|
||||
* [FIX] Publish the slave replication offset even when disconnected from the
|
||||
master if there is still a cached master instance.
|
||||
|
||||
--[ Redis 2.8.2 ] Release date: 2 Dec 2013
|
||||
|
||||
# UPGRADE URGENCY: MODERATE for both Redis and Sentinel.
|
||||
|
||||
* [FIX] Sentinel better desynchronization to avoid split-brain elections
|
||||
where no Sentinel managed to get elected.
|
||||
* [FIX] Stop accepting writes on "MISCONF" error only if master, not slave.
|
||||
* [FIX] Reply to PING with an error on "MISCONF" errors.
|
||||
|
||||
--[ Redis 2.8.1 ] Release date: 25 Nov 2013
|
||||
|
||||
# UPGRADE URGENCY: LOW for Redis, CRITICAL for Senitnel. You don't need to
|
||||
upgrade your Redis instances but it is highly recommended
|
||||
to upgrade and restart all the Sentinel processes.
|
||||
|
||||
* [FIX] Fixed a bug in "new Sentinel" config propagation.
|
||||
* [FIX] Fixed a false positive in Redis tests.
|
||||
|
||||
--[ Redis 2.8.0 ] Release date: 22 Nov 2013
|
||||
|
||||
# UPGRADE URGENCY: LOW, unless you want to upgrade to new Sentinel code.
|
||||
|
||||
* [FIX] Fixed an error in rdbWriteRaw() that should have no practical impact.
|
||||
* [NEW] Log the new master when SLAVEOF command is used.
|
||||
* [NEW] Sentinel code synchronized with the unstable branch, the new Sentinel
|
||||
is a reimplementation that uses more reliable algorithms.
|
||||
|
||||
--[ Redis 2.8 Release Candidate 6 (2.7.106) ] Release date: 6 Nov 2013
|
||||
|
||||
This is the 6th release candidate of Redis 2.8 (official version is 2.7.106).
|
||||
|
||||
# UPGRADE URGENCY: LOW, only new features back ported, no fixes.
|
||||
|
||||
* [NEW] SCAN, SSCAN, HSCAN, ZSCAN commands.
|
||||
|
||||
--[ Redis 2.8 Release Candidate 5 (2.7.105) ] Release date: 9 Oct 2013
|
||||
|
||||
This is the 5th release candidate of Redis 2.8 (official version is 2.7.105).
|
||||
Important bugs fixed inside.
|
||||
|
||||
# UPGRADE URGENCY: HIGH because of many non critical replication bugs fixed.
|
||||
|
||||
* [FIX] redis-cli: don't crash with --bigkeys when the key no longer exist.
|
||||
* [FIX] Allow AUTH / PING when disconnected from slave and serve-stale-data is no.
|
||||
* [FIX] PSYNC: safer handling of PSYNC requests with offsets in the future.
|
||||
* [FIX] Replication: Fix master timeout detection.
|
||||
* [FIX] Replication: Correctly install the write handler after successful PSYNC.
|
||||
|
||||
--[ Redis 2.8 Release Candidate 4 (2.7.104) ] Release date: 30 Aug 2013
|
||||
|
||||
This is the fourth release candidate of Redis 2.8 (official version is 2.7.104).
|
||||
Important bugs fixed inside.
|
||||
|
||||
# UPGRADE URGENCY: HIGH because of the EVAL memory leak.
|
||||
|
||||
* [FIX] Fixed a serious EVAL memory leak in the Lua stack.
|
||||
* [FIX] Fixed server startup when no IPv6 address exists in any interface.
|
||||
* [FIX] Send MISCONFIG error when BGSAVE fails because can't fork.
|
||||
* [FIX] Memory efficiency with large (> a few kbytes) values improved considerably.
|
||||
* [NEW] DEBUG SDSLEN for sds memory debugging.
|
||||
|
||||
--[ Redis 2.8 Release Candidate 3 (2.7.103) ] Release date: 19 Aug 2013
|
||||
|
||||
This is the third release candidate of Redis 2.8 (official version is 2.7.103).
|
||||
Important bugs fixed inside.
|
||||
|
||||
# UPGRADE URGENCY: HIGH
|
||||
|
||||
* [FIX] Improved expired keys collection algorithm. Even under heavy load keys
|
||||
to be expired can't accumulate because of lack of CPU time.
|
||||
* [FIX] Replication speed regression fixed (issue #1238).
|
||||
* [FIX] Fixed an hard to trigger PSYNC bug.
|
||||
* [FIX] Fixed Issue #1240, ZUNIONSTORE could lead to wrong result.
|
||||
* [NEW] Add per-db average TTL information in INFO output.
|
||||
* [NEW] redis-benchmark improvements.
|
||||
* [NEW] dict.c API wrong usage detection.
|
||||
|
||||
--[ Redis 2.8 Release Candidate 2 (2.7.102) ] Release date: 30 Jul 2013
|
||||
|
||||
This is the second release candidate of Redis 2.8 (official version is 2.7.102).
|
||||
Important bugs fixed inside.
|
||||
|
||||
# UPGRADE URGENCY: HIGH
|
||||
|
||||
* [FIX] Fixed a critical replication bug, see issue #1221.
|
||||
* [NEW] The new inline protocol now accepts quoted strings like, for example
|
||||
you can now type in a telnet session: set 'foo bar' "hello world\n".
|
||||
|
||||
--[ Redis 2.8 Release Candidate 1 (2.7.101) ] Release date: 18 Jul 2013
|
||||
|
||||
This is the first release candidate of Redis 2.8 (official version is 2.7.101).
|
||||
|
||||
The following is a list of improvements in Redis 2.8, compared to Redis 2.6.
|
||||
|
||||
* [NEW] Slaves are now able to partially resynchronize with the master, so most
|
||||
of the times a full resynchronization with the RDB creation in the master
|
||||
side is not needed when the master-slave link is disconnected for a short
|
||||
amount of time.
|
||||
* [NEW] Experimental IPv6 support.
|
||||
* [NEW] Slaves explicitly ping masters now, a master is able to detect a timed out
|
||||
slave independently.
|
||||
* [NEW] Masters can stop accepting writes if not enough slaves with a given
|
||||
maximum latency are connected.
|
||||
* [NEW] Keyspace changes notifications via Pub/Sub.
|
||||
* [NEW] CONFIG SET maxclients is now available.
|
||||
* [NEW] Ability to bind multiple IP addresses.
|
||||
* [NEW] Set process names so that you can recognize, in the "ps" command output,
|
||||
the listening port of an instance, or if it is a saving child.
|
||||
* [NEW] Automatic memory check on crash.
|
||||
* [NEW] CONFIG REWRITE is able to materialize the changes in the configuration
|
||||
operated using CONFIG SET into the redis.conf file.
|
||||
* [NEW] More NetBSD friendly code base.
|
||||
* [NEW] PUBSUB command for Pub/Sub introspection capabilities.
|
||||
* [NEW] EVALSHA can now be replicated as such, without requiring to be expanded
|
||||
to a full EVAL for the replication link.
|
||||
* [NEW] Better Lua scripts error reporting.
|
||||
* [NEW] SDIFF performance improved.
|
||||
* [FIX] A number of bugfixes.
|
||||
|
||||
Migrating from 2.6 to 2.8
|
||||
=========================
|
||||
|
||||
Redis 2.4 is mostly a strict subset of 2.6. However there are a few things
|
||||
Redis 2.6 is mostly a strict subset of 2.8. However there are a few things
|
||||
that you should be aware of:
|
||||
|
||||
* You can't use .rdb and AOF files generated with 2.6 into a 2.4 instance.
|
||||
* 2.4 slaves can be attached to 2.6 masters, but not the contrary, and only
|
||||
for the time needed to perform the version upgrade.
|
||||
The following commands changed behavior:
|
||||
|
||||
There are also a few API differences, that are unlikely to cause problems,
|
||||
but it is better to keep them in mind:
|
||||
* The TTL and PTTL commands now return -2 if the key does not exist and
|
||||
-1 if it exists but has no associated expire. Redis 2.6 and previous
|
||||
versions used to return -1 for both the conditions.
|
||||
* SORT with ALPHA now sorts according to local collation locale if no STORE
|
||||
option is used.
|
||||
* ZADD/ZINCRBY are now able to accept a bigger range of values as valid
|
||||
scores, that is, all the values you may end having as a result of
|
||||
calling ZINCRBY multiple times.
|
||||
* Many errors are now prefixed by a more specific error code instead of
|
||||
the generic -ERR, for example -WRONGTYPE, -NOAUTH, ...
|
||||
* PUBLISH called inside Lua scripts is now correctly propagated to slaves.
|
||||
|
||||
* SORT now will refuse to sort in numerical mode elements that can't be parsed
|
||||
as numbers.
|
||||
* EXPIREs now all have millisecond resolution (but this is very unlikely to
|
||||
break code that was not conceived exploting the previous resolution error
|
||||
in some way.)
|
||||
* INFO output is a bit different now, and contains empty lines and comments
|
||||
starting with '#'. All the major clients should be already fixed to work
|
||||
with the new INFO format.
|
||||
The following redis.conf and CONFIG GET / SET parameters changed:
|
||||
|
||||
Also the following redis.conf and CONFIG GET / SET parameters changed name:
|
||||
* logfile now uses the empty string in order to log to standard output,
|
||||
so 'logfile stdout' is now invalid, use 'logfile ""' instead.
|
||||
|
||||
* hash-max-zipmap-entries, now replaced by hash-max-ziplist-entries
|
||||
* hash-max-zipmap-value, now replaced by hash-max-ziplist-value
|
||||
* glueoutputbuf was no completely removed as it does not make sense
|
||||
The following INFO fields changed format in a non-backward compatible way:
|
||||
|
||||
---------
|
||||
CHANGELOG
|
||||
---------
|
||||
* The list of slaves in INFO is now in field=value format.
|
||||
|
||||
What's new in Redis 2.6.0
|
||||
=========================
|
||||
Replication:
|
||||
|
||||
UPGRADE URGENCY: We suggest new users to start with 2.6.0, and old users to
|
||||
upgrade after some testing of the application with the new
|
||||
Redis version.
|
||||
|
||||
* Server side Lua scripting, see http://redis.io/commands/eval
|
||||
* Virtual Memory removed (was deprecated in 2.4)
|
||||
* Hardcoded limits about max number of clients removed.
|
||||
* AOF low level semantics is generally more sane, and especially when used
|
||||
in slaves.
|
||||
* Milliseconds resolution expires, also added new commands with milliseconds
|
||||
precision (PEXPIRE, PTTL, ...).
|
||||
* Clinets max output buffer soft and hard limits. You can specifiy different
|
||||
limits for different classes of clients (normal,pubsub,slave).
|
||||
* AOF is now able to rewrite aggregate data types using variadic commands,
|
||||
often producing an AOF that is faster to save, load, and is smaller in size.
|
||||
* Every redis.conf directive is now accepted as a command line option for the
|
||||
redis-server binary, with the same name and number of arguments.
|
||||
* Hash table seed randomization for protection against collisions attacks.
|
||||
* Performances improved when writing large objects to Redis.
|
||||
* Significant parts of the core refactored or rewritten. New internal APIs
|
||||
and core changes allowed to develop Redis Cluster on top of the new code,
|
||||
however for 2.6 all the cluster code was removed, and will be released with
|
||||
Redis 3.0 when it is more complete and stable.
|
||||
* Redis ASCII art logo added at startup.
|
||||
* Crash report on memory violation or failed asserts improved significantly
|
||||
to make debugging of hard to catch bugs simpler.
|
||||
* redis-benchmark improvements: ability to run selected tests,
|
||||
CSV output, faster, better help.
|
||||
* redis-cli improvements: --eval for comfortable development of Lua scripts.
|
||||
* SHUTDOWN now supports two optional arguments: "SAVE" and "NOSAVE".
|
||||
* INFO output split into sections, the command is now able to just show
|
||||
pecific sections.
|
||||
* New statistics about how many time a command was called, and how much
|
||||
execution time it used (INFO commandstats).
|
||||
* More predictable SORT behavior in edge cases.
|
||||
* INCRBYFLOAT and HINCRBYFLOAT commands.
|
||||
Redis 2.8 can be used as slave for Redis 2.6, but doing this is only
|
||||
a good idea for the short amount of time needed to upgrade your servers.
|
||||
We suggest to update both master and slaves at about the same time.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Credits: Where not specified the implementation and design are done by
|
||||
Salvatore Sanfilippo and Pieter Noordhuis. Thanks to VMware for making all
|
||||
Credits: Where not specified the implementation and design is done by
|
||||
Salvatore Sanfilippo. Thanks to VMware and Pivotal for making all
|
||||
this possible. Also many thanks to all the other contributors and the amazing
|
||||
community we have.
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
Plese check https://github.com/antirez/redis/issues
|
||||
Please check https://github.com/antirez/redis/issues
|
||||
|
||||
+24
-3
@@ -1,8 +1,29 @@
|
||||
1. Enter irc.freenode.org #redis and start talking with 'antirez' and/or 'pietern' to check if there is interest for such a feature and to understand the probability of it being merged. We'll try hard to keep Redis simple... so you'll likely encounter high resistance.
|
||||
Note: by contributing code to the Redis project in any form, including sending
|
||||
a pull request via Github, a code fragment or patch via private email or
|
||||
public discussion groups, you agree to release your code under the terms
|
||||
of the BSD license that you can find in the COPYING file included in the Redis
|
||||
source distribution. You will include BSD license in the COPYING file within
|
||||
each source file that you contribute.
|
||||
|
||||
2. Drop a message to the Redis Google Group with a proposal of semantics/API.
|
||||
# IMPORTANT: HOW TO USE REDIS GITHUB ISSUES
|
||||
|
||||
3. If steps 1 and 2 are ok, use the following procedure to submit a patch:
|
||||
* Github issues SHOULD ONLY BE USED to report bugs, and for DETAILED feature
|
||||
requests. Everything else belongs to the Redis Google Group.
|
||||
|
||||
PLEASE DO NOT POST GENERAL QUESTIONS that are not about bugs or suspected
|
||||
bugs in the Github issues system. We'll be very happy to help you and provide
|
||||
all the support in the Redis Google Group.
|
||||
|
||||
Redis Google Group address:
|
||||
|
||||
https://groups.google.com/forum/?fromgroups#!forum/redis-db
|
||||
|
||||
# How to provide a patch for a new feature
|
||||
|
||||
1. Drop a message to the Redis Google Group with a proposal of semantics/API.
|
||||
|
||||
2. If in step 1 you get an acknowledge from the project leaders, use the
|
||||
following procedure to submit a patch:
|
||||
|
||||
a. Fork Redis on github ( http://help.github.com/fork-a-repo/ )
|
||||
b. Create a topic branch (git checkout -b my_branch)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2006-2009, Salvatore Sanfilippo
|
||||
Copyright (c) 2006-2014, Salvatore Sanfilippo
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -4,17 +4,64 @@
|
||||
Redis Manifesto
|
||||
===============
|
||||
|
||||
1 - A DSL for Abstract Data Types. Redis is a DSL (Domain Specific Language) that manipulates abstract data types and implemented as a TCP daemon. Commands manipulate a key space where keys are binary-safe strings and values are different kinds of abstract data types. Every data type represents an abstract version of a fundamental data structure. For instance Redis Lists are an abstract representation of linked lists. In Redis, the essence of a data type isn't just the kind of operations that the data types support, but also the space and time complexity of the data type and the operations performed upon it.
|
||||
1 - A DSL for Abstract Data Types. Redis is a DSL (Domain Specific Language)
|
||||
that manipulates abstract data types and implemented as a TCP daemon.
|
||||
Commands manipulate a key space where keys are binary-safe strings and
|
||||
values are different kinds of abstract data types. Every data type
|
||||
represents an abstract version of a fundamental data structure. For instance
|
||||
Redis Lists are an abstract representation of linked lists. In Redis, the
|
||||
essence of a data type isn't just the kind of operations that the data types
|
||||
support, but also the space and time complexity of the data type and the
|
||||
operations performed upon it.
|
||||
|
||||
2 - Memory storage is #1. The Redis data set, composed of defined key-value pairs, is primarily stored in the computer's memory. The amount of memory in all kinds of computers, including entry-level servers, is increasing significantly each year. Memory is fast, and allows Redis to have very predictable performance. Datasets composed of 10k or 40 millions keys will perform similarly. Complex data types like Redis Sorted Sets are easy to implement and manipulate in memory with good performance, making Redis very simple. Redis will continue to explore alternative options (where data can be optionally stored on disk, say) but the main goal of the project remains the development of an in-memory database.
|
||||
2 - Memory storage is #1. The Redis data set, composed of defined key-value
|
||||
pairs, is primarily stored in the computer's memory. The amount of memory in
|
||||
all kinds of computers, including entry-level servers, is increasing
|
||||
significantly each year. Memory is fast, and allows Redis to have very
|
||||
predictable performance. Datasets composed of 10k or 40 millions keys will
|
||||
perform similarly. Complex data types like Redis Sorted Sets are easy to
|
||||
implement and manipulate in memory with good performance, making Redis very
|
||||
simple. Redis will continue to explore alternative options (where data can
|
||||
be optionally stored on disk, say) but the main goal of the project remains
|
||||
the development of an in-memory database.
|
||||
|
||||
3 - Fundamental data structures for a fundamental API. The Redis API is a direct consequence of fundamental data structures. APIs can often be arbitrary but not an API that resembles the nature of fundamental data structures. If we ever meet intelligent life forms from another part of the universe, they'll likely know, understand and recognize the same basic data structures we have in our computer science books. Redis will avoid intermediate layers in API, so that the complexity is obvious and more complex operations can be performed as the sum of the basic operations.
|
||||
3 - Fundamental data structures for a fundamental API. The Redis API is a direct
|
||||
consequence of fundamental data structures. APIs can often be arbitrary but
|
||||
not an API that resembles the nature of fundamental data structures. If we
|
||||
ever meet intelligent life forms from another part of the universe, they'll
|
||||
likely know, understand and recognize the same basic data structures we have
|
||||
in our computer science books. Redis will avoid intermediate layers in API,
|
||||
so that the complexity is obvious and more complex operations can be
|
||||
performed as the sum of the basic operations.
|
||||
|
||||
4 - Code is like a poem; it's not just something we write to reach some practical result. Sometimes people that are far from the Redis philosophy suggest using other code written by other authors (frequently in other languages) in order to implement something Redis currently lacks. But to us this is like if Shakespeare decided to end Enrico IV using the Paradiso from the Divina Commedia. Is using any external code a bad idea? Not at all. Like in "One Thousand and One Nights" smaller self contained stories are embedded in a bigger story, we'll be happy to use beautiful self contained libraries when needed. At the same time, when writing the Redis story we're trying to write smaller stories that will fit in to other code.
|
||||
4 - Code is like a poem; it's not just something we write to reach some
|
||||
practical result. Sometimes people that are far from the Redis philosophy
|
||||
suggest using other code written by other authors (frequently in other
|
||||
languages) in order to implement something Redis currently lacks. But to us
|
||||
this is like if Shakespeare decided to end Enrico IV using the Paradiso from
|
||||
the Divina Commedia. Is using any external code a bad idea? Not at all. Like
|
||||
in "One Thousand and One Nights" smaller self contained stories are embedded
|
||||
in a bigger story, we'll be happy to use beautiful self contained libraries
|
||||
when needed. At the same time, when writing the Redis story we're trying to
|
||||
write smaller stories that will fit in to other code.
|
||||
|
||||
5 - We're against complexity. We believe designing systems is a fight against complexity. We'll accept to fight the complexity when it's worthwhile but we'll try hard to recognize when a small feature is not worth 1000s of lines of code. Most of the time the best way to fight complexity is by not creating it at all.
|
||||
5 - We're against complexity. We believe designing systems is a fight against
|
||||
complexity. We'll accept to fight the complexity when it's worthwhile but
|
||||
we'll try hard to recognize when a small feature is not worth 1000s of lines
|
||||
of code. Most of the time the best way to fight complexity is by not
|
||||
creating it at all.
|
||||
|
||||
6 - Two levels of API. The Redis API has two levels: 1) a subset of the API fits naturally into a distributed version of Redis and 2) a more complex API that supports multi-key operations. Both are useful if used judiciously but there's no way to make the more complex multi-keys API distributed in an opaque way without violating our other principles. We don't want to provide the illusion of something that will work magically when actually it can't in all cases. Instead we'll provide commands to quickly migrate keys from one instance to another to perform multi-key operations and expose the tradeoffs to the user.
|
||||
|
||||
7 - We optimize for joy. We believe writing code is a lot of hard work, and the only way it can be worth is by enjoying it. When there is no longer joy in writing code, the best thing to do is stop. To prevent this, we'll avoid taking paths that will make Redis less of a joy to develop.
|
||||
6 - Two levels of API. The Redis API has two levels: 1) a subset of the API fits
|
||||
naturally into a distributed version of Redis and 2) a more complex API that
|
||||
supports multi-key operations. Both are useful if used judiciously but
|
||||
there's no way to make the more complex multi-keys API distributed in an
|
||||
opaque way without violating our other principles. We don't want to provide
|
||||
the illusion of something that will work magically when actually it can't in
|
||||
all cases. Instead we'll provide commands to quickly migrate keys from one
|
||||
instance to another to perform multi-key operations and expose the tradeoffs
|
||||
to the user.
|
||||
|
||||
7 - We optimize for joy. We believe writing code is a lot of hard work, and the
|
||||
only way it can be worth is by enjoying it. When there is no longer joy in
|
||||
writing code, the best thing to do is stop. To prevent this, we'll avoid
|
||||
taking paths that will make Redis less of a joy to develop.
|
||||
|
||||
@@ -5,3 +5,7 @@ default: all
|
||||
.DEFAULT:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
install:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
.PHONY: install
|
||||
|
||||
@@ -7,6 +7,13 @@ documentation at http://redis.io
|
||||
Building Redis
|
||||
--------------
|
||||
|
||||
Redis can be compiled and used on Linux, OSX, OpenBSD, NetBSD, FreeBSD.
|
||||
We support big endian and little endian architectures.
|
||||
|
||||
It may compile on Solaris derived systems (for instance SmartOS) but our
|
||||
support for this platform is "best effort" and Redis is not guaranteed to
|
||||
work as well as in Linux, OSX, and *BSD there.
|
||||
|
||||
It is as simple as:
|
||||
|
||||
% make
|
||||
@@ -19,9 +26,20 @@ After building Redis is a good idea to test it, using:
|
||||
|
||||
% make test
|
||||
|
||||
NOTE: if after building Redis with a 32 bit target you need to rebuild it
|
||||
with a 64 bit target you need to perform a "make clean" in the root
|
||||
directory of the Redis distribution.
|
||||
Fixing problems building 32 bit binaries
|
||||
---------
|
||||
|
||||
If after building Redis with a 32 bit target you need to rebuild it
|
||||
with a 64 bit target, or the other way around, you need to perform a
|
||||
"make distclean" in the root directory of the Redis distribution.
|
||||
|
||||
In case of build errors when trying to build a 32 bit binary of Redis, try
|
||||
the following steps:
|
||||
|
||||
* Install the packages libc6-dev-i386 (also try g++-multilib).
|
||||
* Try using the following command line instead of "make 32bit":
|
||||
|
||||
make CFLAGS="-m32 -march=native" LDFLAGS="-m32"
|
||||
|
||||
Allocator
|
||||
---------
|
||||
@@ -112,7 +130,7 @@ it the proper way for a production system, we have a script doing this
|
||||
for Ubuntu and Debian systems:
|
||||
|
||||
% cd utils
|
||||
% ./install_server
|
||||
% ./install_server.sh
|
||||
|
||||
The script will ask you a few questions and will setup everything you need
|
||||
to run Redis properly as a background daemon that will start again on
|
||||
@@ -121,4 +139,16 @@ system reboots.
|
||||
You'll be able to stop and start Redis using the script named
|
||||
/etc/init.d/redis_<portnumber>, for instance /etc/init.d/redis_6379.
|
||||
|
||||
Code contributions
|
||||
---
|
||||
|
||||
Note: by contributing code to the Redis project in any form, including sending
|
||||
a pull request via Github, a code fragment or patch via private email or
|
||||
public discussion groups, you agree to release your code under the terms
|
||||
of the BSD license that you can find in the COPYING file included in the Redis
|
||||
source distribution.
|
||||
|
||||
Please see the CONTRIBUTING file in this source distribution for more
|
||||
information.
|
||||
|
||||
Enjoy!
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
[](https://ci.appveyor.com/project/MSOpenTech-lab/redis)
|
||||
|
||||
[](http://www.nuget.org/packages/redis-64/)
|
||||
[](http://www.nuget.org/packages/redis-64/)
|
||||
|
||||
[](http://www.chocolatey.org/packages/redis-64/)
|
||||
[](http://www.chocolatey.org/packages/redis-64/)
|
||||
|
||||
Redis on Windows
|
||||
===
|
||||
|
||||
## Redis 2.8 Branch
|
||||
|
||||
- This is a port for Windows based on Redis 2.8.
|
||||
- There is support for the 64-bit version. We have dropped official support for the 32-bit version, though you can build it from source if desired.
|
||||
- You can download the latest binaries (unsigned) from [http://github.com/MSOpenTech/redis/releases](http://github.com/MSOpenTech/redis/releases "Release page"). For releases prior to 2.8.17.1, the binaries can found in a zip file inside the source archive, under the bin/release folder.
|
||||
- Signed binaries can be downloaded using Nuget and Chocolatey.
|
||||
- There is a replacement for the UNIX fork() API that simulates the copy-on-write behavior using a memory mapped file.
|
||||
- Because Redis makes some assumptions about the values of File Descriptors, we have built a virtual file descriptor mapping layer.
|
||||
- We are moving towards moving all Windows-specific changes into the Win32_Interop library.
|
||||
- Redis can be installed as a Windows Service.
|
||||
|
||||
## What's new since 2.8.12
|
||||
|
||||
- See the Redis release notes: http://download.redis.io/redis-stable/00-RELEASENOTES
|
||||
|
||||
## Important: More documentation is available
|
||||
|
||||
Please read the documentation in msvs\setups\documentation. This is the documentation that is bundled with the binaries, and contains vital information about configuring and deploying Redis on Windows.
|
||||
|
||||
## How to build Redis using Visual Studio
|
||||
|
||||
You can use the free Visual Studio Express 2013 for Windows Desktop edition available at http://www.microsoft.com/en-us/download/details.aspx?id=40787.
|
||||
|
||||
- Open the solution file msvs\redisserver.sln in Visual Studio 2013, select a build configuration (Debug or Release) and target (Win32 or x64) then build.
|
||||
|
||||
This should create the following executables in the msvs\$(Target)\$(Configuration) folder:
|
||||
|
||||
- redis-server.exe
|
||||
- redis-benchmark.exe
|
||||
- redis-cli.exe
|
||||
- redis-check-dump.exe
|
||||
- redis-check-aof.exe
|
||||
|
||||
## Unit Testing
|
||||
|
||||
To run the Redis test suite requires some manual work:
|
||||
|
||||
- The tests assume that the binaries are in the src folder. Use mklink to create a symbolic link to the files in the msvs\x64\Debug|Release folders. You will
|
||||
need symbolic links for src\redis-server, src\redis-benchmark, src\redis-check-aof, src\redis-check-dump, src\redis-cli, and src\redis-sentinel.
|
||||
- The tests make use of TCL. This must be installed separately.
|
||||
- To run the tests you need to have a Unix shell on your machine, or MinGW tools in your path. To execute the tests, run the following command:
|
||||
"tclsh8.5.exe tests/test_helper.tcl --clients N", where N is the number of parallel clients . If a Unix shell is not installed you may see the
|
||||
following error message: "couldn't execute "cat": no such file or directory".
|
||||
- By default the test suite launches 16 parallel tests. I will get time out errors on an iCore 7-2620m@2.7Ghz with some of the tests when the number of clients
|
||||
is greater than 6.
|
||||
|
||||
## Known issues
|
||||
|
||||
Problem:
|
||||
On versions of Windows prior to Windows 8/Server 2012, when an AOF or RDB operation is complete and the child process is being rejoined with the parent, it is
|
||||
possible for Redis to unexpectedly terminate.
|
||||
|
||||
Cause:
|
||||
The PAGE_REVERT_TO_FILE_MAP flag is not usable in VirtualProtect() in earlier versions of the OS. This flag allows for removing copy on write(COW) pages from
|
||||
a memory mapped view without unmapping the view. In prior versions of the OS, the only way to purge COW pages is to unmap and then remap the memory mapped view.
|
||||
Between the unmapping and remapping operations a third party process(e.g., an anti-virus program) could allocate virtual memory occupied by the memory mapped view.
|
||||
As this view is used for the Redis heap, failure to remap is a fatal error. (See RejoinCOWPages() in src\Win32_Interop\Win32_QFork.cpp)
|
||||
|
||||
Solution:
|
||||
If you encounter this problem, host Redis on Windows 8/Server 2012 or newer.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
MSOpenTech Redis 2.8.17 Release Notes
|
||||
=====================================
|
||||
|
||||
Welcome to the binary release of Redis from Microsoft Open Technologies, Inc.
|
||||
|
||||
What is Redis?
|
||||
--------------
|
||||
|
||||
Redis is an open source, high performance, key-value store. Values may contain strings, hashes, lists, sets and sorted sets. Redis has been developed primarily for UNIX-like operating systems.
|
||||
|
||||
Porting Goals
|
||||
-------------
|
||||
|
||||
Our goal is to provide a version of Redis that runs on Windows with a performance essentially equal to the performance of Redis on an equivalent UNIX machine.
|
||||
|
||||
What is new with the 2.8.17 release
|
||||
-----------------------------------
|
||||
|
||||
Our last official release was 2.8.12. We have merged in the changes up to 2.8.17. Please see the [release notes for the UNIX 2.8 branch](http://download.redis.io/redis-stable/00-RELEASENOTES) to understand how this impacts Redis functionality.
|
||||
|
||||
### Network layer changes
|
||||
|
||||
There have been significant changes to the networking layer for this version. Likely there will be a few weeks before there is another official (Chocolatey and Nuget) release. Most of these changes target IPv6.
|
||||
|
||||
### persistence-available flag
|
||||
|
||||
If Redis is to be used as an in-memory-only cache without any kind of persistence, then the fork() mechanism used by the background AOF/RDB persistence is unnecessary. As an optimization, all persistence can be turned off in the Windows version of Redis in this scenario. This will disable the creation of the memory mapped heap file, redirect heap allocations to the system heap allocator, and disable commands that would otherwise cause fork() operations: BGSAVE and BGREWRITEAOF. This flag may not be combined with any of the other flags that configure AOF and RDB operations.
|
||||
|
||||
persistence-available [(yes)|no]
|
||||
|
||||
How to develop for Redis
|
||||
------------------------
|
||||
|
||||
You will need a client library for accessing Redis. There are a wide variety of client libraries available as listed at <http://redis.io/clients>.
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
MSOpenTech’s Redis on Windows
|
||||
=============================
|
||||
|
||||
We strive to have a stable, functionally equivalent and comparably performing version of Redis on Windows. We have achieved performance nearly identical to the POSIX version running head-to-head on identical hardware across the network. Aside from feature differences that help Redis take advantage of the Windows infrastructure, our version of Redis should work in most situations with the identical setup and configuration that one would use on a POSIX operating system.
|
||||
|
||||
How is Redis on Windows implemented?
|
||||
====================================
|
||||
|
||||
Redis is a C code base that compiles under Visual Studio. Most of the code compiles with only minor changes to the code due to syntactical differences between compilers and low level API differences on Windows. There are a few areas where there are significant differences in how efficient Windows programs operate relative to POSIX programs. We have encapsulated most these differences in a platform specific library. The areas where there are significant differences are:
|
||||
|
||||
- Networking APIs
|
||||
|
||||
- POSIX File Descriptors
|
||||
|
||||
- POSIX fork()
|
||||
|
||||
- Logging
|
||||
|
||||
- Windows Services API
|
||||
|
||||
Networking Differences
|
||||
----------------------
|
||||
|
||||
The Windows networking stack is split between user mode code and kernel mode code. Transitions between user and kernel mode are expensive operations. The POSIX networking APIs on Windows utilize a programming model that incurs significant performance loss due to the kernel/user mode transitions. Efficient Windows networking code instead uses the IO Completion Port model to reduce the impact of this behavior. The APIs used and the programming model for IO Completion is different enough that we were forced to implement a new networking layer in in Redis.
|
||||
|
||||
File Descriptors
|
||||
----------------
|
||||
|
||||
In a POSIX operating system all data sources (files, pipes, sockets, mail slots, etc.) are referenced in code with a handle called a file descriptor. These are low value integers that increment by one with each successive file descriptor created in a given program. All POSIX APIs that work with file descriptors will function without the programmer having to know what kind of data source a file descriptor represents. On Windows generally each kind of data source has a separate kind of HANDLE. APIs that work with one HANDLE type will not work with another kind of HANDLE. In order to make Redis operate with its assumptions about file descriptor values and data source agnosticism, we implemented a Redis File Descriptor API layer.
|
||||
|
||||
fork()
|
||||
------
|
||||
|
||||
The POSIX version of Redis uses the fork() API. There is no equivalent in Windows, and it is an exceedingly difficult API to completely simulate. For most of the uses of fork() we have used Windows specific programming idioms to bypass the need to use a fork()-like API. The one case where we could not do so was with the point-in-time heap snapshot behavior that the Redis persistence model is based on. We tried several different approaches to work around the need for a fork()-like API, but always ran into significant performance penalties and stability issues.
|
||||
|
||||
Our current approach is to simulate the point-in-time snapshot behavior aspect of fork() without doing a complete simulation of fork(). We do this with a memory mapped file that contains the Redis heap. When a fork() operation is required we do the following:
|
||||
|
||||
- Mark every page in the memory mapped file with the Copy on Write page protection
|
||||
|
||||
- Start a child process and pass it the handle to the memory mapped file
|
||||
|
||||
- Signal the child to start the AOF or RDB persistence process on the memory shared via the memory mapped file
|
||||
|
||||
- Wait (asynchronously) for the child process to finish
|
||||
|
||||
- Map the changes in the Redis heap that occurred during the fork() operation back into the memory mapped file.
|
||||
|
||||
The upside with this implementation is that our performance and stability is now on par with the POSIX version of Redis. The down side is that we have a runtime disk space requirement for Redis equal to the size of the Redis memory mapped heap. The disk space requirement defaults to:
|
||||
|
||||
- The size specified by the –maxheap flag if present, otherwise
|
||||
|
||||
- 50% more than the --maxmemory setting if present, otherwise
|
||||
|
||||
- The size of physical RAM
|
||||
|
||||
We also have a runtime page file commit requirement that varies depending on the amount data in the Redis heap during the quasi-fork operation. The maximum for this is about 3 times the size of the memory mapped file. This is usually not a problem because the default configuration of Windows allows the page file to grow to 3.5 times the size of physical memory. There are scenarios where 3<sup>rd</sup> party programs also compete for system swap space at runtime.
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
In addition to file based logging, the POSIX version of Redis supports logging via the syslog facility. The equivalent in Windows is the Event Log. With the recent addition of the Windows Service code we have added support for logging to the Event Log. We have mapped the –syslogxxxx flags for this purpose.
|
||||
|
||||
Windows Service
|
||||
---------------
|
||||
|
||||
In version 2.8.9 we are adding support to make Redis operate as a service. See the RedisService.docx file included with the GitHub binary distribution for a description of the service commands available.
|
||||
|
||||
Redis on Windows Best Practices
|
||||
===============================
|
||||
|
||||
Binary Distributions
|
||||
--------------------
|
||||
|
||||
The GitHub repository should be considered a work in progress until we release the NuGet and Chocolatey packages and tag the repository at that released version.
|
||||
|
||||
For instance, the Windows Service feature has taken many iterations with community input to get right. The initial Windows service code was checked in on April 3. Since that time we have added the following to the service based on community input:
|
||||
|
||||
- Preshutdown notification in order to clean up the memory mapped file consistently.
|
||||
|
||||
- Code to identify and clean up orphaned memory mapped files left behind when a machine running Redis as a service crashes or loses power.
|
||||
|
||||
- Self elevation of the Redis executable so that service commands would work from a non-elevated command prompt.
|
||||
|
||||
- Service naming so that multiple instances of the Redis service could be installed on one machine.
|
||||
|
||||
- Automatically adjusting folder permissions so that when Redis is run under the NETWORK SERVICE account it could modify the files in the installation directory.
|
||||
|
||||
- Moved all of the pre-main() error reporting code (service and quasi-fork code) that could write errors to stdout to use the Redis logging code. This allows service initialization errors to reach the Event Log. This required intercepting all of the command line and conf file arguments before main() in order to properly initialize the logging engine. There were several fixes related to the intricacies of how to interpret the arguments passed to Redis.
|
||||
|
||||
The final service code has been released as of June 25 in the 2.8.9 Redis-64 packages.
|
||||
|
||||
Heap Sizing
|
||||
-----------
|
||||
|
||||
Native heaps are prone to fragmentation. If we are not able to allocate more heap space due to fragmentation Redis will flag the problem and exit. Unlike the POSIX version of Redis, our heap size is constrained by both by disk space and by swap file space. It is important to consider the how much data you are expecting to put into Redis, and how much fragmentation you are likely to see in the Redis heap. With very high levels of fragmentation the 50% overhead that –maxmemory imposes may not be enough to prevent running out of heap space. In this case, the use of –maxheap will supersede the –maxmemory default heap setting.
|
||||
|
||||
Installation and Maintenance
|
||||
----------------------------
|
||||
|
||||
Since Redis uses system swap space, the most stable configurations will only have Redis running on essentially a virgin operating system install.
|
||||
|
||||
Redis is xcopy deployable. There should be no problem upgrading versions by simply copying new binaries over old ones (assuming they are not currently in use).
|
||||
|
||||
Service Account
|
||||
---------------
|
||||
|
||||
When using Redis as a Windows service, the default installation configures Redis to run under the system’s NETWORK SERVICE account. There are some environments where another account must be used (perhaps a domain service account). Configuration of this account needs to be done manually at this point with the service control manager. If this is done, it is also important to give read/write/create permission to the folder that the Redis executable is in to this user identity.
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
Redis TODO
|
||||
----------
|
||||
|
||||
WARNING: are you a possible Redis contributor?
|
||||
Before implementing what is listed in this file
|
||||
please drop a message in the Redis google group or chat with
|
||||
antirez or pietern on irc.freenode.org #redis to check if the work
|
||||
is already in progress and if the feature is still interesting for
|
||||
us, and *how* exactly this can be implemented to have good changes
|
||||
of a merge. Otherwise it is probably wasted work! Thank you
|
||||
|
||||
|
||||
CLUSTER
|
||||
=======
|
||||
|
||||
* Implement rehashing and cluster check in redis-trib.
|
||||
* Reimplement MIGRATE / RESTORE to use just in memory buffers (no disk at
|
||||
all). This will require touching a lot of the RDB stuff around, but we may
|
||||
hand with faster persistence for RDB.
|
||||
* Implement the slave nodes semantics and election.
|
||||
* Allow redis-trib to create a cluster-wide snapshot (using SYNC).
|
||||
* Allow redis-trib to restore a cluster-wide snapshot (implement UPLOAD?).
|
||||
|
||||
SCRIPTING
|
||||
=========
|
||||
|
||||
* SCRIPT FLUSH or alike to start a fresh interpreter?
|
||||
|
||||
OPTIMIZATIONS
|
||||
=============
|
||||
|
||||
* SORT: Don't copy the list into a vector when BY argument is constant.
|
||||
* Write the hash table size of every db in the dump, so that Redis can resize the hash table just one time when loading a big DB.
|
||||
* Read-only mode for slaves.
|
||||
* Redis big lists as linked lists of small ziplists?
|
||||
Possibly a simple heuristic that join near nodes when some node gets smaller than the low_level, and split it into two if gets bigger than high_level.
|
||||
|
||||
KNOWN BUGS
|
||||
==========
|
||||
|
||||
* #519: Slave may have expired keys that were never read in the master (so a DEL
|
||||
is not sent in the replication channel) but are already expired since
|
||||
a lot of time. Maybe after a given delay that is undoubtably greater than
|
||||
the replication link latency we should expire this key on the slave on
|
||||
access?
|
||||
@@ -0,0 +1,74 @@
|
||||
Running Redis as a Service
|
||||
==========================
|
||||
|
||||
In order to better integrate with the Windows Services model, new command line arguments have been introduced to Redis. These service arguments require an elevated user context in order to connect to the service control manager. If these commands are invoked from a non-elevated context, Redis will attempt to create an elevated context in which to execute these commands. This will cause a User Account Control dialog to be displayed by Windows and may require Administrative user credentials in order to proceed.
|
||||
|
||||
Installing the Service
|
||||
----------------------
|
||||
|
||||
*--service-install*
|
||||
|
||||
This must be the first argument on the redis-server command line. Arguments after this are passed in the order they occur to Redis when the service is launched. The service will be configured as Autostart and will be launched as "NT AUTHORITY\\NetworkService". Upon successful installation a success message will be displayed and Redis will exit.
|
||||
|
||||
This command does not start the service.
|
||||
|
||||
For instance:
|
||||
|
||||
redis-server --service-install redis.windows.conf --loglevel verbose
|
||||
|
||||
Uninstalling the Service
|
||||
------------------------
|
||||
|
||||
*--service-uninstall*
|
||||
|
||||
This will remove the Redis service configuration information from the registry. Upon successful uninstallation a success message will be displayed and Redis will exit.
|
||||
|
||||
This does command not stop the service.
|
||||
|
||||
For instance:
|
||||
|
||||
redis-server --service-uninstall
|
||||
|
||||
Starting the Service
|
||||
--------------------
|
||||
|
||||
*--service-start*
|
||||
|
||||
This will start the Redis service. Upon successful start, a success message will be displayed and Redis will begin running.
|
||||
|
||||
For instance:
|
||||
|
||||
redis-server --service-start
|
||||
|
||||
Stopping the Service
|
||||
--------------------
|
||||
|
||||
*--service-stop*
|
||||
|
||||
This will stop the Redis service. Upon successful termination a success message will be displayed and Redis will exit.
|
||||
|
||||
For instance:
|
||||
|
||||
redis-server --service-stop
|
||||
|
||||
Naming the Service
|
||||
------------------
|
||||
|
||||
*--service-name **name***
|
||||
|
||||
This optional argument may be used with any of the preceding commands to set the name of the installed service. This argument should follow the service-install, service-start, service-stop or service-uninstall commands, and precede any arguments to be passed to Redis via the service-install command.
|
||||
|
||||
The following would install and start three separate instances of Redis as a service:
|
||||
|
||||
redis-server --service-install –service-name redisService1 –port 10001
|
||||
|
||||
redis-server --service-start –service-name redisService1
|
||||
|
||||
redis-server --service-install –service-name redisService2 –port 10002
|
||||
|
||||
redis-server --service-start –service-name redisService2
|
||||
|
||||
redis-server --service-install –service-name redisService3 –port 10003
|
||||
|
||||
redis-server --service-start –service-name redisService3
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
version: 2.8.13.{build}
|
||||
|
||||
branches:
|
||||
# whitelist
|
||||
only:
|
||||
- '2.8'
|
||||
- appveyor
|
||||
|
||||
install:
|
||||
- git submodule -q update --init
|
||||
|
||||
build:
|
||||
project: msvs\RedisServer.sln
|
||||
@@ -0,0 +1,2 @@
|
||||
release/
|
||||
debug/
|
||||
Vendored
+57
-33
@@ -1,17 +1,6 @@
|
||||
# Redis dependency Makefile
|
||||
|
||||
UNAME_S:=$(shell sh -c 'uname -s 2> /dev/null || echo not')
|
||||
|
||||
LUA_CFLAGS=-O2 -Wall $(ARCH)
|
||||
ifeq ($(UNAME_S),SunOS)
|
||||
# Make isinf() available
|
||||
LUA_CFLAGS+= -D__C99FEATURES__=1
|
||||
endif
|
||||
|
||||
JEMALLOC_CFLAGS=
|
||||
ifeq ($(ARCH),-m32)
|
||||
JEMALLOC_CFLAGS+=CFLAGS="-std=gnu99 -Wall -pipe -g3 -fvisibility=hidden -O3 -funroll-loops -m32"
|
||||
endif
|
||||
uname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
|
||||
CCCOLOR="\033[34m"
|
||||
LINKCOLOR="\033[34;1m"
|
||||
@@ -23,37 +12,72 @@ ENDCOLOR="\033[0m"
|
||||
default:
|
||||
@echo "Explicit target required"
|
||||
|
||||
# Clean everything when ARCH is different
|
||||
ifneq ($(shell sh -c '[ -f .make-arch ] && cat .make-arch'), $(ARCH))
|
||||
.make-arch: distclean
|
||||
else
|
||||
.make-arch:
|
||||
.PHONY: default
|
||||
|
||||
# Prerequisites target
|
||||
.make-prerequisites:
|
||||
@touch $@
|
||||
|
||||
# Clean everything when CFLAGS is different
|
||||
ifneq ($(shell sh -c '[ -f .make-cflags ] && cat .make-cflags || echo none'), $(CFLAGS))
|
||||
.make-cflags: distclean
|
||||
-(echo "$(CFLAGS)" > .make-cflags)
|
||||
.make-prerequisites: .make-cflags
|
||||
endif
|
||||
|
||||
.make-arch:
|
||||
-(echo $(ARCH) > .make-arch)
|
||||
# Clean everything when LDFLAGS is different
|
||||
ifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'), $(LDFLAGS))
|
||||
.make-ldflags: distclean
|
||||
-(echo "$(LDFLAGS)" > .make-ldflags)
|
||||
.make-prerequisites: .make-ldflags
|
||||
endif
|
||||
|
||||
distclean:
|
||||
-(cd hiredis && $(MAKE) clean) > /dev/null || true
|
||||
-(cd linenoise && $(MAKE) clean) > /dev/null || true
|
||||
-(cd lua && $(MAKE) clean) > /dev/null || true
|
||||
-(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true
|
||||
-(rm -f .make-arch)
|
||||
-(rm -f .make-*)
|
||||
|
||||
hiredis: .make-arch
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)hiredis$(ENDCOLOR)
|
||||
cd hiredis && $(MAKE) static ARCH="$(ARCH)"
|
||||
.PHONY: distclean
|
||||
|
||||
linenoise: .make-arch
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)linenoise$(ENDCOLOR)
|
||||
cd linenoise && $(MAKE) ARCH="$(ARCH)"
|
||||
hiredis: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd hiredis && $(MAKE) static
|
||||
|
||||
lua: .make-arch
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)lua$(ENDCOLOR)
|
||||
cd lua && $(MAKE) CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(ARCH)" ansi
|
||||
.PHONY: hiredis
|
||||
|
||||
jemalloc: .make-arch
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)jemalloc$(ENDCOLOR)
|
||||
cd jemalloc && ./configure $(JEMALLOC_CFLAGS) --with-jemalloc-prefix=je_ --enable-cc-silence && $(MAKE) lib/libjemalloc.a
|
||||
linenoise: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd linenoise && $(MAKE)
|
||||
|
||||
.PHONY: default conditional_clean hiredis linenoise lua jemalloc
|
||||
.PHONY: linenoise
|
||||
|
||||
ifeq ($(uname_S),SunOS)
|
||||
# Make isinf() available
|
||||
LUA_CFLAGS= -D__C99FEATURES__=1
|
||||
endif
|
||||
|
||||
LUA_CFLAGS+= -O2 -Wall -DLUA_ANSI -DENABLE_CJSON_GLOBAL $(CFLAGS)
|
||||
LUA_LDFLAGS+= $(LDFLAGS)
|
||||
# lua's Makefile defines AR="ar rcu", which is unusual, and makes it more
|
||||
# challenging to cross-compile lua (and redis). These defines make it easier
|
||||
# to fit redis into cross-compilation environments, which typically set AR.
|
||||
AR=ar
|
||||
ARFLAGS=rcu
|
||||
|
||||
lua: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd lua/src && $(MAKE) all CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(LUA_LDFLAGS)" AR="$(AR) $(ARFLAGS)"
|
||||
|
||||
.PHONY: lua
|
||||
|
||||
JEMALLOC_CFLAGS= -std=gnu99 -Wall -pipe -g3 -O3 -funroll-loops $(CFLAGS)
|
||||
JEMALLOC_LDFLAGS= $(LDFLAGS)
|
||||
|
||||
jemalloc: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd jemalloc && ./configure --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)"
|
||||
cd jemalloc && $(MAKE) CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)" lib/libjemalloc.a
|
||||
|
||||
.PHONY: jemalloc
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/hiredis-test
|
||||
/hiredis-example*
|
||||
/examples/hiredis-example*
|
||||
/*.o
|
||||
/*.so
|
||||
/*.dylib
|
||||
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
script: make && make check
|
||||
Vendored
+8
@@ -1,3 +1,11 @@
|
||||
### 0.11.0
|
||||
|
||||
* Increase the maximum multi-bulk reply depth to 7.
|
||||
|
||||
* Increase the read buffer size from 2k to 16k.
|
||||
|
||||
* Use poll(2) instead of select(2) to support large fds (>= 1024).
|
||||
|
||||
### 0.10.1
|
||||
|
||||
* Makefile overhaul. Important to check out if you override one or more
|
||||
|
||||
Vendored
+42
-24
@@ -4,11 +4,24 @@
|
||||
# This file is released under the BSD license, see the COPYING file
|
||||
|
||||
OBJ=net.o hiredis.o sds.o async.o
|
||||
BINS=hiredis-example hiredis-test
|
||||
EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev
|
||||
TESTS=hiredis-test
|
||||
LIBNAME=libhiredis
|
||||
|
||||
HIREDIS_MAJOR=0
|
||||
HIREDIS_MINOR=10
|
||||
HIREDIS_MINOR=11
|
||||
|
||||
# redis-server configuration used for testing
|
||||
REDIS_PORT=56379
|
||||
REDIS_SERVER=redis-server
|
||||
define REDIS_TEST_CONFIG
|
||||
daemonize yes
|
||||
pidfile /tmp/hiredis-test-redis.pid
|
||||
port $(REDIS_PORT)
|
||||
bind 127.0.0.1
|
||||
unixsocket /tmp/hiredis-test-redis.sock
|
||||
endef
|
||||
export REDIS_TEST_CONFIG
|
||||
|
||||
# Fallback to gcc when $CC is not in $PATH.
|
||||
CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
||||
@@ -41,12 +54,11 @@ ifeq ($(uname_S),Darwin)
|
||||
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
all: $(DYLIBNAME) $(BINS)
|
||||
all: $(DYLIBNAME)
|
||||
|
||||
# Deps (use make dep to generate this)
|
||||
net.o: net.c fmacros.h net.h hiredis.h
|
||||
async.o: async.c async.h hiredis.h sds.h dict.c dict.h
|
||||
example.o: example.c hiredis.h
|
||||
hiredis.o: hiredis.c fmacros.h hiredis.h net.h sds.h
|
||||
sds.o: sds.c sds.h
|
||||
test.o: test.c hiredis.h
|
||||
@@ -61,36 +73,44 @@ dynamic: $(DYLIBNAME)
|
||||
static: $(STLIBNAME)
|
||||
|
||||
# Binaries:
|
||||
hiredis-example-libevent: example-libevent.c adapters/libevent.h $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -levent example-libevent.c $(STLIBNAME)
|
||||
hiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME)
|
||||
|
||||
hiredis-example-libev: example-libev.c adapters/libev.h $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -lev example-libev.c $(STLIBNAME)
|
||||
hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)
|
||||
|
||||
ifndef AE_DIR
|
||||
hiredis-example-ae:
|
||||
@echo "Please specify AE_DIR (e.g. <redis repository>/src)"
|
||||
@false
|
||||
else
|
||||
hiredis-example-ae: example-ae.c adapters/ae.h $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I$(AE_DIR) $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o example-ae.c $(STLIBNAME)
|
||||
hiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME)
|
||||
endif
|
||||
|
||||
hiredis-%: %.o $(STLIBNAME)
|
||||
ifndef LIBUV_DIR
|
||||
hiredis-example-libuv:
|
||||
@echo "Please specify LIBUV_DIR (e.g. ../libuv/)"
|
||||
@false
|
||||
else
|
||||
hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME)
|
||||
endif
|
||||
|
||||
hiredis-example: examples/example.c $(STLIBNAME)
|
||||
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME)
|
||||
|
||||
examples: $(EXAMPLES)
|
||||
|
||||
hiredis-test: test.o $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
|
||||
|
||||
test: hiredis-test
|
||||
./hiredis-test
|
||||
|
||||
check: hiredis-test
|
||||
echo \
|
||||
"daemonize yes\n" \
|
||||
"pidfile /tmp/hiredis-test-redis.pid\n" \
|
||||
"port 56379\n" \
|
||||
"bind 127.0.0.1\n" \
|
||||
"unixsocket /tmp/hiredis-test-redis.sock" \
|
||||
| redis-server -
|
||||
./hiredis-test -h 127.0.0.1 -p 56379 -s /tmp/hiredis-test-redis.sock || \
|
||||
@echo "$$REDIS_TEST_CONFIG" | $(REDIS_SERVER) -
|
||||
./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \
|
||||
( kill `cat /tmp/hiredis-test-redis.pid` && false )
|
||||
kill `cat /tmp/hiredis-test-redis.pid`
|
||||
|
||||
@@ -98,17 +118,15 @@ check: hiredis-test
|
||||
$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
|
||||
|
||||
clean:
|
||||
rm -rf $(DYLIBNAME) $(STLIBNAME) $(BINS) hiredis-example* *.o *.gcda *.gcno *.gcov
|
||||
rm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) examples/hiredis-example* *.o *.gcda *.gcno *.gcov
|
||||
|
||||
dep:
|
||||
$(CC) -MM *.c
|
||||
|
||||
# Installation related variables and target
|
||||
PREFIX?=/usr/local
|
||||
INCLUDE_PATH?=include/hiredis
|
||||
LIBRARY_PATH?=lib
|
||||
INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH)
|
||||
INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH)
|
||||
INSTALL_INCLUDE_PATH= $(PREFIX)/include/hiredis
|
||||
INSTALL_LIBRARY_PATH= $(PREFIX)/lib
|
||||
|
||||
ifeq ($(uname_S),SunOS)
|
||||
INSTALL?= cp -r
|
||||
|
||||
Vendored
+35
-3
@@ -1,3 +1,5 @@
|
||||
[](https://travis-ci.org/redis/hiredis)
|
||||
|
||||
# HIREDIS
|
||||
|
||||
Hiredis is a minimalistic C client library for the [Redis](http://redis.io/) database.
|
||||
@@ -44,7 +46,7 @@ After trying to connect to Redis using `redisConnect` you should
|
||||
check the `err` field to see if establishing the connection was successful:
|
||||
|
||||
redisContext *c = redisConnect("127.0.0.1", 6379);
|
||||
if (c->err) {
|
||||
if (c != NULL && c->err) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
// handle error
|
||||
}
|
||||
@@ -66,14 +68,14 @@ When you need to pass binary safe strings in a command, the `%b` specifier can b
|
||||
used. Together with a pointer to the string, it requires a `size_t` length argument
|
||||
of the string:
|
||||
|
||||
reply = redisCommand(context, "SET foo %b", value, valuelen);
|
||||
reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen);
|
||||
|
||||
Internally, Hiredis splits the command in different arguments and will
|
||||
convert it to the protocol used to communicate with Redis.
|
||||
One or more spaces separates arguments, so you can use the specifiers
|
||||
anywhere in an argument:
|
||||
|
||||
reply = redisCommand("SET key:%s %s", myid, value);
|
||||
reply = redisCommand(context, "SET key:%s %s", myid, value);
|
||||
|
||||
### Using replies
|
||||
|
||||
@@ -320,6 +322,10 @@ The reply parsing API consists of the following functions:
|
||||
int redisReaderFeed(redisReader *reader, const char *buf, size_t len);
|
||||
int redisReaderGetReply(redisReader *reader, void **reply);
|
||||
|
||||
The same set of functions are used internally by hiredis when creating a
|
||||
normal Redis context, the above API just exposes it to the user for a direct
|
||||
usage.
|
||||
|
||||
### Usage
|
||||
|
||||
The function `redisReaderCreate` creates a `redisReader` structure that holds a
|
||||
@@ -333,6 +339,9 @@ and a reply object (as described above) via `void **reply`. The returned status
|
||||
can be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went
|
||||
wrong (either a protocol error, or an out of memory error).
|
||||
|
||||
The parser limits the level of nesting for multi bulk payloads to 7. If the
|
||||
multi bulk nesting level is higher than this, the parser returns an error.
|
||||
|
||||
### Customizing replies
|
||||
|
||||
The function `redisReaderGetReply` creates `redisReply` and makes the function
|
||||
@@ -346,6 +355,29 @@ immediately after creating the `redisReader`.
|
||||
For example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c)
|
||||
uses customized reply object functions to create Ruby objects.
|
||||
|
||||
### Reader max buffer
|
||||
|
||||
Both when using the Reader API directly or when using it indirectly via a
|
||||
normal Redis context, the redisReader structure uses a buffer in order to
|
||||
accumulate data from the server.
|
||||
Usually this buffer is destroyed when it is empty and is larger than 16
|
||||
kb in order to avoid wasting memory in unused buffers
|
||||
|
||||
However when working with very big payloads destroying the buffer may slow
|
||||
down performances considerably, so it is possible to modify the max size of
|
||||
an idle buffer changing the value of the `maxbuf` field of the reader structure
|
||||
to the desired value. The special value of 0 means that there is no maximum
|
||||
value for an idle buffer, so the buffer will never get freed.
|
||||
|
||||
For instance if you have a normal Redis context you can set the maximum idle
|
||||
buffer to zero (unlimited) just with:
|
||||
|
||||
context->reader->maxbuf = 0;
|
||||
|
||||
This should be done only in order to maximize performances when working with
|
||||
large payloads. The context should be set back to `REDIS_READER_MAX_BUF` again
|
||||
as soon as possible in order to prevent allocation of useless memory.
|
||||
|
||||
## AUTHORS
|
||||
|
||||
Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and
|
||||
|
||||
Vendored
+46
@@ -1,7 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __HIREDIS_AE_H__
|
||||
#define __HIREDIS_AE_H__
|
||||
#include <sys/types.h>
|
||||
#ifdef _WIN32
|
||||
#include "..\..\src\ae.h"
|
||||
#else
|
||||
#include <ae.h>
|
||||
#endif
|
||||
#include "../hiredis.h"
|
||||
#include "../async.h"
|
||||
|
||||
@@ -35,6 +69,15 @@ static void redisAeAddRead(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void redisAeForceAddRead(void *privdata) {
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
aeEventLoop *loop = e->loop;
|
||||
e->reading = 1;
|
||||
aeCreateFileEvent(loop, e->fd, AE_READABLE, redisAeReadEvent, e);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void redisAeDelRead(void *privdata) {
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
aeEventLoop *loop = e->loop;
|
||||
@@ -86,6 +129,9 @@ static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
|
||||
|
||||
/* Register functions to start/stop listening for events */
|
||||
ac->ev.addRead = redisAeAddRead;
|
||||
#ifdef _WIN32
|
||||
ac->ev.forceAddRead = redisAeForceAddRead;
|
||||
#endif
|
||||
ac->ev.delRead = redisAeDelRead;
|
||||
ac->ev.addWrite = redisAeAddWrite;
|
||||
ac->ev.delWrite = redisAeDelWrite;
|
||||
|
||||
Vendored
+30
@@ -1,3 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __HIREDIS_LIBEV_H__
|
||||
#define __HIREDIS_LIBEV_H__
|
||||
#include <stdlib.h>
|
||||
|
||||
Vendored
+30
@@ -1,3 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __HIREDIS_LIBEVENT_H__
|
||||
#define __HIREDIS_LIBEVENT_H__
|
||||
#include <event.h>
|
||||
|
||||
Vendored
+121
@@ -0,0 +1,121 @@
|
||||
#ifndef __HIREDIS_LIBUV_H__
|
||||
#define __HIREDIS_LIBUV_H__
|
||||
#include <uv.h>
|
||||
#include "../hiredis.h"
|
||||
#include "../async.h"
|
||||
#include <string.h>
|
||||
|
||||
typedef struct redisLibuvEvents {
|
||||
redisAsyncContext* context;
|
||||
uv_poll_t handle;
|
||||
int events;
|
||||
} redisLibuvEvents;
|
||||
|
||||
int redisLibuvAttach(redisAsyncContext*, uv_loop_t*);
|
||||
|
||||
static void redisLibuvPoll(uv_poll_t* handle, int status, int events) {
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
|
||||
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (events & UV_READABLE) {
|
||||
redisAsyncHandleRead(p->context);
|
||||
}
|
||||
if (events & UV_WRITABLE) {
|
||||
redisAsyncHandleWrite(p->context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void redisLibuvAddRead(void *privdata) {
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
||||
|
||||
p->events |= UV_READABLE;
|
||||
|
||||
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
||||
}
|
||||
|
||||
|
||||
static void redisLibuvDelRead(void *privdata) {
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
||||
|
||||
p->events &= ~UV_READABLE;
|
||||
|
||||
if (p->events) {
|
||||
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
||||
} else {
|
||||
uv_poll_stop(&p->handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void redisLibuvAddWrite(void *privdata) {
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
||||
|
||||
p->events |= UV_WRITABLE;
|
||||
|
||||
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
||||
}
|
||||
|
||||
|
||||
static void redisLibuvDelWrite(void *privdata) {
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
||||
|
||||
p->events &= ~UV_WRITABLE;
|
||||
|
||||
if (p->events) {
|
||||
uv_poll_start(&p->handle, p->events, redisLibuvPoll);
|
||||
} else {
|
||||
uv_poll_stop(&p->handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void on_close(uv_handle_t* handle) {
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
static void redisLibuvCleanup(void *privdata) {
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)privdata;
|
||||
|
||||
uv_close((uv_handle_t*)&p->handle, on_close);
|
||||
}
|
||||
|
||||
|
||||
static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
if (ac->ev.data != NULL) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
ac->ev.addRead = redisLibuvAddRead;
|
||||
ac->ev.delRead = redisLibuvDelRead;
|
||||
ac->ev.addWrite = redisLibuvAddWrite;
|
||||
ac->ev.delWrite = redisLibuvDelWrite;
|
||||
ac->ev.cleanup = redisLibuvCleanup;
|
||||
|
||||
redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));
|
||||
|
||||
if (!p) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
if (uv_poll_init(loop, &p->handle, c->fd) != 0) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
ac->ev.data = p;
|
||||
p->handle.data = p;
|
||||
p->context = ac;
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
Vendored
+171
-22
@@ -32,7 +32,9 @@
|
||||
#include "fmacros.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@@ -40,10 +42,18 @@
|
||||
#include "net.h"
|
||||
#include "dict.c"
|
||||
#include "sds.h"
|
||||
#ifdef _WIN32
|
||||
#include "../../src/win32_Interop/win32fixes.h"
|
||||
#endif
|
||||
|
||||
#define _EL_ADD_READ(ctx) do { \
|
||||
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#ifdef _WIN32
|
||||
#define _EL_FORCE_ADD_READ(ctx) do { \
|
||||
if ((ctx)->ev.forceAddRead) (ctx)->ev.forceAddRead((ctx)->ev.data); \
|
||||
} while (0)
|
||||
#endif
|
||||
#define _EL_DEL_READ(ctx) do { \
|
||||
if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \
|
||||
} while(0)
|
||||
@@ -57,27 +67,33 @@
|
||||
if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
|
||||
} while(0);
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strcasecmp _stricmp
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
/* Forward declaration of function in hiredis.c */
|
||||
void __redisAppendCommand(redisContext *c, char *cmd, size_t len);
|
||||
|
||||
/* Functions managing dictionary of callbacks for pub/sub. */
|
||||
static unsigned int callbackHash(const void *key) {
|
||||
return dictGenHashFunction((unsigned char*)key,sdslen((char*)key));
|
||||
return dictGenHashFunction((const unsigned char *)key,
|
||||
(int)sdslen((const sds)key));
|
||||
}
|
||||
|
||||
static void *callbackValDup(void *privdata, const void *src) {
|
||||
((void) privdata);
|
||||
redisCallback *dup = malloc(sizeof(*dup));
|
||||
((void) privdata);
|
||||
memcpy(dup,src,sizeof(*dup));
|
||||
return dup;
|
||||
}
|
||||
|
||||
static int callbackKeyCompare(void *privdata, const void *key1, const void *key2) {
|
||||
int l1, l2;
|
||||
size_t l1, l2;
|
||||
((void) privdata);
|
||||
|
||||
l1 = sdslen((sds)key1);
|
||||
l2 = sdslen((sds)key2);
|
||||
l1 = sdslen((const sds)key1);
|
||||
l2 = sdslen((const sds)key2);
|
||||
if (l1 != l2) return 0;
|
||||
return memcmp(key1,key2,l1) == 0;
|
||||
}
|
||||
@@ -102,7 +118,12 @@ static dictType callbackDict = {
|
||||
};
|
||||
|
||||
static redisAsyncContext *redisAsyncInitialize(redisContext *c) {
|
||||
redisAsyncContext *ac = realloc(c,sizeof(redisAsyncContext));
|
||||
redisAsyncContext *ac;
|
||||
|
||||
ac = realloc(c,sizeof(redisAsyncContext));
|
||||
if (ac == NULL)
|
||||
return NULL;
|
||||
|
||||
c = &(ac->c);
|
||||
|
||||
/* The regular connect functions will always set the flag REDIS_CONNECTED.
|
||||
@@ -116,6 +137,9 @@ static redisAsyncContext *redisAsyncInitialize(redisContext *c) {
|
||||
|
||||
ac->ev.data = NULL;
|
||||
ac->ev.addRead = NULL;
|
||||
#ifdef _WIN32
|
||||
ac->ev.forceAddRead = NULL;
|
||||
#endif
|
||||
ac->ev.delRead = NULL;
|
||||
ac->ev.addWrite = NULL;
|
||||
ac->ev.delWrite = NULL;
|
||||
@@ -141,16 +165,72 @@ static void __redisAsyncCopyError(redisAsyncContext *ac) {
|
||||
ac->errstr = c->errstr;
|
||||
}
|
||||
|
||||
#ifdef WIN32_IOCP
|
||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
|
||||
redisContext *c = redisConnectNonBlock(ip,port);
|
||||
SOCKADDR_STORAGE ss;
|
||||
redisContext *c = redisPreConnectNonBlock(ip, port, &ss);
|
||||
redisAsyncContext *ac = redisAsyncInitialize(c);
|
||||
if (aeWinSocketConnect(ac->c.fd, &ss) != 0) {
|
||||
ac->c.err = errno;
|
||||
strerror_r(errno, ac->c.errstr, sizeof(ac->c.errstr));
|
||||
}
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
}
|
||||
|
||||
redisAsyncContext *redisAsyncConnectUnix(const char *path) {
|
||||
redisContext *c = redisConnectUnixNonBlock(path);
|
||||
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr) {
|
||||
SOCKADDR_STORAGE ss;
|
||||
redisContext *c = redisPreConnectNonBlock(ip, port, &ss);
|
||||
redisAsyncContext *ac = redisAsyncInitialize(c);
|
||||
if (aeWinSocketConnectBind(ac->c.fd, &ss, source_addr) != 0) {
|
||||
ac->c.err = errno;
|
||||
strerror_r(errno, ac->c.errstr, sizeof(ac->c.errstr));
|
||||
}
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
}
|
||||
#else
|
||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
|
||||
redisContext *c;
|
||||
redisAsyncContext *ac;
|
||||
|
||||
c = redisConnectNonBlock(ip,port);
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
ac = redisAsyncInitialize(c);
|
||||
if (ac == NULL) {
|
||||
redisFree(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
}
|
||||
|
||||
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port,
|
||||
const char *source_addr) {
|
||||
redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);
|
||||
redisAsyncContext *ac = redisAsyncInitialize(c);
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
}
|
||||
#endif
|
||||
|
||||
redisAsyncContext *redisAsyncConnectUnix(const char *path) {
|
||||
redisContext *c;
|
||||
redisAsyncContext *ac;
|
||||
|
||||
c = redisConnectUnixNonBlock(path);
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
ac = redisAsyncInitialize(c);
|
||||
if (ac == NULL) {
|
||||
redisFree(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__redisAsyncCopyError(ac);
|
||||
return ac;
|
||||
}
|
||||
@@ -182,6 +262,9 @@ static int __redisPushCallback(redisCallbackList *list, redisCallback *source) {
|
||||
|
||||
/* Copy callback from stack to heap */
|
||||
cb = malloc(sizeof(*cb));
|
||||
if (cb == NULL)
|
||||
return REDIS_ERR_OOM;
|
||||
|
||||
if (source != NULL) {
|
||||
memcpy(cb,source,sizeof(*cb));
|
||||
cb->next = NULL;
|
||||
@@ -360,7 +443,7 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,
|
||||
|
||||
void redisProcessCallbacks(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
redisCallback cb;
|
||||
redisCallback cb = {NULL, NULL, NULL};
|
||||
void *reply = NULL;
|
||||
int status;
|
||||
|
||||
@@ -373,6 +456,11 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If monitor mode, repush callback */
|
||||
if(c->flags & REDIS_MONITORING) {
|
||||
__redisPushCallback(&ac->replies,&cb);
|
||||
}
|
||||
|
||||
/* When the connection is not being disconnected, simply stop
|
||||
* trying to get replies and wait for the next loop tick. */
|
||||
break;
|
||||
@@ -381,22 +469,31 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
||||
/* Even if the context is subscribed, pending regular callbacks will
|
||||
* get a reply before pub/sub messages arrive. */
|
||||
if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {
|
||||
/* A spontaneous reply in a not-subscribed context can only be the
|
||||
* error reply that is sent when a new connection exceeds the
|
||||
* maximum number of allowed connections on the server side. This
|
||||
* is seen as an error instead of a regular reply because the
|
||||
* server closes the connection after sending it. To prevent the
|
||||
* error from being overwritten by an EOF error the connection is
|
||||
* closed here. See issue #43. */
|
||||
if ( !(c->flags & REDIS_SUBSCRIBED) && ((redisReply*)reply)->type == REDIS_REPLY_ERROR ) {
|
||||
/*
|
||||
* A spontaneous reply in a not-subscribed context can be the error
|
||||
* reply that is sent when a new connection exceeds the maximum
|
||||
* number of allowed connections on the server side.
|
||||
*
|
||||
* This is seen as an error instead of a regular reply because the
|
||||
* server closes the connection after sending it.
|
||||
*
|
||||
* To prevent the error from being overwritten by an EOF error the
|
||||
* connection is closed here. See issue #43.
|
||||
*
|
||||
* Another possibility is that the server is loading its dataset.
|
||||
* In this case we also want to close the connection, and have the
|
||||
* user wait until the server is ready to take our request.
|
||||
*/
|
||||
if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {
|
||||
c->err = REDIS_ERR_OTHER;
|
||||
snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
|
||||
__redisAsyncDisconnect(ac);
|
||||
return;
|
||||
}
|
||||
/* No more regular callbacks and no errors, the context *must* be subscribed. */
|
||||
assert(c->flags & REDIS_SUBSCRIBED);
|
||||
__redisGetSubscribeCallback(ac,reply,&cb);
|
||||
/* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */
|
||||
assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING));
|
||||
if(c->flags & REDIS_SUBSCRIBED)
|
||||
__redisGetSubscribeCallback(ac,reply,&cb);
|
||||
}
|
||||
|
||||
if (cb.fn != NULL) {
|
||||
@@ -428,7 +525,7 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
||||
static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
if (redisCheckSocketError(c,c->fd) == REDIS_ERR) {
|
||||
if (redisCheckSocketError(c) == REDIS_ERR) {
|
||||
/* Try again later when connect(2) is still in progress. */
|
||||
if (errno == EINPROGRESS)
|
||||
return REDIS_OK;
|
||||
@@ -463,7 +560,15 @@ void redisAsyncHandleRead(redisAsyncContext *ac) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
/* Always re-schedule reads */
|
||||
#ifdef _WIN32
|
||||
// There appears to be a bug in the Linux version of _EL_ADD_READ which will not reschedule
|
||||
// the read if already reading. This is a problem if there is a large number of async GET
|
||||
// operations. If the receive buffer is exhausted with the data returned, the read would
|
||||
// not be rescheduled, and the async operations would cease. This forces the read to recur.
|
||||
_EL_FORCE_ADD_READ(ac);
|
||||
#else
|
||||
_EL_ADD_READ(ac);
|
||||
#endif
|
||||
redisProcessCallbacks(ac);
|
||||
}
|
||||
}
|
||||
@@ -495,6 +600,46 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* The redisAsyncHandleWrite is split into a Prep and Complete routines
|
||||
To allow using a write routine suitable for async behavior.
|
||||
For Windows this will use IOCP on write. */
|
||||
int redisAsyncHandleWritePrep(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
if (!(c->flags & REDIS_CONNECTED)) {
|
||||
/* Abort connect was not successful. */
|
||||
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
/* Try again later when the context is still not connected. */
|
||||
if (!(c->flags & REDIS_CONNECTED))
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisAsyncHandleWriteComplete(redisAsyncContext *ac, int written) {
|
||||
redisContext *c = &(ac->c);
|
||||
int done = 0;
|
||||
int rc;
|
||||
|
||||
rc = redisBufferWriteDone(c, written, &done);
|
||||
if (rc == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
/* Continue writing when not done, stop writing otherwise */
|
||||
if (!done)
|
||||
_EL_ADD_WRITE(ac);
|
||||
else
|
||||
_EL_DEL_WRITE(ac);
|
||||
|
||||
/* Always schedule reads after writes */
|
||||
_EL_ADD_READ(ac);
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sets a pointer to the first argument and its length starting at p. Returns
|
||||
* the number of bytes to skip to get to the following argument. */
|
||||
static char *nextArgument(char *start, char **str, size_t *len) {
|
||||
@@ -557,6 +702,10 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
|
||||
/* (P)UNSUBSCRIBE does not have its own response: every channel or
|
||||
* pattern that is unsubscribed will receive a message. This means we
|
||||
* should not append a callback function for this command. */
|
||||
} else if(strncasecmp(cstr,"monitor\r\n",9) == 0) {
|
||||
/* Set monitor flag and push callback */
|
||||
c->flags |= REDIS_MONITORING;
|
||||
__redisPushCallback(&ac->replies,&cb);
|
||||
} else {
|
||||
if (c->flags & REDIS_SUBSCRIBED)
|
||||
/* This will likely result in an error reply, but it needs to be
|
||||
|
||||
Vendored
+8
@@ -76,6 +76,9 @@ typedef struct redisAsyncContext {
|
||||
/* Hooks that are called when the library expects to start
|
||||
* reading/writing. These functions should be idempotent. */
|
||||
void (*addRead)(void *privdata);
|
||||
#ifdef _WIN32
|
||||
void (*forceAddRead)(void *privdata);
|
||||
#endif
|
||||
void (*delRead)(void *privdata);
|
||||
void (*addWrite)(void *privdata);
|
||||
void (*delWrite)(void *privdata);
|
||||
@@ -102,6 +105,7 @@ typedef struct redisAsyncContext {
|
||||
|
||||
/* Functions that proxy to hiredis */
|
||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port);
|
||||
redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);
|
||||
redisAsyncContext *redisAsyncConnectUnix(const char *path);
|
||||
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
|
||||
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
|
||||
@@ -111,6 +115,10 @@ void redisAsyncFree(redisAsyncContext *ac);
|
||||
/* Handle read/write events */
|
||||
void redisAsyncHandleRead(redisAsyncContext *ac);
|
||||
void redisAsyncHandleWrite(redisAsyncContext *ac);
|
||||
#ifdef _WIN32
|
||||
int redisAsyncHandleWritePrep(redisAsyncContext *ac);
|
||||
int redisAsyncHandleWriteComplete(redisAsyncContext *ac, int written);
|
||||
#endif
|
||||
|
||||
/* Command functions for an async context. Write the command to the
|
||||
* output buffer and register the provided callback. */
|
||||
|
||||
Vendored
+65
@@ -42,7 +42,11 @@
|
||||
/* -------------------------- private prototypes ---------------------------- */
|
||||
|
||||
static int _dictExpandIfNeeded(dict *ht);
|
||||
#ifdef _WIN32
|
||||
static size_t _dictNextPower(size_t size);
|
||||
#else
|
||||
static unsigned long _dictNextPower(unsigned long size);
|
||||
#endif
|
||||
static int _dictKeyIndex(dict *ht, const void *key);
|
||||
static int _dictInit(dict *ht, dictType *type, void *privDataPtr);
|
||||
|
||||
@@ -85,6 +89,53 @@ static int _dictInit(dict *ht, dictType *type, void *privDataPtr) {
|
||||
}
|
||||
|
||||
/* Expand or create the hashtable */
|
||||
#ifdef _WIN32
|
||||
static int dictExpand(dict *ht, size_t size) {
|
||||
dict n; /* the new hashtable */
|
||||
size_t realsize = _dictNextPower(size), i;
|
||||
|
||||
/* the size is invalid if it is smaller than the number of
|
||||
* elements already inside the hashtable */
|
||||
if (ht->used > size)
|
||||
return DICT_ERR;
|
||||
|
||||
_dictInit(&n, ht->type, ht->privdata);
|
||||
n.size = realsize;
|
||||
n.sizemask = realsize-1;
|
||||
n.table = calloc(realsize,sizeof(dictEntry*));
|
||||
|
||||
/* Copy all the elements from the old to the new table:
|
||||
* note that if the old hash table is empty ht->size is zero,
|
||||
* so dictExpand just creates an hash table. */
|
||||
n.used = ht->used;
|
||||
for (i = 0; i < ht->size && ht->used > 0; i++) {
|
||||
dictEntry *he, *nextHe;
|
||||
|
||||
if (ht->table[i] == NULL) continue;
|
||||
|
||||
/* For each hash entry on this slot... */
|
||||
he = ht->table[i];
|
||||
while(he) {
|
||||
unsigned int h;
|
||||
|
||||
nextHe = he->next;
|
||||
/* Get the new element index */
|
||||
h = dictHashKey(ht, he->key) & n.sizemask;
|
||||
he->next = n.table[h];
|
||||
n.table[h] = he;
|
||||
ht->used--;
|
||||
/* Pass to the next element */
|
||||
he = nextHe;
|
||||
}
|
||||
}
|
||||
assert(ht->used == 0);
|
||||
free(ht->table);
|
||||
|
||||
/* Remap the new hashtable in the old */
|
||||
*ht = n;
|
||||
return DICT_OK;
|
||||
}
|
||||
#else
|
||||
static int dictExpand(dict *ht, unsigned long size) {
|
||||
dict n; /* the new hashtable */
|
||||
unsigned long realsize = _dictNextPower(size), i;
|
||||
@@ -130,6 +181,7 @@ static int dictExpand(dict *ht, unsigned long size) {
|
||||
*ht = n;
|
||||
return DICT_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add an element to the target hash table */
|
||||
static int dictAdd(dict *ht, void *key, void *val) {
|
||||
@@ -303,6 +355,18 @@ static int _dictExpandIfNeeded(dict *ht) {
|
||||
}
|
||||
|
||||
/* Our hash table capability is a power of two */
|
||||
#ifdef _WIN32
|
||||
static size_t _dictNextPower(size_t size) {
|
||||
size_t i = DICT_HT_INITIAL_SIZE;
|
||||
|
||||
if (size >= LONG_MAX) return LONG_MAX;
|
||||
while(1) {
|
||||
if (i >= size)
|
||||
return i;
|
||||
i *= 2;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static unsigned long _dictNextPower(unsigned long size) {
|
||||
unsigned long i = DICT_HT_INITIAL_SIZE;
|
||||
|
||||
@@ -313,6 +377,7 @@ static unsigned long _dictNextPower(unsigned long size) {
|
||||
i *= 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns the index of a free slot that can be populated with
|
||||
* an hash entry for the given 'key'.
|
||||
|
||||
Vendored
+10
@@ -60,9 +60,15 @@ typedef struct dictType {
|
||||
typedef struct dict {
|
||||
dictEntry **table;
|
||||
dictType *type;
|
||||
#ifdef _WIN32
|
||||
size_t size;
|
||||
size_t sizemask;
|
||||
size_t used;
|
||||
#else
|
||||
unsigned long size;
|
||||
unsigned long sizemask;
|
||||
unsigned long used;
|
||||
#endif
|
||||
void *privdata;
|
||||
} dict;
|
||||
|
||||
@@ -113,7 +119,11 @@ typedef struct dictIterator {
|
||||
/* API */
|
||||
static unsigned int dictGenHashFunction(const unsigned char *buf, int len);
|
||||
static dict *dictCreate(dictType *type, void *privDataPtr);
|
||||
#ifdef _WIN32
|
||||
static int dictExpand(dict *ht, size_t size);
|
||||
#else
|
||||
static int dictExpand(dict *ht, unsigned long size);
|
||||
#endif
|
||||
static int dictAdd(dict *ht, void *key, void *val);
|
||||
static int dictReplace(dict *ht, void *key, void *val);
|
||||
static int dictDelete(dict *ht, const void *key);
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#ifdef _WIN32
|
||||
#include "..\..\src\Win32_Interop\win32fixes.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include "hiredis.h"
|
||||
#include "async.h"
|
||||
#include "adapters/ae.h"
|
||||
|
||||
#include <hiredis.h>
|
||||
#include <async.h>
|
||||
#include <adapters\ae.h>
|
||||
|
||||
/* Put event loop in the global scope, so it can be explicitly stopped */
|
||||
static aeEventLoop *loop;
|
||||
@@ -21,21 +26,32 @@ void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
void connectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
aeStop(loop);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Connected...\n");
|
||||
}
|
||||
|
||||
void disconnectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
aeStop(loop);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Disconnected...\n");
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#ifndef _WIN32
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* For Win32_IOCP the event loop must be created before the async connect */
|
||||
loop = aeCreateEventLoop(1024 * 10);
|
||||
#endif
|
||||
|
||||
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
|
||||
if (c->err) {
|
||||
@@ -44,7 +60,9 @@ int main (int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
loop = aeCreateEventLoop();
|
||||
#ifndef _WIN32
|
||||
loop = aeCreateEventLoop(64);
|
||||
#endif
|
||||
redisAeAttach(loop, c);
|
||||
redisAsyncSetConnectCallback(c,connectCallback);
|
||||
redisAsyncSetDisconnectCallback(c,disconnectCallback);
|
||||
@@ -2,9 +2,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include "hiredis.h"
|
||||
#include "async.h"
|
||||
#include "adapters/libev.h"
|
||||
|
||||
#include <hiredis.h>
|
||||
#include <async.h>
|
||||
#include <adapters/libev.h>
|
||||
|
||||
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisReply *reply = r;
|
||||
@@ -2,9 +2,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include "hiredis.h"
|
||||
#include "async.h"
|
||||
#include "adapters/libevent.h"
|
||||
|
||||
#include <hiredis.h>
|
||||
#include <async.h>
|
||||
#include <adapters/libevent.h>
|
||||
|
||||
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisReply *reply = r;
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <hiredis.h>
|
||||
#include <async.h>
|
||||
#include <adapters/libuv.h>
|
||||
|
||||
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisReply *reply = r;
|
||||
if (reply == NULL) return;
|
||||
printf("argv[%s]: %s\n", (char*)privdata, reply->str);
|
||||
|
||||
/* Disconnect after receiving the reply to GET */
|
||||
redisAsyncDisconnect(c);
|
||||
}
|
||||
|
||||
void connectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Connected...\n");
|
||||
}
|
||||
|
||||
void disconnectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Disconnected...\n");
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
|
||||
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
|
||||
if (c->err) {
|
||||
/* Let *c leak for now... */
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
redisLibuvAttach(c,loop);
|
||||
redisAsyncSetConnectCallback(c,connectCallback);
|
||||
redisAsyncSetDisconnectCallback(c,disconnectCallback);
|
||||
redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1]));
|
||||
redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
return 0;
|
||||
}
|
||||
+16
-6
@@ -2,17 +2,24 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hiredis.h"
|
||||
#include <hiredis.h>
|
||||
|
||||
int main(void) {
|
||||
int main(int argc, char **argv) {
|
||||
unsigned int j;
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1";
|
||||
int port = (argc > 2) ? atoi(argv[2]) : 6379;
|
||||
|
||||
struct timeval timeout = { 1, 500000 }; // 1.5 seconds
|
||||
c = redisConnectWithTimeout((char*)"127.0.0.2", 6379, timeout);
|
||||
if (c->err) {
|
||||
printf("Connection error: %s\n", c->errstr);
|
||||
c = redisConnectWithTimeout(hostname, port, timeout);
|
||||
if (c == NULL || c->err) {
|
||||
if (c) {
|
||||
printf("Connection error: %s\n", c->errstr);
|
||||
redisFree(c);
|
||||
} else {
|
||||
printf("Connection error: can't allocate redis context\n");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -27,7 +34,7 @@ int main(void) {
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Set a key using binary safe API */
|
||||
reply = redisCommand(c,"SET %b %b", "bar", 3, "hello", 5);
|
||||
reply = redisCommand(c,"SET %b %b", "bar", (size_t) 3, "hello", (size_t) 5);
|
||||
printf("SET (binary API): %s\n", reply->str);
|
||||
freeReplyObject(reply);
|
||||
|
||||
@@ -64,5 +71,8 @@ int main(void) {
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Disconnects and frees the context */
|
||||
redisFree(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Vendored
+9
-1
@@ -5,12 +5,20 @@
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(_AIX)
|
||||
#define _ALL_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(__sun__)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#elif defined(__linux__)
|
||||
#elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
#if __APPLE__ && __MACH__
|
||||
#define _OSX
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+184
-36
@@ -32,7 +32,9 @@
|
||||
#include "fmacros.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
@@ -40,6 +42,9 @@
|
||||
#include "hiredis.h"
|
||||
#include "net.h"
|
||||
#include "sds.h"
|
||||
#ifdef _WIN32
|
||||
#include "../../src/win32_Interop/win32fixes.h"
|
||||
#endif
|
||||
|
||||
static redisReply *createReplyObject(int type);
|
||||
static void *createStringObject(const redisReadTask *task, char *str, size_t len);
|
||||
@@ -116,7 +121,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
|
||||
memcpy(buf,str,len);
|
||||
buf[len] = '\0';
|
||||
r->str = buf;
|
||||
r->len = len;
|
||||
r->len = (int)len;
|
||||
|
||||
if (task->parent) {
|
||||
parent = task->parent->obj;
|
||||
@@ -259,7 +264,7 @@ static char *readBytes(redisReader *r, unsigned int bytes) {
|
||||
/* Find pointer to \r\n. */
|
||||
static char *seekNewline(char *s, size_t len) {
|
||||
int pos = 0;
|
||||
int _len = len-1;
|
||||
int _len = (int)(len-1);
|
||||
|
||||
/* Position should be < len-1 because the character at "pos" should be
|
||||
* followed by a \n. Note that strchr cannot be used because it doesn't
|
||||
@@ -319,7 +324,7 @@ static char *readLine(redisReader *r, int *_len) {
|
||||
p = r->buf+r->pos;
|
||||
s = seekNewline(p,(r->len-r->pos));
|
||||
if (s != NULL) {
|
||||
len = s-(r->buf+r->pos);
|
||||
len = (int)(s-(r->buf+r->pos));
|
||||
r->pos += len+2; /* skip \r\n */
|
||||
if (_len) *_len = len;
|
||||
return p;
|
||||
@@ -390,7 +395,11 @@ static int processBulkItem(redisReader *r) {
|
||||
redisReadTask *cur = &(r->rstack[r->ridx]);
|
||||
void *obj = NULL;
|
||||
char *p, *s;
|
||||
#ifdef _WIN32
|
||||
long long len;
|
||||
#else
|
||||
long len;
|
||||
#endif
|
||||
unsigned long bytelen;
|
||||
int success = 0;
|
||||
|
||||
@@ -398,7 +407,7 @@ static int processBulkItem(redisReader *r) {
|
||||
s = seekNewline(p,r->len-r->pos);
|
||||
if (s != NULL) {
|
||||
p = r->buf+r->pos;
|
||||
bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
|
||||
bytelen = (int)(s-(r->buf+r->pos)+2); /* include \r\n */
|
||||
len = readLongLong(p);
|
||||
|
||||
if (len < 0) {
|
||||
@@ -410,10 +419,10 @@ static int processBulkItem(redisReader *r) {
|
||||
success = 1;
|
||||
} else {
|
||||
/* Only continue when the buffer contains the entire bulk item. */
|
||||
bytelen += len+2; /* include \r\n */
|
||||
bytelen += (unsigned long)len+2; /* include \r\n */
|
||||
if (r->pos+bytelen <= r->len) {
|
||||
if (r->fn && r->fn->createString)
|
||||
obj = r->fn->createString(cur,s+2,len);
|
||||
obj = r->fn->createString(cur,s+2,(size_t)len);
|
||||
else
|
||||
obj = (void*)REDIS_REPLY_STRING;
|
||||
success = 1;
|
||||
@@ -443,10 +452,14 @@ static int processMultiBulkItem(redisReader *r) {
|
||||
redisReadTask *cur = &(r->rstack[r->ridx]);
|
||||
void *obj;
|
||||
char *p;
|
||||
#ifdef _WIN32
|
||||
long long elements;
|
||||
#else
|
||||
long elements;
|
||||
#endif
|
||||
int root = 0;
|
||||
|
||||
/* Set error for nested multi bulks with depth > 2 */
|
||||
/* Set error for nested multi bulks with depth > 7 */
|
||||
if (r->ridx == 8) {
|
||||
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
|
||||
"No support for nested multi bulk replies with depth > 7");
|
||||
@@ -471,7 +484,7 @@ static int processMultiBulkItem(redisReader *r) {
|
||||
moveToNextTask(r);
|
||||
} else {
|
||||
if (r->fn && r->fn->createArray)
|
||||
obj = r->fn->createArray(cur,elements);
|
||||
obj = r->fn->createArray(cur,(int)elements);
|
||||
else
|
||||
obj = (void*)REDIS_REPLY_ARRAY;
|
||||
|
||||
@@ -482,7 +495,7 @@ static int processMultiBulkItem(redisReader *r) {
|
||||
|
||||
/* Modify task stack when there are more than 0 elements. */
|
||||
if (elements > 0) {
|
||||
cur->elements = elements;
|
||||
cur->elements = (int)elements;
|
||||
cur->obj = obj;
|
||||
r->ridx++;
|
||||
r->rstack[r->ridx].type = -1;
|
||||
@@ -564,6 +577,7 @@ redisReader *redisReaderCreate(void) {
|
||||
r->errstr[0] = '\0';
|
||||
r->fn = &defaultFunctions;
|
||||
r->buf = sdsempty();
|
||||
r->maxbuf = REDIS_READER_MAX_BUF;
|
||||
if (r->buf == NULL) {
|
||||
free(r);
|
||||
return NULL;
|
||||
@@ -590,9 +604,8 @@ int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
|
||||
|
||||
/* Copy the provided buffer. */
|
||||
if (buf != NULL && len >= 1) {
|
||||
#if 0
|
||||
/* Destroy internal buffer when it is empty and is quite large. */
|
||||
if (r->len == 0 && sdsavail(r->buf) > 16*1024) {
|
||||
if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
|
||||
sdsfree(r->buf);
|
||||
r->buf = sdsempty();
|
||||
r->pos = 0;
|
||||
@@ -600,7 +613,6 @@ int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
|
||||
/* r->buf should not be NULL since we just free'd a larger one. */
|
||||
assert(r->buf != NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
newbuf = sdscatlen(r->buf,buf,len);
|
||||
if (newbuf == NULL) {
|
||||
@@ -651,7 +663,7 @@ int redisReaderGetReply(redisReader *r, void **reply) {
|
||||
/* Discard part of the buffer when we've consumed at least 1k, to avoid
|
||||
* doing unnecessary calls to memmove() in sds.c. */
|
||||
if (r->pos >= 1024) {
|
||||
r->buf = sdsrange(r->buf,r->pos,-1);
|
||||
sdsrange(r->buf,(int)(r->pos),-1);
|
||||
r->pos = 0;
|
||||
r->len = sdslen(r->buf);
|
||||
}
|
||||
@@ -681,7 +693,7 @@ static int intlen(int i) {
|
||||
|
||||
/* Helper that calculates the bulk length given a certain string length. */
|
||||
static size_t bulklen(size_t len) {
|
||||
return 1+intlen(len)+2+len+2;
|
||||
return (size_t)(1+intlen((int)len)+2+(int)len+2);
|
||||
}
|
||||
|
||||
int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
||||
@@ -712,7 +724,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
||||
if (newargv == NULL) goto err;
|
||||
curargv = newargv;
|
||||
curargv[argc++] = curarg;
|
||||
totlen += bulklen(sdslen(curarg));
|
||||
totlen += (int)bulklen(sdslen(curarg));
|
||||
|
||||
/* curarg is put in argv so it can be overwritten. */
|
||||
curarg = sdsempty();
|
||||
@@ -864,7 +876,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
||||
if (newargv == NULL) goto err;
|
||||
curargv = newargv;
|
||||
curargv[argc++] = curarg;
|
||||
totlen += bulklen(sdslen(curarg));
|
||||
totlen += (int)bulklen(sdslen(curarg));
|
||||
} else {
|
||||
sdsfree(curarg);
|
||||
}
|
||||
@@ -876,14 +888,18 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
||||
totlen += 1+intlen(argc)+2;
|
||||
|
||||
/* Build the command at protocol level */
|
||||
cmd = malloc(totlen+1);
|
||||
cmd = (char *)malloc(totlen+1);
|
||||
if (cmd == NULL) goto err;
|
||||
|
||||
pos = sprintf(cmd,"*%d\r\n",argc);
|
||||
for (j = 0; j < argc; j++) {
|
||||
#ifdef _WIN32
|
||||
pos += sprintf(cmd+pos,"$%llu\r\n",(unsigned long long)sdslen(curargv[j]));
|
||||
#else
|
||||
pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j]));
|
||||
#endif
|
||||
memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));
|
||||
pos += sdslen(curargv[j]);
|
||||
pos += (int)sdslen(curargv[j]);
|
||||
sdsfree(curargv[j]);
|
||||
cmd[pos++] = '\r';
|
||||
cmd[pos++] = '\n';
|
||||
@@ -918,7 +934,7 @@ err:
|
||||
* %b represents a binary safe string
|
||||
*
|
||||
* When using %b you need to provide both the pointer to the string
|
||||
* and the length in bytes. Examples:
|
||||
* and the length in bytes as a size_t. Examples:
|
||||
*
|
||||
* len = redisFormatCommand(target, "GET %s", mykey);
|
||||
* len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen);
|
||||
@@ -947,7 +963,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
|
||||
totlen = 1+intlen(argc)+2;
|
||||
for (j = 0; j < argc; j++) {
|
||||
len = argvlen ? argvlen[j] : strlen(argv[j]);
|
||||
totlen += bulklen(len);
|
||||
totlen += (int)bulklen(len);
|
||||
}
|
||||
|
||||
/* Build the command at protocol level */
|
||||
@@ -958,9 +974,13 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
|
||||
pos = sprintf(cmd,"*%d\r\n",argc);
|
||||
for (j = 0; j < argc; j++) {
|
||||
len = argvlen ? argvlen[j] : strlen(argv[j]);
|
||||
#ifdef _WIN32
|
||||
pos += sprintf(cmd+pos,"$%llu\r\n",(unsigned long long)len);
|
||||
#else
|
||||
pos += sprintf(cmd+pos,"$%zu\r\n",len);
|
||||
#endif
|
||||
memcpy(cmd+pos,argv[j],len);
|
||||
pos += len;
|
||||
pos += (int)len;
|
||||
cmd[pos++] = '\r';
|
||||
cmd[pos++] = '\n';
|
||||
}
|
||||
@@ -1002,8 +1022,9 @@ static redisContext *redisContextInit(void) {
|
||||
}
|
||||
|
||||
void redisFree(redisContext *c) {
|
||||
if (c->fd > 0)
|
||||
if (c->fd > 0) {
|
||||
close(c->fd);
|
||||
}
|
||||
if (c->obuf != NULL)
|
||||
sdsfree(c->obuf);
|
||||
if (c->reader != NULL)
|
||||
@@ -1011,58 +1032,132 @@ void redisFree(redisContext *c) {
|
||||
free(c);
|
||||
}
|
||||
|
||||
int redisFreeKeepFd(redisContext *c) {
|
||||
int fd = c->fd;
|
||||
c->fd = -1;
|
||||
redisFree(c);
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Connect to a Redis instance. On error the field error in the returned
|
||||
* context will be set to the return value of the error function.
|
||||
* When no set of reply functions is given, the default set will be used. */
|
||||
redisContext *redisConnect(const char *ip, int port) {
|
||||
redisContext *c = redisContextInit();
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectTcp(c,ip,port,NULL);
|
||||
return c;
|
||||
}
|
||||
|
||||
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) {
|
||||
redisContext *c = redisContextInit();
|
||||
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectTcp(c,ip,port,&tv);
|
||||
return c;
|
||||
}
|
||||
|
||||
redisContext *redisConnectNonBlock(const char *ip, int port) {
|
||||
redisContext *c = redisContextInit();
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
redisContextConnectTcp(c,ip,port,NULL);
|
||||
return c;
|
||||
}
|
||||
|
||||
redisContext *redisConnectUnix(const char *path) {
|
||||
redisContext *redisConnectBindNonBlock(const char *ip, int port,
|
||||
const char *source_addr) {
|
||||
redisContext *c = redisContextInit();
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
|
||||
return c;
|
||||
}
|
||||
|
||||
redisContext *redisConnectUnix(const char *path) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectUnix(c,path,NULL);
|
||||
return c;
|
||||
}
|
||||
|
||||
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) {
|
||||
redisContext *c = redisContextInit();
|
||||
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags |= REDIS_BLOCK;
|
||||
redisContextConnectUnix(c,path,&tv);
|
||||
return c;
|
||||
}
|
||||
|
||||
redisContext *redisConnectUnixNonBlock(const char *path) {
|
||||
redisContext *c = redisContextInit();
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
redisContextConnectUnix(c,path,NULL);
|
||||
return c;
|
||||
}
|
||||
|
||||
redisContext *redisConnectFd(int fd) {
|
||||
redisContext *c;
|
||||
|
||||
c = redisContextInit();
|
||||
if (c == NULL)
|
||||
return NULL;
|
||||
|
||||
c->fd = fd;
|
||||
c->flags |= REDIS_BLOCK | REDIS_CONNECTED;
|
||||
return c;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
redisContext *redisPreConnectNonBlock(const char *ip, int port, SOCKADDR_STORAGE *ss) {
|
||||
redisContext *c = redisContextInit();
|
||||
c->fd = -1;
|
||||
c->flags &= ~REDIS_BLOCK;
|
||||
redisContextPreConnectTcp(c, ip, port, NULL, ss);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set read/write timeout on a blocking socket. */
|
||||
int redisSetTimeout(redisContext *c, struct timeval tv) {
|
||||
int redisSetTimeout(redisContext *c, const struct timeval tv) {
|
||||
if (c->flags & REDIS_BLOCK)
|
||||
return redisContextSetTimeout(c,tv);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
/* Enable connection KeepAlive. */
|
||||
int redisEnableKeepAlive(redisContext *c) {
|
||||
if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
/* Use this function to handle a read event on the descriptor. It will try
|
||||
* and read some bytes from the socket and feed them to the reply parser.
|
||||
*
|
||||
@@ -1078,7 +1173,7 @@ int redisBufferRead(redisContext *c) {
|
||||
|
||||
nread = read(c->fd,buf,sizeof(buf));
|
||||
if (nread == -1) {
|
||||
if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
|
||||
if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
||||
/* Try again later */
|
||||
} else {
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
@@ -1096,6 +1191,33 @@ int redisBufferRead(redisContext *c) {
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Use this function if the caller has already read the data. It will
|
||||
* feed bytes to the reply parser.
|
||||
*
|
||||
* After this function is called, you may use redisContextReadReply to
|
||||
* see if there is a reply available. */
|
||||
int redisBufferReadDone(redisContext *c, char *buf, int nread) {
|
||||
if (nread == -1) {
|
||||
if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
|
||||
/* Try again later */
|
||||
} else {
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
} else if (nread == 0) {
|
||||
__redisSetError(c,REDIS_ERR_EOF, sdsnew("Server closed the connection"));
|
||||
return REDIS_ERR;
|
||||
} else {
|
||||
if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {
|
||||
__redisSetError(c,c->reader->err,c->reader->errstr);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write the output buffer to the socket.
|
||||
*
|
||||
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
|
||||
@@ -1115,7 +1237,7 @@ int redisBufferWrite(redisContext *c, int *done) {
|
||||
if (sdslen(c->obuf) > 0) {
|
||||
nwritten = write(c->fd,c->obuf,sdslen(c->obuf));
|
||||
if (nwritten == -1) {
|
||||
if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
|
||||
if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
|
||||
/* Try again later */
|
||||
} else {
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
@@ -1126,7 +1248,7 @@ int redisBufferWrite(redisContext *c, int *done) {
|
||||
sdsfree(c->obuf);
|
||||
c->obuf = sdsempty();
|
||||
} else {
|
||||
c->obuf = sdsrange(c->obuf,nwritten,-1);
|
||||
sdsrange(c->obuf,nwritten,-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1134,6 +1256,23 @@ int redisBufferWrite(redisContext *c, int *done) {
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Use this function if the caller has already written the data.
|
||||
*/
|
||||
int redisBufferWriteDone(redisContext *c, int nwritten, int *done) {
|
||||
if (nwritten > 0) {
|
||||
if (nwritten == (signed)sdslen(c->obuf)) {
|
||||
sdsfree(c->obuf);
|
||||
c->obuf = sdsempty();
|
||||
} else {
|
||||
sdsrange(c->obuf, nwritten, -1);
|
||||
}
|
||||
}
|
||||
if (done != NULL) *done = (sdslen(c->obuf) == 0);
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Internal helper function to try and get a reply from the reader,
|
||||
* or set an error in the context otherwise. */
|
||||
int redisGetReplyFromReader(redisContext *c, void **reply) {
|
||||
@@ -1181,7 +1320,7 @@ int redisGetReply(redisContext *c, void **reply) {
|
||||
* is used, you need to call redisGetReply yourself to retrieve
|
||||
* the reply (or replies in pub/sub).
|
||||
*/
|
||||
int __redisAppendCommand(redisContext *c, char *cmd, size_t len) {
|
||||
int __redisAppendCommand(redisContext *c, const char *cmd, size_t len) {
|
||||
sds newbuf;
|
||||
|
||||
newbuf = sdscatlen(c->obuf,cmd,len);
|
||||
@@ -1194,6 +1333,15 @@ int __redisAppendCommand(redisContext *c, char *cmd, size_t len) {
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) {
|
||||
|
||||
if (__redisAppendCommand(c, cmd, len) != REDIS_OK) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisvAppendCommand(redisContext *c, const char *format, va_list ap) {
|
||||
char *cmd;
|
||||
int len;
|
||||
|
||||
Vendored
+36
-5
@@ -33,11 +33,21 @@
|
||||
#define __HIREDIS_H
|
||||
#include <stdio.h> /* for size_t */
|
||||
#include <stdarg.h> /* for va_list */
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h> /* for struct timeval */
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include "..\..\src\win32_Interop\Win32_FDAPI.h"
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef va_copy
|
||||
#define va_copy(d,s) d = (s)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define HIREDIS_MAJOR 0
|
||||
#define HIREDIS_MINOR 10
|
||||
#define HIREDIS_PATCH 1
|
||||
#define HIREDIS_MINOR 11
|
||||
#define HIREDIS_PATCH 0
|
||||
|
||||
#define REDIS_ERR -1
|
||||
#define REDIS_OK 0
|
||||
@@ -76,6 +86,9 @@
|
||||
/* Flag that is set when the async context has one or more subscriptions. */
|
||||
#define REDIS_SUBSCRIBED 0x20
|
||||
|
||||
/* Flag that is set when monitor mode is active */
|
||||
#define REDIS_MONITORING 0x40
|
||||
|
||||
#define REDIS_REPLY_STRING 1
|
||||
#define REDIS_REPLY_ARRAY 2
|
||||
#define REDIS_REPLY_INTEGER 3
|
||||
@@ -83,6 +96,10 @@
|
||||
#define REDIS_REPLY_STATUS 5
|
||||
#define REDIS_REPLY_ERROR 6
|
||||
|
||||
#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */
|
||||
|
||||
#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -122,6 +139,7 @@ typedef struct redisReader {
|
||||
char *buf; /* Read buffer */
|
||||
size_t pos; /* Buffer cursor */
|
||||
size_t len; /* Buffer length */
|
||||
size_t maxbuf; /* Max length of unused buffer */
|
||||
|
||||
redisReadTask rstack[9];
|
||||
int ridx; /* Index of current read task */
|
||||
@@ -165,15 +183,24 @@ typedef struct redisContext {
|
||||
} redisContext;
|
||||
|
||||
redisContext *redisConnect(const char *ip, int port);
|
||||
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv);
|
||||
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
|
||||
redisContext *redisConnectNonBlock(const char *ip, int port);
|
||||
redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr);
|
||||
redisContext *redisConnectUnix(const char *path);
|
||||
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv);
|
||||
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
|
||||
redisContext *redisConnectUnixNonBlock(const char *path);
|
||||
int redisSetTimeout(redisContext *c, struct timeval tv);
|
||||
redisContext *redisConnectFd(int fd);
|
||||
int redisSetTimeout(redisContext *c, const struct timeval tv);
|
||||
int redisEnableKeepAlive(redisContext *c);
|
||||
void redisFree(redisContext *c);
|
||||
int redisFreeKeepFd(redisContext *c);
|
||||
int redisBufferRead(redisContext *c);
|
||||
int redisBufferWrite(redisContext *c, int *done);
|
||||
#ifdef _WIN32
|
||||
redisContext *redisPreConnectNonBlock(const char *ip, int port, SOCKADDR_STORAGE *sa);
|
||||
int redisBufferReadDone(redisContext *c, char *buf, int nread);
|
||||
int redisBufferWriteDone(redisContext *c, int nwritten, int *done);
|
||||
#endif
|
||||
|
||||
/* In a blocking context, this function first checks if there are unconsumed
|
||||
* replies to return and returns one if so. Otherwise, it flushes the output
|
||||
@@ -182,6 +209,10 @@ int redisBufferWrite(redisContext *c, int *done);
|
||||
int redisGetReply(redisContext *c, void **reply);
|
||||
int redisGetReplyFromReader(redisContext *c, void **reply);
|
||||
|
||||
/* Write a formatted command to the output buffer. Use these functions in blocking mode
|
||||
* to get a pipeline of commands. */
|
||||
int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);
|
||||
|
||||
/* Write a command to the output buffer. Use these functions in blocking mode
|
||||
* to get a pipeline of commands. */
|
||||
int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
|
||||
|
||||
Vendored
+230
-54
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "fmacros.h"
|
||||
#include <sys/types.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/un.h>
|
||||
@@ -39,21 +40,40 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "sds.h"
|
||||
#ifdef _WIN32
|
||||
#include "../../src/win32_Interop/win32fixes.h"
|
||||
#include "mstcpip.h"
|
||||
#endif
|
||||
|
||||
/* Defined in hiredis.c */
|
||||
void __redisSetError(redisContext *c, int type, const char *str);
|
||||
|
||||
static void redisContextCloseFd(redisContext *c) {
|
||||
if (c && c->fd >= 0) {
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
||||
char buf[128];
|
||||
char buf[128] = { 0 };
|
||||
size_t len = 0;
|
||||
|
||||
if (prefix != NULL)
|
||||
@@ -62,11 +82,11 @@ static void __redisSetErrorFromErrno(redisContext *c, int type, const char *pref
|
||||
__redisSetError(c,type,buf);
|
||||
}
|
||||
|
||||
static int redisSetReuseAddr(redisContext *c, int fd) {
|
||||
static int redisSetReuseAddr(redisContext *c) {
|
||||
int on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
||||
if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
@@ -78,23 +98,24 @@ static int redisCreateSocket(redisContext *c, int type) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
c->fd = s;
|
||||
if (type == AF_INET) {
|
||||
if (redisSetReuseAddr(c,s) == REDIS_ERR) {
|
||||
if (redisSetReuseAddr(c) == REDIS_ERR) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
||||
static int redisSetBlocking(redisContext *c, int blocking) {
|
||||
int flags;
|
||||
|
||||
/* Set the socket nonblocking.
|
||||
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
|
||||
* interrupted by a signal. */
|
||||
if ((flags = fcntl(fd, F_GETFL)) == -1) {
|
||||
if ((flags = fcntl(c->fd, F_GETFL,0)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
||||
close(fd);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
@@ -103,84 +124,157 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
||||
else
|
||||
flags |= O_NONBLOCK;
|
||||
|
||||
if (fcntl(fd, F_SETFL, flags) == -1) {
|
||||
if (fcntl(c->fd, F_SETFL, flags) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
||||
close(fd);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisSetTcpNoDelay(redisContext *c, int fd) {
|
||||
int redisKeepAlive(redisContext *c, int interval) {
|
||||
int val = 1;
|
||||
int fd = c->fd;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
val = interval;
|
||||
|
||||
#ifdef _OSX
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
#ifndef __sun
|
||||
#ifdef _WIN32
|
||||
{
|
||||
struct tcp_keepalive settings;
|
||||
DWORD bytesReturned;
|
||||
WSAOVERLAPPED overlapped;
|
||||
settings.onoff = 1;
|
||||
settings.keepalivetime = interval*1000;
|
||||
settings.keepaliveinterval = interval*1000/3;
|
||||
overlapped.hEvent = NULL;
|
||||
WSAIoctl(
|
||||
fd,
|
||||
SIO_KEEPALIVE_VALS,
|
||||
&settings,
|
||||
sizeof(struct tcp_keepalive),
|
||||
NULL,
|
||||
0,
|
||||
&bytesReturned,
|
||||
&overlapped,
|
||||
NULL);
|
||||
}
|
||||
#else
|
||||
val = interval;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
val = interval/3;
|
||||
if (val == 0) val = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
val = 3;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisSetTcpNoDelay(redisContext *c) {
|
||||
int yes = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
||||
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
||||
close(fd);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) {
|
||||
struct timeval to;
|
||||
struct timeval *toptr = NULL;
|
||||
fd_set wfd;
|
||||
#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
|
||||
|
||||
static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {
|
||||
struct pollfd wfd[1];
|
||||
long msec;
|
||||
|
||||
msec = -1;
|
||||
wfd[0].fd = c->fd;
|
||||
wfd[0].events = POLLOUT;
|
||||
|
||||
/* Only use timeout when not NULL. */
|
||||
if (timeout != NULL) {
|
||||
to = *timeout;
|
||||
toptr = &to;
|
||||
if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);
|
||||
|
||||
if (msec < 0 || msec > INT_MAX) {
|
||||
msec = INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (errno == EINPROGRESS) {
|
||||
FD_ZERO(&wfd);
|
||||
FD_SET(fd, &wfd);
|
||||
int res;
|
||||
|
||||
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)");
|
||||
close(fd);
|
||||
if ((res = poll(wfd, 1, msec)) == -1) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (!FD_ISSET(fd, &wfd)) {
|
||||
} else if (res == 0) {
|
||||
errno = ETIMEDOUT;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (redisCheckSocketError(c, fd) != REDIS_OK)
|
||||
if (redisCheckSocketError(c) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
int redisCheckSocketError(redisContext *c, int fd) {
|
||||
int redisCheckSocketError(redisContext *c) {
|
||||
int err = 0;
|
||||
socklen_t errlen = sizeof(err);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
||||
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisContextSetTimeout(redisContext *c, struct timeval tv) {
|
||||
int redisContextSetTimeout(redisContext *c, const struct timeval tv) {
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
|
||||
return REDIS_ERR;
|
||||
@@ -192,10 +286,42 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) {
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) {
|
||||
#ifdef _WIN32
|
||||
|
||||
int redisContextPreConnectTcp(
|
||||
redisContext *c,
|
||||
const char *addr,
|
||||
int port,
|
||||
struct timeval *timeout,
|
||||
SOCKADDR_STORAGE* ss) {
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
|
||||
if (ParseStorageAddress(addr, port, ss) == FALSE) {
|
||||
DebugBreak();
|
||||
}
|
||||
|
||||
if (REDIS_OK != redisCreateSocket(c, ss->ss_family)) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (redisSetTcpNoDelay(c) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
if (blocking == 0) {
|
||||
if (redisSetBlocking(c, 0) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout,
|
||||
const char *source_addr) {
|
||||
int s, rv;
|
||||
char _port[6]; /* strlen("65535"); */
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
struct addrinfo hints, *servinfo, *bservinfo, *p, *b;
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
|
||||
snprintf(_port, 6, "%d", port);
|
||||
@@ -203,33 +329,64 @@ int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct t
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
/* Try with IPv6 if no IPv4 address was found. We do it in this order since
|
||||
* in a Redis client you can't afford to test if you have IPv6 connectivity
|
||||
* as this would add latency to every connect. Otherwise a more sensible
|
||||
* route could be: Use IPv6 if both addresses are available and there is IPv6
|
||||
* connectivity. */
|
||||
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
|
||||
return REDIS_ERR;
|
||||
hints.ai_family = AF_INET6;
|
||||
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
|
||||
continue;
|
||||
|
||||
if (redisSetBlocking(c,s,0) != REDIS_OK)
|
||||
c->fd = s;
|
||||
if (redisSetBlocking(c,0) != REDIS_OK)
|
||||
goto error;
|
||||
if (source_addr) {
|
||||
int bound = 0;
|
||||
/* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */
|
||||
if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) {
|
||||
char buf[128];
|
||||
snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv));
|
||||
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||
goto error;
|
||||
}
|
||||
for (b = bservinfo; b != NULL; b = b->ai_next) {
|
||||
if (bind(s,b->ai_addr,(socklen_t)b->ai_addrlen) != -1) {
|
||||
bound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(bservinfo);
|
||||
if (!bound) {
|
||||
char buf[128];
|
||||
snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno));
|
||||
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
||||
if (errno == EHOSTUNREACH) {
|
||||
close(s);
|
||||
redisContextCloseFd(c);
|
||||
continue;
|
||||
} else if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
|
||||
if (redisContextWaitReady(c,timeout) != REDIS_OK)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
|
||||
if (blocking && redisSetBlocking(c,1) != REDIS_OK)
|
||||
goto error;
|
||||
if (redisSetTcpNoDelay(c,s) != REDIS_OK)
|
||||
if (redisSetTcpNoDelay(c) != REDIS_OK)
|
||||
goto error;
|
||||
|
||||
c->fd = s;
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
rv = REDIS_OK;
|
||||
goto end;
|
||||
@@ -248,32 +405,51 @@ end:
|
||||
return rv; // Need to return REDIS_OK if alright
|
||||
}
|
||||
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) {
|
||||
int s;
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout) {
|
||||
return _redisContextConnectTcp(c, addr, port, timeout, NULL);
|
||||
}
|
||||
|
||||
int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout,
|
||||
const char *source_addr) {
|
||||
return _redisContextConnectTcp(c, addr, port, timeout, source_addr);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
||||
(void) timeout;
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(),"Unix sockets are not suported on Windows platform. (%s)\n", path));
|
||||
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
struct sockaddr_un sa;
|
||||
|
||||
if ((s = redisCreateSocket(c,AF_LOCAL)) < 0)
|
||||
if (redisCreateSocket(c,AF_LOCAL) < 0)
|
||||
return REDIS_ERR;
|
||||
if (redisSetBlocking(c,s,0) != REDIS_OK)
|
||||
if (redisSetBlocking(c,0) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
sa.sun_family = AF_LOCAL;
|
||||
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
|
||||
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
||||
if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
||||
if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
|
||||
if (redisContextWaitReady(c,timeout) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset socket to be blocking after connect(2). */
|
||||
if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
|
||||
if (blocking && redisSetBlocking(c,1) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
c->fd = s;
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
Vendored
+13
-5
@@ -35,13 +35,21 @@
|
||||
|
||||
#include "hiredis.h"
|
||||
|
||||
#if defined(__sun)
|
||||
#if defined(__sun) || defined(_AIX)
|
||||
#define AF_LOCAL AF_UNIX
|
||||
#endif
|
||||
|
||||
int redisCheckSocketError(redisContext *c, int fd);
|
||||
int redisContextSetTimeout(redisContext *c, struct timeval tv);
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout);
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout);
|
||||
int redisCheckSocketError(redisContext *c);
|
||||
int redisContextSetTimeout(redisContext *c, const struct timeval tv);
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);
|
||||
int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout,
|
||||
const char *source_addr);
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout);
|
||||
int redisKeepAlive(redisContext *c, int interval);
|
||||
|
||||
#ifdef _WIN32
|
||||
int redisContextPreConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout, SOCKADDR_STORAGE *ss);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+653
-155
File diff suppressed because it is too large
Load Diff
Vendored
+29
-12
@@ -31,24 +31,30 @@
|
||||
#ifndef __SDS_H
|
||||
#define __SDS_H
|
||||
|
||||
#define SDS_MAX_PREALLOC (1024*1024)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
typedef char *sds;
|
||||
|
||||
struct sdshdr {
|
||||
int len;
|
||||
int free;
|
||||
unsigned int len;
|
||||
unsigned int free;
|
||||
char buf[];
|
||||
};
|
||||
|
||||
static inline size_t sdslen(const sds s) {
|
||||
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
|
||||
struct sdshdr *sh = (struct sdshdr *)(s-(sizeof(struct sdshdr)));
|
||||
return sh->len;
|
||||
}
|
||||
|
||||
static inline size_t sdsavail(const sds s) {
|
||||
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
|
||||
struct sdshdr *sh = (struct sdshdr *)(s-(sizeof(struct sdshdr)));
|
||||
return sh->free;
|
||||
}
|
||||
|
||||
@@ -58,12 +64,13 @@ sds sdsempty(void);
|
||||
size_t sdslen(const sds s);
|
||||
sds sdsdup(const sds s);
|
||||
void sdsfree(sds s);
|
||||
size_t sdsavail(sds s);
|
||||
size_t sdsavail(const sds s);
|
||||
sds sdsgrowzero(sds s, size_t len);
|
||||
sds sdscatlen(sds s, const void *t, size_t len);
|
||||
sds sdscat(sds s, const char *t);
|
||||
sds sdscpylen(sds s, char *t, size_t len);
|
||||
sds sdscpy(sds s, char *t);
|
||||
sds sdscatsds(sds s, const sds t);
|
||||
sds sdscpylen(sds s, const char *t, size_t len);
|
||||
sds sdscpy(sds s, const char *t);
|
||||
|
||||
sds sdscatvprintf(sds s, const char *fmt, va_list ap);
|
||||
#ifdef __GNUC__
|
||||
@@ -73,16 +80,26 @@ sds sdscatprintf(sds s, const char *fmt, ...)
|
||||
sds sdscatprintf(sds s, const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
sds sdscatfmt(sds s, char const *fmt, ...);
|
||||
sds sdstrim(sds s, const char *cset);
|
||||
sds sdsrange(sds s, int start, int end);
|
||||
void sdsrange(sds s, int start, int end);
|
||||
void sdsupdatelen(sds s);
|
||||
int sdscmp(sds s1, sds s2);
|
||||
sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count);
|
||||
void sdsclear(sds s);
|
||||
int sdscmp(const sds s1, const sds s2);
|
||||
sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);
|
||||
void sdsfreesplitres(sds *tokens, int count);
|
||||
void sdstolower(sds s);
|
||||
void sdstoupper(sds s);
|
||||
sds sdsfromlonglong(long long value);
|
||||
sds sdscatrepr(sds s, char *p, size_t len);
|
||||
sds *sdssplitargs(char *line, int *argc);
|
||||
sds sdscatrepr(sds s, const char *p, size_t len);
|
||||
sds *sdssplitargs(const char *line, int *argc);
|
||||
sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
|
||||
sds sdsjoin(char **argv, int argc, char *sep);
|
||||
|
||||
/* Low level functions exposed to the user API */
|
||||
sds sdsMakeRoomFor(sds s, size_t addlen);
|
||||
void sdsIncrLen(sds s, int incr);
|
||||
sds sdsRemoveFreeSpace(sds s);
|
||||
size_t sdsAllocSize(sds s);
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+96
-17
@@ -8,12 +8,14 @@
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "hiredis.h"
|
||||
|
||||
enum connection_type {
|
||||
CONN_TCP,
|
||||
CONN_UNIX
|
||||
CONN_UNIX,
|
||||
CONN_FD
|
||||
};
|
||||
|
||||
struct config {
|
||||
@@ -22,6 +24,7 @@ struct config {
|
||||
struct {
|
||||
const char *host;
|
||||
int port;
|
||||
struct timeval timeout;
|
||||
} tcp;
|
||||
|
||||
struct {
|
||||
@@ -48,7 +51,7 @@ static redisContext *select_database(redisContext *c) {
|
||||
assert(reply != NULL);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Make sure the DB is emtpy */
|
||||
/* Make sure the DB is empty */
|
||||
reply = redisCommand(c,"DBSIZE");
|
||||
assert(reply != NULL);
|
||||
if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {
|
||||
@@ -62,7 +65,7 @@ static redisContext *select_database(redisContext *c) {
|
||||
return c;
|
||||
}
|
||||
|
||||
static void disconnect(redisContext *c) {
|
||||
static int disconnect(redisContext *c, int keep_fd) {
|
||||
redisReply *reply;
|
||||
|
||||
/* Make sure we're on DB 9. */
|
||||
@@ -73,8 +76,11 @@ static void disconnect(redisContext *c) {
|
||||
assert(reply != NULL);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Free the context as well. */
|
||||
/* Free the context as well, but keep the fd if requested. */
|
||||
if (keep_fd)
|
||||
return redisFreeKeepFd(c);
|
||||
redisFree(c);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static redisContext *connect(struct config config) {
|
||||
@@ -84,11 +90,22 @@ static redisContext *connect(struct config config) {
|
||||
c = redisConnect(config.tcp.host, config.tcp.port);
|
||||
} else if (config.type == CONN_UNIX) {
|
||||
c = redisConnectUnix(config.unix.path);
|
||||
} else if (config.type == CONN_FD) {
|
||||
/* Create a dummy connection just to get an fd to inherit */
|
||||
redisContext *dummy_ctx = redisConnectUnix(config.unix.path);
|
||||
if (dummy_ctx) {
|
||||
int fd = disconnect(dummy_ctx, 1);
|
||||
printf("Connecting to inherited fd %d\n", fd);
|
||||
c = redisConnectFd(fd);
|
||||
}
|
||||
} else {
|
||||
assert(NULL);
|
||||
}
|
||||
|
||||
if (c->err) {
|
||||
if (c == NULL) {
|
||||
printf("Connection error: can't allocate redis context\n");
|
||||
exit(1);
|
||||
} else if (c->err) {
|
||||
printf("Connection error: %s\n", c->errstr);
|
||||
exit(1);
|
||||
}
|
||||
@@ -125,13 +142,13 @@ static void test_format_commands(void) {
|
||||
free(cmd);
|
||||
|
||||
test("Format command with %%b string interpolation: ");
|
||||
len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3);
|
||||
len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3);
|
||||
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 &&
|
||||
len == 4+4+(3+2)+4+(3+2)+4+(3+2));
|
||||
free(cmd);
|
||||
|
||||
test("Format command with %%b and an empty string: ");
|
||||
len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0);
|
||||
len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0);
|
||||
test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 &&
|
||||
len == 4+4+(3+2)+4+(3+2)+4+(0+2));
|
||||
free(cmd);
|
||||
@@ -177,7 +194,7 @@ static void test_format_commands(void) {
|
||||
FLOAT_WIDTH_TEST(double);
|
||||
|
||||
test("Format command with invalid printf format: ");
|
||||
len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
|
||||
len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);
|
||||
test_cond(len == -1);
|
||||
|
||||
const char *argv[3];
|
||||
@@ -200,10 +217,33 @@ static void test_format_commands(void) {
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
static void test_append_formatted_commands(struct config config) {
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
char *cmd;
|
||||
int len;
|
||||
|
||||
c = connect(config);
|
||||
|
||||
test("Append format command: ");
|
||||
|
||||
len = redisFormatCommand(&cmd, "SET foo bar");
|
||||
|
||||
test_cond(redisAppendFormattedCommand(c, cmd, len) == REDIS_OK);
|
||||
|
||||
assert(redisGetReply(c, (void*)&reply) == REDIS_OK);
|
||||
|
||||
free(cmd);
|
||||
freeReplyObject(reply);
|
||||
|
||||
disconnect(c, 0);
|
||||
}
|
||||
|
||||
static void test_reply_reader(void) {
|
||||
redisReader *reader;
|
||||
void *reply;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
test("Error handling in reply parser: ");
|
||||
reader = redisReaderCreate();
|
||||
@@ -225,12 +265,13 @@ static void test_reply_reader(void) {
|
||||
strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Set error on nested multi bulks with depth > 2: ");
|
||||
test("Set error on nested multi bulks with depth > 7: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
}
|
||||
|
||||
ret = redisReaderGetReply(reader,NULL);
|
||||
test_cond(ret == REDIS_ERR &&
|
||||
strncasecmp(reader->errstr,"No support for",14) == 0);
|
||||
@@ -284,7 +325,10 @@ static void test_blocking_connection_errors(void) {
|
||||
c = redisConnect((char*)"idontexist.local", 6379);
|
||||
test_cond(c->err == REDIS_ERR_OTHER &&
|
||||
(strcmp(c->errstr,"Name or service not known") == 0 ||
|
||||
strcmp(c->errstr,"Can't resolve: idontexist.local") == 0));
|
||||
strcmp(c->errstr,"Can't resolve: idontexist.local") == 0 ||
|
||||
strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 ||
|
||||
strcmp(c->errstr,"No address associated with hostname") == 0 ||
|
||||
strcmp(c->errstr,"no address associated with name") == 0));
|
||||
redisFree(c);
|
||||
|
||||
test("Returns error when the port is not open: ");
|
||||
@@ -326,7 +370,7 @@ static void test_blocking_connection(struct config config) {
|
||||
freeReplyObject(reply);
|
||||
|
||||
test("%%b String interpolation works: ");
|
||||
reply = redisCommand(c,"SET %b %b","foo",3,"hello\x00world",11);
|
||||
reply = redisCommand(c,"SET %b %b","foo",(size_t)3,"hello\x00world",(size_t)11);
|
||||
freeReplyObject(reply);
|
||||
reply = redisCommand(c,"GET foo");
|
||||
test_cond(reply->type == REDIS_REPLY_STRING &&
|
||||
@@ -374,7 +418,7 @@ static void test_blocking_connection(struct config config) {
|
||||
strcasecmp(reply->element[1]->str,"pong") == 0);
|
||||
freeReplyObject(reply);
|
||||
|
||||
disconnect(c);
|
||||
disconnect(c, 0);
|
||||
}
|
||||
|
||||
static void test_blocking_io_errors(struct config config) {
|
||||
@@ -428,6 +472,30 @@ static void test_blocking_io_errors(struct config config) {
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
static void test_invalid_timeout_errors(struct config config) {
|
||||
redisContext *c;
|
||||
|
||||
test("Set error when an invalid timeout usec value is given to redisConnectWithTimeout: ");
|
||||
|
||||
config.tcp.timeout.tv_sec = 0;
|
||||
config.tcp.timeout.tv_usec = 10000001;
|
||||
|
||||
c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
|
||||
|
||||
test_cond(c->err == REDIS_ERR_IO);
|
||||
|
||||
test("Set error when an invalid timeout sec value is given to redisConnectWithTimeout: ");
|
||||
|
||||
config.tcp.timeout.tv_sec = (((LONG_MAX) - 999) / 1000) + 1;
|
||||
config.tcp.timeout.tv_usec = 0;
|
||||
|
||||
c = redisConnectWithTimeout(config.tcp.host, config.tcp.port, config.tcp.timeout);
|
||||
|
||||
test_cond(c->err == REDIS_ERR_IO);
|
||||
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
static void test_throughput(struct config config) {
|
||||
redisContext *c = connect(config);
|
||||
redisReply **replies;
|
||||
@@ -490,7 +558,7 @@ static void test_throughput(struct config config) {
|
||||
free(replies);
|
||||
printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
|
||||
|
||||
disconnect(c);
|
||||
disconnect(c, 0);
|
||||
}
|
||||
|
||||
// static long __test_callback_flags = 0;
|
||||
@@ -603,6 +671,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
};
|
||||
int throughput = 1;
|
||||
int test_inherit_fd = 1;
|
||||
|
||||
/* Ignore broken pipe signal (for I/O error tests). */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
@@ -621,6 +690,8 @@ int main(int argc, char **argv) {
|
||||
cfg.unix.path = argv[0];
|
||||
} else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {
|
||||
throughput = 0;
|
||||
} else if (argc >= 1 && !strcmp(argv[0],"--skip-inherit-fd")) {
|
||||
test_inherit_fd = 0;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
||||
exit(1);
|
||||
@@ -636,6 +707,8 @@ int main(int argc, char **argv) {
|
||||
cfg.type = CONN_TCP;
|
||||
test_blocking_connection(cfg);
|
||||
test_blocking_io_errors(cfg);
|
||||
test_invalid_timeout_errors(cfg);
|
||||
test_append_formatted_commands(cfg);
|
||||
if (throughput) test_throughput(cfg);
|
||||
|
||||
printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path);
|
||||
@@ -644,6 +717,12 @@ int main(int argc, char **argv) {
|
||||
test_blocking_io_errors(cfg);
|
||||
if (throughput) test_throughput(cfg);
|
||||
|
||||
if (test_inherit_fd) {
|
||||
printf("\nTesting against inherited fd (%s):\n", cfg.unix.path);
|
||||
cfg.type = CONN_FD;
|
||||
test_blocking_connection(cfg);
|
||||
}
|
||||
|
||||
if (fails) {
|
||||
printf("*** %d TESTS FAILED ***\n", fails);
|
||||
return 1;
|
||||
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
/* Drop in replacement for zmalloc.h in order to just use libc malloc without
|
||||
* any wrappering. */
|
||||
|
||||
#ifndef ZMALLOC_H
|
||||
#define ZMALLOC_H
|
||||
|
||||
#define zmalloc malloc
|
||||
#define zrealloc realloc
|
||||
#define zcalloc(x) calloc(x,1)
|
||||
#define zfree free
|
||||
#define zstrdup strdup
|
||||
|
||||
#endif
|
||||
@@ -1,23 +1,72 @@
|
||||
/*.gcov.*
|
||||
|
||||
/autom4te.cache/
|
||||
|
||||
/bin/jemalloc.sh
|
||||
|
||||
/config.stamp
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
|
||||
/doc/html.xsl
|
||||
/doc/manpages.xsl
|
||||
/doc/jemalloc.xml
|
||||
/doc/jemalloc.html
|
||||
/doc/jemalloc.3
|
||||
|
||||
/lib/
|
||||
|
||||
/Makefile
|
||||
/include/jemalloc/internal/jemalloc_internal\.h
|
||||
/include/jemalloc/jemalloc\.h
|
||||
/include/jemalloc/jemalloc_defs\.h
|
||||
/test/jemalloc_test\.h
|
||||
|
||||
/include/jemalloc/internal/jemalloc_internal.h
|
||||
/include/jemalloc/internal/jemalloc_internal_defs.h
|
||||
/include/jemalloc/internal/private_namespace.h
|
||||
/include/jemalloc/internal/private_unnamespace.h
|
||||
/include/jemalloc/internal/public_namespace.h
|
||||
/include/jemalloc/internal/public_symbols.txt
|
||||
/include/jemalloc/internal/public_unnamespace.h
|
||||
/include/jemalloc/internal/size_classes.h
|
||||
/include/jemalloc/jemalloc.h
|
||||
/include/jemalloc/jemalloc_defs.h
|
||||
/include/jemalloc/jemalloc_macros.h
|
||||
/include/jemalloc/jemalloc_mangle.h
|
||||
/include/jemalloc/jemalloc_mangle_jet.h
|
||||
/include/jemalloc/jemalloc_protos.h
|
||||
/include/jemalloc/jemalloc_protos_jet.h
|
||||
/include/jemalloc/jemalloc_rename.h
|
||||
|
||||
/src/*.[od]
|
||||
/test/*.[od]
|
||||
/test/*.out
|
||||
/test/[a-z]*
|
||||
!test/*.c
|
||||
!test/*.exp
|
||||
/src/*.gcda
|
||||
/src/*.gcno
|
||||
|
||||
/test/test.sh
|
||||
test/include/test/jemalloc_test.h
|
||||
test/include/test/jemalloc_test_defs.h
|
||||
|
||||
/test/integration/[A-Za-z]*
|
||||
!/test/integration/[A-Za-z]*.*
|
||||
/test/integration/*.[od]
|
||||
/test/integration/*.gcda
|
||||
/test/integration/*.gcno
|
||||
/test/integration/*.out
|
||||
|
||||
/test/src/*.[od]
|
||||
/test/src/*.gcda
|
||||
/test/src/*.gcno
|
||||
|
||||
/test/stress/[A-Za-z]*
|
||||
!/test/stress/[A-Za-z]*.*
|
||||
/test/stress/*.[od]
|
||||
/test/stress/*.gcda
|
||||
/test/stress/*.gcno
|
||||
/test/stress/*.out
|
||||
|
||||
/test/unit/[A-Za-z]*
|
||||
!/test/unit/[A-Za-z]*.*
|
||||
/test/unit/*.[od]
|
||||
/test/unit/*.gcda
|
||||
/test/unit/*.gcno
|
||||
/test/unit/*.out
|
||||
|
||||
/VERSION
|
||||
|
||||
Vendored
+4
-28
@@ -1,9 +1,10 @@
|
||||
Unless otherwise specified, files in the jemalloc source distribution are
|
||||
subject to the following licenses:
|
||||
subject to the following license:
|
||||
--------------------------------------------------------------------------------
|
||||
Copyright (C) 2002-2010 Jason Evans <jasone@canonware.com>.
|
||||
Copyright (C) 2002-2014 Jason Evans <jasone@canonware.com>.
|
||||
All rights reserved.
|
||||
Copyright (C) 2007-2010 Mozilla Foundation. All rights reserved.
|
||||
Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved.
|
||||
Copyright (C) 2009-2014 Facebook, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@@ -24,28 +25,3 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--------------------------------------------------------------------------------
|
||||
Copyright (C) 2009-2010 Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
* Neither the name of Facebook, Inc. nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Vendored
+300
-2
@@ -3,8 +3,306 @@ bug fixes are all mentioned, but internal enhancements are omitted here for
|
||||
brevity (even though they are more fun to write about). Much more detail can be
|
||||
found in the git revision history:
|
||||
|
||||
http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
|
||||
git://canonware.com/jemalloc.git
|
||||
https://github.com/jemalloc/jemalloc
|
||||
|
||||
* 3.6.0 (March 31, 2014)
|
||||
|
||||
This version contains a critical bug fix for a regression present in 3.5.0 and
|
||||
3.5.1.
|
||||
|
||||
Bug fixes:
|
||||
- Fix a regression in arena_chunk_alloc() that caused crashes during
|
||||
small/large allocation if chunk allocation failed. In the absence of this
|
||||
bug, chunk allocation failure would result in allocation failure, e.g. NULL
|
||||
return from malloc(). This regression was introduced in 3.5.0.
|
||||
- Fix backtracing for gcc intrinsics-based backtracing by specifying
|
||||
-fno-omit-frame-pointer to gcc. Note that the application (and all the
|
||||
libraries it links to) must also be compiled with this option for
|
||||
backtracing to be reliable.
|
||||
- Use dss allocation precedence for huge allocations as well as small/large
|
||||
allocations.
|
||||
- Fix test assertion failure message formatting. This bug did not manifect on
|
||||
x86_64 systems because of implementation subtleties in va_list.
|
||||
- Fix inconsequential test failures for hash and SFMT code.
|
||||
|
||||
New features:
|
||||
- Support heap profiling on FreeBSD. This feature depends on the proc
|
||||
filesystem being mounted during heap profile dumping.
|
||||
|
||||
* 3.5.1 (February 25, 2014)
|
||||
|
||||
This version primarily addresses minor bugs in test code.
|
||||
|
||||
Bug fixes:
|
||||
- Configure Solaris/Illumos to use MADV_FREE.
|
||||
- Fix junk filling for mremap(2)-based huge reallocation. This is only
|
||||
relevant if configuring with the --enable-mremap option specified.
|
||||
- Avoid compilation failure if 'restrict' C99 keyword is not supported by the
|
||||
compiler.
|
||||
- Add a configure test for SSE2 rather than assuming it is usable on i686
|
||||
systems. This fixes test compilation errors, especially on 32-bit Linux
|
||||
systems.
|
||||
- Fix mallctl argument size mismatches (size_t vs. uint64_t) in the stats unit
|
||||
test.
|
||||
- Fix/remove flawed alignment-related overflow tests.
|
||||
- Prevent compiler optimizations that could change backtraces in the
|
||||
prof_accum unit test.
|
||||
|
||||
* 3.5.0 (January 22, 2014)
|
||||
|
||||
This version focuses on refactoring and automated testing, though it also
|
||||
includes some non-trivial heap profiling optimizations not mentioned below.
|
||||
|
||||
New features:
|
||||
- Add the *allocx() API, which is a successor to the experimental *allocm()
|
||||
API. The *allocx() functions are slightly simpler to use because they have
|
||||
fewer parameters, they directly return the results of primary interest, and
|
||||
mallocx()/rallocx() avoid the strict aliasing pitfall that
|
||||
allocm()/rallocm() share with posix_memalign(). Note that *allocm() is
|
||||
slated for removal in the next non-bugfix release.
|
||||
- Add support for LinuxThreads.
|
||||
|
||||
Bug fixes:
|
||||
- Unless heap profiling is enabled, disable floating point code and don't link
|
||||
with libm. This, in combination with e.g. EXTRA_CFLAGS=-mno-sse on x64
|
||||
systems, makes it possible to completely disable floating point register
|
||||
use. Some versions of glibc neglect to save/restore caller-saved floating
|
||||
point registers during dynamic lazy symbol loading, and the symbol loading
|
||||
code uses whatever malloc the application happens to have linked/loaded
|
||||
with, the result being potential floating point register corruption.
|
||||
- Report ENOMEM rather than EINVAL if an OOM occurs during heap profiling
|
||||
backtrace creation in imemalign(). This bug impacted posix_memalign() and
|
||||
aligned_alloc().
|
||||
- Fix a file descriptor leak in a prof_dump_maps() error path.
|
||||
- Fix prof_dump() to close the dump file descriptor for all relevant error
|
||||
paths.
|
||||
- Fix rallocm() to use the arena specified by the ALLOCM_ARENA(s) flag for
|
||||
allocation, not just deallocation.
|
||||
- Fix a data race for large allocation stats counters.
|
||||
- Fix a potential infinite loop during thread exit. This bug occurred on
|
||||
Solaris, and could affect other platforms with similar pthreads TSD
|
||||
implementations.
|
||||
- Don't junk-fill reallocations unless usable size changes. This fixes a
|
||||
violation of the *allocx()/*allocm() semantics.
|
||||
- Fix growing large reallocation to junk fill new space.
|
||||
- Fix huge deallocation to junk fill when munmap is disabled.
|
||||
- Change the default private namespace prefix from empty to je_, and change
|
||||
--with-private-namespace-prefix so that it prepends an additional prefix
|
||||
rather than replacing je_. This reduces the likelihood of applications
|
||||
which statically link jemalloc experiencing symbol name collisions.
|
||||
- Add missing private namespace mangling (relevant when
|
||||
--with-private-namespace is specified).
|
||||
- Add and use JEMALLOC_INLINE_C so that static inline functions are marked as
|
||||
static even for debug builds.
|
||||
- Add a missing mutex unlock in a malloc_init_hard() error path. In practice
|
||||
this error path is never executed.
|
||||
- Fix numerous bugs in malloc_strotumax() error handling/reporting. These
|
||||
bugs had no impact except for malformed inputs.
|
||||
- Fix numerous bugs in malloc_snprintf(). These bugs were not exercised by
|
||||
existing calls, so they had no impact.
|
||||
|
||||
* 3.4.1 (October 20, 2013)
|
||||
|
||||
Bug fixes:
|
||||
- Fix a race in the "arenas.extend" mallctl that could cause memory corruption
|
||||
of internal data structures and subsequent crashes.
|
||||
- Fix Valgrind integration flaws that caused Valgrind warnings about reads of
|
||||
uninitialized memory in:
|
||||
+ arena chunk headers
|
||||
+ internal zero-initialized data structures (relevant to tcache and prof
|
||||
code)
|
||||
- Preserve errno during the first allocation. A readlink(2) call during
|
||||
initialization fails unless /etc/malloc.conf exists, so errno was typically
|
||||
set during the first allocation prior to this fix.
|
||||
- Fix compilation warnings reported by gcc 4.8.1.
|
||||
|
||||
* 3.4.0 (June 2, 2013)
|
||||
|
||||
This version is essentially a small bugfix release, but the addition of
|
||||
aarch64 support requires that the minor version be incremented.
|
||||
|
||||
Bug fixes:
|
||||
- Fix race-triggered deadlocks in chunk_record(). These deadlocks were
|
||||
typically triggered by multiple threads concurrently deallocating huge
|
||||
objects.
|
||||
|
||||
New features:
|
||||
- Add support for the aarch64 architecture.
|
||||
|
||||
* 3.3.1 (March 6, 2013)
|
||||
|
||||
This version fixes bugs that are typically encountered only when utilizing
|
||||
custom run-time options.
|
||||
|
||||
Bug fixes:
|
||||
- Fix a locking order bug that could cause deadlock during fork if heap
|
||||
profiling were enabled.
|
||||
- Fix a chunk recycling bug that could cause the allocator to lose track of
|
||||
whether a chunk was zeroed. On FreeBSD, NetBSD, and OS X, it could cause
|
||||
corruption if allocating via sbrk(2) (unlikely unless running with the
|
||||
"dss:primary" option specified). This was completely harmless on Linux
|
||||
unless using mlockall(2) (and unlikely even then, unless the
|
||||
--disable-munmap configure option or the "dss:primary" option was
|
||||
specified). This regression was introduced in 3.1.0 by the
|
||||
mlockall(2)/madvise(2) interaction fix.
|
||||
- Fix TLS-related memory corruption that could occur during thread exit if the
|
||||
thread never allocated memory. Only the quarantine and prof facilities were
|
||||
susceptible.
|
||||
- Fix two quarantine bugs:
|
||||
+ Internal reallocation of the quarantined object array leaked the old
|
||||
array.
|
||||
+ Reallocation failure for internal reallocation of the quarantined object
|
||||
array (very unlikely) resulted in memory corruption.
|
||||
- Fix Valgrind integration to annotate all internally allocated memory in a
|
||||
way that keeps Valgrind happy about internal data structure access.
|
||||
- Fix building for s390 systems.
|
||||
|
||||
* 3.3.0 (January 23, 2013)
|
||||
|
||||
This version includes a few minor performance improvements in addition to the
|
||||
listed new features and bug fixes.
|
||||
|
||||
New features:
|
||||
- Add clipping support to lg_chunk option processing.
|
||||
- Add the --enable-ivsalloc option.
|
||||
- Add the --without-export option.
|
||||
- Add the --disable-zone-allocator option.
|
||||
|
||||
Bug fixes:
|
||||
- Fix "arenas.extend" mallctl to output the number of arenas.
|
||||
- Fix chunk_recycle() to unconditionally inform Valgrind that returned memory
|
||||
is undefined.
|
||||
- Fix build break on FreeBSD related to alloca.h.
|
||||
|
||||
* 3.2.0 (November 9, 2012)
|
||||
|
||||
In addition to a couple of bug fixes, this version modifies page run
|
||||
allocation and dirty page purging algorithms in order to better control
|
||||
page-level virtual memory fragmentation.
|
||||
|
||||
Incompatible changes:
|
||||
- Change the "opt.lg_dirty_mult" default from 5 to 3 (32:1 to 8:1).
|
||||
|
||||
Bug fixes:
|
||||
- Fix dss/mmap allocation precedence code to use recyclable mmap memory only
|
||||
after primary dss allocation fails.
|
||||
- Fix deadlock in the "arenas.purge" mallctl. This regression was introduced
|
||||
in 3.1.0 by the addition of the "arena.<i>.purge" mallctl.
|
||||
|
||||
* 3.1.0 (October 16, 2012)
|
||||
|
||||
New features:
|
||||
- Auto-detect whether running inside Valgrind, thus removing the need to
|
||||
manually specify MALLOC_CONF=valgrind:true.
|
||||
- Add the "arenas.extend" mallctl, which allows applications to create
|
||||
manually managed arenas.
|
||||
- Add the ALLOCM_ARENA() flag for {,r,d}allocm().
|
||||
- Add the "opt.dss", "arena.<i>.dss", and "stats.arenas.<i>.dss" mallctls,
|
||||
which provide control over dss/mmap precedence.
|
||||
- Add the "arena.<i>.purge" mallctl, which obsoletes "arenas.purge".
|
||||
- Define LG_QUANTUM for hppa.
|
||||
|
||||
Incompatible changes:
|
||||
- Disable tcache by default if running inside Valgrind, in order to avoid
|
||||
making unallocated objects appear reachable to Valgrind.
|
||||
- Drop const from malloc_usable_size() argument on Linux.
|
||||
|
||||
Bug fixes:
|
||||
- Fix heap profiling crash if sampled object is freed via realloc(p, 0).
|
||||
- Remove const from __*_hook variable declarations, so that glibc can modify
|
||||
them during process forking.
|
||||
- Fix mlockall(2)/madvise(2) interaction.
|
||||
- Fix fork(2)-related deadlocks.
|
||||
- Fix error return value for "thread.tcache.enabled" mallctl.
|
||||
|
||||
* 3.0.0 (May 11, 2012)
|
||||
|
||||
Although this version adds some major new features, the primary focus is on
|
||||
internal code cleanup that facilitates maintainability and portability, most
|
||||
of which is not reflected in the ChangeLog. This is the first release to
|
||||
incorporate substantial contributions from numerous other developers, and the
|
||||
result is a more broadly useful allocator (see the git revision history for
|
||||
contribution details). Note that the license has been unified, thanks to
|
||||
Facebook granting a license under the same terms as the other copyright
|
||||
holders (see COPYING).
|
||||
|
||||
New features:
|
||||
- Implement Valgrind support, redzones, and quarantine.
|
||||
- Add support for additional platforms:
|
||||
+ FreeBSD
|
||||
+ Mac OS X Lion
|
||||
+ MinGW
|
||||
+ Windows (no support yet for replacing the system malloc)
|
||||
- Add support for additional architectures:
|
||||
+ MIPS
|
||||
+ SH4
|
||||
+ Tilera
|
||||
- Add support for cross compiling.
|
||||
- Add nallocm(), which rounds a request size up to the nearest size class
|
||||
without actually allocating.
|
||||
- Implement aligned_alloc() (blame C11).
|
||||
- Add the "thread.tcache.enabled" mallctl.
|
||||
- Add the "opt.prof_final" mallctl.
|
||||
- Update pprof (from gperftools 2.0).
|
||||
- Add the --with-mangling option.
|
||||
- Add the --disable-experimental option.
|
||||
- Add the --disable-munmap option, and make it the default on Linux.
|
||||
- Add the --enable-mremap option, which disables use of mremap(2) by default.
|
||||
|
||||
Incompatible changes:
|
||||
- Enable stats by default.
|
||||
- Enable fill by default.
|
||||
- Disable lazy locking by default.
|
||||
- Rename the "tcache.flush" mallctl to "thread.tcache.flush".
|
||||
- Rename the "arenas.pagesize" mallctl to "arenas.page".
|
||||
- Change the "opt.lg_prof_sample" default from 0 to 19 (1 B to 512 KiB).
|
||||
- Change the "opt.prof_accum" default from true to false.
|
||||
|
||||
Removed features:
|
||||
- Remove the swap feature, including the "config.swap", "swap.avail",
|
||||
"swap.prezeroed", "swap.nfds", and "swap.fds" mallctls.
|
||||
- Remove highruns statistics, including the
|
||||
"stats.arenas.<i>.bins.<j>.highruns" and
|
||||
"stats.arenas.<i>.lruns.<j>.highruns" mallctls.
|
||||
- As part of small size class refactoring, remove the "opt.lg_[qc]space_max",
|
||||
"arenas.cacheline", "arenas.subpage", "arenas.[tqcs]space_{min,max}", and
|
||||
"arenas.[tqcs]bins" mallctls.
|
||||
- Remove the "arenas.chunksize" mallctl.
|
||||
- Remove the "opt.lg_prof_tcmax" option.
|
||||
- Remove the "opt.lg_prof_bt_max" option.
|
||||
- Remove the "opt.lg_tcache_gc_sweep" option.
|
||||
- Remove the --disable-tiny option, including the "config.tiny" mallctl.
|
||||
- Remove the --enable-dynamic-page-shift configure option.
|
||||
- Remove the --enable-sysv configure option.
|
||||
|
||||
Bug fixes:
|
||||
- Fix a statistics-related bug in the "thread.arena" mallctl that could cause
|
||||
invalid statistics and crashes.
|
||||
- Work around TLS deallocation via free() on Linux. This bug could cause
|
||||
write-after-free memory corruption.
|
||||
- Fix a potential deadlock that could occur during interval- and
|
||||
growth-triggered heap profile dumps.
|
||||
- Fix large calloc() zeroing bugs due to dropping chunk map unzeroed flags.
|
||||
- Fix chunk_alloc_dss() to stop claiming memory is zeroed. This bug could
|
||||
cause memory corruption and crashes with --enable-dss specified.
|
||||
- Fix fork-related bugs that could cause deadlock in children between fork
|
||||
and exec.
|
||||
- Fix malloc_stats_print() to honor 'b' and 'l' in the opts parameter.
|
||||
- Fix realloc(p, 0) to act like free(p).
|
||||
- Do not enforce minimum alignment in memalign().
|
||||
- Check for NULL pointer in malloc_usable_size().
|
||||
- Fix an off-by-one heap profile statistics bug that could be observed in
|
||||
interval- and growth-triggered heap profiles.
|
||||
- Fix the "epoch" mallctl to update cached stats even if the passed in epoch
|
||||
is 0.
|
||||
- Fix bin->runcur management to fix a layout policy bug. This bug did not
|
||||
affect correctness.
|
||||
- Fix a bug in choose_arena_hard() that potentially caused more arenas to be
|
||||
initialized than necessary.
|
||||
- Add missing "opt.lg_tcache_max" mallctl implementation.
|
||||
- Use glibc allocator hooks to make mixed allocator usage less likely.
|
||||
- Fix build issues for --disable-tcache.
|
||||
- Don't mangle pthread_create() when --with-private-namespace is specified.
|
||||
|
||||
* 2.2.5 (November 14, 2011)
|
||||
|
||||
|
||||
Vendored
+87
-38
@@ -26,6 +26,19 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
Embed one or more library paths, so that libjemalloc can find the libraries
|
||||
it is linked to. This works only on ELF-based systems.
|
||||
|
||||
--with-mangling=<map>
|
||||
Mangle public symbols specified in <map> which is a comma-separated list of
|
||||
name:mangled pairs.
|
||||
|
||||
For example, to use ld's --wrap option as an alternative method for
|
||||
overriding libc's malloc implementation, specify something like:
|
||||
|
||||
--with-mangling=malloc:__wrap_malloc,free:__wrap_free[...]
|
||||
|
||||
Note that mangling happens prior to application of the prefix specified by
|
||||
--with-jemalloc-prefix, and mangled symbols are then ignored when applying
|
||||
the prefix.
|
||||
|
||||
--with-jemalloc-prefix=<prefix>
|
||||
Prefix all public APIs with <prefix>. For example, if <prefix> is
|
||||
"prefix_", API changes like the following occur:
|
||||
@@ -42,11 +55,16 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
jemalloc overlays the default malloc zone, but makes no attempt to actually
|
||||
replace the "malloc", "calloc", etc. symbols.
|
||||
|
||||
--without-export
|
||||
Don't export public APIs. This can be useful when building jemalloc as a
|
||||
static library, or to avoid exporting public APIs when using the zone
|
||||
allocator on OSX.
|
||||
|
||||
--with-private-namespace=<prefix>
|
||||
Prefix all library-private APIs with <prefix>. For shared libraries,
|
||||
Prefix all library-private APIs with <prefix>je_. For shared libraries,
|
||||
symbol visibility mechanisms prevent these symbols from being exported, but
|
||||
for static libraries, naming collisions are a real possibility. By
|
||||
default, the prefix is "" (empty string).
|
||||
default, <prefix> is empty, which results in a symbol prefix of je_ .
|
||||
|
||||
--with-install-suffix=<suffix>
|
||||
Append <suffix> to the base name of all installed files, such that multiple
|
||||
@@ -61,9 +79,28 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
--enable-debug
|
||||
Enable assertions and validation code. This incurs a substantial
|
||||
performance hit, but is very useful during application development.
|
||||
Implies --enable-ivsalloc.
|
||||
|
||||
--enable-stats
|
||||
Enable statistics gathering functionality. See the "opt.stats_print"
|
||||
--enable-code-coverage
|
||||
Enable code coverage support, for use during jemalloc test development.
|
||||
Additional testing targets are available if this option is enabled:
|
||||
|
||||
coverage
|
||||
coverage_unit
|
||||
coverage_integration
|
||||
coverage_stress
|
||||
|
||||
These targets do not clear code coverage results from previous runs, and
|
||||
there are interactions between the various coverage targets, so it is
|
||||
usually advisable to run 'make clean' between repeated code coverage runs.
|
||||
|
||||
--enable-ivsalloc
|
||||
Enable validation code, which verifies that pointers reside within
|
||||
jemalloc-owned chunks before dereferencing them. This incurs a substantial
|
||||
performance hit.
|
||||
|
||||
--disable-stats
|
||||
Disable statistics gathering functionality. See the "opt.stats_print"
|
||||
option documentation for usage details.
|
||||
|
||||
--enable-prof
|
||||
@@ -90,51 +127,54 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
Statically link against the specified libunwind.a rather than dynamically
|
||||
linking with -lunwind.
|
||||
|
||||
--disable-tiny
|
||||
Disable tiny (sub-quantum-sized) object support. Technically it is not
|
||||
legal for a malloc implementation to allocate objects with less than
|
||||
quantum alignment (8 or 16 bytes, depending on architecture), but in
|
||||
practice it never causes any problems if, for example, 4-byte allocations
|
||||
are 4-byte-aligned.
|
||||
|
||||
--disable-tcache
|
||||
Disable thread-specific caches for small objects. Objects are cached and
|
||||
released in bulk, thus reducing the total number of mutex operations. See
|
||||
the "opt.tcache" option for usage details.
|
||||
|
||||
--enable-swap
|
||||
Enable mmap()ed swap file support. When this feature is built in, it is
|
||||
possible to specify one or more files that act as backing store. This
|
||||
effectively allows for per application swap files.
|
||||
--enable-mremap
|
||||
Enable huge realloc() via mremap(2). mremap() is disabled by default
|
||||
because the flavor used is specific to Linux, which has a quirk in its
|
||||
virtual memory allocation algorithm that causes semi-permanent VM map holes
|
||||
under normal jemalloc operation.
|
||||
|
||||
--disable-munmap
|
||||
Disable virtual memory deallocation via munmap(2); instead keep track of
|
||||
the virtual memory for later use. munmap() is disabled by default (i.e.
|
||||
--disable-munmap is implied) on Linux, which has a quirk in its virtual
|
||||
memory allocation algorithm that causes semi-permanent VM map holes under
|
||||
normal jemalloc operation.
|
||||
|
||||
--enable-dss
|
||||
Enable support for page allocation/deallocation via sbrk(2), in addition to
|
||||
mmap(2).
|
||||
|
||||
--enable-fill
|
||||
Enable support for junk/zero filling of memory. See the "opt.junk"/
|
||||
"opt.zero" option documentation for usage details.
|
||||
--disable-fill
|
||||
Disable support for junk/zero filling of memory, quarantine, and redzones.
|
||||
See the "opt.junk", "opt.zero", "opt.quarantine", and "opt.redzone" option
|
||||
documentation for usage details.
|
||||
|
||||
--disable-valgrind
|
||||
Disable support for Valgrind.
|
||||
|
||||
--disable-experimental
|
||||
Disable support for the experimental API (*allocm()).
|
||||
|
||||
--disable-zone-allocator
|
||||
Disable zone allocator for Darwin. This means jemalloc won't be hooked as
|
||||
the default allocator on OSX/iOS.
|
||||
|
||||
--enable-utrace
|
||||
Enable utrace(2)-based allocation tracing. This feature is not broadly
|
||||
portable (FreeBSD has it, but Linux and OS X do not).
|
||||
|
||||
--enable-xmalloc
|
||||
Enable support for optional immediate termination due to out-of-memory
|
||||
errors, as is commonly implemented by "xmalloc" wrapper function for malloc.
|
||||
See the "opt.xmalloc" option documentation for usage details.
|
||||
|
||||
--enable-sysv
|
||||
Enable support for System V semantics, wherein malloc(0) returns NULL
|
||||
rather than a minimal allocation. See the "opt.sysv" option documentation
|
||||
for usage details.
|
||||
|
||||
--enable-dynamic-page-shift
|
||||
Under most conditions, the system page size never changes (usually 4KiB or
|
||||
8KiB, depending on architecture and configuration), and unless this option
|
||||
is enabled, jemalloc assumes that page size can safely be determined during
|
||||
configuration and hard-coded. Enabling dynamic page size determination has
|
||||
a measurable impact on performance, since the compiler is forced to load
|
||||
the page size from memory rather than embedding immediate values.
|
||||
|
||||
--disable-lazy-lock
|
||||
Disable code that wraps pthread_create() to detect when an application
|
||||
--enable-lazy-lock
|
||||
Enable code that wraps pthread_create() to detect when an application
|
||||
switches from single-threaded to multi-threaded mode, so that it can avoid
|
||||
mutex locking/unlocking operations while in single-threaded mode. In
|
||||
practice, this feature usually has little impact on performance unless
|
||||
@@ -181,11 +221,24 @@ PATH="?"
|
||||
|
||||
=== Advanced compilation =======================================================
|
||||
|
||||
To build only parts of jemalloc, use the following targets:
|
||||
|
||||
build_lib_shared
|
||||
build_lib_static
|
||||
build_lib
|
||||
build_doc_html
|
||||
build_doc_man
|
||||
build_doc
|
||||
|
||||
To install only parts of jemalloc, use the following targets:
|
||||
|
||||
install_bin
|
||||
install_include
|
||||
install_lib_shared
|
||||
install_lib_static
|
||||
install_lib
|
||||
install_doc_html
|
||||
install_doc_man
|
||||
install_doc
|
||||
|
||||
To clean up build results to varying degrees, use the following make targets:
|
||||
@@ -248,10 +301,6 @@ directory, issue configuration and build commands:
|
||||
|
||||
The manual page is generated in both html and roff formats. Any web browser
|
||||
can be used to view the html manual. The roff manual page can be formatted
|
||||
prior to installation via any of the following commands:
|
||||
prior to installation via the following command:
|
||||
|
||||
nroff -man -t doc/jemalloc.3
|
||||
|
||||
groff -man -t -Tps doc/jemalloc.3 | ps2pdf - doc/jemalloc.3.pdf
|
||||
|
||||
(cd doc; groff -man -man-ext -t -Thtml jemalloc.3 > jemalloc.3.html)
|
||||
|
||||
Vendored
+335
-156
@@ -17,130 +17,262 @@ INCLUDEDIR := $(DESTDIR)@INCLUDEDIR@
|
||||
LIBDIR := $(DESTDIR)@LIBDIR@
|
||||
DATADIR := $(DESTDIR)@DATADIR@
|
||||
MANDIR := $(DESTDIR)@MANDIR@
|
||||
srcroot := @srcroot@
|
||||
objroot := @objroot@
|
||||
abs_srcroot := @abs_srcroot@
|
||||
abs_objroot := @abs_objroot@
|
||||
|
||||
# Build parameters.
|
||||
CPPFLAGS := @CPPFLAGS@ -I@srcroot@include -I@objroot@include
|
||||
CPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include
|
||||
CFLAGS := @CFLAGS@
|
||||
ifeq (macho, @abi@)
|
||||
CFLAGS += -dynamic
|
||||
endif
|
||||
LDFLAGS := @LDFLAGS@
|
||||
EXTRA_LDFLAGS := @EXTRA_LDFLAGS@
|
||||
LIBS := @LIBS@
|
||||
RPATH_EXTRA := @RPATH_EXTRA@
|
||||
ifeq (macho, @abi@)
|
||||
SO := dylib
|
||||
WL_SONAME := dylib_install_name
|
||||
SO := @so@
|
||||
IMPORTLIB := @importlib@
|
||||
O := @o@
|
||||
A := @a@
|
||||
EXE := @exe@
|
||||
LIBPREFIX := @libprefix@
|
||||
REV := @rev@
|
||||
install_suffix := @install_suffix@
|
||||
ABI := @abi@
|
||||
XSLTPROC := @XSLTPROC@
|
||||
AUTOCONF := @AUTOCONF@
|
||||
_RPATH = @RPATH@
|
||||
RPATH = $(if $(1),$(call _RPATH,$(1)))
|
||||
cfghdrs_in := @cfghdrs_in@
|
||||
cfghdrs_out := @cfghdrs_out@
|
||||
cfgoutputs_in := @cfgoutputs_in@
|
||||
cfgoutputs_out := @cfgoutputs_out@
|
||||
enable_autogen := @enable_autogen@
|
||||
enable_code_coverage := @enable_code_coverage@
|
||||
enable_experimental := @enable_experimental@
|
||||
enable_zone_allocator := @enable_zone_allocator@
|
||||
DSO_LDFLAGS = @DSO_LDFLAGS@
|
||||
SOREV = @SOREV@
|
||||
PIC_CFLAGS = @PIC_CFLAGS@
|
||||
CTARGET = @CTARGET@
|
||||
LDTARGET = @LDTARGET@
|
||||
MKLIB = @MKLIB@
|
||||
AR = @AR@
|
||||
ARFLAGS = @ARFLAGS@
|
||||
CC_MM = @CC_MM@
|
||||
|
||||
ifeq (macho, $(ABI))
|
||||
TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH="$(objroot)lib"
|
||||
else
|
||||
SO := so
|
||||
WL_SONAME := soname
|
||||
endif
|
||||
REV := 1
|
||||
ifeq (macho, @abi@)
|
||||
TEST_LIBRARY_PATH := DYLD_FALLBACK_LIBRARY_PATH=@objroot@lib
|
||||
ifeq (pecoff, $(ABI))
|
||||
TEST_LIBRARY_PATH := PATH="$(PATH):$(objroot)lib"
|
||||
else
|
||||
TEST_LIBRARY_PATH :=
|
||||
endif
|
||||
endif
|
||||
|
||||
LIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix)
|
||||
|
||||
# Lists of files.
|
||||
BINS := @srcroot@bin/pprof
|
||||
CHDRS := @objroot@include/jemalloc/jemalloc@install_suffix@.h \
|
||||
@objroot@include/jemalloc/jemalloc_defs@install_suffix@.h
|
||||
CSRCS := @srcroot@src/jemalloc.c @srcroot@src/arena.c @srcroot@src/atomic.c \
|
||||
@srcroot@src/base.c @srcroot@src/bitmap.c @srcroot@src/chunk.c \
|
||||
@srcroot@src/chunk_dss.c @srcroot@src/chunk_mmap.c \
|
||||
@srcroot@src/chunk_swap.c @srcroot@src/ckh.c @srcroot@src/ctl.c \
|
||||
@srcroot@src/extent.c @srcroot@src/hash.c @srcroot@src/huge.c \
|
||||
@srcroot@src/mb.c @srcroot@src/mutex.c @srcroot@src/prof.c \
|
||||
@srcroot@src/rtree.c @srcroot@src/stats.c @srcroot@src/tcache.c
|
||||
ifeq (macho, @abi@)
|
||||
CSRCS += @srcroot@src/zone.c
|
||||
BINS := $(srcroot)bin/pprof $(objroot)bin/jemalloc.sh
|
||||
C_HDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h
|
||||
C_SRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c \
|
||||
$(srcroot)src/atomic.c $(srcroot)src/base.c $(srcroot)src/bitmap.c \
|
||||
$(srcroot)src/chunk.c $(srcroot)src/chunk_dss.c \
|
||||
$(srcroot)src/chunk_mmap.c $(srcroot)src/ckh.c $(srcroot)src/ctl.c \
|
||||
$(srcroot)src/extent.c $(srcroot)src/hash.c $(srcroot)src/huge.c \
|
||||
$(srcroot)src/mb.c $(srcroot)src/mutex.c $(srcroot)src/prof.c \
|
||||
$(srcroot)src/quarantine.c $(srcroot)src/rtree.c $(srcroot)src/stats.c \
|
||||
$(srcroot)src/tcache.c $(srcroot)src/util.c $(srcroot)src/tsd.c
|
||||
ifeq ($(enable_zone_allocator), 1)
|
||||
C_SRCS += $(srcroot)src/zone.c
|
||||
endif
|
||||
STATIC_LIBS := @objroot@lib/libjemalloc@install_suffix@.a
|
||||
DSOS := @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) \
|
||||
@objroot@lib/libjemalloc@install_suffix@.$(SO) \
|
||||
@objroot@lib/libjemalloc@install_suffix@_pic.a
|
||||
MAN3 := @objroot@doc/jemalloc@install_suffix@.3
|
||||
DOCS_XML := @objroot@doc/jemalloc@install_suffix@.xml
|
||||
DOCS_HTML := $(DOCS_XML:@objroot@%.xml=@srcroot@%.html)
|
||||
DOCS_MAN3 := $(DOCS_XML:@objroot@%.xml=@srcroot@%.3)
|
||||
ifeq ($(IMPORTLIB),$(SO))
|
||||
STATIC_LIBS := $(objroot)lib/$(LIBJEMALLOC).$(A)
|
||||
endif
|
||||
ifdef PIC_CFLAGS
|
||||
STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_pic.$(A)
|
||||
else
|
||||
STATIC_LIBS += $(objroot)lib/$(LIBJEMALLOC)_s.$(A)
|
||||
endif
|
||||
DSOS := $(objroot)lib/$(LIBJEMALLOC).$(SOREV)
|
||||
ifneq ($(SOREV),$(SO))
|
||||
DSOS += $(objroot)lib/$(LIBJEMALLOC).$(SO)
|
||||
endif
|
||||
MAN3 := $(objroot)doc/jemalloc$(install_suffix).3
|
||||
DOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml
|
||||
DOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.html)
|
||||
DOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.3)
|
||||
DOCS := $(DOCS_HTML) $(DOCS_MAN3)
|
||||
CTESTS := @srcroot@test/allocated.c @srcroot@test/allocm.c \
|
||||
@srcroot@test/bitmap.c @srcroot@test/mremap.c \
|
||||
@srcroot@test/posix_memalign.c @srcroot@test/rallocm.c \
|
||||
@srcroot@test/thread_arena.c
|
||||
C_TESTLIB_SRCS := $(srcroot)test/src/math.c $(srcroot)test/src/mtx.c \
|
||||
$(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \
|
||||
$(srcroot)test/src/thd.c
|
||||
C_UTIL_INTEGRATION_SRCS := $(srcroot)src/util.c
|
||||
TESTS_UNIT := $(srcroot)test/unit/bitmap.c \
|
||||
$(srcroot)test/unit/ckh.c \
|
||||
$(srcroot)test/unit/hash.c \
|
||||
$(srcroot)test/unit/junk.c \
|
||||
$(srcroot)test/unit/mallctl.c \
|
||||
$(srcroot)test/unit/math.c \
|
||||
$(srcroot)test/unit/mq.c \
|
||||
$(srcroot)test/unit/mtx.c \
|
||||
$(srcroot)test/unit/prof_accum.c \
|
||||
$(srcroot)test/unit/prof_gdump.c \
|
||||
$(srcroot)test/unit/prof_idump.c \
|
||||
$(srcroot)test/unit/ql.c \
|
||||
$(srcroot)test/unit/qr.c \
|
||||
$(srcroot)test/unit/quarantine.c \
|
||||
$(srcroot)test/unit/rb.c \
|
||||
$(srcroot)test/unit/rtree.c \
|
||||
$(srcroot)test/unit/SFMT.c \
|
||||
$(srcroot)test/unit/stats.c \
|
||||
$(srcroot)test/unit/tsd.c \
|
||||
$(srcroot)test/unit/util.c \
|
||||
$(srcroot)test/unit/zero.c
|
||||
TESTS_UNIT_AUX := $(srcroot)test/unit/prof_accum_a.c \
|
||||
$(srcroot)test/unit/prof_accum_b.c
|
||||
TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \
|
||||
$(srcroot)test/integration/allocated.c \
|
||||
$(srcroot)test/integration/mallocx.c \
|
||||
$(srcroot)test/integration/mremap.c \
|
||||
$(srcroot)test/integration/posix_memalign.c \
|
||||
$(srcroot)test/integration/rallocx.c \
|
||||
$(srcroot)test/integration/thread_arena.c \
|
||||
$(srcroot)test/integration/thread_tcache_enabled.c \
|
||||
$(srcroot)test/integration/xallocx.c
|
||||
ifeq ($(enable_experimental), 1)
|
||||
TESTS_INTEGRATION += $(srcroot)test/integration/allocm.c \
|
||||
$(srcroot)test/integration/MALLOCX_ARENA.c \
|
||||
$(srcroot)test/integration/rallocm.c
|
||||
endif
|
||||
TESTS_STRESS :=
|
||||
TESTS := $(TESTS_UNIT) $(TESTS_INTEGRATION) $(TESTS_STRESS)
|
||||
|
||||
.PHONY: all dist doc_html doc_man doc
|
||||
C_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
C_PIC_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.pic.$(O))
|
||||
C_JET_OBJS := $(C_SRCS:$(srcroot)%.c=$(objroot)%.jet.$(O))
|
||||
C_TESTLIB_UNIT_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.unit.$(O))
|
||||
C_TESTLIB_INTEGRATION_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))
|
||||
C_UTIL_INTEGRATION_OBJS := $(C_UTIL_INTEGRATION_SRCS:$(srcroot)%.c=$(objroot)%.integration.$(O))
|
||||
C_TESTLIB_STRESS_OBJS := $(C_TESTLIB_SRCS:$(srcroot)%.c=$(objroot)%.stress.$(O))
|
||||
C_TESTLIB_OBJS := $(C_TESTLIB_UNIT_OBJS) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(C_TESTLIB_STRESS_OBJS)
|
||||
|
||||
TESTS_UNIT_OBJS := $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_UNIT_AUX_OBJS := $(TESTS_UNIT_AUX:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_INTEGRATION_OBJS := $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_STRESS_OBJS := $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%.$(O))
|
||||
TESTS_OBJS := $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS) $(TESTS_INTEGRATION_OBJS) $(TESTS_STRESS_OBJS)
|
||||
|
||||
.PHONY: all dist build_doc_html build_doc_man build_doc
|
||||
.PHONY: install_bin install_include install_lib
|
||||
.PHONY: install_html install_man install_doc install
|
||||
.PHONY: install_doc_html install_doc_man install_doc install
|
||||
.PHONY: tests check clean distclean relclean
|
||||
|
||||
.SECONDARY : $(CTESTS:@srcroot@%.c=@objroot@%.o)
|
||||
.SECONDARY : $(TESTS_OBJS)
|
||||
|
||||
# Default target.
|
||||
all: $(DSOS) $(STATIC_LIBS)
|
||||
all: build_lib
|
||||
|
||||
dist: doc
|
||||
dist: build_doc
|
||||
|
||||
@srcroot@doc/%.html : @objroot@doc/%.xml @srcroot@doc/stylesheet.xsl @objroot@doc/html.xsl
|
||||
@XSLTPROC@ -o $@ @objroot@doc/html.xsl $<
|
||||
$(srcroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl
|
||||
$(XSLTPROC) -o $@ $(objroot)doc/html.xsl $<
|
||||
|
||||
@srcroot@doc/%.3 : @objroot@doc/%.xml @srcroot@doc/stylesheet.xsl @objroot@doc/manpages.xsl
|
||||
@XSLTPROC@ -o $@ @objroot@doc/manpages.xsl $<
|
||||
$(srcroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl
|
||||
$(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $<
|
||||
|
||||
doc_html: $(DOCS_HTML)
|
||||
doc_man: $(DOCS_MAN3)
|
||||
doc: $(DOCS)
|
||||
build_doc_html: $(DOCS_HTML)
|
||||
build_doc_man: $(DOCS_MAN3)
|
||||
build_doc: $(DOCS)
|
||||
|
||||
#
|
||||
# Include generated dependency files.
|
||||
#
|
||||
-include $(CSRCS:@srcroot@%.c=@objroot@%.d)
|
||||
-include $(CSRCS:@srcroot@%.c=@objroot@%.pic.d)
|
||||
-include $(CTESTS:@srcroot@%.c=@objroot@%.d)
|
||||
ifdef CC_MM
|
||||
-include $(C_OBJS:%.$(O)=%.d)
|
||||
-include $(C_PIC_OBJS:%.$(O)=%.d)
|
||||
-include $(C_JET_OBJS:%.$(O)=%.d)
|
||||
-include $(C_TESTLIB_OBJS:%.$(O)=%.d)
|
||||
-include $(TESTS_OBJS:%.$(O)=%.d)
|
||||
endif
|
||||
|
||||
@objroot@src/%.o: @srcroot@src/%.c
|
||||
$(C_OBJS): $(objroot)src/%.$(O): $(srcroot)src/%.c
|
||||
$(C_PIC_OBJS): $(objroot)src/%.pic.$(O): $(srcroot)src/%.c
|
||||
$(C_PIC_OBJS): CFLAGS += $(PIC_CFLAGS)
|
||||
$(C_JET_OBJS): $(objroot)src/%.jet.$(O): $(srcroot)src/%.c
|
||||
$(C_JET_OBJS): CFLAGS += -DJEMALLOC_JET
|
||||
$(C_TESTLIB_UNIT_OBJS): $(objroot)test/src/%.unit.$(O): $(srcroot)test/src/%.c
|
||||
$(C_TESTLIB_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST
|
||||
$(C_TESTLIB_INTEGRATION_OBJS): $(objroot)test/src/%.integration.$(O): $(srcroot)test/src/%.c
|
||||
$(C_TESTLIB_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST
|
||||
$(C_UTIL_INTEGRATION_OBJS): $(objroot)src/%.integration.$(O): $(srcroot)src/%.c
|
||||
$(C_TESTLIB_STRESS_OBJS): $(objroot)test/src/%.stress.$(O): $(srcroot)test/src/%.c
|
||||
$(C_TESTLIB_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST -DJEMALLOC_STRESS_TESTLIB
|
||||
$(C_TESTLIB_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include
|
||||
$(TESTS_UNIT_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST
|
||||
$(TESTS_UNIT_AUX_OBJS): CPPFLAGS += -DJEMALLOC_UNIT_TEST
|
||||
define make-unit-link-dep
|
||||
$(1): TESTS_UNIT_LINK_OBJS += $(2)
|
||||
$(1): $(2)
|
||||
endef
|
||||
$(foreach test, $(TESTS_UNIT:$(srcroot)test/unit/%.c=$(objroot)test/unit/%$(EXE)), $(eval $(call make-unit-link-dep,$(test),$(filter $(test:%=%_a.$(O)) $(test:%=%_b.$(O)),$(TESTS_UNIT_AUX_OBJS)))))
|
||||
$(TESTS_INTEGRATION_OBJS): CPPFLAGS += -DJEMALLOC_INTEGRATION_TEST
|
||||
$(TESTS_STRESS_OBJS): CPPFLAGS += -DJEMALLOC_STRESS_TEST
|
||||
$(TESTS_OBJS): $(objroot)test/%.$(O): $(srcroot)test/%.c
|
||||
$(TESTS_OBJS): CPPFLAGS += -I$(srcroot)test/include -I$(objroot)test/include
|
||||
ifneq ($(IMPORTLIB),$(SO))
|
||||
$(C_OBJS): CPPFLAGS += -DDLLEXPORT
|
||||
endif
|
||||
|
||||
ifndef CC_MM
|
||||
# Dependencies.
|
||||
HEADER_DIRS = $(srcroot)include/jemalloc/internal \
|
||||
$(objroot)include/jemalloc $(objroot)include/jemalloc/internal
|
||||
HEADERS = $(wildcard $(foreach dir,$(HEADER_DIRS),$(dir)/*.h))
|
||||
$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): $(HEADERS)
|
||||
$(TESTS_OBJS): $(objroot)test/unit/jemalloc_test.h
|
||||
endif
|
||||
|
||||
$(C_OBJS) $(C_PIC_OBJS) $(C_JET_OBJS) $(C_TESTLIB_OBJS) $(TESTS_OBJS): %.$(O):
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c $(CPPFLAGS) -o $@ $<
|
||||
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
|
||||
$(CC) $(CFLAGS) -c $(CPPFLAGS) $(CTARGET) $<
|
||||
ifdef CC_MM
|
||||
@$(CC) -MM $(CPPFLAGS) -MT $@ -o $(@:%.$(O)=%.d) $<
|
||||
endif
|
||||
|
||||
@objroot@src/%.pic.o: @srcroot@src/%.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -fPIC -DPIC -c $(CPPFLAGS) -o $@ $<
|
||||
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $(basename $@))))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.pic.o \2/g\" > $(@:%.o=%.d)"
|
||||
|
||||
%.$(SO) : %.$(SO).$(REV)
|
||||
ifneq ($(SOREV),$(SO))
|
||||
%.$(SO) : %.$(SOREV)
|
||||
@mkdir -p $(@D)
|
||||
ln -sf $(<F) $@
|
||||
|
||||
@objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) : $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
|
||||
@mkdir -p $(@D)
|
||||
$(CC) -shared -Wl,-$(WL_SONAME),$(@F) $(RPATH_EXTRA:%=@RPATH@%) -o $@ $+ $(LDFLAGS) $(LIBS)
|
||||
|
||||
@objroot@lib/libjemalloc@install_suffix@_pic.a : $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
|
||||
@mkdir -p $(@D)
|
||||
ar crus $@ $+
|
||||
|
||||
@objroot@lib/libjemalloc@install_suffix@.a : $(CSRCS:@srcroot@%.c=@objroot@%.o)
|
||||
@mkdir -p $(@D)
|
||||
ar crus $@ $+
|
||||
|
||||
@objroot@test/%.o: @srcroot@test/%.c
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(CFLAGS) -c $(CPPFLAGS) -I@objroot@test -o $@ $<
|
||||
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) -I@objroot@test $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
|
||||
|
||||
# Automatic dependency generation misses #include "*.c".
|
||||
@objroot@test/bitmap.o : @objroot@src/bitmap.o
|
||||
|
||||
@objroot@test/%: @objroot@test/%.o \
|
||||
@objroot@lib/libjemalloc@install_suffix@.$(SO)
|
||||
@mkdir -p $(@D)
|
||||
ifneq (@RPATH@, )
|
||||
$(CC) -o $@ $< @RPATH@@objroot@lib -L@objroot@lib -ljemalloc@install_suffix@ -lpthread
|
||||
else
|
||||
$(CC) -o $@ $< -L@objroot@lib -ljemalloc@install_suffix@ -lpthread
|
||||
endif
|
||||
|
||||
$(objroot)lib/$(LIBJEMALLOC).$(SOREV) : $(if $(PIC_CFLAGS),$(C_PIC_OBJS),$(C_OBJS))
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(DSO_LDFLAGS) $(call RPATH,$(RPATH_EXTRA)) $(LDTARGET) $+ $(LDFLAGS) $(LIBS) $(EXTRA_LDFLAGS)
|
||||
|
||||
$(objroot)lib/$(LIBJEMALLOC)_pic.$(A) : $(C_PIC_OBJS)
|
||||
$(objroot)lib/$(LIBJEMALLOC).$(A) : $(C_OBJS)
|
||||
$(objroot)lib/$(LIBJEMALLOC)_s.$(A) : $(C_OBJS)
|
||||
|
||||
$(STATIC_LIBS):
|
||||
@mkdir -p $(@D)
|
||||
$(AR) $(ARFLAGS)@AROUT@ $+
|
||||
|
||||
$(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(TESTS_UNIT_LINK_OBJS) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS)
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)
|
||||
|
||||
$(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(filter -lpthread,$(LIBS))) -lm $(EXTRA_LDFLAGS)
|
||||
|
||||
$(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB)
|
||||
@mkdir -p $(@D)
|
||||
$(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS)
|
||||
|
||||
build_lib_shared: $(DSOS)
|
||||
build_lib_static: $(STATIC_LIBS)
|
||||
build_lib: build_lib_shared build_lib_static
|
||||
|
||||
install_bin:
|
||||
install -d $(BINDIR)
|
||||
@for b in $(BINS); do \
|
||||
@@ -150,110 +282,157 @@ done
|
||||
|
||||
install_include:
|
||||
install -d $(INCLUDEDIR)/jemalloc
|
||||
@for h in $(CHDRS); do \
|
||||
@for h in $(C_HDRS); do \
|
||||
echo "install -m 644 $$h $(INCLUDEDIR)/jemalloc"; \
|
||||
install -m 644 $$h $(INCLUDEDIR)/jemalloc; \
|
||||
done
|
||||
|
||||
install_lib: $(DSOS) $(STATIC_LIBS)
|
||||
install_lib_shared: $(DSOS)
|
||||
install -d $(LIBDIR)
|
||||
install -m 755 @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR)
|
||||
ln -sf libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR)/libjemalloc@install_suffix@.$(SO)
|
||||
install -m 755 @objroot@lib/libjemalloc@install_suffix@_pic.a $(LIBDIR)
|
||||
install -m 755 @objroot@lib/libjemalloc@install_suffix@.a $(LIBDIR)
|
||||
install -m 755 $(objroot)lib/$(LIBJEMALLOC).$(SOREV) $(LIBDIR)
|
||||
ifneq ($(SOREV),$(SO))
|
||||
ln -sf $(LIBJEMALLOC).$(SOREV) $(LIBDIR)/$(LIBJEMALLOC).$(SO)
|
||||
endif
|
||||
|
||||
install_html:
|
||||
install -d $(DATADIR)/doc/jemalloc@install_suffix@
|
||||
@for d in $(DOCS_HTML); do \
|
||||
echo "install -m 644 $$d $(DATADIR)/doc/jemalloc@install_suffix@"; \
|
||||
install -m 644 $$d $(DATADIR)/doc/jemalloc@install_suffix@; \
|
||||
install_lib_static: $(STATIC_LIBS)
|
||||
install -d $(LIBDIR)
|
||||
@for l in $(STATIC_LIBS); do \
|
||||
echo "install -m 755 $$l $(LIBDIR)"; \
|
||||
install -m 755 $$l $(LIBDIR); \
|
||||
done
|
||||
|
||||
install_man:
|
||||
install_lib: install_lib_shared install_lib_static
|
||||
|
||||
install_doc_html:
|
||||
install -d $(DATADIR)/doc/jemalloc$(install_suffix)
|
||||
@for d in $(DOCS_HTML); do \
|
||||
echo "install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix)"; \
|
||||
install -m 644 $$d $(DATADIR)/doc/jemalloc$(install_suffix); \
|
||||
done
|
||||
|
||||
install_doc_man:
|
||||
install -d $(MANDIR)/man3
|
||||
@for d in $(DOCS_MAN3); do \
|
||||
echo "install -m 644 $$d $(MANDIR)/man3"; \
|
||||
install -m 644 $$d $(MANDIR)/man3; \
|
||||
done
|
||||
|
||||
install_doc: install_html install_man
|
||||
install_doc: install_doc_html install_doc_man
|
||||
|
||||
install: install_bin install_include install_lib install_doc
|
||||
|
||||
tests: $(CTESTS:@srcroot@%.c=@objroot@%)
|
||||
tests_unit: $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%$(EXE))
|
||||
tests_integration: $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%$(EXE))
|
||||
tests_stress: $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%$(EXE))
|
||||
tests: tests_unit tests_integration tests_stress
|
||||
|
||||
check: tests
|
||||
@mkdir -p @objroot@test
|
||||
@$(SHELL) -c 'total=0; \
|
||||
failures=0; \
|
||||
echo "========================================="; \
|
||||
for t in $(CTESTS:@srcroot@%.c=@objroot@%); do \
|
||||
total=`expr $$total + 1`; \
|
||||
/bin/echo -n "$${t} ... "; \
|
||||
$(TEST_LIBRARY_PATH) $${t} @abs_srcroot@ @abs_objroot@ \
|
||||
> @objroot@$${t}.out 2>&1; \
|
||||
if test -e "@srcroot@$${t}.exp"; then \
|
||||
diff -u @srcroot@$${t}.exp \
|
||||
@objroot@$${t}.out >/dev/null 2>&1; \
|
||||
fail=$$?; \
|
||||
if test "$${fail}" -eq "1" ; then \
|
||||
failures=`expr $${failures} + 1`; \
|
||||
echo "*** FAIL ***"; \
|
||||
else \
|
||||
echo "pass"; \
|
||||
fi; \
|
||||
else \
|
||||
echo "*** FAIL *** (.exp file is missing)"; \
|
||||
failures=`expr $${failures} + 1`; \
|
||||
fi; \
|
||||
done; \
|
||||
echo "========================================="; \
|
||||
echo "Failures: $${failures}/$${total}"'
|
||||
check_unit_dir:
|
||||
@mkdir -p $(objroot)test/unit
|
||||
check_integration_dir:
|
||||
@mkdir -p $(objroot)test/integration
|
||||
check_stress_dir:
|
||||
@mkdir -p $(objroot)test/stress
|
||||
check_dir: check_unit_dir check_integration_dir check_stress_dir
|
||||
|
||||
check_unit: tests_unit check_unit_dir
|
||||
$(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%)
|
||||
check_integration: tests_integration check_integration_dir
|
||||
$(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%)
|
||||
check_stress: tests_stress check_stress_dir
|
||||
$(SHELL) $(objroot)test/test.sh $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%)
|
||||
check: tests check_dir
|
||||
$(SHELL) $(objroot)test/test.sh $(TESTS:$(srcroot)%.c=$(objroot)%)
|
||||
|
||||
ifeq ($(enable_code_coverage), 1)
|
||||
coverage_unit: check_unit
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS)
|
||||
|
||||
coverage_integration: check_integration
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)
|
||||
|
||||
coverage_stress: check_stress
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress stress $(TESTS_STRESS_OBJS)
|
||||
|
||||
coverage: check
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)src integration $(C_UTIL_INTEGRATION_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src unit $(C_TESTLIB_UNIT_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/unit unit $(TESTS_UNIT_OBJS) $(TESTS_UNIT_AUX_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS)
|
||||
$(SHELL) $(srcroot)coverage.sh $(srcroot)test/stress integration $(TESTS_STRESS_OBJS)
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.o)
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.d)
|
||||
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.pic.d)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.o)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.d)
|
||||
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.out)
|
||||
rm -f $(C_OBJS)
|
||||
rm -f $(C_PIC_OBJS)
|
||||
rm -f $(C_JET_OBJS)
|
||||
rm -f $(C_TESTLIB_OBJS)
|
||||
rm -f $(C_OBJS:%.$(O)=%.d)
|
||||
rm -f $(C_OBJS:%.$(O)=%.gcda)
|
||||
rm -f $(C_OBJS:%.$(O)=%.gcno)
|
||||
rm -f $(C_PIC_OBJS:%.$(O)=%.d)
|
||||
rm -f $(C_PIC_OBJS:%.$(O)=%.gcda)
|
||||
rm -f $(C_PIC_OBJS:%.$(O)=%.gcno)
|
||||
rm -f $(C_JET_OBJS:%.$(O)=%.d)
|
||||
rm -f $(C_JET_OBJS:%.$(O)=%.gcda)
|
||||
rm -f $(C_JET_OBJS:%.$(O)=%.gcno)
|
||||
rm -f $(C_TESTLIB_OBJS:%.$(O)=%.d)
|
||||
rm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcda)
|
||||
rm -f $(C_TESTLIB_OBJS:%.$(O)=%.gcno)
|
||||
rm -f $(TESTS_OBJS:%.$(O)=%$(EXE))
|
||||
rm -f $(TESTS_OBJS)
|
||||
rm -f $(TESTS_OBJS:%.$(O)=%.d)
|
||||
rm -f $(TESTS_OBJS:%.$(O)=%.gcda)
|
||||
rm -f $(TESTS_OBJS:%.$(O)=%.gcno)
|
||||
rm -f $(TESTS_OBJS:%.$(O)=%.out)
|
||||
rm -f $(DSOS) $(STATIC_LIBS)
|
||||
rm -f $(objroot)*.gcov.*
|
||||
|
||||
distclean: clean
|
||||
rm -rf @objroot@autom4te.cache
|
||||
rm -f @objroot@config.log
|
||||
rm -f @objroot@config.status
|
||||
rm -f @objroot@config.stamp
|
||||
rm -f @cfghdrs_out@
|
||||
rm -f @cfgoutputs_out@
|
||||
rm -rf $(objroot)autom4te.cache
|
||||
rm -f $(objroot)bin/jemalloc.sh
|
||||
rm -f $(objroot)config.log
|
||||
rm -f $(objroot)config.status
|
||||
rm -f $(objroot)config.stamp
|
||||
rm -f $(cfghdrs_out)
|
||||
rm -f $(cfgoutputs_out)
|
||||
|
||||
relclean: distclean
|
||||
rm -f @objroot@configure
|
||||
rm -f @srcroot@VERSION
|
||||
rm -f $(objroot)configure
|
||||
rm -f $(srcroot)VERSION
|
||||
rm -f $(DOCS_HTML)
|
||||
rm -f $(DOCS_MAN3)
|
||||
|
||||
#===============================================================================
|
||||
# Re-configuration rules.
|
||||
|
||||
ifeq (@enable_autogen@, 1)
|
||||
@srcroot@configure : @srcroot@configure.ac
|
||||
cd ./@srcroot@ && @AUTOCONF@
|
||||
ifeq ($(enable_autogen), 1)
|
||||
$(srcroot)configure : $(srcroot)configure.ac
|
||||
cd ./$(srcroot) && $(AUTOCONF)
|
||||
|
||||
@objroot@config.status : @srcroot@configure
|
||||
./@objroot@config.status --recheck
|
||||
$(objroot)config.status : $(srcroot)configure
|
||||
./$(objroot)config.status --recheck
|
||||
|
||||
@srcroot@config.stamp.in : @srcroot@configure.ac
|
||||
echo stamp > @srcroot@config.stamp.in
|
||||
$(srcroot)config.stamp.in : $(srcroot)configure.ac
|
||||
echo stamp > $(srcroot)config.stamp.in
|
||||
|
||||
@objroot@config.stamp : @cfgoutputs_in@ @cfghdrs_in@ @srcroot@configure
|
||||
./@objroot@config.status
|
||||
$(objroot)config.stamp : $(cfgoutputs_in) $(cfghdrs_in) $(srcroot)configure
|
||||
./$(objroot)config.status
|
||||
@touch $@
|
||||
|
||||
# There must be some action in order for make to re-read Makefile when it is
|
||||
# out of date.
|
||||
@cfgoutputs_out@ @cfghdrs_out@ : @objroot@config.stamp
|
||||
$(cfgoutputs_out) $(cfghdrs_out) : $(objroot)config.stamp
|
||||
@true
|
||||
endif
|
||||
|
||||
Vendored
+11
-7
@@ -1,10 +1,14 @@
|
||||
jemalloc is a general-purpose scalable concurrent malloc(3) implementation.
|
||||
This distribution is a stand-alone "portable" implementation that currently
|
||||
targets Linux and Apple OS X. jemalloc is included as the default allocator in
|
||||
the FreeBSD and NetBSD operating systems, and it is used by the Mozilla Firefox
|
||||
web browser on Microsoft Windows-related platforms. Depending on your needs,
|
||||
one of the other divergent versions may suit your needs better than this
|
||||
distribution.
|
||||
jemalloc is a general purpose malloc(3) implementation that emphasizes
|
||||
fragmentation avoidance and scalable concurrency support. jemalloc first came
|
||||
into use as the FreeBSD libc allocator in 2005, and since then it has found its
|
||||
way into numerous applications that rely on its predictable behavior. In 2010
|
||||
jemalloc development efforts broadened to include developer support features
|
||||
such as heap profiling, Valgrind integration, and extensive monitoring/tuning
|
||||
hooks. Modern jemalloc releases continue to be integrated back into FreeBSD,
|
||||
and therefore versatility remains critical. Ongoing development efforts trend
|
||||
toward making jemalloc among the best allocators for a broad range of demanding
|
||||
applications, and eliminating/mitigating weaknesses that have practical
|
||||
repercussions for real world applications.
|
||||
|
||||
The COPYING file contains copyright and licensing information.
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
2.2.5-0-gfc1bb70e5f0d9a58b39efa39cc549b5af5104760
|
||||
3.6.0-0-g46c0af68bd248b04df75e4f92d5fb804c3d75340
|
||||
|
||||
Vendored
-17
@@ -1,17 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
for i in autoconf; do
|
||||
echo "$i"
|
||||
$i
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error $? in $i"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "./configure --enable-autogen $@"
|
||||
./configure --enable-autogen $@
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error $? in ./configure"
|
||||
exit 1
|
||||
fi
|
||||
Vendored
+674
-195
File diff suppressed because it is too large
Load Diff
Vendored
+607
-505
File diff suppressed because it is too large
Load Diff
Vendored
Vendored
+368
-124
@@ -1,42 +1,40 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2004-02-23'
|
||||
timestamp='2013-10-01'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
# the same distribution terms that you use for the rest of that
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
|
||||
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
# that are meaningful with *any* GNU software.
|
||||
@@ -70,8 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Copyright 1992-2013 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -83,11 +80,11 @@ Try \`$me --help' for more information."
|
||||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
--time-stamp | --time* | -t )
|
||||
echo "$timestamp" ; exit 0 ;;
|
||||
echo "$timestamp" ; exit ;;
|
||||
--version | -v )
|
||||
echo "$version" ; exit 0 ;;
|
||||
echo "$version" ; exit ;;
|
||||
--help | --h* | -h )
|
||||
echo "$usage"; exit 0 ;;
|
||||
echo "$usage"; exit ;;
|
||||
-- ) # Stop option processing
|
||||
shift; break ;;
|
||||
- ) # Use stdin as input.
|
||||
@@ -99,7 +96,7 @@ while test $# -gt 0 ; do
|
||||
*local*)
|
||||
# First pass through any local machine types.
|
||||
echo $1
|
||||
exit 0;;
|
||||
exit ;;
|
||||
|
||||
* )
|
||||
break ;;
|
||||
@@ -118,11 +115,18 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
|
||||
kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
android-linux)
|
||||
os=-linux-android
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
||||
;;
|
||||
*)
|
||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||
if [ $basic_machine != $1 ]
|
||||
@@ -145,10 +149,13 @@ case $os in
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis)
|
||||
-apple | -axis | -knuth | -cray | -microblaze*)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-bluegene*)
|
||||
os=-cnk
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
basic_machine=$1
|
||||
@@ -163,13 +170,17 @@ case $os in
|
||||
os=-chorusos
|
||||
basic_machine=$1
|
||||
;;
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
basic_machine=$1
|
||||
;;
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
-sco6)
|
||||
os=-sco5v6
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5)
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
@@ -186,6 +197,10 @@ case $os in
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5v6*)
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco*)
|
||||
os=-sco3.2v2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
@@ -203,6 +218,12 @@ case $os in
|
||||
-isc*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-lynx*178)
|
||||
os=-lynxos178
|
||||
;;
|
||||
-lynx*5)
|
||||
os=-lynxos5
|
||||
;;
|
||||
-lynx*)
|
||||
os=-lynxos
|
||||
;;
|
||||
@@ -227,57 +248,107 @@ case $basic_machine in
|
||||
# Some are omitted here because they have special meanings below.
|
||||
1750a | 580 \
|
||||
| a29k \
|
||||
| aarch64 | aarch64_be \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||
| c4x | clipper \
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| epiphany \
|
||||
| fido | fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| m32r | m68000 | m68k | m88k | mcore \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
| mips64vr | mips64vrel \
|
||||
| mips64octeon | mips64octeonel \
|
||||
| mips64orion | mips64orionel \
|
||||
| mips64r5900 | mips64r5900el \
|
||||
| mips64vr | mips64vrel \
|
||||
| mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr4300 | mips64vr4300el \
|
||||
| mips64vr5000 | mips64vr5000el \
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipsr5900 | mipsr5900el \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| openrisc | or32 \
|
||||
| open8 \
|
||||
| or1k | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| rl78 | rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu \
|
||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| we32k \
|
||||
| x86 | xscale | xstormy16 | xtensa \
|
||||
| z8k)
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
# Motorola 68HC11/12.
|
||||
c54x)
|
||||
basic_machine=tic54x-unknown
|
||||
;;
|
||||
c55x)
|
||||
basic_machine=tic55x-unknown
|
||||
;;
|
||||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||
;;
|
||||
ms1)
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
strongarm | thumb | xscale)
|
||||
basic_machine=arm-unknown
|
||||
;;
|
||||
xgate)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
xscaleeb)
|
||||
basic_machine=armeb-unknown
|
||||
;;
|
||||
|
||||
xscaleel)
|
||||
basic_machine=armel-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
@@ -293,59 +364,83 @@ case $basic_machine in
|
||||
# Recognize the basic CPU types with company name.
|
||||
580-* \
|
||||
| a29k-* \
|
||||
| aarch64-* | aarch64_be-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* \
|
||||
| bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | cydra-* \
|
||||
| avr-* | avr32-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| m32r-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | mcore-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||
| microblaze-* | microblazeel-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
| mips64vr-* | mips64vrel-* \
|
||||
| mips64octeon-* | mips64octeonel-* \
|
||||
| mips64orion-* | mips64orionel-* \
|
||||
| mips64r5900-* | mips64r5900el-* \
|
||||
| mips64vr-* | mips64vrel-* \
|
||||
| mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* \
|
||||
| mips64vr5000-* | mips64vr5000el-* \
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipsr5900-* | mipsr5900el-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
|
||||
| nds32-* | nds32le-* | nds32be-* \
|
||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
||||
| xtensa-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
| z8k-* | z80-*)
|
||||
;;
|
||||
# Recognize the basic CPU types without company name, with glob match.
|
||||
xtensa*)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
@@ -363,7 +458,7 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
@@ -409,6 +504,10 @@ case $basic_machine in
|
||||
basic_machine=m68k-apollo
|
||||
os=-bsd
|
||||
;;
|
||||
aros)
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -417,10 +516,35 @@ case $basic_machine in
|
||||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
blackfin)
|
||||
basic_machine=bfin-unknown
|
||||
os=-linux
|
||||
;;
|
||||
blackfin-*)
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
bluegene*)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-cnk
|
||||
;;
|
||||
c54x-*)
|
||||
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c55x-*)
|
||||
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c6x-*)
|
||||
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cegcc)
|
||||
basic_machine=arm-unknown
|
||||
os=-cegcc
|
||||
;;
|
||||
convex-c1)
|
||||
basic_machine=c1-convex
|
||||
os=-bsd
|
||||
@@ -445,13 +569,20 @@ case $basic_machine in
|
||||
basic_machine=j90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cr16c)
|
||||
basic_machine=cr16c-unknown
|
||||
craynv)
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16 | cr16-*)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
basic_machine=m68k-crds
|
||||
;;
|
||||
crisv32 | crisv32-* | etraxfs*)
|
||||
basic_machine=crisv32-axis
|
||||
;;
|
||||
cris | cris-* | etrax*)
|
||||
basic_machine=cris-axis
|
||||
;;
|
||||
@@ -481,6 +612,14 @@ case $basic_machine in
|
||||
basic_machine=m88k-motorola
|
||||
os=-sysv3
|
||||
;;
|
||||
dicos)
|
||||
basic_machine=i686-pc
|
||||
os=-dicos
|
||||
;;
|
||||
djgpp)
|
||||
basic_machine=i586-pc
|
||||
os=-msdosdjgpp
|
||||
;;
|
||||
dpx20 | dpx20-*)
|
||||
basic_machine=rs6000-bull
|
||||
os=-bosx
|
||||
@@ -592,7 +731,6 @@ case $basic_machine in
|
||||
i370-ibm* | ibm*)
|
||||
basic_machine=i370-ibm
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i*86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
@@ -631,6 +769,14 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
;;
|
||||
m68knommu-*)
|
||||
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
m88k-omron*)
|
||||
basic_machine=m88k-omron
|
||||
;;
|
||||
@@ -642,10 +788,21 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze*)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-mingw64
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
basic_machine=arm-unknown
|
||||
os=-mingw32ce
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
@@ -659,10 +816,6 @@ case $basic_machine in
|
||||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
mmix*)
|
||||
basic_machine=mmix-knuth
|
||||
os=-mmixware
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
@@ -675,10 +828,21 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
;;
|
||||
ms1-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
msys)
|
||||
basic_machine=i686-pc
|
||||
os=-msys
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
nacl)
|
||||
basic_machine=le32-unknown
|
||||
os=-nacl
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
@@ -743,9 +907,11 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
nv1)
|
||||
basic_machine=nv1-cray
|
||||
os=-unicosmp
|
||||
neo-tandem)
|
||||
basic_machine=neo-tandem
|
||||
;;
|
||||
nse-tandem)
|
||||
basic_machine=nse-tandem
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
@@ -754,9 +920,8 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
or32 | or32-*)
|
||||
openrisc | openrisc-*)
|
||||
basic_machine=or32-unknown
|
||||
os=-coff
|
||||
;;
|
||||
os400)
|
||||
basic_machine=powerpc-ibm
|
||||
@@ -778,6 +943,14 @@ case $basic_machine in
|
||||
basic_machine=i860-intel
|
||||
os=-osf
|
||||
;;
|
||||
parisc)
|
||||
basic_machine=hppa-unknown
|
||||
os=-linux
|
||||
;;
|
||||
parisc-*)
|
||||
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
pbd)
|
||||
basic_machine=sparc-tti
|
||||
;;
|
||||
@@ -787,6 +960,12 @@ case $basic_machine in
|
||||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pc98)
|
||||
basic_machine=i386-pc
|
||||
;;
|
||||
pc98-*)
|
||||
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
@@ -816,9 +995,10 @@ case $basic_machine in
|
||||
;;
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
ppc | ppcbe) basic_machine=powerpc-unknown
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
@@ -843,6 +1023,14 @@ case $basic_machine in
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos | rdos64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rdos32)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rom68k)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
@@ -869,6 +1057,10 @@ case $basic_machine in
|
||||
sb1el)
|
||||
basic_machine=mipsisa64sb1el-unknown
|
||||
;;
|
||||
sde)
|
||||
basic_machine=mipsisa32-sde
|
||||
os=-elf
|
||||
;;
|
||||
sei)
|
||||
basic_machine=mips-sei
|
||||
os=-seiux
|
||||
@@ -880,6 +1072,9 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh5el)
|
||||
basic_machine=sh5le-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
@@ -901,6 +1096,9 @@ case $basic_machine in
|
||||
basic_machine=i860-stratus
|
||||
os=-sysv4
|
||||
;;
|
||||
strongarm-* | thumb-*)
|
||||
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
;;
|
||||
@@ -957,17 +1155,9 @@ case $basic_machine in
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
tile*)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
@@ -1029,9 +1219,16 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
xbox)
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
xscale-* | xscalee[bl]-*)
|
||||
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
@@ -1040,6 +1237,10 @@ case $basic_machine in
|
||||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
;;
|
||||
z80-*-coff)
|
||||
basic_machine=z80-unknown
|
||||
os=-sim
|
||||
;;
|
||||
none)
|
||||
basic_machine=none-none
|
||||
os=-none
|
||||
@@ -1059,6 +1260,9 @@ case $basic_machine in
|
||||
romp)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
mmix)
|
||||
basic_machine=mmix-knuth
|
||||
;;
|
||||
rs6000)
|
||||
basic_machine=rs6000-ibm
|
||||
;;
|
||||
@@ -1075,13 +1279,10 @@ case $basic_machine in
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparc | sparcv9 | sparcv9b)
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
@@ -1125,9 +1326,12 @@ esac
|
||||
if [ x"$os" != x"" ]
|
||||
then
|
||||
case $os in
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-auroraux)
|
||||
os=-auroraux
|
||||
;;
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
@@ -1148,26 +1352,31 @@ case $os in
|
||||
# Each alternative MUST END IN A *, to match a version number.
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* \
|
||||
| -aos* | -aros* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1185,7 +1394,7 @@ case $os in
|
||||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
@@ -1206,7 +1415,7 @@ case $os in
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
@@ -1255,7 +1464,7 @@ case $os in
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
@@ -1291,8 +1500,13 @@ case $os in
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
@@ -1316,6 +1530,12 @@ else
|
||||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
score-*)
|
||||
os=-elf
|
||||
;;
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
os=-riscix1.2
|
||||
;;
|
||||
@@ -1325,9 +1545,24 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c8051-*)
|
||||
os=-elf
|
||||
;;
|
||||
hexagon-*)
|
||||
os=-elf
|
||||
;;
|
||||
tic54x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic55x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic6x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
@@ -1346,19 +1581,22 @@ case $basic_machine in
|
||||
;;
|
||||
m68000-sun)
|
||||
os=-sunos3
|
||||
# This also exists in the configure program, but was not the
|
||||
# default.
|
||||
# os=-sunos4
|
||||
;;
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-*)
|
||||
os=-elf
|
||||
;;
|
||||
or1k-*)
|
||||
os=-elf
|
||||
;;
|
||||
or32-*)
|
||||
os=-coff
|
||||
;;
|
||||
@@ -1371,9 +1609,15 @@ case $basic_machine in
|
||||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-haiku)
|
||||
os=-haiku
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
os=-proelf
|
||||
;;
|
||||
@@ -1476,7 +1720,7 @@ case $basic_machine in
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
-cnk*|-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
@@ -1539,7 +1783,7 @@ case $basic_machine in
|
||||
esac
|
||||
|
||||
echo $basic_machine$os
|
||||
exit 0
|
||||
exit
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
|
||||
Vendored
+2625
-1077
File diff suppressed because it is too large
Load Diff
Vendored
+786
-237
File diff suppressed because it is too large
Load Diff
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
objdir=$1
|
||||
suffix=$2
|
||||
shift 2
|
||||
objs=$@
|
||||
|
||||
gcov -b -p -f -o "${objdir}" ${objs}
|
||||
|
||||
# Move gcov outputs so that subsequent gcov invocations won't clobber results
|
||||
# for the same sources with different compilation flags.
|
||||
for f in `find . -maxdepth 1 -type f -name '*.gcov'` ; do
|
||||
mv "${f}" "${f}.${suffix}"
|
||||
done
|
||||
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:import href="@XSLROOT@/html/docbook.xsl"/>
|
||||
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
|
||||
</xsl:stylesheet>
|
||||
Vendored
+465
-310
File diff suppressed because it is too large
Load Diff
Vendored
+489
-507
File diff suppressed because one or more lines are too long
Vendored
+657
-592
File diff suppressed because it is too large
Load Diff
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:import href="@XSLROOT@/manpages/docbook.xsl"/>
|
||||
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
|
||||
</xsl:stylesheet>
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:param name="funcsynopsis.style">ansi</xsl:param>
|
||||
<xsl:param name="function.parens" select="1"/>
|
||||
<xsl:template match="mallctl">
|
||||
"<xsl:call-template name="inline.monoseq"/>"
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
+628
-308
File diff suppressed because it is too large
Load Diff
-169
@@ -1,169 +0,0 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
#define atomic_read_uint64(p) atomic_add_uint64(p, 0)
|
||||
#define atomic_read_uint32(p) atomic_add_uint32(p, 0)
|
||||
|
||||
#if (LG_SIZEOF_PTR == 3)
|
||||
# define atomic_read_z(p) \
|
||||
(size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)0)
|
||||
# define atomic_add_z(p, x) \
|
||||
(size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x)
|
||||
# define atomic_sub_z(p, x) \
|
||||
(size_t)atomic_sub_uint64((uint64_t *)p, (uint64_t)x)
|
||||
#elif (LG_SIZEOF_PTR == 2)
|
||||
# define atomic_read_z(p) \
|
||||
(size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)0)
|
||||
# define atomic_add_z(p, x) \
|
||||
(size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x)
|
||||
# define atomic_sub_z(p, x) \
|
||||
(size_t)atomic_sub_uint32((uint32_t *)p, (uint32_t)x)
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
uint64_t atomic_add_uint64(uint64_t *p, uint64_t x);
|
||||
uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x);
|
||||
uint32_t atomic_add_uint32(uint32_t *p, uint32_t x);
|
||||
uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))
|
||||
/******************************************************************************/
|
||||
/* 64-bit operations. */
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
|
||||
JEMALLOC_INLINE uint64_t
|
||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
|
||||
return (__sync_add_and_fetch(p, x));
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint64_t
|
||||
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
|
||||
return (__sync_sub_and_fetch(p, x));
|
||||
}
|
||||
#elif (defined(JEMALLOC_OSATOMIC))
|
||||
JEMALLOC_INLINE uint64_t
|
||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
|
||||
return (OSAtomicAdd64((int64_t)x, (int64_t *)p));
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint64_t
|
||||
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
|
||||
return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));
|
||||
}
|
||||
#elif (defined(__amd64_) || defined(__x86_64__))
|
||||
JEMALLOC_INLINE uint64_t
|
||||
atomic_add_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
|
||||
asm volatile (
|
||||
"lock; xaddq %0, %1;"
|
||||
: "+r" (x), "=m" (*p) /* Outputs. */
|
||||
: "m" (*p) /* Inputs. */
|
||||
);
|
||||
|
||||
return (x);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint64_t
|
||||
atomic_sub_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
|
||||
x = (uint64_t)(-(int64_t)x);
|
||||
asm volatile (
|
||||
"lock; xaddq %0, %1;"
|
||||
: "+r" (x), "=m" (*p) /* Outputs. */
|
||||
: "m" (*p) /* Inputs. */
|
||||
);
|
||||
|
||||
return (x);
|
||||
}
|
||||
#else
|
||||
# if (LG_SIZEOF_PTR == 3)
|
||||
# error "Missing implementation for 64-bit atomic operations"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* 32-bit operations. */
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
|
||||
JEMALLOC_INLINE uint32_t
|
||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
|
||||
return (__sync_add_and_fetch(p, x));
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint32_t
|
||||
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
|
||||
return (__sync_sub_and_fetch(p, x));
|
||||
}
|
||||
#elif (defined(JEMALLOC_OSATOMIC))
|
||||
JEMALLOC_INLINE uint32_t
|
||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
|
||||
return (OSAtomicAdd32((int32_t)x, (int32_t *)p));
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint32_t
|
||||
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
|
||||
return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));
|
||||
}
|
||||
#elif (defined(__i386__) || defined(__amd64_) || defined(__x86_64__))
|
||||
JEMALLOC_INLINE uint32_t
|
||||
atomic_add_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
|
||||
asm volatile (
|
||||
"lock; xaddl %0, %1;"
|
||||
: "+r" (x), "=m" (*p) /* Outputs. */
|
||||
: "m" (*p) /* Inputs. */
|
||||
);
|
||||
|
||||
return (x);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint32_t
|
||||
atomic_sub_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
|
||||
x = (uint32_t)(-(int32_t)x);
|
||||
asm volatile (
|
||||
"lock; xaddl %0, %1;"
|
||||
: "+r" (x), "=m" (*p) /* Outputs. */
|
||||
: "m" (*p) /* Inputs. */
|
||||
);
|
||||
|
||||
return (x);
|
||||
}
|
||||
#else
|
||||
# error "Missing implementation for 32-bit atomic operations"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
extern malloc_mutex_t base_mtx;
|
||||
|
||||
void *base_alloc(size_t size);
|
||||
extent_node_t *base_node_alloc(void);
|
||||
void base_node_dealloc(extent_node_t *node);
|
||||
bool base_boot(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
-184
@@ -1,184 +0,0 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */
|
||||
#define LG_BITMAP_MAXBITS LG_RUN_MAXREGS
|
||||
|
||||
typedef struct bitmap_level_s bitmap_level_t;
|
||||
typedef struct bitmap_info_s bitmap_info_t;
|
||||
typedef unsigned long bitmap_t;
|
||||
#define LG_SIZEOF_BITMAP LG_SIZEOF_LONG
|
||||
|
||||
/* Number of bits per group. */
|
||||
#define LG_BITMAP_GROUP_NBITS (LG_SIZEOF_BITMAP + 3)
|
||||
#define BITMAP_GROUP_NBITS (ZU(1) << LG_BITMAP_GROUP_NBITS)
|
||||
#define BITMAP_GROUP_NBITS_MASK (BITMAP_GROUP_NBITS-1)
|
||||
|
||||
/* Maximum number of levels possible. */
|
||||
#define BITMAP_MAX_LEVELS \
|
||||
(LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP) \
|
||||
+ !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP)
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
struct bitmap_level_s {
|
||||
/* Offset of this level's groups within the array of groups. */
|
||||
size_t group_offset;
|
||||
};
|
||||
|
||||
struct bitmap_info_s {
|
||||
/* Logical number of bits in bitmap (stored at bottom level). */
|
||||
size_t nbits;
|
||||
|
||||
/* Number of levels necessary for nbits. */
|
||||
unsigned nlevels;
|
||||
|
||||
/*
|
||||
* Only the first (nlevels+1) elements are used, and levels are ordered
|
||||
* bottom to top (e.g. the bottom level is stored in levels[0]).
|
||||
*/
|
||||
bitmap_level_t levels[BITMAP_MAX_LEVELS+1];
|
||||
};
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
void bitmap_info_init(bitmap_info_t *binfo, size_t nbits);
|
||||
size_t bitmap_info_ngroups(const bitmap_info_t *binfo);
|
||||
size_t bitmap_size(size_t nbits);
|
||||
void bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
bool bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo);
|
||||
bool bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);
|
||||
void bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);
|
||||
size_t bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo);
|
||||
void bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_BITMAP_C_))
|
||||
JEMALLOC_INLINE bool
|
||||
bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo)
|
||||
{
|
||||
unsigned rgoff = binfo->levels[binfo->nlevels].group_offset - 1;
|
||||
bitmap_t rg = bitmap[rgoff];
|
||||
/* The bitmap is full iff the root group is 0. */
|
||||
return (rg == 0);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE bool
|
||||
bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)
|
||||
{
|
||||
size_t goff;
|
||||
bitmap_t g;
|
||||
|
||||
assert(bit < binfo->nbits);
|
||||
goff = bit >> LG_BITMAP_GROUP_NBITS;
|
||||
g = bitmap[goff];
|
||||
return (!(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))));
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)
|
||||
{
|
||||
size_t goff;
|
||||
bitmap_t *gp;
|
||||
bitmap_t g;
|
||||
|
||||
assert(bit < binfo->nbits);
|
||||
assert(bitmap_get(bitmap, binfo, bit) == false);
|
||||
goff = bit >> LG_BITMAP_GROUP_NBITS;
|
||||
gp = &bitmap[goff];
|
||||
g = *gp;
|
||||
assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));
|
||||
g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
|
||||
*gp = g;
|
||||
assert(bitmap_get(bitmap, binfo, bit));
|
||||
/* Propagate group state transitions up the tree. */
|
||||
if (g == 0) {
|
||||
unsigned i;
|
||||
for (i = 1; i < binfo->nlevels; i++) {
|
||||
bit = goff;
|
||||
goff = bit >> LG_BITMAP_GROUP_NBITS;
|
||||
gp = &bitmap[binfo->levels[i].group_offset + goff];
|
||||
g = *gp;
|
||||
assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)));
|
||||
g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
|
||||
*gp = g;
|
||||
if (g != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sfu: set first unset. */
|
||||
JEMALLOC_INLINE size_t
|
||||
bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo)
|
||||
{
|
||||
size_t bit;
|
||||
bitmap_t g;
|
||||
unsigned i;
|
||||
|
||||
assert(bitmap_full(bitmap, binfo) == false);
|
||||
|
||||
i = binfo->nlevels - 1;
|
||||
g = bitmap[binfo->levels[i].group_offset];
|
||||
bit = ffsl(g) - 1;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
g = bitmap[binfo->levels[i].group_offset + bit];
|
||||
bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffsl(g) - 1);
|
||||
}
|
||||
|
||||
bitmap_set(bitmap, binfo, bit);
|
||||
return (bit);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit)
|
||||
{
|
||||
size_t goff;
|
||||
bitmap_t *gp;
|
||||
bitmap_t g;
|
||||
bool propagate;
|
||||
|
||||
assert(bit < binfo->nbits);
|
||||
assert(bitmap_get(bitmap, binfo, bit));
|
||||
goff = bit >> LG_BITMAP_GROUP_NBITS;
|
||||
gp = &bitmap[goff];
|
||||
g = *gp;
|
||||
propagate = (g == 0);
|
||||
assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) == 0);
|
||||
g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
|
||||
*gp = g;
|
||||
assert(bitmap_get(bitmap, binfo, bit) == false);
|
||||
/* Propagate group state transitions up the tree. */
|
||||
if (propagate) {
|
||||
unsigned i;
|
||||
for (i = 1; i < binfo->nlevels; i++) {
|
||||
bit = goff;
|
||||
goff = bit >> LG_BITMAP_GROUP_NBITS;
|
||||
gp = &bitmap[binfo->levels[i].group_offset + goff];
|
||||
g = *gp;
|
||||
propagate = (g == 0);
|
||||
assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)))
|
||||
== 0);
|
||||
g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK);
|
||||
*gp = g;
|
||||
if (propagate == false)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
+7
-9
@@ -28,20 +28,14 @@
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
extern size_t opt_lg_chunk;
|
||||
#ifdef JEMALLOC_SWAP
|
||||
extern bool opt_overcommit;
|
||||
#endif
|
||||
extern const char *opt_dss;
|
||||
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
/* Protects stats_chunks; currently not used for any other purpose. */
|
||||
extern malloc_mutex_t chunks_mtx;
|
||||
/* Chunk statistics. */
|
||||
extern chunk_stats_t stats_chunks;
|
||||
#endif
|
||||
|
||||
#ifdef JEMALLOC_IVSALLOC
|
||||
extern rtree_t *chunks_rtree;
|
||||
#endif
|
||||
|
||||
extern size_t chunksize;
|
||||
extern size_t chunksize_mask; /* (chunksize - 1). */
|
||||
@@ -49,9 +43,14 @@ extern size_t chunk_npages;
|
||||
extern size_t map_bias; /* Number of arena chunk header pages. */
|
||||
extern size_t arena_maxclass; /* Max size class for arenas. */
|
||||
|
||||
void *chunk_alloc(size_t size, bool base, bool *zero);
|
||||
void *chunk_alloc(size_t size, size_t alignment, bool base, bool *zero,
|
||||
dss_prec_t dss_prec);
|
||||
void chunk_unmap(void *chunk, size_t size);
|
||||
void chunk_dealloc(void *chunk, size_t size, bool unmap);
|
||||
bool chunk_boot(void);
|
||||
void chunk_prefork(void);
|
||||
void chunk_postfork_parent(void);
|
||||
void chunk_postfork_child(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
@@ -60,6 +59,5 @@ bool chunk_boot(void);
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
|
||||
#include "jemalloc/internal/chunk_swap.h"
|
||||
#include "jemalloc/internal/chunk_dss.h"
|
||||
#include "jemalloc/internal/chunk_mmap.h"
|
||||
|
||||
+18
-10
@@ -1,25 +1,34 @@
|
||||
#ifdef JEMALLOC_DSS
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
typedef enum {
|
||||
dss_prec_disabled = 0,
|
||||
dss_prec_primary = 1,
|
||||
dss_prec_secondary = 2,
|
||||
|
||||
dss_prec_limit = 3
|
||||
} dss_prec_t;
|
||||
#define DSS_PREC_DEFAULT dss_prec_secondary
|
||||
#define DSS_DEFAULT "secondary"
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
extern const char *dss_prec_names[];
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
/*
|
||||
* Protects sbrk() calls. This avoids malloc races among threads, though it
|
||||
* does not protect against races with threads that call sbrk() directly.
|
||||
*/
|
||||
extern malloc_mutex_t dss_mtx;
|
||||
|
||||
void *chunk_alloc_dss(size_t size, bool *zero);
|
||||
dss_prec_t chunk_dss_prec_get(void);
|
||||
bool chunk_dss_prec_set(dss_prec_t dss_prec);
|
||||
void *chunk_alloc_dss(size_t size, size_t alignment, bool *zero);
|
||||
bool chunk_in_dss(void *chunk);
|
||||
bool chunk_dealloc_dss(void *chunk, size_t size);
|
||||
bool chunk_dss_boot(void);
|
||||
void chunk_dss_prefork(void);
|
||||
void chunk_dss_postfork_parent(void);
|
||||
void chunk_dss_postfork_child(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
@@ -27,4 +36,3 @@ bool chunk_dss_boot(void);
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
#endif /* JEMALLOC_DSS */
|
||||
|
||||
+3
-4
@@ -9,11 +9,10 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
void *chunk_alloc_mmap(size_t size);
|
||||
void *chunk_alloc_mmap_noreserve(size_t size);
|
||||
void chunk_dealloc_mmap(void *chunk, size_t size);
|
||||
bool pages_purge(void *addr, size_t length);
|
||||
|
||||
bool chunk_mmap_boot(void);
|
||||
void *chunk_alloc_mmap(size_t size, size_t alignment, bool *zero);
|
||||
bool chunk_dealloc_mmap(void *chunk, size_t size);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifdef JEMALLOC_SWAP
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
extern malloc_mutex_t swap_mtx;
|
||||
extern bool swap_enabled;
|
||||
extern bool swap_prezeroed;
|
||||
extern size_t swap_nfds;
|
||||
extern int *swap_fds;
|
||||
#ifdef JEMALLOC_STATS
|
||||
extern size_t swap_avail;
|
||||
#endif
|
||||
|
||||
void *chunk_alloc_swap(size_t size, bool *zero);
|
||||
bool chunk_in_swap(void *chunk);
|
||||
bool chunk_dealloc_swap(void *chunk, size_t size);
|
||||
bool chunk_swap_enable(const int *fds, unsigned nfds, bool prezeroed);
|
||||
bool chunk_swap_boot(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
#endif /* JEMALLOC_SWAP */
|
||||
+5
-12
@@ -5,7 +5,7 @@ typedef struct ckh_s ckh_t;
|
||||
typedef struct ckhc_s ckhc_t;
|
||||
|
||||
/* Typedefs to allow easy function pointer passing. */
|
||||
typedef void ckh_hash_t (const void *, unsigned, size_t *, size_t *);
|
||||
typedef void ckh_hash_t (const void *, size_t[2]);
|
||||
typedef bool ckh_keycomp_t (const void *, const void *);
|
||||
|
||||
/* Maintain counters used to get an idea of performance. */
|
||||
@@ -17,7 +17,7 @@ typedef bool ckh_keycomp_t (const void *, const void *);
|
||||
* There are 2^LG_CKH_BUCKET_CELLS cells in each hash table bucket. Try to fit
|
||||
* one bucket per L1 cache line.
|
||||
*/
|
||||
#define LG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1)
|
||||
#define LG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1)
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
@@ -30,11 +30,6 @@ struct ckhc_s {
|
||||
};
|
||||
|
||||
struct ckh_s {
|
||||
#ifdef JEMALLOC_DEBUG
|
||||
#define CKH_MAGIC 0x3af2489d
|
||||
uint32_t magic;
|
||||
#endif
|
||||
|
||||
#ifdef CKH_COUNT
|
||||
/* Counters used to get an idea of performance. */
|
||||
uint64_t ngrows;
|
||||
@@ -47,7 +42,7 @@ struct ckh_s {
|
||||
/* Used for pseudo-random number generation. */
|
||||
#define CKH_A 1103515241
|
||||
#define CKH_C 12347
|
||||
uint32_t prn_state;
|
||||
uint32_t prng_state;
|
||||
|
||||
/* Total number of items. */
|
||||
size_t count;
|
||||
@@ -80,11 +75,9 @@ bool ckh_insert(ckh_t *ckh, const void *key, const void *data);
|
||||
bool ckh_remove(ckh_t *ckh, const void *searchkey, void **key,
|
||||
void **data);
|
||||
bool ckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data);
|
||||
void ckh_string_hash(const void *key, unsigned minbits, size_t *hash1,
|
||||
size_t *hash2);
|
||||
void ckh_string_hash(const void *key, size_t r_hash[2]);
|
||||
bool ckh_string_keycomp(const void *k1, const void *k2);
|
||||
void ckh_pointer_hash(const void *key, unsigned minbits, size_t *hash1,
|
||||
size_t *hash2);
|
||||
void ckh_pointer_hash(const void *key, size_t r_hash[2]);
|
||||
bool ckh_pointer_keycomp(const void *k1, const void *k2);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
|
||||
+31
-32
@@ -2,6 +2,8 @@
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
typedef struct ctl_node_s ctl_node_t;
|
||||
typedef struct ctl_named_node_s ctl_named_node_t;
|
||||
typedef struct ctl_indexed_node_s ctl_indexed_node_t;
|
||||
typedef struct ctl_arena_stats_s ctl_arena_stats_t;
|
||||
typedef struct ctl_stats_s ctl_stats_t;
|
||||
|
||||
@@ -11,28 +13,29 @@ typedef struct ctl_stats_s ctl_stats_t;
|
||||
|
||||
struct ctl_node_s {
|
||||
bool named;
|
||||
union {
|
||||
struct {
|
||||
const char *name;
|
||||
/* If (nchildren == 0), this is a terminal node. */
|
||||
unsigned nchildren;
|
||||
const ctl_node_t *children;
|
||||
} named;
|
||||
struct {
|
||||
const ctl_node_t *(*index)(const size_t *, size_t,
|
||||
size_t);
|
||||
} indexed;
|
||||
} u;
|
||||
int (*ctl)(const size_t *, size_t, void *, size_t *, void *,
|
||||
size_t);
|
||||
};
|
||||
|
||||
struct ctl_named_node_s {
|
||||
struct ctl_node_s node;
|
||||
const char *name;
|
||||
/* If (nchildren == 0), this is a terminal node. */
|
||||
unsigned nchildren;
|
||||
const ctl_node_t *children;
|
||||
int (*ctl)(const size_t *, size_t, void *, size_t *,
|
||||
void *, size_t);
|
||||
};
|
||||
|
||||
struct ctl_indexed_node_s {
|
||||
struct ctl_node_s node;
|
||||
const ctl_named_node_t *(*index)(const size_t *, size_t, size_t);
|
||||
};
|
||||
|
||||
struct ctl_arena_stats_s {
|
||||
bool initialized;
|
||||
unsigned nthreads;
|
||||
const char *dss;
|
||||
size_t pactive;
|
||||
size_t pdirty;
|
||||
#ifdef JEMALLOC_STATS
|
||||
arena_stats_t astats;
|
||||
|
||||
/* Aggregate stats for small size classes, based on bin stats. */
|
||||
@@ -41,13 +44,11 @@ struct ctl_arena_stats_s {
|
||||
uint64_t ndalloc_small;
|
||||
uint64_t nrequests_small;
|
||||
|
||||
malloc_bin_stats_t *bstats; /* nbins elements. */
|
||||
malloc_bin_stats_t bstats[NBINS];
|
||||
malloc_large_stats_t *lstats; /* nlclasses elements. */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ctl_stats_s {
|
||||
#ifdef JEMALLOC_STATS
|
||||
size_t allocated;
|
||||
size_t active;
|
||||
size_t mapped;
|
||||
@@ -61,11 +62,8 @@ struct ctl_stats_s {
|
||||
uint64_t nmalloc; /* huge_nmalloc */
|
||||
uint64_t ndalloc; /* huge_ndalloc */
|
||||
} huge;
|
||||
#endif
|
||||
unsigned narenas;
|
||||
ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */
|
||||
#ifdef JEMALLOC_SWAP
|
||||
size_t swap_avail;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
@@ -79,29 +77,30 @@ int ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp);
|
||||
int ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
void *newp, size_t newlen);
|
||||
bool ctl_boot(void);
|
||||
void ctl_prefork(void);
|
||||
void ctl_postfork_parent(void);
|
||||
void ctl_postfork_child(void);
|
||||
|
||||
#define xmallctl(name, oldp, oldlenp, newp, newlen) do { \
|
||||
if (JEMALLOC_P(mallctl)(name, oldp, oldlenp, newp, newlen) \
|
||||
if (je_mallctl(name, oldp, oldlenp, newp, newlen) \
|
||||
!= 0) { \
|
||||
malloc_write("<jemalloc>: Failure in xmallctl(\""); \
|
||||
malloc_write(name); \
|
||||
malloc_write("\", ...)\n"); \
|
||||
malloc_printf( \
|
||||
"<jemalloc>: Failure in xmallctl(\"%s\", ...)\n", \
|
||||
name); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define xmallctlnametomib(name, mibp, miblenp) do { \
|
||||
if (JEMALLOC_P(mallctlnametomib)(name, mibp, miblenp) != 0) { \
|
||||
malloc_write( \
|
||||
"<jemalloc>: Failure in xmallctlnametomib(\""); \
|
||||
malloc_write(name); \
|
||||
malloc_write("\", ...)\n"); \
|
||||
if (je_mallctlnametomib(name, mibp, miblenp) != 0) { \
|
||||
malloc_printf("<jemalloc>: Failure in " \
|
||||
"xmallctlnametomib(\"%s\", ...)\n", name); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define xmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do { \
|
||||
if (JEMALLOC_P(mallctlbymib)(mib, miblen, oldp, oldlenp, newp, \
|
||||
if (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp, \
|
||||
newlen) != 0) { \
|
||||
malloc_write( \
|
||||
"<jemalloc>: Failure in xmallctlbymib()\n"); \
|
||||
|
||||
+3
-6
@@ -9,24 +9,23 @@ typedef struct extent_node_s extent_node_t;
|
||||
|
||||
/* Tree of extents. */
|
||||
struct extent_node_s {
|
||||
#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS))
|
||||
/* Linkage for the size/address-ordered tree. */
|
||||
rb_node(extent_node_t) link_szad;
|
||||
#endif
|
||||
|
||||
/* Linkage for the address-ordered tree. */
|
||||
rb_node(extent_node_t) link_ad;
|
||||
|
||||
#ifdef JEMALLOC_PROF
|
||||
/* Profile counters, used for huge objects. */
|
||||
prof_ctx_t *prof_ctx;
|
||||
#endif
|
||||
|
||||
/* Pointer to the extent that this tree node is responsible for. */
|
||||
void *addr;
|
||||
|
||||
/* Total region size. */
|
||||
size_t size;
|
||||
|
||||
/* True if zero-filled; used by chunk recycling code. */
|
||||
bool zeroed;
|
||||
};
|
||||
typedef rb_tree(extent_node_t) extent_tree_t;
|
||||
|
||||
@@ -34,9 +33,7 @@ typedef rb_tree(extent_node_t) extent_tree_t;
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
#if (defined(JEMALLOC_SWAP) || defined(JEMALLOC_DSS))
|
||||
rb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t)
|
||||
#endif
|
||||
|
||||
rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
|
||||
|
||||
|
||||
+302
-37
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* The following hash function is based on MurmurHash3, placed into the public
|
||||
* domain by Austin Appleby. See http://code.google.com/p/smhasher/ for
|
||||
* details.
|
||||
*/
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
@@ -14,56 +19,316 @@
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
uint64_t hash(const void *key, size_t len, uint64_t seed);
|
||||
uint32_t hash_x86_32(const void *key, int len, uint32_t seed);
|
||||
void hash_x86_128(const void *key, const int len, uint32_t seed,
|
||||
uint64_t r_out[2]);
|
||||
void hash_x64_128(const void *key, const int len, const uint32_t seed,
|
||||
uint64_t r_out[2]);
|
||||
void hash(const void *key, size_t len, const uint32_t seed,
|
||||
size_t r_hash[2]);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_))
|
||||
/*
|
||||
* The following hash function is based on MurmurHash64A(), placed into the
|
||||
* public domain by Austin Appleby. See http://murmurhash.googlepages.com/ for
|
||||
* details.
|
||||
*/
|
||||
JEMALLOC_INLINE uint64_t
|
||||
hash(const void *key, size_t len, uint64_t seed)
|
||||
/******************************************************************************/
|
||||
/* Internal implementation. */
|
||||
JEMALLOC_INLINE uint32_t
|
||||
hash_rotl_32(uint32_t x, int8_t r)
|
||||
{
|
||||
const uint64_t m = 0xc6a4a7935bd1e995LLU;
|
||||
const int r = 47;
|
||||
uint64_t h = seed ^ (len * m);
|
||||
const uint64_t *data = (const uint64_t *)key;
|
||||
const uint64_t *end = data + (len/8);
|
||||
const unsigned char *data2;
|
||||
|
||||
assert(((uintptr_t)key & 0x7) == 0);
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
while(data != end) {
|
||||
uint64_t k = *data++;
|
||||
JEMALLOC_INLINE uint64_t
|
||||
hash_rotl_64(uint64_t x, int8_t r)
|
||||
{
|
||||
return (x << r) | (x >> (64 - r));
|
||||
}
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
JEMALLOC_INLINE uint32_t
|
||||
hash_get_block_32(const uint32_t *p, int i)
|
||||
{
|
||||
|
||||
h ^= k;
|
||||
h *= m;
|
||||
}
|
||||
return (p[i]);
|
||||
}
|
||||
|
||||
data2 = (const unsigned char *)data;
|
||||
switch(len & 7) {
|
||||
case 7: h ^= ((uint64_t)(data2[6])) << 48;
|
||||
case 6: h ^= ((uint64_t)(data2[5])) << 40;
|
||||
case 5: h ^= ((uint64_t)(data2[4])) << 32;
|
||||
case 4: h ^= ((uint64_t)(data2[3])) << 24;
|
||||
case 3: h ^= ((uint64_t)(data2[2])) << 16;
|
||||
case 2: h ^= ((uint64_t)(data2[1])) << 8;
|
||||
case 1: h ^= ((uint64_t)(data2[0]));
|
||||
h *= m;
|
||||
}
|
||||
JEMALLOC_INLINE uint64_t
|
||||
hash_get_block_64(const uint64_t *p, int i)
|
||||
{
|
||||
|
||||
h ^= h >> r;
|
||||
h *= m;
|
||||
h ^= h >> r;
|
||||
return (p[i]);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint32_t
|
||||
hash_fmix_32(uint32_t h)
|
||||
{
|
||||
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
|
||||
return (h);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint64_t
|
||||
hash_fmix_64(uint64_t k)
|
||||
{
|
||||
|
||||
k ^= k >> 33;
|
||||
k *= QU(0xff51afd7ed558ccdLLU);
|
||||
k ^= k >> 33;
|
||||
k *= QU(0xc4ceb9fe1a85ec53LLU);
|
||||
k ^= k >> 33;
|
||||
|
||||
return (k);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE uint32_t
|
||||
hash_x86_32(const void *key, int len, uint32_t seed)
|
||||
{
|
||||
const uint8_t *data = (const uint8_t *) key;
|
||||
const int nblocks = len / 4;
|
||||
|
||||
uint32_t h1 = seed;
|
||||
|
||||
const uint32_t c1 = 0xcc9e2d51;
|
||||
const uint32_t c2 = 0x1b873593;
|
||||
|
||||
/* body */
|
||||
{
|
||||
const uint32_t *blocks = (const uint32_t *) (data + nblocks*4);
|
||||
int i;
|
||||
|
||||
for (i = -nblocks; i; i++) {
|
||||
uint32_t k1 = hash_get_block_32(blocks, i);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = hash_rotl_32(k1, 15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = hash_rotl_32(h1, 13);
|
||||
h1 = h1*5 + 0xe6546b64;
|
||||
}
|
||||
}
|
||||
|
||||
/* tail */
|
||||
{
|
||||
const uint8_t *tail = (const uint8_t *) (data + nblocks*4);
|
||||
|
||||
uint32_t k1 = 0;
|
||||
|
||||
switch (len & 3) {
|
||||
case 3: k1 ^= tail[2] << 16;
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0]; k1 *= c1; k1 = hash_rotl_32(k1, 15);
|
||||
k1 *= c2; h1 ^= k1;
|
||||
}
|
||||
}
|
||||
|
||||
/* finalization */
|
||||
h1 ^= len;
|
||||
|
||||
h1 = hash_fmix_32(h1);
|
||||
|
||||
return (h1);
|
||||
}
|
||||
|
||||
UNUSED JEMALLOC_INLINE void
|
||||
hash_x86_128(const void *key, const int len, uint32_t seed,
|
||||
uint64_t r_out[2])
|
||||
{
|
||||
const uint8_t * data = (const uint8_t *) key;
|
||||
const int nblocks = len / 16;
|
||||
|
||||
uint32_t h1 = seed;
|
||||
uint32_t h2 = seed;
|
||||
uint32_t h3 = seed;
|
||||
uint32_t h4 = seed;
|
||||
|
||||
const uint32_t c1 = 0x239b961b;
|
||||
const uint32_t c2 = 0xab0e9789;
|
||||
const uint32_t c3 = 0x38b34ae5;
|
||||
const uint32_t c4 = 0xa1e38b93;
|
||||
|
||||
/* body */
|
||||
{
|
||||
const uint32_t *blocks = (const uint32_t *) (data + nblocks*16);
|
||||
int i;
|
||||
|
||||
for (i = -nblocks; i; i++) {
|
||||
uint32_t k1 = hash_get_block_32(blocks, i*4 + 0);
|
||||
uint32_t k2 = hash_get_block_32(blocks, i*4 + 1);
|
||||
uint32_t k3 = hash_get_block_32(blocks, i*4 + 2);
|
||||
uint32_t k4 = hash_get_block_32(blocks, i*4 + 3);
|
||||
|
||||
k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;
|
||||
|
||||
h1 = hash_rotl_32(h1, 19); h1 += h2;
|
||||
h1 = h1*5 + 0x561ccd1b;
|
||||
|
||||
k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;
|
||||
|
||||
h2 = hash_rotl_32(h2, 17); h2 += h3;
|
||||
h2 = h2*5 + 0x0bcaa747;
|
||||
|
||||
k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;
|
||||
|
||||
h3 = hash_rotl_32(h3, 15); h3 += h4;
|
||||
h3 = h3*5 + 0x96cd1c35;
|
||||
|
||||
k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;
|
||||
|
||||
h4 = hash_rotl_32(h4, 13); h4 += h1;
|
||||
h4 = h4*5 + 0x32ac3b17;
|
||||
}
|
||||
}
|
||||
|
||||
/* tail */
|
||||
{
|
||||
const uint8_t *tail = (const uint8_t *) (data + nblocks*16);
|
||||
uint32_t k1 = 0;
|
||||
uint32_t k2 = 0;
|
||||
uint32_t k3 = 0;
|
||||
uint32_t k4 = 0;
|
||||
|
||||
switch (len & 15) {
|
||||
case 15: k4 ^= tail[14] << 16;
|
||||
case 14: k4 ^= tail[13] << 8;
|
||||
case 13: k4 ^= tail[12] << 0;
|
||||
k4 *= c4; k4 = hash_rotl_32(k4, 18); k4 *= c1; h4 ^= k4;
|
||||
|
||||
case 12: k3 ^= tail[11] << 24;
|
||||
case 11: k3 ^= tail[10] << 16;
|
||||
case 10: k3 ^= tail[ 9] << 8;
|
||||
case 9: k3 ^= tail[ 8] << 0;
|
||||
k3 *= c3; k3 = hash_rotl_32(k3, 17); k3 *= c4; h3 ^= k3;
|
||||
|
||||
case 8: k2 ^= tail[ 7] << 24;
|
||||
case 7: k2 ^= tail[ 6] << 16;
|
||||
case 6: k2 ^= tail[ 5] << 8;
|
||||
case 5: k2 ^= tail[ 4] << 0;
|
||||
k2 *= c2; k2 = hash_rotl_32(k2, 16); k2 *= c3; h2 ^= k2;
|
||||
|
||||
case 4: k1 ^= tail[ 3] << 24;
|
||||
case 3: k1 ^= tail[ 2] << 16;
|
||||
case 2: k1 ^= tail[ 1] << 8;
|
||||
case 1: k1 ^= tail[ 0] << 0;
|
||||
k1 *= c1; k1 = hash_rotl_32(k1, 15); k1 *= c2; h1 ^= k1;
|
||||
}
|
||||
}
|
||||
|
||||
/* finalization */
|
||||
h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
|
||||
|
||||
h1 += h2; h1 += h3; h1 += h4;
|
||||
h2 += h1; h3 += h1; h4 += h1;
|
||||
|
||||
h1 = hash_fmix_32(h1);
|
||||
h2 = hash_fmix_32(h2);
|
||||
h3 = hash_fmix_32(h3);
|
||||
h4 = hash_fmix_32(h4);
|
||||
|
||||
h1 += h2; h1 += h3; h1 += h4;
|
||||
h2 += h1; h3 += h1; h4 += h1;
|
||||
|
||||
r_out[0] = (((uint64_t) h2) << 32) | h1;
|
||||
r_out[1] = (((uint64_t) h4) << 32) | h3;
|
||||
}
|
||||
|
||||
UNUSED JEMALLOC_INLINE void
|
||||
hash_x64_128(const void *key, const int len, const uint32_t seed,
|
||||
uint64_t r_out[2])
|
||||
{
|
||||
const uint8_t *data = (const uint8_t *) key;
|
||||
const int nblocks = len / 16;
|
||||
|
||||
uint64_t h1 = seed;
|
||||
uint64_t h2 = seed;
|
||||
|
||||
const uint64_t c1 = QU(0x87c37b91114253d5LLU);
|
||||
const uint64_t c2 = QU(0x4cf5ad432745937fLLU);
|
||||
|
||||
/* body */
|
||||
{
|
||||
const uint64_t *blocks = (const uint64_t *) (data);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nblocks; i++) {
|
||||
uint64_t k1 = hash_get_block_64(blocks, i*2 + 0);
|
||||
uint64_t k2 = hash_get_block_64(blocks, i*2 + 1);
|
||||
|
||||
k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;
|
||||
|
||||
h1 = hash_rotl_64(h1, 27); h1 += h2;
|
||||
h1 = h1*5 + 0x52dce729;
|
||||
|
||||
k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;
|
||||
|
||||
h2 = hash_rotl_64(h2, 31); h2 += h1;
|
||||
h2 = h2*5 + 0x38495ab5;
|
||||
}
|
||||
}
|
||||
|
||||
/* tail */
|
||||
{
|
||||
const uint8_t *tail = (const uint8_t*)(data + nblocks*16);
|
||||
uint64_t k1 = 0;
|
||||
uint64_t k2 = 0;
|
||||
|
||||
switch (len & 15) {
|
||||
case 15: k2 ^= ((uint64_t)(tail[14])) << 48;
|
||||
case 14: k2 ^= ((uint64_t)(tail[13])) << 40;
|
||||
case 13: k2 ^= ((uint64_t)(tail[12])) << 32;
|
||||
case 12: k2 ^= ((uint64_t)(tail[11])) << 24;
|
||||
case 11: k2 ^= ((uint64_t)(tail[10])) << 16;
|
||||
case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8;
|
||||
case 9: k2 ^= ((uint64_t)(tail[ 8])) << 0;
|
||||
k2 *= c2; k2 = hash_rotl_64(k2, 33); k2 *= c1; h2 ^= k2;
|
||||
|
||||
case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56;
|
||||
case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48;
|
||||
case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40;
|
||||
case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32;
|
||||
case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24;
|
||||
case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16;
|
||||
case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8;
|
||||
case 1: k1 ^= ((uint64_t)(tail[ 0])) << 0;
|
||||
k1 *= c1; k1 = hash_rotl_64(k1, 31); k1 *= c2; h1 ^= k1;
|
||||
}
|
||||
}
|
||||
|
||||
/* finalization */
|
||||
h1 ^= len; h2 ^= len;
|
||||
|
||||
h1 += h2;
|
||||
h2 += h1;
|
||||
|
||||
h1 = hash_fmix_64(h1);
|
||||
h2 = hash_fmix_64(h2);
|
||||
|
||||
h1 += h2;
|
||||
h2 += h1;
|
||||
|
||||
r_out[0] = h1;
|
||||
r_out[1] = h2;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* API. */
|
||||
JEMALLOC_INLINE void
|
||||
hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2])
|
||||
{
|
||||
#if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN))
|
||||
hash_x64_128(key, len, seed, (uint64_t *)r_hash);
|
||||
#else
|
||||
uint64_t hashes[2];
|
||||
hash_x86_128(key, len, seed, hashes);
|
||||
r_hash[0] = (size_t)hashes[0];
|
||||
r_hash[1] = (size_t)hashes[1];
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
|
||||
+13
-8
@@ -9,29 +9,34 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
/* Huge allocation statistics. */
|
||||
extern uint64_t huge_nmalloc;
|
||||
extern uint64_t huge_ndalloc;
|
||||
extern size_t huge_allocated;
|
||||
#endif
|
||||
|
||||
/* Protects chunk-related data structures. */
|
||||
extern malloc_mutex_t huge_mtx;
|
||||
|
||||
void *huge_malloc(size_t size, bool zero);
|
||||
void *huge_palloc(size_t size, size_t alignment, bool zero);
|
||||
void *huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size,
|
||||
void *huge_malloc(size_t size, bool zero, dss_prec_t dss_prec);
|
||||
void *huge_palloc(size_t size, size_t alignment, bool zero,
|
||||
dss_prec_t dss_prec);
|
||||
bool huge_ralloc_no_move(void *ptr, size_t oldsize, size_t size,
|
||||
size_t extra);
|
||||
void *huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
size_t alignment, bool zero);
|
||||
size_t alignment, bool zero, bool try_tcache_dalloc, dss_prec_t dss_prec);
|
||||
#ifdef JEMALLOC_JET
|
||||
typedef void (huge_dalloc_junk_t)(void *, size_t);
|
||||
extern huge_dalloc_junk_t *huge_dalloc_junk;
|
||||
#endif
|
||||
void huge_dalloc(void *ptr, bool unmap);
|
||||
size_t huge_salloc(const void *ptr);
|
||||
#ifdef JEMALLOC_PROF
|
||||
dss_prec_t huge_dss_prec_get(arena_t *arena);
|
||||
prof_ctx_t *huge_prof_ctx_get(const void *ptr);
|
||||
void huge_prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
|
||||
#endif
|
||||
bool huge_boot(void);
|
||||
void huge_prefork(void);
|
||||
void huge_postfork_parent(void);
|
||||
void huge_postfork_child(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
|
||||
+638
-398
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,205 @@
|
||||
#ifndef JEMALLOC_INTERNAL_DEFS_H_
|
||||
#define JEMALLOC_INTERNAL_DEFS_H_
|
||||
/*
|
||||
* If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all
|
||||
* public APIs to be prefixed. This makes it possible, with some care, to use
|
||||
* multiple allocators simultaneously.
|
||||
*/
|
||||
#undef JEMALLOC_PREFIX
|
||||
#undef JEMALLOC_CPREFIX
|
||||
|
||||
/*
|
||||
* JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs.
|
||||
* For shared libraries, symbol visibility mechanisms prevent these symbols
|
||||
* from being exported, but for static libraries, naming collisions are a real
|
||||
* possibility.
|
||||
*/
|
||||
#undef JEMALLOC_PRIVATE_NAMESPACE
|
||||
|
||||
/*
|
||||
* Hyper-threaded CPUs may need a special instruction inside spin loops in
|
||||
* order to yield to another virtual CPU.
|
||||
*/
|
||||
#undef CPU_SPINWAIT
|
||||
|
||||
/* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */
|
||||
#undef JEMALLOC_ATOMIC9
|
||||
|
||||
/*
|
||||
* Defined if OSAtomic*() functions are available, as provided by Darwin, and
|
||||
* documented in the atomic(3) manual page.
|
||||
*/
|
||||
#undef JEMALLOC_OSATOMIC
|
||||
|
||||
/*
|
||||
* Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and
|
||||
* __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite
|
||||
* __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the
|
||||
* functions are defined in libgcc instead of being inlines)
|
||||
*/
|
||||
#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4
|
||||
|
||||
/*
|
||||
* Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and
|
||||
* __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite
|
||||
* __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the
|
||||
* functions are defined in libgcc instead of being inlines)
|
||||
*/
|
||||
#undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8
|
||||
|
||||
/*
|
||||
* Defined if OSSpin*() functions are available, as provided by Darwin, and
|
||||
* documented in the spinlock(3) manual page.
|
||||
*/
|
||||
#undef JEMALLOC_OSSPIN
|
||||
|
||||
/*
|
||||
* Defined if _malloc_thread_cleanup() exists. At least in the case of
|
||||
* FreeBSD, pthread_key_create() allocates, which if used during malloc
|
||||
* bootstrapping will cause recursion into the pthreads library. Therefore, if
|
||||
* _malloc_thread_cleanup() exists, use it as the basis for thread cleanup in
|
||||
* malloc_tsd.
|
||||
*/
|
||||
#undef JEMALLOC_MALLOC_THREAD_CLEANUP
|
||||
|
||||
/*
|
||||
* Defined if threaded initialization is known to be safe on this platform.
|
||||
* Among other things, it must be possible to initialize a mutex without
|
||||
* triggering allocation in order for threaded allocation to be safe.
|
||||
*/
|
||||
#undef JEMALLOC_THREADED_INIT
|
||||
|
||||
/*
|
||||
* Defined if the pthreads implementation defines
|
||||
* _pthread_mutex_init_calloc_cb(), in which case the function is used in order
|
||||
* to avoid recursive allocation during mutex initialization.
|
||||
*/
|
||||
#undef JEMALLOC_MUTEX_INIT_CB
|
||||
|
||||
/* Defined if sbrk() is supported. */
|
||||
#undef JEMALLOC_HAVE_SBRK
|
||||
|
||||
/* Non-empty if the tls_model attribute is supported. */
|
||||
#undef JEMALLOC_TLS_MODEL
|
||||
|
||||
/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */
|
||||
#undef JEMALLOC_CC_SILENCE
|
||||
|
||||
/* JEMALLOC_CODE_COVERAGE enables test code coverage analysis. */
|
||||
#undef JEMALLOC_CODE_COVERAGE
|
||||
|
||||
/*
|
||||
* JEMALLOC_DEBUG enables assertions and other sanity checks, and disables
|
||||
* inline functions.
|
||||
*/
|
||||
#undef JEMALLOC_DEBUG
|
||||
|
||||
/* JEMALLOC_STATS enables statistics calculation. */
|
||||
#undef JEMALLOC_STATS
|
||||
|
||||
/* JEMALLOC_PROF enables allocation profiling. */
|
||||
#undef JEMALLOC_PROF
|
||||
|
||||
/* Use libunwind for profile backtracing if defined. */
|
||||
#undef JEMALLOC_PROF_LIBUNWIND
|
||||
|
||||
/* Use libgcc for profile backtracing if defined. */
|
||||
#undef JEMALLOC_PROF_LIBGCC
|
||||
|
||||
/* Use gcc intrinsics for profile backtracing if defined. */
|
||||
#undef JEMALLOC_PROF_GCC
|
||||
|
||||
/*
|
||||
* JEMALLOC_TCACHE enables a thread-specific caching layer for small objects.
|
||||
* This makes it possible to allocate/deallocate objects without any locking
|
||||
* when the cache is in the steady state.
|
||||
*/
|
||||
#undef JEMALLOC_TCACHE
|
||||
|
||||
/*
|
||||
* JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage
|
||||
* segment (DSS).
|
||||
*/
|
||||
#undef JEMALLOC_DSS
|
||||
|
||||
/* Support memory filling (junk/zero/quarantine/redzone). */
|
||||
#undef JEMALLOC_FILL
|
||||
|
||||
/* Support utrace(2)-based tracing. */
|
||||
#undef JEMALLOC_UTRACE
|
||||
|
||||
/* Support Valgrind. */
|
||||
#undef JEMALLOC_VALGRIND
|
||||
|
||||
/* Support optional abort() on OOM. */
|
||||
#undef JEMALLOC_XMALLOC
|
||||
|
||||
/* Support lazy locking (avoid locking unless a second thread is launched). */
|
||||
#undef JEMALLOC_LAZY_LOCK
|
||||
|
||||
/* One page is 2^STATIC_PAGE_SHIFT bytes. */
|
||||
#undef STATIC_PAGE_SHIFT
|
||||
|
||||
/*
|
||||
* If defined, use munmap() to unmap freed chunks, rather than storing them for
|
||||
* later reuse. This is disabled by default on Linux because common sequences
|
||||
* of mmap()/munmap() calls will cause virtual memory map holes.
|
||||
*/
|
||||
#undef JEMALLOC_MUNMAP
|
||||
|
||||
/*
|
||||
* If defined, use mremap(...MREMAP_FIXED...) for huge realloc(). This is
|
||||
* disabled by default because it is Linux-specific and it will cause virtual
|
||||
* memory map holes, much like munmap(2) does.
|
||||
*/
|
||||
#undef JEMALLOC_MREMAP
|
||||
|
||||
/* TLS is used to map arenas and magazine caches to threads. */
|
||||
#undef JEMALLOC_TLS
|
||||
|
||||
/*
|
||||
* JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside
|
||||
* within jemalloc-owned chunks before dereferencing them.
|
||||
*/
|
||||
#undef JEMALLOC_IVSALLOC
|
||||
|
||||
/*
|
||||
* Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.
|
||||
*/
|
||||
#undef JEMALLOC_ZONE
|
||||
#undef JEMALLOC_ZONE_VERSION
|
||||
|
||||
/*
|
||||
* Methods for purging unused pages differ between operating systems.
|
||||
*
|
||||
* madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages,
|
||||
* such that new pages will be demand-zeroed if
|
||||
* the address region is later touched.
|
||||
* madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being
|
||||
* unused, such that they will be discarded rather
|
||||
* than swapped out.
|
||||
*/
|
||||
#undef JEMALLOC_PURGE_MADVISE_DONTNEED
|
||||
#undef JEMALLOC_PURGE_MADVISE_FREE
|
||||
|
||||
/*
|
||||
* Define if operating system has alloca.h header.
|
||||
*/
|
||||
#undef JEMALLOC_HAS_ALLOCA_H
|
||||
|
||||
/* C99 restrict keyword supported. */
|
||||
#undef JEMALLOC_HAS_RESTRICT
|
||||
|
||||
/* For use by hash code. */
|
||||
#undef JEMALLOC_BIG_ENDIAN
|
||||
|
||||
/* sizeof(int) == 2^LG_SIZEOF_INT. */
|
||||
#undef LG_SIZEOF_INT
|
||||
|
||||
/* sizeof(long) == 2^LG_SIZEOF_LONG. */
|
||||
#undef LG_SIZEOF_LONG
|
||||
|
||||
/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */
|
||||
#undef LG_SIZEOF_INTMAX_T
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_DEFS_H_ */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* JEMALLOC_ALWAYS_INLINE and JEMALLOC_INLINE are used within header files for
|
||||
* functions that are static inline functions if inlining is enabled, and
|
||||
* single-definition library-private functions if inlining is disabled.
|
||||
*
|
||||
* JEMALLOC_ALWAYS_INLINE_C and JEMALLOC_INLINE_C are for use in .c files, in
|
||||
* which case the denoted functions are always static, regardless of whether
|
||||
* inlining is enabled.
|
||||
*/
|
||||
#if defined(JEMALLOC_DEBUG) || defined(JEMALLOC_CODE_COVERAGE)
|
||||
/* Disable inlining to make debugging/profiling easier. */
|
||||
# define JEMALLOC_ALWAYS_INLINE
|
||||
# define JEMALLOC_ALWAYS_INLINE_C static
|
||||
# define JEMALLOC_INLINE
|
||||
# define JEMALLOC_INLINE_C static
|
||||
# define inline
|
||||
#else
|
||||
# define JEMALLOC_ENABLE_INLINE
|
||||
# ifdef JEMALLOC_HAVE_ATTR
|
||||
# define JEMALLOC_ALWAYS_INLINE \
|
||||
static inline JEMALLOC_ATTR(unused) JEMALLOC_ATTR(always_inline)
|
||||
# define JEMALLOC_ALWAYS_INLINE_C \
|
||||
static inline JEMALLOC_ATTR(always_inline)
|
||||
# else
|
||||
# define JEMALLOC_ALWAYS_INLINE static inline
|
||||
# define JEMALLOC_ALWAYS_INLINE_C static inline
|
||||
# endif
|
||||
# define JEMALLOC_INLINE static inline
|
||||
# define JEMALLOC_INLINE_C static inline
|
||||
# ifdef _MSC_VER
|
||||
# define inline _inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef JEMALLOC_CC_SILENCE
|
||||
# define UNUSED JEMALLOC_ATTR(unused)
|
||||
#else
|
||||
# define UNUSED
|
||||
#endif
|
||||
|
||||
#define ZU(z) ((size_t)z)
|
||||
#define QU(q) ((uint64_t)q)
|
||||
#define QI(q) ((int64_t)q)
|
||||
|
||||
#ifndef __DECONST
|
||||
# define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
|
||||
#endif
|
||||
|
||||
#ifndef JEMALLOC_HAS_RESTRICT
|
||||
# define restrict
|
||||
#endif
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
void mb_write(void);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MB_C_))
|
||||
#ifdef __i386__
|
||||
/*
|
||||
* According to the Intel Architecture Software Developer's Manual, current
|
||||
* processors execute instructions in order from the perspective of other
|
||||
* processors in a multiprocessor system, but 1) Intel reserves the right to
|
||||
* change that, and 2) the compiler's optimizer could re-order instructions if
|
||||
* there weren't some form of barrier. Therefore, even if running on an
|
||||
* architecture that does not need memory barriers (everything through at least
|
||||
* i686), an "optimizer barrier" is necessary.
|
||||
*/
|
||||
JEMALLOC_INLINE void
|
||||
mb_write(void)
|
||||
{
|
||||
|
||||
# if 0
|
||||
/* This is a true memory barrier. */
|
||||
asm volatile ("pusha;"
|
||||
"xor %%eax,%%eax;"
|
||||
"cpuid;"
|
||||
"popa;"
|
||||
: /* Outputs. */
|
||||
: /* Inputs. */
|
||||
: "memory" /* Clobbers. */
|
||||
);
|
||||
#else
|
||||
/*
|
||||
* This is hopefully enough to keep the compiler from reordering
|
||||
* instructions around this one.
|
||||
*/
|
||||
asm volatile ("nop;"
|
||||
: /* Outputs. */
|
||||
: /* Inputs. */
|
||||
: "memory" /* Clobbers. */
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#elif (defined(__amd64_) || defined(__x86_64__))
|
||||
JEMALLOC_INLINE void
|
||||
mb_write(void)
|
||||
{
|
||||
|
||||
asm volatile ("sfence"
|
||||
: /* Outputs. */
|
||||
: /* Inputs. */
|
||||
: "memory" /* Clobbers. */
|
||||
);
|
||||
}
|
||||
#elif defined(__powerpc__)
|
||||
JEMALLOC_INLINE void
|
||||
mb_write(void)
|
||||
{
|
||||
|
||||
asm volatile ("eieio"
|
||||
: /* Outputs. */
|
||||
: /* Inputs. */
|
||||
: "memory" /* Clobbers. */
|
||||
);
|
||||
}
|
||||
#elif defined(__sparc64__)
|
||||
JEMALLOC_INLINE void
|
||||
mb_write(void)
|
||||
{
|
||||
|
||||
asm volatile ("membar #StoreStore"
|
||||
: /* Outputs. */
|
||||
: /* Inputs. */
|
||||
: "memory" /* Clobbers. */
|
||||
);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* This is much slower than a simple memory barrier, but the semantics of mutex
|
||||
* unlock make this work.
|
||||
*/
|
||||
JEMALLOC_INLINE void
|
||||
mb_write(void)
|
||||
{
|
||||
malloc_mutex_t mtx;
|
||||
|
||||
malloc_mutex_init(&mtx);
|
||||
malloc_mutex_lock(&mtx);
|
||||
malloc_mutex_unlock(&mtx);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
#ifdef JEMALLOC_OSSPIN
|
||||
typedef OSSpinLock malloc_mutex_t;
|
||||
#else
|
||||
typedef pthread_mutex_t malloc_mutex_t;
|
||||
#endif
|
||||
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
# define MALLOC_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
#else
|
||||
# define MALLOC_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
#ifdef JEMALLOC_LAZY_LOCK
|
||||
extern bool isthreaded;
|
||||
#else
|
||||
# define isthreaded true
|
||||
#endif
|
||||
|
||||
bool malloc_mutex_init(malloc_mutex_t *mutex);
|
||||
void malloc_mutex_destroy(malloc_mutex_t *mutex);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
void malloc_mutex_lock(malloc_mutex_t *mutex);
|
||||
bool malloc_mutex_trylock(malloc_mutex_t *mutex);
|
||||
void malloc_mutex_unlock(malloc_mutex_t *mutex);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
|
||||
JEMALLOC_INLINE void
|
||||
malloc_mutex_lock(malloc_mutex_t *mutex)
|
||||
{
|
||||
|
||||
if (isthreaded) {
|
||||
#ifdef JEMALLOC_OSSPIN
|
||||
OSSpinLockLock(mutex);
|
||||
#else
|
||||
pthread_mutex_lock(mutex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE bool
|
||||
malloc_mutex_trylock(malloc_mutex_t *mutex)
|
||||
{
|
||||
|
||||
if (isthreaded) {
|
||||
#ifdef JEMALLOC_OSSPIN
|
||||
return (OSSpinLockTry(mutex) == false);
|
||||
#else
|
||||
return (pthread_mutex_trylock(mutex) != 0);
|
||||
#endif
|
||||
} else
|
||||
return (false);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
malloc_mutex_unlock(malloc_mutex_t *mutex)
|
||||
{
|
||||
|
||||
if (isthreaded) {
|
||||
#ifdef JEMALLOC_OSSPIN
|
||||
OSSpinLockUnlock(mutex);
|
||||
#else
|
||||
pthread_mutex_unlock(mutex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
@@ -1,195 +0,0 @@
|
||||
#define arena_bin_index JEMALLOC_N(arena_bin_index)
|
||||
#define arena_boot JEMALLOC_N(arena_boot)
|
||||
#define arena_dalloc JEMALLOC_N(arena_dalloc)
|
||||
#define arena_dalloc_bin JEMALLOC_N(arena_dalloc_bin)
|
||||
#define arena_dalloc_large JEMALLOC_N(arena_dalloc_large)
|
||||
#define arena_malloc JEMALLOC_N(arena_malloc)
|
||||
#define arena_malloc_large JEMALLOC_N(arena_malloc_large)
|
||||
#define arena_malloc_small JEMALLOC_N(arena_malloc_small)
|
||||
#define arena_new JEMALLOC_N(arena_new)
|
||||
#define arena_palloc JEMALLOC_N(arena_palloc)
|
||||
#define arena_prof_accum JEMALLOC_N(arena_prof_accum)
|
||||
#define arena_prof_ctx_get JEMALLOC_N(arena_prof_ctx_get)
|
||||
#define arena_prof_ctx_set JEMALLOC_N(arena_prof_ctx_set)
|
||||
#define arena_prof_promoted JEMALLOC_N(arena_prof_promoted)
|
||||
#define arena_purge_all JEMALLOC_N(arena_purge_all)
|
||||
#define arena_ralloc JEMALLOC_N(arena_ralloc)
|
||||
#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move)
|
||||
#define arena_run_regind JEMALLOC_N(arena_run_regind)
|
||||
#define arena_salloc JEMALLOC_N(arena_salloc)
|
||||
#define arena_salloc_demote JEMALLOC_N(arena_salloc_demote)
|
||||
#define arena_stats_merge JEMALLOC_N(arena_stats_merge)
|
||||
#define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small)
|
||||
#define arenas_bin_i_index JEMALLOC_N(arenas_bin_i_index)
|
||||
#define arenas_extend JEMALLOC_N(arenas_extend)
|
||||
#define arenas_lrun_i_index JEMALLOC_N(arenas_lrun_i_index)
|
||||
#define atomic_add_uint32 JEMALLOC_N(atomic_add_uint32)
|
||||
#define atomic_add_uint64 JEMALLOC_N(atomic_add_uint64)
|
||||
#define atomic_sub_uint32 JEMALLOC_N(atomic_sub_uint32)
|
||||
#define atomic_sub_uint64 JEMALLOC_N(atomic_sub_uint64)
|
||||
#define base_alloc JEMALLOC_N(base_alloc)
|
||||
#define base_boot JEMALLOC_N(base_boot)
|
||||
#define base_node_alloc JEMALLOC_N(base_node_alloc)
|
||||
#define base_node_dealloc JEMALLOC_N(base_node_dealloc)
|
||||
#define bitmap_full JEMALLOC_N(bitmap_full)
|
||||
#define bitmap_get JEMALLOC_N(bitmap_get)
|
||||
#define bitmap_info_init JEMALLOC_N(bitmap_info_init)
|
||||
#define bitmap_info_ngroups JEMALLOC_N(bitmap_info_ngroups)
|
||||
#define bitmap_init JEMALLOC_N(bitmap_init)
|
||||
#define bitmap_set JEMALLOC_N(bitmap_set)
|
||||
#define bitmap_sfu JEMALLOC_N(bitmap_sfu)
|
||||
#define bitmap_size JEMALLOC_N(bitmap_size)
|
||||
#define bitmap_unset JEMALLOC_N(bitmap_unset)
|
||||
#define bt_init JEMALLOC_N(bt_init)
|
||||
#define buferror JEMALLOC_N(buferror)
|
||||
#define choose_arena JEMALLOC_N(choose_arena)
|
||||
#define choose_arena_hard JEMALLOC_N(choose_arena_hard)
|
||||
#define chunk_alloc JEMALLOC_N(chunk_alloc)
|
||||
#define chunk_alloc_dss JEMALLOC_N(chunk_alloc_dss)
|
||||
#define chunk_alloc_mmap JEMALLOC_N(chunk_alloc_mmap)
|
||||
#define chunk_alloc_mmap_noreserve JEMALLOC_N(chunk_alloc_mmap_noreserve)
|
||||
#define chunk_alloc_swap JEMALLOC_N(chunk_alloc_swap)
|
||||
#define chunk_boot JEMALLOC_N(chunk_boot)
|
||||
#define chunk_dealloc JEMALLOC_N(chunk_dealloc)
|
||||
#define chunk_dealloc_dss JEMALLOC_N(chunk_dealloc_dss)
|
||||
#define chunk_dealloc_mmap JEMALLOC_N(chunk_dealloc_mmap)
|
||||
#define chunk_dealloc_swap JEMALLOC_N(chunk_dealloc_swap)
|
||||
#define chunk_dss_boot JEMALLOC_N(chunk_dss_boot)
|
||||
#define chunk_in_dss JEMALLOC_N(chunk_in_dss)
|
||||
#define chunk_in_swap JEMALLOC_N(chunk_in_swap)
|
||||
#define chunk_mmap_boot JEMALLOC_N(chunk_mmap_boot)
|
||||
#define chunk_swap_boot JEMALLOC_N(chunk_swap_boot)
|
||||
#define chunk_swap_enable JEMALLOC_N(chunk_swap_enable)
|
||||
#define ckh_bucket_search JEMALLOC_N(ckh_bucket_search)
|
||||
#define ckh_count JEMALLOC_N(ckh_count)
|
||||
#define ckh_delete JEMALLOC_N(ckh_delete)
|
||||
#define ckh_evict_reloc_insert JEMALLOC_N(ckh_evict_reloc_insert)
|
||||
#define ckh_insert JEMALLOC_N(ckh_insert)
|
||||
#define ckh_isearch JEMALLOC_N(ckh_isearch)
|
||||
#define ckh_iter JEMALLOC_N(ckh_iter)
|
||||
#define ckh_new JEMALLOC_N(ckh_new)
|
||||
#define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash)
|
||||
#define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp)
|
||||
#define ckh_rebuild JEMALLOC_N(ckh_rebuild)
|
||||
#define ckh_remove JEMALLOC_N(ckh_remove)
|
||||
#define ckh_search JEMALLOC_N(ckh_search)
|
||||
#define ckh_string_hash JEMALLOC_N(ckh_string_hash)
|
||||
#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp)
|
||||
#define ckh_try_bucket_insert JEMALLOC_N(ckh_try_bucket_insert)
|
||||
#define ckh_try_insert JEMALLOC_N(ckh_try_insert)
|
||||
#define create_zone JEMALLOC_N(create_zone)
|
||||
#define ctl_boot JEMALLOC_N(ctl_boot)
|
||||
#define ctl_bymib JEMALLOC_N(ctl_bymib)
|
||||
#define ctl_byname JEMALLOC_N(ctl_byname)
|
||||
#define ctl_nametomib JEMALLOC_N(ctl_nametomib)
|
||||
#define extent_tree_ad_first JEMALLOC_N(extent_tree_ad_first)
|
||||
#define extent_tree_ad_insert JEMALLOC_N(extent_tree_ad_insert)
|
||||
#define extent_tree_ad_iter JEMALLOC_N(extent_tree_ad_iter)
|
||||
#define extent_tree_ad_iter_recurse JEMALLOC_N(extent_tree_ad_iter_recurse)
|
||||
#define extent_tree_ad_iter_start JEMALLOC_N(extent_tree_ad_iter_start)
|
||||
#define extent_tree_ad_last JEMALLOC_N(extent_tree_ad_last)
|
||||
#define extent_tree_ad_new JEMALLOC_N(extent_tree_ad_new)
|
||||
#define extent_tree_ad_next JEMALLOC_N(extent_tree_ad_next)
|
||||
#define extent_tree_ad_nsearch JEMALLOC_N(extent_tree_ad_nsearch)
|
||||
#define extent_tree_ad_prev JEMALLOC_N(extent_tree_ad_prev)
|
||||
#define extent_tree_ad_psearch JEMALLOC_N(extent_tree_ad_psearch)
|
||||
#define extent_tree_ad_remove JEMALLOC_N(extent_tree_ad_remove)
|
||||
#define extent_tree_ad_reverse_iter JEMALLOC_N(extent_tree_ad_reverse_iter)
|
||||
#define extent_tree_ad_reverse_iter_recurse JEMALLOC_N(extent_tree_ad_reverse_iter_recurse)
|
||||
#define extent_tree_ad_reverse_iter_start JEMALLOC_N(extent_tree_ad_reverse_iter_start)
|
||||
#define extent_tree_ad_search JEMALLOC_N(extent_tree_ad_search)
|
||||
#define extent_tree_szad_first JEMALLOC_N(extent_tree_szad_first)
|
||||
#define extent_tree_szad_insert JEMALLOC_N(extent_tree_szad_insert)
|
||||
#define extent_tree_szad_iter JEMALLOC_N(extent_tree_szad_iter)
|
||||
#define extent_tree_szad_iter_recurse JEMALLOC_N(extent_tree_szad_iter_recurse)
|
||||
#define extent_tree_szad_iter_start JEMALLOC_N(extent_tree_szad_iter_start)
|
||||
#define extent_tree_szad_last JEMALLOC_N(extent_tree_szad_last)
|
||||
#define extent_tree_szad_new JEMALLOC_N(extent_tree_szad_new)
|
||||
#define extent_tree_szad_next JEMALLOC_N(extent_tree_szad_next)
|
||||
#define extent_tree_szad_nsearch JEMALLOC_N(extent_tree_szad_nsearch)
|
||||
#define extent_tree_szad_prev JEMALLOC_N(extent_tree_szad_prev)
|
||||
#define extent_tree_szad_psearch JEMALLOC_N(extent_tree_szad_psearch)
|
||||
#define extent_tree_szad_remove JEMALLOC_N(extent_tree_szad_remove)
|
||||
#define extent_tree_szad_reverse_iter JEMALLOC_N(extent_tree_szad_reverse_iter)
|
||||
#define extent_tree_szad_reverse_iter_recurse JEMALLOC_N(extent_tree_szad_reverse_iter_recurse)
|
||||
#define extent_tree_szad_reverse_iter_start JEMALLOC_N(extent_tree_szad_reverse_iter_start)
|
||||
#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search)
|
||||
#define hash JEMALLOC_N(hash)
|
||||
#define huge_boot JEMALLOC_N(huge_boot)
|
||||
#define huge_dalloc JEMALLOC_N(huge_dalloc)
|
||||
#define huge_malloc JEMALLOC_N(huge_malloc)
|
||||
#define huge_palloc JEMALLOC_N(huge_palloc)
|
||||
#define huge_prof_ctx_get JEMALLOC_N(huge_prof_ctx_get)
|
||||
#define huge_prof_ctx_set JEMALLOC_N(huge_prof_ctx_set)
|
||||
#define huge_ralloc JEMALLOC_N(huge_ralloc)
|
||||
#define huge_ralloc_no_move JEMALLOC_N(huge_ralloc_no_move)
|
||||
#define huge_salloc JEMALLOC_N(huge_salloc)
|
||||
#define iallocm JEMALLOC_N(iallocm)
|
||||
#define icalloc JEMALLOC_N(icalloc)
|
||||
#define idalloc JEMALLOC_N(idalloc)
|
||||
#define imalloc JEMALLOC_N(imalloc)
|
||||
#define ipalloc JEMALLOC_N(ipalloc)
|
||||
#define iralloc JEMALLOC_N(iralloc)
|
||||
#define isalloc JEMALLOC_N(isalloc)
|
||||
#define ivsalloc JEMALLOC_N(ivsalloc)
|
||||
#define jemalloc_darwin_init JEMALLOC_N(jemalloc_darwin_init)
|
||||
#define jemalloc_postfork JEMALLOC_N(jemalloc_postfork)
|
||||
#define jemalloc_prefork JEMALLOC_N(jemalloc_prefork)
|
||||
#define malloc_cprintf JEMALLOC_N(malloc_cprintf)
|
||||
#define malloc_mutex_destroy JEMALLOC_N(malloc_mutex_destroy)
|
||||
#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init)
|
||||
#define malloc_mutex_lock JEMALLOC_N(malloc_mutex_lock)
|
||||
#define malloc_mutex_trylock JEMALLOC_N(malloc_mutex_trylock)
|
||||
#define malloc_mutex_unlock JEMALLOC_N(malloc_mutex_unlock)
|
||||
#define malloc_printf JEMALLOC_N(malloc_printf)
|
||||
#define malloc_write JEMALLOC_N(malloc_write)
|
||||
#define mb_write JEMALLOC_N(mb_write)
|
||||
#define pow2_ceil JEMALLOC_N(pow2_ceil)
|
||||
#define prof_backtrace JEMALLOC_N(prof_backtrace)
|
||||
#define prof_boot0 JEMALLOC_N(prof_boot0)
|
||||
#define prof_boot1 JEMALLOC_N(prof_boot1)
|
||||
#define prof_boot2 JEMALLOC_N(prof_boot2)
|
||||
#define prof_ctx_get JEMALLOC_N(prof_ctx_get)
|
||||
#define prof_ctx_set JEMALLOC_N(prof_ctx_set)
|
||||
#define prof_free JEMALLOC_N(prof_free)
|
||||
#define prof_gdump JEMALLOC_N(prof_gdump)
|
||||
#define prof_idump JEMALLOC_N(prof_idump)
|
||||
#define prof_lookup JEMALLOC_N(prof_lookup)
|
||||
#define prof_malloc JEMALLOC_N(prof_malloc)
|
||||
#define prof_mdump JEMALLOC_N(prof_mdump)
|
||||
#define prof_realloc JEMALLOC_N(prof_realloc)
|
||||
#define prof_sample_accum_update JEMALLOC_N(prof_sample_accum_update)
|
||||
#define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update)
|
||||
#define prof_tdata_init JEMALLOC_N(prof_tdata_init)
|
||||
#define pthread_create JEMALLOC_N(pthread_create)
|
||||
#define rtree_get JEMALLOC_N(rtree_get)
|
||||
#define rtree_get_locked JEMALLOC_N(rtree_get_locked)
|
||||
#define rtree_new JEMALLOC_N(rtree_new)
|
||||
#define rtree_set JEMALLOC_N(rtree_set)
|
||||
#define s2u JEMALLOC_N(s2u)
|
||||
#define sa2u JEMALLOC_N(sa2u)
|
||||
#define stats_arenas_i_bins_j_index JEMALLOC_N(stats_arenas_i_bins_j_index)
|
||||
#define stats_arenas_i_index JEMALLOC_N(stats_arenas_i_index)
|
||||
#define stats_arenas_i_lruns_j_index JEMALLOC_N(stats_arenas_i_lruns_j_index)
|
||||
#define stats_cactive_add JEMALLOC_N(stats_cactive_add)
|
||||
#define stats_cactive_get JEMALLOC_N(stats_cactive_get)
|
||||
#define stats_cactive_sub JEMALLOC_N(stats_cactive_sub)
|
||||
#define stats_print JEMALLOC_N(stats_print)
|
||||
#define szone2ozone JEMALLOC_N(szone2ozone)
|
||||
#define tcache_alloc_easy JEMALLOC_N(tcache_alloc_easy)
|
||||
#define tcache_alloc_large JEMALLOC_N(tcache_alloc_large)
|
||||
#define tcache_alloc_small JEMALLOC_N(tcache_alloc_small)
|
||||
#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard)
|
||||
#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large)
|
||||
#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small)
|
||||
#define tcache_boot JEMALLOC_N(tcache_boot)
|
||||
#define tcache_create JEMALLOC_N(tcache_create)
|
||||
#define tcache_dalloc_large JEMALLOC_N(tcache_dalloc_large)
|
||||
#define tcache_dalloc_small JEMALLOC_N(tcache_dalloc_small)
|
||||
#define tcache_destroy JEMALLOC_N(tcache_destroy)
|
||||
#define tcache_event JEMALLOC_N(tcache_event)
|
||||
#define tcache_get JEMALLOC_N(tcache_get)
|
||||
#define tcache_stats_merge JEMALLOC_N(tcache_stats_merge)
|
||||
#define thread_allocated_get JEMALLOC_N(thread_allocated_get)
|
||||
#define thread_allocated_get_hard JEMALLOC_N(thread_allocated_get_hard)
|
||||
#define u2s JEMALLOC_N(u2s)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
for symbol in `cat $1` ; do
|
||||
echo "#define ${symbol} JEMALLOC_N(${symbol})"
|
||||
done
|
||||
@@ -0,0 +1,413 @@
|
||||
a0calloc
|
||||
a0free
|
||||
a0malloc
|
||||
arena_alloc_junk_small
|
||||
arena_bin_index
|
||||
arena_bin_info
|
||||
arena_boot
|
||||
arena_dalloc
|
||||
arena_dalloc_bin
|
||||
arena_dalloc_bin_locked
|
||||
arena_dalloc_junk_large
|
||||
arena_dalloc_junk_small
|
||||
arena_dalloc_large
|
||||
arena_dalloc_large_locked
|
||||
arena_dalloc_small
|
||||
arena_dss_prec_get
|
||||
arena_dss_prec_set
|
||||
arena_malloc
|
||||
arena_malloc_large
|
||||
arena_malloc_small
|
||||
arena_mapbits_allocated_get
|
||||
arena_mapbits_binind_get
|
||||
arena_mapbits_dirty_get
|
||||
arena_mapbits_get
|
||||
arena_mapbits_large_binind_set
|
||||
arena_mapbits_large_get
|
||||
arena_mapbits_large_set
|
||||
arena_mapbits_large_size_get
|
||||
arena_mapbits_small_runind_get
|
||||
arena_mapbits_small_set
|
||||
arena_mapbits_unallocated_set
|
||||
arena_mapbits_unallocated_size_get
|
||||
arena_mapbits_unallocated_size_set
|
||||
arena_mapbits_unzeroed_get
|
||||
arena_mapbits_unzeroed_set
|
||||
arena_mapbitsp_get
|
||||
arena_mapbitsp_read
|
||||
arena_mapbitsp_write
|
||||
arena_mapp_get
|
||||
arena_maxclass
|
||||
arena_new
|
||||
arena_palloc
|
||||
arena_postfork_child
|
||||
arena_postfork_parent
|
||||
arena_prefork
|
||||
arena_prof_accum
|
||||
arena_prof_accum_impl
|
||||
arena_prof_accum_locked
|
||||
arena_prof_ctx_get
|
||||
arena_prof_ctx_set
|
||||
arena_prof_promoted
|
||||
arena_ptr_small_binind_get
|
||||
arena_purge_all
|
||||
arena_quarantine_junk_small
|
||||
arena_ralloc
|
||||
arena_ralloc_junk_large
|
||||
arena_ralloc_no_move
|
||||
arena_redzone_corruption
|
||||
arena_run_regind
|
||||
arena_salloc
|
||||
arena_stats_merge
|
||||
arena_tcache_fill_small
|
||||
arenas
|
||||
arenas_booted
|
||||
arenas_cleanup
|
||||
arenas_extend
|
||||
arenas_initialized
|
||||
arenas_lock
|
||||
arenas_tls
|
||||
arenas_tsd
|
||||
arenas_tsd_boot
|
||||
arenas_tsd_cleanup_wrapper
|
||||
arenas_tsd_get
|
||||
arenas_tsd_get_wrapper
|
||||
arenas_tsd_init_head
|
||||
arenas_tsd_set
|
||||
atomic_add_u
|
||||
atomic_add_uint32
|
||||
atomic_add_uint64
|
||||
atomic_add_z
|
||||
atomic_sub_u
|
||||
atomic_sub_uint32
|
||||
atomic_sub_uint64
|
||||
atomic_sub_z
|
||||
base_alloc
|
||||
base_boot
|
||||
base_calloc
|
||||
base_node_alloc
|
||||
base_node_dealloc
|
||||
base_postfork_child
|
||||
base_postfork_parent
|
||||
base_prefork
|
||||
bitmap_full
|
||||
bitmap_get
|
||||
bitmap_info_init
|
||||
bitmap_info_ngroups
|
||||
bitmap_init
|
||||
bitmap_set
|
||||
bitmap_sfu
|
||||
bitmap_size
|
||||
bitmap_unset
|
||||
bt_init
|
||||
buferror
|
||||
choose_arena
|
||||
choose_arena_hard
|
||||
chunk_alloc
|
||||
chunk_alloc_dss
|
||||
chunk_alloc_mmap
|
||||
chunk_boot
|
||||
chunk_dealloc
|
||||
chunk_dealloc_mmap
|
||||
chunk_dss_boot
|
||||
chunk_dss_postfork_child
|
||||
chunk_dss_postfork_parent
|
||||
chunk_dss_prec_get
|
||||
chunk_dss_prec_set
|
||||
chunk_dss_prefork
|
||||
chunk_in_dss
|
||||
chunk_npages
|
||||
chunk_postfork_child
|
||||
chunk_postfork_parent
|
||||
chunk_prefork
|
||||
chunk_unmap
|
||||
chunks_mtx
|
||||
chunks_rtree
|
||||
chunksize
|
||||
chunksize_mask
|
||||
ckh_bucket_search
|
||||
ckh_count
|
||||
ckh_delete
|
||||
ckh_evict_reloc_insert
|
||||
ckh_insert
|
||||
ckh_isearch
|
||||
ckh_iter
|
||||
ckh_new
|
||||
ckh_pointer_hash
|
||||
ckh_pointer_keycomp
|
||||
ckh_rebuild
|
||||
ckh_remove
|
||||
ckh_search
|
||||
ckh_string_hash
|
||||
ckh_string_keycomp
|
||||
ckh_try_bucket_insert
|
||||
ckh_try_insert
|
||||
ctl_boot
|
||||
ctl_bymib
|
||||
ctl_byname
|
||||
ctl_nametomib
|
||||
ctl_postfork_child
|
||||
ctl_postfork_parent
|
||||
ctl_prefork
|
||||
dss_prec_names
|
||||
extent_tree_ad_first
|
||||
extent_tree_ad_insert
|
||||
extent_tree_ad_iter
|
||||
extent_tree_ad_iter_recurse
|
||||
extent_tree_ad_iter_start
|
||||
extent_tree_ad_last
|
||||
extent_tree_ad_new
|
||||
extent_tree_ad_next
|
||||
extent_tree_ad_nsearch
|
||||
extent_tree_ad_prev
|
||||
extent_tree_ad_psearch
|
||||
extent_tree_ad_remove
|
||||
extent_tree_ad_reverse_iter
|
||||
extent_tree_ad_reverse_iter_recurse
|
||||
extent_tree_ad_reverse_iter_start
|
||||
extent_tree_ad_search
|
||||
extent_tree_szad_first
|
||||
extent_tree_szad_insert
|
||||
extent_tree_szad_iter
|
||||
extent_tree_szad_iter_recurse
|
||||
extent_tree_szad_iter_start
|
||||
extent_tree_szad_last
|
||||
extent_tree_szad_new
|
||||
extent_tree_szad_next
|
||||
extent_tree_szad_nsearch
|
||||
extent_tree_szad_prev
|
||||
extent_tree_szad_psearch
|
||||
extent_tree_szad_remove
|
||||
extent_tree_szad_reverse_iter
|
||||
extent_tree_szad_reverse_iter_recurse
|
||||
extent_tree_szad_reverse_iter_start
|
||||
extent_tree_szad_search
|
||||
get_errno
|
||||
hash
|
||||
hash_fmix_32
|
||||
hash_fmix_64
|
||||
hash_get_block_32
|
||||
hash_get_block_64
|
||||
hash_rotl_32
|
||||
hash_rotl_64
|
||||
hash_x64_128
|
||||
hash_x86_128
|
||||
hash_x86_32
|
||||
huge_allocated
|
||||
huge_boot
|
||||
huge_dalloc
|
||||
huge_dalloc_junk
|
||||
huge_dss_prec_get
|
||||
huge_malloc
|
||||
huge_mtx
|
||||
huge_ndalloc
|
||||
huge_nmalloc
|
||||
huge_palloc
|
||||
huge_postfork_child
|
||||
huge_postfork_parent
|
||||
huge_prefork
|
||||
huge_prof_ctx_get
|
||||
huge_prof_ctx_set
|
||||
huge_ralloc
|
||||
huge_ralloc_no_move
|
||||
huge_salloc
|
||||
iallocm
|
||||
icalloc
|
||||
icalloct
|
||||
idalloc
|
||||
idalloct
|
||||
imalloc
|
||||
imalloct
|
||||
ipalloc
|
||||
ipalloct
|
||||
iqalloc
|
||||
iqalloct
|
||||
iralloc
|
||||
iralloct
|
||||
iralloct_realign
|
||||
isalloc
|
||||
isthreaded
|
||||
ivsalloc
|
||||
ixalloc
|
||||
jemalloc_postfork_child
|
||||
jemalloc_postfork_parent
|
||||
jemalloc_prefork
|
||||
malloc_cprintf
|
||||
malloc_mutex_init
|
||||
malloc_mutex_lock
|
||||
malloc_mutex_postfork_child
|
||||
malloc_mutex_postfork_parent
|
||||
malloc_mutex_prefork
|
||||
malloc_mutex_unlock
|
||||
malloc_printf
|
||||
malloc_snprintf
|
||||
malloc_strtoumax
|
||||
malloc_tsd_boot
|
||||
malloc_tsd_cleanup_register
|
||||
malloc_tsd_dalloc
|
||||
malloc_tsd_malloc
|
||||
malloc_tsd_no_cleanup
|
||||
malloc_vcprintf
|
||||
malloc_vsnprintf
|
||||
malloc_write
|
||||
map_bias
|
||||
mb_write
|
||||
mutex_boot
|
||||
narenas_auto
|
||||
narenas_total
|
||||
narenas_total_get
|
||||
ncpus
|
||||
nhbins
|
||||
opt_abort
|
||||
opt_dss
|
||||
opt_junk
|
||||
opt_lg_chunk
|
||||
opt_lg_dirty_mult
|
||||
opt_lg_prof_interval
|
||||
opt_lg_prof_sample
|
||||
opt_lg_tcache_max
|
||||
opt_narenas
|
||||
opt_prof
|
||||
opt_prof_accum
|
||||
opt_prof_active
|
||||
opt_prof_final
|
||||
opt_prof_gdump
|
||||
opt_prof_leak
|
||||
opt_prof_prefix
|
||||
opt_quarantine
|
||||
opt_redzone
|
||||
opt_stats_print
|
||||
opt_tcache
|
||||
opt_utrace
|
||||
opt_valgrind
|
||||
opt_xmalloc
|
||||
opt_zero
|
||||
p2rz
|
||||
pages_purge
|
||||
pow2_ceil
|
||||
prof_backtrace
|
||||
prof_boot0
|
||||
prof_boot1
|
||||
prof_boot2
|
||||
prof_bt_count
|
||||
prof_ctx_get
|
||||
prof_ctx_set
|
||||
prof_dump_open
|
||||
prof_free
|
||||
prof_gdump
|
||||
prof_idump
|
||||
prof_interval
|
||||
prof_lookup
|
||||
prof_malloc
|
||||
prof_mdump
|
||||
prof_postfork_child
|
||||
prof_postfork_parent
|
||||
prof_prefork
|
||||
prof_promote
|
||||
prof_realloc
|
||||
prof_sample_accum_update
|
||||
prof_sample_threshold_update
|
||||
prof_tdata_booted
|
||||
prof_tdata_cleanup
|
||||
prof_tdata_get
|
||||
prof_tdata_init
|
||||
prof_tdata_initialized
|
||||
prof_tdata_tls
|
||||
prof_tdata_tsd
|
||||
prof_tdata_tsd_boot
|
||||
prof_tdata_tsd_cleanup_wrapper
|
||||
prof_tdata_tsd_get
|
||||
prof_tdata_tsd_get_wrapper
|
||||
prof_tdata_tsd_init_head
|
||||
prof_tdata_tsd_set
|
||||
quarantine
|
||||
quarantine_alloc_hook
|
||||
quarantine_boot
|
||||
quarantine_booted
|
||||
quarantine_cleanup
|
||||
quarantine_init
|
||||
quarantine_tls
|
||||
quarantine_tsd
|
||||
quarantine_tsd_boot
|
||||
quarantine_tsd_cleanup_wrapper
|
||||
quarantine_tsd_get
|
||||
quarantine_tsd_get_wrapper
|
||||
quarantine_tsd_init_head
|
||||
quarantine_tsd_set
|
||||
register_zone
|
||||
rtree_delete
|
||||
rtree_get
|
||||
rtree_get_locked
|
||||
rtree_new
|
||||
rtree_postfork_child
|
||||
rtree_postfork_parent
|
||||
rtree_prefork
|
||||
rtree_set
|
||||
s2u
|
||||
sa2u
|
||||
set_errno
|
||||
small_size2bin
|
||||
stats_cactive
|
||||
stats_cactive_add
|
||||
stats_cactive_get
|
||||
stats_cactive_sub
|
||||
stats_chunks
|
||||
stats_print
|
||||
tcache_alloc_easy
|
||||
tcache_alloc_large
|
||||
tcache_alloc_small
|
||||
tcache_alloc_small_hard
|
||||
tcache_arena_associate
|
||||
tcache_arena_dissociate
|
||||
tcache_bin_flush_large
|
||||
tcache_bin_flush_small
|
||||
tcache_bin_info
|
||||
tcache_boot0
|
||||
tcache_boot1
|
||||
tcache_booted
|
||||
tcache_create
|
||||
tcache_dalloc_large
|
||||
tcache_dalloc_small
|
||||
tcache_destroy
|
||||
tcache_enabled_booted
|
||||
tcache_enabled_get
|
||||
tcache_enabled_initialized
|
||||
tcache_enabled_set
|
||||
tcache_enabled_tls
|
||||
tcache_enabled_tsd
|
||||
tcache_enabled_tsd_boot
|
||||
tcache_enabled_tsd_cleanup_wrapper
|
||||
tcache_enabled_tsd_get
|
||||
tcache_enabled_tsd_get_wrapper
|
||||
tcache_enabled_tsd_init_head
|
||||
tcache_enabled_tsd_set
|
||||
tcache_event
|
||||
tcache_event_hard
|
||||
tcache_flush
|
||||
tcache_get
|
||||
tcache_initialized
|
||||
tcache_maxclass
|
||||
tcache_salloc
|
||||
tcache_stats_merge
|
||||
tcache_thread_cleanup
|
||||
tcache_tls
|
||||
tcache_tsd
|
||||
tcache_tsd_boot
|
||||
tcache_tsd_cleanup_wrapper
|
||||
tcache_tsd_get
|
||||
tcache_tsd_get_wrapper
|
||||
tcache_tsd_init_head
|
||||
tcache_tsd_set
|
||||
thread_allocated_booted
|
||||
thread_allocated_initialized
|
||||
thread_allocated_tls
|
||||
thread_allocated_tsd
|
||||
thread_allocated_tsd_boot
|
||||
thread_allocated_tsd_cleanup_wrapper
|
||||
thread_allocated_tsd_get
|
||||
thread_allocated_tsd_get_wrapper
|
||||
thread_allocated_tsd_init_head
|
||||
thread_allocated_tsd_set
|
||||
tsd_init_check_recursion
|
||||
tsd_init_finish
|
||||
u2rz
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
for symbol in `cat $1` ; do
|
||||
echo "#undef ${symbol}"
|
||||
done
|
||||
Vendored
+4
-4
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
* Simple linear congruential pseudo-random number generator:
|
||||
*
|
||||
* prn(y) = (a*x + c) % m
|
||||
* prng(y) = (a*x + c) % m
|
||||
*
|
||||
* where the following constants ensure maximal period:
|
||||
*
|
||||
@@ -25,7 +25,7 @@
|
||||
* uint32_t state : Seed value.
|
||||
* const uint32_t a, c : See above discussion.
|
||||
*/
|
||||
#define prn32(r, lg_range, state, a, c) do { \
|
||||
#define prng32(r, lg_range, state, a, c) do { \
|
||||
assert(lg_range > 0); \
|
||||
assert(lg_range <= 32); \
|
||||
\
|
||||
@@ -34,8 +34,8 @@
|
||||
r >>= (32 - lg_range); \
|
||||
} while (false)
|
||||
|
||||
/* Same as prn32(), but 64 bits of pseudo-randomness, using uint64_t. */
|
||||
#define prn64(r, lg_range, state, a, c) do { \
|
||||
/* Same as prng32(), but 64 bits of pseudo-randomness, using uint64_t. */
|
||||
#define prng64(r, lg_range, state, a, c) do { \
|
||||
assert(lg_range > 0); \
|
||||
assert(lg_range <= 64); \
|
||||
\
|
||||
+167
-101
@@ -1,4 +1,3 @@
|
||||
#ifdef JEMALLOC_PROF
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
@@ -9,29 +8,46 @@ typedef struct prof_ctx_s prof_ctx_t;
|
||||
typedef struct prof_tdata_s prof_tdata_t;
|
||||
|
||||
/* Option defaults. */
|
||||
#define PROF_PREFIX_DEFAULT "jeprof"
|
||||
#define LG_PROF_BT_MAX_DEFAULT 7
|
||||
#define LG_PROF_SAMPLE_DEFAULT 0
|
||||
#ifdef JEMALLOC_PROF
|
||||
# define PROF_PREFIX_DEFAULT "jeprof"
|
||||
#else
|
||||
# define PROF_PREFIX_DEFAULT ""
|
||||
#endif
|
||||
#define LG_PROF_SAMPLE_DEFAULT 19
|
||||
#define LG_PROF_INTERVAL_DEFAULT -1
|
||||
#define LG_PROF_TCMAX_DEFAULT -1
|
||||
|
||||
/*
|
||||
* Hard limit on stack backtrace depth. Note that the version of
|
||||
* prof_backtrace() that is based on __builtin_return_address() necessarily has
|
||||
* a hard-coded number of backtrace frame handlers.
|
||||
* Hard limit on stack backtrace depth. The version of prof_backtrace() that
|
||||
* is based on __builtin_return_address() necessarily has a hard-coded number
|
||||
* of backtrace frame handlers, and should be kept in sync with this setting.
|
||||
*/
|
||||
#if (defined(JEMALLOC_PROF_LIBGCC) || defined(JEMALLOC_PROF_LIBUNWIND))
|
||||
# define LG_PROF_BT_MAX ((ZU(1) << (LG_SIZEOF_PTR+3)) - 1)
|
||||
#else
|
||||
# define LG_PROF_BT_MAX 7 /* >= LG_PROF_BT_MAX_DEFAULT */
|
||||
#endif
|
||||
#define PROF_BT_MAX (1U << LG_PROF_BT_MAX)
|
||||
#define PROF_BT_MAX 128
|
||||
|
||||
/* Maximum number of backtraces to store in each per thread LRU cache. */
|
||||
#define PROF_TCMAX 1024
|
||||
|
||||
/* Initial hash table size. */
|
||||
#define PROF_CKH_MINITEMS 64
|
||||
#define PROF_CKH_MINITEMS 64
|
||||
|
||||
/* Size of memory buffer to use when writing dump files. */
|
||||
#define PROF_DUMP_BUF_SIZE 65536
|
||||
#define PROF_DUMP_BUFSIZE 65536
|
||||
|
||||
/* Size of stack-allocated buffer used by prof_printf(). */
|
||||
#define PROF_PRINTF_BUFSIZE 128
|
||||
|
||||
/*
|
||||
* Number of mutexes shared among all ctx's. No space is allocated for these
|
||||
* unless profiling is enabled, so it's okay to over-provision.
|
||||
*/
|
||||
#define PROF_NCTX_LOCKS 1024
|
||||
|
||||
/*
|
||||
* prof_tdata pointers close to NULL are used to encode state information that
|
||||
* is used for cleaning up during thread shutdown.
|
||||
*/
|
||||
#define PROF_TDATA_STATE_REINCARNATED ((prof_tdata_t *)(uintptr_t)1)
|
||||
#define PROF_TDATA_STATE_PURGATORY ((prof_tdata_t *)(uintptr_t)2)
|
||||
#define PROF_TDATA_STATE_MAX PROF_TDATA_STATE_PURGATORY
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
@@ -109,8 +125,19 @@ struct prof_ctx_s {
|
||||
/* Associated backtrace. */
|
||||
prof_bt_t *bt;
|
||||
|
||||
/* Protects cnt_merged and cnts_ql. */
|
||||
malloc_mutex_t lock;
|
||||
/* Protects nlimbo, cnt_merged, and cnts_ql. */
|
||||
malloc_mutex_t *lock;
|
||||
|
||||
/*
|
||||
* Number of threads that currently cause this ctx to be in a state of
|
||||
* limbo due to one of:
|
||||
* - Initializing per thread counters associated with this ctx.
|
||||
* - Preparing to destroy this ctx.
|
||||
* - Dumping a heap profile that includes this ctx.
|
||||
* nlimbo must be 1 (single destroyer) in order to safely destroy the
|
||||
* ctx.
|
||||
*/
|
||||
unsigned nlimbo;
|
||||
|
||||
/* Temporary storage for summation during dump. */
|
||||
prof_cnt_t cnt_summed;
|
||||
@@ -123,7 +150,11 @@ struct prof_ctx_s {
|
||||
* this context.
|
||||
*/
|
||||
ql_head(prof_thr_cnt_t) cnts_ql;
|
||||
|
||||
/* Linkage for list of contexts to be dumped. */
|
||||
ql_elm(prof_ctx_t) dump_link;
|
||||
};
|
||||
typedef ql_head(prof_ctx_t) prof_ctx_list_t;
|
||||
|
||||
struct prof_tdata_s {
|
||||
/*
|
||||
@@ -145,9 +176,14 @@ struct prof_tdata_s {
|
||||
void **vec;
|
||||
|
||||
/* Sampling state. */
|
||||
uint64_t prn_state;
|
||||
uint64_t prng_state;
|
||||
uint64_t threshold;
|
||||
uint64_t accum;
|
||||
|
||||
/* State used to avoid dumping while operating on prof internals. */
|
||||
bool enq;
|
||||
bool enq_idump;
|
||||
bool enq_gdump;
|
||||
};
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
@@ -162,14 +198,18 @@ extern bool opt_prof;
|
||||
* to notice state changes.
|
||||
*/
|
||||
extern bool opt_prof_active;
|
||||
extern size_t opt_lg_prof_bt_max; /* Maximum backtrace depth. */
|
||||
extern size_t opt_lg_prof_sample; /* Mean bytes between samples. */
|
||||
extern ssize_t opt_lg_prof_interval; /* lg(prof_interval). */
|
||||
extern bool opt_prof_gdump; /* High-water memory dumping. */
|
||||
extern bool opt_prof_final; /* Final profile dumping. */
|
||||
extern bool opt_prof_leak; /* Dump leak summary at exit. */
|
||||
extern bool opt_prof_accum; /* Report cumulative bytes. */
|
||||
extern ssize_t opt_lg_prof_tcmax; /* lg(max per thread bactrace cache) */
|
||||
extern char opt_prof_prefix[PATH_MAX + 1];
|
||||
extern char opt_prof_prefix[
|
||||
/* Minimize memory bloat for non-prof builds. */
|
||||
#ifdef JEMALLOC_PROF
|
||||
PATH_MAX +
|
||||
#endif
|
||||
1];
|
||||
|
||||
/*
|
||||
* Profile dump interval, measured in bytes allocated. Each arena triggers a
|
||||
@@ -186,42 +226,25 @@ extern uint64_t prof_interval;
|
||||
*/
|
||||
extern bool prof_promote;
|
||||
|
||||
/* (1U << opt_lg_prof_bt_max). */
|
||||
extern unsigned prof_bt_max;
|
||||
|
||||
/* Thread-specific backtrace cache, used to reduce bt2ctx contention. */
|
||||
#ifndef NO_TLS
|
||||
extern __thread prof_tdata_t *prof_tdata_tls
|
||||
JEMALLOC_ATTR(tls_model("initial-exec"));
|
||||
# define PROF_TCACHE_GET() prof_tdata_tls
|
||||
# define PROF_TCACHE_SET(v) do { \
|
||||
prof_tdata_tls = (v); \
|
||||
pthread_setspecific(prof_tdata_tsd, (void *)(v)); \
|
||||
} while (0)
|
||||
#else
|
||||
# define PROF_TCACHE_GET() \
|
||||
((prof_tdata_t *)pthread_getspecific(prof_tdata_tsd))
|
||||
# define PROF_TCACHE_SET(v) do { \
|
||||
pthread_setspecific(prof_tdata_tsd, (void *)(v)); \
|
||||
} while (0)
|
||||
#endif
|
||||
/*
|
||||
* Same contents as b2cnt_tls, but initialized such that the TSD destructor is
|
||||
* called when a thread exits, so that prof_tdata_tls contents can be merged,
|
||||
* unlinked, and deallocated.
|
||||
*/
|
||||
extern pthread_key_t prof_tdata_tsd;
|
||||
|
||||
void bt_init(prof_bt_t *bt, void **vec);
|
||||
void prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max);
|
||||
void prof_backtrace(prof_bt_t *bt, unsigned nignore);
|
||||
prof_thr_cnt_t *prof_lookup(prof_bt_t *bt);
|
||||
#ifdef JEMALLOC_JET
|
||||
size_t prof_bt_count(void);
|
||||
typedef int (prof_dump_open_t)(bool, const char *);
|
||||
extern prof_dump_open_t *prof_dump_open;
|
||||
#endif
|
||||
void prof_idump(void);
|
||||
bool prof_mdump(const char *filename);
|
||||
void prof_gdump(void);
|
||||
prof_tdata_t *prof_tdata_init(void);
|
||||
void prof_tdata_cleanup(void *arg);
|
||||
void prof_boot0(void);
|
||||
void prof_boot1(void);
|
||||
bool prof_boot2(void);
|
||||
void prof_prefork(void);
|
||||
void prof_postfork_parent(void);
|
||||
void prof_postfork_child(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
@@ -233,13 +256,13 @@ bool prof_boot2(void);
|
||||
\
|
||||
assert(size == s2u(size)); \
|
||||
\
|
||||
prof_tdata = PROF_TCACHE_GET(); \
|
||||
if (prof_tdata == NULL) { \
|
||||
prof_tdata = prof_tdata_init(); \
|
||||
if (prof_tdata == NULL) { \
|
||||
prof_tdata = prof_tdata_get(true); \
|
||||
if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) { \
|
||||
if (prof_tdata != NULL) \
|
||||
ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
|
||||
else \
|
||||
ret = NULL; \
|
||||
break; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (opt_prof_active == false) { \
|
||||
@@ -249,13 +272,13 @@ bool prof_boot2(void);
|
||||
/* Don't bother with sampling logic, since sampling */\
|
||||
/* interval is 1. */\
|
||||
bt_init(&bt, prof_tdata->vec); \
|
||||
prof_backtrace(&bt, nignore, prof_bt_max); \
|
||||
prof_backtrace(&bt, nignore); \
|
||||
ret = prof_lookup(&bt); \
|
||||
} else { \
|
||||
if (prof_tdata->threshold == 0) { \
|
||||
/* Initialize. Seed the prng differently for */\
|
||||
/* each thread. */\
|
||||
prof_tdata->prn_state = \
|
||||
prof_tdata->prng_state = \
|
||||
(uint64_t)(uintptr_t)&size; \
|
||||
prof_sample_threshold_update(prof_tdata); \
|
||||
} \
|
||||
@@ -272,7 +295,7 @@ bool prof_boot2(void);
|
||||
if (size >= prof_tdata->threshold - \
|
||||
prof_tdata->accum) { \
|
||||
bt_init(&bt, prof_tdata->vec); \
|
||||
prof_backtrace(&bt, nignore, prof_bt_max); \
|
||||
prof_backtrace(&bt, nignore); \
|
||||
ret = prof_lookup(&bt); \
|
||||
} else \
|
||||
ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
|
||||
@@ -280,23 +303,61 @@ bool prof_boot2(void);
|
||||
} while (0)
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
malloc_tsd_protos(JEMALLOC_ATTR(unused), prof_tdata, prof_tdata_t *)
|
||||
|
||||
prof_tdata_t *prof_tdata_get(bool create);
|
||||
void prof_sample_threshold_update(prof_tdata_t *prof_tdata);
|
||||
prof_ctx_t *prof_ctx_get(const void *ptr);
|
||||
void prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
|
||||
void prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx);
|
||||
bool prof_sample_accum_update(size_t size);
|
||||
void prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt);
|
||||
void prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
|
||||
size_t old_size, prof_ctx_t *old_ctx);
|
||||
void prof_malloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt);
|
||||
void prof_realloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt,
|
||||
size_t old_usize, prof_ctx_t *old_ctx);
|
||||
void prof_free(const void *ptr, size_t size);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_PROF_C_))
|
||||
/* Thread-specific backtrace cache, used to reduce bt2ctx contention. */
|
||||
malloc_tsd_externs(prof_tdata, prof_tdata_t *)
|
||||
malloc_tsd_funcs(JEMALLOC_INLINE, prof_tdata, prof_tdata_t *, NULL,
|
||||
prof_tdata_cleanup)
|
||||
|
||||
JEMALLOC_INLINE prof_tdata_t *
|
||||
prof_tdata_get(bool create)
|
||||
{
|
||||
prof_tdata_t *prof_tdata;
|
||||
|
||||
cassert(config_prof);
|
||||
|
||||
prof_tdata = *prof_tdata_tsd_get();
|
||||
if (create && prof_tdata == NULL)
|
||||
prof_tdata = prof_tdata_init();
|
||||
|
||||
return (prof_tdata);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
prof_sample_threshold_update(prof_tdata_t *prof_tdata)
|
||||
{
|
||||
/*
|
||||
* The body of this function is compiled out unless heap profiling is
|
||||
* enabled, so that it is possible to compile jemalloc with floating
|
||||
* point support completely disabled. Avoiding floating point code is
|
||||
* important on memory-constrained systems, but it also enables a
|
||||
* workaround for versions of glibc that don't properly save/restore
|
||||
* floating point registers during dynamic lazy symbol loading (which
|
||||
* internally calls into whatever malloc implementation happens to be
|
||||
* integrated into the application). Note that some compilers (e.g.
|
||||
* gcc 4.8) may use floating point registers for fast memory moves, so
|
||||
* jemalloc must be compiled with such optimizations disabled (e.g.
|
||||
* -mno-sse) in order for the workaround to be complete.
|
||||
*/
|
||||
#ifdef JEMALLOC_PROF
|
||||
uint64_t r;
|
||||
double u;
|
||||
|
||||
cassert(config_prof);
|
||||
|
||||
/*
|
||||
* Compute sample threshold as a geometrically distributed random
|
||||
* variable with mean (2^opt_lg_prof_sample).
|
||||
@@ -313,14 +374,15 @@ prof_sample_threshold_update(prof_tdata_t *prof_tdata)
|
||||
* Luc Devroye
|
||||
* Springer-Verlag, New York, 1986
|
||||
* pp 500
|
||||
* (http://cg.scs.carleton.ca/~luc/rnbookindex.html)
|
||||
* (http://luc.devroye.org/rnbookindex.html)
|
||||
*/
|
||||
prn64(r, 53, prof_tdata->prn_state,
|
||||
(uint64_t)6364136223846793005LLU, (uint64_t)1442695040888963407LLU);
|
||||
prng64(r, 53, prof_tdata->prng_state,
|
||||
UINT64_C(6364136223846793005), UINT64_C(1442695040888963407));
|
||||
u = (double)r * (1.0/9007199254740992.0L);
|
||||
prof_tdata->threshold = (uint64_t)(log(u) /
|
||||
log(1.0 - (1.0 / (double)((uint64_t)1U << opt_lg_prof_sample))))
|
||||
+ (uint64_t)1U;
|
||||
#endif
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE prof_ctx_t *
|
||||
@@ -329,13 +391,12 @@ prof_ctx_get(const void *ptr)
|
||||
prof_ctx_t *ret;
|
||||
arena_chunk_t *chunk;
|
||||
|
||||
cassert(config_prof);
|
||||
assert(ptr != NULL);
|
||||
|
||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||
if (chunk != ptr) {
|
||||
/* Region. */
|
||||
dassert(chunk->arena->magic == ARENA_MAGIC);
|
||||
|
||||
ret = arena_prof_ctx_get(ptr);
|
||||
} else
|
||||
ret = huge_prof_ctx_get(ptr);
|
||||
@@ -344,18 +405,17 @@ prof_ctx_get(const void *ptr)
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
prof_ctx_set(const void *ptr, prof_ctx_t *ctx)
|
||||
prof_ctx_set(const void *ptr, size_t usize, prof_ctx_t *ctx)
|
||||
{
|
||||
arena_chunk_t *chunk;
|
||||
|
||||
cassert(config_prof);
|
||||
assert(ptr != NULL);
|
||||
|
||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||
if (chunk != ptr) {
|
||||
/* Region. */
|
||||
dassert(chunk->arena->magic == ARENA_MAGIC);
|
||||
|
||||
arena_prof_ctx_set(ptr, ctx);
|
||||
arena_prof_ctx_set(ptr, usize, ctx);
|
||||
} else
|
||||
huge_prof_ctx_set(ptr, ctx);
|
||||
}
|
||||
@@ -365,11 +425,13 @@ prof_sample_accum_update(size_t size)
|
||||
{
|
||||
prof_tdata_t *prof_tdata;
|
||||
|
||||
cassert(config_prof);
|
||||
/* Sampling logic is unnecessary if the interval is 1. */
|
||||
assert(opt_lg_prof_sample != 0);
|
||||
|
||||
prof_tdata = PROF_TCACHE_GET();
|
||||
assert(prof_tdata != NULL);
|
||||
prof_tdata = prof_tdata_get(false);
|
||||
if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)
|
||||
return (true);
|
||||
|
||||
/* Take care to avoid integer overflow. */
|
||||
if (size >= prof_tdata->threshold - prof_tdata->accum) {
|
||||
@@ -388,19 +450,20 @@ prof_sample_accum_update(size_t size)
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt)
|
||||
prof_malloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt)
|
||||
{
|
||||
|
||||
cassert(config_prof);
|
||||
assert(ptr != NULL);
|
||||
assert(size == isalloc(ptr));
|
||||
assert(usize == isalloc(ptr, true));
|
||||
|
||||
if (opt_lg_prof_sample != 0) {
|
||||
if (prof_sample_accum_update(size)) {
|
||||
if (prof_sample_accum_update(usize)) {
|
||||
/*
|
||||
* Don't sample. For malloc()-like allocation, it is
|
||||
* always possible to tell in advance how large an
|
||||
* object's usable size will be, so there should never
|
||||
* be a difference between the size passed to
|
||||
* be a difference between the usize passed to
|
||||
* PROF_ALLOC_PREP() and prof_malloc().
|
||||
*/
|
||||
assert((uintptr_t)cnt == (uintptr_t)1U);
|
||||
@@ -408,17 +471,17 @@ prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt)
|
||||
}
|
||||
|
||||
if ((uintptr_t)cnt > (uintptr_t)1U) {
|
||||
prof_ctx_set(ptr, cnt->ctx);
|
||||
prof_ctx_set(ptr, usize, cnt->ctx);
|
||||
|
||||
cnt->epoch++;
|
||||
/*********/
|
||||
mb_write();
|
||||
/*********/
|
||||
cnt->cnts.curobjs++;
|
||||
cnt->cnts.curbytes += size;
|
||||
cnt->cnts.curbytes += usize;
|
||||
if (opt_prof_accum) {
|
||||
cnt->cnts.accumobjs++;
|
||||
cnt->cnts.accumbytes += size;
|
||||
cnt->cnts.accumbytes += usize;
|
||||
}
|
||||
/*********/
|
||||
mb_write();
|
||||
@@ -428,27 +491,28 @@ prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt)
|
||||
mb_write();
|
||||
/*********/
|
||||
} else
|
||||
prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U);
|
||||
prof_ctx_set(ptr, usize, (prof_ctx_t *)(uintptr_t)1U);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
|
||||
size_t old_size, prof_ctx_t *old_ctx)
|
||||
prof_realloc(const void *ptr, size_t usize, prof_thr_cnt_t *cnt,
|
||||
size_t old_usize, prof_ctx_t *old_ctx)
|
||||
{
|
||||
prof_thr_cnt_t *told_cnt;
|
||||
|
||||
cassert(config_prof);
|
||||
assert(ptr != NULL || (uintptr_t)cnt <= (uintptr_t)1U);
|
||||
|
||||
if (ptr != NULL) {
|
||||
assert(size == isalloc(ptr));
|
||||
assert(usize == isalloc(ptr, true));
|
||||
if (opt_lg_prof_sample != 0) {
|
||||
if (prof_sample_accum_update(size)) {
|
||||
if (prof_sample_accum_update(usize)) {
|
||||
/*
|
||||
* Don't sample. The size passed to
|
||||
* Don't sample. The usize passed to
|
||||
* PROF_ALLOC_PREP() was larger than what
|
||||
* actually got allocated, so a backtrace was
|
||||
* captured for this allocation, even though
|
||||
* its actual size was insufficient to cross
|
||||
* its actual usize was insufficient to cross
|
||||
* the sample threshold.
|
||||
*/
|
||||
cnt = (prof_thr_cnt_t *)(uintptr_t)1U;
|
||||
@@ -463,10 +527,10 @@ prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
|
||||
* It's too late to propagate OOM for this realloc(),
|
||||
* so operate directly on old_cnt->ctx->cnt_merged.
|
||||
*/
|
||||
malloc_mutex_lock(&old_ctx->lock);
|
||||
malloc_mutex_lock(old_ctx->lock);
|
||||
old_ctx->cnt_merged.curobjs--;
|
||||
old_ctx->cnt_merged.curbytes -= old_size;
|
||||
malloc_mutex_unlock(&old_ctx->lock);
|
||||
old_ctx->cnt_merged.curbytes -= old_usize;
|
||||
malloc_mutex_unlock(old_ctx->lock);
|
||||
told_cnt = (prof_thr_cnt_t *)(uintptr_t)1U;
|
||||
}
|
||||
} else
|
||||
@@ -475,23 +539,23 @@ prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
|
||||
if ((uintptr_t)told_cnt > (uintptr_t)1U)
|
||||
told_cnt->epoch++;
|
||||
if ((uintptr_t)cnt > (uintptr_t)1U) {
|
||||
prof_ctx_set(ptr, cnt->ctx);
|
||||
prof_ctx_set(ptr, usize, cnt->ctx);
|
||||
cnt->epoch++;
|
||||
} else
|
||||
prof_ctx_set(ptr, (prof_ctx_t *)(uintptr_t)1U);
|
||||
} else if (ptr != NULL)
|
||||
prof_ctx_set(ptr, usize, (prof_ctx_t *)(uintptr_t)1U);
|
||||
/*********/
|
||||
mb_write();
|
||||
/*********/
|
||||
if ((uintptr_t)told_cnt > (uintptr_t)1U) {
|
||||
told_cnt->cnts.curobjs--;
|
||||
told_cnt->cnts.curbytes -= old_size;
|
||||
told_cnt->cnts.curbytes -= old_usize;
|
||||
}
|
||||
if ((uintptr_t)cnt > (uintptr_t)1U) {
|
||||
cnt->cnts.curobjs++;
|
||||
cnt->cnts.curbytes += size;
|
||||
cnt->cnts.curbytes += usize;
|
||||
if (opt_prof_accum) {
|
||||
cnt->cnts.accumobjs++;
|
||||
cnt->cnts.accumbytes += size;
|
||||
cnt->cnts.accumbytes += usize;
|
||||
}
|
||||
}
|
||||
/*********/
|
||||
@@ -510,9 +574,12 @@ prof_free(const void *ptr, size_t size)
|
||||
{
|
||||
prof_ctx_t *ctx = prof_ctx_get(ptr);
|
||||
|
||||
cassert(config_prof);
|
||||
|
||||
if ((uintptr_t)ctx > (uintptr_t)1) {
|
||||
assert(size == isalloc(ptr));
|
||||
prof_thr_cnt_t *tcnt = prof_lookup(ctx->bt);
|
||||
prof_thr_cnt_t *tcnt;
|
||||
assert(size == isalloc(ptr, true));
|
||||
tcnt = prof_lookup(ctx->bt);
|
||||
|
||||
if (tcnt != NULL) {
|
||||
tcnt->epoch++;
|
||||
@@ -533,10 +600,10 @@ prof_free(const void *ptr, size_t size)
|
||||
* OOM during free() cannot be propagated, so operate
|
||||
* directly on cnt->ctx->cnt_merged.
|
||||
*/
|
||||
malloc_mutex_lock(&ctx->lock);
|
||||
malloc_mutex_lock(ctx->lock);
|
||||
ctx->cnt_merged.curobjs--;
|
||||
ctx->cnt_merged.curbytes -= size;
|
||||
malloc_mutex_unlock(&ctx->lock);
|
||||
malloc_mutex_unlock(ctx->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,4 +611,3 @@ prof_free(const void *ptr, size_t size)
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
#endif /* JEMALLOC_PROF */
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
for nm in `cat $1` ; do
|
||||
n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`
|
||||
echo "#define je_${n} JEMALLOC_N(${n})"
|
||||
done
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
for nm in `cat $1` ; do
|
||||
n=`echo ${nm} |tr ':' ' ' |awk '{print $1}'`
|
||||
echo "#undef je_${n}"
|
||||
done
|
||||
+18
-18
@@ -1,61 +1,61 @@
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define ql_head(a_type) \
|
||||
#define ql_head(a_type) \
|
||||
struct { \
|
||||
a_type *qlh_first; \
|
||||
}
|
||||
|
||||
#define ql_head_initializer(a_head) {NULL}
|
||||
#define ql_head_initializer(a_head) {NULL}
|
||||
|
||||
#define ql_elm(a_type) qr(a_type)
|
||||
#define ql_elm(a_type) qr(a_type)
|
||||
|
||||
/* List functions. */
|
||||
#define ql_new(a_head) do { \
|
||||
#define ql_new(a_head) do { \
|
||||
(a_head)->qlh_first = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field)
|
||||
#define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field)
|
||||
|
||||
#define ql_first(a_head) ((a_head)->qlh_first)
|
||||
#define ql_first(a_head) ((a_head)->qlh_first)
|
||||
|
||||
#define ql_last(a_head, a_field) \
|
||||
#define ql_last(a_head, a_field) \
|
||||
((ql_first(a_head) != NULL) \
|
||||
? qr_prev(ql_first(a_head), a_field) : NULL)
|
||||
|
||||
#define ql_next(a_head, a_elm, a_field) \
|
||||
#define ql_next(a_head, a_elm, a_field) \
|
||||
((ql_last(a_head, a_field) != (a_elm)) \
|
||||
? qr_next((a_elm), a_field) : NULL)
|
||||
|
||||
#define ql_prev(a_head, a_elm, a_field) \
|
||||
#define ql_prev(a_head, a_elm, a_field) \
|
||||
((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field) \
|
||||
: NULL)
|
||||
|
||||
#define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \
|
||||
#define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \
|
||||
qr_before_insert((a_qlelm), (a_elm), a_field); \
|
||||
if (ql_first(a_head) == (a_qlelm)) { \
|
||||
ql_first(a_head) = (a_elm); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ql_after_insert(a_qlelm, a_elm, a_field) \
|
||||
#define ql_after_insert(a_qlelm, a_elm, a_field) \
|
||||
qr_after_insert((a_qlelm), (a_elm), a_field)
|
||||
|
||||
#define ql_head_insert(a_head, a_elm, a_field) do { \
|
||||
#define ql_head_insert(a_head, a_elm, a_field) do { \
|
||||
if (ql_first(a_head) != NULL) { \
|
||||
qr_before_insert(ql_first(a_head), (a_elm), a_field); \
|
||||
} \
|
||||
ql_first(a_head) = (a_elm); \
|
||||
} while (0)
|
||||
|
||||
#define ql_tail_insert(a_head, a_elm, a_field) do { \
|
||||
#define ql_tail_insert(a_head, a_elm, a_field) do { \
|
||||
if (ql_first(a_head) != NULL) { \
|
||||
qr_before_insert(ql_first(a_head), (a_elm), a_field); \
|
||||
} \
|
||||
ql_first(a_head) = qr_next((a_elm), a_field); \
|
||||
} while (0)
|
||||
|
||||
#define ql_remove(a_head, a_elm, a_field) do { \
|
||||
#define ql_remove(a_head, a_elm, a_field) do { \
|
||||
if (ql_first(a_head) == (a_elm)) { \
|
||||
ql_first(a_head) = qr_next(ql_first(a_head), a_field); \
|
||||
} \
|
||||
@@ -66,18 +66,18 @@ struct { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ql_head_remove(a_head, a_type, a_field) do { \
|
||||
#define ql_head_remove(a_head, a_type, a_field) do { \
|
||||
a_type *t = ql_first(a_head); \
|
||||
ql_remove((a_head), t, a_field); \
|
||||
} while (0)
|
||||
|
||||
#define ql_tail_remove(a_head, a_type, a_field) do { \
|
||||
#define ql_tail_remove(a_head, a_type, a_field) do { \
|
||||
a_type *t = ql_last(a_head, a_field); \
|
||||
ql_remove((a_head), t, a_field); \
|
||||
} while (0)
|
||||
|
||||
#define ql_foreach(a_var, a_head, a_field) \
|
||||
#define ql_foreach(a_var, a_head, a_field) \
|
||||
qr_foreach((a_var), ql_first(a_head), a_field)
|
||||
|
||||
#define ql_reverse_foreach(a_var, a_head, a_field) \
|
||||
#define ql_reverse_foreach(a_var, a_head, a_field) \
|
||||
qr_reverse_foreach((a_var), ql_first(a_head), a_field)
|
||||
|
||||
+11
-11
@@ -1,28 +1,28 @@
|
||||
/* Ring definitions. */
|
||||
#define qr(a_type) \
|
||||
#define qr(a_type) \
|
||||
struct { \
|
||||
a_type *qre_next; \
|
||||
a_type *qre_prev; \
|
||||
}
|
||||
|
||||
/* Ring functions. */
|
||||
#define qr_new(a_qr, a_field) do { \
|
||||
#define qr_new(a_qr, a_field) do { \
|
||||
(a_qr)->a_field.qre_next = (a_qr); \
|
||||
(a_qr)->a_field.qre_prev = (a_qr); \
|
||||
} while (0)
|
||||
|
||||
#define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next)
|
||||
#define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next)
|
||||
|
||||
#define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev)
|
||||
#define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev)
|
||||
|
||||
#define qr_before_insert(a_qrelm, a_qr, a_field) do { \
|
||||
#define qr_before_insert(a_qrelm, a_qr, a_field) do { \
|
||||
(a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev; \
|
||||
(a_qr)->a_field.qre_next = (a_qrelm); \
|
||||
(a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr); \
|
||||
(a_qrelm)->a_field.qre_prev = (a_qr); \
|
||||
} while (0)
|
||||
|
||||
#define qr_after_insert(a_qrelm, a_qr, a_field) \
|
||||
#define qr_after_insert(a_qrelm, a_qr, a_field) \
|
||||
do \
|
||||
{ \
|
||||
(a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next; \
|
||||
@@ -31,7 +31,7 @@ struct { \
|
||||
(a_qrelm)->a_field.qre_next = (a_qr); \
|
||||
} while (0)
|
||||
|
||||
#define qr_meld(a_qr_a, a_qr_b, a_field) do { \
|
||||
#define qr_meld(a_qr_a, a_qr_b, a_field) do { \
|
||||
void *t; \
|
||||
(a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b); \
|
||||
(a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a); \
|
||||
@@ -42,10 +42,10 @@ struct { \
|
||||
|
||||
/* qr_meld() and qr_split() are functionally equivalent, so there's no need to
|
||||
* have two copies of the code. */
|
||||
#define qr_split(a_qr_a, a_qr_b, a_field) \
|
||||
#define qr_split(a_qr_a, a_qr_b, a_field) \
|
||||
qr_meld((a_qr_a), (a_qr_b), a_field)
|
||||
|
||||
#define qr_remove(a_qr, a_field) do { \
|
||||
#define qr_remove(a_qr, a_field) do { \
|
||||
(a_qr)->a_field.qre_prev->a_field.qre_next \
|
||||
= (a_qr)->a_field.qre_next; \
|
||||
(a_qr)->a_field.qre_next->a_field.qre_prev \
|
||||
@@ -54,13 +54,13 @@ struct { \
|
||||
(a_qr)->a_field.qre_prev = (a_qr); \
|
||||
} while (0)
|
||||
|
||||
#define qr_foreach(var, a_qr, a_field) \
|
||||
#define qr_foreach(var, a_qr, a_field) \
|
||||
for ((var) = (a_qr); \
|
||||
(var) != NULL; \
|
||||
(var) = (((var)->a_field.qre_next != (a_qr)) \
|
||||
? (var)->a_field.qre_next : NULL))
|
||||
|
||||
#define qr_reverse_foreach(var, a_qr, a_field) \
|
||||
#define qr_reverse_foreach(var, a_qr, a_field) \
|
||||
for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL; \
|
||||
(var) != NULL; \
|
||||
(var) = (((var) != (a_qr)) \
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
typedef struct quarantine_obj_s quarantine_obj_t;
|
||||
typedef struct quarantine_s quarantine_t;
|
||||
|
||||
/* Default per thread quarantine size if valgrind is enabled. */
|
||||
#define JEMALLOC_VALGRIND_QUARANTINE_DEFAULT (ZU(1) << 24)
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
struct quarantine_obj_s {
|
||||
void *ptr;
|
||||
size_t usize;
|
||||
};
|
||||
|
||||
struct quarantine_s {
|
||||
size_t curbytes;
|
||||
size_t curobjs;
|
||||
size_t first;
|
||||
#define LG_MAXOBJS_INIT 10
|
||||
size_t lg_maxobjs;
|
||||
quarantine_obj_t objs[1]; /* Dynamically sized ring buffer. */
|
||||
};
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
quarantine_t *quarantine_init(size_t lg_maxobjs);
|
||||
void quarantine(void *ptr);
|
||||
void quarantine_cleanup(void *arg);
|
||||
bool quarantine_boot(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
malloc_tsd_protos(JEMALLOC_ATTR(unused), quarantine, quarantine_t *)
|
||||
|
||||
void quarantine_alloc_hook(void);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_QUARANTINE_C_))
|
||||
malloc_tsd_externs(quarantine, quarantine_t *)
|
||||
malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, quarantine, quarantine_t *, NULL,
|
||||
quarantine_cleanup)
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE void
|
||||
quarantine_alloc_hook(void)
|
||||
{
|
||||
quarantine_t *quarantine;
|
||||
|
||||
assert(config_fill && opt_quarantine);
|
||||
|
||||
quarantine = *quarantine_tsd_get();
|
||||
if (quarantine == NULL)
|
||||
quarantine_init(LG_MAXOBJS_INIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
|
||||
+46
-50
@@ -22,10 +22,6 @@
|
||||
#ifndef RB_H_
|
||||
#define RB_H_
|
||||
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/lib/libc/stdlib/rb.h 204493 2010-02-28 22:57:13Z jasone $");
|
||||
#endif
|
||||
|
||||
#ifdef RB_COMPACT
|
||||
/* Node structure. */
|
||||
#define rb_node(a_type) \
|
||||
@@ -223,88 +219,88 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
|
||||
* The following API is generated:
|
||||
*
|
||||
* static void
|
||||
* ex_new(ex_t *extree);
|
||||
* ex_new(ex_t *tree);
|
||||
* Description: Initialize a red-black tree structure.
|
||||
* Args:
|
||||
* extree: Pointer to an uninitialized red-black tree object.
|
||||
* tree: Pointer to an uninitialized red-black tree object.
|
||||
*
|
||||
* static ex_node_t *
|
||||
* ex_first(ex_t *extree);
|
||||
* ex_first(ex_t *tree);
|
||||
* static ex_node_t *
|
||||
* ex_last(ex_t *extree);
|
||||
* Description: Get the first/last node in extree.
|
||||
* ex_last(ex_t *tree);
|
||||
* Description: Get the first/last node in tree.
|
||||
* Args:
|
||||
* extree: Pointer to an initialized red-black tree object.
|
||||
* Ret: First/last node in extree, or NULL if extree is empty.
|
||||
* tree: Pointer to an initialized red-black tree object.
|
||||
* Ret: First/last node in tree, or NULL if tree is empty.
|
||||
*
|
||||
* static ex_node_t *
|
||||
* ex_next(ex_t *extree, ex_node_t *node);
|
||||
* ex_next(ex_t *tree, ex_node_t *node);
|
||||
* static ex_node_t *
|
||||
* ex_prev(ex_t *extree, ex_node_t *node);
|
||||
* ex_prev(ex_t *tree, ex_node_t *node);
|
||||
* Description: Get node's successor/predecessor.
|
||||
* Args:
|
||||
* extree: Pointer to an initialized red-black tree object.
|
||||
* node : A node in extree.
|
||||
* Ret: node's successor/predecessor in extree, or NULL if node is
|
||||
* tree: Pointer to an initialized red-black tree object.
|
||||
* node: A node in tree.
|
||||
* Ret: node's successor/predecessor in tree, or NULL if node is
|
||||
* last/first.
|
||||
*
|
||||
* static ex_node_t *
|
||||
* ex_search(ex_t *extree, ex_node_t *key);
|
||||
* ex_search(ex_t *tree, ex_node_t *key);
|
||||
* Description: Search for node that matches key.
|
||||
* Args:
|
||||
* extree: Pointer to an initialized red-black tree object.
|
||||
* key : Search key.
|
||||
* Ret: Node in extree that matches key, or NULL if no match.
|
||||
* tree: Pointer to an initialized red-black tree object.
|
||||
* key : Search key.
|
||||
* Ret: Node in tree that matches key, or NULL if no match.
|
||||
*
|
||||
* static ex_node_t *
|
||||
* ex_nsearch(ex_t *extree, ex_node_t *key);
|
||||
* ex_nsearch(ex_t *tree, ex_node_t *key);
|
||||
* static ex_node_t *
|
||||
* ex_psearch(ex_t *extree, ex_node_t *key);
|
||||
* ex_psearch(ex_t *tree, ex_node_t *key);
|
||||
* Description: Search for node that matches key. If no match is found,
|
||||
* return what would be key's successor/predecessor, were
|
||||
* key in extree.
|
||||
* key in tree.
|
||||
* Args:
|
||||
* extree: Pointer to an initialized red-black tree object.
|
||||
* key : Search key.
|
||||
* Ret: Node in extree that matches key, or if no match, hypothetical
|
||||
* node's successor/predecessor (NULL if no successor/predecessor).
|
||||
* tree: Pointer to an initialized red-black tree object.
|
||||
* key : Search key.
|
||||
* Ret: Node in tree that matches key, or if no match, hypothetical node's
|
||||
* successor/predecessor (NULL if no successor/predecessor).
|
||||
*
|
||||
* static void
|
||||
* ex_insert(ex_t *extree, ex_node_t *node);
|
||||
* Description: Insert node into extree.
|
||||
* ex_insert(ex_t *tree, ex_node_t *node);
|
||||
* Description: Insert node into tree.
|
||||
* Args:
|
||||
* extree: Pointer to an initialized red-black tree object.
|
||||
* node : Node to be inserted into extree.
|
||||
* tree: Pointer to an initialized red-black tree object.
|
||||
* node: Node to be inserted into tree.
|
||||
*
|
||||
* static void
|
||||
* ex_remove(ex_t *extree, ex_node_t *node);
|
||||
* Description: Remove node from extree.
|
||||
* ex_remove(ex_t *tree, ex_node_t *node);
|
||||
* Description: Remove node from tree.
|
||||
* Args:
|
||||
* extree: Pointer to an initialized red-black tree object.
|
||||
* node : Node in extree to be removed.
|
||||
* tree: Pointer to an initialized red-black tree object.
|
||||
* node: Node in tree to be removed.
|
||||
*
|
||||
* static ex_node_t *
|
||||
* ex_iter(ex_t *extree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,
|
||||
* ex_iter(ex_t *tree, ex_node_t *start, ex_node_t *(*cb)(ex_t *,
|
||||
* ex_node_t *, void *), void *arg);
|
||||
* static ex_node_t *
|
||||
* ex_reverse_iter(ex_t *extree, ex_node_t *start, ex_node *(*cb)(ex_t *,
|
||||
* ex_reverse_iter(ex_t *tree, ex_node_t *start, ex_node *(*cb)(ex_t *,
|
||||
* ex_node_t *, void *), void *arg);
|
||||
* Description: Iterate forward/backward over extree, starting at node.
|
||||
* If extree is modified, iteration must be immediately
|
||||
* Description: Iterate forward/backward over tree, starting at node. If
|
||||
* tree is modified, iteration must be immediately
|
||||
* terminated by the callback function that causes the
|
||||
* modification.
|
||||
* Args:
|
||||
* extree: Pointer to an initialized red-black tree object.
|
||||
* start : Node at which to start iteration, or NULL to start at
|
||||
* first/last node.
|
||||
* cb : Callback function, which is called for each node during
|
||||
* iteration. Under normal circumstances the callback function
|
||||
* should return NULL, which causes iteration to continue. If a
|
||||
* callback function returns non-NULL, iteration is immediately
|
||||
* terminated and the non-NULL return value is returned by the
|
||||
* iterator. This is useful for re-starting iteration after
|
||||
* modifying extree.
|
||||
* arg : Opaque pointer passed to cb().
|
||||
* tree : Pointer to an initialized red-black tree object.
|
||||
* start: Node at which to start iteration, or NULL to start at
|
||||
* first/last node.
|
||||
* cb : Callback function, which is called for each node during
|
||||
* iteration. Under normal circumstances the callback function
|
||||
* should return NULL, which causes iteration to continue. If a
|
||||
* callback function returns non-NULL, iteration is immediately
|
||||
* terminated and the non-NULL return value is returned by the
|
||||
* iterator. This is useful for re-starting iteration after
|
||||
* modifying tree.
|
||||
* arg : Opaque pointer passed to cb().
|
||||
* Ret: NULL if iteration completed, or the non-NULL callback return value
|
||||
* that caused termination of the iteration.
|
||||
*/
|
||||
|
||||
+32
-21
@@ -14,17 +14,18 @@ typedef struct rtree_s rtree_t;
|
||||
* Size of each radix tree node (must be a power of 2). This impacts tree
|
||||
* depth.
|
||||
*/
|
||||
#if (LG_SIZEOF_PTR == 2)
|
||||
# define RTREE_NODESIZE (1U << 14)
|
||||
#else
|
||||
# define RTREE_NODESIZE CACHELINE
|
||||
#endif
|
||||
#define RTREE_NODESIZE (1U << 16)
|
||||
|
||||
typedef void *(rtree_alloc_t)(size_t);
|
||||
typedef void (rtree_dalloc_t)(void *);
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
struct rtree_s {
|
||||
rtree_alloc_t *alloc;
|
||||
rtree_dalloc_t *dalloc;
|
||||
malloc_mutex_t mutex;
|
||||
void **root;
|
||||
unsigned height;
|
||||
@@ -35,27 +36,31 @@ struct rtree_s {
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
rtree_t *rtree_new(unsigned bits);
|
||||
rtree_t *rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc);
|
||||
void rtree_delete(rtree_t *rtree);
|
||||
void rtree_prefork(rtree_t *rtree);
|
||||
void rtree_postfork_parent(rtree_t *rtree);
|
||||
void rtree_postfork_child(rtree_t *rtree);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
#ifndef JEMALLOC_DEBUG
|
||||
void *rtree_get_locked(rtree_t *rtree, uintptr_t key);
|
||||
#ifdef JEMALLOC_DEBUG
|
||||
uint8_t rtree_get_locked(rtree_t *rtree, uintptr_t key);
|
||||
#endif
|
||||
void *rtree_get(rtree_t *rtree, uintptr_t key);
|
||||
bool rtree_set(rtree_t *rtree, uintptr_t key, void *val);
|
||||
uint8_t rtree_get(rtree_t *rtree, uintptr_t key);
|
||||
bool rtree_set(rtree_t *rtree, uintptr_t key, uint8_t val);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_RTREE_C_))
|
||||
#define RTREE_GET_GENERATE(f) \
|
||||
/* The least significant bits of the key are ignored. */ \
|
||||
JEMALLOC_INLINE void * \
|
||||
JEMALLOC_INLINE uint8_t \
|
||||
f(rtree_t *rtree, uintptr_t key) \
|
||||
{ \
|
||||
void *ret; \
|
||||
uint8_t ret; \
|
||||
uintptr_t subkey; \
|
||||
unsigned i, lshift, height, bits; \
|
||||
void **node, **child; \
|
||||
@@ -65,12 +70,12 @@ f(rtree_t *rtree, uintptr_t key) \
|
||||
i < height - 1; \
|
||||
i++, lshift += bits, node = child) { \
|
||||
bits = rtree->level2bits[i]; \
|
||||
subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR + \
|
||||
subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR + \
|
||||
3)) - bits); \
|
||||
child = (void**)node[subkey]; \
|
||||
if (child == NULL) { \
|
||||
RTREE_UNLOCK(&rtree->mutex); \
|
||||
return (NULL); \
|
||||
return (0); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -81,7 +86,10 @@ f(rtree_t *rtree, uintptr_t key) \
|
||||
bits = rtree->level2bits[i]; \
|
||||
subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - \
|
||||
bits); \
|
||||
ret = node[subkey]; \
|
||||
{ \
|
||||
uint8_t *leaf = (uint8_t *)node; \
|
||||
ret = leaf[subkey]; \
|
||||
} \
|
||||
RTREE_UNLOCK(&rtree->mutex); \
|
||||
\
|
||||
RTREE_GET_VALIDATE \
|
||||
@@ -120,7 +128,7 @@ RTREE_GET_GENERATE(rtree_get)
|
||||
#undef RTREE_GET_VALIDATE
|
||||
|
||||
JEMALLOC_INLINE bool
|
||||
rtree_set(rtree_t *rtree, uintptr_t key, void *val)
|
||||
rtree_set(rtree_t *rtree, uintptr_t key, uint8_t val)
|
||||
{
|
||||
uintptr_t subkey;
|
||||
unsigned i, lshift, height, bits;
|
||||
@@ -135,14 +143,14 @@ rtree_set(rtree_t *rtree, uintptr_t key, void *val)
|
||||
bits);
|
||||
child = (void**)node[subkey];
|
||||
if (child == NULL) {
|
||||
child = (void**)base_alloc(sizeof(void *) <<
|
||||
rtree->level2bits[i+1]);
|
||||
size_t size = ((i + 1 < height - 1) ? sizeof(void *)
|
||||
: (sizeof(uint8_t))) << rtree->level2bits[i+1];
|
||||
child = (void**)rtree->alloc(size);
|
||||
if (child == NULL) {
|
||||
malloc_mutex_unlock(&rtree->mutex);
|
||||
return (true);
|
||||
}
|
||||
memset(child, 0, sizeof(void *) <<
|
||||
rtree->level2bits[i+1]);
|
||||
memset(child, 0, size);
|
||||
node[subkey] = child;
|
||||
}
|
||||
}
|
||||
@@ -150,7 +158,10 @@ rtree_set(rtree_t *rtree, uintptr_t key, void *val)
|
||||
/* node is a leaf, so it contains values rather than node pointers. */
|
||||
bits = rtree->level2bits[i];
|
||||
subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - bits);
|
||||
node[subkey] = val;
|
||||
{
|
||||
uint8_t *leaf = (uint8_t *)node;
|
||||
leaf[subkey] = val;
|
||||
}
|
||||
malloc_mutex_unlock(&rtree->mutex);
|
||||
|
||||
return (false);
|
||||
|
||||
-207
@@ -1,207 +0,0 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
#define UMAX2S_BUFSIZE 65
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
typedef struct tcache_bin_stats_s tcache_bin_stats_t;
|
||||
typedef struct malloc_bin_stats_s malloc_bin_stats_t;
|
||||
typedef struct malloc_large_stats_s malloc_large_stats_t;
|
||||
typedef struct arena_stats_s arena_stats_t;
|
||||
#endif
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
typedef struct chunk_stats_s chunk_stats_t;
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
|
||||
#ifdef JEMALLOC_TCACHE
|
||||
struct tcache_bin_stats_s {
|
||||
/*
|
||||
* Number of allocation requests that corresponded to the size of this
|
||||
* bin.
|
||||
*/
|
||||
uint64_t nrequests;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct malloc_bin_stats_s {
|
||||
/*
|
||||
* Current number of bytes allocated, including objects currently
|
||||
* cached by tcache.
|
||||
*/
|
||||
size_t allocated;
|
||||
|
||||
/*
|
||||
* Total number of allocation/deallocation requests served directly by
|
||||
* the bin. Note that tcache may allocate an object, then recycle it
|
||||
* many times, resulting many increments to nrequests, but only one
|
||||
* each to nmalloc and ndalloc.
|
||||
*/
|
||||
uint64_t nmalloc;
|
||||
uint64_t ndalloc;
|
||||
|
||||
/*
|
||||
* Number of allocation requests that correspond to the size of this
|
||||
* bin. This includes requests served by tcache, though tcache only
|
||||
* periodically merges into this counter.
|
||||
*/
|
||||
uint64_t nrequests;
|
||||
|
||||
#ifdef JEMALLOC_TCACHE
|
||||
/* Number of tcache fills from this bin. */
|
||||
uint64_t nfills;
|
||||
|
||||
/* Number of tcache flushes to this bin. */
|
||||
uint64_t nflushes;
|
||||
#endif
|
||||
|
||||
/* Total number of runs created for this bin's size class. */
|
||||
uint64_t nruns;
|
||||
|
||||
/*
|
||||
* Total number of runs reused by extracting them from the runs tree for
|
||||
* this bin's size class.
|
||||
*/
|
||||
uint64_t reruns;
|
||||
|
||||
/* High-water mark for this bin. */
|
||||
size_t highruns;
|
||||
|
||||
/* Current number of runs in this bin. */
|
||||
size_t curruns;
|
||||
};
|
||||
|
||||
struct malloc_large_stats_s {
|
||||
/*
|
||||
* Total number of allocation/deallocation requests served directly by
|
||||
* the arena. Note that tcache may allocate an object, then recycle it
|
||||
* many times, resulting many increments to nrequests, but only one
|
||||
* each to nmalloc and ndalloc.
|
||||
*/
|
||||
uint64_t nmalloc;
|
||||
uint64_t ndalloc;
|
||||
|
||||
/*
|
||||
* Number of allocation requests that correspond to this size class.
|
||||
* This includes requests served by tcache, though tcache only
|
||||
* periodically merges into this counter.
|
||||
*/
|
||||
uint64_t nrequests;
|
||||
|
||||
/* High-water mark for this size class. */
|
||||
size_t highruns;
|
||||
|
||||
/* Current number of runs of this size class. */
|
||||
size_t curruns;
|
||||
};
|
||||
|
||||
struct arena_stats_s {
|
||||
/* Number of bytes currently mapped. */
|
||||
size_t mapped;
|
||||
|
||||
/*
|
||||
* Total number of purge sweeps, total number of madvise calls made,
|
||||
* and total pages purged in order to keep dirty unused memory under
|
||||
* control.
|
||||
*/
|
||||
uint64_t npurge;
|
||||
uint64_t nmadvise;
|
||||
uint64_t purged;
|
||||
|
||||
/* Per-size-category statistics. */
|
||||
size_t allocated_large;
|
||||
uint64_t nmalloc_large;
|
||||
uint64_t ndalloc_large;
|
||||
uint64_t nrequests_large;
|
||||
|
||||
/*
|
||||
* One element for each possible size class, including sizes that
|
||||
* overlap with bin size classes. This is necessary because ipalloc()
|
||||
* sometimes has to use such large objects in order to assure proper
|
||||
* alignment.
|
||||
*/
|
||||
malloc_large_stats_t *lstats;
|
||||
};
|
||||
#endif /* JEMALLOC_STATS */
|
||||
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
struct chunk_stats_s {
|
||||
# ifdef JEMALLOC_STATS
|
||||
/* Number of chunks that were allocated. */
|
||||
uint64_t nchunks;
|
||||
# endif
|
||||
|
||||
/* High-water mark for number of chunks allocated. */
|
||||
size_t highchunks;
|
||||
|
||||
/*
|
||||
* Current number of chunks allocated. This value isn't maintained for
|
||||
* any other purpose, so keep track of it in order to be able to set
|
||||
* highchunks.
|
||||
*/
|
||||
size_t curchunks;
|
||||
};
|
||||
#endif /* JEMALLOC_STATS */
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
extern bool opt_stats_print;
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
extern size_t stats_cactive;
|
||||
#endif
|
||||
|
||||
char *u2s(uint64_t x, unsigned base, char *s);
|
||||
#ifdef JEMALLOC_STATS
|
||||
void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque,
|
||||
const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4));
|
||||
void malloc_printf(const char *format, ...)
|
||||
JEMALLOC_ATTR(format(printf, 1, 2));
|
||||
#endif
|
||||
void stats_print(void (*write)(void *, const char *), void *cbopaque,
|
||||
const char *opts);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
#ifdef JEMALLOC_STATS
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
size_t stats_cactive_get(void);
|
||||
void stats_cactive_add(size_t size);
|
||||
void stats_cactive_sub(size_t size);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_))
|
||||
JEMALLOC_INLINE size_t
|
||||
stats_cactive_get(void)
|
||||
{
|
||||
|
||||
return (atomic_read_z(&stats_cactive));
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
stats_cactive_add(size_t size)
|
||||
{
|
||||
|
||||
atomic_add_z(&stats_cactive, size);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
stats_cactive_sub(size_t size)
|
||||
{
|
||||
|
||||
atomic_sub_z(&stats_cactive, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_STATS */
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
+215
-203
@@ -1,4 +1,3 @@
|
||||
#ifdef JEMALLOC_TCACHE
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
@@ -6,6 +5,16 @@ typedef struct tcache_bin_info_s tcache_bin_info_t;
|
||||
typedef struct tcache_bin_s tcache_bin_t;
|
||||
typedef struct tcache_s tcache_t;
|
||||
|
||||
/*
|
||||
* tcache pointers close to NULL are used to encode state information that is
|
||||
* used for two purposes: preventing thread caching on a per thread basis and
|
||||
* cleaning up during thread shutdown.
|
||||
*/
|
||||
#define TCACHE_STATE_DISABLED ((tcache_t *)(uintptr_t)1)
|
||||
#define TCACHE_STATE_REINCARNATED ((tcache_t *)(uintptr_t)2)
|
||||
#define TCACHE_STATE_PURGATORY ((tcache_t *)(uintptr_t)3)
|
||||
#define TCACHE_STATE_MAX TCACHE_STATE_PURGATORY
|
||||
|
||||
/*
|
||||
* Absolute maximum number of cache slots for each small bin in the thread
|
||||
* cache. This is an additional constraint beyond that imposed as: twice the
|
||||
@@ -22,17 +31,26 @@ typedef struct tcache_s tcache_t;
|
||||
#define LG_TCACHE_MAXCLASS_DEFAULT 15
|
||||
|
||||
/*
|
||||
* (1U << opt_lg_tcache_gc_sweep) is the approximate number of allocation
|
||||
* events between full GC sweeps (-1: disabled). Integer rounding may cause
|
||||
* the actual number to be slightly higher, since GC is performed
|
||||
* incrementally.
|
||||
* TCACHE_GC_SWEEP is the approximate number of allocation events between
|
||||
* full GC sweeps. Integer rounding may cause the actual number to be
|
||||
* slightly higher, since GC is performed incrementally.
|
||||
*/
|
||||
#define LG_TCACHE_GC_SWEEP_DEFAULT 13
|
||||
#define TCACHE_GC_SWEEP 8192
|
||||
|
||||
/* Number of tcache allocation/deallocation events between incremental GCs. */
|
||||
#define TCACHE_GC_INCR \
|
||||
((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1))
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
typedef enum {
|
||||
tcache_enabled_false = 0, /* Enable cast to/from bool. */
|
||||
tcache_enabled_true = 1,
|
||||
tcache_enabled_default = 2
|
||||
} tcache_enabled_t;
|
||||
|
||||
/*
|
||||
* Read-only information associated with each element of tcache_t's tbins array
|
||||
* is stored separately, mainly to reduce memory usage.
|
||||
@@ -42,9 +60,7 @@ struct tcache_bin_info_s {
|
||||
};
|
||||
|
||||
struct tcache_bin_s {
|
||||
# ifdef JEMALLOC_STATS
|
||||
tcache_bin_stats_t tstats;
|
||||
# endif
|
||||
int low_water; /* Min # cached since last GC. */
|
||||
unsigned lg_fill_div; /* Fill (ncached_max >> lg_fill_div). */
|
||||
unsigned ncached; /* # of cached objects. */
|
||||
@@ -52,12 +68,8 @@ struct tcache_bin_s {
|
||||
};
|
||||
|
||||
struct tcache_s {
|
||||
# ifdef JEMALLOC_STATS
|
||||
ql_elm(tcache_t) link; /* Used for aggregating stats. */
|
||||
# endif
|
||||
# ifdef JEMALLOC_PROF
|
||||
uint64_t prof_accumbytes;/* Cleared after arena_prof_accum() */
|
||||
# endif
|
||||
arena_t *arena; /* This thread's arena. */
|
||||
unsigned ev_cnt; /* Event count since incremental GC. */
|
||||
unsigned next_gc_bin; /* Next bin to GC. */
|
||||
@@ -76,29 +88,11 @@ struct tcache_s {
|
||||
|
||||
extern bool opt_tcache;
|
||||
extern ssize_t opt_lg_tcache_max;
|
||||
extern ssize_t opt_lg_tcache_gc_sweep;
|
||||
|
||||
extern tcache_bin_info_t *tcache_bin_info;
|
||||
|
||||
/* Map of thread-specific caches. */
|
||||
#ifndef NO_TLS
|
||||
extern __thread tcache_t *tcache_tls
|
||||
JEMALLOC_ATTR(tls_model("initial-exec"));
|
||||
# define TCACHE_GET() tcache_tls
|
||||
# define TCACHE_SET(v) do { \
|
||||
tcache_tls = (tcache_t *)(v); \
|
||||
pthread_setspecific(tcache_tsd, (void *)(v)); \
|
||||
} while (0)
|
||||
#else
|
||||
# define TCACHE_GET() ((tcache_t *)pthread_getspecific(tcache_tsd))
|
||||
# define TCACHE_SET(v) do { \
|
||||
pthread_setspecific(tcache_tsd, (void *)(v)); \
|
||||
} while (0)
|
||||
#endif
|
||||
extern pthread_key_t tcache_tsd;
|
||||
|
||||
/*
|
||||
* Number of tcache bins. There are nbins small-object bins, plus 0 or more
|
||||
* Number of tcache bins. There are NBINS small-object bins, plus 0 or more
|
||||
* large-object bins.
|
||||
*/
|
||||
extern size_t nhbins;
|
||||
@@ -106,134 +100,178 @@ extern size_t nhbins;
|
||||
/* Maximum cached size class. */
|
||||
extern size_t tcache_maxclass;
|
||||
|
||||
/* Number of tcache allocation/deallocation events between incremental GCs. */
|
||||
extern unsigned tcache_gc_incr;
|
||||
|
||||
void tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
, tcache_t *tcache
|
||||
#endif
|
||||
);
|
||||
void tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
, tcache_t *tcache
|
||||
#endif
|
||||
);
|
||||
tcache_t *tcache_create(arena_t *arena);
|
||||
size_t tcache_salloc(const void *ptr);
|
||||
void tcache_event_hard(tcache_t *tcache);
|
||||
void *tcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin,
|
||||
size_t binind);
|
||||
void tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem,
|
||||
tcache_t *tcache);
|
||||
void tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem,
|
||||
tcache_t *tcache);
|
||||
void tcache_arena_associate(tcache_t *tcache, arena_t *arena);
|
||||
void tcache_arena_dissociate(tcache_t *tcache);
|
||||
tcache_t *tcache_create(arena_t *arena);
|
||||
void tcache_destroy(tcache_t *tcache);
|
||||
#ifdef JEMALLOC_STATS
|
||||
void tcache_thread_cleanup(void *arg);
|
||||
void tcache_stats_merge(tcache_t *tcache, arena_t *arena);
|
||||
#endif
|
||||
bool tcache_boot(void);
|
||||
bool tcache_boot0(void);
|
||||
bool tcache_boot1(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache, tcache_t *)
|
||||
malloc_tsd_protos(JEMALLOC_ATTR(unused), tcache_enabled, tcache_enabled_t)
|
||||
|
||||
void tcache_event(tcache_t *tcache);
|
||||
tcache_t *tcache_get(void);
|
||||
void tcache_flush(void);
|
||||
bool tcache_enabled_get(void);
|
||||
tcache_t *tcache_get(bool create);
|
||||
void tcache_enabled_set(bool enabled);
|
||||
void *tcache_alloc_easy(tcache_bin_t *tbin);
|
||||
void *tcache_alloc_small(tcache_t *tcache, size_t size, bool zero);
|
||||
void *tcache_alloc_large(tcache_t *tcache, size_t size, bool zero);
|
||||
void tcache_dalloc_small(tcache_t *tcache, void *ptr);
|
||||
void tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind);
|
||||
void tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TCACHE_C_))
|
||||
JEMALLOC_INLINE tcache_t *
|
||||
tcache_get(void)
|
||||
/* Map of thread-specific caches. */
|
||||
malloc_tsd_externs(tcache, tcache_t *)
|
||||
malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache, tcache_t *, NULL,
|
||||
tcache_thread_cleanup)
|
||||
/* Per thread flag that allows thread caches to be disabled. */
|
||||
malloc_tsd_externs(tcache_enabled, tcache_enabled_t)
|
||||
malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, tcache_enabled, tcache_enabled_t,
|
||||
tcache_enabled_default, malloc_tsd_no_cleanup)
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
tcache_flush(void)
|
||||
{
|
||||
tcache_t *tcache;
|
||||
|
||||
if ((isthreaded & opt_tcache) == false)
|
||||
cassert(config_tcache);
|
||||
|
||||
tcache = *tcache_tsd_get();
|
||||
if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX)
|
||||
return;
|
||||
tcache_destroy(tcache);
|
||||
tcache = NULL;
|
||||
tcache_tsd_set(&tcache);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE bool
|
||||
tcache_enabled_get(void)
|
||||
{
|
||||
tcache_enabled_t tcache_enabled;
|
||||
|
||||
cassert(config_tcache);
|
||||
|
||||
tcache_enabled = *tcache_enabled_tsd_get();
|
||||
if (tcache_enabled == tcache_enabled_default) {
|
||||
tcache_enabled = (tcache_enabled_t)opt_tcache;
|
||||
tcache_enabled_tsd_set(&tcache_enabled);
|
||||
}
|
||||
|
||||
return ((bool)tcache_enabled);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
tcache_enabled_set(bool enabled)
|
||||
{
|
||||
tcache_enabled_t tcache_enabled;
|
||||
tcache_t *tcache;
|
||||
|
||||
cassert(config_tcache);
|
||||
|
||||
tcache_enabled = (tcache_enabled_t)enabled;
|
||||
tcache_enabled_tsd_set(&tcache_enabled);
|
||||
tcache = *tcache_tsd_get();
|
||||
if (enabled) {
|
||||
if (tcache == TCACHE_STATE_DISABLED) {
|
||||
tcache = NULL;
|
||||
tcache_tsd_set(&tcache);
|
||||
}
|
||||
} else /* disabled */ {
|
||||
if (tcache > TCACHE_STATE_MAX) {
|
||||
tcache_destroy(tcache);
|
||||
tcache = NULL;
|
||||
}
|
||||
if (tcache == NULL) {
|
||||
tcache = TCACHE_STATE_DISABLED;
|
||||
tcache_tsd_set(&tcache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE tcache_t *
|
||||
tcache_get(bool create)
|
||||
{
|
||||
tcache_t *tcache;
|
||||
|
||||
if (config_tcache == false)
|
||||
return (NULL);
|
||||
if (config_lazy_lock && isthreaded == false)
|
||||
return (NULL);
|
||||
|
||||
tcache = TCACHE_GET();
|
||||
if ((uintptr_t)tcache <= (uintptr_t)2) {
|
||||
tcache = *tcache_tsd_get();
|
||||
if ((uintptr_t)tcache <= (uintptr_t)TCACHE_STATE_MAX) {
|
||||
if (tcache == TCACHE_STATE_DISABLED)
|
||||
return (NULL);
|
||||
if (tcache == NULL) {
|
||||
tcache = tcache_create(choose_arena());
|
||||
if (tcache == NULL)
|
||||
return (NULL);
|
||||
} else {
|
||||
if (tcache == (void *)(uintptr_t)1) {
|
||||
if (create == false) {
|
||||
/*
|
||||
* Make a note that an allocator function was
|
||||
* called after the tcache_thread_cleanup() was
|
||||
* called.
|
||||
* Creating a tcache here would cause
|
||||
* allocation as a side effect of free().
|
||||
* Ordinarily that would be okay since
|
||||
* tcache_create() failure is a soft failure
|
||||
* that doesn't propagate. However, if TLS
|
||||
* data are freed via free() as in glibc,
|
||||
* subtle corruption could result from setting
|
||||
* a TLS variable after its backing memory is
|
||||
* freed.
|
||||
*/
|
||||
TCACHE_SET((uintptr_t)2);
|
||||
return (NULL);
|
||||
}
|
||||
if (tcache_enabled_get() == false) {
|
||||
tcache_enabled_set(false); /* Memoize. */
|
||||
return (NULL);
|
||||
}
|
||||
return (tcache_create(choose_arena(NULL)));
|
||||
}
|
||||
if (tcache == TCACHE_STATE_PURGATORY) {
|
||||
/*
|
||||
* Make a note that an allocator function was called
|
||||
* after tcache_thread_cleanup() was called.
|
||||
*/
|
||||
tcache = TCACHE_STATE_REINCARNATED;
|
||||
tcache_tsd_set(&tcache);
|
||||
return (NULL);
|
||||
}
|
||||
if (tcache == TCACHE_STATE_REINCARNATED)
|
||||
return (NULL);
|
||||
not_reached();
|
||||
}
|
||||
|
||||
return (tcache);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
JEMALLOC_ALWAYS_INLINE void
|
||||
tcache_event(tcache_t *tcache)
|
||||
{
|
||||
|
||||
if (tcache_gc_incr == 0)
|
||||
if (TCACHE_GC_INCR == 0)
|
||||
return;
|
||||
|
||||
tcache->ev_cnt++;
|
||||
assert(tcache->ev_cnt <= tcache_gc_incr);
|
||||
if (tcache->ev_cnt == tcache_gc_incr) {
|
||||
size_t binind = tcache->next_gc_bin;
|
||||
tcache_bin_t *tbin = &tcache->tbins[binind];
|
||||
tcache_bin_info_t *tbin_info = &tcache_bin_info[binind];
|
||||
|
||||
if (tbin->low_water > 0) {
|
||||
/*
|
||||
* Flush (ceiling) 3/4 of the objects below the low
|
||||
* water mark.
|
||||
*/
|
||||
if (binind < nbins) {
|
||||
tcache_bin_flush_small(tbin, binind,
|
||||
tbin->ncached - tbin->low_water +
|
||||
(tbin->low_water >> 2)
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
, tcache
|
||||
#endif
|
||||
);
|
||||
} else {
|
||||
tcache_bin_flush_large(tbin, binind,
|
||||
tbin->ncached - tbin->low_water +
|
||||
(tbin->low_water >> 2)
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
, tcache
|
||||
#endif
|
||||
);
|
||||
}
|
||||
/*
|
||||
* Reduce fill count by 2X. Limit lg_fill_div such that
|
||||
* the fill count is always at least 1.
|
||||
*/
|
||||
if ((tbin_info->ncached_max >> (tbin->lg_fill_div+1))
|
||||
>= 1)
|
||||
tbin->lg_fill_div++;
|
||||
} else if (tbin->low_water < 0) {
|
||||
/*
|
||||
* Increase fill count by 2X. Make sure lg_fill_div
|
||||
* stays greater than 0.
|
||||
*/
|
||||
if (tbin->lg_fill_div > 1)
|
||||
tbin->lg_fill_div--;
|
||||
}
|
||||
tbin->low_water = tbin->ncached;
|
||||
|
||||
tcache->next_gc_bin++;
|
||||
if (tcache->next_gc_bin == nhbins)
|
||||
tcache->next_gc_bin = 0;
|
||||
tcache->ev_cnt = 0;
|
||||
}
|
||||
assert(tcache->ev_cnt <= TCACHE_GC_INCR);
|
||||
if (tcache->ev_cnt == TCACHE_GC_INCR)
|
||||
tcache_event_hard(tcache);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void *
|
||||
JEMALLOC_ALWAYS_INLINE void *
|
||||
tcache_alloc_easy(tcache_bin_t *tbin)
|
||||
{
|
||||
void *ret;
|
||||
@@ -249,7 +287,7 @@ tcache_alloc_easy(tcache_bin_t *tbin)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void *
|
||||
JEMALLOC_ALWAYS_INLINE void *
|
||||
tcache_alloc_small(tcache_t *tcache, size_t size, bool zero)
|
||||
{
|
||||
void *ret;
|
||||
@@ -257,37 +295,44 @@ tcache_alloc_small(tcache_t *tcache, size_t size, bool zero)
|
||||
tcache_bin_t *tbin;
|
||||
|
||||
binind = SMALL_SIZE2BIN(size);
|
||||
assert(binind < nbins);
|
||||
assert(binind < NBINS);
|
||||
tbin = &tcache->tbins[binind];
|
||||
size = arena_bin_info[binind].reg_size;
|
||||
ret = tcache_alloc_easy(tbin);
|
||||
if (ret == NULL) {
|
||||
ret = tcache_alloc_small_hard(tcache, tbin, binind);
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
assert(arena_salloc(ret) == arena_bin_info[binind].reg_size);
|
||||
assert(tcache_salloc(ret) == arena_bin_info[binind].reg_size);
|
||||
|
||||
if (zero == false) {
|
||||
#ifdef JEMALLOC_FILL
|
||||
if (opt_junk)
|
||||
memset(ret, 0xa5, size);
|
||||
else if (opt_zero)
|
||||
memset(ret, 0, size);
|
||||
#endif
|
||||
} else
|
||||
if (config_fill) {
|
||||
if (opt_junk) {
|
||||
arena_alloc_junk_small(ret,
|
||||
&arena_bin_info[binind], false);
|
||||
} else if (opt_zero)
|
||||
memset(ret, 0, size);
|
||||
}
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
|
||||
} else {
|
||||
if (config_fill && opt_junk) {
|
||||
arena_alloc_junk_small(ret, &arena_bin_info[binind],
|
||||
true);
|
||||
}
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
|
||||
memset(ret, 0, size);
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
tbin->tstats.nrequests++;
|
||||
#endif
|
||||
#ifdef JEMALLOC_PROF
|
||||
tcache->prof_accumbytes += arena_bin_info[binind].reg_size;
|
||||
#endif
|
||||
if (config_stats)
|
||||
tbin->tstats.nrequests++;
|
||||
if (config_prof)
|
||||
tcache->prof_accumbytes += arena_bin_info[binind].reg_size;
|
||||
tcache_event(tcache);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void *
|
||||
JEMALLOC_ALWAYS_INLINE void *
|
||||
tcache_alloc_large(tcache_t *tcache, size_t size, bool zero)
|
||||
{
|
||||
void *ret;
|
||||
@@ -296,7 +341,7 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero)
|
||||
|
||||
size = PAGE_CEILING(size);
|
||||
assert(size <= tcache_maxclass);
|
||||
binind = nbins + (size >> PAGE_SHIFT) - 1;
|
||||
binind = NBINS + (size >> LG_PAGE) - 1;
|
||||
assert(binind < nhbins);
|
||||
tbin = &tcache->tbins[binind];
|
||||
ret = tcache_alloc_easy(tbin);
|
||||
@@ -309,74 +354,53 @@ tcache_alloc_large(tcache_t *tcache, size_t size, bool zero)
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
} else {
|
||||
#ifdef JEMALLOC_PROF
|
||||
arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
|
||||
size_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >>
|
||||
PAGE_SHIFT);
|
||||
chunk->map[pageind-map_bias].bits &= ~CHUNK_MAP_CLASS_MASK;
|
||||
#endif
|
||||
if (config_prof && prof_promote && size == PAGE) {
|
||||
arena_chunk_t *chunk =
|
||||
(arena_chunk_t *)CHUNK_ADDR2BASE(ret);
|
||||
size_t pageind = (((uintptr_t)ret - (uintptr_t)chunk) >>
|
||||
LG_PAGE);
|
||||
arena_mapbits_large_binind_set(chunk, pageind,
|
||||
BININD_INVALID);
|
||||
}
|
||||
if (zero == false) {
|
||||
#ifdef JEMALLOC_FILL
|
||||
if (opt_junk)
|
||||
memset(ret, 0xa5, size);
|
||||
else if (opt_zero)
|
||||
memset(ret, 0, size);
|
||||
#endif
|
||||
} else
|
||||
if (config_fill) {
|
||||
if (opt_junk)
|
||||
memset(ret, 0xa5, size);
|
||||
else if (opt_zero)
|
||||
memset(ret, 0, size);
|
||||
}
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
|
||||
} else {
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
|
||||
memset(ret, 0, size);
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
tbin->tstats.nrequests++;
|
||||
#endif
|
||||
#ifdef JEMALLOC_PROF
|
||||
tcache->prof_accumbytes += size;
|
||||
#endif
|
||||
if (config_stats)
|
||||
tbin->tstats.nrequests++;
|
||||
if (config_prof)
|
||||
tcache->prof_accumbytes += size;
|
||||
}
|
||||
|
||||
tcache_event(tcache);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
tcache_dalloc_small(tcache_t *tcache, void *ptr)
|
||||
JEMALLOC_ALWAYS_INLINE void
|
||||
tcache_dalloc_small(tcache_t *tcache, void *ptr, size_t binind)
|
||||
{
|
||||
arena_t *arena;
|
||||
arena_chunk_t *chunk;
|
||||
arena_run_t *run;
|
||||
arena_bin_t *bin;
|
||||
tcache_bin_t *tbin;
|
||||
tcache_bin_info_t *tbin_info;
|
||||
size_t pageind, binind;
|
||||
arena_chunk_map_t *mapelm;
|
||||
|
||||
assert(arena_salloc(ptr) <= small_maxclass);
|
||||
assert(tcache_salloc(ptr) <= SMALL_MAXCLASS);
|
||||
|
||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||
arena = chunk->arena;
|
||||
pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
|
||||
mapelm = &chunk->map[pageind-map_bias];
|
||||
run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
|
||||
(mapelm->bits >> PAGE_SHIFT)) << PAGE_SHIFT));
|
||||
dassert(run->magic == ARENA_RUN_MAGIC);
|
||||
bin = run->bin;
|
||||
binind = ((uintptr_t)bin - (uintptr_t)&arena->bins) /
|
||||
sizeof(arena_bin_t);
|
||||
assert(binind < nbins);
|
||||
|
||||
#ifdef JEMALLOC_FILL
|
||||
if (opt_junk)
|
||||
memset(ptr, 0x5a, arena_bin_info[binind].reg_size);
|
||||
#endif
|
||||
if (config_fill && opt_junk)
|
||||
arena_dalloc_junk_small(ptr, &arena_bin_info[binind]);
|
||||
|
||||
tbin = &tcache->tbins[binind];
|
||||
tbin_info = &tcache_bin_info[binind];
|
||||
if (tbin->ncached == tbin_info->ncached_max) {
|
||||
tcache_bin_flush_small(tbin, binind, (tbin_info->ncached_max >>
|
||||
1)
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
, tcache
|
||||
#endif
|
||||
);
|
||||
1), tcache);
|
||||
}
|
||||
assert(tbin->ncached < tbin_info->ncached_max);
|
||||
tbin->avail[tbin->ncached] = ptr;
|
||||
@@ -385,38 +409,27 @@ tcache_dalloc_small(tcache_t *tcache, void *ptr)
|
||||
tcache_event(tcache);
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE void
|
||||
JEMALLOC_ALWAYS_INLINE void
|
||||
tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size)
|
||||
{
|
||||
arena_t *arena;
|
||||
arena_chunk_t *chunk;
|
||||
size_t pageind, binind;
|
||||
size_t binind;
|
||||
tcache_bin_t *tbin;
|
||||
tcache_bin_info_t *tbin_info;
|
||||
|
||||
assert((size & PAGE_MASK) == 0);
|
||||
assert(arena_salloc(ptr) > small_maxclass);
|
||||
assert(arena_salloc(ptr) <= tcache_maxclass);
|
||||
assert(tcache_salloc(ptr) > SMALL_MAXCLASS);
|
||||
assert(tcache_salloc(ptr) <= tcache_maxclass);
|
||||
|
||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||
arena = chunk->arena;
|
||||
pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
|
||||
binind = nbins + (size >> PAGE_SHIFT) - 1;
|
||||
binind = NBINS + (size >> LG_PAGE) - 1;
|
||||
|
||||
#ifdef JEMALLOC_FILL
|
||||
if (opt_junk)
|
||||
if (config_fill && opt_junk)
|
||||
memset(ptr, 0x5a, size);
|
||||
#endif
|
||||
|
||||
tbin = &tcache->tbins[binind];
|
||||
tbin_info = &tcache_bin_info[binind];
|
||||
if (tbin->ncached == tbin_info->ncached_max) {
|
||||
tcache_bin_flush_large(tbin, binind, (tbin_info->ncached_max >>
|
||||
1)
|
||||
#if (defined(JEMALLOC_STATS) || defined(JEMALLOC_PROF))
|
||||
, tcache
|
||||
#endif
|
||||
);
|
||||
1), tcache);
|
||||
}
|
||||
assert(tbin->ncached < tbin_info->ncached_max);
|
||||
tbin->avail[tbin->ncached] = ptr;
|
||||
@@ -428,4 +441,3 @@ tcache_dalloc_large(tcache_t *tcache, void *ptr, size_t size)
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
#endif /* JEMALLOC_TCACHE */
|
||||
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
/* Maximum number of malloc_tsd users with cleanup functions. */
|
||||
#define MALLOC_TSD_CLEANUPS_MAX 8
|
||||
|
||||
typedef bool (*malloc_tsd_cleanup_t)(void);
|
||||
|
||||
#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \
|
||||
!defined(_WIN32))
|
||||
typedef struct tsd_init_block_s tsd_init_block_t;
|
||||
typedef struct tsd_init_head_s tsd_init_head_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TLS/TSD-agnostic macro-based implementation of thread-specific data. There
|
||||
* are four macros that support (at least) three use cases: file-private,
|
||||
* library-private, and library-private inlined. Following is an example
|
||||
* library-private tsd variable:
|
||||
*
|
||||
* In example.h:
|
||||
* typedef struct {
|
||||
* int x;
|
||||
* int y;
|
||||
* } example_t;
|
||||
* #define EX_INITIALIZER JEMALLOC_CONCAT({0, 0})
|
||||
* malloc_tsd_protos(, example, example_t *)
|
||||
* malloc_tsd_externs(example, example_t *)
|
||||
* In example.c:
|
||||
* malloc_tsd_data(, example, example_t *, EX_INITIALIZER)
|
||||
* malloc_tsd_funcs(, example, example_t *, EX_INITIALIZER,
|
||||
* example_tsd_cleanup)
|
||||
*
|
||||
* The result is a set of generated functions, e.g.:
|
||||
*
|
||||
* bool example_tsd_boot(void) {...}
|
||||
* example_t **example_tsd_get() {...}
|
||||
* void example_tsd_set(example_t **val) {...}
|
||||
*
|
||||
* Note that all of the functions deal in terms of (a_type *) rather than
|
||||
* (a_type) so that it is possible to support non-pointer types (unlike
|
||||
* pthreads TSD). example_tsd_cleanup() is passed an (a_type *) pointer that is
|
||||
* cast to (void *). This means that the cleanup function needs to cast *and*
|
||||
* dereference the function argument, e.g.:
|
||||
*
|
||||
* void
|
||||
* example_tsd_cleanup(void *arg)
|
||||
* {
|
||||
* example_t *example = *(example_t **)arg;
|
||||
*
|
||||
* [...]
|
||||
* if ([want the cleanup function to be called again]) {
|
||||
* example_tsd_set(&example);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* If example_tsd_set() is called within example_tsd_cleanup(), it will be
|
||||
* called again. This is similar to how pthreads TSD destruction works, except
|
||||
* that pthreads only calls the cleanup function again if the value was set to
|
||||
* non-NULL.
|
||||
*/
|
||||
|
||||
/* malloc_tsd_protos(). */
|
||||
#define malloc_tsd_protos(a_attr, a_name, a_type) \
|
||||
a_attr bool \
|
||||
a_name##_tsd_boot(void); \
|
||||
a_attr a_type * \
|
||||
a_name##_tsd_get(void); \
|
||||
a_attr void \
|
||||
a_name##_tsd_set(a_type *val);
|
||||
|
||||
/* malloc_tsd_externs(). */
|
||||
#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
|
||||
#define malloc_tsd_externs(a_name, a_type) \
|
||||
extern __thread a_type a_name##_tls; \
|
||||
extern __thread bool a_name##_initialized; \
|
||||
extern bool a_name##_booted;
|
||||
#elif (defined(JEMALLOC_TLS))
|
||||
#define malloc_tsd_externs(a_name, a_type) \
|
||||
extern __thread a_type a_name##_tls; \
|
||||
extern pthread_key_t a_name##_tsd; \
|
||||
extern bool a_name##_booted;
|
||||
#elif (defined(_WIN32))
|
||||
#define malloc_tsd_externs(a_name, a_type) \
|
||||
extern DWORD a_name##_tsd; \
|
||||
extern bool a_name##_booted;
|
||||
#else
|
||||
#define malloc_tsd_externs(a_name, a_type) \
|
||||
extern pthread_key_t a_name##_tsd; \
|
||||
extern tsd_init_head_t a_name##_tsd_init_head; \
|
||||
extern bool a_name##_booted;
|
||||
#endif
|
||||
|
||||
/* malloc_tsd_data(). */
|
||||
#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
|
||||
#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
|
||||
a_attr __thread a_type JEMALLOC_TLS_MODEL \
|
||||
a_name##_tls = a_initializer; \
|
||||
a_attr __thread bool JEMALLOC_TLS_MODEL \
|
||||
a_name##_initialized = false; \
|
||||
a_attr bool a_name##_booted = false;
|
||||
#elif (defined(JEMALLOC_TLS))
|
||||
#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
|
||||
a_attr __thread a_type JEMALLOC_TLS_MODEL \
|
||||
a_name##_tls = a_initializer; \
|
||||
a_attr pthread_key_t a_name##_tsd; \
|
||||
a_attr bool a_name##_booted = false;
|
||||
#elif (defined(_WIN32))
|
||||
#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
|
||||
a_attr DWORD a_name##_tsd; \
|
||||
a_attr bool a_name##_booted = false;
|
||||
#else
|
||||
#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \
|
||||
a_attr pthread_key_t a_name##_tsd; \
|
||||
a_attr tsd_init_head_t a_name##_tsd_init_head = { \
|
||||
ql_head_initializer(blocks), \
|
||||
MALLOC_MUTEX_INITIALIZER \
|
||||
}; \
|
||||
a_attr bool a_name##_booted = false;
|
||||
#endif
|
||||
|
||||
/* malloc_tsd_funcs(). */
|
||||
#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
|
||||
#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
|
||||
a_cleanup) \
|
||||
/* Initialization/cleanup. */ \
|
||||
a_attr bool \
|
||||
a_name##_tsd_cleanup_wrapper(void) \
|
||||
{ \
|
||||
\
|
||||
if (a_name##_initialized) { \
|
||||
a_name##_initialized = false; \
|
||||
a_cleanup(&a_name##_tls); \
|
||||
} \
|
||||
return (a_name##_initialized); \
|
||||
} \
|
||||
a_attr bool \
|
||||
a_name##_tsd_boot(void) \
|
||||
{ \
|
||||
\
|
||||
if (a_cleanup != malloc_tsd_no_cleanup) { \
|
||||
malloc_tsd_cleanup_register( \
|
||||
&a_name##_tsd_cleanup_wrapper); \
|
||||
} \
|
||||
a_name##_booted = true; \
|
||||
return (false); \
|
||||
} \
|
||||
/* Get/set. */ \
|
||||
a_attr a_type * \
|
||||
a_name##_tsd_get(void) \
|
||||
{ \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
return (&a_name##_tls); \
|
||||
} \
|
||||
a_attr void \
|
||||
a_name##_tsd_set(a_type *val) \
|
||||
{ \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
a_name##_tls = (*val); \
|
||||
if (a_cleanup != malloc_tsd_no_cleanup) \
|
||||
a_name##_initialized = true; \
|
||||
}
|
||||
#elif (defined(JEMALLOC_TLS))
|
||||
#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
|
||||
a_cleanup) \
|
||||
/* Initialization/cleanup. */ \
|
||||
a_attr bool \
|
||||
a_name##_tsd_boot(void) \
|
||||
{ \
|
||||
\
|
||||
if (a_cleanup != malloc_tsd_no_cleanup) { \
|
||||
if (pthread_key_create(&a_name##_tsd, a_cleanup) != 0) \
|
||||
return (true); \
|
||||
} \
|
||||
a_name##_booted = true; \
|
||||
return (false); \
|
||||
} \
|
||||
/* Get/set. */ \
|
||||
a_attr a_type * \
|
||||
a_name##_tsd_get(void) \
|
||||
{ \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
return (&a_name##_tls); \
|
||||
} \
|
||||
a_attr void \
|
||||
a_name##_tsd_set(a_type *val) \
|
||||
{ \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
a_name##_tls = (*val); \
|
||||
if (a_cleanup != malloc_tsd_no_cleanup) { \
|
||||
if (pthread_setspecific(a_name##_tsd, \
|
||||
(void *)(&a_name##_tls))) { \
|
||||
malloc_write("<jemalloc>: Error" \
|
||||
" setting TSD for "#a_name"\n"); \
|
||||
if (opt_abort) \
|
||||
abort(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#elif (defined(_WIN32))
|
||||
#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
|
||||
a_cleanup) \
|
||||
/* Data structure. */ \
|
||||
typedef struct { \
|
||||
bool initialized; \
|
||||
a_type val; \
|
||||
} a_name##_tsd_wrapper_t; \
|
||||
/* Initialization/cleanup. */ \
|
||||
a_attr bool \
|
||||
a_name##_tsd_cleanup_wrapper(void) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper; \
|
||||
\
|
||||
wrapper = (a_name##_tsd_wrapper_t *) TlsGetValue(a_name##_tsd); \
|
||||
if (wrapper == NULL) \
|
||||
return (false); \
|
||||
if (a_cleanup != malloc_tsd_no_cleanup && \
|
||||
wrapper->initialized) { \
|
||||
a_type val = wrapper->val; \
|
||||
a_type tsd_static_data = a_initializer; \
|
||||
wrapper->initialized = false; \
|
||||
wrapper->val = tsd_static_data; \
|
||||
a_cleanup(&val); \
|
||||
if (wrapper->initialized) { \
|
||||
/* Trigger another cleanup round. */ \
|
||||
return (true); \
|
||||
} \
|
||||
} \
|
||||
malloc_tsd_dalloc(wrapper); \
|
||||
return (false); \
|
||||
} \
|
||||
a_attr bool \
|
||||
a_name##_tsd_boot(void) \
|
||||
{ \
|
||||
\
|
||||
a_name##_tsd = TlsAlloc(); \
|
||||
if (a_name##_tsd == TLS_OUT_OF_INDEXES) \
|
||||
return (true); \
|
||||
if (a_cleanup != malloc_tsd_no_cleanup) { \
|
||||
malloc_tsd_cleanup_register( \
|
||||
&a_name##_tsd_cleanup_wrapper); \
|
||||
} \
|
||||
a_name##_booted = true; \
|
||||
return (false); \
|
||||
} \
|
||||
/* Get/set. */ \
|
||||
a_attr a_name##_tsd_wrapper_t * \
|
||||
a_name##_tsd_get_wrapper(void) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \
|
||||
TlsGetValue(a_name##_tsd); \
|
||||
\
|
||||
if (wrapper == NULL) { \
|
||||
wrapper = (a_name##_tsd_wrapper_t *) \
|
||||
malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \
|
||||
if (wrapper == NULL) { \
|
||||
malloc_write("<jemalloc>: Error allocating" \
|
||||
" TSD for "#a_name"\n"); \
|
||||
abort(); \
|
||||
} else { \
|
||||
static a_type tsd_static_data = a_initializer; \
|
||||
wrapper->initialized = false; \
|
||||
wrapper->val = tsd_static_data; \
|
||||
} \
|
||||
if (!TlsSetValue(a_name##_tsd, (void *)wrapper)) { \
|
||||
malloc_write("<jemalloc>: Error setting" \
|
||||
" TSD for "#a_name"\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
} \
|
||||
return (wrapper); \
|
||||
} \
|
||||
a_attr a_type * \
|
||||
a_name##_tsd_get(void) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper; \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
wrapper = a_name##_tsd_get_wrapper(); \
|
||||
return (&wrapper->val); \
|
||||
} \
|
||||
a_attr void \
|
||||
a_name##_tsd_set(a_type *val) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper; \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
wrapper = a_name##_tsd_get_wrapper(); \
|
||||
wrapper->val = *(val); \
|
||||
if (a_cleanup != malloc_tsd_no_cleanup) \
|
||||
wrapper->initialized = true; \
|
||||
}
|
||||
#else
|
||||
#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \
|
||||
a_cleanup) \
|
||||
/* Data structure. */ \
|
||||
typedef struct { \
|
||||
bool initialized; \
|
||||
a_type val; \
|
||||
} a_name##_tsd_wrapper_t; \
|
||||
/* Initialization/cleanup. */ \
|
||||
a_attr void \
|
||||
a_name##_tsd_cleanup_wrapper(void *arg) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *)arg;\
|
||||
\
|
||||
if (a_cleanup != malloc_tsd_no_cleanup && \
|
||||
wrapper->initialized) { \
|
||||
wrapper->initialized = false; \
|
||||
a_cleanup(&wrapper->val); \
|
||||
if (wrapper->initialized) { \
|
||||
/* Trigger another cleanup round. */ \
|
||||
if (pthread_setspecific(a_name##_tsd, \
|
||||
(void *)wrapper)) { \
|
||||
malloc_write("<jemalloc>: Error" \
|
||||
" setting TSD for "#a_name"\n"); \
|
||||
if (opt_abort) \
|
||||
abort(); \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
malloc_tsd_dalloc(wrapper); \
|
||||
} \
|
||||
a_attr bool \
|
||||
a_name##_tsd_boot(void) \
|
||||
{ \
|
||||
\
|
||||
if (pthread_key_create(&a_name##_tsd, \
|
||||
a_name##_tsd_cleanup_wrapper) != 0) \
|
||||
return (true); \
|
||||
a_name##_booted = true; \
|
||||
return (false); \
|
||||
} \
|
||||
/* Get/set. */ \
|
||||
a_attr a_name##_tsd_wrapper_t * \
|
||||
a_name##_tsd_get_wrapper(void) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \
|
||||
pthread_getspecific(a_name##_tsd); \
|
||||
\
|
||||
if (wrapper == NULL) { \
|
||||
tsd_init_block_t block; \
|
||||
wrapper = tsd_init_check_recursion( \
|
||||
&a_name##_tsd_init_head, &block); \
|
||||
if (wrapper) \
|
||||
return (wrapper); \
|
||||
wrapper = (a_name##_tsd_wrapper_t *) \
|
||||
malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \
|
||||
block.data = wrapper; \
|
||||
if (wrapper == NULL) { \
|
||||
malloc_write("<jemalloc>: Error allocating" \
|
||||
" TSD for "#a_name"\n"); \
|
||||
abort(); \
|
||||
} else { \
|
||||
static a_type tsd_static_data = a_initializer; \
|
||||
wrapper->initialized = false; \
|
||||
wrapper->val = tsd_static_data; \
|
||||
} \
|
||||
if (pthread_setspecific(a_name##_tsd, \
|
||||
(void *)wrapper)) { \
|
||||
malloc_write("<jemalloc>: Error setting" \
|
||||
" TSD for "#a_name"\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
tsd_init_finish(&a_name##_tsd_init_head, &block); \
|
||||
} \
|
||||
return (wrapper); \
|
||||
} \
|
||||
a_attr a_type * \
|
||||
a_name##_tsd_get(void) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper; \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
wrapper = a_name##_tsd_get_wrapper(); \
|
||||
return (&wrapper->val); \
|
||||
} \
|
||||
a_attr void \
|
||||
a_name##_tsd_set(a_type *val) \
|
||||
{ \
|
||||
a_name##_tsd_wrapper_t *wrapper; \
|
||||
\
|
||||
assert(a_name##_booted); \
|
||||
wrapper = a_name##_tsd_get_wrapper(); \
|
||||
wrapper->val = *(val); \
|
||||
if (a_cleanup != malloc_tsd_no_cleanup) \
|
||||
wrapper->initialized = true; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \
|
||||
!defined(_WIN32))
|
||||
struct tsd_init_block_s {
|
||||
ql_elm(tsd_init_block_t) link;
|
||||
pthread_t thread;
|
||||
void *data;
|
||||
};
|
||||
struct tsd_init_head_s {
|
||||
ql_head(tsd_init_block_t) blocks;
|
||||
malloc_mutex_t lock;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
void *malloc_tsd_malloc(size_t size);
|
||||
void malloc_tsd_dalloc(void *wrapper);
|
||||
void malloc_tsd_no_cleanup(void *);
|
||||
void malloc_tsd_cleanup_register(bool (*f)(void));
|
||||
void malloc_tsd_boot(void);
|
||||
#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \
|
||||
!defined(_WIN32))
|
||||
void *tsd_init_check_recursion(tsd_init_head_t *head,
|
||||
tsd_init_block_t *block);
|
||||
void tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block);
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_TYPES
|
||||
|
||||
/* Size of stack-allocated buffer passed to buferror(). */
|
||||
#define BUFERROR_BUF 64
|
||||
|
||||
/*
|
||||
* Size of stack-allocated buffer used by malloc_{,v,vc}printf(). This must be
|
||||
* large enough for all possible uses within jemalloc.
|
||||
*/
|
||||
#define MALLOC_PRINTF_BUFSIZE 4096
|
||||
|
||||
/*
|
||||
* Wrap a cpp argument that contains commas such that it isn't broken up into
|
||||
* multiple arguments.
|
||||
*/
|
||||
#define JEMALLOC_ARG_CONCAT(...) __VA_ARGS__
|
||||
|
||||
/*
|
||||
* Silence compiler warnings due to uninitialized values. This is used
|
||||
* wherever the compiler fails to recognize that the variable is never used
|
||||
* uninitialized.
|
||||
*/
|
||||
#ifdef JEMALLOC_CC_SILENCE
|
||||
# define JEMALLOC_CC_SILENCE_INIT(v) = v
|
||||
#else
|
||||
# define JEMALLOC_CC_SILENCE_INIT(v)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define a custom assert() in order to reduce the chances of deadlock during
|
||||
* assertion failure.
|
||||
*/
|
||||
#ifndef assert
|
||||
#define assert(e) do { \
|
||||
if (config_debug && !(e)) { \
|
||||
malloc_printf( \
|
||||
"<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \
|
||||
__FILE__, __LINE__, #e); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef not_reached
|
||||
#define not_reached() do { \
|
||||
if (config_debug) { \
|
||||
malloc_printf( \
|
||||
"<jemalloc>: %s:%d: Unreachable code reached\n", \
|
||||
__FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef not_implemented
|
||||
#define not_implemented() do { \
|
||||
if (config_debug) { \
|
||||
malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \
|
||||
__FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef assert_not_implemented
|
||||
#define assert_not_implemented(e) do { \
|
||||
if (config_debug && !(e)) \
|
||||
not_implemented(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Use to assert a particular configuration, e.g., cassert(config_debug). */
|
||||
#define cassert(c) do { \
|
||||
if ((c) == false) \
|
||||
not_reached(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* JEMALLOC_H_TYPES */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_STRUCTS
|
||||
|
||||
#endif /* JEMALLOC_H_STRUCTS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_EXTERNS
|
||||
|
||||
int buferror(int err, char *buf, size_t buflen);
|
||||
uintmax_t malloc_strtoumax(const char *restrict nptr,
|
||||
char **restrict endptr, int base);
|
||||
void malloc_write(const char *s);
|
||||
|
||||
/*
|
||||
* malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating
|
||||
* point math.
|
||||
*/
|
||||
int malloc_vsnprintf(char *str, size_t size, const char *format,
|
||||
va_list ap);
|
||||
int malloc_snprintf(char *str, size_t size, const char *format, ...)
|
||||
JEMALLOC_ATTR(format(printf, 3, 4));
|
||||
void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
|
||||
const char *format, va_list ap);
|
||||
void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque,
|
||||
const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4));
|
||||
void malloc_printf(const char *format, ...)
|
||||
JEMALLOC_ATTR(format(printf, 1, 2));
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
size_t pow2_ceil(size_t x);
|
||||
void set_errno(int errnum);
|
||||
int get_errno(void);
|
||||
#endif
|
||||
|
||||
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_))
|
||||
/* Compute the smallest power of 2 that is >= x. */
|
||||
JEMALLOC_INLINE size_t
|
||||
pow2_ceil(size_t x)
|
||||
{
|
||||
|
||||
x--;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
#if (LG_SIZEOF_PTR == 3)
|
||||
x |= x >> 32;
|
||||
#endif
|
||||
x++;
|
||||
return (x);
|
||||
}
|
||||
|
||||
/* Sets error code */
|
||||
JEMALLOC_INLINE void
|
||||
set_errno(int errnum)
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
SetLastError(errnum);
|
||||
#else
|
||||
errno = errnum;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get last error code */
|
||||
JEMALLOC_INLINE int
|
||||
get_errno(void)
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
return (GetLastError());
|
||||
#else
|
||||
return (errno);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JEMALLOC_H_INLINES */
|
||||
/******************************************************************************/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user