<commit_before>/*
 * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * -----------------------------------------------------------------------------
 *
 * Project:     CMSIS-RTOS RTX
 * Title:       Mutex functions
 *
 * -----------------------------------------------------------------------------
 */

#include "rtx_lib.h"


//  ==== Library functions ====

/// Release Mutex list when owner Thread terminates.
/// \param[in]  mutex           mutex object.
/// \return 1 - success, 0 - failure.
void osRtxMutexOwnerRelease (os_mutex_t *mutex_list) {
  os_mutex_t  *mutex;
  os_thread_t *thread;

  mutex = mutex_list;
  while (mutex) {
    mutex_list = mutex->owner_next;
    // Check if Mutex is Robust
    if (mutex->attr & osMutexRobust) {
      // Clear Lock counter
      mutex->lock = 0U;
      EvrRtxMutexReleased(mutex, 0U);
      // Check if Thread is waiting for a Mutex
      if (mutex->thread_list != NULL) {
        // Wakeup waiting Thread with highest Priority
        thread = osRtxThreadListGet((os_object_t*)mutex);
        osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
        // Thread is the new Mutex owner
        mutex->owner_thread = thread;
        mutex->owner_next   = thread->mutex_list;
        mutex->owner_prev   = NULL;
        thread->mutex_list  = mutex;
        mutex->lock = 1U;
        EvrRtxMutexAcquired(mutex, 1U);
      }
    }
    mutex = mutex_list;
  }
}


//  ==== Service Calls ====

//  Service Calls definitions
SVC0_1M(MutexNew,      osMutexId_t,  const osMutexAttr_t *)
SVC0_1 (MutexGetName,  const char *, osMutexId_t)
SVC0_2 (MutexAcquire,  osStatus_t,   osMutexId_t, uint32_t)
SVC0_1 (MutexRelease,  osStatus_t,   osMutexId_t)
SVC0_1 (MutexGetOwner, osThreadId_t, osMutexId_t)
SVC0_1 (MutexDelete,   osStatus_t,   osMutexId_t)

/// Create and Initialize a Mutex object.
/// \note API identical to osMutexNew
osMutexId_t svcRtxMutexNew (const osMutexAttr_t *attr) {
  os_mutex_t *mutex;
  uint32_t    attr_bits;
  uint8_t     flags;
  const char *name;

  // Process attributes
  if (attr != NULL) {
    name      = attr->name;
    attr_bits = attr->attr_bits;
    mutex     = attr->cb_mem;
    if (mutex != NULL) {
      if (((uint32_t)mutex & 3U) || (attr->cb_size < sizeof(os_mutex_t))) {
        EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
        return NULL;
      }
    } else {
      if (attr->cb_size != 0U) {
        EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
        return NULL;
      }
    }
  } else {
    name      = NULL;
    attr_bits = 0U;
    mutex     = NULL;
  }

  // Allocate object memory if not provided
  if (mutex == NULL) {
    if (osRtxInfo.mpi.mutex != NULL) {
      mutex = osRtxMemoryPoolAlloc(osRtxInfo.mpi.mutex);
    } else {
      mutex = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_mutex_t), 1U);
    }
    if (mutex == NULL) {
      EvrRtxMutexError(NULL, osErrorNoMemory);
      return NULL;
    }
    flags = osRtxFlagSystemObject;
  } else {
    flags = 0U;
  }

  // Initialize control block
  mutex->id           = osRtxIdMutex;
  mutex->state        = osRtxObjectActive;
  mutex->flags        = flags;
  mutex->attr         = (uint8_t)attr_bits;
  mutex->name         = name;
  mutex->thread_list  = NULL;
  mutex->owner_thread = NULL;
  mutex->owner_prev   = NULL;
  mutex->owner_next   = NULL;
  mutex->lock         = 0U;

  EvrRtxMutexCreated(mutex);

  return mutex;
}

/// Get name of a Mutex object.
/// \note API identical to osMutexGetName
const char *svcRtxMutexGetName (osMutexId_t mutex_id) {
  os_mutex_t *mutex = (os_mutex_t *)mutex_id;

  // Check parameters
  if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
    EvrRtxMutexGetName(mutex, NULL);
    return NULL;
  }

  // Check object state
  if (mutex->state == osRtxObjectInactive) {
    EvrRtxMutexGetName(mutex, NULL);
    return NULL;
  }

  EvrRtxMutexGetName(mutex, mutex->name);

  return mutex->name;
}

