1 /* 2 * Wrappers around mutex/cond/thread functions 3 * 4 * Copyright Red Hat, Inc. 2009 5 * 6 * Author: 7 * Marcelo Tosatti <mtosatti (at) 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 err = pthread_create(&thread->thread, NULL, start_routine, arg); 141 if (err) 142 error_exit(err, __func__); 143 } 144 145 void qemu_thread_signal(QemuThread *thread, int sig) 146 { 147 int err; 148 149 err = pthread_kill(thread->thread, sig); 150 if (err) 151 error_exit(err, __func__); 152 } 153 154 void qemu_thread_self(QemuThread *thread) 155 { 156 thread->thread = pthread_self(); 157 } 158 159 int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2) 160 { 161 return pthread_equal(thread1->thread, thread2->thread); 162 } 163 164