add staticmemory feature

This commit is contained in:
Jacob Barthelmeh
2016-03-23 10:21:26 -06:00
parent d05754f9db
commit 104ff12e76
8 changed files with 1122 additions and 411 deletions

View File

@ -2545,6 +2545,44 @@ AC_SUBST([IPPLINK])
AM_CONDITIONAL([BUILD_FAST_RSA], [test "x$ENABLED_FAST_RSA" = "xyes"])
# static memory use
AC_ARG_ENABLE([staticmemory],
[AS_HELP_STRING([--enable-staticmemory],[Enable static memory use (default: disabled)])],
[ ENABLED_STATICMEMORY=$enableval ],
[ ENABLED_STATICMEMORY=no ]
)
if test "x$ENABLED_STATICMEMORY" = "xyes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY -DWOLFSSL_STATIC_MEMORY_MEDIUM"
fi
if test "x$ENABLED_STATICMEMORY" = "xnone"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY"
fi
if test "x$ENABLED_STATICMEMORY" = "xsmall"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY -DWOLFSSL_STATIC_MEMORY_SMALL"
fi
if test "x$ENABLED_STATICMEMORY" = "xmedium"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY -DWOLFSSL_STATIC_MEMORY_MEDIUM"
fi
if test "x$ENABLED_STATICMEMORY" = "xlarge"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY -DWOLFSSL_STATIC_MEMORY_LARGE"
fi
if test "x$ENABLED_STATICMEMORY" = "xhuge"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_STATIC_MEMORY -DWOLFSSL_STATIC_MEMORY_HUGE"
fi
# microchip api
AC_ARG_ENABLE([mcapi],
[ --enable-mcapi Enable Microchip API (default: disabled)],

View File

@ -1653,10 +1653,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
args.argc = argc;
args.argv = argv;
wolfSSL_Init();
#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL) && !defined(STACK_TRAP)
wolfSSL_Debugging_ON();
#endif
wolfSSL_Init();
ChangeToWolfRoot();
#ifdef HAVE_STACK_SIZE

View File

@ -1048,10 +1048,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
args.signal = &ready;
InitTcpReady(&ready);
CyaSSL_Init();
#if defined(DEBUG_CYASSL) && !defined(WOLFSSL_MDK_SHELL)
CyaSSL_Debugging_ON();
#endif
CyaSSL_Init();
ChangeToWolfRoot();
#ifdef HAVE_STACK_SIZE

View File

@ -38,8 +38,9 @@
#include <wolfssl/wolfcrypt/memory.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef WOLFSSL_MALLOC_CHECK
#if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL)
#include <stdio.h>
#endif
@ -96,7 +97,7 @@ void* wolfSSL_Malloc(size_t size)
if (res == NULL)
puts("wolfSSL_malloc failed");
#endif
return res;
}
@ -140,6 +141,544 @@ void* wolfSSL_Realloc(void *ptr, size_t size)
return res;
}
#ifdef WOLFSSL_STATIC_MEMORY
typedef struct wc_Memory {
word32 sz;
byte* buffer;
byte kill;
struct wc_Memory* next;
} wc_Memory;
#if WC_STATIC_ALIGN < 10
#error Alignment is less than wc_Memory struct
#endif
/* size of chunks of memory to seperate into */
#define WC_MAX_BUCKETS 9
static word32 bucket[] = { 64, 128, 256, 512, 1024, 2400, 3408, 4544, 16000 };
static word32 bucketDist[] = { 8, 4, 4, 12, 4, 5, 2, 1, 1 };
static wc_Memory* available[WC_MAX_BUCKETS];
static word32 inUse = 0; /* amount of static memory in use by wolfSSL */
static byte useStaticMemory = 1;
static volatile byte createMutex = 1;
static wolfSSL_Mutex memory_mutex;
/* returns amount of memory used on success. On error returns negative value
wc_Memory** list is the list that new buckets are prepended to
*/
static int create_memory_buckets(byte* buffer, word32 bufSz,
word32 buckSz, word32 buckNum, wc_Memory** list) {
word32 i;
byte* pt = buffer;
int ret = 0;
/* if not enough space available for bucket size then do not try */
if (buckSz + WC_STATIC_ALIGN > bufSz) {
return ret;
}
if (LockMutex(&memory_mutex) != 0) {
return BAD_MUTEX_E;
}
for (i = 0; i < buckNum; i++) {
if ((buckSz + WC_STATIC_ALIGN) <= (bufSz - ret)) {
/* create a new struct and set its values */
wc_Memory* mem = (struct wc_Memory*)pt;
mem->sz = buckSz;
mem->buffer = (byte*)pt + WC_STATIC_ALIGN;
mem->kill = 0;
mem->next = NULL;
/* add the newly created struct to front of list */
if (*list == NULL) {
*list = mem;
} else {
mem->next = *list;
*list = mem;
}
/* advance pointer and keep track of memory used */
ret += buckSz + WC_STATIC_ALIGN;
pt += WC_STATIC_ALIGN + buckSz;
}
else {
break; /* not enough space left for more buckets of this size */
}
}
UnLockMutex(&memory_mutex);
return ret;
}
/* Starts at left most address and free until either used memory is encounterd
or end of buffer is.
Returns amount of buffer freed on success and a negative value on fail.
*/
int wolfSSL_unload_static_memory(byte* buffer, word32 sz, word32* amt)
{
wc_Memory* cur = NULL;
wc_Memory* fre = NULL;
wc_Memory* prv = NULL;
int i;
word32 idx = 0;
WOLFSSL_ENTER("wolfSSL_unload_static_memory");
if (buffer == NULL || sz == 0 || amt == NULL) {
return BAD_FUNC_ARG;
}
if (LockMutex(&memory_mutex) != 0) {
return BAD_MUTEX_E;
}
/* too small of memory to be placed as a bucket */
if (sz < bucket[0] + WC_STATIC_ALIGN) {
*amt = sz;
return 1;
}
/* advance past alignment padding */
while ((word64)(buffer + idx) % WC_STATIC_ALIGN && idx < sz) { idx++; }
/* buffer should be already divided up into wc_Memory structs */
while (idx < (sz - bucket[0] - WC_STATIC_ALIGN)) {
cur = (struct wc_Memory*)(buffer + idx);
prv = NULL;
for (i = 0; i < WC_MAX_BUCKETS; i++) {
if (bucket[i] >= cur->sz) break;
}
fre = available[i];
/* find the matching address of the memory in available stack */
while (fre != NULL && (cur != fre)) {
prv = fre;
fre = fre->next;
}
if (fre == NULL) {
WOLFSSL_MSG("Could not find static memory address to free");
break;
}
/* fix linked list to jump over the link to free */
if (prv) {
prv->next = fre->next;
}
/* case if memory is head of stack */
if (available[i] == fre) {
available[i] = fre->next;
}
idx += WC_STATIC_ALIGN + fre->sz;
fre = NULL;
}
UnLockMutex(&memory_mutex);
/* account for some left over memory that could not be used for a bucket */
if (idx > (sz - (bucket[0] + WC_STATIC_ALIGN))) {
*amt = sz; /* all posssible was freed */
return 1;
}
else {
*amt = idx;
return 0;
}
}
int wolfSSL_load_static_memory(byte* buffer, word32 sz)
{
word32 ava = sz;
byte* pt = buffer;
int ret = 0;
#ifdef WOLFSSL_TRACK_MEMORY_FULL
word32 created_buckets[WC_MAX_BUCKETS];
int j;
XMEMSET(created_buckets, 0, sizeof(created_buckets));
#endif
WOLFSSL_ENTER("wolfSSL_load_static_memory");
if (buffer == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_TRACK_MEMORY_FULL
printf("\t%u bytes passed in\n", sz);
printf("\tAddress %p - %p\n", buffer, buffer + sz);
#endif
/* align pt */
while ((word64)pt % WC_STATIC_ALIGN && pt < (buffer + sz)) {
*pt = 0x00;
pt++;
}
if (createMutex) {
if (InitMutex(&memory_mutex) != 0) {
WOLFSSL_MSG("Bad mutex init");
return BAD_MUTEX_E;
}
createMutex = 0;
}
/* devide into chunks of memory and add them to available list */
while (ava >= (bucket[0] + WC_STATIC_ALIGN)) {
int i;
/* start at largest and move to smaller buckets */
for (i = (WC_MAX_BUCKETS - 1); i >= 0; i--) {
if ((bucket[i] + WC_STATIC_ALIGN) <= ava) {
if ((ret = create_memory_buckets(pt, ava,
bucket[i], bucketDist[i], &available[i])) < 0) {
WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret);
return ret;
}
#ifdef WOLFSSL_TRACK_MEMORY_FULL
/* if defined keep track of buckets created for printing stats*/
for (j = 0; (j + bucket[i] + WC_STATIC_ALIGN) <=(word32)ret;
j += bucket[i] + WC_STATIC_ALIGN) {
created_buckets[i]++;
}
#endif
/* advance pointer in buffer for next buckets and keep track
of how much memory is left available */
pt += ret;
ava -= ret;
}
}
}
#ifdef WOLFSSL_TRACK_MEMORY_FULL
/* if defined print out stats of number of buckets created */
printf("Created Memory Buckets :\n");
for (j = 0; j < WC_MAX_BUCKETS; j++) {
printf("Created %d\tof bucket size %d\n", created_buckets[j],
bucket[j]);
}
#endif
return 1;
}
int wolfSSL_use_static_memory(byte flag)
{
WOLFSSL_ENTER("wolfSSL_use_static_memory");
useStaticMemory = flag;
return 0;
}
word32 wolfSSL_static_memory_inUse()
{
WOLFSSL_ENTER("wolfSSL_static_memory_inUse");
return inUse;
}
void* wolfSSL_Malloc_Static(size_t size)
{
void* res = 0;
wc_Memory* pt = NULL;
int i;
if (useStaticMemory == 0) {
pt = malloc(size + WC_STATIC_ALIGN);
pt->buffer = (byte*)pt + WC_STATIC_ALIGN;
pt->sz = (word32)size;
pt->kill = 1;
pt->next = NULL;
res = pt->buffer;
}
else {
if (LockMutex(&memory_mutex) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
return NULL;
}
for (i = 0; i < WC_MAX_BUCKETS; i++) {
if ((word32)size < bucket[i]) {
if (available[i] != NULL) {
pt = available[i];
available[i] = pt->next;
res = pt->buffer;
inUse += pt->sz + WC_STATIC_ALIGN;
#ifdef WOLFSSL_TRACK_MEMORY_FULL
printf("used bucket at address %p size of %d for size"
" req %d\n", res, bucket[i], (word32)size);
#endif
break;
}
}
}
UnLockMutex(&memory_mutex);
/* case when no memory size is available */
if (pt == NULL) {
#ifdef WOLFSSL_TRACK_MEMORY_FULL
{
int k, j;
printf("\tRequested size %lu\n\tAvailable memory "
"buckets\n", size);
for (k = 0; k < WC_MAX_BUCKETS; k++) {
pt = available[k];
j = 0;
while (pt) {
j++;
pt = pt->next;
}
printf("\t%d of bucket %d\n", j, bucket[k]);
}
}
#endif
/* check if too large and never going to get memory needed */
if ((word32)size > bucket[WC_MAX_BUCKETS-1]) {
WOLFSSL_MSG("Size of malloc is too large");
return NULL;
}
/* wait then try again if set to */
if (WOLFSSL_STATIC_TIMEOUT > 0) {
WOLFSSL_MSG("Waiting for available memory bucket");
XSLEEP(WOLFSSL_STATIC_TIMEOUT);
if (LockMutex(&memory_mutex) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
return NULL;
}
for (i = 0; i < WC_MAX_BUCKETS; i++) {
if ((word32)size < bucket[i]) {
if (available[i] != NULL) {
pt = available[i];
available[i] = pt->next;
res = pt->buffer;
inUse += pt->sz + WC_STATIC_ALIGN;
#ifdef WOLFSSL_TRACK_MEMORY_FULL
printf("used bucket at address %p size of %d"
" for size req %d\n", res, bucket[i],
(word32)size);
#endif
break;
}
}
}
UnLockMutex(&memory_mutex);
}
if (pt == NULL) {
WOLFSSL_MSG("No available memory bucket");
}
}
}
#ifdef WOLFSSL_MALLOC_CHECK
if (res == NULL)
puts("wolfSSL_malloc failed");
#endif
(void)i;
(void)pt;
return res;
}
void wolfSSL_Free_Static(void *ptr)
{
int i;
wc_Memory* pt;
if (ptr) {
/* get memory struct and add it to available list */
pt = (wc_Memory*)((byte*)ptr - WC_STATIC_ALIGN);
if (pt->kill) {
free(pt);
}
else {
LockMutex(&memory_mutex);
for (i = 0; i < WC_MAX_BUCKETS; i++) {
if (pt->sz == bucket[i]) {
inUse -= WC_STATIC_ALIGN + pt->sz;
pt->next = available[i];
available[i] = pt;
#ifdef WOLFSSL_TRACK_MEMORY_FULL
printf("\tfreed %p bucket size of %d\n"
,pt, bucket[i]);
#endif
break;
}
}
UnLockMutex(&memory_mutex);
}
}
(void)i;
(void)pt;
}
void* wolfSSL_Realloc_Static(void *ptr, size_t size)
{
void* res = 0;
wc_Memory* pt = NULL;
int i;
if (useStaticMemory == 0) {
pt = realloc(ptr, size + WC_STATIC_ALIGN);
pt->buffer = (byte*)pt + WC_STATIC_ALIGN;
pt->sz = (word32)size;
pt->kill = 1;
pt->next = NULL;
res = pt->buffer;
}
else {
if (LockMutex(&memory_mutex) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
return NULL;
}
for (i = 0; i < WC_MAX_BUCKETS; i++) {
if ((word32)size < bucket[i]) {
if (available[i] != NULL) {
word32 prvSz;
pt = available[i];
available[i] = pt->next;
res = pt->buffer;
/* copy over original information and free ptr */
prvSz = ((wc_Memory*)((byte*)ptr -WC_STATIC_ALIGN))->sz;
prvSz = (prvSz > bucket[i])? bucket[i]: prvSz;
XMEMCPY(pt->buffer, ptr, prvSz);
/* free memory that was previously being used */
UnLockMutex(&memory_mutex);
wolfSSL_Free_Static(ptr);
if (LockMutex(&memory_mutex) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
return NULL;
}
inUse += pt->sz + WC_STATIC_ALIGN;
#ifdef WOLFSSL_TRACK_MEMORY_FULL
printf("realloc used a bucket of %d for size req %d\n",
bucket[i], (word32)size);
#endif
break;
}
}
}
UnLockMutex(&memory_mutex);
/* case when no memory size is available */
if (pt == NULL) {
#ifdef WOLFSSL_TRACK_MEMORY_FULL
{
int k, j;
printf("\tRequested size %lu\n\tAvailable memory "
"buckets\n", size);
for (k = 0; k < WC_MAX_BUCKETS; k++) {
pt = available[k];
j = 0;
while (pt) {
j++;
pt = pt->next;
}
printf("\t%d of bucket %d\n", j, bucket[k]);
}
}
#endif
/* check if too large and never going to get memory needed */
if ((word32)size > bucket[WC_MAX_BUCKETS-1]) {
WOLFSSL_MSG("Size of malloc is too large");
return NULL;
}
if (WOLFSSL_STATIC_TIMEOUT > 0) {
WOLFSSL_MSG("Waiting for available memory bucket");
XSLEEP(WOLFSSL_STATIC_TIMEOUT);
if (LockMutex(&memory_mutex) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
return NULL;
}
for (i = 0; i < WC_MAX_BUCKETS; i++) {
if ((word32)size < bucket[i]) {
if (available[i] != NULL) {
word32 prvSz;
pt = available[i];
available[i] = pt->next;
res = pt->buffer;
/* copy over original information and free ptr*/
prvSz = ((wc_Memory*)((byte*)ptr -
WC_STATIC_ALIGN))->sz;
prvSz = (prvSz > bucket[i])? bucket[i]: prvSz;
XMEMCPY(pt->buffer, ptr, prvSz);
/* free memory that was previously being used */
UnLockMutex(&memory_mutex);
wolfSSL_Free_Static(ptr);
if (LockMutex(&memory_mutex) != 0) {
WOLFSSL_MSG("Bad memory_mutex lock");
return NULL;
}
inUse += pt->sz + WC_STATIC_ALIGN;
#ifdef WOLFSSL_TRACK_MEMORY_FULL
printf("realloc used a bucket of %d for size"
" req %d\n", bucket[i], (word32)size);
#endif
break;
}
}
}
UnLockMutex(&memory_mutex);
}
if (pt == NULL) {
WOLFSSL_MSG("No available memory bucket");
}
}
}
(void)i;
(void)pt;
return res;
}
#endif /* WOLFSSL_STATIC_MEMORY */
#endif /* USE_WOLFSSL_MEMORY */

View File

@ -40,6 +40,30 @@
#pragma warning(disable: 4996)
#endif
#ifdef WOLFSSL_STATIC_MEMORY
#if defined(WOLFSSL_STATIC_MEMORY_SMALL)
static byte wc_staticMemory[54833];
/* peak of one connection (10 concurent connections) plus 41 chunks of 64 byte
for structs */
#elif defined(WOLFSSL_STATIC_MEMORY_MEDIUM)
static byte wc_staticMemory[941888];
/* peak of one connection (520 concurent connections) plus 41 chunks of 64 byte
for structs */
#elif defined(WOLFSSL_STATIC_MEMORY_LARGE)
static byte wc_staticMemory[1860992];
/* peak of one connection (1040 concurent connections) plus 41 chunks of 64 byte
for structs */
#elif defined(WOLFSSL_STATIC_MEMORY_HUGE)
static byte wc_staticMemory[3699200];
/* peak of one connection (1040 concurent connections) plus 41 chunks of 64 byte
for structs */
#else
static byte wc_staticMemory[0];
#endif
#endif /* WOLFSSL_STATIC_MEMORY */
/* prevent multiple mutex initializations */
static volatile int initRefCount = 0;
/* Used to initialize state for wolfcrypt
return 0 on success
@ -47,6 +71,8 @@
int wolfCrypt_Init()
{
int ret = 0;
if (initRefCount == 0) {
#if WOLFSSL_CRYPT_HW_MUTEX
/* If crypto hardware mutex protection is enabled, then initialize it */
wolfSSL_CryptHwMutexInit();
@ -65,6 +91,19 @@ int wolfCrypt_Init()
}
#endif
#ifdef WOLFSSL_STATIC_MEMORY
/* set static memory functions and load initial memory */
wolfSSL_SetAllocators(wolfSSL_Malloc_Static, wolfSSL_Free_Static,
wolfSSL_Realloc_Static);
if (wolfSSL_load_static_memory(wc_staticMemory,
sizeof(wc_staticMemory)) != 1) {
WOLFSSL_MSG("Error setting up static memory");
ret = WC_INIT_E;
}
#endif
initRefCount = 1;
}
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,20 @@ WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function,
wolfSSL_Free_cb free_function,
wolfSSL_Realloc_cb realloc_function);
#ifdef WOLFSSL_STATIC_MEMORY
#define WOLFSSL_STATIC_TIMEOUT 1
#define WC_STATIC_ALIGN 64
WOLFSSL_API int wolfSSL_load_static_memory(byte* buffer, word32 sz);
WOLFSSL_API int wolfSSL_unload_static_memory(byte* buffer, word32 sz,
word32* amt);
WOLFSSL_API int wolfSSL_use_static_memory(byte flag);
WOLFSSL_API word32 wolfSSL_static_memory_inUse(void);
WOLFSSL_LOCAL void* wolfSSL_Malloc_Static(size_t size);
WOLFSSL_LOCAL void wolfSSL_Free_Static(void *ptr);
WOLFSSL_LOCAL void* wolfSSL_Realloc_Static(void *ptr, size_t size);
#endif /* WOLFSSL_STATIC_MEMORY */
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -176,12 +176,18 @@
extern void *XMALLOC(size_t n, void* heap, int type);
extern void *XREALLOC(void *p, size_t n, void* heap, int type);
extern void XFREE(void *p, void* heap, int type);
#ifdef WOLFSSL_STATIC_MEMORY /* don't use wolfSSL static memory either*/
#undef WOLFSSL_STATIC_MEMORY
#endif
#elif defined(NO_WOLFSSL_MEMORY)
/* just use plain C stdlib stuff if desired */
#include <stdlib.h>
#define XMALLOC(s, h, t) ((void)h, (void)t, malloc((s)))
#define XFREE(p, h, t) {void* xp = (p); if((xp)) free((xp));}
#define XREALLOC(p, n, h, t) realloc((p), (n))
#ifdef WOLFSSL_STATIC_MEMORY /* don't use wolfSSL static memory either*/
#undef WOLFSSL_STATIC_MEMORY
#endif
#elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \
&& !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \
&& !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \
@ -200,6 +206,13 @@
#endif
#endif
/* sleep function for static memory */
#ifdef WOLFSSL_STATIC_MEMORY
#include <unistd.h>
#define XSLEEP(t) sleep((t))
#endif /* WOLFSSL_STATIC_MEMORY */
#ifndef STRING_USER
#include <string.h>
char* mystrnstr(const char* s1, const char* s2, unsigned int n);