qemu-thread: add QemuSemaphore

The new thread pool will use semaphores instead of condition
variables, because QemuCond does not have qemu_cond_timedwait.
(I also like it more this way).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2011-08-08 14:36:41 +02:00
parent c90caf25e2
commit 38b14db34e
5 changed files with 131 additions and 0 deletions

View file

@ -17,6 +17,9 @@
#include <signal.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <sys/time.h>
#include "qemu-thread.h"
static void error_exit(int err, const char *msg)
@ -115,6 +118,83 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
error_exit(err, __func__);
}
void qemu_sem_init(QemuSemaphore *sem, int init)
{
int rc;
rc = sem_init(&sem->sem, 0, init);
if (rc < 0) {
error_exit(errno, __func__);
}
}
void qemu_sem_destroy(QemuSemaphore *sem)
{
int rc;
rc = sem_destroy(&sem->sem);
if (rc < 0) {
error_exit(errno, __func__);
}
}
void qemu_sem_post(QemuSemaphore *sem)
{
int rc;
rc = sem_post(&sem->sem);
if (rc < 0) {
error_exit(errno, __func__);
}
}
int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
{
int rc;
if (ms <= 0) {
/* This is cheaper than sem_timedwait. */
do {
rc = sem_trywait(&sem->sem);
} while (rc == -1 && errno == EINTR);
if (rc == -1 && errno == EAGAIN) {
return -1;
}
} else {
struct timeval tv;
struct timespec ts;
gettimeofday(&tv, NULL);
ts.tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000;
ts.tv_sec = tv.tv_sec + ms / 1000;
if (ts.tv_nsec >= 1000000000) {
ts.tv_sec++;
ts.tv_nsec -= 1000000000;
}
do {
rc = sem_timedwait(&sem->sem, &ts);
} while (rc == -1 && errno == EINTR);
if (rc == -1 && errno == ETIMEDOUT) {
return -1;
}
}
if (rc < 0) {
error_exit(errno, __func__);
}
return 0;
}
void qemu_sem_wait(QemuSemaphore *sem)
{
int rc;
do {
rc = sem_wait(&sem->sem);
} while (rc == -1 && errno == EINTR);
if (rc < 0) {
error_exit(errno, __func__);
}
}
void qemu_thread_create(QemuThread *thread,
void *(*start_routine)(void*),
void *arg, int mode)

View file

@ -1,6 +1,7 @@
#ifndef __QEMU_THREAD_POSIX_H
#define __QEMU_THREAD_POSIX_H 1
#include "pthread.h"
#include <semaphore.h>
struct QemuMutex {
pthread_mutex_t lock;
@ -10,6 +11,10 @@ struct QemuCond {
pthread_cond_t cond;
};
struct QemuSemaphore {
sem_t sem;
};
struct QemuThread {
pthread_t thread;
};

View file

@ -192,6 +192,41 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
qemu_mutex_lock(mutex);
}
void qemu_sem_init(QemuSemaphore *sem, int init)
{
/* Manual reset. */
sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL);
}
void qemu_sem_destroy(QemuSemaphore *sem)
{
CloseHandle(sem->sema);
}
void qemu_sem_post(QemuSemaphore *sem)
{
ReleaseSemaphore(sem->sema, 1, NULL);
}
int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
{
int rc = WaitForSingleObject(sem->sema, ms);
if (rc == WAIT_OBJECT_0) {
return 0;
}
if (rc != WAIT_TIMEOUT) {
error_exit(GetLastError(), __func__);
}
return -1;
}
void qemu_sem_wait(QemuSemaphore *sem)
{
if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
error_exit(GetLastError(), __func__);
}
}
struct QemuThreadData {
/* Passed to win32_start_routine. */
void *(*start_routine)(void *);

View file

@ -13,6 +13,10 @@ struct QemuCond {
HANDLE continue_event;
};
struct QemuSemaphore {
HANDLE sema;
};
typedef struct QemuThreadData QemuThreadData;
struct QemuThread {
QemuThreadData *data;

View file

@ -6,6 +6,7 @@
typedef struct QemuMutex QemuMutex;
typedef struct QemuCond QemuCond;
typedef struct QemuSemaphore QemuSemaphore;
typedef struct QemuThread QemuThread;
#ifdef _WIN32
@ -38,6 +39,12 @@ void qemu_cond_signal(QemuCond *cond);
void qemu_cond_broadcast(QemuCond *cond);
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
void qemu_sem_init(QemuSemaphore *sem, int init);
void qemu_sem_post(QemuSemaphore *sem);
void qemu_sem_wait(QemuSemaphore *sem);
int qemu_sem_timedwait(QemuSemaphore *sem, int ms);
void qemu_sem_destroy(QemuSemaphore *sem);
void qemu_thread_create(QemuThread *thread,
void *(*start_routine)(void *),
void *arg, int mode);