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) \
({ \
unsigned long _j = jiffies + (timeout / HZ); \
unsigned long _j = jiffies + timeout; \
while(1) { \
__wait_event(); \
if (condition || _j <= jiffies) \

View File

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

View File

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

View File

@ -193,7 +193,7 @@ class Malloc
enum {
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,
};
@ -410,6 +410,9 @@ void *kcalloc(size_t n, size_t size, gfp_t flags)
void kfree(const void *p)
{
if (!p)
return;
if (Malloc::mem()->inside((Genode::addr_t)p))
Malloc::mem()->free(p);
@ -422,17 +425,27 @@ void kfree(const void *p)
** linux/vmalloc.h **
*********************/
void *vzalloc(unsigned long size)
void *vzalloc(unsigned long size)
{
if (size > Malloc::max_alloc()) {
PERR("vzalloc: size %lu > %lu", size, Malloc::max_alloc());
return 0;
}
size_t real_size = size + sizeof(size_t);
size_t *addr;
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);
}
/******************