1243f7a0508bb014c2a7bf592c466a923911db234Jason Evans#include "test/jemalloc_test.h"
2243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
3243f7a0508bb014c2a7bf592c466a923911db234Jason Evansconst char *malloc_conf = "purge:decay,decay_time:1";
4243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
545a5bf677299eb152c3c47836bd5d946234ce40eJason Evansstatic nstime_monotonic_t *nstime_monotonic_orig;
69bad07903962962de9f656d281b9b1e7e9501c87Jason Evansstatic nstime_update_t *nstime_update_orig;
7243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
8243f7a0508bb014c2a7bf592c466a923911db234Jason Evansstatic unsigned nupdates_mock;
99bad07903962962de9f656d281b9b1e7e9501c87Jason Evansstatic nstime_t time_mock;
10a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evansstatic bool monotonic_mock;
11243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
12243f7a0508bb014c2a7bf592c466a923911db234Jason Evansstatic bool
1345a5bf677299eb152c3c47836bd5d946234ce40eJason Evansnstime_monotonic_mock(void)
1445a5bf677299eb152c3c47836bd5d946234ce40eJason Evans{
1545a5bf677299eb152c3c47836bd5d946234ce40eJason Evans
16a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	return (monotonic_mock);
1745a5bf677299eb152c3c47836bd5d946234ce40eJason Evans}
1845a5bf677299eb152c3c47836bd5d946234ce40eJason Evans
1945a5bf677299eb152c3c47836bd5d946234ce40eJason Evansstatic bool
209bad07903962962de9f656d281b9b1e7e9501c87Jason Evansnstime_update_mock(nstime_t *time)
21243f7a0508bb014c2a7bf592c466a923911db234Jason Evans{
22243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
23243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	nupdates_mock++;
24a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	if (monotonic_mock)
259bad07903962962de9f656d281b9b1e7e9501c87Jason Evans		nstime_copy(time, &time_mock);
26a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	return (!monotonic_mock);
27243f7a0508bb014c2a7bf592c466a923911db234Jason Evans}
28243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
29243f7a0508bb014c2a7bf592c466a923911db234Jason EvansTEST_BEGIN(test_decay_ticks)
30243f7a0508bb014c2a7bf592c466a923911db234Jason Evans{
31243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	ticker_t *decay_ticker;
32243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	unsigned tick0, tick1;
33243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	size_t sz, huge0, large0;
34243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	void *p;
35243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
36243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	test_skip_if(opt_purge != purge_mode_decay);
37243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
38243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	decay_ticker = decay_ticker_get(tsd_fetch(), 0);
39243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_ptr_not_null(decay_ticker,
40243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    "Unexpected failure getting decay ticker");
41243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
42243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	sz = sizeof(size_t);
438f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("arenas.hchunk.0.size", (void *)&huge0, &sz, NULL,
448f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    0), 0, "Unexpected mallctl failure");
458f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large0, &sz, NULL,
468f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    0), 0, "Unexpected mallctl failure");
47243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
489f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	/*
499f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 * Test the standard APIs using a huge size class, since we can't
509f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 * control tcache interactions (except by completely disabling tcache
519f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 * for the entire test program).
529f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 */
539f24c944744e91d0cfe1864287ca7a52c16598faJason Evans
54243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* malloc(). */
55243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
56243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	p = malloc(huge0);
57243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_ptr_not_null(p, "Unexpected malloc() failure");
58243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
59243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0, "Expected ticker to tick during malloc()");
60243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* free(). */
61243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
62243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	free(p);
63243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
64243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0, "Expected ticker to tick during free()");
65243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
66243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* calloc(). */
67243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
68243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	p = calloc(1, huge0);
69243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_ptr_not_null(p, "Unexpected calloc() failure");
70243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
71243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0, "Expected ticker to tick during calloc()");
72243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	free(p);
73243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
74243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* posix_memalign(). */
75243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
76243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_d_eq(posix_memalign(&p, sizeof(size_t), huge0), 0,
77243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    "Unexpected posix_memalign() failure");
78243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
79243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0,
80243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    "Expected ticker to tick during posix_memalign()");
81243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	free(p);
82243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
83243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* aligned_alloc(). */
84243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
85243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	p = aligned_alloc(sizeof(size_t), huge0);
86243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_ptr_not_null(p, "Unexpected aligned_alloc() failure");
87243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
88243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0,
89243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    "Expected ticker to tick during aligned_alloc()");
90243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	free(p);
91243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
92243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* realloc(). */
93243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* Allocate. */
94243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
95243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	p = realloc(NULL, huge0);
96243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_ptr_not_null(p, "Unexpected realloc() failure");
97243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
98243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0, "Expected ticker to tick during realloc()");
99243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* Reallocate. */
100243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
101243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	p = realloc(p, huge0);
102243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_ptr_not_null(p, "Unexpected realloc() failure");
103243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
104243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0, "Expected ticker to tick during realloc()");
105243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/* Deallocate. */
106243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick0 = ticker_read(decay_ticker);
107243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	realloc(p, 0);
108243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	tick1 = ticker_read(decay_ticker);
109243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_u32_ne(tick1, tick0, "Expected ticker to tick during realloc()");
110243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
1119f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	/*
1129f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 * Test the *allocx() APIs using huge, large, and small size classes,
1139f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 * with tcache explicitly disabled.
1149f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 */
1159f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	{
1169f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		unsigned i;
1179f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		size_t allocx_sizes[3];
1189f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		allocx_sizes[0] = huge0;
1199f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		allocx_sizes[1] = large0;
1209f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		allocx_sizes[2] = 1;
1219f24c944744e91d0cfe1864287ca7a52c16598faJason Evans
1229f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		for (i = 0; i < sizeof(allocx_sizes) / sizeof(size_t); i++) {
1239f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			sz = allocx_sizes[i];
1249f24c944744e91d0cfe1864287ca7a52c16598faJason Evans
1259f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			/* mallocx(). */
1269f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick0 = ticker_read(decay_ticker);
1279f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			p = mallocx(sz, MALLOCX_TCACHE_NONE);
1289f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_ptr_not_null(p, "Unexpected mallocx() failure");
1299f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick1 = ticker_read(decay_ticker);
1309f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_u32_ne(tick1, tick0,
1319f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Expected ticker to tick during mallocx() (sz=%zu)",
1329f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    sz);
1339f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			/* rallocx(). */
1349f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick0 = ticker_read(decay_ticker);
1359f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			p = rallocx(p, sz, MALLOCX_TCACHE_NONE);
1369f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_ptr_not_null(p, "Unexpected rallocx() failure");
1379f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick1 = ticker_read(decay_ticker);
1389f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_u32_ne(tick1, tick0,
1399f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Expected ticker to tick during rallocx() (sz=%zu)",
1409f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    sz);
1419f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			/* xallocx(). */
1429f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick0 = ticker_read(decay_ticker);
1439f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			xallocx(p, sz, 0, MALLOCX_TCACHE_NONE);
1449f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick1 = ticker_read(decay_ticker);
1459f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_u32_ne(tick1, tick0,
1469f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Expected ticker to tick during xallocx() (sz=%zu)",
1479f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    sz);
1489f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			/* dallocx(). */
1499f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick0 = ticker_read(decay_ticker);
1509f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			dallocx(p, MALLOCX_TCACHE_NONE);
1519f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick1 = ticker_read(decay_ticker);
1529f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_u32_ne(tick1, tick0,
1539f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Expected ticker to tick during dallocx() (sz=%zu)",
1549f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    sz);
1559f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			/* sdallocx(). */
1569f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			p = mallocx(sz, MALLOCX_TCACHE_NONE);
1579f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_ptr_not_null(p, "Unexpected mallocx() failure");
1589f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick0 = ticker_read(decay_ticker);
1599f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			sdallocx(p, sz, MALLOCX_TCACHE_NONE);
1609f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick1 = ticker_read(decay_ticker);
1619f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_u32_ne(tick1, tick0,
1629f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Expected ticker to tick during sdallocx() "
1639f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "(sz=%zu)", sz);
1649f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		}
1659f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	}
1669f24c944744e91d0cfe1864287ca7a52c16598faJason Evans
1679f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	/*
1689f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 * Test tcache fill/flush interactions for large and small size classes,
1699f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 * using an explicit tcache.
1709f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	 */
1717d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans	if (config_tcache) {
1729f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		unsigned tcache_ind, i;
1739f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		size_t tcache_sizes[2];
1749f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		tcache_sizes[0] = large0;
1759f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		tcache_sizes[1] = 1;
1769f24c944744e91d0cfe1864287ca7a52c16598faJason Evans
1779f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		sz = sizeof(unsigned);
1788f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		assert_d_eq(mallctl("tcache.create", (void *)&tcache_ind, &sz,
1798f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		    NULL, 0), 0, "Unexpected mallctl failure");
1809f24c944744e91d0cfe1864287ca7a52c16598faJason Evans
1819f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		for (i = 0; i < sizeof(tcache_sizes) / sizeof(size_t); i++) {
1829f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			sz = tcache_sizes[i];
1839f24c944744e91d0cfe1864287ca7a52c16598faJason Evans
1849f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			/* tcache fill. */
1859f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick0 = ticker_read(decay_ticker);
1869f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			p = mallocx(sz, MALLOCX_TCACHE(tcache_ind));
1879f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_ptr_not_null(p, "Unexpected mallocx() failure");
1889f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick1 = ticker_read(decay_ticker);
1899f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_u32_ne(tick1, tick0,
1909f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Expected ticker to tick during tcache fill "
1919f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "(sz=%zu)", sz);
1929f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			/* tcache flush. */
1939f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			dallocx(p, MALLOCX_TCACHE(tcache_ind));
1949f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick0 = ticker_read(decay_ticker);
1959f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_d_eq(mallctl("tcache.flush", NULL, NULL,
1968f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans			    (void *)&tcache_ind, sizeof(unsigned)), 0,
1979f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Unexpected mallctl failure");
1989f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			tick1 = ticker_read(decay_ticker);
1999f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			assert_u32_ne(tick1, tick0,
2009f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "Expected ticker to tick during tcache flush "
2019f24c944744e91d0cfe1864287ca7a52c16598faJason Evans			    "(sz=%zu)", sz);
2029f24c944744e91d0cfe1864287ca7a52c16598faJason Evans		}
2039f24c944744e91d0cfe1864287ca7a52c16598faJason Evans	}
204243f7a0508bb014c2a7bf592c466a923911db234Jason Evans}
205243f7a0508bb014c2a7bf592c466a923911db234Jason EvansTEST_END
206243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
207243f7a0508bb014c2a7bf592c466a923911db234Jason EvansTEST_BEGIN(test_decay_ticker)
208243f7a0508bb014c2a7bf592c466a923911db234Jason Evans{
209243f7a0508bb014c2a7bf592c466a923911db234Jason Evans#define	NPS 1024
210243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	int flags = (MALLOCX_ARENA(0) | MALLOCX_TCACHE_NONE);
211243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	void *ps[NPS];
212fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	uint64_t epoch;
213fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	uint64_t npurge0 = 0;
214fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	uint64_t npurge1 = 0;
2157d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans	size_t sz, large;
216243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	unsigned i, nupdates0;
2179bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_t time, decay_time, deadline;
218243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
219243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	test_skip_if(opt_purge != purge_mode_decay);
220243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
221243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	/*
222243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	 * Allocate a bunch of large objects, pause the clock, deallocate the
223243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	 * objects, restore the clock, then [md]allocx() in a tight loop to
224243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	 * verify the ticker triggers purging.
225243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	 */
226243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
2277d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans	if (config_tcache) {
2287d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans		size_t tcache_max;
2297d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans
2307d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans		sz = sizeof(size_t);
2318f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		assert_d_eq(mallctl("arenas.tcache_max", (void *)&tcache_max,
2328f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		    &sz, NULL, 0), 0, "Unexpected mallctl failure");
2337d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans		large = nallocx(tcache_max + 1, flags);
2347d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans	}  else {
2357d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans		sz = sizeof(size_t);
2368f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large, &sz,
2378f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		    NULL, 0), 0, "Unexpected mallctl failure");
2387d3055432d303f114d15f67c60bdebcbb4dbd39aJason Evans	}
239243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
240243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
241243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    "Unexpected mallctl failure");
2428f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
2438f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    sizeof(uint64_t)), 0, "Unexpected mallctl failure");
244243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	sz = sizeof(uint64_t);
2458f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge0, &sz,
2468f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    NULL, 0), config_stats ? 0 : ENOENT, "Unexpected mallctl result");
247243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
248243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	for (i = 0; i < NPS; i++) {
249243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		ps[i] = mallocx(large, flags);
250243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		assert_ptr_not_null(ps[i], "Unexpected mallocx() failure");
251243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	}
252243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
253243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	nupdates_mock = 0;
2549bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_init(&time_mock, 0);
2559bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update(&time_mock);
256a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	monotonic_mock = true;
257243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
258a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	nstime_monotonic_orig = nstime_monotonic;
2599bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update_orig = nstime_update;
260a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	nstime_monotonic = nstime_monotonic_mock;
2619bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update = nstime_update_mock;
262243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
263243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	for (i = 0; i < NPS; i++) {
264243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		dallocx(ps[i], flags);
265243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		nupdates0 = nupdates_mock;
266243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		assert_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0,
267243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		    "Unexpected arena.0.decay failure");
268243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		assert_u_gt(nupdates_mock, nupdates0,
2699bad07903962962de9f656d281b9b1e7e9501c87Jason Evans		    "Expected nstime_update() to be called");
270243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	}
271243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
272a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	nstime_monotonic = nstime_monotonic_orig;
2739bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update = nstime_update_orig;
274243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
2759bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_init(&time, 0);
2769bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update(&time);
2779bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_init2(&decay_time, opt_decay_time, 0);
2789bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_copy(&deadline, &time);
2799bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_add(&deadline, &decay_time);
280243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	do {
281243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		for (i = 0; i < DECAY_NTICKS_PER_UPDATE / 2; i++) {
282243f7a0508bb014c2a7bf592c466a923911db234Jason Evans			void *p = mallocx(1, flags);
283243f7a0508bb014c2a7bf592c466a923911db234Jason Evans			assert_ptr_not_null(p, "Unexpected mallocx() failure");
284243f7a0508bb014c2a7bf592c466a923911db234Jason Evans			dallocx(p, flags);
285243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		}
2868f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
287243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		    sizeof(uint64_t)), 0, "Unexpected mallctl failure");
288243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		sz = sizeof(uint64_t);
2898f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge1,
2908f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans		    &sz, NULL, 0), config_stats ? 0 : ENOENT,
291fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans		    "Unexpected mallctl result");
292243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
2939bad07903962962de9f656d281b9b1e7e9501c87Jason Evans		nstime_update(&time);
2949bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	} while (nstime_compare(&time, &deadline) <= 0 && npurge1 == npurge0);
295243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
296fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	if (config_stats)
297fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans		assert_u64_gt(npurge1, npurge0, "Expected purging to occur");
298243f7a0508bb014c2a7bf592c466a923911db234Jason Evans#undef NPS
299243f7a0508bb014c2a7bf592c466a923911db234Jason Evans}
300243f7a0508bb014c2a7bf592c466a923911db234Jason EvansTEST_END
301243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
302243f7a0508bb014c2a7bf592c466a923911db234Jason EvansTEST_BEGIN(test_decay_nonmonotonic)
303243f7a0508bb014c2a7bf592c466a923911db234Jason Evans{
304243f7a0508bb014c2a7bf592c466a923911db234Jason Evans#define	NPS (SMOOTHSTEP_NSTEPS + 1)
305243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	int flags = (MALLOCX_ARENA(0) | MALLOCX_TCACHE_NONE);
306243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	void *ps[NPS];
307fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	uint64_t epoch;
308fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	uint64_t npurge0 = 0;
309fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	uint64_t npurge1 = 0;
310243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	size_t sz, large0;
311243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	unsigned i, nupdates0;
312243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
313243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	test_skip_if(opt_purge != purge_mode_decay);
314243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
315243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	sz = sizeof(size_t);
3168f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large0, &sz, NULL,
3178f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    0), 0, "Unexpected mallctl failure");
318243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
319243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
320243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    "Unexpected mallctl failure");
3218f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
3228f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    sizeof(uint64_t)), 0, "Unexpected mallctl failure");
323243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	sz = sizeof(uint64_t);
3248f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge0, &sz,
3258f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    NULL, 0), config_stats ? 0 : ENOENT, "Unexpected mallctl result");
326243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
327243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	nupdates_mock = 0;
3289bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_init(&time_mock, 0);
3299bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update(&time_mock);
330a14712b4b87df5aa95446f91832ea4846a8f1475Jason Evans	monotonic_mock = false;
331243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
33245a5bf677299eb152c3c47836bd5d946234ce40eJason Evans	nstime_monotonic_orig = nstime_monotonic;
3339bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update_orig = nstime_update;
33445a5bf677299eb152c3c47836bd5d946234ce40eJason Evans	nstime_monotonic = nstime_monotonic_mock;
3359bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update = nstime_update_mock;
336243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
337243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	for (i = 0; i < NPS; i++) {
338243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		ps[i] = mallocx(large0, flags);
339243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		assert_ptr_not_null(ps[i], "Unexpected mallocx() failure");
340243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	}
341243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
342243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	for (i = 0; i < NPS; i++) {
343243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		dallocx(ps[i], flags);
344243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		nupdates0 = nupdates_mock;
345243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		assert_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0,
346243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		    "Unexpected arena.0.decay failure");
347243f7a0508bb014c2a7bf592c466a923911db234Jason Evans		assert_u_gt(nupdates_mock, nupdates0,
3489bad07903962962de9f656d281b9b1e7e9501c87Jason Evans		    "Expected nstime_update() to be called");
349243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	}
350243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
3518f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch,
3528f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    sizeof(uint64_t)), 0, "Unexpected mallctl failure");
353243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	sz = sizeof(uint64_t);
3548f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge1, &sz,
3558f61fdedb908c29905103b22dda32ceb29cd8edeJason Evans	    NULL, 0), config_stats ? 0 : ENOENT, "Unexpected mallctl result");
356243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
357fd4858225b84c12e071eeeaea1fa1bce8731e409Jason Evans	if (config_stats)
35845a5bf677299eb152c3c47836bd5d946234ce40eJason Evans		assert_u64_eq(npurge0, npurge1, "Unexpected purging occurred");
359243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
36045a5bf677299eb152c3c47836bd5d946234ce40eJason Evans	nstime_monotonic = nstime_monotonic_orig;
3619bad07903962962de9f656d281b9b1e7e9501c87Jason Evans	nstime_update = nstime_update_orig;
362243f7a0508bb014c2a7bf592c466a923911db234Jason Evans#undef NPS
363243f7a0508bb014c2a7bf592c466a923911db234Jason Evans}
364243f7a0508bb014c2a7bf592c466a923911db234Jason EvansTEST_END
365243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
366243f7a0508bb014c2a7bf592c466a923911db234Jason Evansint
367243f7a0508bb014c2a7bf592c466a923911db234Jason Evansmain(void)
368243f7a0508bb014c2a7bf592c466a923911db234Jason Evans{
369243f7a0508bb014c2a7bf592c466a923911db234Jason Evans
370243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	return (test(
371243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    test_decay_ticks,
372243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    test_decay_ticker,
373243f7a0508bb014c2a7bf592c466a923911db234Jason Evans	    test_decay_nonmonotonic));
374243f7a0508bb014c2a7bf592c466a923911db234Jason Evans}
375