- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)
1 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,241 +0,0 @@ |
1 |
-/* |
|
2 |
- * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com) |
|
3 |
- * |
|
4 |
- * This file is part of Kamailio, a free SIP server. |
|
5 |
- * |
|
6 |
- * Permission to use, copy, modify, and 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 |
-* \file |
|
20 |
-* \brief Kamailio core :: Asynchronus tasks |
|
21 |
-* \ingroup core |
|
22 |
-* Module: \ref core |
|
23 |
-*/ |
|
24 |
- |
|
25 |
-#include <stdio.h> |
|
26 |
-#include <unistd.h> |
|
27 |
-#include <stdlib.h> |
|
28 |
-#include <string.h> |
|
29 |
- |
|
30 |
-#include <sys/socket.h> |
|
31 |
-#include <sys/types.h> |
|
32 |
-#include <sys/un.h> |
|
33 |
-#include <netinet/in.h> |
|
34 |
-#include <arpa/inet.h> |
|
35 |
-#include <fcntl.h> |
|
36 |
-#include <errno.h> |
|
37 |
- |
|
38 |
-#include "dprint.h" |
|
39 |
-#include "sr_module.h" |
|
40 |
-#include "ut.h" |
|
41 |
-#include "pt.h" |
|
42 |
-#include "cfg/cfg_struct.h" |
|
43 |
- |
|
44 |
- |
|
45 |
-#include "async_task.h" |
|
46 |
- |
|
47 |
-static int _async_task_workers = 0; |
|
48 |
-static int _async_task_sockets[2]; |
|
49 |
-static int _async_task_usleep = 0; |
|
50 |
- |
|
51 |
-int async_task_run(int idx); |
|
52 |
- |
|
53 |
-/** |
|
54 |
- * |
|
55 |
- */ |
|
56 |
-int async_task_init_sockets(void) |
|
57 |
-{ |
|
58 |
- if (socketpair(PF_UNIX, SOCK_DGRAM, 0, _async_task_sockets) < 0) { |
|
59 |
- LM_ERR("opening tasks dgram socket pair\n"); |
|
60 |
- return -1; |
|
61 |
- } |
|
62 |
- LM_DBG("inter-process event notification sockets initialized\n"); |
|
63 |
- return 0; |
|
64 |
-} |
|
65 |
- |
|
66 |
-/** |
|
67 |
- * |
|
68 |
- */ |
|
69 |
-void async_task_close_sockets_child(void) |
|
70 |
-{ |
|
71 |
- LM_DBG("closing the notification socket used by children\n"); |
|
72 |
- close(_async_task_sockets[1]); |
|
73 |
-} |
|
74 |
- |
|
75 |
-/** |
|
76 |
- * |
|
77 |
- */ |
|
78 |
-void async_task_close_sockets_parent(void) |
|
79 |
-{ |
|
80 |
- LM_DBG("closing the notification socket used by parent\n"); |
|
81 |
- close(_async_task_sockets[0]); |
|
82 |
-} |
|
83 |
- |
|
84 |
-/** |
|
85 |
- * |
|
86 |
- */ |
|
87 |
-int async_task_init(void) |
|
88 |
-{ |
|
89 |
- LM_DBG("start initializing asynk task framework\n"); |
|
90 |
- if(_async_task_workers<=0) |
|
91 |
- return 0; |
|
92 |
- |
|
93 |
- /* advertise new processes to core */ |
|
94 |
- register_procs(_async_task_workers); |
|
95 |
- |
|
96 |
- /* advertise new processes to cfg framework */ |
|
97 |
- cfg_register_child(_async_task_workers); |
|
98 |
- |
|
99 |
- return 0; |
|
100 |
-} |
|
101 |
- |
|
102 |
-/** |
|
103 |
- * |
|
104 |
- */ |
|
105 |
-int async_task_initialized(void) |
|
106 |
-{ |
|
107 |
- if(_async_task_workers<=0) |
|
108 |
- return 0; |
|
109 |
- return 1; |
|
110 |
-} |
|
111 |
- |
|
112 |
-/** |
|
113 |
- * |
|
114 |
- */ |
|
115 |
-int async_task_child_init(int rank) |
|
116 |
-{ |
|
117 |
- int pid; |
|
118 |
- int i; |
|
119 |
- |
|
120 |
- if(_async_task_workers<=0) |
|
121 |
- return 0; |
|
122 |
- |
|
123 |
- LM_DBG("child initializing asynk task framework\n"); |
|
124 |
- |
|
125 |
- if (rank==PROC_INIT) { |
|
126 |
- if(async_task_init_sockets()<0) { |
|
127 |
- LM_ERR("failed to initialize tasks sockets\n"); |
|
128 |
- return -1; |
|
129 |
- } |
|
130 |
- return 0; |
|
131 |
- } |
|
132 |
- |
|
133 |
- if(rank>0) { |
|
134 |
- async_task_close_sockets_parent(); |
|
135 |
- return 0; |
|
136 |
- } |
|
137 |
- if (rank!=PROC_MAIN) |
|
138 |
- return 0; |
|
139 |
- |
|
140 |
- for(i=0; i<_async_task_workers; i++) { |
|
141 |
- pid=fork_process(PROC_RPC, "Async Task Worker", 1); |
|
142 |
- if (pid<0) |
|
143 |
- return -1; /* error */ |
|
144 |
- if(pid==0) { |
|
145 |
- /* child */ |
|
146 |
- |
|
147 |
- /* initialize the config framework */ |
|
148 |
- if (cfg_child_init()) |
|
149 |
- return -1; |
|
150 |
- /* main function for workers */ |
|
151 |
- if(async_task_run(i+1)<0) { |
|
152 |
- LM_ERR("failed to initialize task worker process: %d\n", i); |
|
153 |
- return -1; |
|
154 |
- } |
|
155 |
- } |
|
156 |
- } |
|
157 |
- |
|
158 |
- return 0; |
|
159 |
-} |
|
160 |
- |
|
161 |
-/** |
|
162 |
- * |
|
163 |
- */ |
|
164 |
-int async_task_set_workers(int n) |
|
165 |
-{ |
|
166 |
- if(_async_task_workers>0) { |
|
167 |
- LM_WARN("task workers already set\n"); |
|
168 |
- return 0; |
|
169 |
- } |
|
170 |
- if(n<=0) |
|
171 |
- return 0; |
|
172 |
- |
|
173 |
- _async_task_workers = n; |
|
174 |
- |
|
175 |
- return 0; |
|
176 |
-} |
|
177 |
- |
|
178 |
-/** |
|
179 |
- * |
|
180 |
- */ |
|
181 |
-int async_task_set_usleep(int n) |
|
182 |
-{ |
|
183 |
- int v; |
|
184 |
- |
|
185 |
- v = _async_task_usleep; |
|
186 |
- _async_task_usleep = n; |
|
187 |
- |
|
188 |
- return v; |
|
189 |
-} |
|
190 |
- |
|
191 |
-/** |
|
192 |
- * |
|
193 |
- */ |
|
194 |
-int async_task_push(async_task_t *task) |
|
195 |
-{ |
|
196 |
- int len; |
|
197 |
- |
|
198 |
- if(_async_task_workers<=0) |
|
199 |
- return 0; |
|
200 |
- |
|
201 |
- len = write(_async_task_sockets[1], &task, sizeof(async_task_t*)); |
|
202 |
- if(len<=0) { |
|
203 |
- LM_ERR("failed to pass the task to asynk workers\n"); |
|
204 |
- return -1; |
|
205 |
- } |
|
206 |
- LM_DBG("task sent [%p]\n", task); |
|
207 |
- return 0; |
|
208 |
-} |
|
209 |
- |
|
210 |
-/** |
|
211 |
- * |
|
212 |
- */ |
|
213 |
-int async_task_run(int idx) |
|
214 |
-{ |
|
215 |
- async_task_t *ptask; |
|
216 |
- int received; |
|
217 |
- |
|
218 |
- LM_DBG("async task worker %d ready\n", idx); |
|
219 |
- |
|
220 |
- for( ; ; ) { |
|
221 |
- if(unlikely(_async_task_usleep)) sleep_us(_async_task_usleep); |
|
222 |
- if ((received = recvfrom(_async_task_sockets[0], |
|
223 |
- &ptask, sizeof(async_task_t*), |
|
224 |
- 0, NULL, 0)) < 0) { |
|
225 |
- LM_ERR("failed to received task (%d: %s)\n", errno, strerror(errno)); |
|
226 |
- continue; |
|
227 |
- } |
|
228 |
- if(received != sizeof(async_task_t*)) { |
|
229 |
- LM_ERR("invalid task size %d\n", received); |
|
230 |
- continue; |
|
231 |
- } |
|
232 |
- if(ptask->exec!=NULL) { |
|
233 |
- LM_DBG("task executed [%p] (%p/%p)\n", ptask, |
|
234 |
- ptask->exec, ptask->param); |
|
235 |
- ptask->exec(ptask->param); |
|
236 |
- } |
|
237 |
- shm_free(ptask); |
|
238 |
- } |
|
239 |
- |
|
240 |
- return 0; |
|
241 |
-} |
- add option to do usleep() before processing async tasks
- could help saving cpu usage on vms with immediate interruptions
triggered to recvfrom()
... | ... |
@@ -46,6 +46,7 @@ |
46 | 46 |
|
47 | 47 |
static int _async_task_workers = 0; |
48 | 48 |
static int _async_task_sockets[2]; |
49 |
+static int _async_task_usleep = 0; |
|
49 | 50 |
|
50 | 51 |
int async_task_run(int idx); |
51 | 52 |
|
... | ... |
@@ -174,6 +175,19 @@ int async_task_set_workers(int n) |
174 | 175 |
return 0; |
175 | 176 |
} |
176 | 177 |
|
178 |
+/** |
|
179 |
+ * |
|
180 |
+ */ |
|
181 |
+int async_task_set_usleep(int n) |
|
182 |
+{ |
|
183 |
+ int v; |
|
184 |
+ |
|
185 |
+ v = _async_task_usleep; |
|
186 |
+ _async_task_usleep = n; |
|
187 |
+ |
|
188 |
+ return v; |
|
189 |
+} |
|
190 |
+ |
|
177 | 191 |
/** |
178 | 192 |
* |
179 | 193 |
*/ |
... | ... |
@@ -204,6 +218,7 @@ int async_task_run(int idx) |
204 | 218 |
LM_DBG("async task worker %d ready\n", idx); |
205 | 219 |
|
206 | 220 |
for( ; ; ) { |
221 |
+ if(unlikely(_async_task_usleep)) sleep_us(_async_task_usleep); |
|
207 | 222 |
if ((received = recvfrom(_async_task_sockets[0], |
208 | 223 |
&ptask, sizeof(async_task_t*), |
209 | 224 |
0, NULL, 0)) < 0) { |
... | ... |
@@ -1,7 +1,7 @@ |
1 | 1 |
/** |
2 | 2 |
* Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com) |
3 | 3 |
* |
4 |
- * This file is part of Extensible SIP Router, a free SIP server. |
|
4 |
+ * This file is part of Kamailio, a free SIP server. |
|
5 | 5 |
* |
6 | 6 |
* Permission to use, copy, modify, and distribute this software for any |
7 | 7 |
* purpose with or without fee is hereby granted, provided that the above |
... | ... |
@@ -15,6 +15,12 @@ |
15 | 15 |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | 16 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | 17 |
*/ |
18 |
+/*! |
|
19 |
+* \file |
|
20 |
+* \brief Kamailio core :: Asynchronus tasks |
|
21 |
+* \ingroup core |
|
22 |
+* Module: \ref core |
|
23 |
+*/ |
|
18 | 24 |
|
19 | 25 |
#include <stdio.h> |
20 | 26 |
#include <unistd.h> |
... | ... |
@@ -110,11 +110,11 @@ int async_task_child_init(int rank) |
110 | 110 |
int pid; |
111 | 111 |
int i; |
112 | 112 |
|
113 |
- LM_DBG("child initializing asynk task framework\n"); |
|
114 |
- |
|
115 | 113 |
if(_async_task_workers<=0) |
116 | 114 |
return 0; |
117 | 115 |
|
116 |
+ LM_DBG("child initializing asynk task framework\n"); |
|
117 |
+ |
|
118 | 118 |
if (rank==PROC_INIT) { |
119 | 119 |
if(async_task_init_sockets()<0) { |
120 | 120 |
LM_ERR("failed to initialize tasks sockets\n"); |
- dedicated group of processes that can get tasks from other processes
via memory pipe
- react immediately, no time based polling
- should reduce the need for other components to create extra processes
for special handling
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,220 @@ |
1 |
+/** |
|
2 |
+ * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com) |
|
3 |
+ * |
|
4 |
+ * This file is part of Extensible SIP Router, a free SIP server. |
|
5 |
+ * |
|
6 |
+ * Permission to use, copy, modify, and 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 <stdio.h> |
|
20 |
+#include <unistd.h> |
|
21 |
+#include <stdlib.h> |
|
22 |
+#include <string.h> |
|
23 |
+ |
|
24 |
+#include <sys/socket.h> |
|
25 |
+#include <sys/types.h> |
|
26 |
+#include <sys/un.h> |
|
27 |
+#include <netinet/in.h> |
|
28 |
+#include <arpa/inet.h> |
|
29 |
+#include <fcntl.h> |
|
30 |
+#include <errno.h> |
|
31 |
+ |
|
32 |
+#include "dprint.h" |
|
33 |
+#include "sr_module.h" |
|
34 |
+#include "ut.h" |
|
35 |
+#include "pt.h" |
|
36 |
+#include "cfg/cfg_struct.h" |
|
37 |
+ |
|
38 |
+ |
|
39 |
+#include "async_task.h" |
|
40 |
+ |
|
41 |
+static int _async_task_workers = 0; |
|
42 |
+static int _async_task_sockets[2]; |
|
43 |
+ |
|
44 |
+int async_task_run(int idx); |
|
45 |
+ |
|
46 |
+/** |
|
47 |
+ * |
|
48 |
+ */ |
|
49 |
+int async_task_init_sockets(void) |
|
50 |
+{ |
|
51 |
+ if (socketpair(PF_UNIX, SOCK_DGRAM, 0, _async_task_sockets) < 0) { |
|
52 |
+ LM_ERR("opening tasks dgram socket pair\n"); |
|
53 |
+ return -1; |
|
54 |
+ } |
|
55 |
+ LM_DBG("inter-process event notification sockets initialized\n"); |
|
56 |
+ return 0; |
|
57 |
+} |
|
58 |
+ |
|
59 |
+/** |
|
60 |
+ * |
|
61 |
+ */ |
|
62 |
+void async_task_close_sockets_child(void) |
|
63 |
+{ |
|
64 |
+ LM_DBG("closing the notification socket used by children\n"); |
|
65 |
+ close(_async_task_sockets[1]); |
|
66 |
+} |
|
67 |
+ |
|
68 |
+/** |
|
69 |
+ * |
|
70 |
+ */ |
|
71 |
+void async_task_close_sockets_parent(void) |
|
72 |
+{ |
|
73 |
+ LM_DBG("closing the notification socket used by parent\n"); |
|
74 |
+ close(_async_task_sockets[0]); |
|
75 |
+} |
|
76 |
+ |
|
77 |
+/** |
|
78 |
+ * |
|
79 |
+ */ |
|
80 |
+int async_task_init(void) |
|
81 |
+{ |
|
82 |
+ LM_DBG("start initializing asynk task framework\n"); |
|
83 |
+ if(_async_task_workers<=0) |
|
84 |
+ return 0; |
|
85 |
+ |
|
86 |
+ /* advertise new processes to core */ |
|
87 |
+ register_procs(_async_task_workers); |
|
88 |
+ |
|
89 |
+ /* advertise new processes to cfg framework */ |
|
90 |
+ cfg_register_child(_async_task_workers); |
|
91 |
+ |
|
92 |
+ return 0; |
|
93 |
+} |
|
94 |
+ |
|
95 |
+/** |
|
96 |
+ * |
|
97 |
+ */ |
|
98 |
+int async_task_initialized(void) |
|
99 |
+{ |
|
100 |
+ if(_async_task_workers<=0) |
|
101 |
+ return 0; |
|
102 |
+ return 1; |
|
103 |
+} |
|
104 |
+ |
|
105 |
+/** |
|
106 |
+ * |
|
107 |
+ */ |
|
108 |
+int async_task_child_init(int rank) |
|
109 |
+{ |
|
110 |
+ int pid; |
|
111 |
+ int i; |
|
112 |
+ |
|
113 |
+ LM_DBG("child initializing asynk task framework\n"); |
|
114 |
+ |
|
115 |
+ if(_async_task_workers<=0) |
|
116 |
+ return 0; |
|
117 |
+ |
|
118 |
+ if (rank==PROC_INIT) { |
|
119 |
+ if(async_task_init_sockets()<0) { |
|
120 |
+ LM_ERR("failed to initialize tasks sockets\n"); |
|
121 |
+ return -1; |
|
122 |
+ } |
|
123 |
+ return 0; |
|
124 |
+ } |
|
125 |
+ |
|
126 |
+ if(rank>0) { |
|
127 |
+ async_task_close_sockets_parent(); |
|
128 |
+ return 0; |
|
129 |
+ } |
|
130 |
+ if (rank!=PROC_MAIN) |
|
131 |
+ return 0; |
|
132 |
+ |
|
133 |
+ for(i=0; i<_async_task_workers; i++) { |
|
134 |
+ pid=fork_process(PROC_RPC, "Async Task Worker", 1); |
|
135 |
+ if (pid<0) |
|
136 |
+ return -1; /* error */ |
|
137 |
+ if(pid==0) { |
|
138 |
+ /* child */ |
|
139 |
+ |
|
140 |
+ /* initialize the config framework */ |
|
141 |
+ if (cfg_child_init()) |
|
142 |
+ return -1; |
|
143 |
+ /* main function for workers */ |
|
144 |
+ if(async_task_run(i+1)<0) { |
|
145 |
+ LM_ERR("failed to initialize task worker process: %d\n", i); |
|
146 |
+ return -1; |
|
147 |
+ } |
|
148 |
+ } |
|
149 |
+ } |
|
150 |
+ |
|
151 |
+ return 0; |
|
152 |
+} |
|
153 |
+ |
|
154 |
+/** |
|
155 |
+ * |
|
156 |
+ */ |
|
157 |
+int async_task_set_workers(int n) |
|
158 |
+{ |
|
159 |
+ if(_async_task_workers>0) { |
|
160 |
+ LM_WARN("task workers already set\n"); |
|
161 |
+ return 0; |
|
162 |
+ } |
|
163 |
+ if(n<=0) |
|
164 |
+ return 0; |
|
165 |
+ |
|
166 |
+ _async_task_workers = n; |
|
167 |
+ |
|
168 |
+ return 0; |
|
169 |
+} |
|
170 |
+ |
|
171 |
+/** |
|
172 |
+ * |
|
173 |
+ */ |
|
174 |
+int async_task_push(async_task_t *task) |
|
175 |
+{ |
|
176 |
+ int len; |
|
177 |
+ |
|
178 |
+ if(_async_task_workers<=0) |
|
179 |
+ return 0; |
|
180 |
+ |
|
181 |
+ len = write(_async_task_sockets[1], &task, sizeof(async_task_t*)); |
|
182 |
+ if(len<=0) { |
|
183 |
+ LM_ERR("failed to pass the task to asynk workers\n"); |
|
184 |
+ return -1; |
|
185 |
+ } |
|
186 |
+ LM_DBG("task sent [%p]\n", task); |
|
187 |
+ return 0; |
|
188 |
+} |
|
189 |
+ |
|
190 |
+/** |
|
191 |
+ * |
|
192 |
+ */ |
|
193 |
+int async_task_run(int idx) |
|
194 |
+{ |
|
195 |
+ async_task_t *ptask; |
|
196 |
+ int received; |
|
197 |
+ |
|
198 |
+ LM_DBG("async task worker %d ready\n", idx); |
|
199 |
+ |
|
200 |
+ for( ; ; ) { |
|
201 |
+ if ((received = recvfrom(_async_task_sockets[0], |
|
202 |
+ &ptask, sizeof(async_task_t*), |
|
203 |
+ 0, NULL, 0)) < 0) { |
|
204 |
+ LM_ERR("failed to received task (%d: %s)\n", errno, strerror(errno)); |
|
205 |
+ continue; |
|
206 |
+ } |
|
207 |
+ if(received != sizeof(async_task_t*)) { |
|
208 |
+ LM_ERR("invalid task size %d\n", received); |
|
209 |
+ continue; |
|
210 |
+ } |
|
211 |
+ if(ptask->exec!=NULL) { |
|
212 |
+ LM_DBG("task executed [%p] (%p/%p)\n", ptask, |
|
213 |
+ ptask->exec, ptask->param); |
|
214 |
+ ptask->exec(ptask->param); |
|
215 |
+ } |
|
216 |
+ shm_free(ptask); |
|
217 |
+ } |
|
218 |
+ |
|
219 |
+ return 0; |
|
220 |
+} |