2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1994-2017, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
5 * Copyright (C) 1991-3 Stephen Crane
7 * Empire is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * See files README, COPYING and CREDITS in the root of the source
23 * tree for related information and legal notices. It is expected
24 * that future projects/authors will amend these files as needed.
28 * rwlock.c: Read-write locks
30 * Known contributors to this file:
31 * Ron Koenderink, 2007
32 * Markus Armbruster, 2007-2009
47 * -1: locked for writing
48 * >0: locked for reading that many times
51 struct lwpQueue rq; /* read lock sleepers */
52 struct lwpQueue wq; /* write lock sleepers */
57 lwp_rwlock_create(char *name)
59 struct lwp_rwlock *rwlock;
61 rwlock = malloc(sizeof(*rwlock));
65 memset(rwlock, 0, sizeof(*rwlock));
66 rwlock->name = strdup(name);
71 lwp_rwlock_destroy(struct lwp_rwlock *rwlock)
73 if (CANT_HAPPEN(rwlock->count))
80 lwp_rwlock_wrlock(struct lwp_rwlock *rwlock)
83 lwpAddTail(&rwlock->wq, LwpCurrent);
84 lwpStatus(LwpCurrent, "blocked to acquire rwlock %s for writing",
88 CANT_HAPPEN(rwlock->count != 0);
90 lwpStatus(LwpCurrent, "acquired rwlock %s for writing", rwlock->name);
94 lwp_rwlock_rdlock(struct lwp_rwlock *rwlock)
96 if (rwlock->count < 0 || rwlock->wq.head) {
97 lwpStatus(LwpCurrent, "blocked to acquire rwlock %s for reading",
99 lwpAddTail(&rwlock->rq, LwpCurrent);
102 CANT_HAPPEN(rwlock->count < 0);
104 lwpStatus(LwpCurrent, "acquired rwlock %s for reading", rwlock->name);
108 lwp_rwlock_unlock(struct lwp_rwlock *rwlock)
113 lwpStatus(LwpCurrent, "unlocking rwlock %s", rwlock->name);
114 if (CANT_HAPPEN(rwlock->count == 0))
116 if (rwlock->count < 0)
121 if (rwlock->count == 0 && rwlock->wq.head) {
122 p = lwpGetFirst(&rwlock->wq);
123 lwpStatus(p, "wake up next writer of rwlock %s", rwlock->name);
126 } else if (rwlock->count >= 0 && rwlock->rq.head && !rwlock->wq.head) {
128 while ((p = lwpGetFirst(&rwlock->rq))) {
129 lwpStatus(p, "wake up next reader of rwlock %s", rwlock->name);
130 maxpri = MAX(maxpri, p->pri);
136 if (LwpCurrent->pri < maxpri) {
137 lwpStatus(LwpCurrent, "yielding to thread with higher priority");