mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-19 10:58:30 +00:00
Reduce stack virtual memory consumption on Linux
This commit is contained in:
parent
cc8a9eb93c
commit
36e5861b0c
31 changed files with 583 additions and 166 deletions
|
@ -16,64 +16,42 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Configures custom allocated stack for thread, e.g.
|
||||
* Configures custom stack for thread.
|
||||
*
|
||||
* pthread_t id;
|
||||
* pthread_attr_t attr;
|
||||
* char *stk = NewCosmoStack();
|
||||
* pthread_attr_init(&attr);
|
||||
* pthread_attr_setstack(&attr, stk, GetStackSize());
|
||||
* pthread_create(&id, &attr, func, 0);
|
||||
* pthread_attr_destroy(&attr);
|
||||
* pthread_join(id, 0);
|
||||
* FreeCosmoStack(stk);
|
||||
* Normally you want to use pthread_attr_setstacksize() and
|
||||
* pthread_attr_setguardsize() to configure how pthread_create()
|
||||
* allocates stack memory for newly created threads. Cosmopolitan is
|
||||
* very good at managing stack memory. However if you still want to
|
||||
* allocate stack memory on your own, POSIX defines this function.
|
||||
*
|
||||
* Your stack must have at least `PTHREAD_STACK_MIN` bytes, which
|
||||
* Cosmpolitan Libc defines as `GetStackSize()`. It's a link-time
|
||||
* constant used by Actually Portable Executable that's 128 kb by
|
||||
* default. See libc/runtime/stack.h for docs on your stack limit
|
||||
* since the APE ELF phdrs are the one true source of truth here.
|
||||
* Your `stackaddr` points to the byte at the very bottom of your stack.
|
||||
* You are responsible for this memory. Your POSIX threads runtime will
|
||||
* not free or unmap this allocation when the thread has terminated. If
|
||||
* `stackaddr` is null then `stacksize` is ignored and default behavior
|
||||
* is restored, i.e. pthread_create() will manage stack allocations.
|
||||
*
|
||||
* Cosmpolitan Libc runtime magic (e.g. ftrace) and memory safety
|
||||
* (e.g. kprintf) assumes that stack sizes are two-powers and are
|
||||
* aligned to that two-power. Conformance isn't required since we
|
||||
* say caveat emptor to those who don't maintain these invariants
|
||||
* please consider using NewCosmoStack(), which is always perfect
|
||||
* or use `mmap(0, GetStackSize() << 1, ...)` for a bigger stack.
|
||||
* Your `stackaddr` could be created by malloc(). On OpenBSD,
|
||||
* pthread_create() will augment your custom allocation so it's
|
||||
* permissable by the kernel to use as a stack. You may also call
|
||||
* Cosmopolitan APIs such NewCosmoStack() and cosmo_stack_alloc().
|
||||
* Static memory can be used, but it won't reduce pthread footprint.
|
||||
*
|
||||
* Unlike pthread_attr_setstacksize(), this function permits just
|
||||
* about any parameters and will change the values and allocation
|
||||
* as needed to conform to the mandatory requirements of the host
|
||||
* operating system even if it doesn't meet the stricter needs of
|
||||
* Cosmopolitan Libc userspace libraries. For example with malloc
|
||||
* allocations, things like page size alignment, shall be handled
|
||||
* automatically for compatibility with existing codebases.
|
||||
*
|
||||
* The same stack shouldn't be used for two separate threads. Use
|
||||
* fresh stacks for each thread so that ASAN can be much happier.
|
||||
*
|
||||
* @param stackaddr is address of stack allocated by caller, and
|
||||
* may be NULL in which case default behavior is restored
|
||||
* @param stacksize is size of caller allocated stack
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise EINVAL if parameters were unacceptable
|
||||
* @raise EINVAL if `stacksize` is less than `PTHREAD_STACK_MIN`
|
||||
* @see pthread_attr_setstacksize()
|
||||
*/
|
||||
errno_t pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
|
||||
size_t stacksize) {
|
||||
if (!stackaddr) {
|
||||
attr->__stackaddr = 0;
|
||||
attr->__stacksize = 0;
|
||||
attr->__stacksize = GetStackSize();
|
||||
return 0;
|
||||
}
|
||||
if (stacksize > INT_MAX)
|
||||
return EINVAL;
|
||||
if (stacksize < PTHREAD_STACK_MIN)
|
||||
return EINVAL;
|
||||
attr->__stackaddr = stackaddr;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue