Ignore:
File:
1 edited

Legend:

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

    r76e17d7c re88eb48  
    11/*
    22 * Copyright (c) 2001-2004 Jakub Jermar
    3  * Copyright (c) 2023 Jiří Zárevúcky
    43 * All rights reserved.
    54 *
     
    6766bool mutex_locked(mutex_t *mtx)
    6867{
    69         errno_t rc = semaphore_trydown(&mtx->sem);
    70         if (rc == EOK) {
    71                 semaphore_up(&mtx->sem);
    72         }
    73         return rc != EOK;
     68        return semaphore_count_get(&mtx->sem) <= 0;
    7469}
    7570
    76 static 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 }
     71#define MUTEX_DEADLOCK_THRESHOLD        100000000
    9672
    9773/** Acquire mutex.
    9874 *
    99  * This operation is uninterruptible and cannot fail.
    100  */
    101 void 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.
     75 * Timeout mode and non-blocking mode can be requested.
    12076 *
    12177 * @param mtx    Mutex.
    12278 * @param usec   Timeout in microseconds.
     79 * @param flags  Specify mode of operation.
    12380 *
    124  * @return EOK if lock was successfully acquired, something else otherwise.
     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 *
    12586 */
    126 errno_t mutex_lock_timeout(mutex_t *mtx, uint32_t usec)
     87errno_t _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, unsigned int flags)
    12788{
    128         if (usec != 0) {
    129                 assert(mtx->type != MUTEX_ACTIVE);
     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) {
    13094                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);
    131125        }
    132126
    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         }
    144127        return rc;
    145 }
    146 
    147 /** Attempt to acquire mutex without blocking.
    148  *
    149  * @return EOK if lock was successfully acquired, something else otherwise.
    150  */
    151 errno_t mutex_trylock(mutex_t *mtx)
    152 {
    153         return mutex_lock_timeout(mtx, 0);
    154128}
    155129
Note: See TracChangeset for help on using the changeset viewer.