[BACK]Return to lock_stubs.S CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / i386 / i386

Annotation of src/sys/arch/i386/i386/lock_stubs.S, Revision 1.23.2.1

1.23.2.1! uebayasi    1: /*     $NetBSD$        */
1.2       ad          2:
                      3: /*-
1.23      ad          4:  * Copyright (c) 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
1.2       ad          5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Andrew Doran.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
1.23.2.1! uebayasi   33:  * Where possible we make each routine fit into an assumed 64-byte cache
        !            34:  * line.  Please check alignment with 'objdump -d' after making changes.
1.2       ad         35:  */
                     36:
1.11      lukem      37: #include <machine/asm.h>
1.23.2.1! uebayasi   38: __KERNEL_RCSID(0, "$NetBSD$");
1.11      lukem      39:
1.2       ad         40: #include "opt_lockdebug.h"
                     41:
                     42: #include <machine/cputypes.h>
                     43:
                     44: #include "assym.h"
                     45:
                     46: #define        ALIGN64         .align  64
                     47: #define        ALIGN32         .align  32
1.12      ad         48: #define        LOCK(num)       .Lpatch/**/num: lock
1.23      ad         49: #define        RET(num)        .Lret/**/num: ret; nop; nop; ret
1.16      yamt       50: #define        ENDLABEL(name,a) .align a; LABEL(name)
1.2       ad         51:
                     52: #if !defined(LOCKDEBUG)
                     53:
                     54: /*
                     55:  * void mutex_enter(kmutex_t *mtx);
                     56:  *
                     57:  * Acquire a mutex and post a load fence.
                     58:  */
                     59:        ALIGN64
                     60:
1.7       ad         61: ENTRY(mutex_enter)
                     62:        movl    4(%esp), %edx
1.2       ad         63:        xorl    %eax, %eax
1.23      ad         64:        movl    %fs:CPU_INFO_CURLWP(%eax), %ecx
1.12      ad         65:        LOCK(1)
1.22      ad         66:        cmpxchgl %ecx, (%edx)
1.14      ad         67:        jnz     1f
1.23      ad         68:        RET(1)
1.14      ad         69: 1:
                     70:        jmp     _C_LABEL(mutex_vector_enter)
1.17      yamt       71: END(mutex_enter)
1.2       ad         72:
                     73: /*
                     74:  * void mutex_exit(kmutex_t *mtx);
                     75:  *
                     76:  * Release a mutex and post a load fence.
                     77:  *
                     78:  * See comments in mutex_vector_enter() about doing this operation unlocked
                     79:  * on multiprocessor systems, and comments in arch/x86/include/lock.h about
                     80:  * memory ordering on Intel x86 systems.
                     81:  */
1.7       ad         82: ENTRY(mutex_exit)
                     83:        movl    4(%esp), %edx
1.2       ad         84:        xorl    %ecx, %ecx
1.23      ad         85:        movl    %fs:CPU_INFO_CURLWP(%ecx), %eax
1.22      ad         86:        cmpxchgl %ecx, (%edx)
1.14      ad         87:        jnz     1f
1.2       ad         88:        ret
1.14      ad         89: 1:
                     90:        jmp     _C_LABEL(mutex_vector_exit)
1.17      yamt       91: END(mutex_exit)
1.2       ad         92:
                     93: /*
                     94:  * void rw_enter(krwlock_t *rwl, krw_t op);
                     95:  *
                     96:  * Acquire one hold on a RW lock.
                     97:  */
1.7       ad         98: ENTRY(rw_enter)
                     99:        movl    4(%esp), %edx
1.2       ad        100:        cmpl    $RW_READER, 8(%esp)
                    101:        jne     2f
                    102:
                    103:        /*
                    104:         * Reader
                    105:         */
1.22      ad        106:        movl    (%edx), %eax
                    107: 0:
1.2       ad        108:        testb   $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
1.22      ad        109:        jnz     3f
1.2       ad        110:        leal    RW_READ_INCR(%eax), %ecx
1.12      ad        111:        LOCK(2)
1.22      ad        112:        cmpxchgl %ecx, (%edx)
                    113:        jnz     1f
