332 lines
6.0 KiB
Plaintext
332 lines
6.0 KiB
Plaintext
// Copyright (c) 2019-2020 Nordic Semiconductor ASA
|
|
// SPDX-License-Identifer: 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);
|