cpulatency.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include <errno.h>
  2. #include <fcntl.h>
  3. #include <stdint.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. static int32_t pm_qos_fd = -1;
  9. int32_t
  10. low_latency(
  11. int32_t target
  12. )
  13. {
  14. uint32_t sot = sizeof ( target );
  15. uint32_t cwbytes = 0;
  16. if (sot <= 1)
  17. {
  18. fprintf(stderr, "Error: Invalid target size: %u bytes.\n", sot);
  19. return ( 1 );
  20. }
  21. if (pm_qos_fd >= 0)
  22. {
  23. fprintf(stderr, "Error: PM QoS fd: %d.\n", pm_qos_fd);
  24. return ( 1 );
  25. }
  26. pm_qos_fd = open("/dev/cpu_dma_latency", O_RDWR);
  27. if (pm_qos_fd < 0)
  28. {
  29. fprintf(
  30. stderr,
  31. "Error: Failed to open PM QoS device: %s.\n",
  32. strerror(errno));
  33. return ( 1 );
  34. }
  35. cwbytes = write(pm_qos_fd, &target, sot);
  36. if (cwbytes != sot)
  37. {
  38. fprintf(
  39. stderr,
  40. "Error: Only wrote %u out of %u bytes requested.\n",
  41. cwbytes,
  42. sot);
  43. return ( 1 );
  44. }
  45. fprintf(stdout, "CPU DMA latency limit set to %d μs\n", target);
  46. return ( 0 );
  47. }
  48. int
  49. main(
  50. int argc,
  51. char *argv[]
  52. )
  53. {
  54. int32_t llr = 1;
  55. if (!( argc >= 2 ))
  56. {
  57. fprintf(
  58. stdout,
  59. "%s: Set PM QoS CPU DMA latency limit\n \
  60. \rUsage: %s <latency limit in μs> (0 ⟷ %d)\n",
  61. argv[0],
  62. argv[0],
  63. INT32_MAX);
  64. return ( 1 );
  65. }
  66. uint32_t ditr;
  67. size_t dsiz = snprintf(NULL, 0, "%d", INT32_MAX);
  68. char *dstr = malloc(dsiz + 1);
  69. if (dstr == NULL || !dstr)
  70. {
  71. fprintf(stderr, "Error: malloc() failure.\n");
  72. exit(1);
  73. }
  74. size_t dmax = snprintf(dstr, dsiz + 1, "%d", INT32_MAX);
  75. free(dstr);
  76. size_t dlen = strnlen(argv[1], dmax);
  77. size_t dact = strlen(argv[1]);
  78. if (dact > dmax)
  79. {
  80. argv[1][0] = 0;
  81. }
  82. for (ditr = 0; ditr < (uint32_t)dlen; ++ditr)
  83. {
  84. if (argv[1][ditr] < 48 || argv[1][ditr] > 57)
  85. {
  86. fprintf(stderr, "Error: Value must be a non-negative integer.\n");
  87. return ( 1 );
  88. }
  89. }
  90. int64_t target = atoi(argv[1]);
  91. if ((int32_t)target < 0 || target > INT32_MAX)
  92. {
  93. fprintf(stderr, "Error: Value out of range (0 ⟷ %d)\n", INT32_MAX);
  94. return ( 1 );
  95. }
  96. llr = low_latency((int32_t)target);
  97. if (llr != 0)
  98. {
  99. exit(llr);
  100. }
  101. pause();
  102. fprintf(
  103. stderr,
  104. "Warning: pause() failed, falling back to sleep().\n");
  105. while (!sleep(999))
  106. {
  107. ;
  108. }
  109. fprintf(stderr, "Error: sleep() failed, aborting.\n");
  110. exit(1);
  111. return ( 2 );
  112. }