1.23      ad        114:        RET(2)
1.22      ad        115: 1:
                    116:        jmp     0b
1.2       ad        117:
                    118:        /*
                    119:         * Writer
                    120:         */
1.23      ad        121: 2:     xorl    %eax, %eax
                    122:        movl    %fs:CPU_INFO_CURLWP(%eax), %ecx
1.2       ad        123:        orl     $RW_WRITE_LOCKED, %ecx
1.12      ad        124:        LOCK(3)
1.22      ad        125:        cmpxchgl %ecx, (%edx)
1.14      ad        126:        jnz     3f
1.23      ad        127:        RET(3)
1.14      ad        128: 3:
                    129:        jmp     _C_LABEL(rw_vector_enter)
1.17      yamt      130: END(rw_enter)
1.2       ad        131:
                    132: /*
                    133:  * void rw_exit(krwlock_t *rwl);
                    134:  *
                    135:  * Release one hold on a RW lock.
                    136:  */
1.7       ad        137: ENTRY(rw_exit)
                    138:        movl    4(%esp), %edx
1.22      ad        139:        movl    (%edx), %eax
1.2       ad        140:        testb   $RW_WRITE_LOCKED, %al
                    141:        jnz     2f
                    142:
                    143:        /*
                    144:         * Reader
                    145:         */
1.22      ad        146: 0:     testb   $RW_HAS_WAITERS, %al
1.14      ad        147:        jnz     3f
1.2       ad        148:        cmpl    $RW_READ_INCR, %eax
1.22      ad        149:        jb      3f
1.2       ad        150:        leal    -RW_READ_INCR(%eax), %ecx
1.12      ad        151:        LOCK(4)
1.22      ad        152:        cmpxchgl %ecx, (%edx)
                    153:        jnz     1f
1.2       ad        154:        ret
1.22      ad        155: 1:
                    156:        jmp     0b
1.2       ad        157:
                    158:        /*
                    159:         * Writer
                    160:         */
                    161: 2:     leal    -RW_WRITE_LOCKED(%eax), %ecx
                    162:        subl    CPUVAR(CURLWP), %ecx
1.14      ad        163:        jnz     3f
1.12      ad        164:        LOCK(5)
1.22      ad        165:        cmpxchgl %ecx, (%edx)
1.14      ad        166:        jnz     3f
1.2       ad        167:        ret
                    168:
                    169:        /*
                    170:         * Slow path.
                    171:         */
                    172: 3:     jmp     _C_LABEL(rw_vector_exit)
1.17      yamt      173: END(rw_exit)
1.2       ad        174:
1.13      ad        175: /*
                    176:  * int rw_tryenter(krwlock_t *rwl, krw_t op);
                    177:  *
                    178:  * Try to acquire one hold on a RW lock.
                    179:  */
                    180: ENTRY(rw_tryenter)
                    181:        movl    4(%esp), %edx
                    182:        cmpl    $RW_READER, 8(%esp)
                    183:        jne     2f
                    184:
                    185:        /*
                    186:         * Reader
                    187:         */
1.22      ad        188:        movl    (%edx), %eax
                    189: 0:
1.13      ad        190:        testb   $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
1.23      ad        191:        jnz     4f
1.22      ad        192:        leal    RW_READ_INCR(%eax), %ecx
1.13      ad        193:        LOCK(12)
1.22      ad        194:        cmpxchgl %ecx, (%edx)
                    195:        jnz     1f
1.18      ad        196:        movl    %edx, %eax                      /* nonzero */
1.23      ad        197:        RET(4)
1.22      ad        198: 1:
                    199:        jmp     0b
1.13      ad        200:
                    201:        /*
                    202:         * Writer
                    203:         */
1.18      ad        204: 2:
1.23      ad        205:        xorl    %eax, %eax
                    206:        movl    %fs:CPU_INFO_CURLWP(%eax), %ecx
