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 22static void error_exit(int err, const char *msg) 23{ 24 fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err)); 25 exit(1); 26} 27 28void 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 37void qemu_mutex_destroy(QemuMutex *mutex) 38{ 39 int err; 40 41 err = pthread_mutex_destroy(&mutex->lock); 42 if (err) 43 error_exit(err, __func__); 44} 45 46void qemu_mutex_lock(QemuMutex *mutex) 47{ 48 int err; 49 50 err = pthread_mutex_lock(&mutex->lock); 51 if (err) 52 error_exit(err, __func__); 53} 54 55int qemu_mutex_trylock(QemuMutex *mutex) 56{ 57 return pthread_mutex_trylock(&mutex->lock); 58} 59 60static void timespec_add_ms(struct timespec *ts, uint64_t msecs) 61{ 62 ts->tv_sec = ts->tv_sec + (long)(msecs / 1000); 63 ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000); 64 if (ts->tv_nsec >= 1000000000) { 65 ts->tv_nsec -= 1000000000; 66 ts->tv_sec++; 67 } 68} 69 70int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs) 71{ 72 int err; 73 struct timespec ts; 74 75 clock_gettime(CLOCK_REALTIME, &ts); 76 timespec_add_ms(&ts, msecs); 77 78 err = pthread_mutex_timedlock(&mutex->lock, &ts); 79 if (err && err != ETIMEDOUT) 80 error_exit(err, __func__); 81 return err; 82} 83 84void qemu_mutex_unlock(QemuMutex *mutex) 85{ 86 int err; 87 88 err = pthread_mutex_unlock(&mutex->lock); 89 if (err) 90 error_exit(err, __func__); 91} 92 93void qemu_cond_init(QemuCond *cond) 94{ 95 int err; 96 97 err = pthread_cond_init(&cond->cond, NULL); 98 if (err) 99 error_exit(err, __func__); 100} 101 102void qemu_cond_destroy(QemuCond *cond) 103{ 104 int err; 105 106 err = pthread_cond_destroy(&cond->cond); 107 if (err) 108 error_exit(err, __func__); 109} 110 111void qemu_cond_signal(QemuCond *cond) 112{ 113 int err; 114 115 err = pthread_cond_signal(&cond->cond); 116 if (err) 117 error_exit(err, __func__); 118} 119 120void qemu_cond_broadcast(QemuCond *cond) 121{ 122 int err; 123 124 err = pthread_cond_broadcast(&cond->cond); 125 if (err) 126 error_exit(err, __func__); 127} 128 129void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) 130{ 131 int err; 132 133 err = pthread_cond_wait(&cond->cond, &mutex->lock); 134 if (err) 135 error_exit(err, __func__); 136} 137 138int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs) 139{ 140 struct timespec ts; 141 int err; 142 143 clock_gettime(CLOCK_REALTIME, &ts); 144 timespec_add_ms(&ts, msecs); 145 146 err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts); 147 if (err && err != ETIMEDOUT) 148 error_exit(err, __func__); 149 return err; 150} 151 152void qemu_thread_create(QemuThread *thread, 153 void *(*start_routine)(void*), 154 void *arg) 155{ 156 int err; 157 158 /* Leave signal handling to the iothread. */ 159 sigset_t set, oldset; 160 161 sigfillset(&set); 162 pthread_sigmask(SIG_SETMASK, &set, &oldset); 163 err = pthread_create(&thread->thread, NULL, start_routine, arg); 164 if (err) 165 error_exit(err, __func__); 166 167 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 168} 169 170void qemu_thread_signal(QemuThread *thread, int sig) 171{ 172 int err; 173 174 err = pthread_kill(thread->thread, sig); 175 if (err) 176 error_exit(err, __func__); 177} 178 179void qemu_thread_self(QemuThread *thread) 180{ 181 thread->thread = pthread_self(); 182} 183 184int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2) 185{ 186 return pthread_equal(thread1->thread, thread2->thread); 187} 188 189void qemu_thread_exit(void *retval) 190{ 191 pthread_exit(retval); 192} 193