Statistics
| Branch: | Revision:

root / qemu-thread.c @ 55541c8a

History | View | Annotate | Download (3.5 kB)

1
/*
2
 * Wrappers around mutex/cond/thread functions
3
 *
4
 * Copyright Red Hat, Inc. 2009
5
 *
6
 * Author:
7
 *  Marcelo Tosatti <mtosatti@redhat.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10
 * See the COPYING file in the top-level directory.
11
 *
12
 */
13
#include <stdlib.h>
14
#include <stdio.h>
15
#include <errno.h>
16
#include <time.h>
17
#include <signal.h>
18
#include <stdint.h>
19
#include <string.h>
20
#include "qemu-thread.h"
21

    
22
static void error_exit(int err, const char *msg)
23
{
24
    fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
25
    exit(1);
26
}
27

    
28
void qemu_mutex_init(QemuMutex *mutex)
29
{
30
    int err;
31

    
32
    err = pthread_mutex_init(&mutex->lock, NULL);
33
    if (err)
34
        error_exit(err, __func__);
35
}
36

    
37
void qemu_mutex_lock(QemuMutex *mutex)
38
{
39
    int err;
40

    
41
    err = pthread_mutex_lock(&mutex->lock);
42
    if (err)
43
        error_exit(err, __func__);
44
}
45

    
46
int qemu_mutex_trylock(QemuMutex *mutex)
47
{
48
    return pthread_mutex_trylock(&mutex->lock);
49
}
50

    
51
static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
52
{
53
    ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
54
    ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000);
55
    if (ts->tv_nsec >= 1000000000) {
56
        ts->tv_nsec -= 1000000000;
57
        ts->tv_sec++;
58
    }
59
}
60

    
61
int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
62
{
63
    int err;
64
    struct timespec ts;
65

    
66
    clock_gettime(CLOCK_REALTIME, &ts);
67
    timespec_add_ms(&ts, msecs);
68

    
69
    err = pthread_mutex_timedlock(&mutex->lock, &ts);
70
    if (err && err != ETIMEDOUT)
71
        error_exit(err, __func__);
72
    return err;
73
}
74

    
75
void qemu_mutex_unlock(QemuMutex *mutex)
76
{
77
    int err;
78

    
79
    err = pthread_mutex_unlock(&mutex->lock);
80
    if (err)
81
        error_exit(err, __func__);
82
}
83

    
84
void qemu_cond_init(QemuCond *cond)
85
{
86
    int err;
87

    
88
    err = pthread_cond_init(&cond->cond, NULL);
89
    if (err)
90
        error_exit(err, __func__);
91
}
92

    
93
void qemu_cond_signal(QemuCond *cond)
94
{
95
    int err;
96

    
97
    err = pthread_cond_signal(&cond->cond);
98
    if (err)
99
        error_exit(err, __func__);
100
}
101

    
102
void qemu_cond_broadcast(QemuCond *cond)
103
{
104
    int err;
105

    
106
    err = pthread_cond_broadcast(&cond->cond);
107
    if (err)
108
        error_exit(err, __func__);
109
}
110

    
111
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
112
{
113
    int err;
114

    
115
    err = pthread_cond_wait(&cond->cond, &mutex->lock);
116
    if (err)
117
        error_exit(err, __func__);
118
}
119

    
120
int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
121
{
122
    struct timespec ts;
123
    int err;
124

    
125
    clock_gettime(CLOCK_REALTIME, &ts);
126
    timespec_add_ms(&ts, msecs);
127

    
128
    err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
129
    if (err && err != ETIMEDOUT)
130
        error_exit(err, __func__);
131
    return err;
132
}
133

    
134
void qemu_thread_create(QemuThread *thread,
135
                       void *(*start_routine)(void*),
136
                       void *arg)
137
{
138
    int err;
139

    
140
    /* Leave signal handling to the iothread.  */
141
    sigset_t set, oldset;
142

    
143
    sigfillset(&set);
144
    pthread_sigmask(SIG_SETMASK, &set, &oldset);
145
    err = pthread_create(&thread->thread, NULL, start_routine, arg);
146
    if (err)
147
        error_exit(err, __func__);
148

    
149
    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
150
}
151

    
152
void qemu_thread_signal(QemuThread *thread, int sig)
153
{
154
    int err;
155

    
156
    err = pthread_kill(thread->thread, sig);
157
    if (err)
158
        error_exit(err, __func__);
159
}
160

    
161
void qemu_thread_self(QemuThread *thread)
162
{
163
    thread->thread = pthread_self();
164
}
165

    
166
int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2)
167
{
168
   return pthread_equal(thread1->thread, thread2->thread);
169
}
170