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");
if (globals.creator != NULL) {
pthread_t pt;
pthread_attr_t attributes;
pthread_attr_t *attr = NULL, attributes;
pthread_attr_init(&attributes);
CHECK(pthread_attr_setstacksize(&attributes, THREAD_STACK), error);
attr = pw_thread_fill_attr(props, &attributes);
res = -globals.creator(&pt, &attributes, start, arg);
pthread_attr_destroy(&attributes);
res = -globals.creator(&pt, attr, start, arg);
if (attr)
pthread_attr_destroy(attr);
if (res != 0)
goto error;
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;
}
#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 thread *this;
int err;
struct spa_thread *thread;
this = calloc(1, sizeof(*this));
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 */
pthread_mutex_lock(&impl->lock);
err = pthread_create(&this->thread, NULL, custom_start, this);
if (err != 0)
thread = pw_thread_utils_create(props, custom_start, this);
if (thread == NULL)
goto exit;
this->thread = (pthread_t)thread;
pthread_cond_wait(&impl->cond, &impl->lock);
spa_list_append(&impl->threads_list, &this->link);
exit:
pthread_mutex_unlock(&impl->lock);
if (err != 0) {
errno = err;
if (thread == NULL) {
free(this);
return NULL;
}
return (struct spa_thread*)this->thread;
return thread;
}
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,
void *(*start_routine)(void*), void *arg)
{
pthread_t pt;
int err;
err = pthread_create(&pt, NULL, start_routine, arg);
if (err != 0) {
errno = err;
return NULL;
}
return (struct spa_thread*)pt;
return pw_thread_utils_create(props, start_routine, arg);
}
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,

View file

@ -33,12 +33,9 @@
#include <pipewire/log.h>
#include <pipewire/type.h>
#define DATAS_SIZE (4096 * 8)
PW_LOG_TOPIC_EXTERN(log_loop);
#define PW_LOG_TOPIC_DEFAULT log_loop
/** \cond */
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);
pthread_attr_t *pw_thread_fill_attr(const struct spa_dict *props, pthread_attr_t *attr);
/** \endcond */
#ifdef __cplusplus

View file

@ -26,9 +26,11 @@
#include <errno.h>
#include <sys/time.h>
#include <spa/support/thread.h>
#include <spa/utils/result.h>
#include "log.h"
#include "thread.h"
#include "thread-loop.h"
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_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 */
struct pw_thread_loop {
struct pw_loop *loop;
@ -282,20 +273,29 @@ static void *do_loop(void *user_data)
SPA_EXPORT
int pw_thread_loop_start(struct pw_thread_loop *loop)
{
int err;
if (!loop->running) {
int err;
struct spa_thread *thr;
struct spa_dict_item items[1];
loop->running = true;
if ((err = pthread_create(&loop->thread, NULL, do_loop, loop)) != 0) {
pw_log_warn("%p: can't create thread: %s", loop,
strerror(err));
loop->running = false;
return -err;
}
if ((err = pthread_setname_np(loop->thread, loop->name)) != 0)
pw_log_warn("%p: error: %s", loop, strerror(err));
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,
strerror(err));
loop->running = false;
return -err;
}
/** Quit the loop and stop its thread

View file

@ -27,6 +27,7 @@
#include <sys/types.h>
#include <pthread.h>
#include <spa/utils/dict.h>
#include <spa/utils/defs.h>
#include <spa/utils/list.h>
@ -34,16 +35,69 @@
#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,
const struct spa_dict *props,
void *(*start)(void*), void *arg)
{
pthread_t pt;
pthread_attr_t *attr = NULL, attributes;
const char *str;
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;
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;
}