1 /* $OpenBSD: mutex.S,v 1.4 2007/05/27 18:34:01 art Exp $ */
2
3 /*
4 * Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "assym.h"
29 /*
30 * Yeah, we don't really need to implement mtx_init here, but let's keep
31 * all the functions in the same place.
32 */
33 ENTRY(mtx_init)
34 pushl %ebp
35 movl %esp, %ebp
36 movl 8(%esp), %eax
37 movl 12(%esp), %edx
38 movl %edx, MTX_WANTIPL(%eax)
39 xorl %edx, %edx
40 movl %edx, MTX_OLDIPL(%eax)
41 movl %edx, MTX_LOCK(%eax)
42 movl %edx, MTX_OWNER(%eax)
43 leave
44 ret
45
46 #define SOFF 8
47
48 ENTRY(mtx_enter)
49 pushl %ebp
50 movl %esp, %ebp
51 1: movl SOFF(%ebp), %ecx
52 movl MTX_WANTIPL(%ecx), %eax
53 movl CPL, %edx # oipl = cpl;
54 cmpl %edx, %eax # if (cpl < mtx->mtx_wantipl)
55 jle 2f
56 movl %eax, CPL # cpl = mtx->mtx_wantipl;
57 2: /*
58 * %edx now contains the oldipl.
59 * %ecx contains the mtx.
60 */
61 movl $1, %eax
62 xchgl %eax, MTX_LOCK(%ecx) # test_and_set(mtx->mtx_lock)
63 testl %eax, %eax # if (already held)
64 jnz 3f
65 movl CPUVAR(SELF), %eax
66 movl %eax, MTX_OWNER(%ecx)
67 movl %edx, MTX_OLDIPL(%ecx)
68 leave
69 ret
70
71 /* We failed to obtain the lock. splx, spin and retry. */
72 3: pushl %edx
73 call _C_LABEL(splx)
74 movl %ebp, %esp
75 movl SOFF(%ebp), %ecx # %ecx clobbered
76 4:
77 #ifdef DIAGNOSTIC
78 movl CPUVAR(SELF), %edx
79 cmpl MTX_OWNER(%ecx), %edx
80 je 5f
81 #endif
82 movl MTX_LOCK(%ecx), %eax
83 testl %eax, %eax
84 jz 1b
85 jmp 4b
86 #ifdef DIAGNOSTIC
87 5: pushl $6f
88 call _C_LABEL(panic)
89 6: .asciz "mtx_enter: locking against myself"
90 #endif
91
92 ENTRY(mtx_leave)
93 pushl %ebp
94 movl %esp, %ebp
95 movl SOFF(%ebp), %ecx
96 xorl %eax, %eax
97 movl %eax, MTX_OWNER(%ecx)
98 pushl MTX_OLDIPL(%ecx)
99 movl %eax, MTX_OLDIPL(%ecx)
100 movl %eax, MTX_LOCK(%ecx)
101 call _C_LABEL(splx)
102 leave
103 ret