xref: /aosp_15_r20/trusty/kernel/app/dpctest/dpctest.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2019, Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker  *
4*344aa361SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker  * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker  * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker  * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker  * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker  * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker  *
12*344aa361SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker  *
15*344aa361SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker  */
23*344aa361SAndroid Build Coastguard Worker 
24*344aa361SAndroid Build Coastguard Worker #include <err.h>
25*344aa361SAndroid Build Coastguard Worker #include <kernel/timer.h>
26*344aa361SAndroid Build Coastguard Worker #include <lib/dpc.h>
27*344aa361SAndroid Build Coastguard Worker #include <lib/unittest/unittest.h>
28*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
29*344aa361SAndroid Build Coastguard Worker 
30*344aa361SAndroid Build Coastguard Worker #define TEST_REQUEUE_CNT 10
31*344aa361SAndroid Build Coastguard Worker 
32*344aa361SAndroid Build Coastguard Worker struct dpc_test_ctx {
33*344aa361SAndroid Build Coastguard Worker     struct dpc work;
34*344aa361SAndroid Build Coastguard Worker     uint32_t count;
35*344aa361SAndroid Build Coastguard Worker     uint32_t in_atomic_requeue_cnt;
36*344aa361SAndroid Build Coastguard Worker     uint32_t in_thread_requeue_cnt;
37*344aa361SAndroid Build Coastguard Worker     struct event evt;
38*344aa361SAndroid Build Coastguard Worker     struct timer tmr;
39*344aa361SAndroid Build Coastguard Worker };
40*344aa361SAndroid Build Coastguard Worker 
dpc_test_timer_callback(struct timer * t,lk_time_ns_t now,void * arg)41*344aa361SAndroid Build Coastguard Worker static enum handler_return dpc_test_timer_callback(struct timer* t,
42*344aa361SAndroid Build Coastguard Worker                                                    lk_time_ns_t now,
43*344aa361SAndroid Build Coastguard Worker                                                    void* arg) {
44*344aa361SAndroid Build Coastguard Worker     struct dpc_test_ctx* ctx = arg;
45*344aa361SAndroid Build Coastguard Worker 
46*344aa361SAndroid Build Coastguard Worker     ctx->in_atomic_requeue_cnt++;
47*344aa361SAndroid Build Coastguard Worker     dpc_enqueue_work(NULL, &ctx->work, false);
48*344aa361SAndroid Build Coastguard Worker     return INT_RESCHEDULE;
49*344aa361SAndroid Build Coastguard Worker }
50*344aa361SAndroid Build Coastguard Worker 
dpc_test_callback(struct dpc * work)51*344aa361SAndroid Build Coastguard Worker static void dpc_test_callback(struct dpc* work) {
52*344aa361SAndroid Build Coastguard Worker     struct dpc_test_ctx* ctx = containerof(work, struct dpc_test_ctx, work);
53*344aa361SAndroid Build Coastguard Worker 
54*344aa361SAndroid Build Coastguard Worker     if (ctx->count > TEST_REQUEUE_CNT / 2) {
55*344aa361SAndroid Build Coastguard Worker         /* requeue work from irq context */
56*344aa361SAndroid Build Coastguard Worker         ctx->count--;
57*344aa361SAndroid Build Coastguard Worker         timer_set_oneshot_ns(&ctx->tmr, 10 * 1000 * 1000,
58*344aa361SAndroid Build Coastguard Worker                              dpc_test_timer_callback, ctx);
59*344aa361SAndroid Build Coastguard Worker     } else if (ctx->count) {
60*344aa361SAndroid Build Coastguard Worker         /* requeue work from thread context */
61*344aa361SAndroid Build Coastguard Worker         ctx->count--;
62*344aa361SAndroid Build Coastguard Worker         ctx->in_thread_requeue_cnt++;
63*344aa361SAndroid Build Coastguard Worker         dpc_enqueue_work(NULL, &ctx->work, false);
64*344aa361SAndroid Build Coastguard Worker     } else {
65*344aa361SAndroid Build Coastguard Worker         /* we are done here */
66*344aa361SAndroid Build Coastguard Worker         event_signal(&ctx->evt, true);
67*344aa361SAndroid Build Coastguard Worker     }
68*344aa361SAndroid Build Coastguard Worker }
69*344aa361SAndroid Build Coastguard Worker 
TEST(dpctest,test1)70*344aa361SAndroid Build Coastguard Worker TEST(dpctest, test1) {
71*344aa361SAndroid Build Coastguard Worker     status_t rc;
72*344aa361SAndroid Build Coastguard Worker     struct dpc_test_ctx test_ctx;
73*344aa361SAndroid Build Coastguard Worker 
74*344aa361SAndroid Build Coastguard Worker     /* Init test context */
75*344aa361SAndroid Build Coastguard Worker     test_ctx.count = TEST_REQUEUE_CNT;
76*344aa361SAndroid Build Coastguard Worker     test_ctx.in_atomic_requeue_cnt = 0;
77*344aa361SAndroid Build Coastguard Worker     test_ctx.in_thread_requeue_cnt = 0;
78*344aa361SAndroid Build Coastguard Worker     timer_initialize(&test_ctx.tmr);
79*344aa361SAndroid Build Coastguard Worker     event_init(&test_ctx.evt, false, EVENT_FLAG_AUTOUNSIGNAL);
80*344aa361SAndroid Build Coastguard Worker     dpc_work_init(&test_ctx.work, dpc_test_callback, 0);
81*344aa361SAndroid Build Coastguard Worker 
82*344aa361SAndroid Build Coastguard Worker     /* init dpc work and queue it on default queue */
83*344aa361SAndroid Build Coastguard Worker     dpc_enqueue_work(NULL, &test_ctx.work, false);
84*344aa361SAndroid Build Coastguard Worker 
85*344aa361SAndroid Build Coastguard Worker     /* wait for complete */
86*344aa361SAndroid Build Coastguard Worker     rc = event_wait_timeout(&test_ctx.evt, 1000);
87*344aa361SAndroid Build Coastguard Worker 
88*344aa361SAndroid Build Coastguard Worker     /* check results */
89*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(NO_ERROR, rc);
90*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, test_ctx.count);
91*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(TEST_REQUEUE_CNT / 2, test_ctx.in_atomic_requeue_cnt);
92*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(TEST_REQUEUE_CNT / 2, test_ctx.in_thread_requeue_cnt);
93*344aa361SAndroid Build Coastguard Worker }
94*344aa361SAndroid Build Coastguard Worker 
95*344aa361SAndroid Build Coastguard Worker PORT_TEST(dpctest, "com.android.kernel.dpc-unittest");
96