Tizen 2.0 Release
[apps/core/preloaded/myfiles.git] / src / common / mf-ta.c
1 /*
2  * Copyright 2013         Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *  http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18
19
20
21 #include <stdio.h>
22 #include <malloc.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <time.h>
26 #include <sys/time.h>
27 #include <sys/utsname.h>
28 #include <sys/resource.h>
29 #include <unistd.h>
30 #include <stdarg.h>
31
32 #include "mf-ta.h"
33
34 static void __mf_ta_free_cps(void);
35 static int __mf_ta_get_cp_index(char *name);
36
37 static void __mf_ta_free_accums(void);
38 static int __mf_ta_get_accum_index(char *name);
39
40 mf_ta_checkpoint **mf_g_cps = NULL;
41 static int mf_g_cp_index = 0;
42
43 mf_ta_accum_item **mf_g_accums = NULL;
44 static int mf_g_accum_index = 0;
45 static int mf_g_accum_longest_name = 0;
46 static unsigned long mf_g_accum_first_time = 0xFFFFFFFF;
47 static int mf_g_enable = 1;
48
49 int mf_ta_init(void)
50 {
51         if (mf_g_accums)
52                 return 0;
53
54         mf_g_cps = (mf_ta_checkpoint **) malloc(MF_TA_MAX_CHECKPOINT * sizeof(mf_ta_checkpoint *));
55         if (!mf_g_cps)
56                 return -1;
57
58         mf_g_accums = (mf_ta_accum_item **) malloc(MF_TA_MAX_CHECKPOINT * sizeof(mf_ta_accum_item *));
59         if (!mf_g_accums)
60                 return -1;
61
62         mf_g_accum_first_time = 0xFFFFFFFF;
63
64         return 0;
65 }
66
67 int mf_ta_release(void)
68 {
69         if (!mf_g_accums)
70                 return 0;
71
72         __mf_ta_free_cps();
73         __mf_ta_free_accums();
74
75         mf_g_accum_first_time = 0xFFFFFFFF;
76
77         return 0;
78 }
79
80 void mf_ta_set_enable(int enable)
81 {
82         printf("MF_TA : setting enable to %d\n", enable);
83         mf_g_enable = enable;
84 }
85
86 int mf_ta_get_numof_checkpoints()
87 {
88         return mf_g_cp_index;
89 }
90
91 char *mf_ta_fmt(const char *fmt, ...)
92 {
93         static char ta_buf[512];
94         va_list args;
95
96         memset(ta_buf, '\0', 512);
97
98         va_start(args, fmt);
99         vsnprintf(ta_buf, 512, fmt, args);
100         va_end(args);
101
102         return ta_buf;
103 }
104
105
106 int mf_ta_add_checkpoint(char *name, int show, char *filename, int line)
107 {
108         mf_ta_checkpoint *cp = NULL;
109         struct timeval t;
110
111         if (!mf_g_enable)
112                 return -1;
113
114         if (!mf_g_accums)
115                 return 0;
116
117         if (mf_g_cp_index == MF_TA_MAX_CHECKPOINT)
118                 return -1;
119
120         if (!name)
121                 return -1;
122
123         if (strlen(name) == 0)
124                 return -1;
125
126         cp = (mf_ta_checkpoint *) malloc(sizeof(mf_ta_checkpoint));
127         if (!cp)
128                 return -1;
129
130         cp->name = (char *)malloc(strlen(name) + 1);
131         if (!cp->name) {
132                 free(cp);
133                 return -1;
134         }
135         strncpy(cp->name, name, strlen(name));
136
137         if (show)
138                 printf("[CHECK-POINT] %s...(%s:%d)\n", name, filename, line);
139
140         gettimeofday(&t, NULL);
141         cp->timestamp = t.tv_sec * 1000000L + t.tv_usec;
142 #ifdef MF_TA_UNIT_MSEC
143         cp->timestamp = (cp->timestamp >= 1000) ? cp->timestamp / 1000 : 0;
144 #endif
145
146         mf_g_cps[mf_g_cp_index] = cp;
147
148         mf_g_cp_index++;
149
150         return 0;
151 }
152
153 void mf_ta_show_checkpoints(void)
154 {
155         int i = 0;
156         if (!mf_g_accums)
157                 return;
158
159         printf("BEGIN RESULT ============================\n");
160         for (i = 0; i < mf_g_cp_index; i++) {
161                 printf("[%d] %s : %ld us.\n", i, mf_g_cps[i]->name, mf_g_cps[i]->timestamp);
162         }
163         printf("END RESULT   ============================\n");
164 }
165
166 void mf_ta_show_diff(char *name1, char *name2)
167 {
168         if (!mf_g_accums)
169                 return;
170
171
172         printf("Time takes from [%s] to [%s] : %ld us.\n", name1, name2, mf_ta_get_diff(name1, name2));
173 }
174
175 unsigned long mf_ta_get_diff(char *name1, char *name2)
176 {
177         int cp1, cp2;
178
179         if (!mf_g_accums)
180                 return 0;
181
182
183         /* fail if bad param. */
184         if (!name1 || !name2)
185                 return -1;
186
187         /* fail if same. */
188         if (strcmp(name1, name2) == 0)
189                 return -1;
190
191         /*get index */
192         if ((cp1 = __mf_ta_get_cp_index(name1)) == -1)
193                 return -1;
194
195         if ((cp2 = __mf_ta_get_cp_index(name2)) == -1)
196                 return -1;
197
198         /* NOTE :
199          * return value must be positive value.
200          * bcz the value of higher index of mf_g_cps always higher than lower one.
201          */
202         return mf_g_cps[cp2]->timestamp - mf_g_cps[cp1]->timestamp;
203
204 }
205
206 static int __mf_ta_get_cp_index(char *name)
207 {
208         int i;
209
210         assert(name);
211
212         /* find index */
213         for (i = 0; i < mf_g_cp_index; i++) {
214                 if (strcmp(name, mf_g_cps[i]->name) == 0)
215                         return i;
216         }
217
218         return -1;
219 }
220
221 static int __mf_ta_get_accum_index(char *name)
222 {
223         int i;
224
225         assert(name);
226
227         /* find index */
228         for (i = 0; i < mf_g_accum_index; i++) {
229                 if (strcmp(name, mf_g_accums[i]->name) == 0)
230                         return i;
231         }
232
233         return -1;
234 }
235
236 static void __mf_ta_free_cps(void)
237 {
238         int i = 0;
239
240         if (!mf_g_cps)
241                 return;
242
243         for (i = 0; i < mf_g_cp_index; i++) {
244                 if (mf_g_cps[i]) {
245                         if (mf_g_cps[i]->name)
246                                 free(mf_g_cps[i]->name);
247
248                         free(mf_g_cps[i]);
249
250                         mf_g_cps[i] = NULL;
251                 }
252         }
253
254         free(mf_g_cps);
255         mf_g_cps = NULL;
256
257         mf_g_cp_index = 0;
258 }
259
260 static void __mf_ta_free_accums(void)
261 {
262         int i = 0;
263
264         if (!mf_g_accums)
265                 return;
266
267         for (i = 0; i < mf_g_accum_index; i++) {
268                 if (mf_g_accums[i]) {
269                         if (mf_g_accums[i]->name)
270                                 free(mf_g_accums[i]->name);
271
272                         free(mf_g_accums[i]);
273
274                         mf_g_accums[i] = NULL;
275                 }
276         }
277
278         mf_g_accum_index = 0;
279         mf_g_accum_longest_name = 0;
280
281         free(mf_g_accums);
282         mf_g_accums = NULL;
283 }
284
285
286 int mf_ta_accum_item_begin(char *name, int show, char *filename, int line)
287 {
288         mf_ta_accum_item *accum = NULL;
289         int index = 0;
290         int name_len = 0;
291         struct timeval t;
292
293         if (!mf_g_enable)
294                 return -1;
295
296         if (!mf_g_accums)
297                 return 0;
298
299
300
301         if (mf_g_accum_index == MF_TA_MAX_ACCUM)
302                 return -1;
303
304         if (!name)
305                 return -1;
306
307         name_len = strlen(name);
308         if (name_len == 0)
309                 return -1;
310
311         /* if 'name' is new one. create new item. */
312         if ((index = __mf_ta_get_accum_index(name)) == -1) {
313                 accum = (mf_ta_accum_item *) malloc(sizeof(mf_ta_accum_item));
314                 if (!accum)
315                         return -1;
316
317                 /*clear first. */
318                 memset(accum, 0, sizeof(mf_ta_accum_item));
319                 accum->elapsed_min = 0xFFFFFFFF;
320
321                 accum->name = (char *)malloc(name_len + 1);
322                 if (!accum->name) {
323                         free(accum);
324                         return -1;
325                 }
326                 memset(accum->name, 0, name_len + 1);
327                 strncpy(accum->name, name, strlen(name));
328
329                 /* add it to list. */
330                 mf_g_accums[mf_g_accum_index] = accum;
331                 mf_g_accum_index++;
332
333                 if (mf_g_accum_longest_name < name_len)
334                         mf_g_accum_longest_name = name_len;
335
336         } else {
337                 accum = mf_g_accums[index];
338         }
339
340         /*verify pairs of begin, end. */
341         if (accum->on_estimate) {
342                 printf("[%s] is not 'end'ed!\n", accum->name);
343                 accum->num_unpair++;
344                 return -1;
345         }
346         /*get timestamp */
347         gettimeofday(&t, NULL);
348         accum->timestamp = t.tv_sec * 1000000L + t.tv_usec;
349 #ifdef MF_TA_UNIT_MSEC
350         accum->timestamp = (accum->timestamp >= 1000) ? accum->timestamp / 1000 : 0;
351 #endif
352         accum->on_estimate = 1;
353
354         if (accum->first_start == 0) {  /* assum that timestamp never could be zero. */
355                 accum->first_start = accum->timestamp;
356
357                 if (mf_g_accum_first_time > accum->first_start)
358                         mf_g_accum_first_time = accum->first_start;
359         }
360
361         if (show)
362                 printf("[ACCUM BEGIN] %s : %ld ---(%s:%d)\n", name, accum->timestamp, filename, line);
363
364         accum->num_calls++;
365
366         return 0;
367 }
368
369 int mf_ta_accum_item_end(char *name, int show, char *filename, int line)
370 {
371         mf_ta_accum_item *accum = NULL;
372         unsigned int tval = 0;
373         int index = 0;
374         struct timeval t;
375
376         if (!mf_g_enable)
377                 return -1;
378
379         if (!mf_g_accums)
380                 return 0;
381
382
383         /* get time first for more accuracy. */
384         gettimeofday(&t, NULL);
385
386         if (mf_g_accum_index == MF_TA_MAX_ACCUM)
387                 return -1;
388
389         if (!name)
390                 return -1;
391
392         if (strlen(name) == 0)
393                 return -1;
394
395         /* varify the 'name' is already exist. */
396         if ((index = __mf_ta_get_accum_index(name)) == -1) {
397                 printf("[%s] is not added before!\n", name);
398                 return -1;
399         }
400
401         accum = mf_g_accums[index];
402
403         /* verify pairs of begin, end. */
404         if (!accum->on_estimate) {
405                 printf("[%s] is not 'begin' yet!\n", accum->name);
406                 accum->num_unpair++;
407                 return -1;
408         }
409         /* get current timestamp. */
410         tval = t.tv_sec * 1000000L + t.tv_usec;
411 #ifdef MF_TA_UNIT_MSEC
412         tval = (tval >= 1000) ? tval / 1000 : 0;
413 #endif
414
415         /* update last_end */
416         accum->last_end = tval;
417
418         /* make get elapsed time. */
419         tval = tval - accum->timestamp;
420
421         /* update min/max */
422         accum->elapsed_max = tval > accum->elapsed_max ? tval : accum->elapsed_max;
423         accum->elapsed_min = tval < accum->elapsed_min ? tval : accum->elapsed_min;
424
425         if (show)
426                 printf("[ACCUM END] %s : %ld + %u ---(%s:%d)\n", name, accum->elapsed_accum, tval, filename, line);
427
428         /* add elapsed time */
429         accum->elapsed_accum += tval;
430         accum->on_estimate = 0;
431
432         return 0;
433 }
434
435 void __mf_ta_print_some_info(FILE *fp)
436 {
437         if (!fp)
438                 return;
439
440         /* comment */
441         {
442                 fprintf(fp, "\nb~ b~ b~\n\n");
443         }
444
445         /* General infomation */
446         {
447                 time_t t_val;
448                 char hostname[MF_TA_BUFF_SIZE] = { '\0', };
449                 char buf[MF_TA_BUFF_SIZE] = {'\0', };
450                 struct utsname uts;
451                 struct rusage r_usage;
452
453                 fprintf(fp, "\n[[ General info ]]\n");
454
455                 /* time and date */
456                 time(&t_val);
457                 ctime_r(&t_val, buf);
458                 fprintf(fp, "Date : %s", buf);
459
460                 /* system */
461                 if (gethostname(hostname, 255) == 0 && uname(&uts) >= 0) {
462                         fprintf(fp, "Hostname : %s\n", hostname);
463                         fprintf(fp, "System : %s\n", uts.sysname);
464                         fprintf(fp, "Machine : %s\n", uts.machine);
465                         fprintf(fp, "Nodename : %s\n", uts.nodename);
466                         fprintf(fp, "Release : %s \n", uts.release);
467                         fprintf(fp, "Version : %s \n", uts.version);
468                 }
469                 /* process info. */
470                 fprintf(fp, "Process priority : %d\n", getpriority(PRIO_PROCESS, getpid()));
471                 getrusage(RUSAGE_SELF, &r_usage);
472                 fprintf(fp, "CPU usage : User = %ld.%06ld, System = %ld.%06ld\n",
473                         r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec, r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
474
475
476         }
477
478         /* host environment variables */
479         {
480                 extern char **environ;
481                 char **env = environ;
482
483                 fprintf(fp, "\n[[ Host environment variables ]]\n");
484                 while (*env) {
485                         fprintf(fp, "%s\n", *env);
486                         env++;
487                 }
488         }
489 }
490
491 void mf_ta_show_accum_result(int direction)
492 {
493         int i = 0;
494         char format[256];
495         FILE *fp = stderr;
496
497         if (!mf_g_accums)
498                 return;
499
500         switch (direction) {
501         case MF_TA_SHOW_STDOUT:
502                 fp = stdout;
503                 break;
504         case MF_TA_SHOW_STDERR:
505                 fp = stderr;
506                 break;
507         case MF_TA_SHOW_FILE:
508                 {
509                         fp = fopen(MF_TA_RESULT_FILE, "wt");
510                         if (!fp)
511                                 return;
512                 }
513         }
514         __mf_ta_print_some_info(fp);
515
516 #ifdef MF_TA_UNIT_MSEC
517         snprintf(format, sizeof(format),
518                 "[%%3d] %%-%ds | \ttotal : %%4ld\tcalls : %%3ld\tavg : %%4ld\tmin : %%4ld\tmax : %%4ld\tstart : %%4lu\tend : %%4lu\tunpair : %%3ld\n",
519                 mf_g_accum_longest_name);
520         fprintf(fp, "BEGIN RESULT ACCUM============================ : NumOfItems : %d, unit(msec)\n", mf_g_accum_index);
521 #else
522         snprintf(format, sizeof(format),
523                 "[%%3d] %%-%ds : \ttotal : %%ld\t:calls : %%ld\t:avg : %%ld\tmin : %%ld\tmax : %%ld\tstart : %%lu\tend : %%lu\tunpair : %%ld\n",
524                 mf_g_accum_longest_name);
525         fprintf(fp, "BEGIN RESULT ACCUM============================ : NumOfItems : %d, unit(usec)\n", mf_g_accum_index);
526 #endif
527
528         for (i = 0; i < mf_g_accum_index; i++) {
529                 /*prevent 'devide by zero' error */
530                 if (mf_g_accums[i]->num_calls == 0)
531                         mf_g_accums[i]->num_calls = 1;
532
533                 fprintf(fp, format, i, mf_g_accums[i]->name, mf_g_accums[i]->elapsed_accum, mf_g_accums[i]->num_calls,
534                         (mf_g_accums[i]->elapsed_accum == 0) ? 0 : (int)(mf_g_accums[i]->elapsed_accum / mf_g_accums[i]->num_calls),
535                         mf_g_accums[i]->elapsed_min,
536                         mf_g_accums[i]->elapsed_max,
537                         mf_g_accums[i]->first_start - mf_g_accum_first_time,
538                         mf_g_accums[i]->last_end - mf_g_accum_first_time, mf_g_accums[i]->num_unpair);
539         }
540         fprintf(fp, "END RESULT ACCUM  ============================\n");
541
542         if (direction == MF_TA_SHOW_FILE)
543                 fclose(fp);
544 }