base: provide Thread_base::stack_size(size_t)

The new method enhances the stack of the targeted thread if it is smaller
than a given size.

ref #1075
This commit is contained in:
Martin Stein 2014-02-26 16:47:54 +01:00 committed by Norman Feske
parent c3b161e814
commit 3f9b098b70
3 changed files with 88 additions and 0 deletions

View File

@ -31,6 +31,40 @@ namespace Genode {
}
void Thread_base::Context::stack_size(size_t const size)
{
/* check if the stack needs to be enhanced */
size_t const stack_size = (addr_t)_stack - stack_base;
if (stack_size >= size) { return; }
/* check if the stack enhancement fits the context region */
enum {
CONTEXT_SIZE = Native_config::context_virtual_size(),
CONTEXT_AREA_BASE = Native_config::context_area_virtual_base(),
UTCB_SIZE = sizeof(Native_utcb),
PAGE_SIZE_LOG2 = 12,
PAGE_SIZE = (1UL << PAGE_SIZE_LOG2),
};
addr_t const context_base = Context_allocator::addr_to_base(this);
size_t const ds_size = align_addr(size - stack_size, PAGE_SIZE_LOG2);
if (stack_base - ds_size < context_base) { throw Stack_too_large(); }
/* allocate and attach backing store for the stack enhancement */
addr_t const ds_addr = stack_base - ds_size - CONTEXT_AREA_BASE;
try {
Ram_session * const ram = env_context_area_ram_session();
Ram_dataspace_capability const ds_cap = ram->alloc(ds_size);
Rm_session * const rm = env_context_area_rm_session();
void * const attach_addr = rm->attach_at(ds_cap, ds_addr, ds_size);
if (ds_addr != (addr_t)attach_addr) { throw Stack_alloc_failed(); }
}
catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); }
/* update context information */
stack_base -= ds_size;
}
Thread_base::Context *
Thread_base::_alloc_context(size_t stack_size, bool main_thread)
{

View File

@ -112,6 +112,16 @@ namespace Genode {
return ((addr_t)_stack & ~0xf) - Abi::stack_adjustment();
}
/**
* Ensure that the stack has a given size at the minimum
*
* \param size minimum stack size
*
* \throw Stack_too_large
* \throw Stack_alloc_failed
*/
void stack_size(size_t const size);
/**
* Virtual address of the start of the stack
*
@ -421,6 +431,16 @@ namespace Genode {
*/
static Thread_base *myself();
/**
* Ensure that the stack has a given size at the minimum
*
* \param size minimum stack size
*
* \throw Context::Stack_too_large
* \throw Context::Stack_alloc_failed
*/
void stack_size(size_t const size) { _context->stack_size(size); }
/**
* Return user-level thread control block
*

View File

@ -31,6 +31,40 @@ namespace Genode {
}
void Thread_base::Context::stack_size(size_t const size)
{
/* check if the stack needs to be enhanced */
size_t const stack_size = (addr_t)_stack - stack_base;
if (stack_size >= size) { return; }
/* check if the stack enhancement fits the context region */
enum {
CONTEXT_SIZE = Native_config::context_virtual_size(),
CONTEXT_AREA_BASE = Native_config::context_area_virtual_base(),
UTCB_SIZE = sizeof(Native_utcb),
PAGE_SIZE_LOG2 = 12,
PAGE_SIZE = (1UL << PAGE_SIZE_LOG2),
};
addr_t const context_base = Context_allocator::addr_to_base(this);
size_t const ds_size = align_addr(size - stack_size, PAGE_SIZE_LOG2);
if (stack_base - ds_size < context_base) { throw Stack_too_large(); }
/* allocate and attach backing store for the stack enhancement */
addr_t const ds_addr = stack_base - ds_size - CONTEXT_AREA_BASE;
try {
Ram_session * const ram = env_context_area_ram_session();
Ram_dataspace_capability const ds_cap = ram->alloc(ds_size);
Rm_session * const rm = env_context_area_rm_session();
void * const attach_addr = rm->attach_at(ds_cap, ds_addr, ds_size);
if (ds_addr != (addr_t)attach_addr) { throw Stack_alloc_failed(); }
}
catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); }
/* update context information */
stack_base -= ds_size;
}
Thread_base::Context *
Thread_base::_alloc_context(size_t stack_size, bool main_thread)
{