1// SPDX-License-Identifier: GPL-2.0
2#include <linux/kthread.h>
3#include <linux/wait.h>
4
5#include "spk_types.h"
6#include "speakup.h"
7#include "spk_priv.h"
8
9DECLARE_WAIT_QUEUE_HEAD(speakup_event);
10EXPORT_SYMBOL_GPL(speakup_event);
11
12int speakup_thread(void *data)
13{
14	unsigned long flags;
15	int should_break;
16	struct bleep our_sound;
17
18	our_sound.active = 0;
19	our_sound.freq = 0;
20	our_sound.jiffies = 0;
21
22	mutex_lock(&spk_mutex);
23	while (1) {
24		DEFINE_WAIT(wait);
25
26		while (1) {
27			spin_lock_irqsave(&speakup_info.spinlock, flags);
28			our_sound = spk_unprocessed_sound;
29			spk_unprocessed_sound.active = 0;
30			prepare_to_wait(&speakup_event, &wait,
31					TASK_INTERRUPTIBLE);
32			should_break = kthread_should_stop() ||
33				our_sound.active ||
34				(synth && synth->catch_up && synth->alive &&
35					(speakup_info.flushing ||
36					!synth_buffer_empty()));
37			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
38			if (should_break)
39				break;
40			mutex_unlock(&spk_mutex);
41			schedule();
42			mutex_lock(&spk_mutex);
43		}
44		finish_wait(&speakup_event, &wait);
45		if (kthread_should_stop())
46			break;
47
48		if (our_sound.active)
49			kd_mksound(our_sound.freq, our_sound.jiffies);
50		if (synth && synth->catch_up && synth->alive) {
51			/*
52			 * It is up to the callee to take the lock, so that it
53			 * can sleep whenever it likes
54			 */
55			synth->catch_up(synth);
56		}
57
58		speakup_start_ttys();
59	}
60	mutex_unlock(&spk_mutex);
61	return 0;
62}
63