usb_drv: use heap for vmalloc allocations

Do not use slabs for allocations above 64KB, this seems to lead to memory
corruptions and the error described in issue #1613 under certain circumstances.

fixes #1613
This commit is contained in:
Sebastian Sumpf 2015-07-02 14:20:20 +02:00 committed by Christian Helmuth
parent c951c30d8a
commit 49ae508889
4 changed files with 24 additions and 11 deletions

View File

@ -1269,7 +1269,7 @@ void __wait_event(void);
#define _wait_event_timeout(condition, timeout) \ #define _wait_event_timeout(condition, timeout) \
({ \ ({ \
unsigned long _j = jiffies + (timeout / HZ); \ unsigned long _j = jiffies + timeout; \
while(1) { \ while(1) { \
__wait_event(); \ __wait_event(); \
if (condition || _j <= jiffies) \ if (condition || _j <= jiffies) \

View File

@ -135,8 +135,6 @@ class Routine : public Genode::List<Routine>::Element
if (!_list()->first() && !_main) if (!_list()->first() && !_main)
return; return;
Timer::update_jiffies();
if (_current == _main) if (_current == _main)
all = true; all = true;

View File

@ -43,6 +43,8 @@ class Service_handler
*/ */
void process() void process()
{ {
Timer::update_jiffies();
if (Routine::all()) { if (Routine::all()) {
Routine::schedule(); Routine::schedule();
return; return;

View File

@ -193,7 +193,7 @@ class Malloc
enum { enum {
SLAB_START_LOG2 = 3, /* 8 B */ SLAB_START_LOG2 = 3, /* 8 B */
SLAB_STOP_LOG2 = 17, /* 128 KB */ SLAB_STOP_LOG2 = 16, /* 64 KB */
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1, NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
}; };
@ -410,6 +410,9 @@ void *kcalloc(size_t n, size_t size, gfp_t flags)
void kfree(const void *p) void kfree(const void *p)
{ {
if (!p)
return;
if (Malloc::mem()->inside((Genode::addr_t)p)) if (Malloc::mem()->inside((Genode::addr_t)p))
Malloc::mem()->free(p); Malloc::mem()->free(p);
@ -422,17 +425,27 @@ void kfree(const void *p)
** linux/vmalloc.h ** ** linux/vmalloc.h **
*********************/ *********************/
void *vzalloc(unsigned long size) void *vzalloc(unsigned long size)
{ {
if (size > Malloc::max_alloc()) { size_t real_size = size + sizeof(size_t);
PERR("vzalloc: size %lu > %lu", size, Malloc::max_alloc()); size_t *addr;
return 0; try { addr = (size_t *)Genode::env()->heap()->alloc(real_size); }
} catch (...) { return 0; }
return kmalloc(size, 0); *addr = real_size;
memset(addr + 1, 0, size);
return addr + 1;
} }
void vfree(void *addr) { kfree(addr); }
void vfree(void *addr)
{
if (!addr) return;
size_t size = *(((size_t *)addr) - 1);
Genode::env()->heap()->free(const_cast<void *>(addr), size);
}
/****************** /******************