1.18      ad        207:        orl     $RW_WRITE_LOCKED, %ecx
1.13      ad        208:        LOCK(13)
1.22      ad        209:        cmpxchgl %ecx, (%edx)
1.19      ad        210:        movl    $0, %eax
1.13      ad        211:        setz    %al
1.18      ad        212: 3:
1.23      ad        213:        RET(5)
                    214: 4:
1.18      ad        215:        xorl    %eax, %eax
1.23      ad        216:        jmp     3b
1.17      yamt      217: END(rw_tryenter)
1.13      ad        218:
1.2       ad        219: #ifndef __XEN__
                    220:
                    221: /*
                    222:  * void mutex_spin_enter(kmutex_t *mtx);
                    223:  *
                    224:  * Acquire a spin mutex and post a load fence.
                    225:  */
1.7       ad        226: ENTRY(mutex_spin_enter)
                    227:        movl    4(%esp), %edx
1.14      ad        228:        movb    CPUVAR(ILEVEL), %cl
                    229:        movb    MTX_IPL(%edx), %ch
1.21      ad        230:        movl    $0x01, %eax
1.2       ad        231:        cmpb    %ch, %cl
1.14      ad        232:        jg      1f
1.7       ad        233:        movb    %ch, CPUVAR(ILEVEL)             /* splraiseipl() */
1.14      ad        234: 1:
1.21      ad        235:        subl    %eax, CPUVAR(MTX_COUNT)         /* decl does not set CF */
1.14      ad        236:        jnc     2f
                    237:        movb    %cl, CPUVAR(MTX_OLDSPL)
1.2       ad        238: 2:
1.21      ad        239:        xchgb   %al, MTX_LOCK(%edx)             /* lock it */
                    240:        testb   %al, %al
1.14      ad        241:        jnz     3f
1.23      ad        242:        RET(6)
1.14      ad        243: 3:
                    244:        jmp     _C_LABEL(mutex_spin_retry)
1.2       ad        245:
                    246:        ALIGN64
                    247: LABEL(mutex_spin_enter_end)
1.17      yamt      248: END(mutex_spin_enter)
1.2       ad        249:
                    250: /*
                    251:  * Release a spin mutex and post a store fence.
                    252:  */
1.7       ad        253: ENTRY(mutex_spin_exit)
                    254:        movl    4(%esp), %edx
                    255:        movl    CPUVAR(MTX_OLDSPL), %ecx
                    256:        incl    CPUVAR(MTX_COUNT)
                    257:        movb    $0, MTX_LOCK(%edx)              /* zero */
1.2       ad        258:        jnz     1f
1.7       ad        259:        movl    %fs:CPU_INFO_IUNMASK(,%ecx,4), %edx
                    260:        cli
                    261:        testl   CPUVAR(IPENDING), %edx
1.2       ad        262:        movl    %ecx, 4(%esp)
                    263:        jnz     _C_LABEL(Xspllower)             /* does sti */
1.7       ad        264:        movl    %ecx, CPUVAR(ILEVEL)
1.2       ad        265:        sti
                    266: 1:     ret
1.4       ad        267:        nop                                     /* XXX round up */
                    268:        .align  32
1.2       ad        269: LABEL(mutex_spin_exit_end)
1.17      yamt      270: END(mutex_spin_exit)
1.2       ad        271:
                    272: /*
1.20      chs       273:  * Patch for i686 CPUs where cli/sti is prohibitively expensive.
1.2       ad        274:  * Must be the same size as mutex_spin_exit().
                    275:  */
1.4       ad        276: ENTRY(i686_mutex_spin_exit)
1.2       ad        277:        mov     4(%esp),%edx
1.7       ad        278:        movl    CPUVAR(MTX_OLDSPL), %ecx
                    279:        incl    CPUVAR(MTX_COUNT)
                    280:        movb    %ch, MTX_LOCK(%edx)             /* zero */
                    281:        jnz     1f
1.2       ad        282:        pushl   %ebx
1.3       yamt      283: 0:
1.7       ad        284:        movl    CPUVAR(IPENDING), %eax
                    285:        testl   %eax, %fs:CPU_INFO_IUNMASK(,%ecx,4)
