mirror of https://github.com/schoebel/mars
infra: better optimization of memory allocations
This commit is contained in:
parent
1202f2ae8e
commit
20166b6c01
|
@ -6,6 +6,8 @@ ifneq ($(KBUILD_EXTMOD),)
|
||||||
CONFIG_MARS_BIGMODULE := m
|
CONFIG_MARS_BIGMODULE := m
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
KBUILD_CFLAGS += -fdelete-null-pointer-checks
|
||||||
|
|
||||||
mars-objs := \
|
mars-objs := \
|
||||||
brick_say.o \
|
brick_say.o \
|
||||||
brick_mem.o \
|
brick_mem.o \
|
||||||
|
|
|
@ -155,7 +155,6 @@ EXPORT_SYMBOL_GPL(_brick_mem_alloc);
|
||||||
|
|
||||||
void _brick_mem_free(void *data, int cline)
|
void _brick_mem_free(void *data, int cline)
|
||||||
{
|
{
|
||||||
if (data) {
|
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
void *test = data - 4 * sizeof(int);
|
void *test = data - 4 * sizeof(int);
|
||||||
int magic1= INT_ACCESS(test, 0 * sizeof(int));
|
int magic1= INT_ACCESS(test, 0 * sizeof(int));
|
||||||
|
@ -195,7 +194,6 @@ void _brick_mem_free(void *data, int cline)
|
||||||
data = test;
|
data = test;
|
||||||
__brick_mem_free(data, len + PLUS_SIZE);
|
__brick_mem_free(data, len + PLUS_SIZE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(_brick_mem_free);
|
EXPORT_SYMBOL_GPL(_brick_mem_free);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -260,7 +258,6 @@ EXPORT_SYMBOL_GPL(_brick_string_alloc);
|
||||||
|
|
||||||
void _brick_string_free(const char *data, int cline)
|
void _brick_string_free(const char *data, int cline)
|
||||||
{
|
{
|
||||||
if (data) {
|
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
int magic;
|
int magic;
|
||||||
int len;
|
int len;
|
||||||
|
@ -290,7 +287,6 @@ void _brick_string_free(const char *data, int cline)
|
||||||
#endif
|
#endif
|
||||||
kfree(data);
|
kfree(data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(_brick_string_free);
|
EXPORT_SYMBOL_GPL(_brick_string_free);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -581,9 +577,6 @@ void _brick_block_free(void *data, int len, int cline)
|
||||||
const int plus = 0;
|
const int plus = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
order = len2order(len + plus);
|
order = len2order(len + plus);
|
||||||
#ifdef BRICK_DEBUG_MEM
|
#ifdef BRICK_DEBUG_MEM
|
||||||
if (order > 1) {
|
if (order > 1) {
|
||||||
|
|
|
@ -22,12 +22,90 @@ extern atomic64_t brick_global_block_used;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// compiler tweaking
|
||||||
|
|
||||||
|
/* Some functions are known to return non-null pointer values,
|
||||||
|
* at least under some Kconfig conditions.
|
||||||
|
*
|
||||||
|
* In code like...
|
||||||
|
*
|
||||||
|
* void *ptr = myfunction();
|
||||||
|
* if (unlikely(!ptr)) {
|
||||||
|
* printk("ERROR: this should not happen\n");
|
||||||
|
* goto fail;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ... the dead code elimination of gcc will not remove the if clause
|
||||||
|
* because the function might return a NULL value, even if a human
|
||||||
|
* would know that myfunction() does not return a NULL value.
|
||||||
|
*
|
||||||
|
* Unfortunately, the __attribute__((nonnull)) can only be applied
|
||||||
|
* to input parameters, but not to the return value.
|
||||||
|
*
|
||||||
|
* More unfortunately, a small inline wrapper does not help,
|
||||||
|
* because it seems that together with the elimination of the wrapper,
|
||||||
|
* its nonnull attribute seems to be eliminated alltogether.
|
||||||
|
* I don't know whether this is a bug or a feature (or just a weakness).
|
||||||
|
*
|
||||||
|
* Following is a small hack which solves the problem at least for gcc 4.7.
|
||||||
|
*
|
||||||
|
* In order to be useful, the -fdelete-null-pointer-checks must be set.
|
||||||
|
* Since MARS is superuser-only anyway, enabling this for MARS should not
|
||||||
|
* be a security risk
|
||||||
|
* (c.f. upstream kernel commit a3ca86aea507904148870946d599e07a340b39bf)
|
||||||
|
*/
|
||||||
|
extern inline
|
||||||
|
void *__mark_ptr_nonnull(void *_ptr)
|
||||||
|
{
|
||||||
|
char *ptr = _ptr;
|
||||||
|
// fool gcc to believe that the pointer were dereferenced...
|
||||||
|
asm("" : : "X" (*ptr));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All the brick memory allocations are guaranteed to succeed when
|
||||||
|
* CONFIG_MARS_MEM_RETRY is set. In case of low memory, they will just
|
||||||
|
* retry (forever).
|
||||||
|
*
|
||||||
|
* Allow checking code to be written which works for both cases:
|
||||||
|
* CONFIG_MARS_MEM_RETRY is selected, or not.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_MARS_MEM_RETRY
|
||||||
|
#define brick_mark_nonnull __mark_ptr_nonnull
|
||||||
|
#else
|
||||||
|
#define brick_mark_nonnull(p) (p)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// small memory allocation (use this only for len < PAGE_SIZE)
|
// small memory allocation (use this only for len < PAGE_SIZE)
|
||||||
|
|
||||||
#define brick_mem_alloc(_len_) _brick_mem_alloc(_len_, __LINE__)
|
#define brick_mem_alloc(_len_) \
|
||||||
#define brick_zmem_alloc(_len_) ({ void *_res_ = _brick_mem_alloc(_len_, __LINE__); if (_res_) { memset(_res_, 0, _len_); } _res_; })
|
({ \
|
||||||
extern void *_brick_mem_alloc(int len, int line);
|
void *_res_ = _brick_mem_alloc(_len_, __LINE__); \
|
||||||
#define brick_mem_free(_data_) _brick_mem_free(_data_, __LINE__)
|
brick_mark_nonnull(_res_); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define brick_zmem_alloc(_len_) \
|
||||||
|
({ \
|
||||||
|
void *_res_ = _brick_mem_alloc(_len_, __LINE__); \
|
||||||
|
_res_ = brick_mark_nonnull(_res_); \
|
||||||
|
if (_res_) { \
|
||||||
|
memset(_res_, 0, _len_); \
|
||||||
|
} \
|
||||||
|
_res_; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define brick_mem_free(_data_) \
|
||||||
|
do { \
|
||||||
|
if (_data_) { \
|
||||||
|
_brick_mem_free(_data_, __LINE__); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
// don't use the following directly
|
||||||
|
extern void *_brick_mem_alloc(int len, int line) __attribute__((malloc)) __attribute__((alloc_size(1)));
|
||||||
extern void _brick_mem_free(void *data, int line);
|
extern void _brick_mem_free(void *data, int line);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -36,25 +114,68 @@ extern void _brick_mem_free(void *data, int line);
|
||||||
|
|
||||||
#define BRICK_STRING_LEN 1024 /* default value when len == 0 */
|
#define BRICK_STRING_LEN 1024 /* default value when len == 0 */
|
||||||
|
|
||||||
#define brick_string_alloc(_len_) _brick_string_alloc(_len_, __LINE__)
|
#define brick_string_alloc(_len_) \
|
||||||
#define brick_strndup(_orig_,_len_) ({ char *_res_ = _brick_string_alloc((_len_) + 1, __LINE__); if (_res_) { strncpy(_res_, _orig_, (_len_)); _res_[_len_] = '\0';} _res_; })
|
({ \
|
||||||
#define brick_strdup(_orig_) ({ int _len_ = strlen(_orig_); char *_res_ = _brick_string_alloc(_len_ + 1, __LINE__); if (_res_) { strncpy(_res_, _orig_, _len_ + 1); } _res_; })
|
char *_res_ = _brick_string_alloc((_len_), __LINE__); \
|
||||||
extern char *_brick_string_alloc(int len, int line);
|
(char*)brick_mark_nonnull(_res_); \
|
||||||
#define brick_string_free(_data_) _brick_string_free(_data_, __LINE__)
|
})
|
||||||
extern void _brick_string_free(const char *data, int line);
|
|
||||||
|
|
||||||
extern void brick_mem_statistics(void);
|
#define brick_strndup(_orig_,_len_) \
|
||||||
|
({ \
|
||||||
|
char *_res_ = _brick_string_alloc((_len_) + 1, __LINE__); \
|
||||||
|
_res_ = brick_mark_nonnull(_res_); \
|
||||||
|
if (_res_) { \
|
||||||
|
strncpy(_res_, (_orig_), (_len_) + 1); \
|
||||||
|
/* always null-terminate for safety */ \
|
||||||
|
_res_[_len_] = '\0'; \
|
||||||
|
} \
|
||||||
|
(char*)brick_mark_nonnull(_res_); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define brick_strdup(_orig_) \
|
||||||
|
({ \
|
||||||
|
int _len_ = strlen(_orig_); \
|
||||||
|
char *_res_ = _brick_string_alloc((_len_) + 1, __LINE__); \
|
||||||
|
_res_ = brick_mark_nonnull(_res_); \
|
||||||
|
if (_res_) { \
|
||||||
|
strncpy(_res_, (_orig_), (_len_) + 1); \
|
||||||
|
} \
|
||||||
|
(char*)brick_mark_nonnull(_res_); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define brick_string_free(_data_) \
|
||||||
|
do { \
|
||||||
|
if (_data_) { \
|
||||||
|
_brick_string_free(_data_, __LINE__); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
// don't use the following directly
|
||||||
|
extern char *_brick_string_alloc(int len, int line) __attribute__((malloc));
|
||||||
|
extern void _brick_string_free(const char *data, int line);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// block memory allocation (for aligned multiples of 512 resp PAGE_SIZE)
|
// block memory allocation (for aligned multiples of 512 resp PAGE_SIZE)
|
||||||
|
|
||||||
#define brick_block_alloc(_pos_,_len_) _brick_block_alloc(_pos_, _len_, __LINE__)
|
#define brick_block_alloc(_pos_,_len_) \
|
||||||
extern void *_brick_block_alloc(loff_t pos, int len, int line);
|
({ \
|
||||||
extern void _brick_block_free(void *data, int len, int cline);
|
void *_res_ = _brick_block_alloc((_pos_), (_len_), __LINE__); \
|
||||||
#define brick_block_free(_data_,_len_) _brick_block_free(_data_, _len_, __LINE__)
|
brick_mark_nonnull(_res_); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define brick_block_free(_data_,_len_)\
|
||||||
|
do { \
|
||||||
|
if (_data_) { \
|
||||||
|
_brick_block_free((_data_), (_len_), __LINE__); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
extern struct page *brick_iomap(void *data, int *offset, int *len);
|
extern struct page *brick_iomap(void *data, int *offset, int *len);
|
||||||
|
|
||||||
|
// don't use the following directly
|
||||||
|
extern void *_brick_block_alloc(loff_t pos, int len, int line) __attribute__((malloc)) __attribute__((alloc_size(2)));
|
||||||
|
extern void _brick_block_free(void *data, int len, int cline);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -70,6 +191,8 @@ struct mem_reservation {
|
||||||
|
|
||||||
extern int brick_mem_reserve(struct mem_reservation *r);
|
extern int brick_mem_reserve(struct mem_reservation *r);
|
||||||
|
|
||||||
|
extern void brick_mem_statistics(void);
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// init
|
// init
|
||||||
|
|
Loading…
Reference in New Issue