так получается реализация подобная userspace вызову
pthread_rwlock_tryrdlock/pthread_rwlock_unlock. Реализацию, близкую к pthread_trylock/pthread_unlock имеют вызовы pthread_rwlock_trywrlock/pthread_rwlock_unlock.Хотя речь идет о вызовах ядра, можно реализовать тройку вызовов, близких к:
- pthread_rwlock_tryrdlock (my_lock_rd);
- pthread_rwlock_trywrlock (my_lock_wr);
- pthread_rwlock_unlock (my_unlock_rd и my_unlock_wr).
struct my_lock {
. ...
. int mtx_lock_count; // если < 0, значит открыт на запись,
. // если > 0, то открыт на чтение,
. // если == 0, свободен от блокировок.
. spinlock_t mtx_lock;
. ...
};
// смысл mtx_lock_count в том, что читающих процессов может быть несколько,
// и только один - записывающий. Можно договориться использовать значение -1 в
// качестве обозначения блокировки на запись, и любое положительное число -
// блокировка на чтение.
int
my_lock_rd(struct my_lock *mtx) {
. int ret = 0;
.
. spin_lock(&mtx->mtx_lock);
. if (mtx->mtx_lock_count >= 0)
. mtx->mtx_lock_count++;
. else
. ret = mtx->mtx_lock_count;
. spin_unlock(&mtx->mtx_lock);
. return ret;
}
int
my_lock_wr(struct my_lock *mtx) {
. int ret = 0;
.
. spin_lock(&mtx->mtx_lock);
. ret = mtx->mtx_lock_count; // вернем информацию о том, какая блокировка
. // имеет место быть. В нашем случае, ошибкой
. // является ненулевой код возврата.
// чтобы произвести WRITE блокировку, замок должен быть свободен
// от любых блокировок. Иногда для WRITE используется термин
// "исключающая блокировка", а для READ - "конкурирующая блокировка".
. if (mtx->mtx_lock_count == 0)
. mtx->mtx_lock_count = -1; // метка блокировки на запись.
. spin_unlock(&mtx->mtx_lock);
. return ret;
}
// разблокирование - существенно более легкая задача.
// можно произвести кучу проверок, но зачем ?
void
my_unlock_rd(struct my_lock *mtx) {
. spin_lock(&mtx->mtx_lock);
. mtx->mtx_lock_count--;
. spin_unlock(&mtx->mtx_lock);
}
void
my_unlock_wr(struct my_lock *mtx) {
. spin_lock(&mtx->mtx_lock);
. mtx->mtx_lock_count = 0;
. spin_unlock(&mtx->mtx_lock);
}
У тебя используется глобальная переменая. Это будет хорошо работать, если замок нужен только один. В других случаях лучше использовать метод блокировки, подобный данному.