malloc1.c

00001 /*
00002  * Copyright (c) 2009 Martin Decky
00003  * Copyright (c) 2009 Tomas Bures
00004  * Copyright (c) 2009 Lubomir Bulej
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright
00012  *   notice, this list of conditions and the following disclaimer.
00013  * - Redistributions in binary form must reproduce the above copyright
00014  *   notice, this list of conditions and the following disclaimer in the
00015  *   documentation and/or other materials provided with the distribution.
00016  * - The name of the author may not be used to endorse or promote products
00017  *   derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00020  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00021  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00022  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00024  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00028  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include "common.h"
00034 #include "../tester.h"
00035 
00036 /*
00037  * The test consists of several phases which differ in the size of blocks
00038  * they allocate. The size of blocks is given as a range of minimum and
00039  * maximum allowed size. Each of the phases is divided into 3 subphases which
00040  * differ in the probability of free and alloc actions. Second subphase is
00041  * started when malloc returns 'out of memory' or when MAX_ALLOC is reached.
00042  * Third subphase is started after a given number of cycles. The third subphase
00043  * as well as the whole phase ends when all memory blocks are released.
00044  */
00045 
00046 /*
00047  * Subphases are defined separately here. This is for two reasons:
00048  * 1) data are not duplicated, 2) we don't have to state beforehand
00049  * how many subphases a phase contains.
00050  */
00051 static subphase_t subphases_32B[] = {
00052         {
00053                 .name = "Allocation",
00054                 .cond = {
00055                         .max_cycles = 200,
00056                         .no_memory = 1,
00057                         .no_allocated = 0,
00058                 },
00059                 .prob = {
00060                         .alloc = 90,
00061                         .free = 100
00062                 }
00063         },
00064         {
00065                 .name = "Alloc/Dealloc",
00066                 .cond = {
00067                         .max_cycles = 200,
00068                         .no_memory = 0,
00069                         .no_allocated = 0,
00070                 },
00071                 .prob = {
00072                         .alloc = 50,
00073                         .free = 100
00074                 }
00075         },
00076         {
00077                 .name = "Deallocation",
00078                 .cond = {
00079                         .max_cycles = 0,
00080                         .no_memory = 0,
00081                         .no_allocated = 1,
00082                 },
00083                 .prob = {
00084                         .alloc = 10,
00085                         .free = 100
00086                 }
00087         }
00088 };
00089 
00090 static subphase_t subphases_128K[] = {
00091         {
00092                 .name = "Allocation",
00093                 .cond = {
00094                         .max_cycles = 0,
00095                         .no_memory = 1,
00096                         .no_allocated = 0,
00097                 },
00098                 .prob = {
00099                         .alloc = 70,
00100                         .free = 100
00101                 }
00102         },
00103         {
00104                 .name = "Alloc/Dealloc",
00105                 .cond = {
00106                         .max_cycles = 30,
00107                         .no_memory = 0,
00108                         .no_allocated = 0,
00109                 },
00110                 .prob = {
00111                         .alloc = 50,
00112                         .free = 100
00113                 }
00114         },
00115         {
00116                 .name = "Deallocation",
00117                 .cond = {
00118                         .max_cycles = 0,
00119                         .no_memory = 0,
00120                         .no_allocated = 1,
00121                 },
00122                 .prob = {
00123                         .alloc = 30,
00124                         .free = 100
00125                 }
00126         }
00127 };
00128 
00129 static subphase_t subphases_default[] = {
00130         {
00131                 .name = "Allocation",
00132                 .cond = {
00133                         .max_cycles = 0,
00134                         .no_memory = 1,
00135                         .no_allocated = 0,
00136                 },
00137                 .prob = {
00138                         .alloc = 90,
00139                         .free = 100
00140                 }
00141         },
00142         {
00143                 .name = "Alloc/Dealloc",
00144                 .cond = {
00145                         .max_cycles = 200,
00146                         .no_memory = 0,
00147                         .no_allocated = 0,
00148                 },
00149                 .prob = {
00150                         .alloc = 50,
00151                         .free = 100
00152                 }
00153         },
00154         {
00155                 .name = "Deallocation",
00156                 .cond = {
00157                         .max_cycles = 0,
00158                         .no_memory = 0,
00159                         .no_allocated = 1,
00160                 },
00161                 .prob = {
00162                         .alloc = 10,
00163                         .free = 100
00164                 }
00165         }
00166 };
00167 
00168 /*
00169  * Phase definitions.
00170  */
00171 static phase_t phases[] = {
00172         {
00173                 .name = "32 B memory blocks",
00174                 .alloc = {
00175                         .min_block_size = 32,
00176                         .max_block_size = 32
00177                 },
00178                 .subphases = subphases_32B
00179         },
00180         {
00181                 .name = "128 KB memory blocks",
00182                 .alloc = {
00183                         .min_block_size = 128 * 1024,
00184                         .max_block_size = 128 * 1024
00185                 },
00186                 .subphases = subphases_128K
00187         },
00188         {
00189                 .name = "2500 B memory blocks",
00190                 .alloc = {
00191                         .min_block_size = 2500,
00192                         .max_block_size = 2500
00193                 },
00194                 .subphases = subphases_default
00195         },
00196         {
00197                 .name = "1 B .. 250000 B memory blocks",
00198                 .alloc = {
00199                         .min_block_size = 1,
00200                         .max_block_size = 250000
00201                 },
00202                 .subphases = subphases_default
00203         }
00204 };
00205 
00206 static void do_subphase(phase_t *phase, subphase_t *subphase)
00207 {
00208         for (unsigned int cycles = 0; /* always */; cycles++) {
00209                 
00210                 if ((subphase->cond.max_cycles) &&
00211                     (cycles >= subphase->cond.max_cycles)) {
00212                         /*
00213                          * We have performed the required number of
00214                          * cycles. End the current subphase.
00215                          */
00216                         break;
00217                 }
00218                 
00219                 /*
00220                  * Decide whether we alloc or free memory in this step.
00221                  */
00222                 unsigned int rnd = rand() % 100;
00223                 if (rnd < subphase->prob.alloc) {
00224                         /*
00225                          * Compute a random number lying in interval
00226                          * <min_block_size, max_block_size>
00227                          */
00228                         int alloc = phase->alloc.min_block_size +
00229                             (rand() % (phase->alloc.max_block_size - phase->alloc.min_block_size + 1));
00230                         
00231                         mem_block_t *blk = alloc_block(alloc);
00232                         RETURN_IF_ERROR;
00233                         
00234                         if (blk == NULL) {
00235                                 TPRINTF("F(A)");
00236                                 if (subphase->cond.no_memory) {
00237                                         /* We filled the memory. Proceed to next subphase */
00238                                         break;
00239                                 }
00240                         } else {
00241                                 TPRINTF("A");
00242                                 fill_block(blk);
00243                                 RETURN_IF_ERROR;
00244                         }
00245                         
00246                 } else if (rnd < subphase->prob.free) {
00247                         mem_block_t *blk = get_random_block();
00248                         if (blk == NULL) {
00249                                 TPRINTF("F(R)");
00250                                 if (subphase->cond.no_allocated) {
00251                                         /* We free all the memory. Proceed to next subphase. */
00252                                         break;
00253                                 }
00254                         } else {
00255                                 TPRINTF("R");
00256                                 check_block(blk);
00257                                 RETURN_IF_ERROR;
00258                                 
00259                                 free_block(blk);
00260                                 RETURN_IF_ERROR;
00261                         }
00262                 }
00263         }
00264         
00265         TPRINTF("\n..  finished.\n");
00266 }
00267 
00268 static void do_phase(phase_t *phase)
00269 {
00270         for (unsigned int subno = 0; subno < 3; subno++) {
00271                 subphase_t *subphase = &phase->subphases[subno];
00272                 
00273                 TPRINTF(".. Sub-phase %u (%s)\n", subno + 1, subphase->name);
00274                 do_subphase(phase, subphase);
00275                 RETURN_IF_ERROR;
00276         }
00277 }
00278 
00279 const char *test_malloc1(void)
00280 {
00281         init_mem();
00282         
00283         for (unsigned int phaseno = 0; phaseno < sizeof_array(phases);
00284             phaseno++) {
00285                 phase_t *phase = &phases[phaseno];
00286                 
00287                 TPRINTF("Entering phase %u (%s)\n", phaseno + 1, phase->name);
00288                 
00289                 do_phase(phase);
00290                 if (error_flag)
00291                         break;
00292                 
00293                 TPRINTF("Phase finished.\n");
00294         }
00295         
00296         TPRINTF("Cleaning up.\n");
00297         done_mem();
00298         if (error_flag)
00299                 return "Test failed";
00300         
00301         return NULL;
00302 }

Generated on Thu Jun 2 07:45:43 2011 for HelenOS/USB by  doxygen 1.4.7