[REFACTOR] encapsulate target struct (part 1)
[platform/core/system/swap-manager.git] / daemon / threads.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12  * Nikita Kalyazin    <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31
32
33 #include <stdio.h>
34 #include <stdlib.h>                     // for atoi, atol
35 #include <string.h>                     // for strchr
36 #include <stdint.h>                     // for uint64_t
37 #include <sys/types.h>          // for recv
38 #include <sys/socket.h>         // for recv
39 #include <sys/time.h>           // for setitimer
40 #include <signal.h>                     // for sigemptyset, sigset_t, sigaddset, ...
41 #include <unistd.h>                     // for write
42
43 #include "daemon.h"
44 #include "utils.h"
45 #include "sys_stat.h"
46
47 #include "da_protocol.h"
48 #include "da_data.h"
49 #include "da_inst.h"
50 #include "debug.h"
51 #include "buffer.h"
52 #include "input_events.h"
53
54 static void* recvThread(void* data)
55 {
56         struct target *target = data;
57         int pass = 0;
58         uint64_t event;
59         struct msg_target_t log;
60         int err;
61
62         // initialize target variable
63         target->allocmem = 0;
64
65         for (;;) {
66                 err = target_recv_msg(target, &log);
67                 if (err != 0) {
68                         /* disconnect */
69                         event = EVENT_STOP;
70                         write(target->event_fd, &event, sizeof(event));
71                         break;
72                 }
73
74                 if (IS_PROBE_MSG(log.type)) {
75                         struct msg_data_t *msg_data = (struct msg_data_t *)&log;
76
77                         if (write_to_buf(msg_data) != 0)
78                                 LOGE("write to buf fail\n");
79
80                         continue;
81                 }
82
83                 log.data[log.length] = '\0';
84                 if(log.type == MSG_ALLOC)
85                 {
86                         target->allocmem = str_to_int64(log.data);
87                         continue;               // don't send to host
88                 }
89                 else if(log.type == MSG_PID)
90                 {
91                         LOGI("MSG_PID arrived (pid ppid): %s\n", log.data);
92
93                         // only when first MSG_PID is arrived
94                         if (target_get_pid(target) == UNKNOWN_PID) {
95                                 int n;
96                                 pid_t pid, ppid;
97
98                                 n = sscanf(log.data, "%d %d", &pid, &ppid);
99                                 if (n != 2)
100                                 {
101                                         /**
102                                          * TODO: complain to host about wrong
103                                          * pid message send stop message to
104                                          * main thread
105                                          */
106                                         event = EVENT_STOP;
107                                         write(target->event_fd, &event,
108                                               sizeof(uint64_t));
109                                         break;
110                                 }
111
112                                 /* set pid and ppid */
113                                 target_set_pid(target, pid);
114                                 target_set_ppid(target, ppid);
115
116                                 /* send event */
117                                 event = EVENT_PID;
118                                 write(target->event_fd, &event, sizeof(uint64_t));
119                         }
120                         send_maps_inst_msg_to(target);
121                         continue;               // don't send to host
122                 }
123                 else if(log.type == MSG_TERMINATE)
124                 {
125                         LOGI("MSG_TERMINATE arrived: pid[%d]\n",
126                              target_get_pid(target));
127
128                         // send stop message to main thread
129                         event = EVENT_STOP;
130                         write(target->event_fd, &event,
131                               sizeof(uint64_t));
132
133                         break;
134                 } else if (log.type == MSG_MSG) {
135                         // don't send to host
136                         LOGI("EXTRA '%s'\n", log.data);
137                         continue;
138                 } else if (log.type == MSG_ERROR) {
139                         // don't send to host
140                         LOGE("EXTRA '%s'\n", log.data);
141                         continue;
142                 } else if (log.type == MSG_WARNING) {
143                         // don't send to host
144                         LOGW("EXTRA '%s'\n", log.data);
145                         continue;
146                 }
147 #ifdef PRINT_TARGET_LOG
148                 else if(log.type == MSG_LOG)
149                 {
150                         switch(log.data[0])
151                         {
152                                 case '2':       // UI control creation log
153                                 case '3':       // UI event log
154                                 case '6':       // UI lifecycle log
155                                 case '7':       // screenshot log
156                                 case '8':       // scene transition log
157                                         LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
158                                         break;
159                                 default:
160                                         break;
161                         }
162                 }
163                 else if(log.type == MSG_IMAGE)
164                 {
165                         LOGI("MSG_IMAGE received\n");
166                 }
167                 else    // not MSG_LOG and not MSG_IMAGE
168                 {
169                         LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
170                 }
171 #endif
172
173                 // do not send any message to host until MSG_PID message arrives
174                 if(unlikely(pass == 0))
175                 {
176                         while(target->initial_log == 0)
177                         {
178                                 sleep(0);
179                         }
180                 }
181                 pass = 1;
182         }
183
184         target->recv_thread = -1;
185         return NULL;
186 }
187
188 int makeRecvThread(struct target *target)
189 {
190         if (target_start(target, recvThread) < 0) {
191                 LOGE("Failed to create recv thread\n");
192                 return -1;
193         }
194
195         return 0;
196 }
197
198 static void *samplingThread(void *data)
199 {
200         int err, signo;
201         sigset_t waitsigmask;
202
203         LOGI("sampling thread started\n");
204
205         sigemptyset(&waitsigmask);
206         sigaddset(&waitsigmask, SIGALRM);
207         sigaddset(&waitsigmask, SIGUSR1);
208
209         while (1) {
210                 err = sigwait(&waitsigmask, &signo);
211                 if (err != 0) {
212                         LOGE("Failed to sigwait() in sampling thread\n");
213                         continue;
214                 }
215
216                 if (signo == SIGALRM) {
217                         struct system_info_t sys_info;
218                         struct msg_data_t *msg;
219
220                         if (get_system_info(&sys_info) == -1) {
221                                 LOGE("Cannot get system info\n");
222                                 //do not send sys_info because
223                                 //it is corrupted
224                                 continue;
225                         }
226
227                         msg = pack_system_info(&sys_info);
228                         if (!msg) {
229                                 LOGE("Cannot pack system info\n");
230                                 reset_system_info(&sys_info);
231                                 continue;
232                         }
233
234                         if (write_to_buf(msg) != 0)
235                                 LOGE("write to buf fail\n");
236
237 #ifdef THREAD_SAMPLING_DEBUG
238                         printBuf((char *)msg, MSG_DATA_HDR_LEN + msg->len);
239 #endif
240
241                         free_msg_data(msg);
242                         reset_system_info(&sys_info);
243                         flush_buf();
244                 }
245                 else if(signo == SIGUSR1)
246                 {
247                         LOGI("SIGUSR1 catched\n");
248                         // end this thread
249                         break;
250                 }
251                 else
252                 {
253                         // never happen
254                         LOGE("This should never happen in sampling thread\n");
255                 }
256         }
257
258         LOGI("sampling thread ended\n");
259         return NULL;
260 }
261
262 // return 0 if normal case
263 // return minus value if critical error
264 // return plus value if non-critical error
265 int samplingStart(void)
266 {
267         struct itimerval timerval;
268         time_t sec = prof_session.conf.system_trace_period / 1000;
269         suseconds_t usec = prof_session.conf.system_trace_period * 1000 %
270                 1000000;
271
272         if(manager.sampling_thread != -1)       // already started
273                 return 1;
274
275         if (check_running_status(&prof_session) == 0) {
276                 LOGI("try to start sampling when running_status is 0\n");
277                 return 1;
278         }
279
280         if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
281         {
282                 LOGE("Failed to create sampling thread\n");
283                 return -1;
284         }
285
286         timerval.it_interval.tv_sec = sec;
287         timerval.it_interval.tv_usec = usec;
288         timerval.it_value.tv_sec = sec;
289         timerval.it_value.tv_usec = usec;
290         setitimer(ITIMER_REAL, &timerval, NULL);
291
292         return 0;
293 }
294
295 int samplingStop(void)
296 {
297         if(manager.sampling_thread != -1)
298         {
299                 struct itimerval stopval;
300
301                 // stop timer
302                 stopval.it_interval.tv_sec = 0;
303                 stopval.it_interval.tv_usec = 0;
304                 stopval.it_value.tv_sec = 0;
305                 stopval.it_value.tv_usec = 0;
306                 setitimer(ITIMER_REAL, &stopval, NULL);
307
308                 pthread_kill(manager.sampling_thread, SIGUSR1);
309                 LOGI("join sampling thread started\n");
310                 pthread_join(manager.sampling_thread, NULL);
311                 LOGI("join sampling thread done\n");
312
313                 manager.sampling_thread = -1;
314         }
315
316         return 0;
317 }
318
319 static useconds_t time_diff_us(struct timeval *tv1, struct timeval *tv2)
320 {
321         return (tv1->tv_sec - tv2->tv_sec) * 1000000 +
322                 ((int)tv1->tv_usec - (int)tv2->tv_usec);
323 }
324
325 static void *replay_thread(void *arg)
326 {
327         struct replay_event_seq_t *event_seq = (struct replay_event_seq_t *)arg;
328         int i = 0;
329         useconds_t ms;
330         useconds_t prev_event_offset = 0;
331
332         struct replay_event_t * pevent = NULL;
333
334         LOGI_th_rep("replay events thread started\n");
335         if (event_seq->event_num != 0)
336         {
337                 pevent = event_seq->events;
338         }
339
340         for (i = 0; i < event_seq->event_num; i++) {
341                 useconds_t event_offset = time_diff_us(&pevent->ev.time, &event_seq->tv);
342                 if (event_offset >= prev_event_offset)
343                         ms = event_offset - prev_event_offset;
344                 else
345                         ms = 0;
346
347 #ifdef THREAD_REPLAY_DEBUG
348                 print_replay_event(pevent, i + 1, "\t");
349 #endif
350                 LOGI_th_rep("%d) sleep %d\n", i, ms);
351                 usleep(ms);
352
353                 write_input_event(pevent->id, &pevent->ev);
354
355                 prev_event_offset = event_offset;
356
357                 pevent++;
358         }
359
360         LOGI("replay events thread finished\n");
361
362         return arg;
363 }
364
365 int start_replay()
366 {
367         if (manager.replay_thread != -1) // already started
368                 return 1;
369
370         if (pthread_create(&(manager.replay_thread),
371                            NULL,
372                            replay_thread,
373                            &prof_session.replay_event_seq) < 0)
374         {
375                 LOGE("Failed to create replay thread\n");
376                 return 1;
377         }
378
379         return 0;
380 }
381
382 void stop_replay()
383 {
384         if (manager.replay_thread == -1) {
385                 LOGI("replay thread not running\n");
386                 return;
387         }
388         LOGI("stopping replay thread\n");
389         pthread_cancel(manager.replay_thread);
390         pthread_join(manager.replay_thread, NULL);
391         manager.replay_thread = -1;
392         reset_replay_event_seq(&prof_session.replay_event_seq);
393         LOGI("replay thread joined\n");
394 }