Remove definition of builtin function
[platform/upstream/db4.git] / mutex / mut_fcntl.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996-2009 Oracle.  All rights reserved.
5  *
6  * $Id$
7  */
8
9 #include "db_config.h"
10
11 #include "db_int.h"
12
13 static inline int __db_fcntl_mutex_lock_int __P((ENV *, db_mutex_t, int));
14
15 /*
16  * __db_fcntl_mutex_init --
17  *      Initialize a fcntl mutex.
18  *
19  * PUBLIC: int __db_fcntl_mutex_init __P((ENV *, db_mutex_t, u_int32_t));
20  */
21 int
22 __db_fcntl_mutex_init(env, mutex, flags)
23         ENV *env;
24         db_mutex_t mutex;
25         u_int32_t flags;
26 {
27         COMPQUIET(env, NULL);
28         COMPQUIET(mutex, MUTEX_INVALID);
29         COMPQUIET(flags, 0);
30
31         return (0);
32 }
33
34 /*
35  * __db_fcntl_mutex_lock_int
36  *      Internal function to lock a mutex, blocking only when requested
37  */
38 inline int
39 __db_fcntl_mutex_lock_int(env, mutex, wait)
40         ENV *env;
41         db_mutex_t mutex;
42         int wait;
43 {
44         DB_ENV *dbenv;
45         DB_MUTEX *mutexp;
46         DB_MUTEXMGR *mtxmgr;
47         DB_THREAD_INFO *ip;
48         struct flock k_lock;
49         int locked, ms, ret;
50
51         dbenv = env->dbenv;
52
53         if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
54                 return (0);
55
56         mtxmgr = env->mutex_handle;
57         mutexp = MUTEXP_SET(mtxmgr, mutex);
58
59         CHECK_MTX_THREAD(env, mutexp);
60
61 #ifdef HAVE_STATISTICS
62         if (F_ISSET(mutexp, DB_MUTEX_LOCKED))
63                 ++mutexp->mutex_set_wait;
64         else
65                 ++mutexp->mutex_set_nowait;
66 #endif
67
68         /* Initialize the lock. */
69         k_lock.l_whence = SEEK_SET;
70         k_lock.l_start = mutex;
71         k_lock.l_len = 1;
72
73         /*
74          * Only check the thread state once, by initializing the thread
75          * control block pointer to null.  If it is not the failchk
76          * thread, then ip will have a valid value subsequent times
77          * in the loop.
78          */
79         ip = NULL;
80
81         for (locked = 0;;) {
82                 /*
83                  * Wait for the lock to become available; wait 1ms initially,
84                  * up to 1 second.
85                  */
86                 for (ms = 1; F_ISSET(mutexp, DB_MUTEX_LOCKED);) {
87                         if (F_ISSET(dbenv, DB_ENV_FAILCHK) &&
88                             ip == NULL && dbenv->is_alive(dbenv,
89                             mutexp->pid, mutexp->tid, 0) == 0) {
90                                 ret = __env_set_state(env, &ip, THREAD_VERIFY);
91                                 if (ret != 0 ||
92                                     ip->dbth_state == THREAD_FAILCHK)
93                                         return (DB_RUNRECOVERY);
94                         }
95                         if (!wait)
96                                 return (DB_LOCK_NOTGRANTED);
97                         __os_yield(NULL, 0, ms * US_PER_MS);
98                         if ((ms <<= 1) > MS_PER_SEC)
99                                 ms = MS_PER_SEC;
100                 }
101
102                 /* Acquire an exclusive kernel lock on the byte. */
103                 k_lock.l_type = F_WRLCK;
104                 if (fcntl(env->lockfhp->fd, F_SETLKW, &k_lock))
105                         goto err;
106
107                 /* If the resource is still available, it's ours. */
108                 if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
109                         locked = 1;
110
111                         F_SET(mutexp, DB_MUTEX_LOCKED);
112                         dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid);
113                 }
114
115                 /* Release the kernel lock. */
116                 k_lock.l_type = F_UNLCK;
117                 if (fcntl(env->lockfhp->fd, F_SETLK, &k_lock))
118                         goto err;
119
120                 /*
121                  * If we got the resource lock we're done.
122                  *
123                  * !!!
124                  * We can't check to see if the lock is ours, because we may
125                  * be trying to block ourselves in the lock manager, and so
126                  * the holder of the lock that's preventing us from getting
127                  * the lock may be us!  (Seriously.)
128                  */
129                 if (locked)
130                         break;
131         }
132
133 #ifdef DIAGNOSTIC
134         /*
135          * We want to switch threads as often as possible.  Yield every time
136          * we get a mutex to ensure contention.
137          */
138         if (F_ISSET(dbenv, DB_ENV_YIELDCPU))
139                 __os_yield(env, 0, 0);
140 #endif
141         return (0);
142
143 err:    ret = __os_get_syserr();
144         __db_syserr(env, ret, "fcntl lock failed");
145         return (__env_panic(env, __os_posix_err(ret)));
146 }
147
148 /*
149  * __db_fcntl_mutex_lock
150  *      Lock a mutex, blocking if necessary.
151  *
152  * PUBLIC: int __db_fcntl_mutex_lock __P((ENV *, db_mutex_t));
153  */
154 int
155 __db_fcntl_mutex_lock(env, mutex)
156         ENV *env;
157         db_mutex_t mutex;
158 {
159         return (__db_fcntl_mutex_lock_int(env, mutex, 1));
160 }
161
162 /*
163  * __db_fcntl_mutex_trylock
164  *      Try to lock a mutex, without blocking when it is busy.
165  *
166  * PUBLIC: int __db_fcntl_mutex_trylock __P((ENV *, db_mutex_t));
167  */
168 int
169 __db_fcntl_mutex_trylock(env, mutex)
170         ENV *env;
171         db_mutex_t mutex;
172 {
173         return (__db_fcntl_mutex_lock_int(env, mutex, 0));
174 }
175
176 /*
177  * __db_fcntl_mutex_unlock --
178  *      Release a mutex.
179  *
180  * PUBLIC: int __db_fcntl_mutex_unlock __P((ENV *, db_mutex_t));
181  */
182 int
183 __db_fcntl_mutex_unlock(env, mutex)
184         ENV *env;
185         db_mutex_t mutex;
186 {
187         DB_ENV *dbenv;
188         DB_MUTEX *mutexp;
189         DB_MUTEXMGR *mtxmgr;
190
191         dbenv = env->dbenv;
192
193         if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING))
194                 return (0);
195
196         mtxmgr = env->mutex_handle;
197         mutexp = MUTEXP_SET(mtxmgr, mutex);
198
199 #ifdef DIAGNOSTIC
200         if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) {
201                 __db_errx(env, "fcntl unlock failed: lock already unlocked");
202                 return (__env_panic(env, EACCES));
203         }
204 #endif
205
206         /*
207          * Release the resource.  We don't have to acquire any locks because
208          * processes trying to acquire the lock are waiting for the flag to
209          * go to 0.  Once that happens the waiters will serialize acquiring
210          * an exclusive kernel lock before locking the mutex.
211          */
212         F_CLR(mutexp, DB_MUTEX_LOCKED);
213
214         return (0);
215 }
216
217 /*
218  * __db_fcntl_mutex_destroy --
219  *      Destroy a mutex.
220  *
221  * PUBLIC: int __db_fcntl_mutex_destroy __P((ENV *, db_mutex_t));
222  */
223 int
224 __db_fcntl_mutex_destroy(env, mutex)
225         ENV *env;
226         db_mutex_t mutex;
227 {
228         COMPQUIET(env, NULL);
229         COMPQUIET(mutex, MUTEX_INVALID);
230
231         return (0);
232 }