15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Wrappers around mutex/cond/thread functions
35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright Red Hat, Inc. 2009
55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Author:
75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *  Marcelo Tosatti <mtosatti@redhat.com>
85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This work is licensed under the terms of the GNU GPL, version 2 or later.
105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * See the COPYING file in the top-level directory.
115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stdlib.h>
145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stdio.h>
155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <errno.h>
165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <time.h>
175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <signal.h>
185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stdint.h>
195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <string.h>
205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-thread.h"
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void error_exit(int err, const char *msg)
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    exit(1);
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_mutex_init(QemuMutex *mutex)
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_mutex_init(&mutex->lock, NULL);
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
370c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turnervoid qemu_mutex_destroy(QemuMutex *mutex)
380c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner{
390c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    int err;
400c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner
410c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    err = pthread_mutex_destroy(&mutex->lock);
420c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    if (err)
430c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner        error_exit(err, __func__);
440c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner}
450c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_mutex_lock(QemuMutex *mutex)
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_mutex_lock(&mutex->lock);
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_mutex_trylock(QemuMutex *mutex)
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return pthread_mutex_trylock(&mutex->lock);
585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void timespec_add_ms(struct timespec *ts, uint64_t msecs)
615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000);
645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ts->tv_nsec >= 1000000000) {
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ts->tv_nsec -= 1000000000;
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ts->tv_sec++;
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct timespec ts;
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    clock_gettime(CLOCK_REALTIME, &ts);
765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    timespec_add_ms(&ts, msecs);
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_mutex_timedlock(&mutex->lock, &ts);
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err && err != ETIMEDOUT)
805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return err;
825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_mutex_unlock(QemuMutex *mutex)
855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_mutex_unlock(&mutex->lock);
895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_cond_init(QemuCond *cond)
945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_cond_init(&cond->cond, NULL);
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1020c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turnervoid qemu_cond_destroy(QemuCond *cond)
1030c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner{
1040c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    int err;
1050c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner
1060c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    err = pthread_cond_destroy(&cond->cond);
1070c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    if (err)
1080c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner        error_exit(err, __func__);
1090c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner}
1100c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner
1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_cond_signal(QemuCond *cond)
1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_cond_signal(&cond->cond);
1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_cond_broadcast(QemuCond *cond)
1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_cond_broadcast(&cond->cond);
1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_cond_wait(&cond->cond, &mutex->lock);
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct timespec ts;
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    clock_gettime(CLOCK_REALTIME, &ts);
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    timespec_add_ms(&ts, msecs);
1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err && err != ETIMEDOUT)
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return err;
1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_thread_create(QemuThread *thread,
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       void *(*start_routine)(void*),
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       void *arg)
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1580c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    /* Leave signal handling to the iothread.  */
1590c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    sigset_t set, oldset;
1600c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner
1610c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    sigfillset(&set);
1620c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    pthread_sigmask(SIG_SETMASK, &set, &oldset);
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_create(&thread->thread, NULL, start_routine, arg);
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
1660c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner
1670c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_thread_signal(QemuThread *thread, int sig)
1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int err;
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    err = pthread_kill(thread->thread, sig);
1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (err)
1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error_exit(err, __func__);
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_thread_self(QemuThread *thread)
1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    thread->thread = pthread_self();
1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_thread_equal(QemuThread *thread1, QemuThread *thread2)
1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
186dd9cb7929e2b98bf9f8017ebbd7e433d38541664David 'Digit' Turner   return pthread_equal(thread1->thread, thread2->thread);
1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1890c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turnervoid qemu_thread_exit(void *retval)
1900c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner{
1910c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner    pthread_exit(retval);
1920c0b2b4e96b030854987b16a779e30a3741d3b0dDavid Turner}
193