| #define _GNU_SOURCE |
| #include <assert.h> |
| #include <errno.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <threads.h> |
| #include <pthread.h> |
| |
| static void cleanup (void* arg) { |
| printf("cleanup: %ld\n", (intptr_t)arg); |
| } |
| |
| int start(void* arg) { |
| assert(0); |
| return 0; |
| } |
| |
| void* start_pthread(void* arg) { |
| assert(0); |
| return NULL; |
| } |
| |
| #define CHECK(X, EXPECTED) rtn = X; if (rtn != EXPECTED) printf(#X " returned %s\n", strerror(rtn)); assert(rtn == EXPECTED) |
| #define CHECK_FAIL(X) CHECK(X, ENOTSUP) |
| #define CHECK_SUCCESS(X) CHECK(X, 0) |
| |
| #define CHECK_C11(X, expected) rtn = X; if (rtn != expected) printf(#X " returned %d\n", rtn); assert(rtn == expected) |
| #define CHECK_C11_SUCCESS(X) CHECK_C11(X, thrd_success) |
| #define CHECK_C11_FAIL(X) CHECK_C11(X, thrd_error) |
| |
| void test_c11_threads() { |
| printf("test_c11_threads\n"); |
| int rtn; |
| int res; |
| |
| thrd_t thread; |
| CHECK_C11_FAIL(thrd_create(&thread, start, NULL)); |
| // FIXME(sbc): Bug in thrd_join.c ignored pthread_join return code |
| //CHECK_C11_FAIL(thrd_join(thread, &res)); |
| |
| mtx_t mutex; |
| CHECK_C11_SUCCESS(mtx_init(&mutex, mtx_plain)); |
| |
| cnd_t cond; |
| CHECK_C11_SUCCESS(cnd_init(&cond)); |
| } |
| |
| void test_pthreads() { |
| printf("test_pthreads\n"); |
| int rtn; |
| int res; |
| |
| printf("__builtin_thread_pointer non-null: %d\n", __builtin_thread_pointer() != NULL); |
| |
| // pthread_atfork should silently succeed. |
| CHECK_SUCCESS(pthread_atfork(NULL, NULL, NULL)); |
| |
| pthread_t thread; |
| CHECK_FAIL(pthread_create(&thread, NULL, start_pthread, NULL)); |
| |
| // Thread cleanup push/pop should still work for the main thread |
| pthread_cleanup_push(cleanup, (void*)42); |
| pthread_cleanup_pop(1); |
| } |
| |
| void test_pthread_getattr_np() { |
| printf("test_pthread_getattr_np\n"); |
| int rtn; |
| pthread_attr_t attr; |
| size_t stack_size, guard_size; |
| void *stack_addr; |
| |
| CHECK_SUCCESS(pthread_getattr_np(pthread_self(), &attr)); |
| CHECK_SUCCESS(pthread_attr_getguardsize(&attr, &guard_size)); |
| CHECK_SUCCESS(pthread_attr_getstack(&attr, &stack_addr, &stack_size)); |
| CHECK_SUCCESS(pthread_attr_destroy(&attr)); |
| printf("stack_addr: %p, stack_size: %zu, guard_size: %zu\n", stack_addr, stack_size, guard_size); |
| } |
| |
| int main() { |
| test_c11_threads(); |
| test_pthreads(); |
| test_pthread_getattr_np(); |
| return 0; |
| } |