thread: implement some properties

Make helper method to parse thread properties and add 2 new properties
to control name and stack-size of the thread.
Use properties when creating threads with the default utils.
Use the default thread utils instead of pthread_create so that the
properties are used.
This commit is contained in:
Wim Taymans 2022-04-18 13:02:27 +02:00
parent 5f7421b946
commit 0b96b87331
7 changed files with 93 additions and 46 deletions

View file

@ -2508,14 +2508,13 @@ static struct spa_thread *impl_create(void *object,
pw_log_info("create thread"); pw_log_info("create thread");
if (globals.creator != NULL) { if (globals.creator != NULL) {
pthread_t pt; pthread_t pt;
pthread_attr_t attributes; pthread_attr_t *attr = NULL, attributes;
pthread_attr_init(&attributes); attr = pw_thread_fill_attr(props, &attributes);
CHECK(pthread_attr_setstacksize(&attributes, THREAD_STACK), error);
res = -globals.creator(&pt, &attributes, start, arg); res = -globals.creator(&pt, attr, start, arg);
if (attr)
pthread_attr_destroy(&attributes); pthread_attr_destroy(attr);
if (res != 0) if (res != 0)
goto error; goto error;
thr = (struct spa_thread*)pt; thr = (struct spa_thread*)pt;

View file

@ -135,6 +135,9 @@ static inline int spa_thread_utils_drop_rt(struct spa_thread_utils *o,
return res; return res;
} }
#define SPA_KEY_THREAD_NAME "thread.name" /* the thread name */
#define SPA_KEY_THREAD_STACK_SIZE "thread.stack-size" /* the stack size of the thread */
/** /**
* \} * \}
*/ */

View file

@ -658,7 +658,7 @@ static struct spa_thread *impl_create(void *object, const struct spa_dict *props
{ {
struct impl *impl = object; struct impl *impl = object;
struct thread *this; struct thread *this;
int err; struct spa_thread *thread;
this = calloc(1, sizeof(*this)); this = calloc(1, sizeof(*this));
this->impl = impl; this->impl = impl;
@ -667,22 +667,22 @@ static struct spa_thread *impl_create(void *object, const struct spa_dict *props
/* This thread list is only used for the RTKit implementation */ /* This thread list is only used for the RTKit implementation */
pthread_mutex_lock(&impl->lock); pthread_mutex_lock(&impl->lock);
err = pthread_create(&this->thread, NULL, custom_start, this); thread = pw_thread_utils_create(props, custom_start, this);
if (err != 0) if (thread == NULL)
goto exit; goto exit;
this->thread = (pthread_t)thread;
pthread_cond_wait(&impl->cond, &impl->lock); pthread_cond_wait(&impl->cond, &impl->lock);
spa_list_append(&impl->threads_list, &this->link); spa_list_append(&impl->threads_list, &this->link);
exit: exit:
pthread_mutex_unlock(&impl->lock); pthread_mutex_unlock(&impl->lock);
if (err != 0) { if (thread == NULL) {
errno = err;
free(this); free(this);
return NULL; return NULL;
} }
return (struct spa_thread*)this->thread; return thread;
} }
static int impl_join(void *object, struct spa_thread *thread, void **retval) static int impl_join(void *object, struct spa_thread *thread, void **retval)
@ -789,20 +789,12 @@ static const struct spa_thread_utils_methods impl_thread_utils = {
static struct spa_thread *impl_create(void *object, const struct spa_dict *props, static struct spa_thread *impl_create(void *object, const struct spa_dict *props,
void *(*start_routine)(void*), void *arg) void *(*start_routine)(void*), void *arg)
{ {
pthread_t pt; return pw_thread_utils_create(props, start_routine, arg);
int err;
err = pthread_create(&pt, NULL, start_routine, arg);
if (err != 0) {
errno = err;
return NULL;
}
return (struct spa_thread*)pt;
} }
static int impl_join(void *object, struct spa_thread *thread, void **retval) static int impl_join(void *object, struct spa_thread *thread, void **retval)
{ {
return pthread_join((pthread_t)thread, retval); return pw_thread_utils_join(thread, retval);
} }
static int impl_get_rt_range(void *object, const struct spa_dict *props, static int impl_get_rt_range(void *object, const struct spa_dict *props,

View file

@ -33,12 +33,9 @@
#include <pipewire/log.h> #include <pipewire/log.h>
#include <pipewire/type.h> #include <pipewire/type.h>
#define DATAS_SIZE (4096 * 8)
PW_LOG_TOPIC_EXTERN(log_loop); PW_LOG_TOPIC_EXTERN(log_loop);
#define PW_LOG_TOPIC_DEFAULT log_loop #define PW_LOG_TOPIC_DEFAULT log_loop
/** \cond */ /** \cond */
struct impl { struct impl {

View file

@ -1290,6 +1290,8 @@ void pw_settings_clean(struct pw_context *context);
void pw_impl_module_schedule_destroy(struct pw_impl_module *module); void pw_impl_module_schedule_destroy(struct pw_impl_module *module);
pthread_attr_t *pw_thread_fill_attr(const struct spa_dict *props, pthread_attr_t *attr);
/** \endcond */ /** \endcond */
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -26,9 +26,11 @@
#include <errno.h> #include <errno.h>
#include <sys/time.h> #include <sys/time.h>
#include <spa/support/thread.h>
#include <spa/utils/result.h> #include <spa/utils/result.h>
#include "log.h" #include "log.h"
#include "thread.h"
#include "thread-loop.h" #include "thread-loop.h"
PW_LOG_TOPIC_EXTERN(log_thread_loop); PW_LOG_TOPIC_EXTERN(log_thread_loop);
@ -38,17 +40,6 @@ PW_LOG_TOPIC_EXTERN(log_thread_loop);
#define pw_thread_loop_events_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_thread_loop_events, m, v, ##__VA_ARGS__) #define pw_thread_loop_events_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_thread_loop_events, m, v, ##__VA_ARGS__)
#define pw_thread_loop_events_destroy(o) pw_thread_loop_events_emit(o, destroy, 0) #define pw_thread_loop_events_destroy(o) pw_thread_loop_events_emit(o, destroy, 0)
#ifdef __FreeBSD__
#include <sys/param.h>
#if __FreeBSD_version < 1202000
int pthread_setname_np(pthread_t thread, const char *name)
{
pthread_set_name_np(thread, name);
return 0;
}
#endif
#endif
/** \cond */ /** \cond */
struct pw_thread_loop { struct pw_thread_loop {
struct pw_loop *loop; struct pw_loop *loop;
@ -282,20 +273,29 @@ static void *do_loop(void *user_data)
SPA_EXPORT SPA_EXPORT
int pw_thread_loop_start(struct pw_thread_loop *loop) int pw_thread_loop_start(struct pw_thread_loop *loop)
{ {
if (!loop->running) {
int err; int err;
if (!loop->running) {
struct spa_thread *thr;
struct spa_dict_item items[1];
loop->running = true; loop->running = true;
if ((err = pthread_create(&loop->thread, NULL, do_loop, loop)) != 0) {
items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_THREAD_NAME, loop->name);
thr = pw_thread_utils_create(&SPA_DICT_INIT_ARRAY(items), do_loop, loop);
if (thr == NULL)
goto error;
loop->thread = (pthread_t)thr;
}
return 0;
error:
err = errno;
pw_log_warn("%p: can't create thread: %s", loop, pw_log_warn("%p: can't create thread: %s", loop,
strerror(err)); strerror(err));
loop->running = false; loop->running = false;
return -err; return -err;
}
if ((err = pthread_setname_np(loop->thread, loop->name)) != 0)
pw_log_warn("%p: error: %s", loop, strerror(err));
}
return 0;
} }
/** Quit the loop and stop its thread /** Quit the loop and stop its thread

View file

@ -27,6 +27,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <pthread.h> #include <pthread.h>
#include <spa/utils/dict.h>
#include <spa/utils/defs.h> #include <spa/utils/defs.h>
#include <spa/utils/list.h> #include <spa/utils/list.h>
@ -34,16 +35,69 @@
#include "thread.h" #include "thread.h"
#define CHECK(expression,label) \
do { \
if ((errno = expression) != 0) { \
res = -errno; \
pw_log_error(#expression ": %s", strerror(errno)); \
goto label; \
} \
} while(false);
SPA_EXPORT
pthread_attr_t *pw_thread_fill_attr(const struct spa_dict *props, pthread_attr_t *attr)
{
const char *str;
int res;
if (props == NULL)
return NULL;
pthread_attr_init(attr);
if ((str = spa_dict_lookup(props, SPA_KEY_THREAD_STACK_SIZE)) != NULL)
CHECK(pthread_attr_setstacksize(attr, atoi(str)), error);
return attr;
error:
errno = -res;
return NULL;
}
#ifdef __FreeBSD__
#include <sys/param.h>
#if __FreeBSD_version < 1202000
int pthread_setname_np(pthread_t thread, const char *name)
{
pthread_set_name_np(thread, name);
return 0;
}
#endif
#endif
static struct spa_thread *impl_create(void *object, static struct spa_thread *impl_create(void *object,
const struct spa_dict *props, const struct spa_dict *props,
void *(*start)(void*), void *arg) void *(*start)(void*), void *arg)
{ {
pthread_t pt; pthread_t pt;
pthread_attr_t *attr = NULL, attributes;
const char *str;
int err; int err;
if ((err = pthread_create(&pt, NULL, start, arg)) != 0) {
attr = pw_thread_fill_attr(props, &attributes);
err = pthread_create(&pt, attr, start, arg);
if (attr)
pthread_attr_destroy(attr);
if (err != 0) {
errno = err; errno = err;
return NULL; return NULL;
} }
if (props) {
if ((str = spa_dict_lookup(props, SPA_KEY_THREAD_NAME)) != NULL &&
(err = pthread_setname_np(pt, str)) != 0)
pw_log_warn("pthread_setname error: %s", strerror(err));
}
return (struct spa_thread*)pt; return (struct spa_thread*)pt;
} }