From 07a908343d2cd26ee5e6b35dd70116a2c1dc16ab Mon Sep 17 00:00:00 2001 From: uwe Date: Wed, 14 Mar 2007 05:03:52 +0000 Subject: [PATCH] Convert _lock_cas to RAS. Check for restart in ast() on return from interrupt. --- sys/arch/sh3/sh3/exception.c | 14 +++++++++++--- sys/arch/sh3/sh3/lock_stubs.S | 22 ++++++++++------------ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/sys/arch/sh3/sh3/exception.c b/sys/arch/sh3/sh3/exception.c index cd8db0929188..fddb317bc83e 100644 --- a/sys/arch/sh3/sh3/exception.c +++ b/sys/arch/sh3/sh3/exception.c @@ -1,4 +1,4 @@ -/* $NetBSD: exception.c,v 1.35 2007/02/21 22:59:51 thorpej Exp $ */ +/* $NetBSD: exception.c,v 1.36 2007/03/14 05:03:52 uwe Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved. @@ -79,7 +79,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: exception.c,v 1.35 2007/02/21 22:59:51 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exception.c,v 1.36 2007/03/14 05:03:52 uwe Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" @@ -436,8 +436,16 @@ void ast(struct lwp *l, struct trapframe *tf) { - if (KERNELMODE(tf->tf_ssr)) + if (KERNELMODE(tf->tf_ssr)) { + extern char _lock_cas_ras_start[]; + extern char _lock_cas_ras_end[]; + + if ((uintptr_t)tf->tf_spc > (uintptr_t)_lock_cas_ras_start + && (uintptr_t)tf->tf_spc < (uintptr_t)_lock_cas_ras_end) + tf->tf_spc = (uintptr_t)_lock_cas_ras_start; return; + } + KDASSERT(l != NULL); KDASSERT(l->l_md.md_regs == tf); diff --git a/sys/arch/sh3/sh3/lock_stubs.S b/sys/arch/sh3/sh3/lock_stubs.S index c796d1fb959f..7a15bcaa594d 100644 --- a/sys/arch/sh3/sh3/lock_stubs.S +++ b/sys/arch/sh3/sh3/lock_stubs.S @@ -1,4 +1,4 @@ -/* $NetBSD: lock_stubs.S,v 1.5 2007/03/14 02:01:19 uwe Exp $ */ +/* $NetBSD: lock_stubs.S,v 1.6 2007/03/14 05:03:52 uwe Exp $ */ /* * Copyright (c) 2007 Valeriy E. Ushakov @@ -42,25 +42,23 @@ /* * LINTSTUB: Func: int _lock_cas(volatile uintptr_t *ptr, uintptr_t old, uintptr_t new); * - * Brute force with splhigh() for now. Need to be redone as RAS. + * Atomic compare-and-swap for kernel use. SuperH machines are + * uniprocessor, so we need to be atomic only w.r.t. interrupts. + * Implement this as (the only in-kernel) RAS, with restart check + * done in ast() on return from interrupt. */ NENTRY(_lock_cas) - mov #PSL_IMASK, r2 ! 0xf0 - gets sign extended - stc sr, r3 - extu.b r2, r2 ! undo sign extention - mov r3, r7 ! preserve SR - or r2, r3 ! mask all interrupts - ldc r3, sr - +ALTENTRY(_lock_cas_ras_start) mov.l @r4, r1 cmp/eq r1, r5 ! T = (*ptr == old) bf.s 1f movt r0 ! retval = T mov.l r6, @r4 ! *ptr = new -1: - ldc r7, sr ! restore SR (cannot be in delay slot) - rts +ALTENTRY(_lock_cas_ras_end) +1: rts nop + SET_ENTRY_SIZE(_lock_cas) + #if !defined(LOCKDEBUG)