From d1f280c80529d5f0bc55030c2934f9255bc7f6a2 Mon Sep 17 00:00:00 2001 From: Hamish Morrison Date: Sun, 1 Apr 2012 08:37:42 +0000 Subject: [PATCH] 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. --- headers/posix/pthread.h | 9 ++--- headers/private/kernel/vm/VMCache.h | 2 + headers/private/kernel/vm/vm.h | 4 +- headers/private/libroot/pthread_private.h | 1 + headers/private/system/thread_defs.h | 14 +++---- .../kernel/bus_managers/scsi/dma_buffer.cpp | 2 +- .../kernel/bus_managers/scsi/emulation.cpp | 2 +- .../compat/freebsd_network/compat_cpp.cpp | 2 +- src/libs/posix_error_mapper/pthread_attr.cpp | 14 +++++++ .../arm/paging/32bit/ARMPagingMethod32Bit.cpp | 2 +- src/system/kernel/arch/x86/32/descriptors.cpp | 2 +- src/system/kernel/arch/x86/arch_cpu.cpp | 2 +- .../x86/paging/32bit/X86PagingMethod32Bit.cpp | 2 +- .../x86/paging/pae/X86PagingMethodPAE.cpp | 2 +- src/system/kernel/debug/debug_heap.cpp | 2 +- src/system/kernel/debug/tracing.cpp | 8 ++-- .../kernel/device_manager/dma_resources.cpp | 2 +- src/system/kernel/elf.cpp | 2 +- src/system/kernel/sem.cpp | 2 +- src/system/kernel/slab/MemoryManager.cpp | 2 +- src/system/kernel/team.cpp | 2 +- src/system/kernel/thread.cpp | 40 +++++++++++++------ src/system/kernel/vm/VMAnonymousCache.cpp | 21 +++++----- src/system/kernel/vm/VMAnonymousCache.h | 2 + .../kernel/vm/VMAnonymousNoSwapCache.cpp | 21 +++++----- src/system/kernel/vm/VMAnonymousNoSwapCache.h | 2 + src/system/kernel/vm/vm.cpp | 37 ++++++++--------- src/system/libroot/posix/pthread/pthread.cpp | 4 +- .../libroot/posix/pthread/pthread_attr.c | 28 +++++++++++++ 29 files changed, 148 insertions(+), 87 deletions(-) diff --git a/headers/posix/pthread.h b/headers/posix/pthread.h index cc5b900dfd..ac84d62315 100644 --- a/headers/posix/pthread.h +++ b/headers/posix/pthread.h @@ -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); diff --git a/headers/private/kernel/vm/VMCache.h b/headers/private/kernel/vm/VMCache.h index 06bb0b9bba..ffa236a280 100644 --- a/headers/private/kernel/vm/VMCache.h +++ b/headers/private/kernel/vm/VMCache.h @@ -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); diff --git a/headers/private/kernel/vm/vm.h b/headers/private/kernel/vm/vm.h index ef1b829915..bd9fd16aa8 100644 --- a/headers/private/kernel/vm/vm.h +++ b/headers/private/kernel/vm/vm.h @@ -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); diff --git a/headers/private/libroot/pthread_private.h b/headers/private/libroot/pthread_private.h index f50bd28e0e..1ddc00c6be 100644 --- a/headers/private/libroot/pthread_private.h +++ b/headers/private/libroot/pthread_private.h @@ -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 { diff --git a/headers/private/system/thread_defs.h b/headers/private/system/thread_defs.h index 9f1b527b8e..2d559378f4 100644 --- a/headers/private/system/thread_defs.h +++ b/headers/private/system/thread_defs.h @@ -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; }; diff --git a/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp b/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp index 338a45f647..ef548102c6 100644 --- a/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp @@ -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) { diff --git a/src/add-ons/kernel/bus_managers/scsi/emulation.cpp b/src/add-ons/kernel/bus_managers/scsi/emulation.cpp index 9127e242c3..161b27395e 100644 --- a/src/add-ons/kernel/bus_managers/scsi/emulation.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/emulation.cpp @@ -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! diff --git a/src/libs/compat/freebsd_network/compat_cpp.cpp b/src/libs/compat/freebsd_network/compat_cpp.cpp index 97c9243c83..a9ae740755 100644 --- a/src/libs/compat/freebsd_network/compat_cpp.cpp +++ b/src/libs/compat/freebsd_network/compat_cpp.cpp @@ -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; diff --git a/src/libs/posix_error_mapper/pthread_attr.cpp b/src/libs/posix_error_mapper/pthread_attr.cpp index 163220afeb..2783bfd038 100644 --- a/src/libs/posix_error_mapper/pthread_attr.cpp +++ b/src/libs/posix_error_mapper/pthread_attr.cpp @@ -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)); +) diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp index fe033e0ac9..a973bb2e82 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp @@ -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; diff --git a/src/system/kernel/arch/x86/32/descriptors.cpp b/src/system/kernel/arch/x86/32/descriptors.cpp index 2a957e3e66..465aab78ca 100644 --- a/src/system/kernel/arch/x86/32/descriptors.cpp +++ b/src/system/kernel/arch/x86/32/descriptors.cpp @@ -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; diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 155ed9753c..7438203853 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -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); diff --git a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp index 987f3b4c8d..be91ed524a 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp +++ b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp @@ -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; diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp index 3a3115ff4d..34258f0c1d 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp @@ -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; diff --git a/src/system/kernel/debug/debug_heap.cpp b/src/system/kernel/debug/debug_heap.cpp index 996f5213b9..efdd734560 100644 --- a/src/system/kernel/debug/debug_heap.cpp +++ b/src/system/kernel/debug/debug_heap.cpp @@ -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; diff --git a/src/system/kernel/debug/tracing.cpp b/src/system/kernel/debug/tracing.cpp index 02b55c7ef3..e52ffb72e9 100644 --- a/src/system/kernel/debug/tracing.cpp +++ b/src/system/kernel/debug/tracing.cpp @@ -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 " diff --git a/src/system/kernel/device_manager/dma_resources.cpp b/src/system/kernel/device_manager/dma_resources.cpp index 7e334f4e21..71753c8414 100644 --- a/src/system/kernel/device_manager/dma_resources.cpp +++ b/src/system/kernel/device_manager/dma_resources.cpp @@ -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; diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 19d5e55646..0bb496fa7b 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -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)); diff --git a/src/system/kernel/sem.cpp b/src/system/kernel/sem.cpp index 13fe243b4d..0b761c2724 100644 --- a/src/system/kernel/sem.cpp +++ b/src/system/kernel/sem.cpp @@ -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"); diff --git a/src/system/kernel/slab/MemoryManager.cpp b/src/system/kernel/slab/MemoryManager.cpp index 39d6d579be..1dab8fb807 100644 --- a/src/system/kernel/slab/MemoryManager.cpp +++ b/src/system/kernel/slab/MemoryManager.cpp @@ -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; diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index e492bcdb1f..381be36458 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -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; diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index e0eae26d2f..02a574e518 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -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; } diff --git a/src/system/kernel/vm/VMAnonymousCache.cpp b/src/system/kernel/vm/VMAnonymousCache.cpp index 78925e9500..8302f997ee 100644 --- a/src/system/kernel/vm/VMAnonymousCache.cpp +++ b/src/system/kernel/vm/VMAnonymousCache.cpp @@ -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) diff --git a/src/system/kernel/vm/VMAnonymousCache.h b/src/system/kernel/vm/VMAnonymousCache.h index a3d51ad43b..065f422325 100644 --- a/src/system/kernel/vm/VMAnonymousCache.h +++ b/src/system/kernel/vm/VMAnonymousCache.h @@ -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); diff --git a/src/system/kernel/vm/VMAnonymousNoSwapCache.cpp b/src/system/kernel/vm/VMAnonymousNoSwapCache.cpp index bd8ec84d6c..1de023a26f 100644 --- a/src/system/kernel/vm/VMAnonymousNoSwapCache.cpp +++ b/src/system/kernel/vm/VMAnonymousNoSwapCache.cpp @@ -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) diff --git a/src/system/kernel/vm/VMAnonymousNoSwapCache.h b/src/system/kernel/vm/VMAnonymousNoSwapCache.h index c9b839ea04..c9250ed6bf 100644 --- a/src/system/kernel/vm/VMAnonymousNoSwapCache.h +++ b/src/system/kernel/vm/VMAnonymousNoSwapCache.h @@ -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); diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 1559491fe5..6e809b66a0 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -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(lowerCache) == NULL, + lowerCache->GuardSize() / B_PAGE_SIZE, + dynamic_cast(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) { diff --git a/src/system/libroot/posix/pthread/pthread.cpp b/src/system/libroot/posix/pthread/pthread.cpp index 4c5104a06b..15c25165a6 100644 --- a/src/system/libroot/posix/pthread/pthread.cpp +++ b/src/system/libroot/posix/pthread/pthread.cpp @@ -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; diff --git a/src/system/libroot/posix/pthread/pthread_attr.c b/src/system/libroot/posix/pthread/pthread_attr.c index 3054690632..f6a15ff5e6 100644 --- a/src/system/libroot/posix/pthread/pthread_attr.c +++ b/src/system/libroot/posix/pthread/pthread_attr.c @@ -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; +}