You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
331 lines
6.0 KiB
331 lines
6.0 KiB
// Copyright (c) 2019-2020 Nordic Semiconductor ASA |
|
// SPDX-License-Identifier: Apache-2.0 |
|
|
|
// Convert legacy integer timeouts to timeout API |
|
// |
|
// 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 integer |
|
// literals and parameters to the desired equivalent |
|
// |
|
// A few expressions that are clearly integer values are also |
|
// converted. |
|
// |
|
// 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); |
|
|
|
// ** Handle call sites where a timeout is specified by an expression |
|
// ** scaled by MSEC_PER_SEC and replace with the corresponding |
|
// ** K_SECONDS() expression. |
|
|
|
@r_last_timeout_scaled_patch |
|
extends r_last_timeout |
|
depends on patch |
|
@ |
|
// identifier K_MSEC =~ "^K_MSEC$"; |
|
symbol K_MSEC; |
|
identifier MSEC_PER_SEC =~ "^MSEC_PER_SEC$"; |
|
expression V; |
|
position p; |
|
@@ |
|
last_timeout@p(..., |
|
( |
|
- MSEC_PER_SEC |
|
+ K_SECONDS(1) |
|
| |
|
- V * MSEC_PER_SEC |
|
+ K_SECONDS(V) |
|
| |
|
- K_MSEC(MSEC_PER_SEC) |
|
+ K_SECONDS(1) |
|
| |
|
- K_MSEC(V * MSEC_PER_SEC) |
|
+ K_SECONDS(V) |
|
) |
|
) |
|
|
|
@r_last_timeout_scaled_report_req |
|
extends r_last_timeout |
|
depends on report |
|
@ |
|
identifier MSEC_PER_SEC =~ "^MSEC_PER_SEC$"; |
|
expression V; |
|
position p; |
|
@@ |
|
last_timeout@p(..., |
|
( |
|
MSEC_PER_SEC |
|
| V * MSEC_PER_SEC |
|
) |
|
) |
|
|
|
@r_last_timeout_scaled_report_opt |
|
extends r_last_timeout |
|
depends on report |
|
@ |
|
identifier MSEC_PER_SEC =~ "^MSEC_PER_SEC$"; |
|
expression V; |
|
position p; |
|
@@ |
|
last_timeout@p(..., |
|
( |
|
K_MSEC(MSEC_PER_SEC) |
|
| K_MSEC(V * MSEC_PER_SEC) |
|
) |
|
) |
|
|
|
@script:python |
|
depends on report |
|
@ |
|
fn << r_last_timeout.last_timeout; |
|
p << r_last_timeout_scaled_report_req.p; |
|
@@ |
|
msg = "WARNING: use K_SECONDS() for timeout in {}".format(fn) |
|
coccilib.report.print_report(p[0], msg); |
|
|
|
@script:python |
|
depends on report |
|
@ |
|
fn << r_last_timeout.last_timeout; |
|
p << r_last_timeout_scaled_report_opt.p; |
|
@@ |
|
msg = "NOTE: use K_SECONDS() for timeout in {}".format(fn) |
|
coccilib.report.print_report(p[0], msg); |
|
|
|
// ** Handle call sites where an integer parameter is used in a |
|
// ** position that requires a timeout value. |
|
|
|
@r_last_timeout_int_param_patch |
|
extends r_last_timeout |
|
depends on patch |
|
@ |
|
identifier FN; |
|
identifier P; |
|
typedef int32_t, uint32_t; |
|
@@ |
|
FN(..., |
|
(int |
|
|int32_t |
|
|uint32_t |
|
) |
|
P, ...) { |
|
... |
|
last_timeout(..., |
|
-P |
|
+K_MSEC(P) |
|
) |
|
... |
|
} |
|
|
|
@r_last_timeout_int_param_report |
|
extends r_last_timeout |
|
depends on report |
|
@ |
|
identifier FN; |
|
identifier P; |
|
position p; |
|
typedef int32_t, uint32_t; |
|
@@ |
|
FN(..., |
|
(int |
|
|int32_t |
|
|uint32_t |
|
) |
|
P, ...) { |
|
... |
|
last_timeout@p(..., P) |
|
... |
|
} |
|
|
|
@script:python |
|
depends on report |
|
@ |
|
param << r_last_timeout_int_param_report.P; |
|
fn << r_last_timeout.last_timeout; |
|
p << r_last_timeout_int_param_report.p; |
|
@@ |
|
msg = "WARNING: replace integer parameter {} with timeout in {}".format(param, fn) |
|
coccilib.report.print_report(p[0], msg); |
|
|
|
// ** Convert timeout-valued delays in K_THREAD_DEFINE with durations |
|
// ** in milliseconds |
|
|
|
// Select declarers where the startup delay is a timeout expression |
|
// and replace with the corresponding millisecond duration. |
|
@r_thread_decl_patch |
|
depends on patch@ |
|
declarer name K_THREAD_DEFINE; |
|
identifier K_NO_WAIT =~ "^K_NO_WAIT$"; |
|
identifier K_FOREVER =~ "^K_FOREVER$"; |
|
expression E; |
|
position p; |
|
@@ |
|
K_THREAD_DEFINE@p(..., |
|
( |
|
- K_NO_WAIT |
|
+ 0 |
|
| |
|
- K_FOREVER |
|
+ -1 |
|
| |
|
- K_MSEC(E) |
|
+ E |
|
) |
|
); |
|
|
|
// |
|
@r_thread_decl_report |
|
depends on report@ |
|
declarer name K_THREAD_DEFINE; |
|
identifier K_NO_WAIT =~ "^K_NO_WAIT$"; |
|
identifier K_FOREVER =~ "^K_FOREVER$"; |
|
expression V; |
|
position p; |
|
@@ |
|
K_THREAD_DEFINE@p(..., |
|
( |
|
K_NO_WAIT |
|
| |
|
K_FOREVER |
|
| |
|
K_MSEC(V) |
|
) |
|
); |
|
|
|
|
|
@script:python |
|
depends on report |
|
@ |
|
p << r_thread_decl_report.p; |
|
@@ |
|
msg = "WARNING: replace timeout-valued delay with millisecond duration".format() |
|
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);
|
|
|