blob: 65de868e863ac33d5c6a6543230babdde6f0419c [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/lock.h>
20#include <pj/os.h>
21#include <pj/assert.h>
22#include <pj/pool.h>
23#include <pj/string.h>
24#include <pj/errno.h>
25
26
27typedef void LOCK_OBJ;
28
29/*
30 * Lock structure.
31 */
32struct pj_lock_t
33{
34 LOCK_OBJ *lock_object;
35
36 pj_status_t (*acquire) (LOCK_OBJ*);
37 pj_status_t (*tryacquire) (LOCK_OBJ*);
38 pj_status_t (*release) (LOCK_OBJ*);
39 pj_status_t (*destroy) (LOCK_OBJ*);
40};
41
42typedef pj_status_t (*FPTR)(LOCK_OBJ*);
43
44/******************************************************************************
45 * Implementation of lock object with mutex.
46 */
47static pj_lock_t mutex_lock_template =
48{
49 NULL,
50 (FPTR) &pj_mutex_lock,
51 (FPTR) &pj_mutex_trylock,
52 (FPTR) &pj_mutex_unlock,
53 (FPTR) &pj_mutex_destroy
54};
55
56static pj_status_t create_mutex_lock( pj_pool_t *pool,
57 const char *name,
58 int type,
59 pj_lock_t **lock )
60{
61 pj_lock_t *p_lock;
62 pj_status_t rc;
63
64 PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
65
66 p_lock = pj_pool_alloc(pool, sizeof(pj_lock_t));
67 if (!p_lock)
68 return PJ_ENOMEM;
69
70 pj_memcpy(p_lock, &mutex_lock_template, sizeof(pj_lock_t));
71 rc = pj_mutex_create(pool, name, type, (pj_mutex_t**)&p_lock->lock_object);
72 if (rc != PJ_SUCCESS)
73 return rc;
74
75 *lock = p_lock;
76 return PJ_SUCCESS;
77}
78
79
80PJ_DEF(pj_status_t) pj_lock_create_simple_mutex( pj_pool_t *pool,
81 const char *name,
82 pj_lock_t **lock )
83{
84 return create_mutex_lock(pool, name, PJ_MUTEX_SIMPLE, lock);
85}
86
87PJ_DEF(pj_status_t) pj_lock_create_recursive_mutex( pj_pool_t *pool,
88 const char *name,
89 pj_lock_t **lock )
90{
91 return create_mutex_lock(pool, name, PJ_MUTEX_RECURSE, lock);
92}
93
94
95/******************************************************************************
96 * Implementation of NULL lock object.
97 */
98static pj_status_t null_op(void *arg)
99{
100 PJ_UNUSED_ARG(arg);
101 return PJ_SUCCESS;
102}
103
104static pj_lock_t null_lock_template =
105{
106 NULL,
107 &null_op,
108 &null_op,
109 &null_op,
110 &null_op
111};
112
113PJ_DEF(pj_status_t) pj_lock_create_null_mutex( pj_pool_t *pool,
114 const char *name,
115 pj_lock_t **lock )
116{
117 PJ_UNUSED_ARG(name);
118 PJ_UNUSED_ARG(pool);
119
120 PJ_ASSERT_RETURN(lock, PJ_EINVAL);
121
122 *lock = &null_lock_template;
123 return PJ_SUCCESS;
124}
125
126
127/******************************************************************************
128 * Implementation of semaphore lock object.
129 */
130#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
131
132static pj_lock_t sem_lock_template =
133{
134 NULL,
135 (FPTR) &pj_sem_wait,
136 (FPTR) &pj_sem_trywait,
137 (FPTR) &pj_sem_post,
138 (FPTR) &pj_sem_destroy
139};
140
141PJ_DEF(pj_status_t) pj_lock_create_semaphore( pj_pool_t *pool,
142 const char *name,
143 unsigned initial,
144 unsigned max,
145 pj_lock_t **lock )
146{
147 pj_lock_t *p_lock;
148 pj_status_t rc;
149
150 PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
151
152 p_lock = pj_pool_alloc(pool, sizeof(pj_lock_t));
153 if (!p_lock)
154 return PJ_ENOMEM;
155
156 pj_memcpy(p_lock, &sem_lock_template, sizeof(pj_lock_t));
157 rc = pj_sem_create( pool, name, initial, max,
158 (pj_sem_t**)&p_lock->lock_object);
159 if (rc != PJ_SUCCESS)
160 return rc;
161
162 *lock = p_lock;
163
164 return PJ_SUCCESS;
165}
166
167
168#endif /* PJ_HAS_SEMAPHORE */
169
170
171PJ_DEF(pj_status_t) pj_lock_acquire( pj_lock_t *lock )
172{
173 PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
174 return (*lock->acquire)(lock->lock_object);
175}
176
177PJ_DEF(pj_status_t) pj_lock_tryacquire( pj_lock_t *lock )
178{
179 PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
180 return (*lock->tryacquire)(lock->lock_object);
181}
182
183PJ_DEF(pj_status_t) pj_lock_release( pj_lock_t *lock )
184{
185 PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
186 return (*lock->release)(lock->lock_object);
187}
188
189PJ_DEF(pj_status_t) pj_lock_destroy( pj_lock_t *lock )
190{
191 PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
192 return (*lock->destroy)(lock->lock_object);
193}
194