Remove whitespace
[eleutheria.git] / buddy / test4.c
blob2e87d191e8137ce7dd041377c656233a7b9e981f
1 /*
2 * Compile with:
3 * gcc test4.c mpool.c mstat.c -o test4 -Wall -W -Wextra -ansi -pedantic
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h> /* for memset() */
9 #include <time.h> /* for time() in srand() */
10 #include <sys/queue.h>
12 #include "mpool.h"
13 #include "mstat.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 {
21 void *ptr;
22 unsigned int lifetime;
23 LIST_ENTRY(simnode) next_node;
24 } simnode_t;
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);
34 int main(void)
36 simnode_t simnode[MAX_EPOCHS];
37 mpool_t *mpool;
38 mpret_t mpret;
39 simhead_t simhead;
40 size_t t, sz, lt;
42 /* Initialize memory pool */
43 mpret = mpool_init(&mpool, 25, 5);
44 if (mpret == MPOOL_ENOMEM) {
45 fprintf(stderr, "mpool: not enough memory\n");
46 exit(EXIT_FAILURE);
48 else if (mpret == MPOOL_ERANGE) {
49 fprintf(stderr, "mpool: out of range in mpool_init()\n");
50 exit(EXIT_FAILURE);
52 else if (mpret == MPOOL_EBADVAL) {
53 fprintf(stderr, "mpool: bad value passed to mpool_init()\n");
54 exit(EXIT_FAILURE);
57 /* Initialize random number generator */
58 srand(time(NULL));
60 /* Initialize simlist */
61 LIST_INIT(&simhead);
63 /* Run simulation */
64 for (t = 0; t < MAX_EPOCHS; t++) {
65 /* Is it time to dump statistics ? */
66 if (t % TI == 0)
67 sim_print_stats(mpool, t, stdout);
69 /* Free all blocks that lived their life */
70 sim_free_from_list(mpool, &simhead, t);
73 * Calculate a random size `sz' and a random lifetime `lt',
74 * similar to the way Moirae defined peoples' lives in Greek Mythology.
75 * (One could use other distributions than the uniform we use here)
77 sz = 1 << rand() % (1 + MAX_LOGSIZE);
78 if (t < (MAX_EPOCHS - MAX_LIFETIME))
79 lt = 1 + rand() % MAX_LIFETIME;
80 else
81 lt = 1 + rand() % (MAX_EPOCHS - t);
82 /*printf("t = %u\tsz = %u\tlt = %u\n", t, sz, lt);*/
84 /* Allocate a block of size `sz' and make it last `lt' time intervals */
85 if ((simnode[t].ptr = mpool_alloc(mpool, sz)) == NULL) {
86 fprintf(stderr, "mpool: no available block\n");
87 mpool_destroy(mpool);
88 exit(EXIT_FAILURE);
90 simnode[t].lifetime = t + lt;
92 /* Add block to list and let it find its correct position in it */
93 sim_add_to_list(&simhead, &simnode[t]);
96 /* Free the last of Mohicans */
97 sim_free_from_list(mpool, &simhead, t);
99 /* Dump statistics */
100 sim_print_stats(mpool, t, stdout);
102 /* Destroy memory pool and free all resources */
103 mpool_destroy(mpool);
105 return EXIT_SUCCESS;
108 void sim_add_to_list(simhead_t *simhead, simnode_t *simnode)
110 simnode_t *pnode;
113 * LIST_FOREACH(pnode, simhead, next_node)
114 * printf("%u -> ", pnode->lifetime);
115 * printf("\n");
118 /* Make sure that we put `simnode' in the right position */
119 LIST_FOREACH(pnode, simhead, next_node) {
120 if (simnode->lifetime < pnode->lifetime) {
121 LIST_INSERT_BEFORE(pnode, simnode, next_node);
122 return;
124 else if (LIST_NEXT(pnode, next_node) == NULL) {
125 LIST_INSERT_AFTER(pnode, simnode, next_node);
126 return;
131 * First element goes here.
132 * This is called only when the list is empty.
134 LIST_INSERT_HEAD(simhead, simnode, next_node);
137 void sim_free_from_list(mpool_t *mpool, simhead_t *simhead, unsigned int t)
139 simnode_t *pnode;
142 * Blocks with the same lifetime are placed together,
143 * e.g. ... -> 5 -> 5 -> 7 -> 7 -> 7 -> 7 -> 8 -> 8 -> 9 -> 9 -> ...
144 * That said, if the continuity breaks in one node,
145 * we are done and we should return.
147 LIST_FOREACH(pnode, simhead, next_node) {
148 if (t == pnode->lifetime) {
149 /*printf("freeing %u\tptr = %p\n", t, pnode->ptr);*/
150 mpool_free(mpool, pnode->ptr);
151 LIST_REMOVE(pnode, next_node);
153 else
154 return;
158 void sim_print_stats(const mpool_t *mpool, unsigned int t, FILE *fp)
160 size_t an, un; /* nodes */
161 size_t ab, ub; /* blocks */
162 size_t me = 1, sp = 1; /* merges, splits */
163 /*size_t i;*/
165 mpool_stat_get_nodes(mpool, &an, &un);
166 mpool_stat_get_bytes(mpool, &ab, &ub);
167 me = mpool_stat_get_merges(mpool);
168 sp = mpool_stat_get_splits(mpool);
170 fprintf(fp, "%u\t%u\t%u\t%.2f\t%u\t%u\t%.2f\t%u\t%u\t%.2f\n", t,
171 an, un, 100.0 * an / (an + un),
172 ab, ub, 100.0 * ab / (ab + ub),
173 sp, me, 1.0 * sp/me);
175 /* Print length of every block
176 * for (i = 0; i < mpool_stat_get_blocks(mpool); i++)
177 * fprintf(fp, "%u\n", mpool_stat_get_block_length(mpool, i));