summaryrefslogtreecommitdiff
path: root/Userland/tt.cpp
diff options
context:
space:
mode:
authorAndrew Kaster <andrewdkaster@gmail.com>2019-11-17 20:08:10 -0700
committerAndreas Kling <awesomekling@gmail.com>2019-11-18 09:04:32 +0100
commit618aebdd8ab55f9b63256e8195fa4e0f6fe305aa (patch)
treec076bbff894ee4f0151ae91049d62bad1e499d32 /Userland/tt.cpp
parentaae26a3a1ec059ca16cb7930f4f78b908ec6e8a1 (diff)
downloadserenity-618aebdd8ab55f9b63256e8195fa4e0f6fe305aa.zip
Kernel+LibPthread: pthread_create handles pthread_attr_t
Add an initial implementation of pthread attributes for: * detach state (joinable, detached) * schedule params (just priority) * guard page size (as skeleton) (requires kernel support maybe?) * stack size and user-provided stack location (4 or 8 MB only, must be aligned) Add some tests too, to the thread test program. Also, LibC: Move pthread declarations to sys/types.h, where they belong.
Diffstat (limited to 'Userland/tt.cpp')
-rw-r--r--Userland/tt.cpp254
1 files changed, 253 insertions, 1 deletions
diff --git a/Userland/tt.cpp b/Userland/tt.cpp
index 2823a19103..ea966ce8cb 100644
--- a/Userland/tt.cpp
+++ b/Userland/tt.cpp
@@ -1,14 +1,28 @@
+#include <mman.h>
#include <pthread.h>
#include <stdio.h>
-#include <unistd.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
static int mutex_test();
+static int detached_test();
+static int priority_test();
+static int stack_size_test();
+static int set_stack_test();
int main(int argc, char** argv)
{
if (argc == 2 && *argv[1] == 'm')
return mutex_test();
+ if (argc == 2 && *argv[1] == 'd')
+ return detached_test();
+ if (argc == 2 && *argv[1] == 'p')
+ return priority_test();
+ if (argc == 2 && *argv[1] == 's')
+ return stack_size_test();
+ if (argc == 2 && *argv[1] == 'x')
+ return set_stack_test();
printf("Hello from the first thread!\n");
pthread_t thread_id;
@@ -70,3 +84,241 @@ int mutex_test()
}
return 0;
}
+
+int detached_test()
+{
+ pthread_attr_t attributes;
+ int rc = pthread_attr_init(&attributes);
+ if (rc != 0) {
+ printf("pthread_attr_setdetachstate: %s\n", strerror(rc));
+ return 1;
+ }
+
+ int detach_state = 99; // clearly invalid
+ rc = pthread_attr_getdetachstate(&attributes, &detach_state);
+ if (rc != 0) {
+ printf("pthread_attr_setdetachstate: %s\n", strerror(rc));
+ return 2;
+ }
+ printf("Default detach state: %s\n", detach_state == PTHREAD_CREATE_JOINABLE ? "joinable" : "detached");
+
+ detach_state = PTHREAD_CREATE_DETACHED;
+ rc = pthread_attr_setdetachstate(&attributes, detach_state);
+ if (rc != 0) {
+ printf("pthread_attr_setdetachstate: %s\n", strerror(rc));
+ return 3;
+ }
+ printf("Set detach state on new thread to detached\n");
+
+ pthread_t thread_id;
+ rc = pthread_create(
+ &thread_id, &attributes, [](void*) -> void* {
+ printf("I'm the secondary thread :^)\n");
+ sleep(1);
+ pthread_exit((void*)0xDEADBEEF);
+ return nullptr;
+ },
+ nullptr);
+ if (rc < 0) {
+ perror("pthread_create");
+ return 4;
+ }
+
+ void* ret_val;
+ errno = 0;
+ rc = pthread_join(thread_id, &ret_val);
+ if (rc < 0 && errno != EINVAL) {
+ perror("pthread_join");
+ return 5;
+ }
+ if (errno != EINVAL) {
+ printf("Expected EINVAL! Thread was joinable?\n");
+ return 6;
+ }
+
+ sleep(2);
+ printf("Thread was created detached. I sure hope it exited on its own.\n");
+
+ rc = pthread_attr_destroy(&attributes);
+ if (rc != 0) {
+ printf("pthread_attr_setdetachstate: %s\n", strerror(rc));
+ return 7;
+ }
+
+ return 0;
+}
+
+int priority_test()
+{
+ pthread_attr_t attributes;
+ int rc = pthread_attr_init(&attributes);
+ if (rc != 0) {
+ printf("pthread_attr_init: %s\n", strerror(rc));
+ return 1;
+ }
+
+ struct sched_param sched_params;
+ rc = pthread_attr_getschedparam(&attributes, &sched_params);
+ if (rc != 0) {
+ printf("pthread_attr_getschedparam: %s\n", strerror(rc));
+ return 2;
+ }
+ printf("Default priority: %d\n", sched_params.sched_priority);
+
+ sched_params.sched_priority = 3;
+ rc = pthread_attr_setschedparam(&attributes, &sched_params);
+ if (rc != 0) {
+ printf("pthread_attr_setschedparam: %s\n", strerror(rc));
+ return 3;
+ }
+ printf("Set thread priority to 3\n");
+
+ pthread_t thread_id;
+ rc = pthread_create(
+ &thread_id, &attributes, [](void*) -> void* {
+ printf("I'm the secondary thread :^)\n");
+ sleep(1);
+ pthread_exit((void*)0xDEADBEEF);
+ return nullptr;
+ },
+ nullptr);
+ if (rc < 0) {
+ perror("pthread_create");
+ return 4;
+ }
+
+ rc = pthread_join(thread_id, nullptr);
+ if (rc < 0) {
+ perror("pthread_join");
+ return 5;
+ }
+
+ rc = pthread_attr_destroy(&attributes);
+ if (rc != 0) {
+ printf("pthread_attr_destroy: %s\n", strerror(rc));
+ return 6;
+ }
+
+ return 0;
+}
+
+int stack_size_test()
+{
+ pthread_attr_t attributes;
+ int rc = pthread_attr_init(&attributes);
+ if (rc != 0) {
+ printf("pthread_attr_init: %s\n", strerror(rc));
+ return 1;
+ }
+
+ size_t stack_size;
+ rc = pthread_attr_getstacksize(&attributes, &stack_size);
+ if (rc != 0) {
+ printf("pthread_attr_getstacksize: %s\n", strerror(rc));
+ return 2;
+ }
+ printf("Default stack size: %zu\n", stack_size);
+
+ stack_size = 8 * 1024 * 1024;
+ rc = pthread_attr_setstacksize(&attributes, stack_size);
+ if (rc != 0) {
+ printf("pthread_attr_setstacksize: %s\n", strerror(rc));
+ return 3;
+ }
+ printf("Set thread stack size to 8 MB\n");
+
+ pthread_t thread_id;
+ rc = pthread_create(
+ &thread_id, &attributes, [](void*) -> void* {
+ printf("I'm the secondary thread :^)\n");
+ sleep(1);
+ pthread_exit((void*)0xDEADBEEF);
+ return nullptr;
+ },
+ nullptr);
+ if (rc < 0) {
+ perror("pthread_create");
+ return 4;
+ }
+
+ rc = pthread_join(thread_id, nullptr);
+ if (rc < 0) {
+ perror("pthread_join");
+ return 5;
+ }
+
+ rc = pthread_attr_destroy(&attributes);
+ if (rc != 0) {
+ printf("pthread_attr_destroy: %s\n", strerror(rc));
+ return 6;
+ }
+
+ return 0;
+}
+
+int set_stack_test()
+{
+ pthread_attr_t attributes;
+ int rc = pthread_attr_init(&attributes);
+ if (rc < 0) {
+ printf("pthread_attr_init: %s\n", strerror(rc));
+ return 1;
+ }
+
+ size_t stack_size = 8 * 1024 * 1024;
+ void* stack_addr = mmap_with_name(nullptr, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 0, 0, "Cool stack");
+
+ if (!stack_addr) {
+ perror("mmap_with_name");
+ return -1;
+ }
+
+ rc = pthread_attr_setstack(&attributes, stack_addr, stack_size);
+ if (rc != 0) {
+ printf("pthread_attr_setstack: %s\n", strerror(rc));
+ return 2;
+ }
+ printf("Set thread stack to %p, size %zu\n", stack_addr, stack_size);
+
+ size_t stack_size_verify;
+ void* stack_addr_verify;
+
+ rc = pthread_attr_getstack(&attributes, &stack_addr_verify, &stack_size_verify);
+ if (rc != 0) {
+ printf("pthread_attr_getstack: %s\n", strerror(rc));
+ return 3;
+ }
+
+ if (stack_addr != stack_addr_verify || stack_size != stack_size_verify) {
+ printf("Stack address and size don't match! addr: %p %p, size: %zu %zu\n", stack_addr, stack_addr_verify, stack_size, stack_size_verify);
+ return 4;
+ }
+
+ pthread_t thread_id;
+ rc = pthread_create(
+ &thread_id, &attributes, [](void*) -> void* {
+ printf("I'm the secondary thread :^)\n");
+ sleep(1);
+ pthread_exit((void*)0xDEADBEEF);
+ return nullptr;
+ },
+ nullptr);
+ if (rc < 0) {
+ perror("pthread_create");
+ return 5;
+ }
+
+ rc = pthread_join(thread_id, nullptr);
+ if (rc < 0) {
+ perror("pthread_join");
+ return 6;
+ }
+
+ rc = pthread_attr_destroy(&attributes);
+ if (rc != 0) {
+ printf("pthread_attr_destroy: %s\n", strerror(rc));
+ return 7;
+ }
+
+ return 0;
+}