[ac7d5ef0] | 1 | /* |
---|
| 2 | * Description: |
---|
| 3 | * HPPA fast spinlock semaphores based on LDCWX instruction. |
---|
| 4 | * These semaphores are not known to RTEMS. |
---|
| 5 | * |
---|
| 6 | * TODO: |
---|
| 7 | * Put node number in high 16 bits of flag?? |
---|
| 8 | * XXX: Need h_s_deallocate |
---|
| 9 | * |
---|
[e71ce071] | 10 | * COPYRIGHT (c) 1994 by Division Incorporated |
---|
| 11 | * |
---|
| 12 | * The license and distribution terms for this file may in |
---|
| 13 | * the file LICENSE in this distribution or at |
---|
| 14 | * http://www.OARcorp.com/rtems/license.html. |
---|
| 15 | * |
---|
[ac7d5ef0] | 16 | * $Id$ |
---|
| 17 | */ |
---|
| 18 | |
---|
| 19 | #include <bsp.h> |
---|
| 20 | |
---|
| 21 | #include "semaphore.h" |
---|
| 22 | |
---|
| 23 | /* |
---|
| 24 | * Report fatal semaphore error |
---|
| 25 | */ |
---|
| 26 | |
---|
| 27 | #define SEM_FATAL_ERROR(sp) rtems_fatal_error_occurred((rtems_unsigned32) sp) |
---|
| 28 | |
---|
| 29 | #define SEM_CHECK(sp) do { \ |
---|
| 30 | if (((sp) == 0) || (int) (sp) & 0xf) \ |
---|
| 31 | { \ |
---|
| 32 | SEM_FATAL_ERROR(sp); \ |
---|
| 33 | } \ |
---|
| 34 | } while (0) |
---|
| 35 | |
---|
| 36 | /* |
---|
| 37 | * Init a semaphore to be free |
---|
| 38 | */ |
---|
| 39 | |
---|
| 40 | #define SEM_FREE_INIT(sp) \ |
---|
| 41 | do { \ |
---|
| 42 | (sp)->lock = 1; \ |
---|
| 43 | (sp)->flags = 0; \ |
---|
| 44 | (sp)->owner_tcb = 0; \ |
---|
| 45 | } while (0) |
---|
| 46 | |
---|
| 47 | /* |
---|
| 48 | * Grab a semaphore recording its owner. |
---|
| 49 | */ |
---|
| 50 | |
---|
| 51 | #define SEM_MARK_GRABBED(sp) \ |
---|
| 52 | do { \ |
---|
| 53 | (sp)->owner_tcb = _Thread_Executing; \ |
---|
| 54 | } while (0) |
---|
| 55 | |
---|
| 56 | /* |
---|
| 57 | * Mark the semaphore busy |
---|
| 58 | */ |
---|
| 59 | |
---|
| 60 | #define SEM_MARK_BUSY(sp) ((sp)->flags |= HPPA_SEM_IN_USE) |
---|
| 61 | |
---|
| 62 | /* |
---|
| 63 | * Is a semaphore available? |
---|
| 64 | */ |
---|
| 65 | |
---|
| 66 | #define SEM_IS_AVAILABLE(sp) ((sp)->owner_tcb == 0) |
---|
| 67 | |
---|
| 68 | /* |
---|
| 69 | * The pool control semaphore is the first in the pool |
---|
| 70 | */ |
---|
| 71 | |
---|
| 72 | #define SEM_CONTROL (&hppa_semaphore_pool[0]) |
---|
| 73 | #define SEM_FIRST (&hppa_semaphore_pool[1]) |
---|
| 74 | |
---|
| 75 | #define SEM_PRIVATE(cookie) rtems_interrupt_disable(cookie) |
---|
| 76 | |
---|
| 77 | #define SEM_PUBLIC(cookie) rtems_interrupt_enable(cookie) |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | /* |
---|
| 81 | * Control variables for the pool |
---|
| 82 | */ |
---|
| 83 | |
---|
| 84 | hppa_semaphore_t *hppa_semaphore_pool; /* ptr to first */ |
---|
| 85 | int hppa_semaphores; |
---|
| 86 | int hppa_semaphores_available; |
---|
| 87 | |
---|
| 88 | void |
---|
| 89 | hppa_semaphore_pool_initialize(void *pool_base, |
---|
| 90 | int pool_size) |
---|
| 91 | { |
---|
| 92 | hppa_semaphore_t *sp; |
---|
| 93 | int align_factor; |
---|
| 94 | rtems_unsigned32 isr_level; |
---|
| 95 | |
---|
| 96 | /* |
---|
| 97 | * round pool_base up to be a multiple of SEM_ALIGN |
---|
| 98 | */ |
---|
| 99 | |
---|
| 100 | align_factor = SEM_ALIGN - (((int) pool_base) & (SEM_ALIGN-1)); |
---|
| 101 | if (align_factor != SEM_ALIGN) |
---|
| 102 | { |
---|
| 103 | pool_base += align_factor; |
---|
| 104 | pool_size -= align_factor; |
---|
| 105 | } |
---|
| 106 | |
---|
| 107 | /* |
---|
| 108 | * How many can the pool hold? |
---|
| 109 | * Assumes the semaphores are SEM_ALIGN bytes each |
---|
| 110 | */ |
---|
| 111 | |
---|
| 112 | if (sizeof(hppa_semaphore_t) != SEM_ALIGN) |
---|
| 113 | rtems_fatal_error_occurred(RTEMS_INVALID_SIZE); |
---|
| 114 | |
---|
| 115 | pool_size &= ~(SEM_ALIGN - 1); |
---|
| 116 | |
---|
| 117 | SEM_PRIVATE(isr_level); |
---|
| 118 | |
---|
| 119 | hppa_semaphore_pool = pool_base; |
---|
| 120 | hppa_semaphores = pool_size / SEM_ALIGN; |
---|
| 121 | |
---|
| 122 | /* |
---|
| 123 | * If we are node0, then init all in the pool |
---|
| 124 | */ |
---|
| 125 | |
---|
| 126 | if (cpu_number == 0) |
---|
| 127 | { |
---|
| 128 | /* |
---|
| 129 | * Tell other cpus we are not done, jic |
---|
| 130 | */ |
---|
| 131 | SEM_CONTROL->user = rtems_build_name('!', 'D', 'N', 'E'); |
---|
| 132 | |
---|
| 133 | for (sp=SEM_FIRST; sp < &hppa_semaphore_pool[hppa_semaphores]; sp++) |
---|
| 134 | SEM_FREE_INIT(sp); |
---|
| 135 | SEM_FREE_INIT(SEM_CONTROL); |
---|
| 136 | } |
---|
| 137 | |
---|
| 138 | /* |
---|
| 139 | * Tell other cpus we are done, or wait for it to be done if on another cpu |
---|
| 140 | */ |
---|
| 141 | |
---|
| 142 | if (cpu_number == 0) |
---|
| 143 | SEM_CONTROL->user = rtems_build_name('D', 'O', 'N', 'E'); |
---|
| 144 | else |
---|
| 145 | while (SEM_CONTROL->user != rtems_build_name('D', 'O', 'N', 'E')) |
---|
| 146 | ; |
---|
| 147 | |
---|
| 148 | hppa_semaphores_available = hppa_semaphores; |
---|
| 149 | |
---|
| 150 | SEM_PUBLIC(isr_level); |
---|
| 151 | } |
---|
| 152 | |
---|
| 153 | /* |
---|
| 154 | * Function: hppa_semaphore_acquire |
---|
| 155 | * Created: 94/11/29 |
---|
| 156 | * RespEngr: tony bennett |
---|
| 157 | * |
---|
| 158 | * Description: |
---|
| 159 | * Acquire a semaphore. Will spin on the semaphore unless |
---|
| 160 | * 'flag' says not to. |
---|
| 161 | * |
---|
| 162 | * Parameters: |
---|
| 163 | * |
---|
| 164 | * |
---|
| 165 | * Returns: |
---|
| 166 | * 0 -- if did not acquire |
---|
| 167 | * non-zero -- if acquired semaphore |
---|
| 168 | * (actually this is the spin count) |
---|
| 169 | * |
---|
| 170 | * Notes: |
---|
| 171 | * There is no requirement that the semaphore be within the pool |
---|
| 172 | * |
---|
| 173 | * Deficiencies/ToDo: |
---|
| 174 | * |
---|
| 175 | */ |
---|
| 176 | |
---|
| 177 | |
---|
| 178 | rtems_unsigned32 |
---|
| 179 | hppa_semaphore_acquire(hppa_semaphore_t *sp, |
---|
| 180 | int flag) |
---|
| 181 | { |
---|
| 182 | rtems_unsigned32 lock_value; |
---|
| 183 | rtems_unsigned32 spin_count = 1; |
---|
| 184 | |
---|
| 185 | SEM_CHECK(sp); |
---|
| 186 | |
---|
| 187 | for (;;) |
---|
| 188 | { |
---|
| 189 | HPPA_ASM_LDCWS(0, 0, sp, lock_value); |
---|
| 190 | |
---|
| 191 | if (lock_value) /* we now own the lock */ |
---|
| 192 | { |
---|
| 193 | SEM_MARK_GRABBED(sp); |
---|
| 194 | return spin_count ? spin_count : ~0; /* jic */ |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | if (flag & HPPA_SEM_NO_SPIN) |
---|
| 198 | return 0; |
---|
| 199 | |
---|
| 200 | spin_count++; |
---|
| 201 | } |
---|
| 202 | } |
---|
| 203 | |
---|
| 204 | void |
---|
| 205 | hppa_semaphore_release(hppa_semaphore_t *sp) |
---|
| 206 | { |
---|
| 207 | SEM_CHECK(sp); |
---|
| 208 | |
---|
| 209 | if (sp->owner_tcb != _Thread_Executing) |
---|
| 210 | SEM_FATAL_ERROR("owner mismatch"); |
---|
| 211 | |
---|
| 212 | sp->lock = 1; |
---|
| 213 | } |
---|
| 214 | |
---|
| 215 | |
---|
| 216 | /* |
---|
| 217 | * Function: hppa_semaphore_allocate |
---|
| 218 | * Created: 94/11/29 |
---|
| 219 | * RespEngr: tony bennett |
---|
| 220 | * |
---|
| 221 | * Description: |
---|
| 222 | * Get a pointer to a semaphore. |
---|
| 223 | * |
---|
| 224 | * Parameters: |
---|
| 225 | * which -- if 0, then allocate a free semaphore from the pool |
---|
| 226 | * if non-zero, then return pointer to that one, even |
---|
| 227 | * if it is already busy. |
---|
| 228 | * |
---|
| 229 | * Returns: |
---|
| 230 | * successful -- pointer to semaphore |
---|
| 231 | * NULL otherwise |
---|
| 232 | * |
---|
| 233 | * Notes: |
---|
| 234 | * |
---|
| 235 | * |
---|
| 236 | * Deficiencies/ToDo: |
---|
| 237 | * |
---|
| 238 | * |
---|
| 239 | */ |
---|
| 240 | |
---|
| 241 | hppa_semaphore_t * |
---|
| 242 | hppa_semaphore_allocate(rtems_unsigned32 which, |
---|
| 243 | int flag) |
---|
| 244 | { |
---|
| 245 | hppa_semaphore_t *sp = 0; |
---|
| 246 | |
---|
| 247 | /* |
---|
| 248 | * grab the control semaphore |
---|
| 249 | */ |
---|
| 250 | |
---|
| 251 | if (hppa_semaphore_acquire(SEM_CONTROL, 0) == 0) |
---|
| 252 | SEM_FATAL_ERROR("could not grab control semaphore"); |
---|
| 253 | |
---|
| 254 | /* |
---|
| 255 | * Find a free one and init it |
---|
| 256 | */ |
---|
| 257 | |
---|
| 258 | if (which) |
---|
| 259 | { |
---|
| 260 | if (which >= hppa_semaphores) |
---|
| 261 | SEM_FATAL_ERROR("requested non-existent semaphore"); |
---|
| 262 | sp = &hppa_semaphore_pool[which]; |
---|
| 263 | |
---|
| 264 | /* |
---|
| 265 | * if it is "free", then mark it claimed now. |
---|
| 266 | * If it is not free then we are done. |
---|
| 267 | */ |
---|
| 268 | |
---|
| 269 | if (SEM_IS_AVAILABLE(sp)) |
---|
| 270 | goto allmine; |
---|
| 271 | } |
---|
| 272 | else for (sp = SEM_FIRST; |
---|
| 273 | sp < &hppa_semaphore_pool[hppa_semaphores]; |
---|
| 274 | sp++) |
---|
| 275 | { |
---|
| 276 | if (SEM_IS_AVAILABLE(sp)) |
---|
| 277 | { |
---|
| 278 | allmine: SEM_FREE_INIT(sp); |
---|
| 279 | SEM_MARK_BUSY(sp); |
---|
| 280 | if ( ! (flag & HPPA_SEM_INITIALLY_FREE)) |
---|
| 281 | SEM_MARK_GRABBED(sp); |
---|
| 282 | break; |
---|
| 283 | } |
---|
| 284 | } |
---|
| 285 | |
---|
| 286 | /* |
---|
| 287 | * Free up the control semaphore |
---|
| 288 | */ |
---|
| 289 | |
---|
| 290 | hppa_semaphore_release(SEM_CONTROL); |
---|
| 291 | |
---|
| 292 | return sp; |
---|
| 293 | } |
---|
| 294 | |
---|