// 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);