]>
git.ipfire.org Git - thirdparty/systemd.git/blob - tdb/spinlock.c
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.
31 #define _KLIBC_HAS_ARCH_SIG_ATOMIC_T
54 #if defined(SPARC_SPINLOCKS)
56 static inline int __spin_trylock(spinlock_t
*lock
)
60 asm volatile("ldstub [%1], %0"
65 return (result
== 0) ? 0 : EBUSY
;
68 static inline void __spin_unlock(spinlock_t
*lock
)
70 asm volatile("":::"memory");
74 static inline void __spin_lock_init(spinlock_t
*lock
)
79 static inline int __spin_is_locked(spinlock_t
*lock
)
84 #elif defined(POWERPC_SPINLOCKS)
86 static inline int __spin_trylock(spinlock_t
*lock
)
103 return (result
== 1) ? 0 : EBUSY
;
106 static inline void __spin_unlock(spinlock_t
*lock
)
108 asm volatile("eieio":::"memory");
112 static inline void __spin_lock_init(spinlock_t
*lock
)
117 static inline int __spin_is_locked(spinlock_t
*lock
)
122 #elif defined(INTEL_SPINLOCKS)
124 static inline int __spin_trylock(spinlock_t
*lock
)
128 asm volatile("xchgl %0,%1"
129 : "=r" (oldval
), "=m" (*lock
)
133 return oldval
> 0 ? 0 : EBUSY
;
136 static inline void __spin_unlock(spinlock_t
*lock
)
138 asm volatile("":::"memory");
142 static inline void __spin_lock_init(spinlock_t
*lock
)
147 static inline int __spin_is_locked(spinlock_t
*lock
)
152 #elif defined(MIPS_SPINLOCKS)
154 static inline unsigned int load_linked(unsigned long addr
)
158 __asm__
__volatile__("ll\t%0,(%1)"
165 static inline unsigned int store_conditional(unsigned long addr
, unsigned int value
)
169 __asm__
__volatile__("sc\t%0,(%2)"
171 : "0" (value
), "r" (addr
));
175 static inline int __spin_trylock(spinlock_t
*lock
)
180 mw
= load_linked(lock
);
183 } while (!store_conditional(lock
, 1));
185 asm volatile("":::"memory");
190 static inline void __spin_unlock(spinlock_t
*lock
)
192 asm volatile("":::"memory");
196 static inline void __spin_lock_init(spinlock_t
*lock
)
201 static inline int __spin_is_locked(spinlock_t
*lock
)
207 #error Need to implement spinlock code in spinlock.c
214 static void yield_cpu(void)
218 #ifdef USE_SCHED_YIELD
221 /* Linux will busy loop for delays < 2ms on real time tasks */
223 tm
.tv_nsec
= 2000000L + 1;
224 nanosleep(&tm
, NULL
);
228 static int this_is_smp(void)
237 static int smp_machine
= 0;
239 static inline void __spin_lock(spinlock_t
*lock
)
243 while(__spin_trylock(lock
)) {
244 while(__spin_is_locked(lock
)) {
245 if (smp_machine
&& ntries
++ < MAX_BUSY_LOOPS
)
252 static void __read_lock(tdb_rwlock_t
*rwlock
)
257 __spin_lock(&rwlock
->lock
);
259 if (!(rwlock
->count
& RWLOCK_BIAS
)) {
261 __spin_unlock(&rwlock
->lock
);
265 __spin_unlock(&rwlock
->lock
);
267 while(rwlock
->count
& RWLOCK_BIAS
) {
268 if (smp_machine
&& ntries
++ < MAX_BUSY_LOOPS
)
275 static void __write_lock(tdb_rwlock_t
*rwlock
)
280 __spin_lock(&rwlock
->lock
);
282 if (rwlock
->count
== 0) {
283 rwlock
->count
|= RWLOCK_BIAS
;
284 __spin_unlock(&rwlock
->lock
);
288 __spin_unlock(&rwlock
->lock
);
290 while(rwlock
->count
!= 0) {
291 if (smp_machine
&& ntries
++ < MAX_BUSY_LOOPS
)
298 static void __write_unlock(tdb_rwlock_t
*rwlock
)
300 __spin_lock(&rwlock
->lock
);
302 if (!(rwlock
->count
& RWLOCK_BIAS
))
303 dbg("bug: write_unlock");
305 rwlock
->count
&= ~RWLOCK_BIAS
;
306 __spin_unlock(&rwlock
->lock
);
309 static void __read_unlock(tdb_rwlock_t
*rwlock
)
311 __spin_lock(&rwlock
->lock
);
314 dbg("bug: read_unlock");
316 if (rwlock
->count
& RWLOCK_BIAS
)
317 dbg("bug: read_unlock");
320 __spin_unlock(&rwlock
->lock
);
325 /* lock a list in the database. list -1 is the alloc list */
326 int tdb_spinlock(TDB_CONTEXT
*tdb
, int list
, int rw_type
)
328 tdb_rwlock_t
*rwlocks
;
330 if (!tdb
->map_ptr
) return -1;
331 rwlocks
= (tdb_rwlock_t
*)((char *)tdb
->map_ptr
+ tdb
->header
.rwlocks
);
335 __read_lock(&rwlocks
[list
+1]);
339 __write_lock(&rwlocks
[list
+1]);
343 return TDB_ERRCODE(TDB_ERR_LOCK
, -1);
348 /* unlock the database. */
349 int tdb_spinunlock(TDB_CONTEXT
*tdb
, int list
, int rw_type
)
351 tdb_rwlock_t
*rwlocks
;
353 if (!tdb
->map_ptr
) return -1;
354 rwlocks
= (tdb_rwlock_t
*)((char *)tdb
->map_ptr
+ tdb
->header
.rwlocks
);
358 __read_unlock(&rwlocks
[list
+1]);
362 __write_unlock(&rwlocks
[list
+1]);
366 return TDB_ERRCODE(TDB_ERR_LOCK
, -1);
372 int tdb_create_rwlocks(int fd
, unsigned int hash_size
)
375 tdb_rwlock_t
*rwlocks
;
377 size
= (hash_size
+ 1) * sizeof(tdb_rwlock_t
);
378 rwlocks
= malloc(size
);
382 for(i
= 0; i
< hash_size
+1; i
++) {
383 __spin_lock_init(&rwlocks
[i
].lock
);
384 rwlocks
[i
].count
= 0;
387 /* Write it out (appending to end) */
388 if (write(fd
, rwlocks
, size
) != size
) {
392 smp_machine
= this_is_smp();
397 int tdb_clear_spinlocks(TDB_CONTEXT
*tdb
)
399 tdb_rwlock_t
*rwlocks
;
402 if (tdb
->header
.rwlocks
== 0) return 0;
403 if (!tdb
->map_ptr
) return -1;
405 /* We're mmapped here */
406 rwlocks
= (tdb_rwlock_t
*)((char *)tdb
->map_ptr
+ tdb
->header
.rwlocks
);
407 for(i
= 0; i
< tdb
->header
.hash_size
+1; i
++) {
408 __spin_lock_init(&rwlocks
[i
].lock
);
409 rwlocks
[i
].count
= 0;
414 int tdb_create_rwlocks(int fd
, unsigned int hash_size
) { return 0; }
415 int tdb_spinlock(TDB_CONTEXT
*tdb
, int list
, int rw_type
) { return -1; }
416 int tdb_spinunlock(TDB_CONTEXT
*tdb
, int list
, int rw_type
) { return -1; }
418 /* Non-spinlock version: remove spinlock pointer */
419 int tdb_clear_spinlocks(TDB_CONTEXT
*tdb
)
421 tdb_off off
= (tdb_off
)((char *)&tdb
->header
.rwlocks
422 - (char *)&tdb
->header
);
424 tdb
->header
.rwlocks
= 0;
425 if (lseek(tdb
->fd
, off
, SEEK_SET
) != off
426 || write(tdb
->fd
, (void *)&tdb
->header
.rwlocks
,
427 sizeof(tdb
->header
.rwlocks
))
428 != sizeof(tdb
->header
.rwlocks
))