Rev 5056 | Rev 5272 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5056 | Rev 5270 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Mutexes: blocking mutual exclusion locks |
2 | * Mutexes: blocking mutual exclusion locks |
3 | * |
3 | * |
4 | * started by Ingo Molnar: |
4 | * started by Ingo Molnar: |
5 | * |
5 | * |
6 | * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar |
6 | * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar |
7 | * |
7 | * |
8 | * This file contains the main data structure and API definitions. |
8 | * This file contains the main data structure and API definitions. |
9 | */ |
9 | */ |
10 | #ifndef __LINUX_MUTEX_H |
10 | #ifndef __LINUX_MUTEX_H |
11 | #define __LINUX_MUTEX_H |
11 | #define __LINUX_MUTEX_H |
- | 12 | ||
12 | 13 | #include |
|
13 | #include |
14 | #include |
- | 15 | #include |
|
- | 16 | #include |
|
- | 17 | #include |
|
14 | #include |
18 | #include |
15 | 19 | ||
16 | /* |
20 | /* |
17 | * Simple, straightforward mutexes with strict semantics: |
21 | * Simple, straightforward mutexes with strict semantics: |
18 | * |
22 | * |
19 | * - only one task can hold the mutex at a time |
23 | * - only one task can hold the mutex at a time |
20 | * - only the owner can unlock the mutex |
24 | * - only the owner can unlock the mutex |
21 | * - multiple unlocks are not permitted |
25 | * - multiple unlocks are not permitted |
22 | * - recursive locking is not permitted |
26 | * - recursive locking is not permitted |
23 | * - a mutex object must be initialized via the API |
27 | * - a mutex object must be initialized via the API |
24 | * - a mutex object must not be initialized via memset or copying |
28 | * - a mutex object must not be initialized via memset or copying |
25 | * - task may not exit with mutex held |
29 | * - task may not exit with mutex held |
26 | * - memory areas where held locks reside must not be freed |
30 | * - memory areas where held locks reside must not be freed |
27 | * - held mutexes must not be reinitialized |
31 | * - held mutexes must not be reinitialized |
28 | * - mutexes may not be used in hardware or software interrupt |
32 | * - mutexes may not be used in hardware or software interrupt |
29 | * contexts such as tasklets and timers |
33 | * contexts such as tasklets and timers |
30 | * |
34 | * |
31 | * These semantics are fully enforced when DEBUG_MUTEXES is |
35 | * These semantics are fully enforced when DEBUG_MUTEXES is |
32 | * enabled. Furthermore, besides enforcing the above rules, the mutex |
36 | * enabled. Furthermore, besides enforcing the above rules, the mutex |
33 | * debugging code also implements a number of additional features |
37 | * debugging code also implements a number of additional features |
34 | * that make lock debugging easier and faster: |
38 | * that make lock debugging easier and faster: |
35 | * |
39 | * |
36 | * - uses symbolic names of mutexes, whenever they are printed in debug output |
40 | * - uses symbolic names of mutexes, whenever they are printed in debug output |
37 | * - point-of-acquire tracking, symbolic lookup of function names |
41 | * - point-of-acquire tracking, symbolic lookup of function names |
38 | * - list of all locks held in the system, printout of them |
42 | * - list of all locks held in the system, printout of them |
39 | * - owner tracking |
43 | * - owner tracking |
40 | * - detects self-recursing locks and prints out all relevant info |
44 | * - detects self-recursing locks and prints out all relevant info |
41 | * - detects multi-task circular deadlocks and prints out all affected |
45 | * - detects multi-task circular deadlocks and prints out all affected |
42 | * locks and tasks (and only those tasks) |
46 | * locks and tasks (and only those tasks) |
43 | */ |
47 | */ |
44 | struct mutex { |
48 | struct mutex { |
45 | /* 1: unlocked, 0: locked, negative: locked, possible waiters */ |
49 | /* 1: unlocked, 0: locked, negative: locked, possible waiters */ |
46 | struct list_head wait_list; |
50 | struct list_head wait_list; |
47 | atomic_t count; |
51 | atomic_t count; |
48 | }; |
52 | }; |
49 | 53 | ||
50 | /* |
54 | /* |
51 | * This is the control structure for tasks blocked on mutex, |
55 | * This is the control structure for tasks blocked on mutex, |
52 | * which resides on the blocked task's kernel stack: |
56 | * which resides on the blocked task's kernel stack: |
53 | */ |
57 | */ |
54 | struct mutex_waiter { |
58 | struct mutex_waiter { |
55 | struct list_head list; |
59 | struct list_head list; |
56 | int *task; |
60 | int *task; |
57 | }; |
61 | }; |
58 | 62 | ||
59 | 63 | ||
60 | #define __MUTEX_INITIALIZER(lockname) \ |
64 | #define __MUTEX_INITIALIZER(lockname) \ |
61 | { .wait_list = LIST_HEAD_INIT(lockname.wait_list), \ |
65 | { .wait_list = LIST_HEAD_INIT(lockname.wait_list), \ |
62 | .count = ATOMIC_INIT(1) \ |
66 | .count = ATOMIC_INIT(1) \ |
63 | } |
67 | } |
64 | 68 | ||
65 | #define DEFINE_MUTEX(mutexname) \ |
69 | #define DEFINE_MUTEX(mutexname) \ |
66 | struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) |
70 | struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) |
67 | 71 | ||
68 | void __attribute__ ((fastcall)) __attribute__ ((dllimport)) |
72 | void __attribute__ ((fastcall)) __attribute__ ((dllimport)) |
69 | mutex_init(struct mutex*)__asm__("MutexInit"); |
73 | mutex_init(struct mutex*)__asm__("MutexInit"); |
70 | void __attribute__ ((fastcall)) __attribute__ ((dllimport)) |
74 | void __attribute__ ((fastcall)) __attribute__ ((dllimport)) |
71 | mutex_lock(struct mutex*)__asm__("MutexLock"); |
75 | mutex_lock(struct mutex*)__asm__("MutexLock"); |
72 | void __attribute__ ((fastcall)) __attribute__ ((dllimport)) |
76 | void __attribute__ ((fastcall)) __attribute__ ((dllimport)) |
73 | mutex_unlock(struct mutex*)__asm__("MutexUnlock"); |
77 | mutex_unlock(struct mutex*)__asm__("MutexUnlock"); |
74 | 78 | ||
75 | static inline int mutex_lock_interruptible(struct mutex *lock) |
79 | static inline int mutex_lock_interruptible(struct mutex *lock) |
76 | { |
80 | { |
77 | mutex_lock(lock); |
81 | mutex_lock(lock); |
78 | return 0; |
82 | return 0; |
79 | } |
83 | } |
80 | 84 | ||
81 | # define mutex_lock_nest_lock(lock, nest_lock) mutex_lock(lock) |
85 | # define mutex_lock_nest_lock(lock, nest_lock) mutex_lock(lock) |
82 | 86 | ||
83 | 87 | ||
84 | /** |
88 | /** |
85 | * mutex_is_locked - is the mutex locked |
89 | * mutex_is_locked - is the mutex locked |
86 | * @lock: the mutex to be queried |
90 | * @lock: the mutex to be queried |
87 | * |
91 | * |
88 | * Returns 1 if the mutex is locked, 0 if unlocked. |
92 | * Returns 1 if the mutex is locked, 0 if unlocked. |
89 | */ |
93 | */ |
90 | static inline int mutex_is_locked(struct mutex *lock) |
94 | static inline int mutex_is_locked(struct mutex *lock) |
91 | { |
95 | { |
92 | return atomic_read(&lock->count) != 1; |
96 | return atomic_read(&lock->count) != 1; |
93 | } |
97 | } |
94 | 98 | ||
95 | static inline int mutex_trylock(struct mutex *lock) |
99 | static inline int mutex_trylock(struct mutex *lock) |
96 | { |
100 | { |
97 | if (likely(atomic_cmpxchg(&lock->count, 1, 0) == 1)) |
101 | if (likely(atomic_cmpxchg(&lock->count, 1, 0) == 1)) |
98 | return 1; |
102 | return 1; |
99 | return 0; |
103 | return 0; |
100 | } |
104 | } |
101 | 105 | ||
102 | static inline void mutex_destroy(struct mutex *lock) |
106 | static inline void mutex_destroy(struct mutex *lock) |
103 | { |
107 | { |
104 | 108 | ||
105 | }; |
109 | }; |
106 | 110 | ||
107 | #endif |
111 | #endif |