Files
mkrtos-real/mkrtos_user/lib/libc_backend/src/fd_map.c

183 lines
4.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file fd_map.c
* @author your name (1358745329@qq.com)
* @brief fd map layer
* @version 0.1
* @date 2024-08-08
*
* @copyright Copyright (c) ATShining 2024
*
*/
#include <u_types.h>
#include <assert.h>
#include <malloc.h>
#include <errno.h>
#include <pthread.h>
#include <fd_map.h>
#include <string.h>
#define FD_MAP_TOTAL (CONFIG_FD_MAP_ROW_CN * CONFIG_FD_MAP_ROW_NR)
typedef struct fd_map_row
{
fd_map_entry_t entry[CONFIG_FD_MAP_ROW_CN];
} fd_map_row_t;
typedef struct fd_map
{
fd_map_row_t *row[CONFIG_FD_MAP_ROW_NR];
pthread_spinlock_t lock;
uint16_t free_fd;
} fd_map_t;
static fd_map_t fd_map;
/**
* @brief 分配一个可用的fd
*
* @param svr_fd
* @param priv_fd
* @param type
* @return int
*/
int fd_map_alloc(uint32_t svr_fd, uint32_t priv_fd, enum fd_type type)
{
int alloc_fd = 0;
pthread_spin_lock(&fd_map.lock);
if (fd_map.free_fd >= FD_MAP_TOTAL)
{
// 没有可用的fd了尝试循环查找
for (int i = 0; i < CONFIG_FD_MAP_ROW_NR; i++)
{
for (int j = 0; j < CONFIG_FD_MAP_ROW_CN; j++)
{
if (fd_map.row[i]->entry[j].flags == 0)
{
alloc_fd = i * CONFIG_FD_MAP_ROW_CN + j;
goto next;
}
}
}
pthread_spin_unlock(&fd_map.lock);
// 没有可用的了
return -EAGAIN;
}
else
{
alloc_fd = fd_map.free_fd;
}
next:;
int row_inx = alloc_fd / CONFIG_FD_MAP_ROW_CN;
int inx = alloc_fd % CONFIG_FD_MAP_ROW_CN;
assert(row_inx < CONFIG_FD_MAP_ROW_NR);
if (fd_map.row[row_inx] == NULL)
{
fd_map.row[row_inx] = malloc(sizeof(fd_map_row_t));
if (fd_map.row[row_inx] == NULL)
{
pthread_spin_unlock(&fd_map.lock);
return -EAGAIN;
}
memset(fd_map.row[row_inx], 0, sizeof(fd_map_row_t));
}
assert(fd_map.row[row_inx]->entry[inx].flags == 0);
fd_map.row[row_inx]->entry[inx].flags = 1;
fd_map.row[row_inx]->entry[inx].svr_fd = svr_fd;
fd_map.row[row_inx]->entry[inx].priv_fd = priv_fd;
fd_map.row[row_inx]->entry[inx].type = type;
fd_map.free_fd++;
pthread_spin_unlock(&fd_map.lock);
return alloc_fd;
}
/**
* @brief 获取fd
*
* @param fd
* @param new_entry
* @return int
*/
int fd_map_get(int fd, fd_map_entry_t *new_entry)
{
assert(new_entry);
if (fd >= FD_MAP_TOTAL)
{
return -1;
}
int row_inx = fd / CONFIG_FD_MAP_ROW_CN;
int inx = fd % CONFIG_FD_MAP_ROW_CN;
pthread_spin_lock(&fd_map.lock);
if (fd_map.row[row_inx] == NULL)
{
pthread_spin_unlock(&fd_map.lock);
return -1;
}
*new_entry = fd_map.row[row_inx]->entry[inx];
pthread_spin_unlock(&fd_map.lock);
return 0;
}
/**
* @brief 更新fd
*
* @param fd
* @param new_entry
* @return int
*/
int fd_map_update(int fd, fd_map_entry_t *new_entry)
{
if (fd >= FD_MAP_TOTAL)
{
return -1;
}
int row_inx = fd / CONFIG_FD_MAP_ROW_CN;
int inx = fd % CONFIG_FD_MAP_ROW_CN;
pthread_spin_lock(&fd_map.lock);
int flags = fd_map.row[row_inx]->entry[inx].flags;
fd_map.row[row_inx]->entry[inx] = *new_entry;
fd_map.row[row_inx]->entry[inx].flags = flags;
pthread_spin_unlock(&fd_map.lock);
return 0;
}
/**
* @brief 释放fd
*
* @param fd
* @param ret_entry
* @return int
*/
int fd_map_free(int fd, fd_map_entry_t *ret_entry)
{
if (fd >= FD_MAP_TOTAL)
{
return -1;
}
int row_inx = fd / CONFIG_FD_MAP_ROW_CN;
int inx = fd % CONFIG_FD_MAP_ROW_CN;
pthread_spin_lock(&fd_map.lock);
if (fd_map.row[row_inx]->entry[inx].flags == 1)
{
if (ret_entry)
{
*ret_entry = fd_map.row[row_inx]->entry[inx];
}
fd_map.row[row_inx]->entry[inx].flags = 0;
if (fd_map.free_fd > fd)
{
fd_map.free_fd = fd;
}
pthread_spin_unlock(&fd_map.lock);
}
else
{
pthread_spin_unlock(&fd_map.lock);
return -1;
}
return 0;
}