3 * gcc test4.c mpool.c mstat.c -o test4 -Wall -W -Wextra -ansi -pedantic
8 #include <string.h> /* for memset() */
9 #include <time.h> /* for time() in srand() */
10 #include <sys/queue.h>
15 #define MAX_EPOCHS 20000 /* Maximum number of epochs of simulation */
16 #define MAX_LIFETIME 1000 /* Maximum lifetime of a reserved block */
17 #define MAX_LOGSIZE 5 /* Maximum logarithm of block's size */
18 #define TI 5 /* Every `TI' steps dump statistics */
20 typedef struct simnode
{
22 unsigned int lifetime
;
23 LIST_ENTRY(simnode
) next_node
;
26 LIST_HEAD(simhead
, simnode
);
27 typedef struct simhead simhead_t
;
29 /* Function prototypes */
30 void sim_add_to_list(simhead_t
*simhead
, simnode_t
*simnode
);
31 void sim_free_from_list(mpool_t
*mpool
, simhead_t
*simhead
, unsigned int t
);
32 void sim_print_stats(const mpool_t
*mpool
, unsigned int t
, FILE *fp
);
36 simnode_t simnode
[MAX_EPOCHS
];
42 /* Initialize memory pool */
43 mpret
= mpool_init(&mpool
, 25, 5);
44 if (mpret
== MPOOL_ENOMEM
) {
45 fprintf(stderr
, "mpool: not enough memory\n");
48 else if (mpret
== MPOOL_EBADVAL
) {
49 fprintf(stderr
, "mpool: bad value passed to mpool_init()\n");
53 /* Initialize random number generator */
56 /* Initialize simlist */
60 for (t
= 0; t
< MAX_EPOCHS
; t
++) {
61 /* Is it time to dump statistics ? */
63 sim_print_stats(mpool
, t
, stdout
);
65 /* Free all blocks that lived their life */
66 sim_free_from_list(mpool
, &simhead
, t
);
69 * Calculate a random size `sz' and a random lifetime `lt',
70 * similar to the way Moirae defined peoples' lives in Greek Mythology.
71 * (One could use other distributions than the uniform we use here)
73 sz
= 1 << rand() % (1 + MAX_LOGSIZE
);
74 if (t
< (MAX_EPOCHS
- MAX_LIFETIME
))
75 lt
= 1 + rand() % MAX_LIFETIME
;
77 lt
= 1 + rand() % (MAX_EPOCHS
- t
);
78 /*printf("t = %u\tsz = %u\tlt = %u\n", t, sz, lt);*/
80 /* Allocate a block of size `sz' and make it last `lt' time intervals */
81 if ((simnode
[t
].ptr
= mpool_alloc(mpool
, sz
)) == NULL
) {
82 fprintf(stderr
, "mpool: no available block\n");
86 simnode
[t
].lifetime
= t
+ lt
;
88 /* Add block to list and let it find its correct position in it */
89 sim_add_to_list(&simhead
, &simnode
[t
]);
92 /* Free the last of Mohicans */
93 sim_free_from_list(mpool
, &simhead
, t
);
96 sim_print_stats(mpool
, t
, stdout
);
98 /* Destroy memory pool and free all resources */
104 void sim_add_to_list(simhead_t
*simhead
, simnode_t
*simnode
)
109 * LIST_FOREACH(pnode, simhead, next_node)
110 * printf("%u -> ", pnode->lifetime);
114 /* Make sure that we put `simnode' in the right position */
115 LIST_FOREACH(pnode
, simhead
, next_node
) {
116 if (simnode
->lifetime
< pnode
->lifetime
) {
117 LIST_INSERT_BEFORE(pnode
, simnode
, next_node
);
120 else if (LIST_NEXT(pnode
, next_node
) == NULL
) {
121 LIST_INSERT_AFTER(pnode
, simnode
, next_node
);
127 * First element goes here.
128 * This is called only when the list is empty.
130 LIST_INSERT_HEAD(simhead
, simnode
, next_node
);
133 void sim_free_from_list(mpool_t
*mpool
, simhead_t
*simhead
, unsigned int t
)
138 * Blocks with the same lifetime are placed together,
139 * e.g. ... -> 5 -> 5 -> 7 -> 7 -> 7 -> 7 -> 8 -> 8 -> 9 -> 9 -> ...
140 * That said, if the continuity breaks in one node,
141 * we are done and we should return.
143 LIST_FOREACH(pnode
, simhead
, next_node
) {
144 if (t
== pnode
->lifetime
) {
145 /*printf("freeing %u\tptr = %p\n", t, pnode->ptr);*/
146 mpool_free(mpool
, pnode
->ptr
);
147 LIST_REMOVE(pnode
, next_node
);
154 void sim_print_stats(const mpool_t
*mpool
, unsigned int t
, FILE *fp
)
156 size_t an
, un
; /* nodes */
157 size_t ab
, ub
; /* blocks */
158 size_t me
= 1, sp
= 1; /* merges, splits */
161 mpool_stat_get_nodes(mpool
, &an
, &un
);
162 mpool_stat_get_bytes(mpool
, &ab
, &ub
);
163 me
= mpool_stat_get_merges(mpool
);
164 sp
= mpool_stat_get_splits(mpool
);
166 fprintf(fp
, "%u\t%u\t%u\t%.2f\t%u\t%u\t%.2f\t%u\t%u\t%.2f\n", t
,
167 an
, un
, 100.0 * an
/ (an
+ un
),
168 ab
, ub
, 100.0 * ab
/ (ab
+ ub
),
169 sp
, me
, 1.0 * sp
/me
);
171 /* Print length of every block
172 * for (i = 0; i < mpool_stat_get_blocks(mpool); i++)
173 * fprintf(fp, "%u\n", mpool_stat_get_block_length(mpool, i));