diff options
author | Henrik Gramner <gramner@twoorioles.com> | 2019-05-03 16:01:04 +0300 |
---|---|---|
committer | Henrik Gramner <henrik@gramner.com> | 2019-05-04 22:58:02 +0300 |
commit | 2756254fc6ba402c5b6ab345944d0878975ed715 (patch) | |
tree | ace10546f1201c056478f58492e9cc867c9964c6 | |
parent | 1d5c1a493742503838b12f108e041644d4838656 (diff) |
Control the stack size of spawned threads
On some systems (e.g. Google Fuchsia) the default stack size of new
threads is insufficient, resulting in crashes.
On other systems the default stack size is unnecessarily large,
which can waste a lot of virtual memory.
By setting it to a sufficiently large fixed value we can ensure that
we don't run out of stack space while keeping down memory usage.
-rw-r--r-- | src/lib.c | 11 | ||||
-rw-r--r-- | src/thread.h | 22 | ||||
-rw-r--r-- | src/win32/thread.c | 8 |
3 files changed, 35 insertions, 6 deletions
@@ -90,6 +90,10 @@ int dav1d_open(Dav1dContext **const c_out, validate_input_or_ret(s->operating_point >= 0 && s->operating_point <= 31, -EINVAL); + pthread_attr_t thread_attr; + if (pthread_attr_init(&thread_attr)) return -ENOMEM; + pthread_attr_setstacksize(&thread_attr, 512 * 1024); + Dav1dContext *const c = *c_out = dav1d_alloc_aligned(sizeof(*c), 32); if (!c) goto error; memset(c, 0, sizeof(*c)); @@ -151,7 +155,7 @@ int dav1d_open(Dav1dContext **const c_out, goto error; } t->tile_thread.fttd = &f->tile_thread; - if (pthread_create(&t->tile_thread.td.thread, NULL, dav1d_tile_task, t)) { + if (pthread_create(&t->tile_thread.td.thread, &thread_attr, dav1d_tile_task, t)) { pthread_cond_destroy(&t->tile_thread.td.cond); pthread_mutex_destroy(&t->tile_thread.td.lock); goto error; @@ -167,7 +171,7 @@ int dav1d_open(Dav1dContext **const c_out, pthread_mutex_destroy(&f->frame_thread.td.lock); goto error; } - if (pthread_create(&f->frame_thread.td.thread, NULL, dav1d_frame_task, f)) { + if (pthread_create(&f->frame_thread.td.thread, &thread_attr, dav1d_frame_task, f)) { pthread_cond_destroy(&f->frame_thread.td.cond); pthread_mutex_destroy(&f->frame_thread.td.lock); goto error; @@ -182,10 +186,13 @@ int dav1d_open(Dav1dContext **const c_out, c->intra_edge.root[BL_64X64] = &c->intra_edge.branch_sb64[0].node; dav1d_init_mode_tree(c->intra_edge.root[BL_64X64], c->intra_edge.tip_sb64, 0); + pthread_attr_destroy(&thread_attr); + return 0; error: if (c) close_internal(c_out, 0); + pthread_attr_destroy(&thread_attr); return -ENOMEM; } diff --git a/src/thread.h b/src/thread.h index f8da628..b2529fc 100644 --- a/src/thread.h +++ b/src/thread.h @@ -40,11 +40,15 @@ typedef struct { void *arg; } pthread_t; +typedef struct { + unsigned stack_size; +} pthread_attr_t; + typedef SRWLOCK pthread_mutex_t; typedef CONDITION_VARIABLE pthread_cond_t; typedef INIT_ONCE pthread_once_t; -int dav1d_pthread_create(pthread_t *thread, const void *attr, +int dav1d_pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*func)(void*), void *arg); int dav1d_pthread_join(pthread_t *thread, void **res); int dav1d_pthread_once(pthread_once_t *once_control, @@ -54,6 +58,22 @@ int dav1d_pthread_once(pthread_once_t *once_control, #define pthread_join(thread, res) dav1d_pthread_join(&(thread), res) #define pthread_once dav1d_pthread_once +static inline int pthread_attr_init(pthread_attr_t *const attr) { + attr->stack_size = 0; + return 0; +} + +static inline int pthread_attr_destroy(pthread_attr_t *const attr) { + return 0; +} + +static inline int pthread_attr_setstacksize(pthread_attr_t *const attr, + const unsigned stack_size) +{ + attr->stack_size = stack_size; + return 0; +} + static inline int pthread_mutex_init(pthread_mutex_t *const mutex, const void *const attr) { diff --git a/src/win32/thread.c b/src/win32/thread.c index c3fb557..2c2a578 100644 --- a/src/win32/thread.c +++ b/src/win32/thread.c @@ -41,13 +41,15 @@ static unsigned __stdcall thread_entrypoint(void *const data) { return 0; } -int dav1d_pthread_create(pthread_t *const thread, const void *const attr, +int dav1d_pthread_create(pthread_t *const thread, + const pthread_attr_t *const attr, void *(*const func)(void*), void *const arg) { + const unsigned stack_size = attr ? attr->stack_size : 0; thread->func = func; thread->arg = arg; - thread->h = (HANDLE)_beginthreadex(NULL, 0, thread_entrypoint, - thread, 0, NULL); + thread->h = (HANDLE)_beginthreadex(NULL, stack_size, thread_entrypoint, thread, + STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); return !thread->h; } |