Revision dcc772e2 async.c

b/async.c
47 47
    bh->ctx = ctx;
48 48
    bh->cb = cb;
49 49
    bh->opaque = opaque;
50
    qemu_mutex_lock(&ctx->bh_lock);
50 51
    bh->next = ctx->first_bh;
52
    /* Make sure that the members are ready before putting bh into list */
53
    smp_wmb();
51 54
    ctx->first_bh = bh;
55
    qemu_mutex_unlock(&ctx->bh_lock);
52 56
    return bh;
53 57
}
54 58

  
59
/* Multiple occurrences of aio_bh_poll cannot be called concurrently */
55 60
int aio_bh_poll(AioContext *ctx)
56 61
{
57 62
    QEMUBH *bh, **bhp, *next;
......
61 66

  
62 67
    ret = 0;
63 68
    for (bh = ctx->first_bh; bh; bh = next) {
69
        /* Make sure that fetching bh happens before accessing its members */
70
        smp_read_barrier_depends();
64 71
        next = bh->next;
65 72
        if (!bh->deleted && bh->scheduled) {
66 73
            bh->scheduled = 0;
74
            /* Paired with write barrier in bh schedule to ensure reading for
75
             * idle & callbacks coming after bh's scheduling.
76
             */
77
            smp_rmb();
67 78
            if (!bh->idle)
68 79
                ret = 1;
69 80
            bh->idle = 0;
......
75 86

  
76 87
    /* remove deleted bhs */
77 88
    if (!ctx->walking_bh) {
89
        qemu_mutex_lock(&ctx->bh_lock);
78 90
        bhp = &ctx->first_bh;
79 91
        while (*bhp) {
80 92
            bh = *bhp;
......
85 97
                bhp = &bh->next;
86 98
            }
87 99
        }
100
        qemu_mutex_unlock(&ctx->bh_lock);
88 101
    }
89 102

  
90 103
    return ret;
......
94 107
{
95 108
    if (bh->scheduled)
96 109
        return;
97
    bh->scheduled = 1;
98 110
    bh->idle = 1;
111
    /* Make sure that idle & any writes needed by the callback are done
112
     * before the locations are read in the aio_bh_poll.
113
     */
114
    smp_wmb();
115
    bh->scheduled = 1;
99 116
}
100 117

  
101 118
void qemu_bh_schedule(QEMUBH *bh)
102 119
{
103 120
    if (bh->scheduled)
104 121
        return;
105
    bh->scheduled = 1;
106 122
    bh->idle = 0;
123
    /* Make sure that idle & any writes needed by the callback are done
124
     * before the locations are read in the aio_bh_poll.
125
     */
126
    smp_wmb();
127
    bh->scheduled = 1;
107 128
    aio_notify(bh->ctx);
108 129
}
109 130

  
131

  
132
/* This func is async.
133
 */
110 134
void qemu_bh_cancel(QEMUBH *bh)
111 135
{
112 136
    bh->scheduled = 0;
113 137
}
114 138

  
139
/* This func is async.The bottom half will do the delete action at the finial
140
 * end.
141
 */
115 142
void qemu_bh_delete(QEMUBH *bh)
116 143
{
117 144
    bh->scheduled = 0;
......
176 203
    thread_pool_free(ctx->thread_pool);
177 204
    aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
178 205
    event_notifier_cleanup(&ctx->notifier);
206
    qemu_mutex_destroy(&ctx->bh_lock);
179 207
    g_array_free(ctx->pollfds, TRUE);
180 208
}
181 209

  
......
211 239
    ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
212 240
    ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
213 241
    ctx->thread_pool = NULL;
242
    qemu_mutex_init(&ctx->bh_lock);
214 243
    event_notifier_init(&ctx->notifier, false);
215 244
    aio_set_event_notifier(ctx, &ctx->notifier, 
216 245
                           (EventNotifierHandler *)

Also available in: Unified diff