/commands/time/time.c

https://bitbucket.org/gthummalapalle/minix-project2 · C · 187 lines · 155 code · 24 blank · 8 comment · 24 complexity · a5c4eee2d8d91645fc61b5f20df504ce MD5 · raw file

  1. /* time - time a command Authors: Andy Tanenbaum & Michiel Huisjes */
  2. #define NEW 1
  3. #include <sys/types.h>
  4. #include <sys/times.h>
  5. #include <limits.h>
  6. #include <time.h>
  7. #include <signal.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <sys/wait.h>
  11. #include <minix/minlib.h>
  12. // #include <minix/u64.h>
  13. #include <stdio.h>
  14. /* -DNEW prints time to 0.01 sec. */
  15. #ifdef NEW
  16. #define HUNDREDTHS 1
  17. #endif
  18. char **args;
  19. char *name;
  20. int digit_seen;
  21. char a[] = " . \0";
  22. int main(int argc, char **argv);
  23. void print_time(clock_t t);
  24. void twin(int n, char *p);
  25. void execute(void);
  26. int main(argc, argv)
  27. int argc;
  28. char *argv[];
  29. {
  30. int cycles = 0;
  31. struct tms pre_buf, post_buf;
  32. int status, pid;
  33. #if _VMD_EXT
  34. struct timeval start_time, end_time;
  35. #else
  36. struct tms dummy;
  37. int start_time, end_time;
  38. #endif
  39. u64_t start_tsc, end_tsc, spent_tsc;
  40. clock_t real_time;
  41. int c;
  42. if (argc == 1) exit(0);
  43. while((c=getopt(argc, argv, "C")) != EOF) {
  44. switch(c) {
  45. case 'C':
  46. cycles = 1;
  47. break;
  48. default:
  49. fprintf(stderr, "usage: time [-C] <command>\n");
  50. exit(1);
  51. }
  52. }
  53. argv += optind;
  54. argc -= optind;
  55. args = &argv[0];
  56. name = argv[0];
  57. /* Get real time at start of run. */
  58. #if _VMD_EXT
  59. (void) sysutime(UTIME_TIMEOFDAY, &start_time);
  60. #else
  61. start_time = times(&dummy);
  62. #endif
  63. read_tsc_64(&start_tsc);
  64. /* Fork off child. */
  65. if ((pid = fork()) < 0) {
  66. std_err("Cannot fork\n");
  67. exit(1);
  68. }
  69. if (pid == 0) execute();
  70. /* Parent is the time program. Disable interrupts and wait. */
  71. signal(SIGINT, SIG_IGN);
  72. signal(SIGQUIT, SIG_IGN);
  73. do {
  74. times(&pre_buf);
  75. } while (wait(&status) != pid);
  76. read_tsc_64(&end_tsc);
  77. spent_tsc = end_tsc - start_tsc;
  78. #if _VMD_EXT
  79. (void) sysutime(UTIME_TIMEOFDAY, &end_time);
  80. real_time = (end_time.tv_sec - start_time.tv_sec) * CLOCKS_PER_SEC
  81. + (end_time.tv_usec - start_time.tv_usec) * CLOCKS_PER_SEC / 1000000;
  82. #else
  83. end_time = times(&dummy);
  84. real_time = (end_time - start_time);
  85. #endif
  86. if ((status & 0377) != 0) std_err("Command terminated abnormally.\n");
  87. times(&post_buf);
  88. if(cycles) {
  89. fprintf(stderr, "%qd tsc ", spent_tsc);
  90. }
  91. /* Print results. -DNEW enables time on one line to 0.01 sec */
  92. #ifndef NEW
  93. std_err("real ");
  94. print_time(real_time);
  95. std_err("\nuser ");
  96. print_time(post_buf.tms_cutime - pre_buf.tms_cutime);
  97. std_err("\nsys ");
  98. print_time(post_buf.tms_cstime - pre_buf.tms_cstime);
  99. std_err("\n");
  100. #else
  101. print_time(real_time);
  102. std_err(" real");
  103. print_time(post_buf.tms_cutime - pre_buf.tms_cutime);
  104. std_err(" user");
  105. print_time(post_buf.tms_cstime - pre_buf.tms_cstime);
  106. std_err(" sys\n");
  107. #endif
  108. return((status & 0377) ? -1 : (status >> 8));
  109. }
  110. void print_time(t)
  111. register clock_t t;
  112. {
  113. /* Print the time 't' in hours: minutes: seconds. 't' is in ticks. */
  114. int hours, minutes, seconds, hundredths, i;
  115. u32_t system_hz;
  116. system_hz = (u32_t) sysconf(_SC_CLK_TCK);
  117. digit_seen = 0;
  118. for (i = 0; i < 8; i++) a[i] = ' ';
  119. hours = (int) (t / ((clock_t) 3600 * system_hz));
  120. t -= (clock_t) hours * 3600 * system_hz;
  121. minutes = (int) (t / ((clock_t) 60 * system_hz));
  122. t -= (clock_t) minutes * 60 * system_hz;
  123. seconds = (int) (t / system_hz);
  124. t -= (clock_t) seconds * system_hz;
  125. hundredths = (int) (t * 100 / system_hz);
  126. if (hours) {
  127. twin(hours, &a[0]);
  128. a[2] = ':';
  129. }
  130. if (minutes || digit_seen) {
  131. twin(minutes, &a[3]);
  132. a[5] = ':';
  133. }
  134. if (seconds || digit_seen)
  135. twin(seconds, &a[6]);
  136. else
  137. a[7] = '0';
  138. a[9] = hundredths / 10 + '0';
  139. #ifdef HUNDREDTHS /* tenths used to be enough */
  140. a[10] = hundredths % 10 + '0';
  141. #endif
  142. std_err(a);
  143. }
  144. void twin(n, p)
  145. int n;
  146. char *p;
  147. {
  148. char c1, c2;
  149. c1 = (n / 10) + '0';
  150. c2 = (n % 10) + '0';
  151. if (digit_seen == 0 && c1 == '0') c1 = ' ';
  152. *p++ = c1;
  153. *p++ = c2;
  154. if (n > 0) digit_seen = 1;
  155. }
  156. void execute()
  157. {
  158. execvp(name, args);
  159. std_err("Cannot execute ");
  160. std_err(name);
  161. std_err("\n");
  162. exit(-1);
  163. }