darling-libpthread/tests/pthread_exit.c
2022-11-20 19:57:28 -08:00

122 lines
2.9 KiB
C

#include <stdio.h>
#include <pthread.h>
#include <pthread/private.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include "darwintest_defaults.h"
#define STACK_SIZE 32768
#define THREAD_DEPTH 2000
static unsigned int glob = 0;
static unsigned int i;
static pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
static void *
thread_exit(__unused void *arg)
{
unsigned int count;
sleep(5);
pthread_mutex_lock(&count_lock);
count = ++glob;
pthread_mutex_unlock(&count_lock);
T_QUIET; T_EXPECT_NE(pthread_mach_thread_np(pthread_self()), (mach_port_t)0, NULL);
if (count == THREAD_DEPTH){
T_PASS("all the threads survived main thread exit");
T_END;
}
return NULL;
}
T_DECL(pthread_exit, "pthread_exit", T_META_LTEPHASE(LTE_INSTALLEDUSEROS))
{
int j;
pthread_t th[THREAD_DEPTH];
T_LOG("Creating threads %d..%d", i, i+THREAD_DEPTH-1);
for (j = 0; j < THREAD_DEPTH; j++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
T_QUIET; T_ASSERT_POSIX_SUCCESS(pthread_create(&th[j], &attr, thread_exit, (void *)&glob), NULL);
pthread_attr_destroy(&attr);
}
pthread_exit(pthread_self());
T_FAIL("Zombie walks");
}
static void *
thread_stub(__unused void *arg)
{
return NULL;
}
T_DECL(pthread_exit_private_stacks, "pthread_exit with private stacks",
T_META_CHECK_LEAKS(NO))
{
int j;
pthread_t th[THREAD_DEPTH];
void *stacks[THREAD_DEPTH];
for (j = 0; j < THREAD_DEPTH; j++) {
T_QUIET; T_ASSERT_NOTNULL((stacks[j] = malloc(STACK_SIZE)), NULL);
}
for (i=0;i < 20; i++) {
for (j = 0; j < THREAD_DEPTH; j++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstack(&attr, stacks[j], STACK_SIZE);
T_QUIET; T_ASSERT_POSIX_SUCCESS(pthread_create(&th[j], &attr, thread_stub, (void *)&glob), NULL);
pthread_attr_destroy(&attr);
}
for (j = 0; j < THREAD_DEPTH; j++) {
T_QUIET; T_ASSERT_POSIX_SUCCESS(pthread_join(th[j], NULL), NULL);
}
T_PASS("Created threads %d..%d", i*THREAD_DEPTH, (i+1)*THREAD_DEPTH-1);
}
}
T_DECL(pthread_exit_detached, "pthread_exit with detached threads")
{
int j;
pthread_t th[THREAD_DEPTH];
for (i=0;i < 20; i++) {
for (j = 0; j < THREAD_DEPTH; j++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
T_QUIET; T_ASSERT_POSIX_SUCCESS(pthread_create(&th[j], &attr, thread_stub, (void *)&glob), NULL);
pthread_attr_destroy(&attr);
}
sleep(1);
T_PASS("Created threads %d..%d", i*THREAD_DEPTH, (i+1)*THREAD_DEPTH-1);
}
T_PASS("Success!");
}
static void
key_dtor(void *value)
{
T_ASSERT_EQ(1, pthread_self_is_exiting_np(), "exiting");
}
T_DECL(pthread_self_is_exiting_np, "pthread_self_is_exiting_np")
{
pthread_key_t key;
T_ASSERT_POSIX_ZERO(pthread_key_create(&key, key_dtor), NULL);
pthread_setspecific(key, (void *)-1);
T_ASSERT_EQ(0, pthread_self_is_exiting_np(), "not exiting");
pthread_exit(NULL);
}