~ubuntu-branches/ubuntu/saucy/qemu/saucy-proposed

« back to all changes in this revision

Viewing changes to coroutine-ucontext.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include <valgrind/valgrind.h>
35
35
#endif
36
36
 
37
 
enum {
38
 
    /* Maximum free pool size prevents holding too many freed coroutines */
39
 
    POOL_MAX_SIZE = 64,
40
 
};
41
 
 
42
 
/** Free list to speed up creation */
43
 
static QSLIST_HEAD(, Coroutine) pool = QSLIST_HEAD_INITIALIZER(pool);
44
 
static unsigned int pool_size;
45
 
 
46
37
typedef struct {
47
38
    Coroutine base;
48
39
    void *stack;
49
 
    jmp_buf env;
 
40
    sigjmp_buf env;
50
41
 
51
42
#ifdef CONFIG_VALGRIND_H
52
43
    unsigned int valgrind_stack_id;
96
87
    g_free(s);
97
88
}
98
89
 
99
 
static void __attribute__((destructor)) coroutine_cleanup(void)
100
 
{
101
 
    Coroutine *co;
102
 
    Coroutine *tmp;
103
 
 
104
 
    QSLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
105
 
        g_free(DO_UPCAST(CoroutineUContext, base, co)->stack);
106
 
        g_free(co);
107
 
    }
108
 
}
109
 
 
110
90
static void __attribute__((constructor)) coroutine_init(void)
111
91
{
112
92
    int ret;
130
110
    co = &self->base;
131
111
 
132
112
    /* Initialize longjmp environment and switch back the caller */
133
 
    if (!setjmp(self->env)) {
134
 
        longjmp(*(jmp_buf *)co->entry_arg, 1);
 
113
    if (!sigsetjmp(self->env, 0)) {
 
114
        siglongjmp(*(sigjmp_buf *)co->entry_arg, 1);
135
115
    }
136
116
 
137
117
    while (true) {
140
120
    }
141
121
}
142
122
 
143
 
static Coroutine *coroutine_new(void)
 
123
Coroutine *qemu_coroutine_new(void)
144
124
{
145
125
    const size_t stack_size = 1 << 20;
146
126
    CoroutineUContext *co;
147
127
    ucontext_t old_uc, uc;
148
 
    jmp_buf old_env;
 
128
    sigjmp_buf old_env;
149
129
    union cc_arg arg = {0};
150
130
 
151
 
    /* The ucontext functions preserve signal masks which incurs a system call
152
 
     * overhead.  setjmp()/longjmp() does not preserve signal masks but only
153
 
     * works on the current stack.  Since we need a way to create and switch to
154
 
     * a new stack, use the ucontext functions for that but setjmp()/longjmp()
155
 
     * for everything else.
 
131
    /* The ucontext functions preserve signal masks which incurs a
 
132
     * system call overhead.  sigsetjmp(buf, 0)/siglongjmp() does not
 
133
     * preserve signal masks but only works on the current stack.
 
134
     * Since we need a way to create and switch to a new stack, use
 
135
     * the ucontext functions for that but sigsetjmp()/siglongjmp() for
 
136
     * everything else.
156
137
     */
157
138
 
158
139
    if (getcontext(&uc) == -1) {
178
159
    makecontext(&uc, (void (*)(void))coroutine_trampoline,
179
160
                2, arg.i[0], arg.i[1]);
180
161
 
181
 
    /* swapcontext() in, longjmp() back out */
182
 
    if (!setjmp(old_env)) {
 
162
    /* swapcontext() in, siglongjmp() back out */
 
163
    if (!sigsetjmp(old_env, 0)) {
183
164
        swapcontext(&old_uc, &uc);
184
165
    }
185
166
    return &co->base;
186
167
}
187
168
 
188
 
Coroutine *qemu_coroutine_new(void)
189
 
{
190
 
    Coroutine *co;
191
 
 
192
 
    co = QSLIST_FIRST(&pool);
193
 
    if (co) {
194
 
        QSLIST_REMOVE_HEAD(&pool, pool_next);
195
 
        pool_size--;
196
 
    } else {
197
 
        co = coroutine_new();
198
 
    }
199
 
    return co;
200
 
}
201
 
 
202
169
#ifdef CONFIG_VALGRIND_H
203
170
#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
204
171
/* Work around an unused variable in the valgrind.h macro... */
 
172
#pragma GCC diagnostic push
205
173
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
206
174
#endif
207
175
static inline void valgrind_stack_deregister(CoroutineUContext *co)
209
177
    VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id);
210
178
}
211
179
#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
212
 
#pragma GCC diagnostic error "-Wunused-but-set-variable"
 
180
#pragma GCC diagnostic pop
213
181
#endif
214
182
#endif
215
183
 
217
185
{
218
186
    CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
219
187
 
220
 
    if (pool_size < POOL_MAX_SIZE) {
221
 
        QSLIST_INSERT_HEAD(&pool, &co->base, pool_next);
222
 
        co->base.caller = NULL;
223
 
        pool_size++;
224
 
        return;
225
 
    }
226
 
 
227
188
#ifdef CONFIG_VALGRIND_H
228
189
    valgrind_stack_deregister(co);
229
190
#endif
242
203
 
243
204
    s->current = to_;
244
205
 
245
 
    ret = setjmp(from->env);
 
206
    ret = sigsetjmp(from->env, 0);
246
207
    if (ret == 0) {
247
 
        longjmp(to->env, action);
 
208
        siglongjmp(to->env, action);
248
209
    }
249
210
    return ret;
250
211
}