e16/src/memory.c

431 lines
13 KiB
C

/*
* Copyright (C) 1999 Carsten Haitzler, Geoff Harrison and various contributors
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
/* uncomment DBUG_MEM to get rudamentary pointer checking */
/* uncomment MEM_OUT to get full debug output. to make this work you have to */
/* put a file in the directory (cwd) you run E from calle e.sym */
/* to generate the e.sym file do: */
/* */
/* nm enlightenment | grep " T " > e.sym */
/* nm enlightenment | grep " t " > e.sym2 */
/* cat e.sym >> e.sym2 */
/* sort < e.sym2 > e.sym */
/* rm e.sym2 */
/* */
/* do that whenever you recompile enlightenment and place the e.sym file in */
/* the current working directory of enlightenment */
/* */
/*#define DBUG_MEM 1 */
/*#define MEM_OUT 1 */
#ifdef DBUG_MEM
#define POINTERS_SIZE 50000
static unsigned int num_pointers = 0;
static void *pointers_ptr[POINTERS_SIZE];
static unsigned int pointers_size[POINTERS_SIZE];
#ifdef MEM_OUT
static void *pointers_stack[POINTERS_SIZE][32];
static char pointers_file[POINTERS_SIZE][16];
static int pointers_line[POINTERS_SIZE];
static time_t pointers_time[POINTERS_SIZE];
#define PSTK(y, x) if (__builtin_frame_address(x)) \
pointers_stack[y][x] = __builtin_return_address(x);\
else goto end;
#define PST(y)\
{\
int _pi;\
for (_pi = 0; _pi < 32; _pi++)\
pointers_stack[y][_pi] = NULL;\
PSTK(y, 0); PSTK(y, 1); PSTK(y, 2); PSTK(y, 3); PSTK(y, 4);\
PSTK(y, 5); PSTK(y, 6); PSTK(y, 7); PSTK(y, 8); PSTK(y, 9);\
PSTK(y, 10); PSTK(y, 11); PSTK(y, 12); PSTK(y, 13); PSTK(y, 14);\
PSTK(y, 15); PSTK(y, 16); PSTK(y, 17); PSTK(y, 18); PSTK(y, 19);\
PSTK(y, 20); PSTK(y, 21); PSTK(y, 22); PSTK(y, 23); PSTK(y, 24);\
PSTK(y, 25); PSTK(y, 26); PSTK(y, 27); PSTK(y, 28); PSTK(y, 29);\
PSTK(y, 30); PSTK(y, 31);\
end: \
}
static struct _symtab
{
void *val;
char *symbol;
}
*sym = NULL;
static int sym_count = 0;
char *
getsym(void *p)
{
int i;
for (i = 0; i < sym_count - 1; i++)
{
if ((p > sym[i].val) && (p < sym[i + 1].val))
return sym[i].symbol;
}
return "";
}
#endif
#endif
void
EDisplayMemUse()
{
#ifdef DBUG_MEM
FILE *f;
unsigned int i, min, max, sum;
max = 0;
min = 0x7ffffff;
sum = 0;
if (!sym)
{
f = fopen("e.sym", "r");
if (f)
{
void *p;
char buf[256];
while (fscanf(f, "%x %*s %250s\n", &p, buf) != EOF)
{
sym_count++;
sym = realloc(sym, sizeof(struct _symtab) * sym_count);
sym[sym_count - 1].val = p;
sym[sym_count - 1].symbol = strdup(buf);
}
fclose(f);
}
}
f = fopen("e.mem.out", "w");
for (i = 0; i < num_pointers; i++)
{
char tm[32];
struct tm tim;
struct tm *tim2;
time_t t2;
sum += pointers_size[i];
if (pointers_size[i] < min)
min = pointers_size[i];
if (pointers_size[i] > max)
max = pointers_size[i];
t2 = pointers_time[i];
tim2 = localtime(&t2);
if (tim2)
{
memcpy(&tim, tim2, sizeof(struct tm));
strftime(tm, 31, "%T", &tim);
}
fprintf(f, "%6i > %p %5i @ %s - %16s line %5i : "
"%s %s %s %s %s %s %s %s "
"%s %s %s %s %s %s %s %s "
"%s %s %s %s %s %s %s %s "
"%s %s %s %s %s %s %s %s\n",
i, pointers_ptr[i], pointers_size[i], tm,
pointers_file[i], pointers_line[i],
getsym(pointers_stack[i][0]), getsym(pointers_stack[i][1]),
getsym(pointers_stack[i][2]), getsym(pointers_stack[i][3]),
getsym(pointers_stack[i][4]), getsym(pointers_stack[i][5]),
getsym(pointers_stack[i][6]), getsym(pointers_stack[i][7]),
getsym(pointers_stack[i][8]), getsym(pointers_stack[i][9]),
getsym(pointers_stack[i][10]), getsym(pointers_stack[i][11]),
getsym(pointers_stack[i][12]), getsym(pointers_stack[i][13]),
getsym(pointers_stack[i][14]), getsym(pointers_stack[i][15]),
getsym(pointers_stack[i][16]), getsym(pointers_stack[i][17]),
getsym(pointers_stack[i][18]), getsym(pointers_stack[i][19]),
getsym(pointers_stack[i][20]), getsym(pointers_stack[i][21]),
getsym(pointers_stack[i][22]), getsym(pointers_stack[i][23]),
getsym(pointers_stack[i][24]), getsym(pointers_stack[i][25]),
getsym(pointers_stack[i][26]), getsym(pointers_stack[i][27]),
getsym(pointers_stack[i][28]), getsym(pointers_stack[i][29]),
getsym(pointers_stack[i][30]), getsym(pointers_stack[i][31]));
}
if (num_pointers > 0)
{
fprintf(f, "Num:%6i Sum:%8i Av:%8i Min:%8i Max%6i\n",
num_pointers, sum, sum / num_pointers, min, max);
}
fclose(f);
#endif
}
#if defined(__FILE__) && defined(__LINE__)
void *
__Emalloc(int size, const char *file, int line)
{
void *p;
EDBUG(9, "Emalloc");
if (size <= 0)
return NULL;
p = malloc(size);
if (!p)
{
if (disp)
UngrabX();
ASSIGN_ALERT(gettext("Cannot allocate enough memory"),
gettext("Ignore this"),
gettext("Restart Enlightenment"),
gettext("Quit Enlightenment"));
Alert(gettext("WARNING!!!!!!\n"
"\n"
"Allocation for %i bytes (%3.0f kB or %3.1f MB) did not succeed.\n"
"\n"
"Either this is a bug where ridiculous amounts of memory\n"
"are being allocated, or your system has run out of both\n"
"real and virtual memory and is unable to satisfy the request.\n"
"\n"
"If you have a low memory system it is suggested to either\n"
"purchase more memory, increase SWAP space, or reconfigure\n"
"Enlightenment to use less resources by turning features off.\n"
"\n"
"The malloc requested was at %s, line %d\n "),
size, (float)size / 1024, (float)size / (1024 * 1024), file,
line);
RESET_ALERT;
}
#ifdef DBUG_MEM
if (p)
{
num_pointers++;
pointers_ptr[num_pointers - 1] = p;
pointers_size[num_pointers - 1] = size;
#ifdef MEM_OUT
strcpy(pointers_file[num_pointers - 1], file);
pointers_line[num_pointers - 1] = line;
pointers_time[num_pointers - 1] = time(NULL);
PST(num_pointers - 1);
#endif
}
#endif
EDBUG_RETURN(p);
}
void *
__Erealloc(void *ptr, int size, const char *file, int line)
{
void *p;
#ifdef DBUG_MEM
char bad = 0;
#endif
if (ptr == NULL)
{
if (size > 0)
return __Emalloc(size, file, line);
else
return NULL;
}
/* If we get here, we know ptr != NULL, so don't test for that case -- mej */
if (size <= 0)
{
__Efree(ptr, file, line);
return NULL;
}
EDBUG(9, "Erealloc");
#ifdef DBUG_MEM
if (ptr)
{
unsigned int i;
bad = 1;
for (i = 0; i < num_pointers; i++)
{
if (pointers_ptr[i] == ptr)
{
bad = 0;
i = num_pointers;
}
}
}
if (bad)
{
if (disp)
UngrabX();
ASSIGN_ALERT(gettext
("Error in reallocating memory that hasn't been allocated"),
gettext("Ignore this"), gettext("Restart Enlightenment"),
gettext("Quit Enlightenment"));
Alert(gettext
("WARNING!!!!!!\n" "\n"
"Re-allocation for %i bytes (%3.0f kB or %3.1f MB)\n"
"for pointer %x is attempting to re-allocate memory for a\n"
"memory chunk that has not been allocated or has already been\n"
"freed.\n" "\n" "This is definitely a bug. Please report it.\n"
"\n" "The error occurred at %s, line %d.\n"), size,
(float)size / 1024, (float)size / (1024 * 1024), ptr, file, line);
RESET_ALERT;
EDBUG_RETURN(NULL);
}
#endif
p = realloc(ptr, size);
if ((!p) && (size != 0))
{
if (disp)
UngrabX();
ASSIGN_ALERT(gettext("Cannot allocate enough memory"),
gettext("Ignore this"),
gettext("Restart Enlightenment"),
gettext("Quit Enlightenment"));
Alert(gettext("WARNING!!!!!!\n"
"\n"
"Re-allocation for %i bytes (%3.0f kB or %3.1f MB) did not succeed.\n"
"\n"
"Either this is a bug where ridiculous amounts of memory\n"
"are being allocated, or your system has run out of both\n"
"real and virtual memory and is unable to satisfy the request.\n"
"\n"
"If you have a low memory system it is suggested to either\n"
"purchase more memory, increase SWAP space, or reconfigure\n"
"Enlightenment to use less resources by turning features off.\n"
"\n"
"The realloc requested was at %s, line %d\n "),
size, (float)size / 1024, (float)size / (1024 * 1024), file,
line);
RESET_ALERT;
}
#ifdef DBUG_MEM
if (p)
{
unsigned int i;
bad = 1;
for (i = 0; i < num_pointers; i++)
{
if (pointers_ptr[i] == ptr)
{
pointers_size[i] = size;
pointers_ptr[i] = p;
i = num_pointers;
}
}
}
#endif
EDBUG_RETURN(p);
}
void
__Efree(void *ptr, const char *file, int line)
{
#ifdef DBUG_MEM
char bad = 0;
#endif
EDBUG(9, "Efree");
#ifdef DBUG_MEM
{
unsigned int i, j, k;
bad = 1;
for (i = 0; i < num_pointers; i++)
{
if (pointers_ptr[i] == ptr)
{
for (j = i; j < num_pointers - 1; j++)
{
pointers_ptr[j] = pointers_ptr[j + 1];
pointers_size[j] = pointers_size[j + 1];
#ifdef MEM_OUT
for (k = 0; k < 32; k++)
pointers_stack[j][k] = pointers_stack[j + 1][k];
strcpy(pointers_file[j], pointers_file[j + 1]);
pointers_line[j] = pointers_line[j + 1];
pointers_time[j] = pointers_time[j + 1];
#endif
}
bad = 0;
i = num_pointers;
num_pointers--;
break;
}
}
}
if (bad)
{
if (disp)
UngrabX();
ASSIGN_ALERT(gettext
("Error in freeing memory that hasn't been allocated"),
gettext("Ignore this"), gettext("Restart Enlightenment"),
gettext("Quit Enlightenment"));
Alert(gettext
("WARNING!!!!!!\n" "\n"
"freeing for pointer %x is attempting to free memory for a\n"
"memory chunk that has not been allocated, or has already been\n"
"freed.\n" "\n" "This is definitely a bug. Please report it.\n"
"\n" "The error occurred at %s, line %d.\n"), ptr, file, line);
RESET_ALERT;
EDBUG_RETURN_;
}
#endif
if (!ptr)
{
if (disp)
UngrabX();
ASSIGN_ALERT(gettext("Error in attempting to free NULL pointer"),
gettext("Ignore this (safe)"),
gettext("Restart Enlightenment"),
gettext("Quit Enlightenment"));
Alert(gettext("WARNING!!!!!!\n"
"\n"
"Enlightenment attempted to free a NULL pointer.\n"
"\n"
"This is definitely a bug. Please report it.\n"
"It is safe to ignore this error and continue running Enlightenment.\n"
"\n"
"The pointer value was %x.\n"
"The error occurred at %s, line %d.\n"), ptr, file, line);
RESET_ALERT;
EDBUG_RETURN_;
}
free(ptr);
EDBUG_RETURN_;
}
#endif
char *
duplicate(char *s)
{
char *ss;
int sz;
EDBUG(9, "duplicate");
if (!s)
EDBUG_RETURN(NULL);
sz = strlen(s);
ss = Emalloc(sz + 1);
strncpy(ss, s, sz + 1);
EDBUG_RETURN(ss);
}