Annotation of XNU/osfmk/i386/i386_lock.s, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1989 Carnegie-Mellon University
                     28:  * All rights reserved.  The CMU software License Agreement specifies
                     29:  * the terms and conditions for use and redistribution.
                     30:  */
                     31: 
                     32: #include <cpus.h>
                     33: #include <mach_rt.h>
                     34: #include <platforms.h>
                     35: #include <mach_ldebug.h>
                     36: #include <i386/asm.h>
                     37: #include <assym.s>
                     38: #include <kern/etap_options.h>
                     39: 
                     40: 
                     41: /*
                     42:  *     When performance isn't the only concern, it's
                     43:  *     nice to build stack frames...
                     44:  */
                     45: #define        BUILD_STACK_FRAMES   ((MACH_LDEBUG || ETAP_LOCK_TRACE) && MACH_KDB)
                     46: 
                     47: #if    BUILD_STACK_FRAMES
                     48: 
                     49: #define        L_PC            4(%ebp)
                     50: #define        L_ARG0          8(%ebp)
                     51: #define        L_ARG1          12(%ebp)
                     52: 
                     53: #define SWT_HI          -4(%ebp)
                     54: #define SWT_LO          -8(%ebp)
                     55: #define MISSED          -12(%ebp)
                     56: 
                     57: #else   /* BUILD_STACK_FRAMES */
                     58: 
                     59: #undef FRAME
                     60: #undef EMARF
                     61: #define        FRAME
                     62: #define        EMARF
                     63: #define        L_PC            (%esp)
                     64: #define        L_ARG0          4(%esp)
                     65: #define        L_ARG1          8(%esp)
                     66: 
                     67: #endif   /* BUILD_STACK_FRAMES */
                     68: 
                     69: 
                     70: #define        M_ILK           (%edx)
                     71: #define        M_LOCKED        1(%edx)
                     72: #define        M_WAITERS       2(%edx)
                     73: #if    MACH_LDEBUG
                     74: #define        M_TYPE          4(%edx)
                     75: #define        M_PC            8(%edx)
                     76: #define        M_THREAD        12(%edx)
                     77: #endif /* MACH_LDEBUG */
                     78: 
                     79: #include <i386/AT386/mp/mp.h>
                     80: #if    (NCPUS > 1)
                     81: #define        CX(addr,reg)    addr(,reg,4)
                     82: #else
                     83: #define        CPU_NUMBER(reg)
                     84: #define        CX(addr,reg)    addr
                     85: #endif /* (NCPUS > 1) */
                     86: 
                     87: #if    MACH_LDEBUG
                     88: /*
                     89:  *  Routines for general lock debugging.
                     90:  */
                     91: #define        S_TYPE          4(%edx)
                     92: #define        S_PC            8(%edx)
                     93: #define        S_THREAD        12(%edx)
                     94: #define        S_DURATIONH     16(%edx)
                     95: #define        S_DURATIONL     20(%edx)
                     96: 
                     97: /* 
                     98:  * Checks for expected lock types and calls "panic" on
                     99:  * mismatch.  Detects calls to Mutex functions with
                    100:  * type simplelock and vice versa.
                    101:  */
                    102: #define        CHECK_MUTEX_TYPE()                                      \
                    103:        cmpl    $MUTEX_TAG, M_TYPE                      ;       \
                    104:        je      1f                                      ;       \
                    105:        pushl   $2f                                     ;       \
                    106:        call    EXT(panic)                              ;       \
                    107:        hlt                                             ;       \
                    108:        .data                                           ;       \
                    109: 2:     String  "not a mutex!"                          ;       \
                    110:        .text                                           ;       \
                    111: 1:
                    112: 
                    113: #define        CHECK_SIMPLE_LOCK_TYPE()                                \
                    114:        cmpl    $SIMPLE_LOCK_TAG,S_TYPE                 ;       \
                    115:        je      1f                                      ;       \
                    116:        pushl   $2f                                     ;       \
                    117:        call    EXT(panic)                              ;       \
                    118:        hlt                                             ;       \
                    119:        .data                                           ;       \
                    120: 2:     String  "not a simple lock!"                    ;       \
                    121:        .text                                           ;       \
                    122: 1:
                    123: 
                    124: /*
                    125:  * If one or more simplelocks are currently held by a thread,
                    126:  * an attempt to acquire a mutex will cause this check to fail
                    127:  * (since a mutex lock may context switch, holding a simplelock
                    128:  * is not a good thing).
                    129:  */
                    130: #if    0 /*MACH_RT - 11/12/99 - [email protected] disable check for now*/
                    131: #define CHECK_PREEMPTION_LEVEL()                               \
                    132:        movl    $CPD_PREEMPTION_LEVEL,%eax              ;       \
                    133:        cmpl    $0,%gs:(%eax)                           ;       \
                    134:        je      1f                                      ;       \
                    135:        pushl   $2f                                     ;       \
                    136:        call    EXT(panic)                              ;       \
                    137:        hlt                                             ;       \
                    138:        .data                                           ;       \
                    139: 2:     String  "preemption_level != 0!"                ;       \
                    140:        .text                                           ;       \
                    141: 1:
                    142: #else  /* MACH_RT */
                    143: #define        CHECK_PREEMPTION_LEVEL()
                    144: #endif /* MACH_RT */
                    145: 
                    146: #define        CHECK_NO_SIMPLELOCKS()                                  \
                    147:        movl    $CPD_SIMPLE_LOCK_COUNT,%eax             ;       \
                    148:        cmpl    $0,%gs:(%eax)                           ;       \
                    149:        je      1f                                      ;       \
                    150:        pushl   $2f                                     ;       \
                    151:        call    EXT(panic)                              ;       \
                    152:        hlt                                             ;       \
                    153:        .data                                           ;       \
                    154: 2:     String  "simple_locks_held!"                    ;       \
                    155:        .text                                           ;       \
                    156: 1:
                    157: 
                    158: /* 
                    159:  * Verifies return to the correct thread in "unlock" situations.
                    160:  */
                    161: #define        CHECK_THREAD(thd)                                       \
                    162:        movl    $CPD_ACTIVE_THREAD,%eax                 ;       \
                    163:        movl    %gs:(%eax),%ecx                         ;       \
                    164:        testl   %ecx,%ecx                               ;       \
                    165:        je      1f                                      ;       \
                    166:        cmpl    %ecx,thd                                ;       \
                    167:        je      1f                                      ;       \
                    168:        pushl   $2f                                     ;       \
                    169:        call    EXT(panic)                              ;       \
                    170:        hlt                                             ;       \
                    171:        .data                                           ;       \
                    172: 2:     String  "wrong thread!"                         ;       \
                    173:        .text                                           ;       \
                    174: 1:
                    175: 
                    176: #define        CHECK_MYLOCK(thd)                                       \
                    177:        movl    $CPD_ACTIVE_THREAD,%eax                 ;       \
                    178:        movl    %gs:(%eax),%ecx                         ;       \
                    179:        testl   %ecx,%ecx                               ;       \
                    180:        je      1f                                      ;       \
                    181:        cmpl    %ecx,thd                                ;       \
                    182:        jne     1f                                      ;       \
                    183:        pushl   $2f                                     ;       \
                    184:        call    EXT(panic)                              ;       \
                    185:        hlt                                             ;       \
                    186:        .data                                           ;       \
                    187: 2:     String  "mylock attempt!"                       ;       \
                    188:        .text                                           ;       \
                    189: 1:
                    190: 
                    191: #define        METER_SIMPLE_LOCK_LOCK(reg)                             \
                    192:        pushl   reg                                     ;       \
                    193:        call    EXT(meter_simple_lock)                  ;       \
                    194:        popl    reg
                    195: 
                    196: #define        METER_SIMPLE_LOCK_UNLOCK(reg)                           \
                    197:        pushl   reg                                     ;       \
                    198:        call    EXT(meter_simple_unlock)                ;       \
                    199:        popl    reg
                    200: 
                    201: #else  /* MACH_LDEBUG */
                    202: #define        CHECK_MUTEX_TYPE()
                    203: #define        CHECK_SIMPLE_LOCK_TYPE
                    204: #define        CHECK_THREAD(thd)
                    205: #define CHECK_PREEMPTION_LEVEL()
                    206: #define        CHECK_NO_SIMPLELOCKS()
                    207: #define        CHECK_MYLOCK(thd)
                    208: #define        METER_SIMPLE_LOCK_LOCK(reg)
                    209: #define        METER_SIMPLE_LOCK_UNLOCK(reg)
                    210: #endif /* MACH_LDEBUG */
                    211: 
                    212: 
                    213: /*
                    214:  *     void hw_lock_init(hw_lock_t)
                    215:  *
                    216:  *     Initialize a hardware lock.
                    217:  */
                    218: ENTRY(hw_lock_init)
                    219:        FRAME
                    220:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    221:        xorl    %eax,%eax
                    222:        movb    %al,0(%edx)             /* clear the lock */
                    223:        EMARF
                    224:        ret
                    225: 
                    226: /*
                    227:  *     void hw_lock_lock(hw_lock_t)
                    228:  *
                    229:  *     Acquire lock, spinning until it becomes available.
                    230:  *     MACH_RT:  also return with preemption disabled.
                    231:  */
                    232: ENTRY(hw_lock_lock)
                    233:        FRAME
                    234:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    235: 
                    236: 1:     DISABLE_PREEMPTION(%eax)
                    237:        movb    $1,%cl
                    238:        xchgb   0(%edx),%cl             /* try to acquire the HW lock */
                    239:        testb   %cl,%cl                 /* success? */
                    240:        jne     3f
                    241: 
                    242:        EMARF                           /* if yes, then nothing left to do */
                    243:        ret
                    244: 
                    245: 3:     ENABLE_PREEMPTION(%eax)         /* no reason we can't be preemptable now */
                    246: 
                    247:        movb    $1,%cl
                    248: 2:     testb   %cl,0(%edx)             /* spin checking lock value in cache */
                    249:        jne     2b                      /* non-zero means locked, keep spinning */
                    250:        jmp     1b                      /* zero means unlocked, try to grab it */
                    251: 
                    252: /*
                    253:  *     void hw_lock_unlock(hw_lock_t)
                    254:  *
                    255:  *     Unconditionally release lock.
                    256:  *     MACH_RT:  release preemption level.
                    257:  */
                    258: ENTRY(hw_lock_unlock)
                    259:        FRAME
                    260:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    261:        xorl    %eax,%eax
                    262:        xchgb   0(%edx),%al             /* clear the lock... a mov instruction */
                    263:                                        /* ...might be cheaper and less paranoid */
                    264:        ENABLE_PREEMPTION(%eax)
                    265:        EMARF
                    266:        ret
                    267: 
                    268: /*
                    269:  *     unsigned int hw_lock_try(hw_lock_t)
                    270:  *     MACH_RT:  returns with preemption disabled on success.
                    271:  */
                    272: ENTRY(hw_lock_try)
                    273:        FRAME
                    274:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    275: 
                    276:        DISABLE_PREEMPTION(%eax)
                    277:        movb    $1,%cl
                    278:        xchgb   0(%edx),%cl             /* try to acquire the HW lock */
                    279:        testb   %cl,%cl                 /* success? */
                    280:        jne     1f                      /* if yes, let the caller know */
                    281: 
                    282:        movl    $1,%eax                 /* success */
                    283:        EMARF
                    284:        ret
                    285: 
                    286: 1:     ENABLE_PREEMPTION(%eax)         /* failure:  release preemption... */
                    287:        xorl    %eax,%eax               /* ...and return failure */
                    288:        EMARF
                    289:        ret     
                    290: 
                    291: /*
                    292:  *     unsigned int hw_lock_held(hw_lock_t)
                    293:  *     MACH_RT:  doesn't change preemption state.
                    294:  *     N.B.  Racy, of course.
                    295:  */
                    296: ENTRY(hw_lock_held)
                    297:        FRAME
                    298:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    299: 
                    300:        movb    $1,%cl
                    301:        testb   %cl,0(%edx)             /* check lock value */
                    302:        jne     1f                      /* non-zero means locked */
                    303:        xorl    %eax,%eax               /* tell caller:  lock wasn't locked */
                    304:        EMARF
                    305:        ret     
                    306: 
                    307: 1:     movl    $1,%eax                 /* tell caller:  lock was locked */
                    308:        EMARF
                    309:        ret
                    310:        
                    311: 
                    312: 
                    313: #if    0
                    314: 
                    315: 
                    316: ENTRY(_usimple_lock_init)
                    317:        FRAME
                    318:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    319:        xorl    %eax,%eax
                    320:        movb    %al,USL_INTERLOCK(%edx) /* unlock the HW lock */
                    321:        EMARF
                    322:        ret
                    323: 
                    324: ENTRY(_simple_lock)
                    325:        FRAME
                    326:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    327: 
                    328:        CHECK_SIMPLE_LOCK_TYPE()
                    329: 
                    330:        DISABLE_PREEMPTION(%eax)
                    331: 
                    332: sl_get_hw:
                    333:        movb    $1,%cl
                    334:        xchgb   USL_INTERLOCK(%edx),%cl /* try to acquire the HW lock */
                    335:        testb   %cl,%cl                 /* did we succeed? */
                    336: 
                    337: #if    MACH_LDEBUG
                    338:        je      5f
                    339:        CHECK_MYLOCK(S_THREAD)
                    340:        jmp     sl_get_hw
                    341: 5:
                    342: #else  /* MACH_LDEBUG */
                    343:        jne     sl_get_hw               /* no, try again */
                    344: #endif /* MACH_LDEBUG */
                    345: 
                    346: #if    MACH_LDEBUG
                    347:        movl    L_PC,%ecx
                    348:        movl    %ecx,S_PC
                    349:        movl    $CPD_ACTIVE_THREAD,%eax
                    350:        movl    %gs:(%eax),%ecx
                    351:        movl    %ecx,S_THREAD
                    352:        incl    CX(EXT(simple_lock_count),%eax)
                    353: #if 0
                    354:        METER_SIMPLE_LOCK_LOCK(%edx)
                    355: #endif
                    356: #if    NCPUS == 1
                    357:        pushf
                    358:        pushl   %edx
                    359:        cli
                    360:        call    EXT(lock_stack_push)
                    361:        popl    %edx
                    362:        popfl
                    363: #endif /* NCPUS == 1 */
                    364: #endif /* MACH_LDEBUG */
                    365: 
                    366:        EMARF
                    367:        ret
                    368: 
                    369: ENTRY(_simple_lock_try)
                    370:        FRAME
                    371:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    372: 
                    373:        CHECK_SIMPLE_LOCK_TYPE()
                    374: 
                    375:        DISABLE_PREEMPTION(%eax)
                    376: 
                    377:        movb    $1,%cl
                    378:        xchgb   USL_INTERLOCK(%edx),%cl /* try to acquire the HW lock */
                    379:        testb   %cl,%cl                 /* did we succeed? */
                    380:        jne     1f                      /* no, return failure */
                    381: 
                    382: #if    MACH_LDEBUG
                    383:        movl    L_PC,%ecx
                    384:        movl    %ecx,S_PC
                    385:        movl    $CPD_ACTIVE_THREAD,%eax
                    386:        movl    %gs:(%eax),%ecx
                    387:        movl    %ecx,S_THREAD
                    388:        incl    CX(EXT(simple_lock_count),%eax)
                    389: #if 0
                    390:        METER_SIMPLE_LOCK_LOCK(%edx)
                    391: #endif
                    392: #if    NCPUS == 1
                    393:        pushf
                    394:        pushl   %edx
                    395:        cli
                    396:        call    EXT(lock_stack_push)
                    397:        popl    %edx
                    398:        popfl
                    399: #endif /* NCPUS == 1 */
                    400: #endif /* MACH_LDEBUG */
                    401: 
                    402:        movl    $1,%eax                 /* return success */
                    403: 
                    404:        EMARF
                    405:        ret
                    406: 
                    407: 1:
                    408:        ENABLE_PREEMPTION(%eax)
                    409: 
                    410:        xorl    %eax,%eax               /* and return failure */
                    411: 
                    412:        EMARF
                    413:        ret
                    414: 
                    415: ENTRY(_simple_unlock)
                    416:        FRAME
                    417:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    418: 
                    419:        CHECK_SIMPLE_LOCK_TYPE()
                    420:        CHECK_THREAD(S_THREAD)
                    421: 
                    422: #if    MACH_LDEBUG
                    423:        xorl    %eax,%eax
                    424:        movl    %eax,S_THREAD           /* disown thread */
                    425:        MP_DISABLE_PREEMPTION(%eax)
                    426:        CPU_NUMBER(%eax)
                    427:        decl    CX(EXT(simple_lock_count),%eax)
                    428:        MP_ENABLE_PREEMPTION(%eax)
                    429: #if 0
                    430:        METER_SIMPLE_LOCK_UNLOCK(%edx)
                    431: #endif
                    432: #if    NCPUS == 1
                    433:        pushf
                    434:        pushl   %edx
                    435:        cli
                    436:        call    EXT(lock_stack_pop)
                    437:        popl    %edx
                    438:        popfl
                    439: #endif /* NCPUS == 1 */
                    440: #endif /* MACH_LDEBUG */
                    441: 
                    442:        xorb    %cl,%cl
                    443:        xchgb   USL_INTERLOCK(%edx),%cl /* unlock the HW lock */
                    444: 
                    445:        ENABLE_PREEMPTION(%eax)
                    446: 
                    447:        EMARF
                    448:        ret
                    449: 
                    450: #endif /* 0 */
                    451: 
                    452: 
                    453: ENTRY(mutex_init)
                    454:        FRAME
                    455:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    456:        xorl    %eax,%eax
                    457:        movb    %al,M_ILK               /* clear interlock */
                    458:        movb    %al,M_LOCKED            /* clear locked flag */
                    459:        movw    %ax,M_WAITERS           /* init waiter count */
                    460: 
                    461: #if    MACH_LDEBUG
                    462:        movl    $MUTEX_TAG,M_TYPE       /* set lock type */
                    463:        movl    %eax,M_PC               /* init caller pc */
                    464:        movl    %eax,M_THREAD           /* and owning thread */
                    465: #endif
                    466: #if    ETAP_LOCK_TRACE
                    467:        movl    L_ARG1,%ecx             /* fetch event type */
                    468:        pushl   %ecx                    /* push event type */
                    469:        pushl   %edx                    /* push mutex address */
                    470:        call    EXT(etap_mutex_init)    /* init ETAP data */
                    471:        addl    $8,%esp
                    472: #endif /* ETAP_LOCK_TRACE */
                    473: 
                    474:        EMARF
                    475:        ret
                    476: 
                    477: ENTRY(_mutex_lock)
                    478:        FRAME
                    479: 
                    480: #if    ETAP_LOCK_TRACE
                    481:        subl    $12,%esp                /* make room for locals */
                    482:        movl    $0,SWT_HI               /* set wait time to zero (HI) */
                    483:        movl    $0,SWT_LO               /* set wait time to zero (LO) */
                    484:        movl    $0,MISSED               /* clear local miss marker */
                    485: #endif /* ETAP_LOCK_TRACE */
                    486: 
                    487:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    488: 
                    489:        CHECK_MUTEX_TYPE()
                    490:        CHECK_NO_SIMPLELOCKS()
                    491:        CHECK_PREEMPTION_LEVEL()
                    492: 
                    493: ml_retry:
                    494:        DISABLE_PREEMPTION(%eax)
                    495: 
                    496: ml_get_hw:
                    497:        movb    $1,%cl
                    498:        xchgb   %cl,M_ILK
                    499:        testb   %cl,%cl                 /* did we succeed? */
                    500:        jne     ml_get_hw               /* no, try again */
                    501: 
                    502: /*
                    503: / Beware of a race between this code path and the inline ASM fast-path locking
                    504: / sequence which attempts to lock a mutex by directly setting the locked flag 
                    505: / 
                    506: */
                    507: 
                    508:        movb    $1,%cl
                    509:        xchgb   %cl,M_LOCKED            /* try to set locked flag */
                    510:        testb   %cl,%cl                 /* is the mutex locked? */
                    511:        jne     ml_fail                 /* yes, we lose */
                    512: 
                    513: #if    MACH_LDEBUG
                    514:        movl    L_PC,%ecx
                    515:        movl    %ecx,M_PC
                    516:        movl    $CPD_ACTIVE_THREAD,%eax
                    517:        movl    %gs:(%eax),%ecx
                    518:        movl    %ecx,M_THREAD
                    519:        testl   %ecx,%ecx
                    520:        je      3f
                    521:        incl    TH_MUTEX_COUNT(%ecx)
                    522: 3:
                    523: #endif
                    524: 
                    525:        xorb    %cl,%cl
                    526:        xchgb   %cl,M_ILK
                    527: 
                    528:        ENABLE_PREEMPTION(%eax)
                    529: 
                    530: #if    ETAP_LOCK_TRACE
                    531:        movl    L_PC,%eax               /* fetch pc */
                    532:        pushl   SWT_LO                  /* push wait time (low) */
                    533:        pushl   SWT_HI                  /* push wait time (high) */
                    534:        pushl   %eax                    /* push pc */
                    535:        pushl   %edx                    /* push mutex address */
                    536:        call    EXT(etap_mutex_hold)    /* collect hold timestamp */
                    537:        addl    $16+12,%esp             /* clean up stack, adjusting for locals */
                    538: #endif /* ETAP_LOCK_TRACE */
                    539: 
                    540:        EMARF
                    541:        ret
                    542: 
                    543: ml_fail:
                    544: #if    ETAP_LOCK_TRACE
                    545:        cmp     $0,MISSED               /* did we already take a wait timestamp? */
                    546:        jne     ml_block                /* yup. carry-on */
                    547:        pushl   %edx                    /* push mutex address */
                    548:        call    EXT(etap_mutex_miss)    /* get wait timestamp */
                    549:        movl    %eax,SWT_HI             /* set wait time (high word) */
                    550:        movl    %edx,SWT_LO             /* set wait time (low word) */
                    551:        popl    %edx                    /* clean up stack */
                    552:        movl    $1,MISSED               /* mark wait timestamp as taken */
                    553: #endif /* ETAP_LOCK_TRACE */
                    554: 
                    555: ml_block:
                    556:        CHECK_MYLOCK(M_THREAD)
                    557:        pushl   %edx                    /* push mutex address */
                    558:        call    EXT(mutex_lock_wait)    /* wait for the lock */
                    559:        addl    $4,%esp
                    560:        movl    L_ARG0,%edx             /* refetch lock pointer */
                    561:        jmp     ml_retry                /* and try again */
                    562: 
                    563: ENTRY(_mutex_try)
                    564:        FRAME
                    565: 
                    566: #if    ETAP_LOCK_TRACE
                    567:        subl    $8,%esp                 /* make room for locals */
                    568:        movl    $0,SWT_HI               /* set wait time to zero (HI) */
                    569:        movl    $0,SWT_LO               /* set wait time to zero (LO) */
                    570: #endif /* ETAP_LOCK_TRACE */
                    571: 
                    572:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    573: 
                    574:        CHECK_MUTEX_TYPE()
                    575:        CHECK_NO_SIMPLELOCKS()
                    576: 
                    577:        xorl    %eax,%eax
                    578:        movb    $1,%al                  /* locked value for mutex */
                    579:        xchgb   %al,M_LOCKED            /* swap locked values */
                    580:        xorb    $1,%al                  /* generate return value */
                    581: 
                    582: #if    MACH_LDEBUG || ETAP_LOCK_TRACE
                    583:        testl   %eax,%eax               /* did we succeed? */
                    584:        je      2f                      /* no, skip */
                    585: #endif
                    586: 
                    587: #if    MACH_LDEBUG
                    588:        movl    L_PC,%ecx
                    589:        movl    %ecx,M_PC
                    590:        movl    $CPD_ACTIVE_THREAD,%ecx
                    591:        movl    %gs:(%ecx),%ecx
                    592:        movl    %ecx,M_THREAD
                    593:        testl   %ecx,%ecx
                    594:        je      1f
                    595:        incl    TH_MUTEX_COUNT(%ecx)
                    596: 1:
                    597: #endif
                    598: 
                    599: #if    ETAP_LOCK_TRACE
                    600:        movl    L_PC,%eax               /* fetch pc */
                    601:        pushl   SWT_LO                  /* push wait time (low) */
                    602:        pushl   SWT_HI                  /* push wait time (high) */
                    603:        pushl   %eax                    /* push pc */
                    604:        pushl   %edx                    /* push mutex address */
                    605:        call    EXT(etap_mutex_hold)    /* get start hold timestamp */
                    606:        addl    $16,%esp                /* clean up stack, adjusting for locals */
                    607:        movl    $1,%eax                 /* put back successful return value */
                    608: #endif /* ETAP_LOCK_TRACE */
                    609: 
                    610: #if    MACH_LDEBUG || ETAP_LOCK_TRACE
                    611: 2:
                    612: #if    ETAP_LOCK_TRACE
                    613:        addl    $8,%esp                 /* pop stack claimed on entry */
                    614: #endif
                    615: #endif
                    616: 
                    617:        EMARF
                    618:        ret
                    619: 
                    620: ENTRY(mutex_unlock)
                    621:        FRAME
                    622:        movl    L_ARG0,%edx             /* fetch lock pointer */
                    623: 
                    624: #if    ETAP_LOCK_TRACE
                    625:        pushl   %edx                    /* push mutex address */
                    626:        call    EXT(etap_mutex_unlock)  /* collect ETAP data */
                    627:        popl    %edx                    /* restore mutex address */
                    628: #endif /* ETAP_LOCK_TRACE */
                    629: 
                    630:        CHECK_MUTEX_TYPE()
                    631:        CHECK_THREAD(M_THREAD)
                    632: 
                    633:        DISABLE_PREEMPTION(%eax)
                    634: 
                    635: mu_get_hw:
                    636:        movb    $1,%cl
                    637:        xchgb   %cl,M_ILK
                    638:        testb   %cl,%cl                 /* did we succeed? */
                    639:        jne     mu_get_hw               /* no, try again */
                    640: 
                    641:        cmpw    $0,M_WAITERS            /* are there any waiters? */
                    642:        jne     mu_wakeup               /* yes, more work to do */
                    643: 
                    644: mu_doit:
                    645: #if    MACH_LDEBUG
                    646:        xorl    %eax,%eax
                    647:        movl    %eax,M_THREAD           /* disown thread */
                    648:        movl    $CPD_ACTIVE_THREAD,%eax
                    649:        movl    %gs:(%eax),%ecx
                    650:        testl   %ecx,%ecx
                    651:        je      0f
                    652:        decl    TH_MUTEX_COUNT(%ecx)
                    653: 0:
                    654: #endif
                    655: 
                    656:        xorb    %cl,%cl
                    657:        xchgb   %cl,M_LOCKED            /* unlock the mutex */
                    658: 
                    659:        xorb    %cl,%cl
                    660:        xchgb   %cl,M_ILK
                    661: 
                    662:        ENABLE_PREEMPTION(%eax)
                    663: 
                    664:        EMARF
                    665:        ret
                    666: 
                    667: mu_wakeup:
                    668:        pushl   %edx                    /* push mutex address */
                    669:        call    EXT(mutex_unlock_wakeup)/* yes, wake a thread */
                    670:        addl    $4,%esp
                    671:        movl    L_ARG0,%edx             /* refetch lock pointer */
                    672:        jmp     mu_doit
                    673: 
                    674: ENTRY(interlock_unlock)
                    675:        FRAME
                    676:        movl    L_ARG0,%edx
                    677: 
                    678:        xorb    %cl,%cl
                    679:        xchgb   %cl,M_ILK
                    680: 
                    681:        ENABLE_PREEMPTION(%eax)
                    682: 
                    683:        EMARF
                    684:        ret
                    685: 
                    686:        
                    687: ENTRY(_disable_preemption)
                    688: #if    MACH_RT
                    689:        _DISABLE_PREEMPTION(%eax)
                    690: #endif /* MACH_RT */
                    691:        ret
                    692: 
                    693: ENTRY(_enable_preemption)
                    694: #if    MACH_RT
                    695: #if    MACH_ASSERT
                    696:        movl    $CPD_PREEMPTION_LEVEL,%eax
                    697:        cmpl    $0,%gs:(%eax)
                    698:        jg      1f
                    699:        pushl   %gs:(%eax)
                    700:        pushl   $2f
                    701:        call    EXT(panic)
                    702:        hlt
                    703:        .data
                    704: 2:     String  "_enable_preemption: preemption_level(%d)  < 0!"
                    705:        .text
                    706: 1:
                    707: #endif /* MACH_ASSERT */
                    708:        _ENABLE_PREEMPTION(%eax)
                    709: #endif /* MACH_RT */
                    710:        ret
                    711: 
                    712: ENTRY(_enable_preemption_no_check)
                    713: #if    MACH_RT
                    714: #if    MACH_ASSERT
                    715:        movl    $CPD_PREEMPTION_LEVEL,%eax
                    716:        cmpl    $0,%gs:(%eax)
                    717:        jg      1f
                    718:        pushl   $2f
                    719:        call    EXT(panic)
                    720:        hlt
                    721:        .data
                    722: 2:     String  "_enable_preemption_no_check: preemption_level <= 0!"
                    723:        .text
                    724: 1:
                    725: #endif /* MACH_ASSERT */
                    726:        _ENABLE_PREEMPTION_NO_CHECK(%eax)
                    727: #endif /* MACH_RT */
                    728:        ret
                    729:        
                    730:        
                    731: ENTRY(_mp_disable_preemption)
                    732: #if    MACH_RT && NCPUS > 1
                    733:        _DISABLE_PREEMPTION(%eax)
                    734: #endif /* MACH_RT && NCPUS > 1*/
                    735:        ret
                    736: 
                    737: ENTRY(_mp_enable_preemption)
                    738: #if    MACH_RT && NCPUS > 1
                    739: #if    MACH_ASSERT
                    740:        movl    $CPD_PREEMPTION_LEVEL,%eax
                    741:        cmpl    $0,%gs:(%eax)
                    742:        jg      1f
                    743:        pushl   %gs:(%eax)
                    744:        pushl   $2f
                    745:        call    EXT(panic)
                    746:        hlt
                    747:        .data
                    748: 2:     String  "_mp_enable_preemption: preemption_level (%d) <= 0!"
                    749:        .text
                    750: 1:
                    751: #endif /* MACH_ASSERT */
                    752:        _ENABLE_PREEMPTION(%eax)
                    753: #endif /* MACH_RT && NCPUS > 1 */
                    754:        ret
                    755: 
                    756: ENTRY(_mp_enable_preemption_no_check)
                    757: #if    MACH_RT && NCPUS > 1
                    758: #if    MACH_ASSERT
                    759:        movl    $CPD_PREEMPTION_LEVEL,%eax
                    760:        cmpl    $0,%gs:(%eax)
                    761:        jg      1f
                    762:        pushl   $2f
                    763:        call    EXT(panic)
                    764:        hlt
                    765:        .data
                    766: 2:     String  "_mp_enable_preemption_no_check: preemption_level <= 0!"
                    767:        .text
                    768: 1:
                    769: #endif /* MACH_ASSERT */
                    770:        _ENABLE_PREEMPTION_NO_CHECK(%eax)
                    771: #endif /* MACH_RT && NCPUS > 1 */
                    772:        ret
                    773:        
                    774:        
                    775: ENTRY(i_bit_set)
                    776:        movl    S_ARG0,%edx
                    777:        movl    S_ARG1,%eax
                    778:        lock
                    779:        bts     %dl,(%eax)
                    780:        ret
                    781: 
                    782: ENTRY(i_bit_clear)
                    783:        movl    S_ARG0,%edx
                    784:        movl    S_ARG1,%eax
                    785:        lock
                    786:        btr     %dl,(%eax)
                    787:        ret
                    788: 
                    789: ENTRY(bit_lock)
                    790:        movl    S_ARG0,%ecx
                    791:        movl    S_ARG1,%eax
                    792: 1:
                    793:        lock
                    794:        bts     %ecx,(%eax)
                    795:        jb      1b
                    796:        ret
                    797: 
                    798: ENTRY(bit_lock_try)
                    799:        movl    S_ARG0,%ecx
                    800:        movl    S_ARG1,%eax
                    801:        lock
                    802:        bts     %ecx,(%eax)
                    803:        jb      bit_lock_failed
                    804:        ret                     /* %eax better not be null ! */
                    805: bit_lock_failed:
                    806:        xorl    %eax,%eax
                    807:        ret
                    808: 
                    809: ENTRY(bit_unlock)
                    810:        movl    S_ARG0,%ecx
                    811:        movl    S_ARG1,%eax
                    812:        lock
                    813:        btr     %ecx,(%eax)
                    814:        ret

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.