Subversion Repositories Kolibri OS

Rev

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