#include <sys/types.h>
#include <sys/mman.h>
#include <stdint.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "test.h"
#define LARGE_SIZE (1024 * 1024)
void *
tmain0(void *arg)
{
int s;
return (&s);
}
void *
tmain1(void *arg)
{
char buf[LARGE_SIZE];
memset(buf, 0xd0, sizeof(buf));
return (buf + LARGE_SIZE/2);
}
struct st
{
char *addr;
size_t size;
};
void *
tmain2(void *arg)
{
struct st *s = arg;
ASSERT((char *)&s >= s->addr && (char *)&s - s->addr < s->size);
return (NULL);
}
int
main(void)
{
pthread_attr_t attr;
pthread_t t;
struct st thread_stack;
void *addr, *addr2;
size_t size, size2, pagesize;
int err;
pagesize = (size_t)sysconf(_SC_PAGESIZE);
CHECKr(pthread_attr_init(&attr));
size = 1;
CHECKr(pthread_attr_getguardsize(&attr, &size));
ASSERT(size != 1);
ASSERT(size != 0);
size = 1;
CHECKr(pthread_attr_getstacksize(&attr, &size));
ASSERT(size >= PTHREAD_STACK_MIN);
addr = &addr;
CHECKr(pthread_attr_getstackaddr(&attr, &addr));
ASSERT(addr == NULL);
addr2 = &addr;
size2 = 1;
CHECKr(pthread_attr_getstack(&attr, &addr2, &size2));
ASSERT(addr2 == addr);
ASSERT(size2 == size);
err = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN - 1);
ASSERT(err == EINVAL);
CHECKr(pthread_attr_getstacksize(&attr, &size2));
ASSERT(size2 == size);
CHECKr(pthread_create(&t, NULL, &tmain0, NULL));
sleep(1);
CHECKr(pthread_join(t, &addr));
*(int *)addr = 100;
CHECKr(pthread_create(&t, NULL, &tmain0, NULL));
sleep(1);
CHECKr(pthread_join(t, &addr2));
ASSERT(addr == addr2);
size2 += LARGE_SIZE;
CHECKr(pthread_attr_setstacksize(&attr, size2));
CHECKr(pthread_attr_getstacksize(&attr, &size));
ASSERT(size == size2);
CHECKr(pthread_create(&t, &attr, &tmain1, NULL));
sleep(1);
CHECKr(pthread_join(t, &addr));
addr = (void *)((uintptr_t)addr & ~(pagesize - 1));
ASSERT(mquery(addr, pagesize, PROT_READ, MAP_FIXED|MAP_ANON, -1, 0)
== addr);
size = 1;
CHECKr(pthread_attr_getstacksize(&attr, &size));
ASSERT(size == size2);
size = pagesize * 4;
addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE,
-1, 0);
ASSERT(addr != MAP_FAILED);
memset(addr, 0xd0, size);
CHECKr(pthread_attr_setstack(&attr, addr, size));
CHECKr(pthread_attr_getstacksize(&attr, &size2));
ASSERT(size2 == size);
CHECKr(pthread_attr_getstackaddr(&attr, &addr2));
ASSERT(addr2 == addr);
CHECKr(pthread_attr_getstack(&attr, &addr2, &size2));
ASSERT(addr2 == addr);
ASSERT(size2 == size);
thread_stack.addr = addr;
thread_stack.size = size;
CHECKr(pthread_create(&t, &attr, &tmain2, &thread_stack));
sleep(1);
CHECKr(pthread_join(t, NULL));
memset(addr, 0xd0, size);
return (0);
}