/// Acquire a Mutex or timeout if it is locked.
/// \note API identical to osMutexAcquire
osStatus_t svcRtxMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
  os_mutex_t  *mutex = (os_mutex_t *)mutex_id;
  os_thread_t *runnig_thread;

  runnig_thread = osRtxThreadGetRunning();
  if (runnig_thread == NULL) {
    EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
    return osError;
  }

  // Check parameters
  if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
    EvrRtxMutexError(mutex, osErrorParameter);
    return osErrorParameter;
  }

  // Check object state
  if (mutex->state == osRtxObjectInactive) {
    EvrRtxMutexError(mutex, osErrorResource);
    return osErrorResource;
  }

  // Check if Mutex is not locked
  if (mutex->lock == 0U) {
    // Acquire Mutex
    mutex->owner_thread = runnig_thread;
    mutex->owner_next   = runnig_thread->mutex_list;
    mutex->owner_prev   = NULL;
    runnig_thread->mutex_list = mutex;
    mutex->lock = 1U;
    EvrRtxMutexAcquired(mutex, mutex->lock);
    return osOK;
  }

  // Check if Mutex is recursive and running Thread is the owner
  if ((mutex->attr & osMutexRecursive) && (mutex->owner_thread == runnig_thread)) {
    // Increment lock counter
    if (mutex->lock == osRtxMutexLockLimit) {
      EvrRtxMutexError(mutex, osRtxErrorMutexLockLimit);
      return osErrorResource;
    }
    mutex->lock++;
    EvrRtxMutexAcquired(mutex, mutex->lock);
    return osOK;<commit_msg>RTX: Fixed RTXv5 mutex owner list handling.<commit_after>/*
 * Copyright (c) 2013-2017 ARM Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * -----------------------------------------------------------------------------
 *
 * Project:     CMSIS-RTOS RTX
 * Title:       Mutex functions
 *
 * -----------------------------------------------------------------------------
 */

#include "rtx_lib.h"


//  ==== Library functions ====

/// Release Mutex list when owner Thread terminates.
/// \param[in]  mutex           mutex object.
/// \return 1 - success, 0 - failure.
void osRtxMutexOwnerRelease (os_mutex_t *mutex_list) {
  os_mutex_t  *mutex;
  os_thread_t *thread;

  mutex = mutex_list;
  while (mutex) {
    mutex_list = mutex->owner_next;
    // Check if Mutex is Robust
    if (mutex->attr & osMutexRobust) {
      // Clear Lock counter
      mutex->lock = 0U;
      EvrRtxMutexReleased(mutex, 0U);
      // Check if Thread is waiting for a Mutex
      if (mutex->thread_list != NULL) {
        // Wakeup waiting Thread with highest Priority
        thread = osRtxThreadListGet((os_object_t*)mutex);
        osRtxThreadWaitExit(thread, (uint32_t)osOK, false);
        // Thread is the new Mutex owner
        mutex->owner_thread = thread;
        mutex->owner_next   = thread->mutex_list;
        mutex->owner_prev   = NULL;
        thread->mutex_list  = mutex;
        mutex->lock = 1U;
        EvrRtxMutexAcquired(mutex, 1U);
      }
    }
    mutex = mutex_list;
  }
}


//  ==== Service Calls ====

//  Service Calls definitions
SVC0_1M(MutexNew,      osMutexId_t,  const osMutexAttr_t *)
SVC0_1 (MutexGetName,  const char *, osMutexId_t)
SVC0_2 (MutexAcquire,  osStatus_t,   osMutexId_t, uint32_t)
SVC0_1 (MutexRelease,  osStatus_t,   osMutexId_t)
SVC0_1 (MutexGetOwner, osThreadId_t, osMutexId_t)
SVC0_1 (MutexDelete,   osStatus_t,   osMutexId_t)

/// Create and Initialize a Mutex object.
/// \note API identical to osMutexNew
osMutexId_t svcRtxMutexNew (const osMutexAttr_t *attr) {
  os_mutex_t *mutex;
  uint32_t    attr_bits;
  uint8_t     flags;
  const char *name;

  // Process attributes
  if (attr != NULL) {
    name      = attr->name;
    attr_bits = attr->attr_bits;
    mutex     = attr->cb_mem;
    if (mutex != NULL) {
      if (((uint32_t)mutex & 3U) || (attr->cb_size < sizeof(os_mutex_t))) {
        EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
        return NULL;
      }
    } else {
      if (attr->cb_size != 0U) {
        EvrRtxMutexError(NULL, osRtxErrorInvalidControlBlock);
        return NULL;
      }
    }
  } else {
    name      = NULL;
    attr_bits = 0U;
    mutex     = NULL;
  }

  // Allocate object memory if not provided
  if (mutex == NULL) {
    if (osRtxInfo.mpi.mutex != NULL) {
      mutex = osRtxMemoryPoolAlloc(osRtxInfo.mpi.mutex);
    } else {
      mutex = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_mutex_t), 1U);
    }
    if (mutex == NULL) {
      EvrRtxMutexError(NULL, osErrorNoMemory);
      return NULL;
    }
    flags = osRtxFlagSystemObject;
  } else {
    flags = 0U;
  }

  // Initialize control block
  mutex->id           = osRtxIdMutex;
  mutex->state        = osRtxObjectActive;
  mutex->flags        = flags;
  mutex->attr         = (uint8_t)attr_bits;
  mutex->name         = name;
  mutex->thread_list  = NULL;
  mutex->owner_thread = NULL;
  mutex->owner_prev   = NULL;
  mutex->owner_next   = NULL;
  mutex->lock         = 0U;

  EvrRtxMutexCreated(mutex);

  return mutex;
}

