Base WG Resolution Ref: bwg2000-003
Topic: pthreads stack handling


This is an approved Base Working Group Resolution for XSH5.

Last update: 29 April,2000


								2000 #003r2

 _____________________________________________________________________________

	Topic:			pthreads stack handling
	Relevant Sections:	pthread_
	Spec:			XSH5

Resolution Request:
-------------------

POSIX 1003.1c included an optional feature known as the "stackaddr"
attribute, manipulated using the pthread_attr_setstackaddr() and
pthread_attr_getstackaddr() functions. This optional features was
designed to allow an application to create and manage its own stacks.

PROBLEM STATEMENT:

There are some problems with the "stackaddr" attribute, stemming from
the fact that the standard does not provide any way to specify the size
of the application-managed stack.

  1. The implementation cannot know the size without guessing, or
     utilizing some non-standard mechanism.
  2. The standard does not specify, or even suggest, the relationship
     between the specified address and the actual base of the thread's
     stack. There various possibilities, depending on whether the
     machine modifies a stack pointer before or after storing data, and
     whether it increases or decreases the stack pointer. (There are
     more than the obvious four combinations because on Intel's IA-64
     architecture each thread has two independent stacks, one of which
     grows UP while the other grows DOWN.)

An implementation can only make one "guess" about the stack's size
that's remotely supported by the standard: that the stack is precisely
PTHREAD_STACK_MIN bytes. This, however, is not useful because, by
definition, that is a "minimal" size, not even a "typical" size. There's
little value to an application in being able to "manage its own stacks"
if it can do so only for stacks of the architecturally minimum size.

The only suggestion provided by the standard for a means to specify the
size of a "stackaddr" stack is to presume a connection between the
"stackaddr" and "stacksize" attributes. No such connection, however, is
specified, or even explicitly allowed, by the standard. Therefore, any
application depending on such a connection is non-portable. To require
such a connection now would break existing applications, where the value
of "stacksize" that happens to be in an attributes object could suddenly
become an actual limit.

Furthermore, there's little value to improving the situation unless we
define "stackaddr" in a way that would become portable, such as
specifying that it be the low address of the stack. Such a change would
also break existing code on real implementations. (For example, Tru64
UNIX, where "stackaddr" must specify the address immediately following
the stack buffer because the stack grows down and the pointer is
decreased before storing data.)

PROPOSED SOLUTION:

The "stackaddr" attribute should be marked "obsolete", and should be
replaced by an attribute that's clear, useful, and can be used portably,
such as the proposed "stack" attribute. An application-managed stack is
specified using the low memory address (e.g., the address returned by
malloc, or mmap), and a size. The implementation can position the
thread's initial stack pointer(s) where necessary and appropriate within
that region, without guessing, and without additional assistance from
the application.

The "stack" attribute is intended to be MINIMAL, not COMPREHENSIVE. For
example, it has frequently been assumed that applications can provide
stack overflow protection with a protected page (or pages) outside the
described area. However, no fully portable application can do this,
because it would still need to know at which end of the stack the
protected page should go. While it could place protected pages at both
ends, an implementation on Intel's IA-64 is likely to create two
separate stacks that grow towards the center of the provided region. It
would be possible to extend the stack attribute interface, either by
adding a parameter or by specifying a connection with the "guardsize"
attribute, to cause the implementation to provide appropriate guard
page(s) for the application stack. (I'd prefer to avoid such a
connection, because experience has shown, as with policy and priority,
and expecially inheritsched, that this causes programmer confusion and
unnecessary support calls.) I am not proposing either extension, but I
would not object to adding a "guardsize" parameter to the "stack"
attribute functions.


Resolution Response
-------------------


Two new functions will be added to a future revision of the
specification. A new manual page is attached.
This is an XSI extension.


NAME

pthread_attr_getstack, pthread_attr_setstack - get and
set stack attribute

SYNOPSIS

#include <pthread.h>

int pthread_attr_getstack(const pthread_attr_t *attr,
void **stackaddr, size_t *stacksize);
int pthread_attr_setstack(pthread_attr_t *attr,
void *stackaddr, size_t stacksize);

DESCRIPTION

The functions pthread_attr_getstack() and
pthread_attr_setstack(), respectively, shall get and set the thread
creation stack attribute in the attr object.

The stack attribute specifies the area of storage to be
used for the created thread's stack. The base (lowest addressable
byte) of the storage is stackaddr, and the size of the storage is
stacksize bytes. The stacksize shall be at least
PTHREAD_STACK_MIN. The stackaddr shall be aligned appropriately to
be used as a stack; for example, pthread_attr_setstack may fail
with EINVAL if (stackaddr & 0x7) is not 0. All pages within the stack
described by stackaddr and stacksize shall be both readable and writeable
by the thread.

RETURN VALUE

Upon successful completion, pthread_attr_getstack() and
pthread_attr_setstack() shall return a value of 0; otherwise, an error
number shall be returned to indicate the error.

The pthread_attr_getstack() function shall store the stack attribute
values in stackaddr and stacksize if successful.

ERRORS

The pthread_attr_setstack() function shall fail if:

[EINVAL]
The value of stacksize is less than PTHREAD_STACK_MIN or
exceeds a system-imposed limit.

The pthread_attr_setstack() function may fail if:

[EINVAL]
The value of stackaddr does not have proper alignment to
be used as a stack, or if (stackaddr + stacksize) lacks
proper alignment.

[EACCES]
The stack page(s) describe by stackaddr and stacksize are not
both readable and writeable by the thread.

These functions shall not return an error code of [EINTR].

EXAMPLES

None.

APPLICATION USAGE

These functions are appropriate for use by applications in an
environment where the stack for a thread must be placed in some
particular region of memory.

While it might seem that an application could detect stack
overflow by providing a protected page outside the specified
stack region, this cannot be done portably. Implementations are
free to place the thread's initial stack pointer anywhere within
the specified region to accomodate the machine's stack pointer
behavior and allocation requirements. Furthermore, on some
architectures, such as the IA-64 , "overflow" might mean that
two separate stack pointers allocated within the region
will overlap somewhere in the middle of the region.

FUTURE DIRECTIONS

None.

SEE ALSO

pthread_attr_init(), pthread_attr_setdetachstate(),
pthread_attr_setstacksize(), pthread_create(), <limits.h>,
<pthread.h>.

Rationale
-------------

See the problem statement.

Circulated for review: 26 Apr 2000
Proposed resolution: 26 Apr 2000
Approved: April 2000