18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/kthread.h>
38c2ecf20Sopenharmony_ci#include <linux/wait.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include "spk_types.h"
68c2ecf20Sopenharmony_ci#include "speakup.h"
78c2ecf20Sopenharmony_ci#include "spk_priv.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciDECLARE_WAIT_QUEUE_HEAD(speakup_event);
108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(speakup_event);
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ciint speakup_thread(void *data)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	unsigned long flags;
158c2ecf20Sopenharmony_ci	int should_break;
168c2ecf20Sopenharmony_ci	struct bleep our_sound;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	our_sound.active = 0;
198c2ecf20Sopenharmony_ci	our_sound.freq = 0;
208c2ecf20Sopenharmony_ci	our_sound.jiffies = 0;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	mutex_lock(&spk_mutex);
238c2ecf20Sopenharmony_ci	while (1) {
248c2ecf20Sopenharmony_ci		DEFINE_WAIT(wait);
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci		while (1) {
278c2ecf20Sopenharmony_ci			spin_lock_irqsave(&speakup_info.spinlock, flags);
288c2ecf20Sopenharmony_ci			our_sound = spk_unprocessed_sound;
298c2ecf20Sopenharmony_ci			spk_unprocessed_sound.active = 0;
308c2ecf20Sopenharmony_ci			prepare_to_wait(&speakup_event, &wait,
318c2ecf20Sopenharmony_ci					TASK_INTERRUPTIBLE);
328c2ecf20Sopenharmony_ci			should_break = kthread_should_stop() ||
338c2ecf20Sopenharmony_ci				our_sound.active ||
348c2ecf20Sopenharmony_ci				(synth && synth->catch_up && synth->alive &&
358c2ecf20Sopenharmony_ci					(speakup_info.flushing ||
368c2ecf20Sopenharmony_ci					!synth_buffer_empty()));
378c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
388c2ecf20Sopenharmony_ci			if (should_break)
398c2ecf20Sopenharmony_ci				break;
408c2ecf20Sopenharmony_ci			mutex_unlock(&spk_mutex);
418c2ecf20Sopenharmony_ci			schedule();
428c2ecf20Sopenharmony_ci			mutex_lock(&spk_mutex);
438c2ecf20Sopenharmony_ci		}
448c2ecf20Sopenharmony_ci		finish_wait(&speakup_event, &wait);
458c2ecf20Sopenharmony_ci		if (kthread_should_stop())
468c2ecf20Sopenharmony_ci			break;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci		if (our_sound.active)
498c2ecf20Sopenharmony_ci			kd_mksound(our_sound.freq, our_sound.jiffies);
508c2ecf20Sopenharmony_ci		if (synth && synth->catch_up && synth->alive) {
518c2ecf20Sopenharmony_ci			/*
528c2ecf20Sopenharmony_ci			 * It is up to the callee to take the lock, so that it
538c2ecf20Sopenharmony_ci			 * can sleep whenever it likes
548c2ecf20Sopenharmony_ci			 */
558c2ecf20Sopenharmony_ci			synth->catch_up(synth);
568c2ecf20Sopenharmony_ci		}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci		speakup_start_ttys();
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci	mutex_unlock(&spk_mutex);
618c2ecf20Sopenharmony_ci	return 0;
628c2ecf20Sopenharmony_ci}
63