Add support for pthread_attr_get/setguardsize()
* Added the aforementioned functions. * create_area_etc() now takes a guard size parameter. * The thread_info::stack_base/end range now refers to the usable range only.
This commit is contained in:
@@ -185,6 +185,10 @@ extern int pthread_attr_getschedparam(const pthread_attr_t *attr,
|
||||
extern int pthread_attr_setschedparam(pthread_attr_t *attr,
|
||||
const struct sched_param *param);
|
||||
|
||||
extern int pthread_attr_getguardsize(const pthread_attr_t *attr,
|
||||
size_t *guardsize);
|
||||
extern int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
|
||||
|
||||
#if 0 /* Unimplemented attribute functions: */
|
||||
|
||||
/* [TPS] */
|
||||
@@ -196,11 +200,6 @@ extern int pthread_attr_getschedpolicy(const pthread_attr_t *attr,
|
||||
int *policy);
|
||||
extern int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
|
||||
|
||||
/* [XSI] */
|
||||
extern int pthread_attr_getguardsize(const pthread_attr_t *attr,
|
||||
size_t *guardsize);
|
||||
extern int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
|
||||
|
||||
/* [TSA] */
|
||||
extern int pthread_attr_getstackaddr(const pthread_attr_t *attr,
|
||||
void **stackaddr);
|
||||
|
||||
@@ -117,6 +117,8 @@ public:
|
||||
inline void IncrementWiredPagesCount();
|
||||
inline void DecrementWiredPagesCount();
|
||||
|
||||
virtual int32 GuardSize() { return 0; }
|
||||
|
||||
void AddConsumer(VMCache* consumer);
|
||||
|
||||
status_t InsertAreaLocked(VMArea* area);
|
||||
|
||||
@@ -77,7 +77,7 @@ void forbid_page_faults(void);
|
||||
|
||||
// private kernel only extension (should be moved somewhere else):
|
||||
area_id create_area_etc(team_id team, const char *name, uint32 size,
|
||||
uint32 lock, uint32 protection, uint32 flags,
|
||||
uint32 lock, uint32 protection, uint32 flags, uint32 guardSize,
|
||||
const virtual_address_restrictions* virtualAddressRestrictions,
|
||||
const physical_address_restrictions* physicalAddressRestrictions,
|
||||
void **_address);
|
||||
@@ -95,7 +95,7 @@ status_t vm_unreserve_address_range(team_id team, void *address, addr_t size);
|
||||
status_t vm_reserve_address_range(team_id team, void **_address,
|
||||
uint32 addressSpec, addr_t size, uint32 flags);
|
||||
area_id vm_create_anonymous_area(team_id team, const char* name, addr_t size,
|
||||
uint32 wiring, uint32 protection, uint32 flags,
|
||||
uint32 wiring, uint32 protection, uint32 flags, addr_t guardSize,
|
||||
const virtual_address_restrictions* virtualAddressRestrictions,
|
||||
const physical_address_restrictions* physicalAddressRestrictions,
|
||||
bool kernel, void** _address);
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef struct _pthread_attr {
|
||||
int32 detach_state;
|
||||
int32 sched_priority;
|
||||
size_t stack_size;
|
||||
size_t guard_size;
|
||||
} pthread_attr;
|
||||
|
||||
typedef struct _pthread_rwlockattr {
|
||||
|
||||
@@ -12,14 +12,11 @@
|
||||
|
||||
|
||||
/** Size of the stack given to teams in user space */
|
||||
#define USER_STACK_GUARD_PAGES 4 // 16 kB
|
||||
#define USER_MAIN_THREAD_STACK_SIZE (16 * 1024 * 1024 \
|
||||
- USER_STACK_GUARD_PAGES * B_PAGE_SIZE) // 16 MB
|
||||
#define USER_STACK_SIZE (256 * 1024 \
|
||||
- USER_STACK_GUARD_PAGES * B_PAGE_SIZE) // 256 kB
|
||||
#define MIN_USER_STACK_SIZE (4 * 1024) // 4 KB
|
||||
#define MAX_USER_STACK_SIZE (16 * 1024 * 1024 \
|
||||
- USER_STACK_GUARD_PAGES * B_PAGE_SIZE) // 16 MB
|
||||
#define USER_STACK_GUARD_SIZE (4 * B_PAGE_SIZE) // 16 kB
|
||||
#define USER_MAIN_THREAD_STACK_SIZE (16 * 1024 * 1024) // 16 MB
|
||||
#define USER_STACK_SIZE (256 * 1024) // 256 kB
|
||||
#define MIN_USER_STACK_SIZE (4 * 1024) // 4 KB
|
||||
#define MAX_USER_STACK_SIZE (16 * 1024 * 1024) // 16 MB
|
||||
|
||||
|
||||
// The type of object a thread blocks on (thread::wait::type, set by
|
||||
@@ -50,6 +47,7 @@ struct thread_creation_attributes {
|
||||
void* args2;
|
||||
void* stack_address;
|
||||
size_t stack_size;
|
||||
size_t guard_size;
|
||||
pthread_t pthread;
|
||||
uint32 flags;
|
||||
};
|
||||
|
||||
@@ -195,7 +195,7 @@ scsi_alloc_dma_buffer(dma_buffer *buffer, dma_params *dma_params, uint32 size)
|
||||
// TODO: Use 64 bit addresses, if possible!
|
||||
#endif
|
||||
buffer->area = create_area_etc(B_SYSTEM_TEAM, "DMA buffer", size,
|
||||
B_CONTIGUOUS, 0, 0, &virtualRestrictions, &physicalRestrictions,
|
||||
B_CONTIGUOUS, 0, 0, 0, &virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&buffer->address);
|
||||
|
||||
if (buffer->area < 0) {
|
||||
|
||||
@@ -74,7 +74,7 @@ scsi_init_emulation_buffer(scsi_device_info *device, size_t buffer_size)
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
physicalRestrictions.alignment = buffer_size;
|
||||
device->buffer_area = create_area_etc(B_SYSTEM_TEAM, "ATAPI buffer",
|
||||
total_size, B_32_BIT_CONTIGUOUS, 0, 0, &virtualRestrictions,
|
||||
total_size, B_32_BIT_CONTIGUOUS, 0, 0, 0, &virtualRestrictions,
|
||||
&physicalRestrictions, &address);
|
||||
// TODO: Use B_CONTIGUOUS, if possible!
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ _kernel_contigmalloc_cpp(const char* file, int line, size_t size,
|
||||
|
||||
void* address;
|
||||
area_id area = create_area_etc(B_SYSTEM_TEAM, name, size, B_CONTIGUOUS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, creationFlags,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, creationFlags, 0,
|
||||
&virtualRestrictions, &physicalRestrictions, &address);
|
||||
if (area < 0)
|
||||
return NULL;
|
||||
|
||||
@@ -73,3 +73,17 @@ WRAPPER_FUNCTION(int, pthread_attr_getschedparam,
|
||||
return B_TO_POSITIVE_ERROR(sReal_pthread_attr_getschedparam(attr,
|
||||
param));
|
||||
)
|
||||
|
||||
|
||||
WRAPPER_FUNCTION(int, pthread_attr_getguardsize,
|
||||
(const pthread_attr_t *attr, size_t *guardsize),
|
||||
return B_TO_POSITIVE_ERROR(sReal_pthread_attr_getguardsize(attr,
|
||||
guardsize));
|
||||
)
|
||||
|
||||
|
||||
WRAPPER_FUNCTION(int, pthread_attr_setguardsize,
|
||||
(pthread_attr_t *attr, size_t guardsize),
|
||||
return B_TO_POSITIVE_ERROR(sReal_pthread_attr_setguardsize(attr,
|
||||
guardsize));
|
||||
)
|
||||
|
||||
@@ -197,7 +197,7 @@ ARMPagingMethod32Bit::PhysicalPageSlotPool::AllocatePool(
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area_id dataArea = create_area_etc(B_SYSTEM_TEAM, "physical page pool",
|
||||
PAGE_ALIGN(areaSize), B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 0,
|
||||
&virtualRestrictions, &physicalRestrictions, &data);
|
||||
if (dataArea < 0)
|
||||
return dataArea;
|
||||
|
||||
@@ -552,7 +552,7 @@ x86_descriptors_init_post_vm(kernel_args* args)
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area = create_area_etc(B_SYSTEM_TEAM, "idt", areaSize, B_CONTIGUOUS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
|
||||
&virtualRestrictions, &physicalRestrictions, (void**)&idt);
|
||||
0, &virtualRestrictions, &physicalRestrictions, (void**)&idt);
|
||||
if (area < 0)
|
||||
return area;
|
||||
|
||||
|
||||
@@ -792,7 +792,7 @@ arch_cpu_init_post_vm(kernel_args* args)
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
create_area_etc(B_SYSTEM_TEAM, "double fault stacks",
|
||||
kDoubleFaultStackSize * smp_get_num_cpus(), B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 0,
|
||||
&virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&sDoubleFaultStacks);
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ X86PagingMethod32Bit::PhysicalPageSlotPool::AllocatePool(
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area_id dataArea = create_area_etc(B_SYSTEM_TEAM, "physical page pool",
|
||||
PAGE_ALIGN(areaSize), B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 0,
|
||||
&virtualRestrictions, &physicalRestrictions, &data);
|
||||
if (dataArea < 0)
|
||||
return dataArea;
|
||||
|
||||
@@ -487,7 +487,7 @@ X86PagingMethodPAE::PhysicalPageSlotPool::AllocatePool(
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area_id dataArea = create_area_etc(B_SYSTEM_TEAM, "physical page pool",
|
||||
PAGE_ALIGN(areaSize), B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 0,
|
||||
&virtualRestrictions, &physicalRestrictions, &data);
|
||||
if (dataArea < 0)
|
||||
return dataArea;
|
||||
|
||||
@@ -309,7 +309,7 @@ debug_heap_init()
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area_id area = create_area_etc(B_SYSTEM_TEAM, "kdebug heap", KDEBUG_HEAP,
|
||||
B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||
CREATE_AREA_DONT_WAIT, &virtualRestrictions, &physicalRestrictions,
|
||||
CREATE_AREA_DONT_WAIT, 0, &virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&base);
|
||||
if (area < 0)
|
||||
return;
|
||||
|
||||
@@ -452,7 +452,7 @@ TracingMetaData::Create(TracingMetaData*& _metaData)
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area = create_area_etc(B_SYSTEM_TEAM, "tracing log",
|
||||
kTraceOutputBufferSize + MAX_TRACE_SIZE, B_CONTIGUOUS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 0,
|
||||
&virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&metaData->fTraceOutputBuffer);
|
||||
if (area < 0)
|
||||
@@ -503,8 +503,8 @@ TracingMetaData::_CreateMetaDataArea(bool findPrevious, area_id& _area,
|
||||
physicalRestrictions.high_address = metaDataAddress + B_PAGE_SIZE;
|
||||
area_id area = create_area_etc(B_SYSTEM_TEAM, "tracing metadata",
|
||||
B_PAGE_SIZE, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||
CREATE_AREA_DONT_CLEAR, &virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&metaData);
|
||||
CREATE_AREA_DONT_CLEAR, 0, &virtualRestrictions,
|
||||
&physicalRestrictions, (void**)&metaData);
|
||||
if (area < 0)
|
||||
continue;
|
||||
|
||||
@@ -567,7 +567,7 @@ TracingMetaData::_InitPreviousTracingData()
|
||||
+ ROUNDUP(kTraceOutputBufferSize + MAX_TRACE_SIZE, B_PAGE_SIZE);
|
||||
area_id area = create_area_etc(B_SYSTEM_TEAM, "tracing log",
|
||||
kTraceOutputBufferSize + MAX_TRACE_SIZE, B_CONTIGUOUS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_CLEAR,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_CLEAR, 0,
|
||||
&virtualRestrictions, &physicalRestrictions, NULL);
|
||||
if (area < 0) {
|
||||
dprintf("Failed to init tracing meta data: Mapping tracing log "
|
||||
|
||||
@@ -246,7 +246,7 @@ DMAResource::CreateBounceBuffer(DMABounceBuffer** _buffer)
|
||||
physicalRestrictions.alignment = fRestrictions.alignment;
|
||||
physicalRestrictions.boundary = fRestrictions.boundary;
|
||||
area = create_area_etc(B_SYSTEM_TEAM, "dma buffer", size, B_CONTIGUOUS,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0, &virtualRestrictions,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0, 0, &virtualRestrictions,
|
||||
&physicalRestrictions, &bounceBuffer);
|
||||
if (area < B_OK)
|
||||
return area;
|
||||
|
||||
@@ -1943,7 +1943,7 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
|
||||
virtualRestrictions.address_specification = B_EXACT_ADDRESS;
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK,
|
||||
B_READ_AREA | B_WRITE_AREA, 0, &virtualRestrictions,
|
||||
B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions,
|
||||
&physicalRestrictions, (void**)®ionAddress);
|
||||
if (id < B_OK) {
|
||||
dprintf("error allocating bss area: %s!\n", strerror(id));
|
||||
|
||||
@@ -432,7 +432,7 @@ haiku_sem_init(kernel_args *args)
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area = create_area_etc(B_SYSTEM_TEAM, "sem_table",
|
||||
sizeof(struct sem_entry) * sMaxSems, B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 0,
|
||||
&virtualRestrictions, &physicalRestrictions, (void**)&sSems);
|
||||
if (area < 0)
|
||||
panic("unable to allocate semaphore table!\n");
|
||||
|
||||
@@ -627,7 +627,7 @@ MemoryManager::AllocateRaw(size_t size, uint32 flags, void*& _pages)
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||
((flags & CACHE_DONT_WAIT_FOR_MEMORY) != 0
|
||||
? CREATE_AREA_DONT_WAIT : 0)
|
||||
| CREATE_AREA_DONT_CLEAR,
|
||||
| CREATE_AREA_DONT_CLEAR, 0,
|
||||
&virtualRestrictions, &physicalRestrictions, &_pages);
|
||||
|
||||
status_t result = area >= 0 ? B_OK : area;
|
||||
|
||||
@@ -1333,7 +1333,7 @@ create_team_user_data(Team* team)
|
||||
virtualRestrictions.address_specification = B_BASE_ADDRESS;
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
team->user_data_area = create_area_etc(team->id, "user area", size,
|
||||
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA, 0, &virtualRestrictions,
|
||||
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions,
|
||||
&physicalRestrictions, &address);
|
||||
if (team->user_data_area < 0)
|
||||
return team->user_data_area;
|
||||
|
||||
@@ -524,6 +524,7 @@ ThreadCreationAttributes::ThreadCreationAttributes(thread_func function,
|
||||
this->args2 = NULL;
|
||||
this->stack_address = NULL;
|
||||
this->stack_size = 0;
|
||||
this->guard_size = 0;
|
||||
this->pthread = NULL;
|
||||
this->flags = 0;
|
||||
this->team = team >= 0 ? team : team_get_kernel_team()->id;
|
||||
@@ -781,14 +782,15 @@ init_thread_kernel_stack(Thread* thread, const void* data, size_t dataSize)
|
||||
|
||||
static status_t
|
||||
create_thread_user_stack(Team* team, Thread* thread, void* _stackBase,
|
||||
size_t stackSize, size_t additionalSize, char* nameBuffer)
|
||||
size_t stackSize, size_t additionalSize, size_t guardSize,
|
||||
char* nameBuffer)
|
||||
{
|
||||
area_id stackArea = -1;
|
||||
uint8* stackBase = (uint8*)_stackBase;
|
||||
|
||||
if (stackBase != NULL) {
|
||||
// A stack has been specified. It must be large enough to hold the
|
||||
// TLS space at least.
|
||||
// TLS space at least. Guard pages are ignored for existing stacks.
|
||||
STATIC_ASSERT(TLS_SIZE < MIN_USER_STACK_SIZE);
|
||||
if (stackSize < MIN_USER_STACK_SIZE)
|
||||
return B_BAD_VALUE;
|
||||
@@ -799,20 +801,22 @@ create_thread_user_stack(Team* team, Thread* thread, void* _stackBase,
|
||||
// will be between USER_STACK_REGION and the main thread stack area. For
|
||||
// a main thread the position is fixed.
|
||||
|
||||
guardSize = PAGE_ALIGN(guardSize);
|
||||
|
||||
if (stackSize == 0) {
|
||||
// Use the default size (a different one for a main thread).
|
||||
stackSize = thread->id == team->id
|
||||
? USER_MAIN_THREAD_STACK_SIZE : USER_STACK_SIZE;
|
||||
} else {
|
||||
// Verify that the given stack size is large enough.
|
||||
if (stackSize < MIN_USER_STACK_SIZE - TLS_SIZE)
|
||||
if (stackSize < MIN_USER_STACK_SIZE)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
stackSize = PAGE_ALIGN(stackSize);
|
||||
}
|
||||
stackSize += USER_STACK_GUARD_PAGES * B_PAGE_SIZE;
|
||||
|
||||
size_t areaSize = PAGE_ALIGN(stackSize + TLS_SIZE + additionalSize);
|
||||
size_t areaSize = PAGE_ALIGN(guardSize + stackSize + TLS_SIZE
|
||||
+ additionalSize);
|
||||
|
||||
snprintf(nameBuffer, B_OS_NAME_LENGTH, "%s_%" B_PRId32 "_stack",
|
||||
thread->name, thread->id);
|
||||
@@ -836,7 +840,7 @@ create_thread_user_stack(Team* team, Thread* thread, void* _stackBase,
|
||||
|
||||
stackArea = create_area_etc(team->id, nameBuffer,
|
||||
areaSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA | B_STACK_AREA,
|
||||
0, &virtualRestrictions, &physicalRestrictions,
|
||||
0, guardSize, &virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&stackBase);
|
||||
if (stackArea < 0)
|
||||
return stackArea;
|
||||
@@ -844,7 +848,11 @@ create_thread_user_stack(Team* team, Thread* thread, void* _stackBase,
|
||||
|
||||
// set the stack
|
||||
ThreadLocker threadLocker(thread);
|
||||
#ifdef STACK_GROWS_DOWNWARDS
|
||||
thread->user_stack_base = (addr_t)stackBase + guardSize;
|
||||
#else
|
||||
thread->user_stack_base = (addr_t)stackBase;
|
||||
#endif
|
||||
thread->user_stack_size = stackSize;
|
||||
thread->user_stack_area = stackArea;
|
||||
|
||||
@@ -858,7 +866,7 @@ thread_create_user_stack(Team* team, Thread* thread, void* stackBase,
|
||||
{
|
||||
char nameBuffer[B_OS_NAME_LENGTH];
|
||||
return create_thread_user_stack(team, thread, stackBase, stackSize,
|
||||
additionalSize, nameBuffer);
|
||||
additionalSize, USER_STACK_GUARD_SIZE, nameBuffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -915,11 +923,16 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel)
|
||||
char stackName[B_OS_NAME_LENGTH];
|
||||
snprintf(stackName, B_OS_NAME_LENGTH, "%s_%" B_PRId32 "_kstack",
|
||||
thread->name, thread->id);
|
||||
thread->kernel_stack_area = create_area(stackName,
|
||||
(void **)&thread->kernel_stack_base, B_ANY_KERNEL_ADDRESS,
|
||||
KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE,
|
||||
B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_KERNEL_STACK_AREA);
|
||||
virtual_address_restrictions virtualRestrictions = {};
|
||||
virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS;
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
|
||||
thread->kernel_stack_area = create_area_etc(B_SYSTEM_TEAM, stackName,
|
||||
KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE,
|
||||
B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA
|
||||
| B_KERNEL_STACK_AREA, 0, KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE,
|
||||
&virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&thread->kernel_stack_base);
|
||||
|
||||
if (thread->kernel_stack_area < 0) {
|
||||
// we're not yet part of a team, so we can just bail out
|
||||
@@ -948,7 +961,8 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel)
|
||||
if (thread->user_stack_base == 0) {
|
||||
status = create_thread_user_stack(team, thread,
|
||||
attributes.stack_address, attributes.stack_size,
|
||||
attributes.additional_stack_size, stackName);
|
||||
attributes.additional_stack_size, attributes.guard_size,
|
||||
stackName);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -787,25 +787,24 @@ VMAnonymousCache::MaxPagesPerAsyncWrite() const
|
||||
status_t
|
||||
VMAnonymousCache::Fault(struct VMAddressSpace* aspace, off_t offset)
|
||||
{
|
||||
if (fCanOvercommit && LookupPage(offset) == NULL && !HasPage(offset)) {
|
||||
if (fGuardedSize > 0) {
|
||||
uint32 guardOffset;
|
||||
if (fGuardedSize > 0) {
|
||||
uint32 guardOffset;
|
||||
|
||||
#ifdef STACK_GROWS_DOWNWARDS
|
||||
guardOffset = 0;
|
||||
guardOffset = 0;
|
||||
#elif defined(STACK_GROWS_UPWARDS)
|
||||
guardOffset = virtual_size - fGuardedSize;
|
||||
guardOffset = virtual_size - fGuardedSize;
|
||||
#else
|
||||
# error Stack direction has not been defined in arch_config.h
|
||||
#endif
|
||||
|
||||
// report stack fault, guard page hit!
|
||||
if (offset >= guardOffset && offset < guardOffset + fGuardedSize) {
|
||||
TRACE(("stack overflow!\n"));
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
// report stack fault, guard page hit!
|
||||
if (offset >= guardOffset && offset < guardOffset + fGuardedSize) {
|
||||
TRACE(("stack overflow!\n"));
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (fCanOvercommit && LookupPage(offset) == NULL && !HasPage(offset)) {
|
||||
if (fPrecommittedPages == 0) {
|
||||
// never commit more than needed
|
||||
if (committed_size / B_PAGE_SIZE > page_count)
|
||||
|
||||
@@ -45,6 +45,8 @@ public:
|
||||
virtual bool HasPage(off_t offset);
|
||||
virtual bool DebugHasPage(off_t offset);
|
||||
|
||||
virtual int32 GuardSize() { return fGuardedSize; }
|
||||
|
||||
virtual status_t Read(off_t offset, const generic_io_vec* vecs,
|
||||
size_t count, uint32 flags,
|
||||
generic_size_t* _numBytes);
|
||||
|
||||
@@ -120,25 +120,24 @@ VMAnonymousNoSwapCache::Write(off_t offset, const iovec* vecs, size_t count,
|
||||
status_t
|
||||
VMAnonymousNoSwapCache::Fault(struct VMAddressSpace* aspace, off_t offset)
|
||||
{
|
||||
if (fCanOvercommit) {
|
||||
if (fGuardedSize > 0) {
|
||||
uint32 guardOffset;
|
||||
if (fGuardedSize > 0) {
|
||||
uint32 guardOffset;
|
||||
|
||||
#ifdef STACK_GROWS_DOWNWARDS
|
||||
guardOffset = 0;
|
||||
guardOffset = 0;
|
||||
#elif defined(STACK_GROWS_UPWARDS)
|
||||
guardOffset = virtual_size - fGuardedSize;
|
||||
guardOffset = virtual_size - fGuardedSize;
|
||||
#else
|
||||
# error Stack direction has not been defined in arch_config.h
|
||||
#endif
|
||||
|
||||
// report stack fault, guard page hit!
|
||||
if (offset >= guardOffset && offset < guardOffset + fGuardedSize) {
|
||||
TRACE(("stack overflow!\n"));
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
// report stack fault, guard page hit!
|
||||
if (offset >= guardOffset && offset < guardOffset + fGuardedSize) {
|
||||
TRACE(("stack overflow!\n"));
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (fCanOvercommit) {
|
||||
if (fPrecommittedPages == 0) {
|
||||
// never commit more than needed
|
||||
if (committed_size / B_PAGE_SIZE > page_count)
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
virtual status_t Commit(off_t size, int priority);
|
||||
virtual bool HasPage(off_t offset);
|
||||
|
||||
virtual int32 GuardSize() { return fGuardedSize; }
|
||||
|
||||
virtual status_t Read(off_t offset, const iovec* vecs,
|
||||
size_t count, uint32 flags,
|
||||
size_t* _numBytes);
|
||||
|
||||
+19
-18
@@ -817,10 +817,10 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset,
|
||||
VMCache* newCache;
|
||||
|
||||
// create an anonymous cache
|
||||
bool isStack = (protection & B_STACK_AREA) != 0;
|
||||
status = VMCacheFactory::CreateAnonymousCache(newCache,
|
||||
isStack || (protection & B_OVERCOMMITTING_AREA) != 0, 0,
|
||||
isStack ? USER_STACK_GUARD_PAGES : 0, true, VM_PRIORITY_USER);
|
||||
(protection & B_STACK_AREA) != 0
|
||||
|| (protection & B_OVERCOMMITTING_AREA) != 0, 0,
|
||||
cache->GuardSize() / B_PAGE_SIZE, true, VM_PRIORITY_USER);
|
||||
if (status != B_OK)
|
||||
goto err1;
|
||||
|
||||
@@ -1178,7 +1178,7 @@ vm_reserve_address_range(team_id team, void** _address, uint32 addressSpec,
|
||||
|
||||
area_id
|
||||
vm_create_anonymous_area(team_id team, const char *name, addr_t size,
|
||||
uint32 wiring, uint32 protection, uint32 flags,
|
||||
uint32 wiring, uint32 protection, uint32 flags, addr_t guardSize,
|
||||
const virtual_address_restrictions* virtualAddressRestrictions,
|
||||
const physical_address_restrictions* physicalAddressRestrictions,
|
||||
bool kernel, void** _address)
|
||||
@@ -1196,8 +1196,10 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size,
|
||||
team, name, size));
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
guardSize = PAGE_ALIGN(guardSize);
|
||||
guardPages = guardSize / B_PAGE_SIZE;
|
||||
|
||||
if (size == 0)
|
||||
if (size == 0 || size < guardSize)
|
||||
return B_BAD_VALUE;
|
||||
if (!arch_vm_supports_protection(protection))
|
||||
return B_NOT_SUPPORTED;
|
||||
@@ -1373,8 +1375,6 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size,
|
||||
|
||||
// create an anonymous cache
|
||||
// if it's a stack, make sure that two pages are available at least
|
||||
guardPages = isStack ? ((protection & B_USER_PROTECTION) != 0
|
||||
? USER_STACK_GUARD_PAGES : KERNEL_STACK_GUARD_PAGES) : 0;
|
||||
status = VMCacheFactory::CreateAnonymousCache(cache, canOvercommit,
|
||||
isStack ? (min_c(2, size / B_PAGE_SIZE - guardPages)) : 0, guardPages,
|
||||
wiring == B_NO_LOCK, priority);
|
||||
@@ -1879,7 +1879,7 @@ _vm_map_file(team_id team, const char* name, void** _address,
|
||||
virtualRestrictions.address_specification = addressSpec;
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
return vm_create_anonymous_area(team, name, size, B_NO_LOCK, protection,
|
||||
flags, &virtualRestrictions, &physicalRestrictions, kernel,
|
||||
flags, 0, &virtualRestrictions, &physicalRestrictions, kernel,
|
||||
_address);
|
||||
}
|
||||
|
||||
@@ -2305,7 +2305,8 @@ vm_copy_on_write_area(VMCache* lowerCache,
|
||||
|
||||
// create an anonymous cache
|
||||
status_t status = VMCacheFactory::CreateAnonymousCache(upperCache, false, 0,
|
||||
0, dynamic_cast<VMAnonymousNoSwapCache*>(lowerCache) == NULL,
|
||||
lowerCache->GuardSize() / B_PAGE_SIZE,
|
||||
dynamic_cast<VMAnonymousNoSwapCache*>(lowerCache) == NULL,
|
||||
VM_PRIORITY_USER);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
@@ -3893,8 +3894,8 @@ vm_init(kernel_args* args)
|
||||
create_area_etc(VMAddressSpace::KernelID(), "cache info table",
|
||||
ROUNDUP(kCacheInfoTableCount * sizeof(cache_info), B_PAGE_SIZE),
|
||||
B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||
CREATE_AREA_DONT_WAIT, &virtualRestrictions, &physicalRestrictions,
|
||||
(void**)&sCacheInfoTable);
|
||||
CREATE_AREA_DONT_WAIT, 0, &virtualRestrictions,
|
||||
&physicalRestrictions, (void**)&sCacheInfoTable);
|
||||
}
|
||||
#endif // DEBUG_CACHE_LIST
|
||||
|
||||
@@ -5863,7 +5864,7 @@ clone_area(const char* name, void** _address, uint32 addressSpec,
|
||||
|
||||
area_id
|
||||
create_area_etc(team_id team, const char* name, uint32 size, uint32 lock,
|
||||
uint32 protection, uint32 flags,
|
||||
uint32 protection, uint32 flags, uint32 guardSize,
|
||||
const virtual_address_restrictions* virtualAddressRestrictions,
|
||||
const physical_address_restrictions* physicalAddressRestrictions,
|
||||
void** _address)
|
||||
@@ -5871,8 +5872,8 @@ create_area_etc(team_id team, const char* name, uint32 size, uint32 lock,
|
||||
fix_protection(&protection);
|
||||
|
||||
return vm_create_anonymous_area(team, name, size, lock, protection, flags,
|
||||
virtualAddressRestrictions, physicalAddressRestrictions, true,
|
||||
_address);
|
||||
guardSize, virtualAddressRestrictions, physicalAddressRestrictions,
|
||||
true, _address);
|
||||
}
|
||||
|
||||
|
||||
@@ -5887,8 +5888,8 @@ __create_area_haiku(const char* name, void** _address, uint32 addressSpec,
|
||||
virtualRestrictions.address_specification = addressSpec;
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
return vm_create_anonymous_area(VMAddressSpace::KernelID(), name, size,
|
||||
lock, protection, 0, &virtualRestrictions, &physicalRestrictions, true,
|
||||
_address);
|
||||
lock, protection, 0, 0, &virtualRestrictions, &physicalRestrictions,
|
||||
true, _address);
|
||||
}
|
||||
|
||||
|
||||
@@ -6131,8 +6132,8 @@ _user_create_area(const char* userName, void** userAddress, uint32 addressSpec,
|
||||
virtualRestrictions.address_specification = addressSpec;
|
||||
physical_address_restrictions physicalRestrictions = {};
|
||||
area_id area = vm_create_anonymous_area(VMAddressSpace::CurrentID(), name,
|
||||
size, lock, protection, 0, &virtualRestrictions, &physicalRestrictions,
|
||||
false, &address);
|
||||
size, lock, protection, 0, 0, &virtualRestrictions,
|
||||
&physicalRestrictions, false, &address);
|
||||
|
||||
if (area >= B_OK
|
||||
&& user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
static const pthread_attr pthread_attr_default = {
|
||||
PTHREAD_CREATE_JOINABLE,
|
||||
B_NORMAL_PRIORITY,
|
||||
USER_STACK_SIZE
|
||||
USER_STACK_SIZE,
|
||||
USER_STACK_GUARD_SIZE
|
||||
};
|
||||
|
||||
|
||||
@@ -117,6 +118,7 @@ __pthread_init_creation_attributes(const pthread_attr_t* pthreadAttributes,
|
||||
attributes->args2 = argument2;
|
||||
attributes->stack_address = NULL;
|
||||
attributes->stack_size = attr->stack_size;
|
||||
attributes->guard_size = attr->guard_size;
|
||||
attributes->pthread = thread;
|
||||
attributes->flags = 0;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ pthread_attr_init(pthread_attr_t *_attr)
|
||||
attr->detach_state = PTHREAD_CREATE_JOINABLE;
|
||||
attr->sched_priority = B_NORMAL_PRIORITY;
|
||||
attr->stack_size = USER_STACK_SIZE;
|
||||
attr->guard_size = USER_STACK_GUARD_SIZE;
|
||||
|
||||
*_attr = attr;
|
||||
return B_OK;
|
||||
@@ -162,3 +163,30 @@ pthread_attr_getschedparam(const pthread_attr_t *attr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pthread_attr_getguardsize(const pthread_attr_t *_attr, size_t *guardsize)
|
||||
{
|
||||
pthread_attr *attr;
|
||||
|
||||
if (_attr == NULL || (attr = *_attr) == NULL || guardsize == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
*guardsize = attr->guard_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pthread_attr_setguardsize(pthread_attr_t *_attr, size_t guardsize)
|
||||
{
|
||||
pthread_attr *attr;
|
||||
|
||||
if (_attr == NULL || (attr = *_attr) == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
attr->guard_size = guardsize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user