mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	jack: make a custom thread-utils
Make a custom thread_utils that can use the configured global thread creator and set this in the data-loop. This ensure that the data loop uses the creator thread when activated. See #1495
This commit is contained in:
		
							parent
							
								
									d306786012
								
							
						
					
					
						commit
						6041d939a0
					
				
					 1 changed files with 83 additions and 34 deletions
				
			
		| 
						 | 
					@ -2486,6 +2486,77 @@ static const struct pw_client_node_events client_node_events = {
 | 
				
			||||||
	.port_set_mix_info = client_node_port_set_mix_info,
 | 
						.port_set_mix_info = client_node_port_set_mix_info,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CHECK(expression,label)						\
 | 
				
			||||||
 | 
					do {									\
 | 
				
			||||||
 | 
						if ((errno = expression) != 0) {				\
 | 
				
			||||||
 | 
							res = -errno;						\
 | 
				
			||||||
 | 
							pw_log_error(#expression ": %s", strerror(errno));	\
 | 
				
			||||||
 | 
							goto label;						\
 | 
				
			||||||
 | 
						}								\
 | 
				
			||||||
 | 
					} while(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct spa_thread *impl_create(void *data,
 | 
				
			||||||
 | 
								const struct spa_dict *props,
 | 
				
			||||||
 | 
								void *(*start)(void*), void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct spa_thread *thr;
 | 
				
			||||||
 | 
						int res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_log_info("create thread");
 | 
				
			||||||
 | 
						if (globals.creator != NULL) {
 | 
				
			||||||
 | 
							pthread_t pt;
 | 
				
			||||||
 | 
							pthread_attr_t attributes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pthread_attr_init(&attributes);
 | 
				
			||||||
 | 
							CHECK(pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE), error);
 | 
				
			||||||
 | 
							CHECK(pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM), error);
 | 
				
			||||||
 | 
							CHECK(pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED), error);
 | 
				
			||||||
 | 
							CHECK(pthread_attr_setstacksize(&attributes, THREAD_STACK), error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							res = -globals.creator(&pt, &attributes, start, arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pthread_attr_destroy(&attributes);
 | 
				
			||||||
 | 
							if (res != 0)
 | 
				
			||||||
 | 
								goto error;
 | 
				
			||||||
 | 
							thr = (struct spa_thread*)pt;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							thr = pw_thread_utils_create(NULL, start, arg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return thr;
 | 
				
			||||||
 | 
					error:
 | 
				
			||||||
 | 
						pw_log_warn("create RT thread failed: %s", strerror(res));
 | 
				
			||||||
 | 
						errno = -res;
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int impl_join(void *d,
 | 
				
			||||||
 | 
							struct spa_thread *thread, void **retval)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						pw_log_info("join thread");
 | 
				
			||||||
 | 
						return pw_thread_utils_join(thread, retval);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int impl_acquire_rt(void *data, struct spa_thread *thread, int priority)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return pw_thread_utils_acquire_rt(thread, priority);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct {
 | 
				
			||||||
 | 
						struct spa_thread_utils utils;
 | 
				
			||||||
 | 
						struct spa_thread_utils_methods methods;
 | 
				
			||||||
 | 
					} thread_utils_impl = {
 | 
				
			||||||
 | 
						{ { SPA_TYPE_INTERFACE_ThreadUtils,
 | 
				
			||||||
 | 
							SPA_VERSION_THREAD_UTILS,
 | 
				
			||||||
 | 
							SPA_CALLBACKS_INIT(&thread_utils_impl.methods,
 | 
				
			||||||
 | 
									&thread_utils_impl) } },
 | 
				
			||||||
 | 
						{ SPA_VERSION_THREAD_UTILS_METHODS,
 | 
				
			||||||
 | 
							.create = impl_create,
 | 
				
			||||||
 | 
							.join = impl_join,
 | 
				
			||||||
 | 
							.acquire_rt = impl_acquire_rt,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static jack_port_type_id_t string_to_type(const char *port_type)
 | 
					static jack_port_type_id_t string_to_type(const char *port_type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (spa_streq(JACK_DEFAULT_AUDIO_TYPE, port_type))
 | 
						if (spa_streq(JACK_DEFAULT_AUDIO_TYPE, port_type))
 | 
				
			||||||
| 
						 | 
					@ -3208,6 +3279,7 @@ jack_client_t * jack_client_open (const char *client_name,
 | 
				
			||||||
	client->loop = client->context.context->data_loop_impl;
 | 
						client->loop = client->context.context->data_loop_impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_data_loop_stop(client->loop);
 | 
						pw_data_loop_stop(client->loop);
 | 
				
			||||||
 | 
						pw_data_loop_set_thread_utils(client->loop, &thread_utils_impl.utils);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_init(&client->links);
 | 
						spa_list_init(&client->links);
 | 
				
			||||||
	spa_list_init(&client->rt.target_links);
 | 
						spa_list_init(&client->rt.target_links);
 | 
				
			||||||
| 
						 | 
					@ -5972,15 +6044,6 @@ int jack_client_max_real_time_priority (jack_client_t *client)
 | 
				
			||||||
	return SPA_MIN(max, c->rt_max) - 1;
 | 
						return SPA_MIN(max, c->rt_max) - 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHECK(expression,label)						\
 | 
					 | 
				
			||||||
do {									\
 | 
					 | 
				
			||||||
	if ((errno = expression) != 0) {				\
 | 
					 | 
				
			||||||
		res = -errno;						\
 | 
					 | 
				
			||||||
		pw_log_error(#expression ": %s", strerror(errno));	\
 | 
					 | 
				
			||||||
		goto label;						\
 | 
					 | 
				
			||||||
	}								\
 | 
					 | 
				
			||||||
} while(false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SPA_EXPORT
 | 
					SPA_EXPORT
 | 
				
			||||||
int jack_acquire_real_time_scheduling (jack_native_thread_t thread, int priority)
 | 
					int jack_acquire_real_time_scheduling (jack_native_thread_t thread, int priority)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -6020,41 +6083,27 @@ int jack_client_create_thread (jack_client_t* client,
 | 
				
			||||||
                               void *arg)
 | 
					                               void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int res = 0;
 | 
						int res = 0;
 | 
				
			||||||
 | 
						struct spa_thread *thr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_return_val_if_fail(client != NULL, -EINVAL);
 | 
						spa_return_val_if_fail(client != NULL, -EINVAL);
 | 
				
			||||||
 | 
						spa_return_val_if_fail(thread != NULL, -EINVAL);
 | 
				
			||||||
 | 
						spa_return_val_if_fail(start_routine != NULL, -EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info("client %p: create thread rt:%d prio:%d", client, realtime, priority);
 | 
						pw_log_info("client %p: create thread rt:%d prio:%d", client, realtime, priority);
 | 
				
			||||||
	if (globals.creator != NULL) {
 | 
					 | 
				
			||||||
		pthread_attr_t attributes;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pthread_attr_init(&attributes);
 | 
						thr = spa_thread_utils_create(&thread_utils_impl.utils, NULL, start_routine, arg);
 | 
				
			||||||
		CHECK(pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE), error);
 | 
						if (thr == NULL)
 | 
				
			||||||
		CHECK(pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM), error);
 | 
							res = -errno;
 | 
				
			||||||
		CHECK(pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED), error);
 | 
						*thread = (pthread_t)thr;
 | 
				
			||||||
		CHECK(pthread_attr_setstacksize(&attributes, THREAD_STACK), error);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		res = globals.creator(thread, &attributes, start_routine, arg);
 | 
						if (res != 0) {
 | 
				
			||||||
 | 
							pw_log_warn("client %p: create RT thread failed: %s",
 | 
				
			||||||
		pthread_attr_destroy(&attributes);
 | 
									client, strerror(res));
 | 
				
			||||||
	} else {
 | 
						} else if (realtime) {
 | 
				
			||||||
		struct spa_thread *thr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		thr = pw_thread_utils_create(NULL, start_routine, arg);
 | 
					 | 
				
			||||||
		if (thr == NULL)
 | 
					 | 
				
			||||||
			res = -errno;
 | 
					 | 
				
			||||||
		*thread = (pthread_t)thr;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (res == 0 && realtime) {
 | 
					 | 
				
			||||||
		/* Try to acquire RT scheduling, we don't fail here but the
 | 
							/* Try to acquire RT scheduling, we don't fail here but the
 | 
				
			||||||
		 * function will emit a warning. Real JACK fails here. */
 | 
							 * function will emit a warning. Real JACK fails here. */
 | 
				
			||||||
		jack_acquire_real_time_scheduling(*thread, priority);
 | 
							jack_acquire_real_time_scheduling(*thread, priority);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
error:
 | 
					 | 
				
			||||||
	if (res != 0)
 | 
					 | 
				
			||||||
		pw_log_warn("client %p: create RT thread failed: %s",
 | 
					 | 
				
			||||||
				client, strerror(res));
 | 
					 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue