2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 rwlock_decl(iomux_rwlock);
21 static struct iomux_wait **iowait_directory;
22 static size_t iowait_directory_size;
24 static bool iomux_poll = false;
26 void iomux_enable_poll(void)
28 bool was_poll = iomux_poll;
29 if (unlikely(!was_poll)) {
35 void iomux_never(mutex_t **mutex_to_lock, struct list *list_entry)
37 *mutex_to_lock = address_get_mutex(NULL, DEPTH_THUNK);
38 list_init(list_entry);
41 static struct iomux_wait *iomux_get_iowait(handle_t handle)
43 struct iomux_wait *result;
45 rwlock_lock_read(&iomux_rwlock);
46 if (likely((size_t)handle < iowait_directory_size) && likely((result = iowait_directory[handle]) != NULL)) {
47 rwlock_unlock_read(&iomux_rwlock);
50 rwlock_unlock_read(&iomux_rwlock);
52 rwlock_lock_write(&iomux_rwlock);
53 while ((size_t)handle >= iowait_directory_size) {
54 array_add(struct iomux_wait *, &iowait_directory, &iowait_directory_size, NULL);
57 if (!(result = iowait_directory[handle])) {
58 result = iowait_directory[handle] = mem_alloc(struct iomux_wait *, sizeof(struct iomux_wait));
59 iomux_wait_init(result, handle);
62 rwlock_unlock_write(&iomux_rwlock);
66 static uint32_t iomux_get_time(uint32_t us)
68 if (unlikely(iomux_poll))
69 us = minimum(us, POLL_US);
73 uint32_t tm = timer_wait_now();
84 static thread_t iomux_thread;
87 #define do_timer_check_all timer_check_all()
89 #define do_timer_check_all do { } while (0)
93 * select doesn't work well with signals, the standard says that it's
94 * implementation-defined whether SA_RESTART restarts select or not.
96 * If SA_RESTART signal restarts select with the original timeval, it causes
99 * So, we'd better disable signals for the iomux thread and let the system
100 * deliver them to another thread.
102 #if defined(IOMUX_SELECT)
103 #define iomux_block_signals true
105 #define iomux_block_signals false
108 thread_function_decl(iomux_poll_thread,
110 if (iomux_block_signals)
111 os_block_signals(&set);
113 while (likely(!os_drain_notify_pipe())) {
116 os_signal_check_all();
117 iomux_check_all(IOMUX_INDEFINITE_WAIT);
119 if (iomux_block_signals)
120 os_unblock_signals(&set);