| // Copyright (c) 2019 Nordic Semiconductor ASA |
| // SPDX-License-Identifer: Apache-2.0 |
| |
| // Replace integer constant timeouts with K_MSEC variants |
| // |
| // Some existing code assumes that timeout parameters are provided as |
| // integer milliseconds, when they were intended to be timeout values |
| // produced by specific constants and macros. Convert the integer |
| // literals to the desired equivalent. |
| // |
| // Options: --include-headers |
| |
| virtual patch |
| virtual report |
| |
| // ** Handle timeouts at the last position of kernel API arguments |
| |
| // Base rule provides the complex identifier regular expression |
| @r_last_timeout@ |
| identifier last_timeout =~ "(?x)^k_ |
| ( delayed_work_submit(|_to_queue) |
| | futex_wait |
| | mbox_data_block_get |
| | (mbox|msgq)_get |
| | mem_(pool|slab)_alloc |
| | mutex_lock |
| | pipe_(get|put) |
| | poll |
| | queue_get |
| | sem_take |
| | sleep |
| | stack_pop |
| | thread_create |
| | timer_start |
| | work_poll_submit(|_to_queue) |
| )$"; |
| @@ |
| last_timeout(...) |
| |
| // Identify call sites where an identifier is used for the timeout |
| @r_last_timeout_id |
| extends r_last_timeout |
| @ |
| identifier D; |
| position p; |
| @@ |
| last_timeout@p(..., D) |
| |
| // Select call sites where a constant literal (not identifier) is used |
| // for the timeout and replace the constant with the appropriate macro |
| |
| @r_last_timeout_const_patch |
| extends r_last_timeout |
| depends on patch |
| @ |
| constant C; |
| position p != r_last_timeout_id.p; |
| @@ |
| last_timeout@p(..., |
| ( |
| - 0 |
| + K_NO_WAIT |
| | |
| - -1 |
| + K_FOREVER |
| | |
| - C |
| + K_MSEC(C) |
| ) |
| ) |
| |
| @r_last_timeout_const_report |
| extends r_last_timeout |
| depends on report |
| @ |
| constant C; |
| position p != r_last_timeout_id.p; |
| @@ |
| last_timeout@p(..., C) |
| |
| @script:python |
| depends on report |
| @ |
| fn << r_last_timeout.last_timeout; |
| p << r_last_timeout_const_report.p; |
| C << r_last_timeout_const_report.C; |
| @@ |
| msg = "WARNING: replace constant {} with timeout in {}".format(C, fn) |
| coccilib.report.print_report(p[0], msg); |
| |
| // ** Convert integer delays in K_THREAD_DEFINE to the appropriate macro |
| |
| // Identify declarers where an identifier is used for the delay |
| @r_thread_decl_id@ |
| declarer name K_THREAD_DEFINE; |
| identifier C; |
| position p; |
| @@ |
| K_THREAD_DEFINE@p(..., C); |
| |
| // Select declarers with constant literal delay and replace with |
| // appropriate macro |
| @depends on patch@ |
| declarer name K_THREAD_DEFINE; |
| constant C; |
| position p != r_thread_decl_id.p; |
| @@ |
| K_THREAD_DEFINE@p(..., |
| ( |
| - 0 |
| + K_NO_WAIT |
| | |
| - -1 |
| + K_FOREVER |
| | |
| - C |
| + K_MSEC(C) |
| ) |
| ); |
| |
| // Identify declarers where an identifier is used for the delay |
| @r_thread_decl_const |
| depends on report@ |
| declarer name K_THREAD_DEFINE; |
| constant C; |
| position p != r_thread_decl_id.p; |
| @@ |
| K_THREAD_DEFINE@p(..., C); |
| |
| |
| @script:python |
| depends on report |
| @ |
| C << r_thread_decl_const.C; |
| p << r_thread_decl_const.p; |
| @@ |
| msg = "WARNING: replace constant {} with timeout in K_THREAD_DEFINE".format(C) |
| coccilib.report.print_report(p[0], msg); |
| |
| // ** Handle k_timer_start where the second (not last) argument is a |
| // ** constant literal. |
| |
| // Select call sites where an identifier is used for the duration timeout |
| @r_timer_duration@ |
| expression T; |
| identifier D; |
| expression I; |
| position p; |
| @@ |
| k_timer_start@p(T, D, I) |
| |
| // Select call sites where a constant literal (not identifier) is used |
| // for the timeout and replace the constant with the appropriate macro |
| @depends on patch@ |
| expression T; |
| constant C; |
| expression I; |
| position p != r_timer_duration.p; |
| @@ |
| k_timer_start@p(T, |
| ( |
| - 0 |
| + K_NO_WAIT |
| | |
| - -1 |
| + K_FOREVER |
| | |
| - C |
| + K_MSEC(C) |
| ) |
| , I) |
| |
| @r_timer_duration_report |
| depends on report |
| @ |
| expression T; |
| constant C; |
| expression I; |
| position p != r_timer_duration.p; |
| @@ |
| k_timer_start@p(T, C, I) |
| |
| @script:python |
| depends on report |
| @ |
| p << r_timer_duration_report.p; |
| C << r_timer_duration_report.C; |
| @@ |
| msg = "WARNING: replace constant {} with duration timeout in k_timer_start".format(C) |
| coccilib.report.print_report(p[0], msg); |