You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.1 KiB
109 lines
3.1 KiB
/*
|
|
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
|
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
|
* either version 1.0 of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the Phytium Public License for more details.
|
|
*
|
|
*
|
|
* FilePath: fspin.c
|
|
* Date: 2024-08-08 14:53:42
|
|
* LastEditTime: 2024-08-08 17:58:14
|
|
* Description: This files is for a way to provide spinlocks for multicore operations
|
|
*
|
|
* Modify History:
|
|
* Ver Who Date Changes
|
|
* ----- ------ -------- --------------------------------------
|
|
* 1.1 carl 2022-12-30 add init function
|
|
* 1.2 carl 2023-02-28 Use GCC built-in functions to implement spinlock
|
|
* 1.3 wangxiaodong 2024-08-08 Use mcs lock to implement spinlock
|
|
*/
|
|
#include <stdint.h>
|
|
#include <stdatomic.h>
|
|
#include "fspin.h"
|
|
#include "sdkconfig.h"
|
|
#include "ftypes.h"
|
|
#include "fatomic.h"
|
|
|
|
mcs_lock_t *mcs_lock_instance = NULL;
|
|
|
|
/* init mcs lock */
|
|
void FMcsLockInit(mcs_lock_t *lock)
|
|
{
|
|
if (mcs_lock_instance != NULL)
|
|
{
|
|
return;
|
|
}
|
|
mcs_lock_instance = lock;
|
|
if (atomic_load(&mcs_lock_instance->is_ready) == 1)
|
|
{
|
|
return;
|
|
}
|
|
atomic_store(&mcs_lock_instance->tail, NULL);
|
|
atomic_store(&mcs_lock_instance->is_ready, 1);
|
|
}
|
|
|
|
/* mcs lock */
|
|
void FMcsLock(mcs_lock_t *lock, mcs_node_t *node)
|
|
{
|
|
if (lock == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(atomic_load(&lock->is_ready) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
volatile mcs_node_t *prev;
|
|
node->next = NULL;/*初始化节点的next指针*/
|
|
atomic_store(&node->locked, 1);/*将节点的locked标志设置为1,表示锁定*/
|
|
|
|
prev = atomic_exchange(&lock->tail, node);/*将当前节点设置为新的尾部节点,并返回之前的尾部节点*/
|
|
if (prev != NULL)
|
|
{
|
|
atomic_store(&prev->next, node);/*将之前的尾部节点的next指针指向当前节点*/
|
|
while(atomic_load(&node->locked)) /*自旋等待,直到当前节点的locked标志被前驱节点清除*/
|
|
{
|
|
/*busy wait*/
|
|
}
|
|
}
|
|
}
|
|
|
|
/* mcs unlock */
|
|
void FMcsUnlock(mcs_lock_t *lock, mcs_node_t *node)
|
|
{
|
|
if (lock == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(atomic_load(&lock->is_ready) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
mcs_node_t *next = atomic_load(&node->next);
|
|
if (next == NULL) /*如果没有后继节点,尝试将tail设置为NULL*/
|
|
{
|
|
/*尝试将tail指针设置为NULL,表示锁已空闲*/
|
|
if (atomic_compare_exchange_strong(&lock->tail, &node, NULL))
|
|
{
|
|
return;
|
|
}
|
|
/*等待后继节点被设置*/
|
|
while ((next = atomic_load(&node->next)) == NULL)
|
|
{
|
|
/*busy wait*/
|
|
}
|
|
}
|
|
|
|
/*清除下一个节点的locked标志,释放锁*/
|
|
atomic_store(&next->locked, 0);
|
|
}
|
|
|