cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_sysmutex.c (5166B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../../SDL_internal.h"
     22
     23#ifndef _GNU_SOURCE
     24#define _GNU_SOURCE
     25#endif
     26#include <pthread.h>
     27#include <errno.h>
     28
     29#include "SDL_thread.h"
     30
     31#if !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX && \
     32    !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
     33#define FAKE_RECURSIVE_MUTEX 1
     34#endif
     35
     36struct SDL_mutex
     37{
     38    pthread_mutex_t id;
     39#if FAKE_RECURSIVE_MUTEX
     40    int recursive;
     41    pthread_t owner;
     42#endif
     43};
     44
     45SDL_mutex *
     46SDL_CreateMutex(void)
     47{
     48    SDL_mutex *mutex;
     49    pthread_mutexattr_t attr;
     50
     51    /* Allocate the structure */
     52    mutex = (SDL_mutex *) SDL_calloc(1, sizeof(*mutex));
     53    if (mutex) {
     54        pthread_mutexattr_init(&attr);
     55#if SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
     56        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
     57#elif SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
     58        pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
     59#else
     60        /* No extra attributes necessary */
     61#endif
     62        if (pthread_mutex_init(&mutex->id, &attr) != 0) {
     63            SDL_SetError("pthread_mutex_init() failed");
     64            SDL_free(mutex);
     65            mutex = NULL;
     66        }
     67    } else {
     68        SDL_OutOfMemory();
     69    }
     70    return (mutex);
     71}
     72
     73void
     74SDL_DestroyMutex(SDL_mutex * mutex)
     75{
     76    if (mutex) {
     77        pthread_mutex_destroy(&mutex->id);
     78        SDL_free(mutex);
     79    }
     80}
     81
     82/* Lock the mutex */
     83int
     84SDL_LockMutex(SDL_mutex * mutex)
     85{
     86#if FAKE_RECURSIVE_MUTEX
     87    pthread_t this_thread;
     88#endif
     89
     90    if (mutex == NULL) {
     91        return SDL_SetError("Passed a NULL mutex");
     92    }
     93
     94#if FAKE_RECURSIVE_MUTEX
     95    this_thread = pthread_self();
     96    if (mutex->owner == this_thread) {
     97        ++mutex->recursive;
     98    } else {
     99        /* The order of operations is important.
    100           We set the locking thread id after we obtain the lock
    101           so unlocks from other threads will fail.
    102         */
    103        if (pthread_mutex_lock(&mutex->id) == 0) {
    104            mutex->owner = this_thread;
    105            mutex->recursive = 0;
    106        } else {
    107            return SDL_SetError("pthread_mutex_lock() failed");
    108        }
    109    }
    110#else
    111    if (pthread_mutex_lock(&mutex->id) < 0) {
    112        return SDL_SetError("pthread_mutex_lock() failed");
    113    }
    114#endif
    115    return 0;
    116}
    117
    118int
    119SDL_TryLockMutex(SDL_mutex * mutex)
    120{
    121    int retval;
    122#if FAKE_RECURSIVE_MUTEX
    123    pthread_t this_thread;
    124#endif
    125
    126    if (mutex == NULL) {
    127        return SDL_SetError("Passed a NULL mutex");
    128    }
    129
    130    retval = 0;
    131#if FAKE_RECURSIVE_MUTEX
    132    this_thread = pthread_self();
    133    if (mutex->owner == this_thread) {
    134        ++mutex->recursive;
    135    } else {
    136        /* The order of operations is important.
    137         We set the locking thread id after we obtain the lock
    138         so unlocks from other threads will fail.
    139         */
    140        if (pthread_mutex_lock(&mutex->id) == 0) {
    141            mutex->owner = this_thread;
    142            mutex->recursive = 0;
    143        } else if (errno == EBUSY) {
    144            retval = SDL_MUTEX_TIMEDOUT;
    145        } else {
    146            retval = SDL_SetError("pthread_mutex_trylock() failed");
    147        }
    148    }
    149#else
    150    if (pthread_mutex_trylock(&mutex->id) != 0) {
    151        if (errno == EBUSY) {
    152            retval = SDL_MUTEX_TIMEDOUT;
    153        } else {
    154            retval = SDL_SetError("pthread_mutex_trylock() failed");
    155        }
    156    }
    157#endif
    158    return retval;
    159}
    160
    161int
    162SDL_UnlockMutex(SDL_mutex * mutex)
    163{
    164    if (mutex == NULL) {
    165        return SDL_SetError("Passed a NULL mutex");
    166    }
    167
    168#if FAKE_RECURSIVE_MUTEX
    169    /* We can only unlock the mutex if we own it */
    170    if (pthread_self() == mutex->owner) {
    171        if (mutex->recursive) {
    172            --mutex->recursive;
    173        } else {
    174            /* The order of operations is important.
    175               First reset the owner so another thread doesn't lock
    176               the mutex and set the ownership before we reset it,
    177               then release the lock semaphore.
    178             */
    179            mutex->owner = 0;
    180            pthread_mutex_unlock(&mutex->id);
    181        }
    182    } else {
    183        return SDL_SetError("mutex not owned by this thread");
    184    }
    185
    186#else
    187    if (pthread_mutex_unlock(&mutex->id) < 0) {
    188        return SDL_SetError("pthread_mutex_unlock() failed");
    189    }
    190#endif /* FAKE_RECURSIVE_MUTEX */
    191
    192    return 0;
    193}
    194
    195/* vi: set ts=4 sw=4 expandtab: */