Home | History | Annotate | Download | only in qemu
      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_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 
     46 void 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 
     55 int qemu_mutex_trylock(QemuMutex *mutex)
     56 {
     57     return pthread_mutex_trylock(&mutex->lock);
     58 }
     59 
     60 static 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 
     70 int 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 
     84 void 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 
     93 void 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 
    102 void 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 
    111 void 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 
    120 void 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 
    129 void 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 
    138 int 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 
    152 void 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 
    170 void 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 
    179 void qemu_thread_self(QemuThread *thread)
    180 {
    181     thread->thread = pthread_self();
    182 }
    183 
    184 int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2)
    185 {
    186    return pthread_equal(thread1->thread, thread2->thread);
    187 }
    188 
    189 void qemu_thread_exit(void *retval)
    190 {
    191     pthread_exit(retval);
    192 }
    193