summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/slang/slmalloc.c
blob: be4ed6caee5e2fdd7b2c18008ec3c53554abdc4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* Copyright (c) 1992, 1999, 2001 John E. Davis
 * This file is part of the S-Lang library.
 *
 * You may distribute under the terms of either the GNU General Public
 * License or the Perl Artistic License.
 */
#include "slinclud.h"

#ifdef SL_MALLOC_DEBUG
# undef SL_MALLOC_DEBUG
#endif

#include "slang.h"
#include "_slang.h"

#ifdef __alpha
# define Chunk 8
#else
# define Chunk 4
#endif

static long Total_Allocated;
static long Max_Single_Allocation;
static long Max_Allocated;
/* #define SLDEBUG_DOUT */

#ifdef SLDEBUG_DOUT
static FILE *dout;
#endif

void SLmalloc_dump_statistics (void)
{
#ifdef SLDEBUG_DOUT
   fflush (dout);
#endif
   fprintf (stderr, "Total Allocated: %ld\nHighest single allocation: %ld\nHighest Total Allocated:%ld\n",
	    Total_Allocated, Max_Single_Allocation, Max_Allocated);
}

static void register_at_exit_fun (void)
{
   static int is_registered = 0;
   if (is_registered)
     return;
   is_registered = 1;

#ifdef SLDEBUG_DOUT
   if (dout == NULL) dout = fopen ("malloc.out", "w");
#endif
   SLang_add_cleanup_function (SLmalloc_dump_statistics);
}

static void fixup (unsigned char *p, unsigned long n, char *what)
{
   register_at_exit_fun ();

   p += Chunk;
   *(p - 4)= (unsigned char) ((n >> 24) & 0xFF);
   *(p - 3) = (unsigned char) ((n >> 16) & 0xFF);
   *(p - 2) = (unsigned char) ((n >> 8) & 0xFF);
   *(p - 1) = (unsigned char) (n & 0xFF);
   *(p + (int) n) = 27;
   *(p + (int) (n + 1)) = 182;
   *(p + (int) (n + 2)) = 81;
   *(p + (int) (n + 3)) = 86;
   Total_Allocated += (long) n;
   if (Total_Allocated > Max_Allocated) Max_Allocated = Total_Allocated;
   if ((long) n > Max_Single_Allocation)
     Max_Single_Allocation = (long) n;

#ifdef SLDEBUG_DOUT
   fprintf (dout, "ALLOC: %s\t%p %ld\n", what, p, (long) n);
#else
   (void) what;
#endif
}

static void SLmalloc_doerror (char *buf)
{
   SLang_doerror (buf);
}

static int check_memory (unsigned char *p, char *what)
{
   char buf[128];
   unsigned long n;

   register_at_exit_fun ();

   n = ((unsigned long) *(p - 4)) << 24;
   n |= ((unsigned long) *(p - 3)) << 16;
   n |= ((unsigned long) *(p - 2)) << 8;
   n |= (unsigned long) *(p - 1);

   if (n == 0xFFFFFFFFUL)
     {
	sprintf (buf, "%s: %p: Already FREE! Abort NOW.", what, (void*)p - Chunk);
	SLmalloc_doerror (buf);
	return -1;
     }

   if ((*(p + (int) n) != 27)
       || (*(p + (int) (n + 1)) != 182)
       || (*(p + (int) (n + 2)) != 81)
       || (*(p + (int) (n + 3)) != 86))
     {
	sprintf (buf, "\007%s: %p: Memory corrupt! Abort NOW.", what, (void*)p);
	SLmalloc_doerror (buf);
	return -1;
     }

   *(p - 4) = *(p - 3) = *(p - 2) = *(p - 1) = 0xFF;

   Total_Allocated -= (long) n;
   if (Total_Allocated < 0)
     {
	sprintf (buf, "\007%s: %p\nFreed %ld, Allocated is: %ld!\n",
		 what, (void*)p, (long) n, Total_Allocated);
	SLang_doerror (buf);
     }
#ifdef SLDEBUG_DOUT
   fprintf (dout, "FREE: %s:\t%p %ld\n", what, p, (long) n);
#endif
   return 0;
}

void SLdebug_free (char *p)
{
   if (p == NULL) return;
   if (-1 == check_memory ((unsigned char *) p, "FREE")) return;

   SLFREE (p - Chunk);
}

char *SLdebug_malloc (unsigned long n)
{
   char *p;

   if ((p = (char *) SLMALLOC (n + 2 * Chunk)) == NULL) return NULL;

   fixup ((unsigned char *) p, n, "MALLOC");
   return p + Chunk;
}

char *SLdebug_realloc (char *p, unsigned long n)
{
   if (-1 == check_memory ((unsigned char *) p, "REALLOC")) return NULL;
   if ((p = (char *) SLREALLOC (p - Chunk, n + 2 * Chunk)) == NULL) return NULL;
   fixup ((unsigned char *) p, n, "REALLOC");
   return p + Chunk;
}

char *SLdebug_calloc (unsigned long n, unsigned long size)
{
   char *p;
   int m;

   /* This is tough -- hope this is a good assumption!! */
   if (size >= Chunk) m = 1; else m = Chunk;

   if ((p = (char *) SLCALLOC (n + m + m, size)) == NULL) return NULL;
   fixup ((unsigned char *) p, size * n, "CALLOC");
   return p + Chunk;
}