libclod
C library for interacting with NBTs, region files, LOD data and other things.
Loading...
Searching...
No Matches
thread_pthread.c
1#include "clod_thread_config.h"
2#include "thread_impl.h"
3#include <pthread.h>
4#include <stdlib.h>
5#include <errno.h>
6#include <stdio.h>
7
9 struct clod_process_common common;
10 pthread_t thread;
11};
12
14 clod_process_main *main;
15};
16
17void *clod_process_pthread_main(void *ptr) {
18 struct thread_args *thread_args = ptr;
19 auto args = (struct clod_process_args *)((char*)ptr + ALIGN(sizeof(struct thread_args), 16));
20 thread_args->main(args->arg_count, args->arg_vector);
21 free(thread_args);
22 return nullptr;
23}
24
25enum clod_process_result clod_process_start_pthread(
26 struct clod_process_opts *opts,
27 struct clod_process_common **process_out
28) {
29 if (!opts->main) {
30 #if CLOD_DEBUG_THREAD
31 fprintf(stderr, "libclod: clod_process_start_pthread: no thread main function given.\n");
32 #endif
33 return CLOD_PROCESS_INVALID;
34 }
35 if (opts->type != CLOD_THREAD) {
36 #if CLOD_DEBUG_THREAD
37 fprintf(stderr, "libclod: clod_process_start_pthread: given %d, but only CLOD_THREAD (1) is supported here.\n", opts->type);
38 #endif
39 return CLOD_PROCESS_INVALID;
40 }
41
42 struct clod_process_args args_in = {
43 .arg_count = opts->arg_count,
44 .arg_sizes = opts->arg_sizes,
45 .arg_vector = opts->arg_vector
46 };
47
48 char *data = malloc(ALIGN(sizeof(struct thread_args), 16) + args_size(&args_in));
49 auto thread_args = (struct thread_args *)data;
50 auto args = (struct clod_process_args *)(data + ALIGN(sizeof(struct thread_args), 16));
51
52 thread_args->main = opts->main;
53 args_copy(args, &args_in);
54
55 pthread_attr_t attr;
56 pthread_attr_init(&attr);
57 pthread_attr_setdetachstate(&attr, process_out ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
58 if (opts->stack_size)
59 pthread_attr_setstacksize(&attr, opts->stack_size);
60
61 pthread_t thread;
62 const int res = pthread_create(&thread, &attr, clod_process_pthread_main, data);
63 if (res != 0) {
64 free(data);
65 #if CLOD_DEBUG_THREAD
66 fprintf(stderr, "libclod: pthread_create: %d\n", res);
67 #endif
68 if (errno == EAGAIN) return CLOD_PROCESS_NO_MEMORY;
69 return CLOD_PROCESS_INVALID;
70 }
71
72 if (process_out) {
73 struct clod_process_pthread *process = malloc(sizeof(struct clod_process_pthread));
74 process->common.type = CLOD_THREAD;
75 process->thread = thread;
76 *process_out = &process->common;
77 } else {
78 pthread_detach(thread);
79 }
80
81 return CLOD_PROCESS_OK;
82}
83
84enum clod_process_result clod_process_join_pthread(struct clod_process_common *process) {
85 auto pthread_process = (struct clod_process_pthread*)process;
86 const int res = pthread_join(pthread_process->thread, nullptr);
87 free(pthread_process);
88 if (res != 0) return CLOD_PROCESS_INVALID;
89 return CLOD_PROCESS_OK;
90}
@ CLOD_THREAD
Definition thread.h:32
clod_process_main * main
Process entry point.
Definition thread.h:84
int arg_count
Number of arguments passed to main.
Definition thread.h:87
char ** arg_vector
Definition thread.h:91
size_t * arg_sizes
Definition thread.h:95
size_t stack_size
Definition thread.h:81
enum clod_process_type type
Type of process to create.
Definition thread.h:77