threads-pthread.c 5.0 KB
Newer Older
1 2 3
/*
 * threads-pthread.c: basic thread synchronization primitives
 *
4
 * Copyright (C) 2009-2010 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 */

#include <config.h>

24
#include <unistd.h>
25
#include <inttypes.h>
26 27 28 29
#if HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif

30 31
#include "memory.h"

32 33 34 35 36 37 38 39 40 41 42 43 44 45

/* Nothing special required for pthreads */
int virThreadInitialize(void)
{
    return 0;
}

void virThreadOnExit(void)
{
}


int virMutexInit(virMutexPtr m)
{
46
    int ret;
47 48 49 50
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
    if ((ret = pthread_mutex_init(&m->lock, &attr)) != 0) {
51
        errno = ret;
52 53 54 55 56
        return -1;
    }
    return 0;
}

S
Stefan Berger 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69
int virMutexInitRecursive(virMutexPtr m)
{
    int ret;
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    if ((ret = pthread_mutex_init(&m->lock, &attr)) != 0) {
        errno = ret;
        return -1;
    }
    return 0;
}

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
void virMutexDestroy(virMutexPtr m)
{
    pthread_mutex_destroy(&m->lock);
}

void virMutexLock(virMutexPtr m){
    pthread_mutex_lock(&m->lock);
}

void virMutexUnlock(virMutexPtr m)
{
    pthread_mutex_unlock(&m->lock);
}


int virCondInit(virCondPtr c)
{
87 88 89
    int ret;
    if ((ret = pthread_cond_init(&c->cond, NULL)) != 0) {
        errno = ret;
90 91 92 93 94 95 96
        return -1;
    }
    return 0;
}

int virCondDestroy(virCondPtr c)
{
97 98 99
    int ret;
    if ((ret = pthread_cond_destroy(&c->cond)) != 0) {
        errno = ret;
100 101 102 103 104 105 106
        return -1;
    }
    return 0;
}

int virCondWait(virCondPtr c, virMutexPtr m)
{
107 108 109
    int ret;
    if ((ret = pthread_cond_wait(&c->cond, &m->lock)) != 0) {
        errno = ret;
110 111 112 113 114
        return -1;
    }
    return 0;
}

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms)
{
    int ret;
    struct timespec ts;

    ts.tv_sec = whenms / 1000;
    ts.tv_nsec = (whenms % 1000) * 1000;

    if ((ret = pthread_cond_timedwait(&c->cond, &m->lock, &ts)) != 0) {
        errno = ret;
        return -1;
    }
    return 0;
}

130 131 132 133 134 135 136 137 138 139
void virCondSignal(virCondPtr c)
{
    pthread_cond_signal(&c->cond);
}

void virCondBroadcast(virCondPtr c)
{
    pthread_cond_broadcast(&c->cond);
}

140 141 142 143 144 145 146 147 148
struct virThreadArgs {
    virThreadFunc func;
    void *opaque;
};

static void *virThreadHelper(void *data)
{
    struct virThreadArgs *args = data;
    args->func(args->opaque);
149
    VIR_FREE(args);
150 151 152 153 154 155 156 157
    return NULL;
}

int virThreadCreate(virThreadPtr thread,
                    bool joinable,
                    virThreadFunc func,
                    void *opaque)
{
158
    struct virThreadArgs *args;
159 160
    pthread_attr_t attr;
    pthread_attr_init(&attr);
161 162 163 164 165 166
    if (VIR_ALLOC(args) < 0)
        return -1;

    args->func = func;
    args->opaque = opaque;

167 168 169
    if (!joinable)
        pthread_attr_setdetachstate(&attr, 1);

170
    int ret = pthread_create(&thread->thread, &attr, virThreadHelper, args);
171
    if (ret != 0) {
172
        VIR_FREE(args);
173 174 175
        errno = ret;
        return -1;
    }
176
    /* New thread owns 'args' in success case, so don't free */
177 178 179 180 181 182 183 184 185 186 187 188 189
    return 0;
}

void virThreadSelf(virThreadPtr thread)
{
    thread->thread = pthread_self();
}

bool virThreadIsSelf(virThreadPtr thread)
{
    return pthread_equal(pthread_self(), thread->thread) ? true : false;
}

190 191
/* For debugging use only; this result is not guaranteed unique on BSD
 * systems when pthread_t is a 64-bit pointer.  */
192 193 194 195 196 197 198 199 200 201 202
int virThreadSelfID(void)
{
#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid)
    pid_t tid;
    tid = syscall(SYS_gettid);
    return (int)tid;
#else
    return (int)pthread_self();
#endif
}

203 204 205 206 207 208 209 210
/* For debugging use only; this result is not guaranteed unique on BSD
 * systems when pthread_t is a 64-bit pointer, nor does it match the
 * thread id of virThreadSelfID on Linux.  */
int virThreadID(virThreadPtr thread)
{
    return (int)(uintptr_t)thread->thread;
}

211 212 213 214
void virThreadJoin(virThreadPtr thread)
{
    pthread_join(thread->thread, NULL);
}
215 216 217 218

int virThreadLocalInit(virThreadLocalPtr l,
                       virThreadLocalCleanup c)
{
219 220 221
    int ret;
    if ((ret = pthread_key_create(&l->key, c)) != 0) {
        errno = ret;
222 223 224 225 226 227 228 229 230 231 232 233 234 235
        return -1;
    }
    return 0;
}

void *virThreadLocalGet(virThreadLocalPtr l)
{
    return pthread_getspecific(l->key);
}

void virThreadLocalSet(virThreadLocalPtr l, void *val)
{
    pthread_setspecific(l->key, val);
}