Subversion Repositories Kolibri OS

Rev

Rev 5347 | Rev 6934 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5347 Rev 6102
1
/* rwsem.h: R/W semaphores implemented using XADD/CMPXCHG for i486+
1
/* rwsem.h: R/W semaphores implemented using XADD/CMPXCHG for i486+
2
 *
2
 *
3
 * Written by David Howells (dhowells@redhat.com).
3
 * Written by David Howells (dhowells@redhat.com).
4
 *
4
 *
5
 * Derived from asm-x86/semaphore.h
5
 * Derived from asm-x86/semaphore.h
6
 *
6
 *
7
 *
7
 *
8
 * The MSW of the count is the negated number of active writers and waiting
8
 * The MSW of the count is the negated number of active writers and waiting
9
 * lockers, and the LSW is the total number of active locks
9
 * lockers, and the LSW is the total number of active locks
10
 *
10
 *
11
 * The lock count is initialized to 0 (no active and no waiting lockers).
11
 * The lock count is initialized to 0 (no active and no waiting lockers).
12
 *
12
 *
13
 * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case of an
13
 * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case of an
14
 * uncontended lock. This can be determined because XADD returns the old value.
14
 * uncontended lock. This can be determined because XADD returns the old value.
15
 * Readers increment by 1 and see a positive value when uncontended, negative
15
 * Readers increment by 1 and see a positive value when uncontended, negative
16
 * if there are writers (and maybe) readers waiting (in which case it goes to
16
 * if there are writers (and maybe) readers waiting (in which case it goes to
17
 * sleep).
17
 * sleep).
18
 *
18
 *
19
 * The value of WAITING_BIAS supports up to 32766 waiting processes. This can
19
 * The value of WAITING_BIAS supports up to 32766 waiting processes. This can
20
 * be extended to 65534 by manually checking the whole MSW rather than relying
20
 * be extended to 65534 by manually checking the whole MSW rather than relying
21
 * on the S flag.
21
 * on the S flag.
22
 *
22
 *
23
 * The value of ACTIVE_BIAS supports up to 65535 active processes.
23
 * The value of ACTIVE_BIAS supports up to 65535 active processes.
24
 *
24
 *
25
 * This should be totally fair - if anything is waiting, a process that wants a
25
 * This should be totally fair - if anything is waiting, a process that wants a
26
 * lock will go to the back of the queue. When the currently active lock is
26
 * lock will go to the back of the queue. When the currently active lock is
27
 * released, if there's a writer at the front of the queue, then that and only
27
 * released, if there's a writer at the front of the queue, then that and only
28
 * that will be woken up; if there's a bunch of consequtive readers at the
28
 * that will be woken up; if there's a bunch of consequtive readers at the
29
 * front, then they'll all be woken up, but no other readers will be.
29
 * front, then they'll all be woken up, but no other readers will be.
30
 */
30
 */
31
 
31
 
32
#ifndef _ASM_X86_RWSEM_H
32
#ifndef _ASM_X86_RWSEM_H
33
#define _ASM_X86_RWSEM_H
33
#define _ASM_X86_RWSEM_H
34
 
34
 
35
#ifndef _LINUX_RWSEM_H
35
#ifndef _LINUX_RWSEM_H
36
#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
36
#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
37
#endif
37
#endif
38
 
38
 
39
#ifdef __KERNEL__
39
#ifdef __KERNEL__
40
#include 
40
#include 
41
 
41
 
42
#define FASTCALL __attribute__ ((fastcall)) __attribute__ ((dllimport))
42
#define FASTCALL __attribute__ ((fastcall)) __attribute__ ((dllimport))
43
 
43
 
