xref: /openbmc/qemu/block/aio_task.c (revision 6e9b225f737d53afae8160d73da72ee8f38eb1a6)
1*6e9b225fSVladimir Sementsov-Ogievskiy /*
2*6e9b225fSVladimir Sementsov-Ogievskiy  * Aio tasks loops
3*6e9b225fSVladimir Sementsov-Ogievskiy  *
4*6e9b225fSVladimir Sementsov-Ogievskiy  * Copyright (c) 2019 Virtuozzo International GmbH.
5*6e9b225fSVladimir Sementsov-Ogievskiy  *
6*6e9b225fSVladimir Sementsov-Ogievskiy  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*6e9b225fSVladimir Sementsov-Ogievskiy  * of this software and associated documentation files (the "Software"), to deal
8*6e9b225fSVladimir Sementsov-Ogievskiy  * in the Software without restriction, including without limitation the rights
9*6e9b225fSVladimir Sementsov-Ogievskiy  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10*6e9b225fSVladimir Sementsov-Ogievskiy  * copies of the Software, and to permit persons to whom the Software is
11*6e9b225fSVladimir Sementsov-Ogievskiy  * furnished to do so, subject to the following conditions:
12*6e9b225fSVladimir Sementsov-Ogievskiy  *
13*6e9b225fSVladimir Sementsov-Ogievskiy  * The above copyright notice and this permission notice shall be included in
14*6e9b225fSVladimir Sementsov-Ogievskiy  * all copies or substantial portions of the Software.
15*6e9b225fSVladimir Sementsov-Ogievskiy  *
16*6e9b225fSVladimir Sementsov-Ogievskiy  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*6e9b225fSVladimir Sementsov-Ogievskiy  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*6e9b225fSVladimir Sementsov-Ogievskiy  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*6e9b225fSVladimir Sementsov-Ogievskiy  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*6e9b225fSVladimir Sementsov-Ogievskiy  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*6e9b225fSVladimir Sementsov-Ogievskiy  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22*6e9b225fSVladimir Sementsov-Ogievskiy  * THE SOFTWARE.
23*6e9b225fSVladimir Sementsov-Ogievskiy  */
24*6e9b225fSVladimir Sementsov-Ogievskiy 
25*6e9b225fSVladimir Sementsov-Ogievskiy #include "qemu/osdep.h"
26*6e9b225fSVladimir Sementsov-Ogievskiy #include "block/aio.h"
27*6e9b225fSVladimir Sementsov-Ogievskiy #include "block/aio_task.h"
28*6e9b225fSVladimir Sementsov-Ogievskiy 
29*6e9b225fSVladimir Sementsov-Ogievskiy struct AioTaskPool {
30*6e9b225fSVladimir Sementsov-Ogievskiy     Coroutine *main_co;
31*6e9b225fSVladimir Sementsov-Ogievskiy     int status;
32*6e9b225fSVladimir Sementsov-Ogievskiy     int max_busy_tasks;
33*6e9b225fSVladimir Sementsov-Ogievskiy     int busy_tasks;
34*6e9b225fSVladimir Sementsov-Ogievskiy     bool waiting;
35*6e9b225fSVladimir Sementsov-Ogievskiy };
36*6e9b225fSVladimir Sementsov-Ogievskiy 
37*6e9b225fSVladimir Sementsov-Ogievskiy static void coroutine_fn aio_task_co(void *opaque)
38*6e9b225fSVladimir Sementsov-Ogievskiy {
39*6e9b225fSVladimir Sementsov-Ogievskiy     AioTask *task = opaque;
40*6e9b225fSVladimir Sementsov-Ogievskiy     AioTaskPool *pool = task->pool;
41*6e9b225fSVladimir Sementsov-Ogievskiy 
42*6e9b225fSVladimir Sementsov-Ogievskiy     assert(pool->busy_tasks < pool->max_busy_tasks);
43*6e9b225fSVladimir Sementsov-Ogievskiy     pool->busy_tasks++;
44*6e9b225fSVladimir Sementsov-Ogievskiy 
45*6e9b225fSVladimir Sementsov-Ogievskiy     task->ret = task->func(task);
46*6e9b225fSVladimir Sementsov-Ogievskiy 
47*6e9b225fSVladimir Sementsov-Ogievskiy     pool->busy_tasks--;
48*6e9b225fSVladimir Sementsov-Ogievskiy 
49*6e9b225fSVladimir Sementsov-Ogievskiy     if (task->ret < 0 && pool->status == 0) {
50*6e9b225fSVladimir Sementsov-Ogievskiy         pool->status = task->ret;
51*6e9b225fSVladimir Sementsov-Ogievskiy     }
52*6e9b225fSVladimir Sementsov-Ogievskiy 
53*6e9b225fSVladimir Sementsov-Ogievskiy     g_free(task);
54*6e9b225fSVladimir Sementsov-Ogievskiy 
55*6e9b225fSVladimir Sementsov-Ogievskiy     if (pool->waiting) {
56*6e9b225fSVladimir Sementsov-Ogievskiy         pool->waiting = false;
57*6e9b225fSVladimir Sementsov-Ogievskiy         aio_co_wake(pool->main_co);
58*6e9b225fSVladimir Sementsov-Ogievskiy     }
59*6e9b225fSVladimir Sementsov-Ogievskiy }
60*6e9b225fSVladimir Sementsov-Ogievskiy 
61*6e9b225fSVladimir Sementsov-Ogievskiy void coroutine_fn aio_task_pool_wait_one(AioTaskPool *pool)
62*6e9b225fSVladimir Sementsov-Ogievskiy {
63*6e9b225fSVladimir Sementsov-Ogievskiy     assert(pool->busy_tasks > 0);
64*6e9b225fSVladimir Sementsov-Ogievskiy     assert(qemu_coroutine_self() == pool->main_co);
65*6e9b225fSVladimir Sementsov-Ogievskiy 
66*6e9b225fSVladimir Sementsov-Ogievskiy     pool->waiting = true;
67*6e9b225fSVladimir Sementsov-Ogievskiy     qemu_coroutine_yield();
68*6e9b225fSVladimir Sementsov-Ogievskiy 
69*6e9b225fSVladimir Sementsov-Ogievskiy     assert(!pool->waiting);
70*6e9b225fSVladimir Sementsov-Ogievskiy     assert(pool->busy_tasks < pool->max_busy_tasks);
71*6e9b225fSVladimir Sementsov-Ogievskiy }
72*6e9b225fSVladimir Sementsov-Ogievskiy 
73*6e9b225fSVladimir Sementsov-Ogievskiy void coroutine_fn aio_task_pool_wait_slot(AioTaskPool *pool)
74*6e9b225fSVladimir Sementsov-Ogievskiy {
75*6e9b225fSVladimir Sementsov-Ogievskiy     if (pool->busy_tasks < pool->max_busy_tasks) {
76*6e9b225fSVladimir Sementsov-Ogievskiy         return;
77*6e9b225fSVladimir Sementsov-Ogievskiy     }
78*6e9b225fSVladimir Sementsov-Ogievskiy 
79*6e9b225fSVladimir Sementsov-Ogievskiy     aio_task_pool_wait_one(pool);
80*6e9b225fSVladimir Sementsov-Ogievskiy }
81*6e9b225fSVladimir Sementsov-Ogievskiy 
82*6e9b225fSVladimir Sementsov-Ogievskiy void coroutine_fn aio_task_pool_wait_all(AioTaskPool *pool)
83*6e9b225fSVladimir Sementsov-Ogievskiy {
84*6e9b225fSVladimir Sementsov-Ogievskiy     while (pool->busy_tasks > 0) {
85*6e9b225fSVladimir Sementsov-Ogievskiy         aio_task_pool_wait_one(pool);
86*6e9b225fSVladimir Sementsov-Ogievskiy     }
87*6e9b225fSVladimir Sementsov-Ogievskiy }
88*6e9b225fSVladimir Sementsov-Ogievskiy 
89*6e9b225fSVladimir Sementsov-Ogievskiy void coroutine_fn aio_task_pool_start_task(AioTaskPool *pool, AioTask *task)
90*6e9b225fSVladimir Sementsov-Ogievskiy {
91*6e9b225fSVladimir Sementsov-Ogievskiy     aio_task_pool_wait_slot(pool);
92*6e9b225fSVladimir Sementsov-Ogievskiy 
93*6e9b225fSVladimir Sementsov-Ogievskiy     task->pool = pool;
94*6e9b225fSVladimir Sementsov-Ogievskiy     qemu_coroutine_enter(qemu_coroutine_create(aio_task_co, task));
95*6e9b225fSVladimir Sementsov-Ogievskiy }
96*6e9b225fSVladimir Sementsov-Ogievskiy 
97*6e9b225fSVladimir Sementsov-Ogievskiy AioTaskPool *coroutine_fn aio_task_pool_new(int max_busy_tasks)
98*6e9b225fSVladimir Sementsov-Ogievskiy {
99*6e9b225fSVladimir Sementsov-Ogievskiy     AioTaskPool *pool = g_new0(AioTaskPool, 1);
100*6e9b225fSVladimir Sementsov-Ogievskiy 
101*6e9b225fSVladimir Sementsov-Ogievskiy     pool->main_co = qemu_coroutine_self();
102*6e9b225fSVladimir Sementsov-Ogievskiy     pool->max_busy_tasks = max_busy_tasks;
103*6e9b225fSVladimir Sementsov-Ogievskiy 
104*6e9b225fSVladimir Sementsov-Ogievskiy     return pool;
105*6e9b225fSVladimir Sementsov-Ogievskiy }
106*6e9b225fSVladimir Sementsov-Ogievskiy 
107*6e9b225fSVladimir Sementsov-Ogievskiy void aio_task_pool_free(AioTaskPool *pool)
108*6e9b225fSVladimir Sementsov-Ogievskiy {
109*6e9b225fSVladimir Sementsov-Ogievskiy     g_free(pool);
110*6e9b225fSVladimir Sementsov-Ogievskiy }
111*6e9b225fSVladimir Sementsov-Ogievskiy 
112*6e9b225fSVladimir Sementsov-Ogievskiy int aio_task_pool_status(AioTaskPool *pool)
113*6e9b225fSVladimir Sementsov-Ogievskiy {
114*6e9b225fSVladimir Sementsov-Ogievskiy     if (!pool) {
115*6e9b225fSVladimir Sementsov-Ogievskiy         return 0; /* Sugar for lazy allocation of aio pool */
116*6e9b225fSVladimir Sementsov-Ogievskiy     }
117*6e9b225fSVladimir Sementsov-Ogievskiy 
118*6e9b225fSVladimir Sementsov-Ogievskiy     return pool->status;
119*6e9b225fSVladimir Sementsov-Ogievskiy }
120*6e9b225fSVladimir Sementsov-Ogievskiy 
121*6e9b225fSVladimir Sementsov-Ogievskiy bool aio_task_pool_empty(AioTaskPool *pool)
122*6e9b225fSVladimir Sementsov-Ogievskiy {
123*6e9b225fSVladimir Sementsov-Ogievskiy     return pool->busy_tasks == 0;
124*6e9b225fSVladimir Sementsov-Ogievskiy }
125