Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/synch/mutex.c

    re88eb48 r76e17d7c  
    11/*
    22 * Copyright (c) 2001-2004 Jakub Jermar
     3 * Copyright (c) 2023 Jiří Zárevúcky
    34 * All rights reserved.
    45 *
     
    6667bool mutex_locked(mutex_t *mtx)
    6768{
    68         return semaphore_count_get(&mtx->sem) <= 0;
     69        errno_t rc = semaphore_trydown(&mtx->sem);
     70        if (rc == EOK) {
     71                semaphore_up(&mtx->sem);
     72        }
     73        return rc != EOK;
    6974}
    7075
    71 #define MUTEX_DEADLOCK_THRESHOLD        100000000
     76static void mutex_lock_active(mutex_t *mtx)
     77{
     78        assert((mtx->type == MUTEX_ACTIVE) || !THREAD);
     79
     80        const unsigned deadlock_treshold = 100000000;
     81        unsigned int cnt = 0;
     82        bool deadlock_reported = false;
     83
     84        while (semaphore_trydown(&mtx->sem) != EOK) {
     85                if (cnt++ > deadlock_treshold) {
     86                        printf("cpu%u: looping on active mutex %p\n", CPU->id, mtx);
     87                        stack_trace();
     88                        cnt = 0;
     89                        deadlock_reported = true;
     90                }
     91        }
     92
     93        if (deadlock_reported)
     94                printf("cpu%u: not deadlocked\n", CPU->id);
     95}
    7296
    7397/** Acquire mutex.
    7498 *
    75  * Timeout mode and non-blocking mode can be requested.
     99 * This operation is uninterruptible and cannot fail.
     100 */
     101void mutex_lock(mutex_t *mtx)
     102{
     103        if (mtx->type == MUTEX_RECURSIVE && mtx->owner == THREAD) {
     104                assert(THREAD);
     105                mtx->nesting++;
     106                return;
     107        }
     108
     109        if (mtx->type == MUTEX_ACTIVE || !THREAD) {
     110                mutex_lock_active(mtx);
     111                return;
     112        }
     113
     114        semaphore_down(&mtx->sem);
     115        mtx->owner = THREAD;
     116        mtx->nesting = 1;
     117}
     118
     119/** Acquire mutex with timeout.
    76120 *
    77121 * @param mtx    Mutex.
    78122 * @param usec   Timeout in microseconds.
    79  * @param flags  Specify mode of operation.
    80123 *
    81  * For exact description of possible combinations of usec and flags, see
    82  * comment for waitq_sleep_timeout().
    83  *
    84  * @return See comment for waitq_sleep_timeout().
    85  *
     124 * @return EOK if lock was successfully acquired, something else otherwise.
    86125 */
    87 errno_t _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, unsigned int flags)
     126errno_t mutex_lock_timeout(mutex_t *mtx, uint32_t usec)
    88127{
    89         errno_t rc;
    90 
    91         if (mtx->type == MUTEX_PASSIVE && THREAD) {
    92                 rc = _semaphore_down_timeout(&mtx->sem, usec, flags);
    93         } else if (mtx->type == MUTEX_RECURSIVE) {
     128        if (usec != 0) {
     129                assert(mtx->type != MUTEX_ACTIVE);
    94130                assert(THREAD);
    95 
    96                 if (mtx->owner == THREAD) {
    97                         mtx->nesting++;
    98                         return EOK;
    99                 } else {
    100                         rc = _semaphore_down_timeout(&mtx->sem, usec, flags);
    101                         if (rc == EOK) {
    102                                 mtx->owner = THREAD;
    103                                 mtx->nesting = 1;
    104                         }
    105                 }
    106         } else {
    107                 assert((mtx->type == MUTEX_ACTIVE) || !THREAD);
    108                 assert(usec == SYNCH_NO_TIMEOUT);
    109                 assert(!(flags & SYNCH_FLAGS_INTERRUPTIBLE));
    110 
    111                 unsigned int cnt = 0;
    112                 bool deadlock_reported = false;
    113                 do {
    114                         if (cnt++ > MUTEX_DEADLOCK_THRESHOLD) {
    115                                 printf("cpu%u: looping on active mutex %p\n",
    116                                     CPU->id, mtx);
    117                                 stack_trace();
    118                                 cnt = 0;
    119                                 deadlock_reported = true;
    120                         }
    121                         rc = semaphore_trydown(&mtx->sem);
    122                 } while (rc != EOK && !(flags & SYNCH_FLAGS_NON_BLOCKING));
    123                 if (deadlock_reported)
    124                         printf("cpu%u: not deadlocked\n", CPU->id);
    125131        }
    126132
     133        if (mtx->type == MUTEX_RECURSIVE && mtx->owner == THREAD) {
     134                assert(THREAD);
     135                mtx->nesting++;
     136                return EOK;
     137        }
     138
     139        errno_t rc = semaphore_down_timeout(&mtx->sem, usec);
     140        if (rc == EOK) {
     141                mtx->owner = THREAD;
     142                mtx->nesting = 1;
     143        }
    127144        return rc;
     145}
     146
     147/** Attempt to acquire mutex without blocking.
     148 *
     149 * @return EOK if lock was successfully acquired, something else otherwise.
     150 */
     151errno_t mutex_trylock(mutex_t *mtx)
     152{
     153        return mutex_lock_timeout(mtx, 0);
    128154}
    129155
Note: See TracChangeset for help on using the changeset viewer.