libubox
C utility functions for OpenWrt.
runqueue.c
Go to the documentation of this file.
1 /*
2  * runqueue.c - a simple task queueing/completion tracking helper
3  *
4  * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <string.h>
20 #include <stdio.h>
21 #include "runqueue.h"
22 
23 static void
25 {
26  struct runqueue *q = container_of(timeout, struct runqueue, timeout);
27 
28  q->empty_cb(q);
29 }
30 
31 void runqueue_init(struct runqueue *q)
32 {
35 }
36 
38 {
39  struct runqueue *q = container_of(timeout, struct runqueue, timeout);
40  struct runqueue_task *t;
41 
42  do {
43  if (q->stopped)
44  break;
45 
47  break;
48 
50  break;
51 
53  safe_list_del(&t->list);
55  t->running = true;
56  q->running_tasks++;
57  if (t->run_timeout)
59  t->type->run(q, t);
60  } while (1);
61 
62  if (!q->empty &&
65  q->empty = true;
66  if (q->empty_cb) {
69  }
70  }
71 }
72 
73 static void runqueue_start_next(struct runqueue *q)
74 {
75  if (q->empty)
76  return;
77 
80 }
81 
82 static int __runqueue_cancel(void *ctx, struct safe_list *list)
83 {
84  struct runqueue_task *t;
85 
86  t = container_of(list, struct runqueue_task, list);
88 
89  return 0;
90 }
91 
93 {
95 }
96 
98 {
100 }
101 
103 {
106 }
107 
108 void runqueue_kill(struct runqueue *q)
109 {
110  struct runqueue_task *t;
111 
112  while (!list_empty(&q->tasks_active.list)) {
115  }
118 }
119 
121 {
122  if (!t->queued)
123  return;
124 
125  if (!t->running) {
127  return;
128  }
129 
130  t->cancelled = true;
131  if (t->cancel_timeout)
133  if (t->type->cancel)
134  t->type->cancel(t->q, t, type);
135 }
136 
137 static void
139 {
141 
142  if (t->cancelled)
144  else
146 }
147 
148 static void _runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running, bool first)
149 {
150  struct safe_list *head;
151 
152  if (t->queued)
153  return;
154 
155  if (!t->type->run && !running) {
156  fprintf(stderr, "BUG: inactive task added without run() callback\n");
157  return;
158  }
159 
160  if (running) {
161  q->running_tasks++;
162  head = &q->tasks_active;
163  } else {
164  head = &q->tasks_inactive;
165  }
166 
168  t->q = q;
169  if (first)
170  safe_list_add_first(&t->list, head);
171  else
172  safe_list_add(&t->list, head);
173  t->cancelled = false;
174  t->queued = true;
175  t->running = running;
176  q->empty = false;
177 
179 }
180 
181 void runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running)
182 {
183  _runqueue_task_add(q, t, running, 0);
184 }
185 
186 void runqueue_task_add_first(struct runqueue *q, struct runqueue_task *t, bool running)
187 {
188  _runqueue_task_add(q, t, running, 1);
189 }
190 
192 {
193  struct runqueue *q = t->q;
194  bool running = t->running;
195 
196  if (!t->queued)
197  return;
198 
199  if (running && t->type->kill)
200  t->type->kill(q, t);
201 
203 }
204 
205 void runqueue_stop(struct runqueue *q)
206 {
207  q->stopped = true;
208 }
209 
211 {
212  q->stopped = false;
214 }
215 
217 {
218  struct runqueue *q = t->q;
219 
220  if (!t->queued)
221  return;
222 
223  if (t->running)
224  t->q->running_tasks--;
225 
227 
228  safe_list_del(&t->list);
229  t->queued = false;
230  t->running = false;
231  t->cancelled = false;
232  if (t->complete)
233  t->complete(q, t);
235 }
236 
237 static void
239 {
240  struct runqueue_process *t = container_of(p, struct runqueue_process, proc);
241 
243 }
244 
246 {
247  struct runqueue_process *p = container_of(t, struct runqueue_process, task);
248 
249  if (!type)
250  type = SIGTERM;
251 
252  kill(p->proc.pid, type);
253 }
254 
256 {
257  struct runqueue_process *p = container_of(t, struct runqueue_process, task);
258 
260  kill(p->proc.pid, SIGKILL);
261 }
262 
263 static const struct runqueue_task_type runqueue_proc_type = {
264  .name = "process",
265  .cancel = runqueue_process_cancel_cb,
266  .kill = runqueue_process_kill_cb,
267 };
268 
269 void runqueue_process_add(struct runqueue *q, struct runqueue_process *p, pid_t pid)
270 {
271  if (p->proc.pending)
272  return;
273 
274  p->proc.pid = pid;
276  if (!p->task.type)
278  uloop_process_add(&p->proc);
279  if (!p->task.running)
280  runqueue_task_add(q, &p->task, true);
281 }
static bool list_empty(const struct list_head *head)
Definition: list.h:69
#define list_first_entry(ptr, type, field)
Definition: list.h:121
#define container_of(ptr, type, member)
Definition: list.h:38
static void _runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running, bool first)
Definition: runqueue.c:148
void runqueue_task_add_first(struct runqueue *q, struct runqueue_task *t, bool running)
Definition: runqueue.c:186
void runqueue_cancel_active(struct runqueue *q)
Definition: runqueue.c:92
void runqueue_process_cancel_cb(struct runqueue *q, struct runqueue_task *t, int type)
Definition: runqueue.c:245
void runqueue_resume(struct runqueue *q)
Definition: runqueue.c:210
static void __runqueue_start_next(struct uloop_timeout *timeout)
Definition: runqueue.c:37
static void runqueue_start_next(struct runqueue *q)
Definition: runqueue.c:73
void runqueue_stop(struct runqueue *q)
Definition: runqueue.c:205
static int __runqueue_cancel(void *ctx, struct safe_list *list)
Definition: runqueue.c:82
void runqueue_task_cancel(struct runqueue_task *t, int type)
Definition: runqueue.c:120
void runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running)
Definition: runqueue.c:181
static void __runqueue_task_timeout(struct uloop_timeout *timeout)
Definition: runqueue.c:138
void runqueue_cancel(struct runqueue *q)
Definition: runqueue.c:102
void runqueue_init(struct runqueue *q)
Definition: runqueue.c:31
void runqueue_kill(struct runqueue *q)
Definition: runqueue.c:108
void runqueue_task_complete(struct runqueue_task *t)
Definition: runqueue.c:216
void runqueue_task_kill(struct runqueue_task *t)
Definition: runqueue.c:191
void runqueue_process_add(struct runqueue *q, struct runqueue_process *p, pid_t pid)
Definition: runqueue.c:269
static void __runqueue_empty_cb(struct uloop_timeout *timeout)
Definition: runqueue.c:24
static const struct runqueue_task_type runqueue_proc_type
Definition: runqueue.c:263
void runqueue_process_kill_cb(struct runqueue *q, struct runqueue_task *t)
Definition: runqueue.c:255
static void __runqueue_proc_cb(struct uloop_process *p, int ret)
Definition: runqueue.c:238
void runqueue_cancel_pending(struct runqueue *q)
Definition: runqueue.c:97
int safe_list_for_each(struct safe_list *head, int(*cb)(void *ctx, struct safe_list *list), void *ctx)
Definition: safe_list.c:62
void safe_list_add(struct safe_list *list, struct safe_list *head)
Definition: safe_list.c:83
void safe_list_add_first(struct safe_list *list, struct safe_list *head)
Definition: safe_list.c:89
void safe_list_del(struct safe_list *list)
Definition: safe_list.c:95
#define INIT_SAFE_LIST(_head)
Definition: safe_list.h:48
struct runqueue_task task
Definition: runqueue.h:89
struct uloop_process proc
Definition: runqueue.h:90
const char * name
Definition: runqueue.h:45
void(* kill)(struct runqueue *q, struct runqueue_task *t)
Definition: runqueue.h:68
void(* cancel)(struct runqueue *q, struct runqueue_task *t, int type)
Definition: runqueue.h:62
void(* run)(struct runqueue *q, struct runqueue_task *t)
Definition: runqueue.h:53
const struct runqueue_task_type * type
Definition: runqueue.h:73
struct safe_list list
Definition: runqueue.h:72
bool cancelled
Definition: runqueue.h:85
bool running
Definition: runqueue.h:84
bool queued
Definition: runqueue.h:83
void(* complete)(struct runqueue *q, struct runqueue_task *t)
Definition: runqueue.h:76
struct runqueue * q
Definition: runqueue.h:74
struct uloop_timeout timeout
Definition: runqueue.h:78
int cancel_timeout
Definition: runqueue.h:80
int cancel_type
Definition: runqueue.h:81
int run_timeout
Definition: runqueue.h:79
int max_running_tasks
Definition: runqueue.h:36
struct safe_list tasks_inactive
Definition: runqueue.h:32
bool stopped
Definition: runqueue.h:37
int running_tasks
Definition: runqueue.h:35
bool empty
Definition: runqueue.h:38
struct uloop_timeout timeout
Definition: runqueue.h:33
void(* empty_cb)(struct runqueue *q)
Definition: runqueue.h:41
struct safe_list tasks_active
Definition: runqueue.h:31
struct list_head list
Definition: safe_list.h:36
pid_t pid
Definition: uloop.h:87
uloop_process_handler cb
Definition: uloop.h:86
bool pending
Definition: uloop.h:84
uloop_timeout_handler cb
Definition: uloop.h:77
static struct runqueue q
Definition: test-runqueue.c:27
uint8_t type
Definition: udebug-proto.h:0
int uloop_process_delete(struct uloop_process *p)
Definition: uloop.c:412
int uloop_timeout_cancel(struct uloop_timeout *timeout)
Definition: uloop.c:348
int uloop_timeout_set(struct uloop_timeout *timeout, int msecs)
Definition: uloop.c:328
int uloop_process_add(struct uloop_process *p)
Definition: uloop.c:391