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