#include <stdio.h>
#include <pthread.h>
#include <thread.h>
#include <door.h>
#include <stdlib.h>
#include <unistd.h>
#include <ucontext.h>
#include <sys/stack.h>
#if defined(__i386)
#undef STACK_ALIGN
#define STACK_ALIGN 16
#endif
#define ALIGN_ERR_IMPL(align, text) \
"stack was not aligned to " #align " on " text "\n"
#define ALIGN_ERR_HELP(align, text) ALIGN_ERR_IMPL(align, text)
#define ALIGN_ERR(text) ALIGN_ERR_HELP(STACK_ALIGN, text)
#define STACK_SIZE 16*1024
typedef struct test_ctx {
void (*func)(uintptr_t, char *);
char *text;
} test_ctx_t;
extern void get_stack_at_entry(test_ctx_t *);
void
teststack(uintptr_t stack, char *arg)
{
if ((stack & (STACK_ALIGN - 1)) != 0) {
fprintf(stderr, ALIGN_ERR("%s"), (char *)arg);
exit(1);
}
}
void
initmain(uintptr_t stack)
{
teststack(stack, "section .init");
}
void
initarray(uintptr_t stack)
{
teststack(stack, "section .init_array");
}
void
doorstack(uintptr_t stack, char *arg)
{
teststack(stack, arg);
(void) door_return(NULL, 0, NULL, 0);
}
char door_arg[] = "DOOR ARG";
int
main(int argc, char *argv[])
{
door_arg_t da = {
.data_ptr = (void *)door_arg,
.data_size = sizeof (door_arg)
};
test_ctx_t arg = {
.func = teststack,
.text = "pthread_create()"
};
ucontext_t back, uc;
pthread_t tid;
int door_fd, rc;
if (pthread_create(&tid, NULL,
(void *(*)(void *))(uintptr_t)get_stack_at_entry, &arg) != 0) {
perror("pthread_create() failed:");
exit(-2);
}
(void) pthread_join(tid, NULL);
arg.text = "thr_create()";
if (thr_create(NULL, 0,
(void *(*)(void *))(uintptr_t)get_stack_at_entry,
&arg, 0, &tid) != 0) {
perror("thr_create() failed:");
exit(-3);
}
(void) thr_join(tid, NULL, NULL);
if (getcontext(&uc) < 0) {
perror("getcontext() failed");
exit(-4);
}
uc.uc_link = &back;
uc.uc_stack.ss_size = STACK_SIZE;
uc.uc_stack.ss_flags = 0;
if ((uc.uc_stack.ss_sp = malloc(STACK_SIZE)) == NULL) {
perror("failed to allocate stack");
exit(-5);
}
arg.text = "swapcontext()";
makecontext(&uc, (void (*)(void *))get_stack_at_entry, 1, &arg);
if (swapcontext(&back, &uc) < 0) {
perror("swapcontext() failed");
exit(-6);
}
arg.func = doorstack;
arg.text = "door_call()";
if ((door_fd = door_create(
(door_server_procedure_t *)(uintptr_t)get_stack_at_entry,
&arg, 0)) < 0) {
perror("failed to create door");
exit(-7);
}
rc = door_call(door_fd, &da);
if (rc < 0) {
perror("door call #1 failed");
exit(-8);
}
da.data_size += 5;
rc = door_call(door_fd, &da);
if (rc < 0) {
perror("door call #2 failed");
exit(-9);
}
(void) close(door_fd);
return (0);
}