1.22      ad        286:        jnz     2f
1.2       ad        287:        movl    %eax, %ebx
1.7       ad        288:        cmpxchg8b CPUVAR(ISTATE)                /* swap in new ilevel */
                    289:        jnz     0b
                    290:        popl    %ebx
1.2       ad        291: 1:
                    292:        ret
                    293: 2:
                    294:        popl    %ebx
                    295:        movl    %ecx,4(%esp)
                    296: LABEL(i686_mutex_spin_exit_patch)
                    297:        jmp     _C_LABEL(Xspllower)
1.4       ad        298:        .align  32
1.2       ad        299: LABEL(i686_mutex_spin_exit_end)
1.17      yamt      300: END(i686_mutex_spin_exit)
1.2       ad        301:
                    302: #else  /* !__XEN__ */
                    303:
                    304: /* For now; strong alias not working for some reason. */
1.5       ad        305: ENTRY(mutex_spin_enter)
1.2       ad        306:        jmp     _C_LABEL(mutex_vector_enter)
                    307:
1.5       ad        308: ENTRY(mutex_spin_exit)
1.2       ad        309:        jmp     _C_LABEL(mutex_vector_exit)
                    310:
                    311: #endif /* !__XEN__ */
                    312:
                    313: #endif /* !LOCKDEBUG */
                    314:
                    315: /*
1.12      ad        316:  * Spinlocks.
1.2       ad        317:  */
1.20      chs       318: ENTRY(__cpu_simple_lock_init)
1.12      ad        319:        movl    4(%esp), %edx
                    320:        movb    $0, (%edx)
1.2       ad        321:        ret
1.17      yamt      322: END(__cpu_simple_lock_init)
1.14      ad        323:
1.12      ad        324: NENTRY(__cpu_simple_lock)
                    325:        movl    4(%esp), %edx
                    326:        movl    $0x0100, %eax
                    327: 1:
                    328:        LOCK(6)
                    329:        cmpxchgb %ah, (%edx)
                    330:        jnz     2f
1.23      ad        331:        RET(7)
1.12      ad        332: 2:
                    333:        movl    $0x0100, %eax
                    334:        pause
                    335:        nop
1.7       ad        336:        nop
1.12      ad        337:        cmpb    $0, (%edx)
                    338:        je      1b
                    339:        jmp     2b
1.17      yamt      340: END(__cpu_simple_lock)
1.2       ad        341:
1.20      chs       342: ENTRY(__cpu_simple_unlock)
1.12      ad        343:        movl    4(%esp), %edx
                    344:        movb    $0, (%edx)
1.2       ad        345:        ret
1.17      yamt      346: END(__cpu_simple_unlock)
1.2       ad        347:
1.20      chs       348: ENTRY(__cpu_simple_lock_try)
1.12      ad        349:        movl    4(%esp), %edx
                    350:        movl    $0x0100, %eax
                    351:        LOCK(7)
                    352:        cmpxchgb %ah, (%edx)
                    353:        movl    $0, %eax
                    354:        setz    %al
1.23      ad        355:        RET(8)
1.17      yamt      356: END(__cpu_simple_lock_try)
1.2       ad        357:
                    358: /*
1.7       ad        359:  * Patchpoints to replace with NOP when ncpu == 1.
                    360:  */
1.12      ad        361:        .data
                    362:
1.7       ad        363: #ifndef LOCKDEBUG
                    364: LABEL(x86_lockpatch)
1.12      ad        365:        .long   .Lpatch1, .Lpatch2, .Lpatch3, .Lpatch4
1.13      ad        366:        .long   .Lpatch5, .Lpatch6, .Lpatch7, .Lpatch12
                    367:        .long   .Lpatch13
1.7       ad        368:        .long   0
                    369: #endif
1.23      ad        370:
                    371: LABEL(x86_retpatch)
                    372: #ifndef LOCKDEBUG
                    373:        .long   .Lret1, .Lret2, .Lret3, .Lret4, .Lret5
                    374: #ifndef __XEN__
                    375:        .long   .Lret6
                    376: #endif
                    377: #endif
                    378:        .long   .Lret7, .Lret8
                    379:        .long   0

CVSweb <webmaster@jp.NetBSD.org>