1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
/*
* Copyright (C) 2005-2010 Andrej N. Gritsenko <andrej@rep.kiev.ua>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This file is part of FoxEye's source: own implementation of Sun's
* read-write locks
*/
#include "foxeye.h"
/* locks order: wr, ct, rd */
struct rwlock_t {
pthread_mutex_t ct; /* set while testing x */
pthread_mutex_t wr; /* set while writer waits and works */
pthread_mutex_t rd; /* set while read or write */
unsigned int x; /* count of readers working */
};
int rwlock_init (rwlock_t *rwp, int type, void *u)
{
if (type != USYNC_THREAD)
return -1;
pthread_mutex_init (&rwp->ct, NULL);
pthread_mutex_init (&rwp->rd, NULL);
pthread_mutex_init (&rwp->wr, NULL);
rwp->x = 0;
return 0;
}
int rw_rdlock (rwlock_t *rwp)
{
unsigned int x;
pthread_mutex_lock (&rwp->wr); /* wait while write unlocks */
pthread_mutex_lock (&rwp->ct);
x = rwp->x++; /* it's 1 now if no other readers and >1 if there were */
pthread_mutex_unlock (&rwp->ct); /* avoid deadlock by unlocking immediately */
if (x == 0)
pthread_mutex_lock (&rwp->rd); /* no lock yet so set it */
pthread_mutex_unlock (&rwp->wr);
return 0;
}
int rw_tryrdlock (rwlock_t *rwp)
{
int n;
n = pthread_mutex_trylock (&rwp->wr);
if (n != 0) /* failed on write */
return n;
pthread_mutex_lock (&rwp->ct);
if (rwp->x == 0)
n = pthread_mutex_trylock (&rwp->rd);
else
n = 0;
if (n == 0) /* succeed */
rwp->x++;
pthread_mutex_unlock (&rwp->ct);
pthread_mutex_unlock (&rwp->wr);
return n;
}
int rw_wrlock (rwlock_t *rwp)
{
pthread_mutex_lock (&rwp->wr); /* lock both write and read */
return pthread_mutex_lock (&rwp->rd);
}
int rw_trywrlock (rwlock_t *rwp)
{
int n = pthread_mutex_trylock (&rwp->wr);
if (n != 0)
return n; /* fail on write lock */
n = pthread_mutex_trylock (&rwp->rd);
if (n != 0)
pthread_mutex_unlock (&rwp->wr); /* fail on read lock */
return n;
}
int rw_unlock (rwlock_t *rwp)
{
pthread_mutex_lock (&rwp->ct);
if (rwp->x > 0)
rwp->x--; /* it was read lock */
else
pthread_mutex_unlock (&rwp->wr); /* it was write lock */
if (rwp->x == 0)
pthread_mutex_unlock (&rwp->rd); /* read is unlocked now */
pthread_mutex_unlock (&rwp->ct);
return 0;
}
int rwlock_destroy (rwlock_t *rwp)
{
pthread_mutex_destroy (&rwp->ct);
pthread_mutex_destroy (&rwp->wr);
pthread_mutex_destroy (&rwp->rd);
return 0;
}
|