blob: f2fee7ffe6dd9482659709f15a4aa504fb7ca644 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2014 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include "minip-internal.h"
25
26#include <trace.h>
27#include <debug.h>
28#include <compiler.h>
29#include <stdlib.h>
30#include <list.h>
31#include <err.h>
32#include <sys/types.h>
33#include <kernel/thread.h>
34#include <kernel/event.h>
35#include <kernel/mutex.h>
36#include <platform.h>
37
38#define LOCAL_TRACE 0
39
40static struct list_node net_timer_list = LIST_INITIAL_VALUE(net_timer_list);
41static event_t net_timer_event = EVENT_INITIAL_VALUE(net_timer_event, false, 0);
42static mutex_t net_timer_lock = MUTEX_INITIAL_VALUE(net_timer_lock);
43
44static void add_to_queue(net_timer_t *t)
45{
46 net_timer_t *e;
47 list_for_every_entry(&net_timer_list, e, net_timer_t, node) {
48 if (TIME_GT(e->sched_time, t->sched_time)) {
49 list_add_before(&e->node, &t->node);
50 return;
51 }
52 }
53
54 list_add_tail(&net_timer_list, &t->node);
55}
56
57bool net_timer_set(net_timer_t *t, net_timer_callback_t cb, void *callback_args, lk_time_t delay)
58{
59 bool newly_queued = true;
60
61 lk_time_t now = current_time();
62
63 mutex_acquire(&net_timer_lock);
64
65 if (list_in_list(&t->node)) {
66 list_delete(&t->node);
67 newly_queued = false;
68 }
69
70 t->cb = cb;
71 t->arg = callback_args;
72 t->sched_time = now + delay;
73
74 add_to_queue(t);
75
76 mutex_release(&net_timer_lock);
77
78 event_signal(&net_timer_event, true);
79
80 return newly_queued;
81}
82
83bool net_timer_cancel(net_timer_t *t)
84{
85 bool was_queued = false;
86
87 mutex_acquire(&net_timer_lock);
88
89 if (list_in_list(&t->node)) {
90 list_delete(&t->node);
91 was_queued = true;
92 }
93
94 mutex_release(&net_timer_lock);
95
96 return was_queued;
97}
98
99/* returns the delay to the next event */
100static lk_time_t net_timer_work_routine(void)
101{
102 lk_time_t now = current_time();
103 lk_time_t delay = INFINITE_TIME;
104
105 mutex_acquire(&net_timer_lock);
106
107 for (;;) {
108 net_timer_t *e;
109 e = list_peek_head_type(&net_timer_list, net_timer_t, node);
110 if (!e) {
111 delay = INFINITE_TIME;
112 goto done;
113 }
114
115 if (TIME_GT(e->sched_time, now)) {
116 delay = e->sched_time - now;
117 goto done;
118 }
119
120 list_delete(&e->node);
121
122 mutex_release(&net_timer_lock);
123
124 LTRACEF("firing timer %p, cb %p, arg %p\n", e, e->cb, e->arg);
125 e->cb(e->arg);
126
127 mutex_acquire(&net_timer_lock);
128 }
129
130done:
131 if (delay == INFINITE_TIME)
132 event_unsignal(&net_timer_event);
133
134 mutex_release(&net_timer_lock);
135
136 return delay;
137}
138
139int net_timer_work_thread(void *args)
140{
141 for (;;) {
142 event_wait(&net_timer_event);
143
144 lk_time_t delay = net_timer_work_routine();
145 if (delay != INFINITE_TIME) {
146 thread_sleep(MIN(delay, 100));
147 }
148 }
149
150 return 0;
151}
152
153void net_timer_init(void)
154{
155 thread_detach_and_resume(thread_create("net timer", &net_timer_work_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
156}
157
158