forked from Telodendria/Cytoplasm
Make Memory use a recursive mutex.
This allows some additional operations to be performed inside the memory hooks, although it's still a bad idea to allocate or free memory while inside the hook.
This commit is contained in:
parent
3ef8a2b234
commit
a177c55c26
2 changed files with 69 additions and 13 deletions
32
src/Memory.c
32
src/Memory.c
|
@ -57,14 +57,42 @@ struct MemoryInfo
|
||||||
#define MEM_BOUND_UPPER(p, x) *(((MEM_BOUND_TYPE *) (((UInt8 *) p) + x)) + 1)
|
#define MEM_BOUND_UPPER(p, x) *(((MEM_BOUND_TYPE *) (((UInt8 *) p) + x)) + 1)
|
||||||
#define MEM_SIZE_ACTUAL(x) (((x) * sizeof(UInt8)) + (2 * sizeof(MEM_BOUND_TYPE)))
|
#define MEM_SIZE_ACTUAL(x) (((x) * sizeof(UInt8)) + (2 * sizeof(MEM_BOUND_TYPE)))
|
||||||
|
|
||||||
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t lock;
|
||||||
static void (*hook) (MemoryAction, MemoryInfo *, void *) = NULL;
|
static void (*hook) (MemoryAction, MemoryInfo *, void *) = MemoryDefaultHook;
|
||||||
static void *hookArgs = NULL;
|
static void *hookArgs = NULL;
|
||||||
|
|
||||||
static MemoryInfo **allocations = NULL;
|
static MemoryInfo **allocations = NULL;
|
||||||
static size_t allocationsSize = 0;
|
static size_t allocationsSize = 0;
|
||||||
static size_t allocationsLen = 0;
|
static size_t allocationsLen = 0;
|
||||||
|
|
||||||
|
int
|
||||||
|
MemoryRuntimeInit(void)
|
||||||
|
{
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (pthread_mutexattr_init(&attr) != 0)
|
||||||
|
{
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
ret = pthread_mutex_init(&lock, &attr);
|
||||||
|
pthread_mutexattr_destroy(&attr);
|
||||||
|
|
||||||
|
ret = (ret == 0);
|
||||||
|
|
||||||
|
finish:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
MemoryRuntimeDestroy(void)
|
||||||
|
{
|
||||||
|
MemoryFreeAll();
|
||||||
|
return pthread_mutex_destroy(&lock) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
MemoryHash(void *p)
|
MemoryHash(void *p)
|
||||||
{
|
{
|
||||||
|
|
50
src/RtStub.c
50
src/RtStub.c
|
@ -33,12 +33,18 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define ERR_BUF_SIZE 128
|
||||||
|
|
||||||
/* Specified by POSIX to contain environment variables */
|
/* Specified by POSIX to contain environment variables */
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
/* The linking program is expected to provide Main */
|
/* The linking program is expected to provide Main */
|
||||||
extern int Main(Array *, HashMap *);
|
extern int Main(Array *, HashMap *);
|
||||||
|
|
||||||
|
/* Functions in the Memory API that are not exported via header */
|
||||||
|
extern int MemoryRuntimeInit(void);
|
||||||
|
extern int MemoryRuntimeDestroy(void);
|
||||||
|
|
||||||
typedef struct MainArgs
|
typedef struct MainArgs
|
||||||
{
|
{
|
||||||
Array *args;
|
Array *args;
|
||||||
|
@ -69,32 +75,46 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
MainArgs args;
|
MainArgs args;
|
||||||
|
|
||||||
MemoryHook(MemoryDefaultHook, NULL);
|
char errBuf[ERR_BUF_SIZE];
|
||||||
|
int errLen;
|
||||||
|
|
||||||
args.args = NULL;
|
args.args = NULL;
|
||||||
args.env = NULL;
|
args.env = NULL;
|
||||||
args.ret = EXIT_FAILURE;
|
args.ret = EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (!MemoryRuntimeInit())
|
||||||
|
{
|
||||||
|
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to initialize Memory runtime.\n");
|
||||||
|
write(STDERR_FILENO, errBuf, errLen);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
args.args = ArrayCreate();
|
args.args = ArrayCreate();
|
||||||
|
|
||||||
if (!args.args)
|
if (!args.args)
|
||||||
{
|
{
|
||||||
Log(LOG_ERR, "Bootstrap error: Unable to allocate memory for arguments.");
|
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to allocate heap memory for program arguments.\n");
|
||||||
args.ret = EXIT_FAILURE;
|
write(STDERR_FILENO, errBuf, errLen);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
args.env = HashMapCreate();
|
args.env = HashMapCreate();
|
||||||
if (!args.env)
|
if (!args.env)
|
||||||
{
|
{
|
||||||
Log(LOG_ERR, "Bootstrap error: Unable to allocate memory for environment.");
|
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to allocate heap memory for program environment.\n");
|
||||||
args.ret = EXIT_FAILURE;
|
write(STDERR_FILENO, errBuf, errLen);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < (size_t) argc; i++)
|
for (i = 0; i < (size_t) argc; i++)
|
||||||
{
|
{
|
||||||
ArrayAdd(args.args, StrDuplicate(argv[i]));
|
char *arg = StrDuplicate(argv[i]);
|
||||||
|
if (!arg || !ArrayAdd(args.args, arg))
|
||||||
|
{
|
||||||
|
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to allocate heap memory for program argument.\n");
|
||||||
|
write(STDERR_FILENO, errBuf, errLen);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
envp = environ;
|
envp = environ;
|
||||||
|
@ -105,6 +125,14 @@ main(int argc, char **argv)
|
||||||
/* It is unclear whether or not envp strings are writable, so
|
/* It is unclear whether or not envp strings are writable, so
|
||||||
* we make our own copy to manipulate it */
|
* we make our own copy to manipulate it */
|
||||||
key = StrDuplicate(*envp);
|
key = StrDuplicate(*envp);
|
||||||
|
|
||||||
|
if (!key)
|
||||||
|
{
|
||||||
|
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to allocate heap memory for program environment variable.\n");
|
||||||
|
write(STDERR_FILENO, errBuf, errLen);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
valInd = strcspn(key, "=");
|
valInd = strcspn(key, "=");
|
||||||
|
|
||||||
key[valInd] = '\0';
|
key[valInd] = '\0';
|
||||||
|
@ -116,15 +144,15 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
if (pthread_create(&mainThread, NULL, MainThread, &args) != 0)
|
if (pthread_create(&mainThread, NULL, MainThread, &args) != 0)
|
||||||
{
|
{
|
||||||
Log(LOG_ERR, "Bootstrap error: Unable to create main thread.");
|
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to create main thread.\n");
|
||||||
args.ret = EXIT_FAILURE;
|
write(STDERR_FILENO, errBuf, errLen);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pthread_join(mainThread, NULL) != 0)
|
if (pthread_join(mainThread, NULL) != 0)
|
||||||
{
|
{
|
||||||
/* Should never happen */
|
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to join main thread.\n");
|
||||||
Log(LOG_ERR, "Unable to join main thread.");
|
write(STDERR_FILENO, errBuf, errLen);
|
||||||
args.ret = EXIT_FAILURE;
|
args.ret = EXIT_FAILURE;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +184,7 @@ finish:
|
||||||
|
|
||||||
GenerateMemoryReport(argc, argv);
|
GenerateMemoryReport(argc, argv);
|
||||||
|
|
||||||
MemoryFreeAll();
|
MemoryRuntimeDestroy();
|
||||||
|
|
||||||
return args.ret;
|
return args.ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue