2 Unix SMB/CIFS implementation.
3 Samba database functions
4 Copyright (C) Anton Blanchard 2001
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #define _KLIBC_HAS_ARCH_SIG_ATOMIC_T
43 #include "../logging.h"
55 #if defined(SPARC_SPINLOCKS)
57 static inline int __spin_trylock(spinlock_t *lock)
61 asm volatile("ldstub [%1], %0"
66 return (result == 0) ? 0 : EBUSY;
69 static inline void __spin_unlock(spinlock_t *lock)
71 asm volatile("":::"memory");
75 static inline void __spin_lock_init(spinlock_t *lock)
80 static inline int __spin_is_locked(spinlock_t *lock)
85 #elif defined(POWERPC_SPINLOCKS)
87 static inline int __spin_trylock(spinlock_t *lock)
104 return (result == 1) ? 0 : EBUSY;
107 static inline void __spin_unlock(spinlock_t *lock)
109 asm volatile("eieio":::"memory");
113 static inline void __spin_lock_init(spinlock_t *lock)
118 static inline int __spin_is_locked(spinlock_t *lock)
123 #elif defined(INTEL_SPINLOCKS)
125 static inline int __spin_trylock(spinlock_t *lock)
129 asm volatile("xchgl %0,%1"
130 : "=r" (oldval), "=m" (*lock)
134 return oldval > 0 ? 0 : EBUSY;
137 static inline void __spin_unlock(spinlock_t *lock)
139 asm volatile("":::"memory");
143 static inline void __spin_lock_init(spinlock_t *lock)
148 static inline int __spin_is_locked(spinlock_t *lock)
153 #elif defined(MIPS_SPINLOCKS)
155 static inline unsigned int load_linked(unsigned long addr)
159 __asm__ __volatile__("ll\t%0,(%1)"
166 static inline unsigned int store_conditional(unsigned long addr, unsigned int value)
170 __asm__ __volatile__("sc\t%0,(%2)"
172 : "0" (value), "r" (addr));
176 static inline int __spin_trylock(spinlock_t *lock)
181 mw = load_linked(lock);
184 } while (!store_conditional(lock, 1));
186 asm volatile("":::"memory");
191 static inline void __spin_unlock(spinlock_t *lock)
193 asm volatile("":::"memory");
197 static inline void __spin_lock_init(spinlock_t *lock)
202 static inline int __spin_is_locked(spinlock_t *lock)
208 #error Need to implement spinlock code in spinlock.c
215 static void yield_cpu(void)
219 #ifdef USE_SCHED_YIELD
222 /* Linux will busy loop for delays < 2ms on real time tasks */
224 tm.tv_nsec = 2000000L + 1;
225 nanosleep(&tm, NULL);
229 static int this_is_smp(void)
238 static int smp_machine = 0;
240 static inline void __spin_lock(spinlock_t *lock)
244 while(__spin_trylock(lock)) {
245 while(__spin_is_locked(lock)) {
246 if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
253 static void __read_lock(tdb_rwlock_t *rwlock)
258 __spin_lock(&rwlock->lock);
260 if (!(rwlock->count & RWLOCK_BIAS)) {
262 __spin_unlock(&rwlock->lock);
266 __spin_unlock(&rwlock->lock);
268 while(rwlock->count & RWLOCK_BIAS) {
269 if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
276 static void __write_lock(tdb_rwlock_t *rwlock)
281 __spin_lock(&rwlock->lock);
283 if (rwlock->count == 0) {
284 rwlock->count |= RWLOCK_BIAS;
285 __spin_unlock(&rwlock->lock);
289 __spin_unlock(&rwlock->lock);
291 while(rwlock->count != 0) {
292 if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
299 static void __write_unlock(tdb_rwlock_t *rwlock)
301 __spin_lock(&rwlock->lock);
303 if (!(rwlock->count & RWLOCK_BIAS))
304 dbg("bug: write_unlock");
306 rwlock->count &= ~RWLOCK_BIAS;
307 __spin_unlock(&rwlock->lock);
310 static void __read_unlock(tdb_rwlock_t *rwlock)
312 __spin_lock(&rwlock->lock);
315 dbg("bug: read_unlock");
317 if (rwlock->count & RWLOCK_BIAS)
318 dbg("bug: read_unlock");
321 __spin_unlock(&rwlock->lock);
326 /* lock a list in the database. list -1 is the alloc list */
327 int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type)
329 tdb_rwlock_t *rwlocks;
331 if (!tdb->map_ptr) return -1;
332 rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
336 __read_lock(&rwlocks[list+1]);
340 __write_lock(&rwlocks[list+1]);
344 return TDB_ERRCODE(TDB_ERR_LOCK, -1);
349 /* unlock the database. */
350 int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type)
352 tdb_rwlock_t *rwlocks;
354 if (!tdb->map_ptr) return -1;
355 rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
359 __read_unlock(&rwlocks[list+1]);
363 __write_unlock(&rwlocks[list+1]);
367 return TDB_ERRCODE(TDB_ERR_LOCK, -1);
373 int tdb_create_rwlocks(int fd, unsigned int hash_size)
376 tdb_rwlock_t *rwlocks;
378 size = (hash_size + 1) * sizeof(tdb_rwlock_t);
379 rwlocks = malloc(size);
383 for(i = 0; i < hash_size+1; i++) {
384 __spin_lock_init(&rwlocks[i].lock);
385 rwlocks[i].count = 0;
388 /* Write it out (appending to end) */
389 if (write(fd, rwlocks, size) != size) {
393 smp_machine = this_is_smp();
398 int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
400 tdb_rwlock_t *rwlocks;
403 if (tdb->header.rwlocks == 0) return 0;
404 if (!tdb->map_ptr) return -1;
406 /* We're mmapped here */
407 rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
408 for(i = 0; i < tdb->header.hash_size+1; i++) {
409 __spin_lock_init(&rwlocks[i].lock);
410 rwlocks[i].count = 0;
415 int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; }
416 int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
417 int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
419 /* Non-spinlock version: remove spinlock pointer */
420 int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
422 tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks
423 - (char *)&tdb->header);
425 tdb->header.rwlocks = 0;
426 if (lseek(tdb->fd, off, SEEK_SET) != off
427 || write(tdb->fd, (void *)&tdb->header.rwlocks,
428 sizeof(tdb->header.rwlocks))
429 != sizeof(tdb->header.rwlocks))