forked from latticeware/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_SIZE_ACTUAL(x) (((x) * sizeof(UInt8)) + (2 * sizeof(MEM_BOUND_TYPE)))
|
||||
|
||||
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static void (*hook) (MemoryAction, MemoryInfo *, void *) = NULL;
|
||||
static pthread_mutex_t lock;
|
||||
static void (*hook) (MemoryAction, MemoryInfo *, void *) = MemoryDefaultHook;
|
||||
static void *hookArgs = NULL;
|
||||
|
||||
static MemoryInfo **allocations = NULL;
|
||||
static size_t allocationsSize = 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
|
||||
MemoryHash(void *p)
|
||||
{
|
||||
|
|
50
src/RtStub.c
50
src/RtStub.c
|
@ -33,12 +33,18 @@
|
|||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define ERR_BUF_SIZE 128
|
||||
|
||||
/* Specified by POSIX to contain environment variables */
|
||||
extern char **environ;
|
||||
|
||||
/* The linking program is expected to provide Main */
|
||||
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
|
||||
{
|
||||
Array *args;
|
||||
|
@ -69,32 +75,46 @@ main(int argc, char **argv)
|
|||
|
||||
MainArgs args;
|
||||
|
||||
MemoryHook(MemoryDefaultHook, NULL);
|
||||
char errBuf[ERR_BUF_SIZE];
|
||||
int errLen;
|
||||
|
||||
args.args = NULL;
|
||||
args.env = NULL;
|
||||
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();
|
||||
|
||||
if (!args.args)
|
||||
{
|
||||
Log(LOG_ERR, "Bootstrap error: Unable to allocate memory for arguments.");
|
||||
args.ret = EXIT_FAILURE;
|
||||
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to allocate heap memory for program arguments.\n");
|
||||
write(STDERR_FILENO, errBuf, errLen);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
args.env = HashMapCreate();
|
||||
if (!args.env)
|
||||
{
|
||||
Log(LOG_ERR, "Bootstrap error: Unable to allocate memory for environment.");
|
||||
args.ret = EXIT_FAILURE;
|
||||
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to allocate heap memory for program environment.\n");
|
||||
write(STDERR_FILENO, errBuf, errLen);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -105,6 +125,14 @@ main(int argc, char **argv)
|
|||
/* It is unclear whether or not envp strings are writable, so
|
||||
* we make our own copy to manipulate it */
|
||||
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, "=");
|
||||
|
||||
key[valInd] = '\0';
|
||||
|
@ -116,15 +144,15 @@ main(int argc, char **argv)
|
|||
|
||||
if (pthread_create(&mainThread, NULL, MainThread, &args) != 0)
|
||||
{
|
||||
Log(LOG_ERR, "Bootstrap error: Unable to create main thread.");
|
||||
args.ret = EXIT_FAILURE;
|
||||
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to create main thread.\n");
|
||||
write(STDERR_FILENO, errBuf, errLen);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (pthread_join(mainThread, NULL) != 0)
|
||||
{
|
||||
/* Should never happen */
|
||||
Log(LOG_ERR, "Unable to join main thread.");
|
||||
errLen = snprintf(errBuf, ERR_BUF_SIZE, "Fatal: Unable to join main thread.\n");
|
||||
write(STDERR_FILENO, errBuf, errLen);
|
||||
args.ret = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
@ -156,7 +184,7 @@ finish:
|
|||
|
||||
GenerateMemoryReport(argc, argv);
|
||||
|
||||
MemoryFreeAll();
|
||||
MemoryRuntimeDestroy();
|
||||
|
||||
return args.ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue