libubox
C utility functions for OpenWrt.
test-runqueue.c
Go to the documentation of this file.
1 /*
2  * runqueue-example.c
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 <stdbool.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 
24 #include "uloop.h"
25 #include "runqueue.h"
26 
27 static struct runqueue q;
28 
29 struct sleeper {
30  int val;
31  bool kill;
32  struct uloop_timeout t;
33  struct runqueue_process proc;
34 };
35 
36 static void q_empty(struct runqueue *q)
37 {
38  fprintf(stderr, "All done!\n");
39  uloop_end();
40 }
41 
42 static const char* sleeper_type(struct sleeper *s)
43 {
44  return s->kill ? "killer" : "sleeper";
45 }
46 
47 static void q_sleep_run(struct runqueue *q, struct runqueue_task *t)
48 {
49  struct sleeper *s = container_of(t, struct sleeper, proc.task);
50  char str[32];
51  pid_t pid;
52 
53  fprintf(stderr, "[%d/%d] start 'sleep %d' (%s)\n", q->running_tasks,
55 
56  pid = fork();
57  if (pid < 0)
58  return;
59 
60  if (pid) {
61  runqueue_process_add(q, &s->proc, pid);
62  return;
63  }
64 
65  sprintf(str, "%d", s->val);
66  execlp("sleep", "sleep", str, NULL);
67  exit(1);
68 }
69 
70 static void q_sleep_cancel(struct runqueue *q, struct runqueue_task *t, int type)
71 {
72  struct sleeper *s = container_of(t, struct sleeper, proc.task);
73 
74  fprintf(stderr, "[%d/%d] cancel 'sleep %d' (%s)\n", q->running_tasks,
77 }
78 
79 static void q_sleep_complete(struct runqueue *q, struct runqueue_task *p)
80 {
81  struct sleeper *s = container_of(p, struct sleeper, proc.task);
82 
83  fprintf(stderr, "[%d/%d] finish 'sleep %d' (%s) \n", q->running_tasks,
85  free(s);
86 }
87 
88 static void my_runqueue_process_kill_cb(struct runqueue *q, struct runqueue_task *p)
89 {
90  struct sleeper *s = container_of(p, struct sleeper, proc.task);
91 
92  fprintf(stderr, "[%d/%d] killing process (%s)\n", q->running_tasks,
95 }
96 
97 static void timer_cb(struct uloop_timeout *t)
98 {
99  struct sleeper *s = container_of(t, struct sleeper, t);
100  if (s->kill)
102 }
103 
104 static struct sleeper* create_sleeper(int val, const struct runqueue_task_type *type, bool kill)
105 {
106  struct sleeper *s = calloc(1, sizeof(*s));
107  s->kill = kill;
108  s->t.cb = timer_cb;
109  s->proc.task.type = type;
110  s->proc.task.run_timeout = 500;
112  s->val = val;
113 
114  return s;
115 }
116 
117 static void add_sleeper(int val)
118 {
119  static const struct runqueue_task_type sleeper_type = {
120  .run = q_sleep_run,
121  .cancel = q_sleep_cancel,
122  .kill = runqueue_process_kill_cb,
123  };
124 
125  static const struct runqueue_task_type killer_type = {
126  .run = q_sleep_run,
127  .cancel = q_sleep_cancel,
129  };
130 
131  struct sleeper *k = create_sleeper(val, &killer_type, true);
132  uloop_timeout_set(&k->t, 10);
133  uloop_timeout_add(&k->t);
134  runqueue_task_add(&q, &k->proc.task, false);
135 
136  struct sleeper *s = create_sleeper(val, &sleeper_type, false);
137  runqueue_task_add(&q, &s->proc.task, false);
138 }
139 
140 int main(int argc, char **argv)
141 {
142  uloop_init();
143 
144  runqueue_init(&q);
145  q.empty_cb = q_empty;
146  q.max_running_tasks = 1;
147 
148  if (argc > 1)
149  q.max_running_tasks = atoi(argv[1]);
150 
151  add_sleeper(1);
152  add_sleeper(1);
153  add_sleeper(1);
154 
155  uloop_run();
156  uloop_done();
157 
158  return 0;
159 }
#define container_of(ptr, type, member)
Definition: list.h:38
void runqueue_process_cancel_cb(struct runqueue *q, struct runqueue_task *t, int type)
Definition: runqueue.c:245
void runqueue_task_add(struct runqueue *q, struct runqueue_task *t, bool running)
Definition: runqueue.c:181
void runqueue_init(struct runqueue *q)
Definition: runqueue.c:31
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
void runqueue_process_kill_cb(struct runqueue *q, struct runqueue_task *t)
Definition: runqueue.c:255
struct runqueue_task task
Definition: runqueue.h:89
void(* run)(struct runqueue *q, struct runqueue_task *t)
Definition: runqueue.h:53
const struct runqueue_task_type * type
Definition: runqueue.h:73
void(* complete)(struct runqueue *q, struct runqueue_task *t)
Definition: runqueue.h:76
int run_timeout
Definition: runqueue.h:79
int max_running_tasks
Definition: runqueue.h:36
int running_tasks
Definition: runqueue.h:35
void(* empty_cb)(struct runqueue *q)
Definition: runqueue.h:41
struct runqueue_process proc
Definition: test-runqueue.c:33
bool kill
Definition: test-runqueue.c:31
struct uloop_timeout t
Definition: test-runqueue.c:32
uloop_timeout_handler cb
Definition: uloop.h:77
static struct sleeper * create_sleeper(int val, const struct runqueue_task_type *type, bool kill)
static void q_sleep_run(struct runqueue *q, struct runqueue_task *t)
Definition: test-runqueue.c:47
int main(int argc, char **argv)
static void q_empty(struct runqueue *q)
Definition: test-runqueue.c:36
static struct runqueue q
Definition: test-runqueue.c:27
static void my_runqueue_process_kill_cb(struct runqueue *q, struct runqueue_task *p)
Definition: test-runqueue.c:88
static void timer_cb(struct uloop_timeout *t)
Definition: test-runqueue.c:97
static void q_sleep_complete(struct runqueue *q, struct runqueue_task *p)
Definition: test-runqueue.c:79
static void q_sleep_cancel(struct runqueue *q, struct runqueue_task *t, int type)
Definition: test-runqueue.c:70
static const char * sleeper_type(struct sleeper *s)
Definition: test-runqueue.c:42
static void add_sleeper(int val)
uint8_t type
Definition: udebug-proto.h:0
void uloop_done(void)
Definition: uloop.c:686
int uloop_timeout_add(struct uloop_timeout *timeout)
Definition: uloop.c:298
int uloop_init(void)
Definition: uloop.c:150
int uloop_timeout_set(struct uloop_timeout *timeout, int msecs)
Definition: uloop.c:328
static void uloop_end(void)
Definition: uloop.h:140
static int uloop_run(void)
Definition: uloop.h:147