00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <pthread.h>
00013 #include <stdarg.h>
00014 #include <stdint.h>
00015 #include <stdlib.h>
00016 #include <unistd.h>
00017 #include <string.h>
00018 #include <list.h>
00019 #include <debug.h>
00020 #include "memalloc.h"
00021
00022 #define ROUNDS 1000
00023 #define NPTRS 256
00024 #define ALLOCSIZE (256*3)
00025 #define NTHREADS 5
00026
00027 #define MEMSIZE (1<<16)
00028 static long long leftfence;
00029 static uint8_t memory[MEMSIZE];
00030 static long long rightfence;
00031
00032
00033
00034 extern void exit(int);
00035 extern int rand_r(unsigned int *);
00036
00037
00038
00039 static void
00040 check_and_free(uint8_t **ptr, size_t sz)
00041 {
00042 int k = 0, s = 0;
00043 for (k = 0; k < sz; k++)
00044 s += sz + k - (*ptr)[k];
00045 s = s % 256;
00046 ASSERT (s == 0 || !!!"Memory corruption detected!");
00047
00048 mem_free(*ptr);
00049 *ptr = NULL;
00050 }
00051
00052
00053
00054
00055 static void
00056 allocate_and_set(uint8_t **ptr, size_t sz)
00057 {
00058 if (*ptr == NULL)
00059 *ptr = mem_alloc(sz);
00060
00061 if (*ptr)
00062 {
00063 int k = 0;
00064 for (k = 0; k < sz; k++)
00065 (*ptr)[k] = sz + k;
00066 }
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076 static void *
00077 test_single(void *arg)
00078 {
00079 uint8_t *ptrs[NPTRS];
00080 size_t sizes[NPTRS];
00081 memset(ptrs, 0, sizeof ptrs);
00082
00083 unsigned seed = (unsigned) arg;
00084
00085
00086 bool alloc = true;
00087 int j;
00088 for (j = 0; j < ROUNDS; j++)
00089 {
00090 int i;
00091 for (i = 0; i < NPTRS; i++)
00092 {
00093
00094 if (rand_r(&seed) % 100 < 50)
00095 continue;
00096
00097 if (alloc)
00098 {
00099
00100 if (ptrs[i] == NULL)
00101 sizes[i] = (rand_r(&seed) % (ALLOCSIZE/4) + 1) * 4;
00102 allocate_and_set(&ptrs[i], sizes[i]);
00103 }
00104 else
00105 if (ptrs[i] != NULL)
00106
00107 check_and_free(&ptrs[i], sizes[i]);
00108 }
00109
00110 alloc = !alloc;
00111 }
00112
00113
00114 int i;
00115 for (i = 0; i < NPTRS; i++)
00116 if (ptrs[i] != NULL)
00117 check_and_free(ptrs + i, sizes[i]);
00118
00119 return NULL;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128 static void
00129 check_free_list_size()
00130 {
00131 bool success = true;
00132 if (mem_sizeof_free_list() != 1)
00133 {
00134 printf("elements in free list %d, should be 1.\n",
00135 mem_sizeof_free_list());
00136 success = false;
00137 }
00138
00139 if (!success)
00140 {
00141 printf("Test failed.\n");
00142 exit(-1);
00143 }
00144 }
00145
00146
00147
00148
00149
00150
00151
00152 static int
00153 basic_tests()
00154 {
00155 const size_t HEADER = 12;
00156
00157
00158
00159 void *bottom = mem_alloc(MEMSIZE-sizeof(size_t));
00160 ASSERT(bottom || !!!"Unable to allocate");
00161 mem_free(bottom);
00162 check_free_list_size();
00163
00164 bottom = mem_alloc(MEMSIZE-sizeof(size_t)-HEADER-4);
00165 ASSERT(bottom || !!!"Unable to allocate");
00166
00167 void *top = mem_alloc(4);
00168 ASSERT(top || !!!"Unable to allocate");
00169
00170 mem_free(top);
00171 mem_free(bottom);
00172 check_free_list_size();
00173
00174 bottom = mem_alloc(1024-sizeof(size_t));
00175 ASSERT(bottom || !!!"Unable to allocate");
00176 void *middle = mem_alloc(MEMSIZE-HEADER-2*1024);
00177 ASSERT(middle || !!!"Unable to allocate");
00178 top = mem_alloc(1024-HEADER);
00179 ASSERT(top || !!!"Unable to allocate");
00180 mem_free(bottom);
00181
00182 bottom = mem_alloc(2048-HEADER);
00183 ASSERT(bottom == NULL || !!!"Impossible to allocate");
00184 bottom = mem_alloc(512-HEADER);
00185 mem_free(middle);
00186 mem_free(top);
00187 top = mem_alloc(MEMSIZE-512-1024-HEADER);
00188 ASSERT(bottom || !!!"Unable to allocate");
00189
00190 mem_free(bottom);
00191 mem_free(top);
00192 check_free_list_size();
00193 return 0;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 int
00203 main(int ac, char *av[])
00204 {
00205 const long long magic = 0xdeadbeefdeadbeefLL;
00206 leftfence = rightfence = magic;
00207
00208
00209 mem_init(memory, sizeof memory);
00210
00211 basic_tests();
00212 basic_tests();
00213 printf("Test 1 (basic functionality) passed.\n");
00214
00215
00216 test_single(0);
00217 check_free_list_size();
00218 printf("Test 2 (single-threaded) passed.\n");
00219
00220
00221 pthread_t threads[NTHREADS];
00222 int i;
00223 for (i = 0; i < NTHREADS; i++)
00224 if (pthread_create(threads + i, (const pthread_attr_t*)NULL, test_single, (void*)i) == -1)
00225 {
00226 printf("error creating pthread\n");
00227 exit(-1);
00228 }
00229
00230
00231 for (i = 0; i < NTHREADS; i++)
00232 pthread_join(threads[i], NULL);
00233
00234 check_free_list_size();
00235 printf("Test 3 (with %d threads) passed.\n", NTHREADS);
00236
00237 basic_tests();
00238 ASSERT (leftfence == magic || !!!"Memory corruption");
00239 ASSERT (rightfence == magic || !!!"Memory corruption");
00240 printf("Test 4 (basic functionality) passed.\n");
00241 return 0;
00242 }
00243
00244
00245
00246
00247
00248
00249 void
00250 debug_panic (const char *file, int line, const char *function,
00251 const char *message, ...)
00252 {
00253 va_list args;
00254 printf ("Kernel PANIC at %s:%d in %s(): ", file, line, function);
00255
00256 va_start (args, message);
00257 vprintf (message, args);
00258 printf ("\n");
00259 va_end (args);
00260 exit(-1);
00261 }
00262
00263