44
void  FASTCALL InitRwsem(struct rw_semaphore *sem)__asm__("InitRwsem");
44
void  FASTCALL InitRwsem(struct rw_semaphore *sem)__asm__("InitRwsem");
45
void  FASTCALL DownRead(struct rw_semaphore *sem)__asm__("DownRead");
45
void  FASTCALL DownRead(struct rw_semaphore *sem)__asm__("DownRead");
46
void  FASTCALL DownWrite(struct rw_semaphore *sem)__asm__("DownWrite");
46
void  FASTCALL DownWrite(struct rw_semaphore *sem)__asm__("DownWrite");
47
void  FASTCALL UpRead(struct rw_semaphore *sem)__asm__("UpRead");
47
void  FASTCALL UpRead(struct rw_semaphore *sem)__asm__("UpRead");
48
void  FASTCALL UpWrite(struct rw_semaphore *sem)__asm__("UpWrite");
48
void  FASTCALL UpWrite(struct rw_semaphore *sem)__asm__("UpWrite");
49
 
49
 
50
static inline void __init_rwsem(struct rw_semaphore *sem, const char *name,
50
static inline void __init_rwsem(struct rw_semaphore *sem, const char *name,
51
                  struct lock_class_key *key)
51
                  struct lock_class_key *key)
52
{
52
{
53
    InitRwsem(sem);
53
    InitRwsem(sem);
54
}
54
}
55
 
55
 
56
/*
56
/*
57
 * lock for reading
57
 * lock for reading
58
 */
58
 */
59
static inline void down_read(struct rw_semaphore *sem)
59
static inline void down_read(struct rw_semaphore *sem)
60
{
60
{
61
    DownRead(sem);
61
    DownRead(sem);
62
}
62
}
63
 
63
 
64
static inline void down_write(struct rw_semaphore *sem)
64
static inline void down_write(struct rw_semaphore *sem)
65
{
65
{
66
    DownWrite(sem);
66
    DownWrite(sem);
67
}
67
}
68
 
68
 
69
/*
69
/*
70
 * unlock after reading
70
 * unlock after reading
71
 */
71
 */
72
static inline void up_read(struct rw_semaphore *sem)
72
static inline void up_read(struct rw_semaphore *sem)
73
{
73
{
74
    UpRead(sem);
74
    UpRead(sem);
75
}
75
}
76
 
76
 
77
/*
77
/*
78
 * unlock after writing
78
 * unlock after writing
79
 */
79
 */
80
static inline void up_write(struct rw_semaphore *sem)
80
static inline void up_write(struct rw_semaphore *sem)
81
{
81
{
82
    UpWrite(sem);
82
    UpWrite(sem);
83
}
83
}
-
 
84
 
-
 
85
#define RWSEM_UNLOCKED_VALUE            0x00000000L
-
 
86
#define RWSEM_ACTIVE_BIAS               0x00000001L
-
 
87
#define RWSEM_WAITING_BIAS              (-RWSEM_ACTIVE_MASK-1)
-
 
88
#define RWSEM_ACTIVE_READ_BIAS          RWSEM_ACTIVE_BIAS
-
 
89
#define RWSEM_ACTIVE_WRITE_BIAS         (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-
 
90
 
-
 
91
static inline int down_read_trylock(struct rw_semaphore *sem)
-
 
92
{
-
 
93
    long result, tmp;
-
 
94
    asm volatile("# beginning __down_read_trylock\n\t"
-
 
95
                 "  mov          %0,%1\n\t"
-
 
96
                 "1:\n\t"
-
 
97
                 "  mov          %1,%2\n\t"
-
 
98
                 "  add          %3,%2\n\t"
-
 
99
                 "  jle          2f\n\t"
-
 
100
                 LOCK_PREFIX "  cmpxchg  %2,%0\n\t"
-
 
101
                 "  jnz          1b\n\t"
-
 
102
                 "2:\n\t"
-
 
103
                 "# ending __down_read_trylock\n\t"
-
 
104
                 : "+m" (sem->count), "=&a" (result), "=&r" (tmp)
-
 
105
                 : "i" (RWSEM_ACTIVE_READ_BIAS)
-
 
106
                 : "memory", "cc");
-
 
107
    return result >= 0 ? 1 : 0;
-
 
108
}
-
 
109
 
84
 
110
 
85
#endif /* __KERNEL__ */
111
#endif /* __KERNEL__ */
86
#endif /* _ASM_X86_RWSEM_H */
112
#endif /* _ASM_X86_RWSEM_H */