blob: 570fb6c910d1c3fd8833b6496bdc92334d8b42d1 [file] [log] [blame]
Benny Prijono42c5b9e2006-05-10 19:24:40 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono42c5b9e2006-05-10 19:24:40 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * Note:
23 *
24 * DO NOT BUILD THIS FILE DIRECTLY. THIS FILE WILL BE INCLUDED BY os_core_*.c
25 * WHEN MACRO PJ_EMULATE_RWMUTEX IS SET.
26 */
27
28/*
29 * os_rwmutex.c:
30 *
31 * Implementation of Read-Write mutex for platforms that lack it (e.g.
32 * Win32, RTEMS).
33 */
34
35
36struct pj_rwmutex_t
37{
38 pj_mutex_t *read_lock;
39 /* write_lock must use semaphore, because write_lock may be released
40 * by thread other than the thread that acquire the write_lock in the
41 * first place.
42 */
43 pj_sem_t *write_lock;
44 pj_int32_t reader_count;
45};
46
47/*
48 * Create reader/writer mutex.
49 *
50 */
51PJ_DEF(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
52 pj_rwmutex_t **p_mutex)
53{
54 pj_status_t status;
55 pj_rwmutex_t *rwmutex;
56
57 PJ_ASSERT_RETURN(pool && p_mutex, PJ_EINVAL);
58
59 *p_mutex = NULL;
Benny Prijonof260e462007-04-30 21:03:32 +000060 rwmutex = PJ_POOL_ALLOC_T(pool, pj_rwmutex_t);
Benny Prijono42c5b9e2006-05-10 19:24:40 +000061
62 status = pj_mutex_create_simple(pool, name, &rwmutex ->read_lock);
63 if (status != PJ_SUCCESS)
64 return status;
65
66 status = pj_sem_create(pool, name, 1, 1, &rwmutex->write_lock);
67 if (status != PJ_SUCCESS) {
68 pj_mutex_destroy(rwmutex->read_lock);
69 return status;
70 }
71
72 rwmutex->reader_count = 0;
73 *p_mutex = rwmutex;
74 return PJ_SUCCESS;
75}
76
77/*
78 * Lock the mutex for reading.
79 *
80 */
81PJ_DEF(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex)
82{
83 pj_status_t status;
84
85 PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
86
87 status = pj_mutex_lock(mutex->read_lock);
88 if (status != PJ_SUCCESS) {
89 pj_assert(!"This pretty much is unexpected");
90 return status;
91 }
92
93 mutex->reader_count++;
94
95 pj_assert(mutex->reader_count < 0x7FFFFFF0L);
96
97 if (mutex->reader_count == 1)
98 pj_sem_wait(mutex->write_lock);
99
100 status = pj_mutex_unlock(mutex->read_lock);
101 return status;
102}
103
104/*
105 * Lock the mutex for writing.
106 *
107 */
108PJ_DEF(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex)
109{
110 PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
111 return pj_sem_wait(mutex->write_lock);
112}
113
114/*
115 * Release read lock.
116 *
117 */
118PJ_DEF(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex)
119{
120 pj_status_t status;
121
122 PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
123
124 status = pj_mutex_lock(mutex->read_lock);
125 if (status != PJ_SUCCESS) {
126 pj_assert(!"This pretty much is unexpected");
127 return status;
128 }
129
130 pj_assert(mutex->reader_count >= 1);
131
132 --mutex->reader_count;
133 if (mutex->reader_count == 0)
134 pj_sem_post(mutex->write_lock);
135
136 status = pj_mutex_unlock(mutex->read_lock);
137 return status;
138}
139
140/*
141 * Release write lock.
142 *
143 */
144PJ_DEF(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex)
145{
146 PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
147 pj_assert(mutex->reader_count <= 1);
148 return pj_sem_post(mutex->write_lock);
149}
150
151
152/*
153 * Destroy reader/writer mutex.
154 *
155 */
156PJ_DEF(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex)
157{
158 PJ_ASSERT_RETURN(mutex, PJ_EINVAL);
159 pj_mutex_destroy(mutex->read_lock);
160 pj_sem_destroy(mutex->write_lock);
161 return PJ_SUCCESS;
162}
163