int_ms_to_timeout.cocci 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // Copyright (c) 2019-2020 Nordic Semiconductor ASA
  2. // SPDX-License-Identifer: Apache-2.0
  3. // Convert legacy integer timeouts to timeout API
  4. //
  5. // Some existing code assumes that timeout parameters are provided as
  6. // integer milliseconds, when they were intended to be timeout values
  7. // produced by specific constants and macros. Convert integer
  8. // literals and parameters to the desired equivalent
  9. //
  10. // A few expressions that are clearly integer values are also
  11. // converted.
  12. //
  13. // Options: --include-headers
  14. virtual patch
  15. virtual report
  16. // ** Handle timeouts at the last position of kernel API arguments
  17. // Base rule provides the complex identifier regular expression
  18. @r_last_timeout@
  19. identifier last_timeout =~ "(?x)^k_
  20. ( delayed_work_submit(|_to_queue)
  21. | futex_wait
  22. | mbox_data_block_get
  23. | (mbox|msgq)_get
  24. | mem_(pool|slab)_alloc
  25. | mutex_lock
  26. | pipe_(get|put)
  27. | poll
  28. | queue_get
  29. | sem_take
  30. | sleep
  31. | stack_pop
  32. | thread_create
  33. | timer_start
  34. | work_poll_submit(|_to_queue)
  35. )$";
  36. @@
  37. last_timeout(...)
  38. // Identify call sites where an identifier is used for the timeout
  39. @r_last_timeout_id
  40. extends r_last_timeout
  41. @
  42. identifier D;
  43. position p;
  44. @@
  45. last_timeout@p(..., D)
  46. // Select call sites where a constant literal (not identifier) is used
  47. // for the timeout and replace the constant with the appropriate macro
  48. @r_last_timeout_const_patch
  49. extends r_last_timeout
  50. depends on patch
  51. @
  52. constant C;
  53. position p != r_last_timeout_id.p;
  54. @@
  55. last_timeout@p(...,
  56. (
  57. - 0
  58. + K_NO_WAIT
  59. |
  60. - -1
  61. + K_FOREVER
  62. |
  63. - C
  64. + K_MSEC(C)
  65. )
  66. )
  67. @r_last_timeout_const_report
  68. extends r_last_timeout
  69. depends on report
  70. @
  71. constant C;
  72. position p != r_last_timeout_id.p;
  73. @@
  74. last_timeout@p(..., C)
  75. @script:python
  76. depends on report
  77. @
  78. fn << r_last_timeout.last_timeout;
  79. p << r_last_timeout_const_report.p;
  80. C << r_last_timeout_const_report.C;
  81. @@
  82. msg = "WARNING: replace constant {} with timeout in {}".format(C, fn)
  83. coccilib.report.print_report(p[0], msg);
  84. // ** Handle call sites where a timeout is specified by an expression
  85. // ** scaled by MSEC_PER_SEC and replace with the corresponding
  86. // ** K_SECONDS() expression.
  87. @r_last_timeout_scaled_patch
  88. extends r_last_timeout
  89. depends on patch
  90. @
  91. // identifier K_MSEC =~ "^K_MSEC$";
  92. symbol K_MSEC;
  93. identifier MSEC_PER_SEC =~ "^MSEC_PER_SEC$";
  94. expression V;
  95. position p;
  96. @@
  97. last_timeout@p(...,
  98. (
  99. - MSEC_PER_SEC
  100. + K_SECONDS(1)
  101. |
  102. - V * MSEC_PER_SEC
  103. + K_SECONDS(V)
  104. |
  105. - K_MSEC(MSEC_PER_SEC)
  106. + K_SECONDS(1)
  107. |
  108. - K_MSEC(V * MSEC_PER_SEC)
  109. + K_SECONDS(V)
  110. )
  111. )
  112. @r_last_timeout_scaled_report_req
  113. extends r_last_timeout
  114. depends on report
  115. @
  116. identifier MSEC_PER_SEC =~ "^MSEC_PER_SEC$";
  117. expression V;
  118. position p;
  119. @@
  120. last_timeout@p(...,
  121. (
  122. MSEC_PER_SEC
  123. | V * MSEC_PER_SEC
  124. )
  125. )
  126. @r_last_timeout_scaled_report_opt
  127. extends r_last_timeout
  128. depends on report
  129. @
  130. identifier MSEC_PER_SEC =~ "^MSEC_PER_SEC$";
  131. expression V;
  132. position p;
  133. @@
  134. last_timeout@p(...,
  135. (
  136. K_MSEC(MSEC_PER_SEC)
  137. | K_MSEC(V * MSEC_PER_SEC)
  138. )
  139. )
  140. @script:python
  141. depends on report
  142. @
  143. fn << r_last_timeout.last_timeout;
  144. p << r_last_timeout_scaled_report_req.p;
  145. @@
  146. msg = "WARNING: use K_SECONDS() for timeout in {}".format(fn)
  147. coccilib.report.print_report(p[0], msg);
  148. @script:python
  149. depends on report
  150. @
  151. fn << r_last_timeout.last_timeout;
  152. p << r_last_timeout_scaled_report_opt.p;
  153. @@
  154. msg = "NOTE: use K_SECONDS() for timeout in {}".format(fn)
  155. coccilib.report.print_report(p[0], msg);
  156. // ** Handle call sites where an integer parameter is used in a
  157. // ** position that requires a timeout value.
  158. @r_last_timeout_int_param_patch
  159. extends r_last_timeout
  160. depends on patch
  161. @
  162. identifier FN;
  163. identifier P;
  164. typedef int32_t, uint32_t;
  165. @@
  166. FN(...,
  167. (int
  168. |int32_t
  169. |uint32_t
  170. )
  171. P, ...) {
  172. ...
  173. last_timeout(...,
  174. -P
  175. +K_MSEC(P)
  176. )
  177. ...
  178. }
  179. @r_last_timeout_int_param_report
  180. extends r_last_timeout
  181. depends on report
  182. @
  183. identifier FN;
  184. identifier P;
  185. position p;
  186. typedef int32_t, uint32_t;
  187. @@
  188. FN(...,
  189. (int
  190. |int32_t
  191. |uint32_t
  192. )
  193. P, ...) {
  194. ...
  195. last_timeout@p(..., P)
  196. ...
  197. }
  198. @script:python
  199. depends on report
  200. @
  201. param << r_last_timeout_int_param_report.P;
  202. fn << r_last_timeout.last_timeout;
  203. p << r_last_timeout_int_param_report.p;
  204. @@
  205. msg = "WARNING: replace integer parameter {} with timeout in {}".format(param, fn)
  206. coccilib.report.print_report(p[0], msg);
  207. // ** Convert timeout-valued delays in K_THREAD_DEFINE with durations
  208. // ** in milliseconds
  209. // Select declarers where the startup delay is a timeout expression
  210. // and replace with the corresponding millisecond duration.
  211. @r_thread_decl_patch
  212. depends on patch@
  213. declarer name K_THREAD_DEFINE;
  214. identifier K_NO_WAIT =~ "^K_NO_WAIT$";
  215. identifier K_FOREVER =~ "^K_FOREVER$";
  216. expression E;
  217. position p;
  218. @@
  219. K_THREAD_DEFINE@p(...,
  220. (
  221. - K_NO_WAIT
  222. + 0
  223. |
  224. - K_FOREVER
  225. + -1
  226. |
  227. - K_MSEC(E)
  228. + E
  229. )
  230. );
  231. //
  232. @r_thread_decl_report
  233. depends on report@
  234. declarer name K_THREAD_DEFINE;
  235. identifier K_NO_WAIT =~ "^K_NO_WAIT$";
  236. identifier K_FOREVER =~ "^K_FOREVER$";
  237. expression V;
  238. position p;
  239. @@
  240. K_THREAD_DEFINE@p(...,
  241. (
  242. K_NO_WAIT
  243. |
  244. K_FOREVER
  245. |
  246. K_MSEC(V)
  247. )
  248. );
  249. @script:python
  250. depends on report
  251. @
  252. p << r_thread_decl_report.p;
  253. @@
  254. msg = "WARNING: replace timeout-valued delay with millisecond duration".format()
  255. coccilib.report.print_report(p[0], msg);
  256. // ** Handle k_timer_start where the second (not last) argument is a
  257. // ** constant literal.
  258. // Select call sites where an identifier is used for the duration timeout
  259. @r_timer_duration@
  260. expression T;
  261. identifier D;
  262. expression I;
  263. position p;
  264. @@
  265. k_timer_start@p(T, D, I)
  266. // Select call sites where a constant literal (not identifier) is used
  267. // for the timeout and replace the constant with the appropriate macro
  268. @depends on patch@
  269. expression T;
  270. constant C;
  271. expression I;
  272. position p != r_timer_duration.p;
  273. @@
  274. k_timer_start@p(T,
  275. (
  276. - 0
  277. + K_NO_WAIT
  278. |
  279. - -1
  280. + K_FOREVER
  281. |
  282. - C
  283. + K_MSEC(C)
  284. )
  285. , I)
  286. @r_timer_duration_report
  287. depends on report
  288. @
  289. expression T;
  290. constant C;
  291. expression I;
  292. position p != r_timer_duration.p;
  293. @@
  294. k_timer_start@p(T, C, I)
  295. @script:python
  296. depends on report
  297. @
  298. p << r_timer_duration_report.p;
  299. C << r_timer_duration_report.C;
  300. @@
  301. msg = "WARNING: replace constant {} with duration timeout in k_timer_start".format(C)
  302. coccilib.report.print_report(p[0], msg);