diff options
Diffstat (limited to 'firmware/kernel/mutex.c')
-rw-r--r-- | firmware/kernel/mutex.c | 65 |
1 files changed, 21 insertions, 44 deletions
diff --git a/firmware/kernel/mutex.c b/firmware/kernel/mutex.c index f1e4b3c722..2e90b0f4b1 100644 --- a/firmware/kernel/mutex.c +++ b/firmware/kernel/mutex.c | |||
@@ -27,31 +27,10 @@ | |||
27 | #include <stdbool.h> | 27 | #include <stdbool.h> |
28 | #include "config.h" | 28 | #include "config.h" |
29 | #include "system.h" | 29 | #include "system.h" |
30 | #include "mutex.h" | 30 | #include "kernel.h" |
31 | #include "corelock.h" | ||
32 | #include "thread-internal.h" | 31 | #include "thread-internal.h" |
33 | #include "kernel-internal.h" | 32 | #include "kernel-internal.h" |
34 | 33 | ||
35 | static inline void __attribute__((always_inline)) | ||
36 | mutex_set_thread(struct mutex *mtx, struct thread_entry *td) | ||
37 | { | ||
38 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
39 | mtx->blocker.thread = td; | ||
40 | #else | ||
41 | mtx->thread = td; | ||
42 | #endif | ||
43 | } | ||
44 | |||
45 | static inline struct thread_entry * __attribute__((always_inline)) | ||
46 | mutex_get_thread(volatile struct mutex *mtx) | ||
47 | { | ||
48 | #ifdef HAVE_PRIORITY_SCHEDULING | ||
49 | return mtx->blocker.thread; | ||
50 | #else | ||
51 | return mtx->thread; | ||
52 | #endif | ||
53 | } | ||
54 | |||
55 | /* Initialize a mutex object - call before any use and do not call again once | 34 | /* Initialize a mutex object - call before any use and do not call again once |
56 | * the object is available to other threads */ | 35 | * the object is available to other threads */ |
57 | void mutex_init(struct mutex *m) | 36 | void mutex_init(struct mutex *m) |
@@ -59,10 +38,9 @@ void mutex_init(struct mutex *m) | |||
59 | corelock_init(&m->cl); | 38 | corelock_init(&m->cl); |
60 | m->queue = NULL; | 39 | m->queue = NULL; |
61 | m->recursion = 0; | 40 | m->recursion = 0; |
62 | mutex_set_thread(m, NULL); | 41 | m->blocker.thread = NULL; |
63 | #ifdef HAVE_PRIORITY_SCHEDULING | 42 | #ifdef HAVE_PRIORITY_SCHEDULING |
64 | m->blocker.priority = PRIORITY_IDLE; | 43 | m->blocker.priority = PRIORITY_IDLE; |
65 | m->blocker.wakeup_protocol = wakeup_priority_protocol_transfer; | ||
66 | m->no_preempt = false; | 44 | m->no_preempt = false; |
67 | #endif | 45 | #endif |
68 | } | 46 | } |
@@ -72,7 +50,7 @@ void mutex_lock(struct mutex *m) | |||
72 | { | 50 | { |
73 | struct thread_entry *current = thread_self_entry(); | 51 | struct thread_entry *current = thread_self_entry(); |
74 | 52 | ||
75 | if(current == mutex_get_thread(m)) | 53 | if(current == m->blocker.thread) |
76 | { | 54 | { |
77 | /* current thread already owns this mutex */ | 55 | /* current thread already owns this mutex */ |
78 | m->recursion++; | 56 | m->recursion++; |
@@ -83,10 +61,10 @@ void mutex_lock(struct mutex *m) | |||
83 | corelock_lock(&m->cl); | 61 | corelock_lock(&m->cl); |
84 | 62 | ||
85 | /* must read thread again inside cs (a multiprocessor concern really) */ | 63 | /* must read thread again inside cs (a multiprocessor concern really) */ |
86 | if(LIKELY(mutex_get_thread(m) == NULL)) | 64 | if(LIKELY(m->blocker.thread == NULL)) |
87 | { | 65 | { |
88 | /* lock is open */ | 66 | /* lock is open */ |
89 | mutex_set_thread(m, current); | 67 | m->blocker.thread = current; |
90 | corelock_unlock(&m->cl); | 68 | corelock_unlock(&m->cl); |
91 | return; | 69 | return; |
92 | } | 70 | } |
@@ -97,7 +75,7 @@ void mutex_lock(struct mutex *m) | |||
97 | current->bqp = &m->queue; | 75 | current->bqp = &m->queue; |
98 | 76 | ||
99 | disable_irq(); | 77 | disable_irq(); |
100 | block_thread(current); | 78 | block_thread(current, TIMEOUT_BLOCK); |
101 | 79 | ||
102 | corelock_unlock(&m->cl); | 80 | corelock_unlock(&m->cl); |
103 | 81 | ||
@@ -109,9 +87,9 @@ void mutex_lock(struct mutex *m) | |||
109 | void mutex_unlock(struct mutex *m) | 87 | void mutex_unlock(struct mutex *m) |
110 | { | 88 | { |
111 | /* unlocker not being the owner is an unlocking violation */ | 89 | /* unlocker not being the owner is an unlocking violation */ |
112 | KERNEL_ASSERT(mutex_get_thread(m) == thread_self_entry(), | 90 | KERNEL_ASSERT(m->blocker.thread == thread_self_entry(), |
113 | "mutex_unlock->wrong thread (%s != %s)\n", | 91 | "mutex_unlock->wrong thread (%s != %s)\n", |
114 | mutex_get_thread(m)->name, | 92 | m->blocker.thread->name, |
115 | thread_self_entry()->name); | 93 | thread_self_entry()->name); |
116 | 94 | ||
117 | if(m->recursion > 0) | 95 | if(m->recursion > 0) |
@@ -128,25 +106,24 @@ void mutex_unlock(struct mutex *m) | |||
128 | if(LIKELY(m->queue == NULL)) | 106 | if(LIKELY(m->queue == NULL)) |
129 | { | 107 | { |
130 | /* no threads waiting - open the lock */ | 108 | /* no threads waiting - open the lock */ |
131 | mutex_set_thread(m, NULL); | 109 | m->blocker.thread = NULL; |
132 | corelock_unlock(&m->cl); | 110 | corelock_unlock(&m->cl); |
133 | return; | 111 | return; |
134 | } | 112 | } |
135 | else | ||
136 | { | ||
137 | const int oldlevel = disable_irq_save(); | ||
138 | /* Tranfer of owning thread is handled in the wakeup protocol | ||
139 | * if priorities are enabled otherwise just set it from the | ||
140 | * queue head. */ | ||
141 | IFN_PRIO( mutex_set_thread(m, m->queue); ) | ||
142 | IF_PRIO( unsigned int result = ) wakeup_thread(&m->queue); | ||
143 | restore_irq(oldlevel); | ||
144 | 113 | ||
145 | corelock_unlock(&m->cl); | 114 | const int oldlevel = disable_irq_save(); |
115 | /* Tranfer of owning thread is handled in the wakeup protocol | ||
116 | * if priorities are enabled otherwise just set it from the | ||
117 | * queue head. */ | ||
118 | IFN_PRIO( m->blocker.thread = m->queue; ) | ||
119 | unsigned int result = wakeup_thread(&m->queue, WAKEUP_TRANSFER); | ||
120 | restore_irq(oldlevel); | ||
121 | |||
122 | corelock_unlock(&m->cl); | ||
146 | 123 | ||
147 | #ifdef HAVE_PRIORITY_SCHEDULING | 124 | #ifdef HAVE_PRIORITY_SCHEDULING |
148 | if((result & THREAD_SWITCH) && !m->no_preempt) | 125 | if((result & THREAD_SWITCH) && !m->no_preempt) |
149 | switch_thread(); | 126 | switch_thread(); |
150 | #endif | 127 | #endif |
151 | } | 128 | (void)result; |
152 | } | 129 | } |