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:
parent
c90caf25e2
commit
38b14db34e
@ -17,6 +17,9 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include "qemu-thread.h"
|
#include "qemu-thread.h"
|
||||||
|
|
||||||
static void error_exit(int err, const char *msg)
|
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__);
|
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 qemu_thread_create(QemuThread *thread,
|
||||||
void *(*start_routine)(void*),
|
void *(*start_routine)(void*),
|
||||||
void *arg, int mode)
|
void *arg, int mode)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef __QEMU_THREAD_POSIX_H
|
#ifndef __QEMU_THREAD_POSIX_H
|
||||||
#define __QEMU_THREAD_POSIX_H 1
|
#define __QEMU_THREAD_POSIX_H 1
|
||||||
#include "pthread.h"
|
#include "pthread.h"
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
struct QemuMutex {
|
struct QemuMutex {
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
@ -10,6 +11,10 @@ struct QemuCond {
|
|||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct QemuSemaphore {
|
||||||
|
sem_t sem;
|
||||||
|
};
|
||||||
|
|
||||||
struct QemuThread {
|
struct QemuThread {
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
};
|
};
|
||||||
|
@ -192,6 +192,41 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
|
|||||||
qemu_mutex_lock(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 {
|
struct QemuThreadData {
|
||||||
/* Passed to win32_start_routine. */
|
/* Passed to win32_start_routine. */
|
||||||
void *(*start_routine)(void *);
|
void *(*start_routine)(void *);
|
||||||
|
@ -13,6 +13,10 @@ struct QemuCond {
|
|||||||
HANDLE continue_event;
|
HANDLE continue_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct QemuSemaphore {
|
||||||
|
HANDLE sema;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct QemuThreadData QemuThreadData;
|
typedef struct QemuThreadData QemuThreadData;
|
||||||
struct QemuThread {
|
struct QemuThread {
|
||||||
QemuThreadData *data;
|
QemuThreadData *data;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
typedef struct QemuMutex QemuMutex;
|
typedef struct QemuMutex QemuMutex;
|
||||||
typedef struct QemuCond QemuCond;
|
typedef struct QemuCond QemuCond;
|
||||||
|
typedef struct QemuSemaphore QemuSemaphore;
|
||||||
typedef struct QemuThread QemuThread;
|
typedef struct QemuThread QemuThread;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -38,6 +39,12 @@ void qemu_cond_signal(QemuCond *cond);
|
|||||||
void qemu_cond_broadcast(QemuCond *cond);
|
void qemu_cond_broadcast(QemuCond *cond);
|
||||||
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
|
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 qemu_thread_create(QemuThread *thread,
|
||||||
void *(*start_routine)(void *),
|
void *(*start_routine)(void *),
|
||||||
void *arg, int mode);
|
void *arg, int mode);
|
||||||
|
Loading…
Reference in New Issue
Block a user