153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 553a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 653a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 753a5a1b3Sopenharmony_ci or (at your option) any later version. 853a5a1b3Sopenharmony_ci 953a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1053a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1153a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1253a5a1b3Sopenharmony_ci General Public License for more details. 1353a5a1b3Sopenharmony_ci 1453a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1553a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1653a5a1b3Sopenharmony_ci***/ 1753a5a1b3Sopenharmony_ci 1853a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 1953a5a1b3Sopenharmony_ci#include <config.h> 2053a5a1b3Sopenharmony_ci#endif 2153a5a1b3Sopenharmony_ci 2253a5a1b3Sopenharmony_ci#include <stdlib.h> 2353a5a1b3Sopenharmony_ci#include <unistd.h> 2453a5a1b3Sopenharmony_ci#include <stdio.h> 2553a5a1b3Sopenharmony_ci 2653a5a1b3Sopenharmony_ci#include <check.h> 2753a5a1b3Sopenharmony_ci 2853a5a1b3Sopenharmony_ci#include <pulse/rtclock.h> 2953a5a1b3Sopenharmony_ci#include <pulse/timeval.h> 3053a5a1b3Sopenharmony_ci#include <pulse/util.h> 3153a5a1b3Sopenharmony_ci#include <pulse/thread-mainloop.h> 3253a5a1b3Sopenharmony_ci 3353a5a1b3Sopenharmony_ci#include <pulsecore/core-rtclock.h> 3453a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3553a5a1b3Sopenharmony_ci#include <pulsecore/mutex.h> 3653a5a1b3Sopenharmony_ci 3753a5a1b3Sopenharmony_cistatic void tcb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *tv, void *userdata) { 3853a5a1b3Sopenharmony_ci pa_assert_se(pa_threaded_mainloop_in_thread(userdata)); 3953a5a1b3Sopenharmony_ci fprintf(stderr, "TIME EVENT START\n"); 4053a5a1b3Sopenharmony_ci pa_threaded_mainloop_signal(userdata, 1); 4153a5a1b3Sopenharmony_ci fprintf(stderr, "TIME EVENT END\n"); 4253a5a1b3Sopenharmony_ci} 4353a5a1b3Sopenharmony_ci 4453a5a1b3Sopenharmony_cistatic void ocb(pa_threaded_mainloop *m, void *userdata) { 4553a5a1b3Sopenharmony_ci pa_threaded_mainloop_lock(m); 4653a5a1b3Sopenharmony_ci pa_threaded_mainloop_signal(m, 0); 4753a5a1b3Sopenharmony_ci pa_threaded_mainloop_unlock(m); 4853a5a1b3Sopenharmony_ci} 4953a5a1b3Sopenharmony_ci 5053a5a1b3Sopenharmony_ciSTART_TEST (thread_mainloop_test) { 5153a5a1b3Sopenharmony_ci pa_mainloop_api *a; 5253a5a1b3Sopenharmony_ci pa_threaded_mainloop *m; 5353a5a1b3Sopenharmony_ci struct timeval tv; 5453a5a1b3Sopenharmony_ci 5553a5a1b3Sopenharmony_ci m = pa_threaded_mainloop_new(); 5653a5a1b3Sopenharmony_ci fail_unless(m != NULL); 5753a5a1b3Sopenharmony_ci a = pa_threaded_mainloop_get_api(m); 5853a5a1b3Sopenharmony_ci fail_unless(m != NULL); 5953a5a1b3Sopenharmony_ci 6053a5a1b3Sopenharmony_ci fail_unless(pa_threaded_mainloop_start(m) >= 0); 6153a5a1b3Sopenharmony_ci 6253a5a1b3Sopenharmony_ci pa_threaded_mainloop_lock(m); 6353a5a1b3Sopenharmony_ci 6453a5a1b3Sopenharmony_ci fail_unless(!pa_threaded_mainloop_in_thread(m)); 6553a5a1b3Sopenharmony_ci 6653a5a1b3Sopenharmony_ci a->time_new(a, pa_timeval_rtstore(&tv, pa_rtclock_now() + 5 * PA_USEC_PER_SEC, true), tcb, m); 6753a5a1b3Sopenharmony_ci 6853a5a1b3Sopenharmony_ci fprintf(stderr, "waiting 5s (signal)\n"); 6953a5a1b3Sopenharmony_ci pa_threaded_mainloop_wait(m); 7053a5a1b3Sopenharmony_ci fprintf(stderr, "wait completed\n"); 7153a5a1b3Sopenharmony_ci pa_threaded_mainloop_accept(m); 7253a5a1b3Sopenharmony_ci fprintf(stderr, "signal accepted\n"); 7353a5a1b3Sopenharmony_ci 7453a5a1b3Sopenharmony_ci pa_threaded_mainloop_unlock(m); 7553a5a1b3Sopenharmony_ci 7653a5a1b3Sopenharmony_ci fprintf(stderr, "waiting 5s (sleep)\n"); 7753a5a1b3Sopenharmony_ci pa_msleep(5000); 7853a5a1b3Sopenharmony_ci 7953a5a1b3Sopenharmony_ci /* Test pa_threaded_mainloop_once_unlocked() */ 8053a5a1b3Sopenharmony_ci pa_threaded_mainloop_lock(m); 8153a5a1b3Sopenharmony_ci 8253a5a1b3Sopenharmony_ci fprintf(stderr, "scheduling unlocked callback\n"); 8353a5a1b3Sopenharmony_ci pa_threaded_mainloop_once_unlocked(m, ocb, NULL); 8453a5a1b3Sopenharmony_ci 8553a5a1b3Sopenharmony_ci pa_threaded_mainloop_wait(m); 8653a5a1b3Sopenharmony_ci fprintf(stderr, "got unlocked callback\n"); 8753a5a1b3Sopenharmony_ci 8853a5a1b3Sopenharmony_ci pa_threaded_mainloop_unlock(m); 8953a5a1b3Sopenharmony_ci 9053a5a1b3Sopenharmony_ci pa_threaded_mainloop_stop(m); 9153a5a1b3Sopenharmony_ci 9253a5a1b3Sopenharmony_ci pa_threaded_mainloop_free(m); 9353a5a1b3Sopenharmony_ci} 9453a5a1b3Sopenharmony_ciEND_TEST 9553a5a1b3Sopenharmony_ci 9653a5a1b3Sopenharmony_ciint main(int argc, char *argv[]) { 9753a5a1b3Sopenharmony_ci int failed = 0; 9853a5a1b3Sopenharmony_ci Suite *s; 9953a5a1b3Sopenharmony_ci TCase *tc; 10053a5a1b3Sopenharmony_ci SRunner *sr; 10153a5a1b3Sopenharmony_ci 10253a5a1b3Sopenharmony_ci s = suite_create("Thread MainLoop"); 10353a5a1b3Sopenharmony_ci tc = tcase_create("threadmainloop"); 10453a5a1b3Sopenharmony_ci tcase_add_test(tc, thread_mainloop_test); 10553a5a1b3Sopenharmony_ci /* the default timeout is too small, 10653a5a1b3Sopenharmony_ci * set it to a reasonable large one. 10753a5a1b3Sopenharmony_ci */ 10853a5a1b3Sopenharmony_ci tcase_set_timeout(tc, 60 * 60); 10953a5a1b3Sopenharmony_ci suite_add_tcase(s, tc); 11053a5a1b3Sopenharmony_ci 11153a5a1b3Sopenharmony_ci sr = srunner_create(s); 11253a5a1b3Sopenharmony_ci srunner_run_all(sr, CK_NORMAL); 11353a5a1b3Sopenharmony_ci failed = srunner_ntests_failed(sr); 11453a5a1b3Sopenharmony_ci srunner_free(sr); 11553a5a1b3Sopenharmony_ci 11653a5a1b3Sopenharmony_ci return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 11753a5a1b3Sopenharmony_ci} 118