mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Move safe memory helper functions to dedicated memory.c and memory.h
This commit is contained in:
parent
07f7247fce
commit
4da1ab072b
5 changed files with 210 additions and 189 deletions
|
|
@ -44,6 +44,7 @@ snapraid_SOURCES = \
|
|||
cmdline/util.c \
|
||||
cmdline/stream.c \
|
||||
cmdline/support.c \
|
||||
cmdline/memory.c \
|
||||
cmdline/elem.c \
|
||||
cmdline/state.c \
|
||||
cmdline/scan.c \
|
||||
|
|
@ -100,6 +101,7 @@ noinst_HEADERS = \
|
|||
cmdline/util.h \
|
||||
cmdline/stream.h \
|
||||
cmdline/support.h \
|
||||
cmdline/memory.h \
|
||||
cmdline/elem.h \
|
||||
cmdline/state.h \
|
||||
cmdline/parity.h \
|
||||
|
|
@ -130,6 +132,7 @@ mktest_SOURCES = \
|
|||
os/unix.c \
|
||||
cmdline/unixapp.c \
|
||||
cmdline/support.c \
|
||||
cmdline/memory.c \
|
||||
tommyds/tommy.c
|
||||
|
||||
mkstream_SOURCES = \
|
||||
|
|
@ -139,6 +142,7 @@ mkstream_SOURCES = \
|
|||
os/unix.c \
|
||||
cmdline/unixapp.c \
|
||||
cmdline/support.c \
|
||||
cmdline/memory.c \
|
||||
cmdline/util.c \
|
||||
cmdline/stream.c \
|
||||
raid/memory.c \
|
||||
|
|
|
|||
160
cmdline/memory.c
Normal file
160
cmdline/memory.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (C) 2011 Andrea Mazzoleni
|
||||
|
||||
#include "os/portable.h"
|
||||
|
||||
#include "support.h"
|
||||
#include "memory.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* memory */
|
||||
|
||||
/**
|
||||
* Cumulative amount of memory allocated.
|
||||
*/
|
||||
static size_t mcounter;
|
||||
|
||||
size_t malloc_counter_get(void)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
lock_memory();
|
||||
|
||||
ret = mcounter;
|
||||
|
||||
unlock_memory();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void malloc_counter_inc(size_t inc)
|
||||
{
|
||||
lock_memory();
|
||||
|
||||
mcounter += inc;
|
||||
|
||||
unlock_memory();
|
||||
}
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
static ssize_t malloc_print(int f, const char* str)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
|
||||
while (str[len])
|
||||
++len;
|
||||
return write(f, str, len);
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
static ssize_t malloc_printn(int f, size_t value)
|
||||
{
|
||||
char buf[32];
|
||||
int i;
|
||||
|
||||
if (!value)
|
||||
return write(f, "0", 1);
|
||||
|
||||
i = sizeof(buf);
|
||||
while (value) {
|
||||
buf[--i] = (value % 10) + '0';
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
return write(f, buf + i, sizeof(buf) - i);
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
void malloc_fail(size_t size)
|
||||
{
|
||||
/* don't use printf to avoid any possible extra allocation */
|
||||
int f = 2; /* stderr */
|
||||
|
||||
malloc_print(f, "Failed for Low Memory!\n");
|
||||
malloc_print(f, "Allocating ");
|
||||
malloc_printn(f, size);
|
||||
malloc_print(f, " bytes.\n");
|
||||
malloc_print(f, "Already allocated ");
|
||||
malloc_printn(f, malloc_counter_get());
|
||||
malloc_print(f, " bytes.\n");
|
||||
if (sizeof(void*) == 4) {
|
||||
malloc_print(f, "You are currently using a 32 bits executable.\n");
|
||||
malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
|
||||
}
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
void* malloc_nofail(size_t size)
|
||||
{
|
||||
void* ptr = malloc(size ? size : 1);
|
||||
|
||||
if (!ptr) {
|
||||
/* LCOV_EXCL_START */
|
||||
malloc_fail(size);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
#ifndef CHECKER /* Don't preinitialize when running for valgrind */
|
||||
/*
|
||||
* Here we preinitialize the memory to ensure that the OS is really allocating it
|
||||
* and not only reserving the addressable space.
|
||||
* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process.
|
||||
* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to
|
||||
* get a real error from malloc() instead than a process killed.
|
||||
* Note that calloc() doesn't have the same effect.
|
||||
*/
|
||||
memset(ptr, 0xA5, size);
|
||||
#endif
|
||||
|
||||
malloc_counter_inc(size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* nalloc_nofail(size_t count, size_t size)
|
||||
{
|
||||
if (count > SIZE_MAX / size) {
|
||||
log_fatal(EINTERNAL, "Allocation size overflow\n");
|
||||
os_abort();
|
||||
}
|
||||
|
||||
size *= count;
|
||||
|
||||
/* see the note in malloc_nofail() of why we don't use calloc() */
|
||||
void* ptr = malloc(size ? size : 1);
|
||||
|
||||
if (!ptr) {
|
||||
/* LCOV_EXCL_START */
|
||||
malloc_fail(size);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
malloc_counter_inc(size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* calloc_nofail(size_t count, size_t size)
|
||||
{
|
||||
void* ptr = nalloc_nofail(count, size);
|
||||
|
||||
memset(ptr, 0, count * size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char* strdup_nofail(const char* str)
|
||||
{
|
||||
size_t size = strlen(str) + 1;
|
||||
|
||||
char* ptr = malloc_nofail(size);
|
||||
|
||||
memcpy(ptr, str, size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
45
cmdline/memory.h
Normal file
45
cmdline/memory.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (C) 2011 Andrea Mazzoleni
|
||||
|
||||
#ifndef __MEMORY_H
|
||||
#define __MEMORY_H
|
||||
|
||||
/****************************************************************************/
|
||||
/* memory */
|
||||
|
||||
/**
|
||||
* Return the size of the cumulative allocated memory.
|
||||
*/
|
||||
size_t malloc_counter_get(void);
|
||||
|
||||
/**
|
||||
* Safe malloc.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
void* malloc_nofail(size_t size);
|
||||
|
||||
/**
|
||||
* Safe malloc with calloc calling arguments.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
void* nalloc_nofail(size_t count, size_t size);
|
||||
|
||||
/**
|
||||
* Safe calloc.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
void* calloc_nofail(size_t count, size_t size);
|
||||
|
||||
/**
|
||||
* Safe strdup.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
char* strdup_nofail(const char* str);
|
||||
|
||||
/**
|
||||
* Helper for printing an error about a failed allocation.
|
||||
*/
|
||||
void malloc_fail(size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -2103,158 +2103,6 @@ void advise_close(struct advise_struct* advise, int f)
|
|||
advise->dirty_end = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* memory */
|
||||
|
||||
/**
|
||||
* Cumulative amount of memory allocated.
|
||||
*/
|
||||
static size_t mcounter;
|
||||
|
||||
size_t malloc_counter_get(void)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
lock_memory();
|
||||
|
||||
ret = mcounter;
|
||||
|
||||
unlock_memory();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void malloc_counter_inc(size_t inc)
|
||||
{
|
||||
lock_memory();
|
||||
|
||||
mcounter += inc;
|
||||
|
||||
unlock_memory();
|
||||
}
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
static ssize_t malloc_print(int f, const char* str)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
|
||||
while (str[len])
|
||||
++len;
|
||||
return write(f, str, len);
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
static ssize_t malloc_printn(int f, size_t value)
|
||||
{
|
||||
char buf[32];
|
||||
int i;
|
||||
|
||||
if (!value)
|
||||
return write(f, "0", 1);
|
||||
|
||||
i = sizeof(buf);
|
||||
while (value) {
|
||||
buf[--i] = (value % 10) + '0';
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
return write(f, buf + i, sizeof(buf) - i);
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
void malloc_fail(size_t size)
|
||||
{
|
||||
/* don't use printf to avoid any possible extra allocation */
|
||||
int f = 2; /* stderr */
|
||||
|
||||
malloc_print(f, "Failed for Low Memory!\n");
|
||||
malloc_print(f, "Allocating ");
|
||||
malloc_printn(f, size);
|
||||
malloc_print(f, " bytes.\n");
|
||||
malloc_print(f, "Already allocated ");
|
||||
malloc_printn(f, malloc_counter_get());
|
||||
malloc_print(f, " bytes.\n");
|
||||
if (sizeof(void*) == 4) {
|
||||
malloc_print(f, "You are currently using a 32 bits executable.\n");
|
||||
malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
|
||||
}
|
||||
}
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
||||
void* malloc_nofail(size_t size)
|
||||
{
|
||||
void* ptr = malloc(size ? size : 1);
|
||||
|
||||
if (!ptr) {
|
||||
/* LCOV_EXCL_START */
|
||||
malloc_fail(size);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
#ifndef CHECKER /* Don't preinitialize when running for valgrind */
|
||||
/*
|
||||
* Here we preinitialize the memory to ensure that the OS is really allocating it
|
||||
* and not only reserving the addressable space.
|
||||
* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process.
|
||||
* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to
|
||||
* get a real error from malloc() instead than a process killed.
|
||||
* Note that calloc() doesn't have the same effect.
|
||||
*/
|
||||
memset(ptr, 0xA5, size);
|
||||
#endif
|
||||
|
||||
malloc_counter_inc(size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* nalloc_nofail(size_t count, size_t size)
|
||||
{
|
||||
if (count > SIZE_MAX / size) {
|
||||
log_fatal(EINTERNAL, "Allocation size overflow\n");
|
||||
os_abort();
|
||||
}
|
||||
|
||||
size *= count;
|
||||
|
||||
/* see the note in malloc_nofail() of why we don't use calloc() */
|
||||
void* ptr = malloc(size ? size : 1);
|
||||
|
||||
if (!ptr) {
|
||||
/* LCOV_EXCL_START */
|
||||
malloc_fail(size);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
malloc_counter_inc(size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* calloc_nofail(size_t count, size_t size)
|
||||
{
|
||||
void* ptr = nalloc_nofail(count, size);
|
||||
|
||||
memset(ptr, 0, count * size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char* strdup_nofail(const char* str)
|
||||
{
|
||||
size_t size = strlen(str) + 1;
|
||||
|
||||
char* ptr = malloc_nofail(size);
|
||||
|
||||
memcpy(ptr, str, size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* smartctl */
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#define __SUPPORT_H
|
||||
|
||||
#include "app.h"
|
||||
#include "memory.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* lock */
|
||||
|
|
@ -519,43 +520,6 @@ int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_of
|
|||
int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size);
|
||||
void advise_close(struct advise_struct* advise, int f);
|
||||
|
||||
/****************************************************************************/
|
||||
/* memory */
|
||||
|
||||
/**
|
||||
* Return the size of the cumulative allocated memory.
|
||||
*/
|
||||
size_t malloc_counter_get(void);
|
||||
|
||||
/**
|
||||
* Safe malloc.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
void* malloc_nofail(size_t size);
|
||||
|
||||
/**
|
||||
* Safe malloc with calloc calling arguments.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
void* nalloc_nofail(size_t count, size_t size);
|
||||
|
||||
/**
|
||||
* Safe calloc.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
void* calloc_nofail(size_t count, size_t size);
|
||||
|
||||
/**
|
||||
* Safe strdup.
|
||||
* If no memory is available, it aborts.
|
||||
*/
|
||||
char* strdup_nofail(const char* str);
|
||||
|
||||
/**
|
||||
* Helper for printing an error about a failed allocation.
|
||||
*/
|
||||
void malloc_fail(size_t size);
|
||||
|
||||
/****************************************************************************/
|
||||
/* smartctl */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue