* @brief This function will release a mutex. If there is thread suspended on the mutex, the thread will be resumed. * * @note If there are threads suspended on this mutex, the first thread in the list of this mutex object * will be resumed, and a thread scheduling (rt_schedule) will be executed. * If no threads are suspended on this mutex, the count value mutex->valu
| 1589 | * If the return value is any other values, it means that the mutex release failed. |
| 1590 | */ |
| 1591 | rt_err_t rt_mutex_release(rt_mutex_t mutex) |
| 1592 | { |
| 1593 | rt_sched_lock_level_t slvl; |
| 1594 | struct rt_thread *thread; |
| 1595 | rt_bool_t need_schedule; |
| 1596 | |
| 1597 | /* parameter check */ |
| 1598 | RT_ASSERT(mutex != RT_NULL); |
| 1599 | RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex); |
| 1600 | |
| 1601 | need_schedule = RT_FALSE; |
| 1602 | |
| 1603 | /* only thread could release mutex because we need test the ownership */ |
| 1604 | RT_DEBUG_IN_THREAD_CONTEXT; |
| 1605 | |
| 1606 | /* get current thread */ |
| 1607 | thread = rt_thread_self(); |
| 1608 | |
| 1609 | rt_spin_lock(&(mutex->spinlock)); |
| 1610 | |
| 1611 | LOG_D("mutex_release:current thread %s, hold: %d", |
| 1612 | thread->parent.name, mutex->hold); |
| 1613 | |
| 1614 | RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mutex->parent.parent))); |
| 1615 | |
| 1616 | /* mutex only can be released by owner */ |
| 1617 | if (thread != mutex->owner) |
| 1618 | { |
| 1619 | thread->error = -RT_ERROR; |
| 1620 | rt_spin_unlock(&(mutex->spinlock)); |
| 1621 | |
| 1622 | return -RT_ERROR; |
| 1623 | } |
| 1624 | |
| 1625 | /* decrease hold */ |
| 1626 | mutex->hold --; |
| 1627 | /* if no hold */ |
| 1628 | if (mutex->hold == 0) |
| 1629 | { |
| 1630 | rt_sched_lock(&slvl); |
| 1631 | |
| 1632 | /* remove mutex from thread's taken list */ |
| 1633 | rt_list_remove(&mutex->taken_list); |
| 1634 | |
| 1635 | /* whether change the thread priority */ |
| 1636 | need_schedule = _check_and_update_prio(thread, mutex); |
| 1637 | |
| 1638 | /* wakeup suspended thread */ |
| 1639 | if (!rt_list_isempty(&mutex->parent.suspend_thread)) |
| 1640 | { |
| 1641 | struct rt_thread *next_thread; |
| 1642 | do |
| 1643 | { |
| 1644 | /* get the first suspended thread */ |
| 1645 | next_thread = RT_THREAD_LIST_NODE_ENTRY(mutex->parent.suspend_thread.next); |
| 1646 | |
| 1647 | RT_ASSERT(rt_sched_thread_is_suspended(next_thread)); |
| 1648 |