2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1994-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
5 * Copyright (C) 1991-3 Stephen Crane
7 * This program 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 2 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, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * See files README, COPYING and CREDITS in the root of the source
24 * tree for related information and legal notices. It is expected
25 * that future projects/authors will amend these files as needed.
29 * rwlock.c: Read-write locks
31 * Known contributors to this file:
32 * Ron Koenderink, 2007
33 * Markus Armbruster, 2007
48 * -1: locked for writing
49 * >0: locked for reading that many times
52 struct lwpQueue rq; /* read lock sleepers */
53 struct lwpQueue wq; /* write lock sleepers */
58 lwp_rwlock_create(char *name)
60 struct lwp_rwlock *rwlock;
62 rwlock = malloc(sizeof(*rwlock));
66 memset(rwlock, 0, sizeof(*rwlock));
67 rwlock->name = strdup(name);
72 lwp_rwlock_destroy(struct lwp_rwlock *rwlock)
74 if (CANT_HAPPEN(rwlock->count))
81 lwp_rwlock_wrlock(struct lwp_rwlock *rwlock)
84 lwpAddTail(&rwlock->wq, LwpCurrent);
85 lwpStatus(LwpCurrent, "blocked to acquire rwlock %s for writing",
89 CANT_HAPPEN(rwlock->count != 0);
91 lwpStatus(LwpCurrent, "acquired rwlock %s for writing", rwlock->name);
95 lwp_rwlock_rdlock(struct lwp_rwlock *rwlock)
97 if (rwlock->count < 0 || rwlock->wq.head) {
98 lwpStatus(LwpCurrent, "blocked to acquire rwlock %s for reading",
100 lwpAddTail(&rwlock->rq, LwpCurrent);
103 CANT_HAPPEN(rwlock->count < 0);
105 lwpStatus(LwpCurrent, "acquired rwlock %s for reading", rwlock->name);
109 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);
124 } else if (rwlock->count >= 0 && rwlock->rq.head && !rwlock->wq.head) {
125 p = lwpGetFirst(&rwlock->rq);
126 lwpStatus(p, "wake up next reader of rwlock %s", rwlock->name);
131 if (LwpCurrent->pri < p->pri) {
132 lwpStatus(LwpCurrent, "yielding to thread with higher priority");