/// Get name of a Mutex object.
/// \note API identical to osMutexGetName
const char *svcRtxMutexGetName (osMutexId_t mutex_id) {
  os_mutex_t *mutex = (os_mutex_t *)mutex_id;

  // Check parameters
  if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
    EvrRtxMutexGetName(mutex, NULL);
    return NULL;
  }

  // Check object state
  if (mutex->state == osRtxObjectInactive) {
    EvrRtxMutexGetName(mutex, NULL);
    return NULL;
  }

  EvrRtxMutexGetName(mutex, mutex->name);

  return mutex->name;
}

/// Acquire a Mutex or timeout if it is locked.
/// \note API identical to osMutexAcquire
osStatus_t svcRtxMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) {
  os_mutex_t  *mutex = (os_mutex_t *)mutex_id;
  os_thread_t *runnig_thread;

  runnig_thread = osRtxThreadGetRunning();
  if (runnig_thread == NULL) {
    EvrRtxMutexError(mutex, osRtxErrorKernelNotRunning);
    return osError;
  }

  // Check parameters
  if ((mutex == NULL) || (mutex->id != osRtxIdMutex)) {
    EvrRtxMutexError(mutex, osErrorParameter);
    return osErrorParameter;
  }

  // Check object state
  if (mutex->state == osRtxObjectInactive) {
    EvrRtxMutexError(mutex, osErrorResource);
    return osErrorResource;
  }

  // Check if Mutex is not locked
  if (mutex->lock == 0U) {
    // Acquire Mutex
    mutex->owner_thread = runnig_thread;
    mutex->owner_next   = runnig_thread->mutex_list;
    mutex->owner_prev   = NULL;
    if (runnig_thread->mutex_list != NULL) {
        runnig_thread->mutex_list->owner_prev = mutex;
    }
    runnig_thread->mutex_list = mutex;
    mutex->lock = 1U;
    EvrRtxMutexAcquired(mutex, mutex->lock);
    return osOK;
  }

  // Check if Mutex is recursive and running Thread is the owner
  if ((mutex->attr & osMutexRecursive) && (mutex->owner_thread == runnig_thread)) {
    // Increment lock counter
    if (mutex->lock == osRtxMutexLockLimit) {
      EvrRtxMutexError(mutex, osRtxErrorMutexLockLimit);
      return osErrorResource;
    }
    mutex->lock++;
    EvrRtxMutexAcquired(mutex, mutex->lock);
    return osOK;
{'fraction_non_alphanumeric': 0.1329134902220749, 'fraction_numerical': 0.008700696055684454, 'mean_word_length': 2.6265024038461537, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 94, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4922962', 'n_tokens_mistral': 4157, 'n_tokens_neox': 4078, 'n_words': 998}