From ac7d5ef06a6d6e8d84abbd1f0b82162725f98326 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 11 May 1995 17:39:37 +0000 Subject: Initial revision --- c/src/lib/libcpu/hppa1.1/semaphore/semaphore.c | 308 +++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 c/src/lib/libcpu/hppa1.1/semaphore/semaphore.c (limited to 'c/src/lib/libcpu/hppa1.1/semaphore/semaphore.c') diff --git a/c/src/lib/libcpu/hppa1.1/semaphore/semaphore.c b/c/src/lib/libcpu/hppa1.1/semaphore/semaphore.c new file mode 100644 index 0000000000..aa8b768b3a --- /dev/null +++ b/c/src/lib/libcpu/hppa1.1/semaphore/semaphore.c @@ -0,0 +1,308 @@ +/* + * File: $RCSfile$ + * Project: PixelFlow + * Created: 94/11/29 + * RespEngr: tony bennett + * Revision: $Revision$ + * Last Mod: $Date$ + * + * COPYRIGHT (c) 1994 by Division Incorporated + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Division Incorporated not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Division Incorporated makes no representations about the + * suitability of this software for any purpose. + * + * Description: + * HPPA fast spinlock semaphores based on LDCWX instruction. + * These semaphores are not known to RTEMS. + * + * TODO: + * Put node number in high 16 bits of flag?? + * XXX: Need h_s_deallocate + * + * $Id$ + */ + +#include + +#include "semaphore.h" + +/* + * Report fatal semaphore error + */ + +#define SEM_FATAL_ERROR(sp) rtems_fatal_error_occurred((rtems_unsigned32) sp) + +#define SEM_CHECK(sp) do { \ + if (((sp) == 0) || (int) (sp) & 0xf) \ + { \ + SEM_FATAL_ERROR(sp); \ + } \ + } while (0) + +/* + * Init a semaphore to be free + */ + +#define SEM_FREE_INIT(sp) \ + do { \ + (sp)->lock = 1; \ + (sp)->flags = 0; \ + (sp)->owner_tcb = 0; \ + } while (0) + +/* + * Grab a semaphore recording its owner. + */ + +#define SEM_MARK_GRABBED(sp) \ + do { \ + (sp)->owner_tcb = _Thread_Executing; \ + } while (0) + +/* + * Mark the semaphore busy + */ + +#define SEM_MARK_BUSY(sp) ((sp)->flags |= HPPA_SEM_IN_USE) + +/* + * Is a semaphore available? + */ + +#define SEM_IS_AVAILABLE(sp) ((sp)->owner_tcb == 0) + +/* + * The pool control semaphore is the first in the pool + */ + +#define SEM_CONTROL (&hppa_semaphore_pool[0]) +#define SEM_FIRST (&hppa_semaphore_pool[1]) + +#define SEM_PRIVATE(cookie) rtems_interrupt_disable(cookie) + +#define SEM_PUBLIC(cookie) rtems_interrupt_enable(cookie) + + +/* + * Control variables for the pool + */ + +hppa_semaphore_t *hppa_semaphore_pool; /* ptr to first */ +int hppa_semaphores; +int hppa_semaphores_available; + +void +hppa_semaphore_pool_initialize(void *pool_base, + int pool_size) +{ + hppa_semaphore_t *sp; + int align_factor; + rtems_unsigned32 isr_level; + + /* + * round pool_base up to be a multiple of SEM_ALIGN + */ + + align_factor = SEM_ALIGN - (((int) pool_base) & (SEM_ALIGN-1)); + if (align_factor != SEM_ALIGN) + { + pool_base += align_factor; + pool_size -= align_factor; + } + + /* + * How many can the pool hold? + * Assumes the semaphores are SEM_ALIGN bytes each + */ + + if (sizeof(hppa_semaphore_t) != SEM_ALIGN) + rtems_fatal_error_occurred(RTEMS_INVALID_SIZE); + + pool_size &= ~(SEM_ALIGN - 1); + + SEM_PRIVATE(isr_level); + + hppa_semaphore_pool = pool_base; + hppa_semaphores = pool_size / SEM_ALIGN; + + /* + * If we are node0, then init all in the pool + */ + + if (cpu_number == 0) + { + /* + * Tell other cpus we are not done, jic + */ + SEM_CONTROL->user = rtems_build_name('!', 'D', 'N', 'E'); + + for (sp=SEM_FIRST; sp < &hppa_semaphore_pool[hppa_semaphores]; sp++) + SEM_FREE_INIT(sp); + SEM_FREE_INIT(SEM_CONTROL); + } + + /* + * Tell other cpus we are done, or wait for it to be done if on another cpu + */ + + if (cpu_number == 0) + SEM_CONTROL->user = rtems_build_name('D', 'O', 'N', 'E'); + else + while (SEM_CONTROL->user != rtems_build_name('D', 'O', 'N', 'E')) + ; + + hppa_semaphores_available = hppa_semaphores; + + SEM_PUBLIC(isr_level); +} + +/* + * Function: hppa_semaphore_acquire + * Created: 94/11/29 + * RespEngr: tony bennett + * + * Description: + * Acquire a semaphore. Will spin on the semaphore unless + * 'flag' says not to. + * + * Parameters: + * + * + * Returns: + * 0 -- if did not acquire + * non-zero -- if acquired semaphore + * (actually this is the spin count) + * + * Notes: + * There is no requirement that the semaphore be within the pool + * + * Deficiencies/ToDo: + * + */ + + +rtems_unsigned32 +hppa_semaphore_acquire(hppa_semaphore_t *sp, + int flag) +{ + rtems_unsigned32 lock_value; + rtems_unsigned32 spin_count = 1; + + SEM_CHECK(sp); + + for (;;) + { + HPPA_ASM_LDCWS(0, 0, sp, lock_value); + + if (lock_value) /* we now own the lock */ + { + SEM_MARK_GRABBED(sp); + return spin_count ? spin_count : ~0; /* jic */ + } + + if (flag & HPPA_SEM_NO_SPIN) + return 0; + + spin_count++; + } +} + +void +hppa_semaphore_release(hppa_semaphore_t *sp) +{ + SEM_CHECK(sp); + + if (sp->owner_tcb != _Thread_Executing) + SEM_FATAL_ERROR("owner mismatch"); + + sp->lock = 1; +} + + +/* + * Function: hppa_semaphore_allocate + * Created: 94/11/29 + * RespEngr: tony bennett + * + * Description: + * Get a pointer to a semaphore. + * + * Parameters: + * which -- if 0, then allocate a free semaphore from the pool + * if non-zero, then return pointer to that one, even + * if it is already busy. + * + * Returns: + * successful -- pointer to semaphore + * NULL otherwise + * + * Notes: + * + * + * Deficiencies/ToDo: + * + * + */ + +hppa_semaphore_t * +hppa_semaphore_allocate(rtems_unsigned32 which, + int flag) +{ + hppa_semaphore_t *sp = 0; + + /* + * grab the control semaphore + */ + + if (hppa_semaphore_acquire(SEM_CONTROL, 0) == 0) + SEM_FATAL_ERROR("could not grab control semaphore"); + + /* + * Find a free one and init it + */ + + if (which) + { + if (which >= hppa_semaphores) + SEM_FATAL_ERROR("requested non-existent semaphore"); + sp = &hppa_semaphore_pool[which]; + + /* + * if it is "free", then mark it claimed now. + * If it is not free then we are done. + */ + + if (SEM_IS_AVAILABLE(sp)) + goto allmine; + } + else for (sp = SEM_FIRST; + sp < &hppa_semaphore_pool[hppa_semaphores]; + sp++) + { + if (SEM_IS_AVAILABLE(sp)) + { +allmine: SEM_FREE_INIT(sp); + SEM_MARK_BUSY(sp); + if ( ! (flag & HPPA_SEM_INITIALLY_FREE)) + SEM_MARK_GRABBED(sp); + break; + } + } + + /* + * Free up the control semaphore + */ + + hppa_semaphore_release(SEM_CONTROL); + + return sp; +} + -- cgit v1.2.3