2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
27 #include <sys/utsname.h>
28 #include <sys/resource.h>
34 static void __mf_ta_free_cps(void);
35 static int __mf_ta_get_cp_index(char *name);
37 static void __mf_ta_free_accums(void);
38 static int __mf_ta_get_accum_index(char *name);
40 mf_ta_checkpoint **mf_g_cps = NULL;
41 static int mf_g_cp_index = 0;
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;
54 mf_g_cps = (mf_ta_checkpoint **) malloc(MF_TA_MAX_CHECKPOINT * sizeof(mf_ta_checkpoint *));
58 mf_g_accums = (mf_ta_accum_item **) malloc(MF_TA_MAX_CHECKPOINT * sizeof(mf_ta_accum_item *));
62 mf_g_accum_first_time = 0xFFFFFFFF;
67 int mf_ta_release(void)
73 __mf_ta_free_accums();
75 mf_g_accum_first_time = 0xFFFFFFFF;
80 void mf_ta_set_enable(int enable)
82 printf("MF_TA : setting enable to %d\n", enable);
86 int mf_ta_get_numof_checkpoints()
91 char *mf_ta_fmt(const char *fmt, ...)
93 static char ta_buf[512];
96 memset(ta_buf, '\0', 512);
99 vsnprintf(ta_buf, 512, fmt, args);
106 int mf_ta_add_checkpoint(char *name, int show, char *filename, int line)
108 mf_ta_checkpoint *cp = NULL;
117 if (mf_g_cp_index == MF_TA_MAX_CHECKPOINT)
123 if (strlen(name) == 0)
126 cp = (mf_ta_checkpoint *) malloc(sizeof(mf_ta_checkpoint));
130 cp->name = (char *)malloc(strlen(name) + 1);
135 strncpy(cp->name, name, strlen(name));
138 printf("[CHECK-POINT] %s...(%s:%d)\n", name, filename, line);
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;
146 mf_g_cps[mf_g_cp_index] = cp;
153 void mf_ta_show_checkpoints(void)
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);
163 printf("END RESULT ============================\n");
166 void mf_ta_show_diff(char *name1, char *name2)
172 printf("Time takes from [%s] to [%s] : %ld us.\n", name1, name2, mf_ta_get_diff(name1, name2));
175 unsigned long mf_ta_get_diff(char *name1, char *name2)
183 /* fail if bad param. */
184 if (!name1 || !name2)
188 if (strcmp(name1, name2) == 0)
192 if ((cp1 = __mf_ta_get_cp_index(name1)) == -1)
195 if ((cp2 = __mf_ta_get_cp_index(name2)) == -1)
199 * return value must be positive value.
200 * bcz the value of higher index of mf_g_cps always higher than lower one.
202 return mf_g_cps[cp2]->timestamp - mf_g_cps[cp1]->timestamp;
206 static int __mf_ta_get_cp_index(char *name)
213 for (i = 0; i < mf_g_cp_index; i++) {
214 if (strcmp(name, mf_g_cps[i]->name) == 0)
221 static int __mf_ta_get_accum_index(char *name)
228 for (i = 0; i < mf_g_accum_index; i++) {
229 if (strcmp(name, mf_g_accums[i]->name) == 0)
236 static void __mf_ta_free_cps(void)
243 for (i = 0; i < mf_g_cp_index; i++) {
245 if (mf_g_cps[i]->name)
246 free(mf_g_cps[i]->name);
260 static void __mf_ta_free_accums(void)
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);
272 free(mf_g_accums[i]);
274 mf_g_accums[i] = NULL;
278 mf_g_accum_index = 0;
279 mf_g_accum_longest_name = 0;
286 int mf_ta_accum_item_begin(char *name, int show, char *filename, int line)
288 mf_ta_accum_item *accum = NULL;
301 if (mf_g_accum_index == MF_TA_MAX_ACCUM)
307 name_len = strlen(name);
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));
318 memset(accum, 0, sizeof(mf_ta_accum_item));
319 accum->elapsed_min = 0xFFFFFFFF;
321 accum->name = (char *)malloc(name_len + 1);
326 memset(accum->name, 0, name_len + 1);
327 strncpy(accum->name, name, strlen(name));
329 /* add it to list. */
330 mf_g_accums[mf_g_accum_index] = accum;
333 if (mf_g_accum_longest_name < name_len)
334 mf_g_accum_longest_name = name_len;
337 accum = mf_g_accums[index];
340 /*verify pairs of begin, end. */
341 if (accum->on_estimate) {
342 printf("[%s] is not 'end'ed!\n", accum->name);
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;
352 accum->on_estimate = 1;
354 if (accum->first_start == 0) { /* assum that timestamp never could be zero. */
355 accum->first_start = accum->timestamp;
357 if (mf_g_accum_first_time > accum->first_start)
358 mf_g_accum_first_time = accum->first_start;
362 printf("[ACCUM BEGIN] %s : %ld ---(%s:%d)\n", name, accum->timestamp, filename, line);
369 int mf_ta_accum_item_end(char *name, int show, char *filename, int line)
371 mf_ta_accum_item *accum = NULL;
372 unsigned int tval = 0;
383 /* get time first for more accuracy. */
384 gettimeofday(&t, NULL);
386 if (mf_g_accum_index == MF_TA_MAX_ACCUM)
392 if (strlen(name) == 0)
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);
401 accum = mf_g_accums[index];
403 /* verify pairs of begin, end. */
404 if (!accum->on_estimate) {
405 printf("[%s] is not 'begin' yet!\n", accum->name);
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;
415 /* update last_end */
416 accum->last_end = tval;
418 /* make get elapsed time. */
419 tval = tval - accum->timestamp;
422 accum->elapsed_max = tval > accum->elapsed_max ? tval : accum->elapsed_max;
423 accum->elapsed_min = tval < accum->elapsed_min ? tval : accum->elapsed_min;
426 printf("[ACCUM END] %s : %ld + %u ---(%s:%d)\n", name, accum->elapsed_accum, tval, filename, line);
428 /* add elapsed time */
429 accum->elapsed_accum += tval;
430 accum->on_estimate = 0;
435 void __mf_ta_print_some_info(FILE *fp)
442 fprintf(fp, "\nb~ b~ b~\n\n");
445 /* General infomation */
448 char hostname[MF_TA_BUFF_SIZE] = { '\0', };
449 char buf[MF_TA_BUFF_SIZE] = {'\0', };
451 struct rusage r_usage;
453 fprintf(fp, "\n[[ General info ]]\n");
457 ctime_r(&t_val, buf);
458 fprintf(fp, "Date : %s", buf);
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);
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);
478 /* host environment variables */
480 extern char **environ;
481 char **env = environ;
483 fprintf(fp, "\n[[ Host environment variables ]]\n");
485 fprintf(fp, "%s\n", *env);
491 void mf_ta_show_accum_result(int direction)
501 case MF_TA_SHOW_STDOUT:
504 case MF_TA_SHOW_STDERR:
507 case MF_TA_SHOW_FILE:
509 fp = fopen(MF_TA_RESULT_FILE, "wt");
514 __mf_ta_print_some_info(fp);
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);
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);
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;
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);
540 fprintf(fp, "END RESULT ACCUM ============================\n");
542 if (direction == MF_TA_SHOW_FILE)