Changeset 76e17d7c in mainline


Ignore:
Timestamp:
2023-02-11T18:50:54Z (17 months ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
111b9b9
Parents:
11d2c983
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2023-02-05 15:30:26)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2023-02-11 18:50:54)
Message:

Reorganize mutex implementation

Location:
kernel/generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/synch/mutex.h

    r11d2c983 r76e17d7c  
    5959extern bool mutex_locked(mutex_t *);
    6060extern errno_t mutex_trylock(mutex_t *);
    61 extern errno_t mutex_lock(mutex_t *);
     61extern void mutex_lock(mutex_t *);
    6262extern errno_t mutex_lock_timeout(mutex_t *, uint32_t);
    6363extern void mutex_unlock(mutex_t *);
  • kernel/generic/include/synch/semaphore.h

    r11d2c983 r76e17d7c  
    4646
    4747extern void semaphore_initialize(semaphore_t *, int);
    48 extern errno_t _semaphore_down_timeout(semaphore_t *, uint32_t, unsigned);
    4948extern errno_t semaphore_down_timeout(semaphore_t *, uint32_t);
    5049extern errno_t semaphore_trydown(semaphore_t *);
  • kernel/generic/src/synch/mutex.c

    r11d2c983 r76e17d7c  
    11/*
    22 * Copyright (c) 2001-2004 Jakub Jermar
     3 * Copyright (c) 2023 Jiří Zárevúcky
    34 * All rights reserved.
    45 *
     
    7374}
    7475
    75 #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}
    7696
    7797/** Acquire mutex.
    7898 *
    79  * 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.
    80120 *
    81121 * @param mtx    Mutex.
    82122 * @param usec   Timeout in microseconds.
    83  * @param flags  Specify mode of operation.
    84123 *
    85  * For exact description of possible combinations of usec and flags, see
    86  * comment for waitq_sleep_timeout().
    87  *
    88  * @return See comment for waitq_sleep_timeout().
    89  *
     124 * @return EOK if lock was successfully acquired, something else otherwise.
    90125 */
    91 static 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)
    92127{
    93         errno_t rc;
    94 
    95         if (mtx->type == MUTEX_PASSIVE && THREAD) {
    96                 rc = _semaphore_down_timeout(&mtx->sem, usec, flags);
    97         } else if (mtx->type == MUTEX_RECURSIVE) {
     128        if (usec != 0) {
     129                assert(mtx->type != MUTEX_ACTIVE);
    98130                assert(THREAD);
    99 
    100                 if (mtx->owner == THREAD) {
    101                         mtx->nesting++;
    102                         return EOK;
    103                 } else {
    104                         rc = _semaphore_down_timeout(&mtx->sem, usec, flags);
    105                         if (rc == EOK) {
    106                                 mtx->owner = THREAD;
    107                                 mtx->nesting = 1;
    108                         }
    109                 }
    110         } else {
    111                 assert((mtx->type == MUTEX_ACTIVE) || !THREAD);
    112                 assert(usec == SYNCH_NO_TIMEOUT);
    113                 assert(!(flags & SYNCH_FLAGS_INTERRUPTIBLE));
    114 
    115                 unsigned int cnt = 0;
    116                 bool deadlock_reported = false;
    117                 do {
    118                         if (cnt++ > MUTEX_DEADLOCK_THRESHOLD) {
    119                                 printf("cpu%u: looping on active mutex %p\n",
    120                                     CPU->id, mtx);
    121                                 stack_trace();
    122                                 cnt = 0;
    123                                 deadlock_reported = true;
    124                         }
    125                         rc = semaphore_trydown(&mtx->sem);
    126                 } while (rc != EOK && !(flags & SYNCH_FLAGS_NON_BLOCKING));
    127                 if (deadlock_reported)
    128                         printf("cpu%u: not deadlocked\n", CPU->id);
    129131        }
    130132
     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        }
    131144        return rc;
    132145}
    133146
     147/** Attempt to acquire mutex without blocking.
     148 *
     149 * @return EOK if lock was successfully acquired, something else otherwise.
     150 */
    134151errno_t mutex_trylock(mutex_t *mtx)
    135152{
    136         return _mutex_lock_timeout(mtx, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING);
    137 }
    138 
    139 errno_t mutex_lock(mutex_t *mtx)
    140 {
    141         return _mutex_lock_timeout(mtx, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
    142 }
    143 
    144 errno_t mutex_lock_timeout(mutex_t *mtx, uint32_t usec)
    145 {
    146         return _mutex_lock_timeout(mtx, usec, SYNCH_FLAGS_NON_BLOCKING);
     153        return mutex_lock_timeout(mtx, 0);
    147154}
    148155
  • kernel/generic/src/synch/semaphore.c

    r11d2c983 r76e17d7c  
    5555}
    5656
    57 errno_t _semaphore_down_timeout(semaphore_t *sem, uint32_t usec, unsigned flags)
    58 {
    59         errno_t rc = waitq_sleep_timeout(&sem->wq, usec, flags, NULL);
    60         assert(rc == EOK || rc == ETIMEOUT || rc == EAGAIN);
    61         return rc;
    62 }
    63 
    6457errno_t semaphore_trydown(semaphore_t *sem)
    6558{
    66         return _semaphore_down_timeout(sem, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING);
     59        return semaphore_down_timeout(sem, 0);
    6760}
    6861
     
    7770errno_t semaphore_down_timeout(semaphore_t *sem, uint32_t usec)
    7871{
    79         return _semaphore_down_timeout(sem, usec, SYNCH_FLAGS_NON_BLOCKING);
     72        errno_t rc = waitq_sleep_timeout(&sem->wq, usec, SYNCH_FLAGS_NON_BLOCKING, NULL);
     73        assert(rc == EOK || rc == ETIMEOUT || rc == EAGAIN);
     74        return rc;
    8075}
    8176
Note: See TracChangeset for help on using the changeset viewer.