mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-07 01:06:41 +08:00
Add cpul, date and unitt
This commit is contained in:
parent
ca9bdaad24
commit
a2125c2b9f
10
README.en.md
10
README.en.md
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
[](https://gitee.com/Lamdonn/varch)
|
||||||
|
[](LICENSE)
|
||||||
|
[](Lamdonn@163.com)
|
||||||
|

|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
[中文版](README.md)
|
[中文版](README.md)
|
||||||
@ -30,6 +35,7 @@ It has the characteristics of **simplicity, universality, and efficiency**, with
|
|||||||
| valloc | 01.00.00 | [link](/doc/valloc.md) | [path](./source/01_general) | Dynamic memory usage testing tool
|
| valloc | 01.00.00 | [link](/doc/valloc.md) | [path](./source/01_general) | Dynamic memory usage testing tool
|
||||||
| vlog | 01.01.00 | [link](/doc/vlog.md) | [path](./source/01_general) | Log output module
|
| vlog | 01.01.00 | [link](/doc/vlog.md) | [path](./source/01_general) | Log output module
|
||||||
| intl | 01.00.00 | [link](/doc/intl.md) | [path](./source/01_general) | Large integer arithmetic module
|
| intl | 01.00.00 | [link](/doc/intl.md) | [path](./source/01_general) | Large integer arithmetic module
|
||||||
|
| date | 01.00.00 | [link](/doc/date.md) | [path](./source/01_general) | Date calculation module, calculating date differences, printing calendars, etc
|
||||||
| vctype | 01.00.00 | [link](/doc/vctype.md) | [path](./source/02_vstd) | Similar to the C standard library ctype
|
| vctype | 01.00.00 | [link](/doc/vctype.md) | [path](./source/02_vstd) | Similar to the C standard library ctype
|
||||||
| vmath | 01.00.00 | [link](/doc/vmath.md) | [path](./source/02_vstd) | Similar to the C standard library math
|
| vmath | 01.00.00 | [link](/doc/vmath.md) | [path](./source/02_vstd) | Similar to the C standard library math
|
||||||
| vmem | 01.00.00 | [link](/doc/vmem.md) | [path](./source/02_vstd) | Simple implementation of memory pool
|
| vmem | 01.00.00 | [link](/doc/vmem.md) | [path](./source/02_vstd) | Simple implementation of memory pool
|
||||||
@ -62,6 +68,10 @@ It has the characteristics of **simplicity, universality, and efficiency**, with
|
|||||||
| json | 01.00.00 | [link](/doc/json.md) | [path](./source/05_parser) | JSON file parsing generator
|
| json | 01.00.00 | [link](/doc/json.md) | [path](./source/05_parser) | JSON file parsing generator
|
||||||
| txls | 01.00.00 | [link](/doc/txls.md) | [path](./source/05_parser) | TXLS file parsing generator
|
| txls | 01.00.00 | [link](/doc/txls.md) | [path](./source/05_parser) | TXLS file parsing generator
|
||||||
| xml | 01.00.00 | [link](/doc/xml.md) | [path](./source/05_parser) | XML file parsing generator
|
| xml | 01.00.00 | [link](/doc/xml.md) | [path](./source/05_parser) | XML file parsing generator
|
||||||
|
| ramt | 01.00.00 | [link](/doc/ramt.md) | [path](./source/06_performance) | RAM test module
|
||||||
|
| romt | 01.00.00 | [link](/doc/romt.md) | [path](./source/06_performance) | ROM test module
|
||||||
|
| cpul | 01.00.00 | [link](/doc/cpul.md) | [path](./source/06_performance) | CPU load test module, including obtaining and increasing load
|
||||||
|
| unitt | 01.00.00 | [link](/doc/unitt.md) | [path](./source/06_performance) | Simple unit test module
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
10
README.md
10
README.md
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
[](https://gitee.com/Lamdonn/varch)
|
||||||
|
[](LICENSE)
|
||||||
|
[](Lamdonn@163.com)
|
||||||
|

|
||||||
|
|
||||||
## 介绍
|
## 介绍
|
||||||
|
|
||||||
[English version](README.en.md)
|
[English version](README.en.md)
|
||||||
@ -30,6 +35,7 @@ varch(we-architecture,意为我们的框架库)是嵌入式C语言常用
|
|||||||
| valloc | 01.00.00 | [link](/doc/valloc.md) | [path](./source/01_general) | 动态内存使用测试工具
|
| valloc | 01.00.00 | [link](/doc/valloc.md) | [path](./source/01_general) | 动态内存使用测试工具
|
||||||
| vlog | 01.01.00 | [link](/doc/vlog.md) | [path](./source/01_general) | 日志输出模块
|
| vlog | 01.01.00 | [link](/doc/vlog.md) | [path](./source/01_general) | 日志输出模块
|
||||||
| intl | 01.00.00 | [link](/doc/intl.md) | [path](./source/01_general) | 大型整数运算模块
|
| intl | 01.00.00 | [link](/doc/intl.md) | [path](./source/01_general) | 大型整数运算模块
|
||||||
|
| date | 01.00.00 | [link](/doc/date.md) | [path](./source/01_general) | 日期计算模块,计算日期差、打印日历等
|
||||||
| vctype | 01.00.00 | [link](/doc/vctype.md) | [path](./source/02_vstd) | 类似于C标准库ctype
|
| vctype | 01.00.00 | [link](/doc/vctype.md) | [path](./source/02_vstd) | 类似于C标准库ctype
|
||||||
| vmath | 01.00.00 | [link](/doc/vmath.md) | [path](./source/02_vstd) | 类似于C标准库math
|
| vmath | 01.00.00 | [link](/doc/vmath.md) | [path](./source/02_vstd) | 类似于C标准库math
|
||||||
| vmem | 01.00.00 | [link](/doc/vmem.md) | [path](./source/02_vstd) | 内存池的简单实现
|
| vmem | 01.00.00 | [link](/doc/vmem.md) | [path](./source/02_vstd) | 内存池的简单实现
|
||||||
@ -62,6 +68,10 @@ varch(we-architecture,意为我们的框架库)是嵌入式C语言常用
|
|||||||
| json | 01.00.00 | [link](/doc/json.md) | [path](./source/05_parser) | JSON文件解析生成器
|
| json | 01.00.00 | [link](/doc/json.md) | [path](./source/05_parser) | JSON文件解析生成器
|
||||||
| txls | 01.00.00 | [link](/doc/txls.md) | [path](./source/05_parser) | TXLS文件解析生成器
|
| txls | 01.00.00 | [link](/doc/txls.md) | [path](./source/05_parser) | TXLS文件解析生成器
|
||||||
| xml | 01.00.00 | [link](/doc/xml.md) | [path](./source/05_parser) | XML文件解析生成器
|
| xml | 01.00.00 | [link](/doc/xml.md) | [path](./source/05_parser) | XML文件解析生成器
|
||||||
|
| ramt | 01.00.00 | [link](/doc/ramt.md) | [path](./source/06_performance) | RAM测试模块
|
||||||
|
| romt | 01.00.00 | [link](/doc/romt.md) | [path](./source/06_performance) | ROM测试模块
|
||||||
|
| cpul | 01.00.00 | [link](/doc/cpul.md) | [path](./source/06_performance) | CPU负载测试模块,包含获取和增加负载
|
||||||
|
| unitt | 01.00.00 | [link](/doc/unitt.md) | [path](./source/06_performance) | 简易的单元测试模块
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
|
|||||||
8
makefile
8
makefile
@ -58,6 +58,12 @@ include $(TESTSPACE)/test.mk
|
|||||||
TESTSRC += $(APPLICATION_PATH)/main.c
|
TESTSRC += $(APPLICATION_PATH)/main.c
|
||||||
TESTSRC += $(TEST_SRC)
|
TESTSRC += $(TEST_SRC)
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
UNAME := Windows
|
||||||
|
else
|
||||||
|
UNAME := $(shell uname -s)
|
||||||
|
endif
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
### recipes
|
### recipes
|
||||||
##################################################################################
|
##################################################################################
|
||||||
@ -79,7 +85,7 @@ LIBP ?= /usr
|
|||||||
|
|
||||||
# link
|
# link
|
||||||
${TARP}:$(OBJS)
|
${TARP}:$(OBJS)
|
||||||
mkdir -p $(dir $@)
|
@ mkdir -p $(dir $@)
|
||||||
@ $(CC) $(CFLAG) $(OBJS) -o $(TARP) $(LIBS)
|
@ $(CC) $(CFLAG) $(OBJS) -o $(TARP) $(LIBS)
|
||||||
|
|
||||||
# compile
|
# compile
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include "init.h"
|
#include "init.h"
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
#include <windows.h>
|
||||||
#elif defined(__unix)
|
#elif defined(__unix)
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#endif
|
#endif
|
||||||
@ -39,9 +40,9 @@ static int kbhit(void)
|
|||||||
if (ch != EOF)
|
if (ch != EOF)
|
||||||
{
|
{
|
||||||
ungetc(ch, stdin);
|
ungetc(ch, stdin);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -67,8 +68,8 @@ static int into(int argc, char *argv[])
|
|||||||
|
|
||||||
static void console_main(void)
|
static void console_main(void)
|
||||||
{
|
{
|
||||||
int c;
|
int c = 0;
|
||||||
if (!kbhit())
|
if (kbhit())
|
||||||
{
|
{
|
||||||
c = getchar();
|
c = getchar();
|
||||||
#if CONSOLE_DEBUG == 1
|
#if CONSOLE_DEBUG == 1
|
||||||
@ -124,6 +125,7 @@ void console_init(void)
|
|||||||
if (!console_task) return;
|
if (!console_task) return;
|
||||||
|
|
||||||
printf("console init! task<%d>!\r\n", console_task);
|
printf("console init! task<%d>!\r\n", console_task);
|
||||||
|
printf("Press `Enter` to enter the console, input `cmd -h` to get help!\r\n");
|
||||||
|
|
||||||
/* Export into command */
|
/* Export into command */
|
||||||
command_export("into", into);
|
command_export("into", into);
|
||||||
|
|||||||
234
source/01_general/date.c
Normal file
234
source/01_general/date.c
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file date.c
|
||||||
|
* \unit date
|
||||||
|
* \brief This is a simple date calculate module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v1.0.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#include "date.h"
|
||||||
|
|
||||||
|
// TODO: 1582.10.04 - 1582.10.15
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check if a year is a leap year.
|
||||||
|
* \param[in] year: The year to check.
|
||||||
|
* \return 1 if the year is a leap year, 0 otherwise.
|
||||||
|
*/
|
||||||
|
uint8_t date_isleap(uint16_t year)
|
||||||
|
{
|
||||||
|
return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the number of days in a century.
|
||||||
|
* \param[in] century: The century to evaluate.
|
||||||
|
* \return Number of days in the given century.
|
||||||
|
*/
|
||||||
|
uint32_t date_century_days(uint16_t century)
|
||||||
|
{
|
||||||
|
if (century == 0) return 0u; // No days in century 0
|
||||||
|
return (century % 4 == 0) ? 36525u : 36524u; // 25 leap years in 400 years
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the number of days in a year.
|
||||||
|
* \param[in] year: The year to evaluate.
|
||||||
|
* \return Number of days in the given year.
|
||||||
|
*/
|
||||||
|
uint32_t date_year_days(uint16_t year)
|
||||||
|
{
|
||||||
|
if (year == 0) return 0u; // No days in year 0
|
||||||
|
return date_isleap(year) ? 366u : 365u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the number of days in a month of a given year.
|
||||||
|
* \param[in] year: The year of the month.
|
||||||
|
* \param[in] month: The month to evaluate (1-12).
|
||||||
|
* \return Number of days in the specified month of the specified year.
|
||||||
|
*/
|
||||||
|
uint32_t date_month_days(uint16_t year, uint8_t month)
|
||||||
|
{
|
||||||
|
if (year == 0) return 0; // No valid month days for year 0
|
||||||
|
switch (month)
|
||||||
|
{
|
||||||
|
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
|
||||||
|
return 31; // Months with 31 days
|
||||||
|
case 4: case 6: case 9: case 11:
|
||||||
|
return 30; // Months with 30 days
|
||||||
|
case 2:
|
||||||
|
return date_isleap(year) ? 29 : 28; // February days depending on leap year
|
||||||
|
default:
|
||||||
|
return 0; // Invalid month
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Validate a date.
|
||||||
|
* \param[in] date: The date structure to validate.
|
||||||
|
* \return 1 if the date is valid, 0 otherwise.
|
||||||
|
*/
|
||||||
|
uint8_t date_isvalid(DATE date)
|
||||||
|
{
|
||||||
|
if (date.year == 0 || date.month == 0 || date.day == 0) return 0; // Year, month or day 0 is not valid
|
||||||
|
return (date_month_days(date.year, date.month) >= date.day);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Calculate the total number of days from a given date to a base date.
|
||||||
|
* \param[in] date: The date to calculate the total days for.
|
||||||
|
* \return Total number of days from a base date to the given date, 0 if invalid.
|
||||||
|
*/
|
||||||
|
uint32_t date_current_days(DATE date)
|
||||||
|
{
|
||||||
|
uint32_t days = 0;
|
||||||
|
uint16_t year = 1;
|
||||||
|
uint8_t month = 1;
|
||||||
|
|
||||||
|
// Validate the input date; return 0 if invalid
|
||||||
|
if (!date_isvalid(date)) return 0;
|
||||||
|
|
||||||
|
// Count days for complete centuries
|
||||||
|
for ( ; year + 2000 <= date.year; year += 2000) days += 730485u;
|
||||||
|
// Count days for complete centuries within the current century
|
||||||
|
for ( ; year + 100 <= date.year; year += 100) days += date_century_days((year / 100) + 1);
|
||||||
|
// Count days for complete years within the current century
|
||||||
|
for ( ; year + 1 <= date.year; year++) days += date_year_days(year);
|
||||||
|
// Count days for completed months in the current year
|
||||||
|
for ( ; month < date.month; month++) days += date_month_days(date.year, month);
|
||||||
|
// Add the days of the current month
|
||||||
|
days += date.day;
|
||||||
|
|
||||||
|
return days;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the week number of a given date based on the total days.
|
||||||
|
* \param[in] date: The date to evaluate.
|
||||||
|
* \return The week number [1, 7] for the specified date (Mon | Tue | Wed | Thu | Fri | Sat | Sun), 0 if invalid.
|
||||||
|
*/
|
||||||
|
uint32_t date_get_week(DATE date)
|
||||||
|
{
|
||||||
|
#define bias 0 // Adjust to week start
|
||||||
|
uint32_t days = date_current_days(date);
|
||||||
|
uint32_t week = 0;
|
||||||
|
|
||||||
|
// If days is 0, return 0 indicating invalid date
|
||||||
|
if (days == 0) return 0;
|
||||||
|
|
||||||
|
week = (days + bias) % 7;
|
||||||
|
if (week == 0) week = 7;
|
||||||
|
|
||||||
|
return week;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Calculate the difference in days between two dates.
|
||||||
|
* \param[in] date1: The first date.
|
||||||
|
* \param[in] date2: The second date.
|
||||||
|
* \return The difference in days between the two dates. Returns 0 if either date is invalid.
|
||||||
|
*/
|
||||||
|
int32_t date_diff_days(DATE date1, DATE date2)
|
||||||
|
{
|
||||||
|
uint32_t days1 = date_current_days(date1);
|
||||||
|
uint32_t days2 = date_current_days(date2); // Corrected to use date2
|
||||||
|
|
||||||
|
// Return 0 if either date is invalid
|
||||||
|
if (days1 == 0 || days2 == 0) return 0;
|
||||||
|
|
||||||
|
return (int32_t)(days1 - days2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Convert a number of days to a DATE structure.
|
||||||
|
* \param[in] days: The number of days to convert.
|
||||||
|
* \return A DATE structure representing the converted days.
|
||||||
|
*/
|
||||||
|
DATE date_from_days(uint32_t days)
|
||||||
|
{
|
||||||
|
DATE date = {1, 1, 1}; // Initialize to base date (1/1/1)
|
||||||
|
uint32_t tdays = 0;
|
||||||
|
|
||||||
|
// Return zero date if days are 0
|
||||||
|
if (days == 0) return DATE(0,0,0);
|
||||||
|
|
||||||
|
// Convert days to years
|
||||||
|
for ( ; days > 730485; days -= 730485) date.year += 2000;
|
||||||
|
for ( ; days > (tdays = date_century_days((date.year / 100) + 1)); days -= tdays) date.year += 100;
|
||||||
|
for ( ; days > (tdays = date_year_days(date.year)); days -= tdays) date.year++;
|
||||||
|
for ( ; days > (tdays = date_month_days(date.year, date.month)); days -= tdays) date.month++;
|
||||||
|
date.day = days;
|
||||||
|
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Offset a date by a certain number of days.
|
||||||
|
* \param[in] date: The date to offset.
|
||||||
|
* \param[in] days: The number of days to offset (can be negative).
|
||||||
|
* \return A new DATE structure after applying the offset, or a zero date if invalid.
|
||||||
|
*/
|
||||||
|
DATE date_offset(DATE date, int32_t days)
|
||||||
|
{
|
||||||
|
if (!date_isvalid(date)) return DATE(0,0,0); // Return zero date if invalid
|
||||||
|
return date_from_days(date_current_days(date) + days);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Show the calendar for a specific month and year.
|
||||||
|
* \param[in] year: The year of the calendar to show.
|
||||||
|
* \param[in] month: The month of the calendar to show.
|
||||||
|
*/
|
||||||
|
void date_show(uint16_t year, uint8_t month)
|
||||||
|
{
|
||||||
|
DATE date = {year, month, 1};
|
||||||
|
uint32_t days;
|
||||||
|
uint32_t tday = 1;
|
||||||
|
uint32_t week = 0;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
days = date_month_days(year, month);
|
||||||
|
if (days == 0)
|
||||||
|
{
|
||||||
|
printf("[ERROR] Invalid date!\r\n");
|
||||||
|
return; // Exit if the date is invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
week = date_get_week(date) % 7; // Get the starting day of the week
|
||||||
|
|
||||||
|
// Print the calendar header
|
||||||
|
printf("+-----------------------------------------+\r\n");
|
||||||
|
len = printf("| %04d/%02d", year, month); while (len++ < 42) printf(" "); printf("|\r\n");
|
||||||
|
printf("+-----------------------------------------+\r\n");
|
||||||
|
printf("| Sun | Mon | Tue | Wed | Thu | Fri | Sat |\r\n");
|
||||||
|
printf("+-----------------------------------------+\r\n");
|
||||||
|
|
||||||
|
// Print the days of the month
|
||||||
|
while (tday <= days)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
if (i == 0) printf("|"); // Start of the week
|
||||||
|
|
||||||
|
if (i == week && tday <= days)
|
||||||
|
{
|
||||||
|
printf(" %3u |", tday); // Print the current day
|
||||||
|
tday++;
|
||||||
|
week = (week + 1) % 7; // Move to the next week day
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" |"); // Empty space for days not in the current month
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 6) printf("\r\n"); // End of the week
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("+-----------------------------------------+\r\n"); // End of the calendar
|
||||||
|
}
|
||||||
120
source/01_general/date.h
Normal file
120
source/01_general/date.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file date.h
|
||||||
|
* \unit date
|
||||||
|
* \brief This is a simple date calculate module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v1.0.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#ifndef __date_H
|
||||||
|
#define __date_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Version infomation */
|
||||||
|
|
||||||
|
#define DATE_V_MAJOR 1
|
||||||
|
#define DATE_V_MINOR 0
|
||||||
|
#define DATE_V_PATCH 0
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t year; /**< Year component of the date */
|
||||||
|
uint8_t month; /**< Month component of the date */
|
||||||
|
uint8_t day; /**< Day component of the date */
|
||||||
|
} DATE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Macro to create a DATE structure instance.
|
||||||
|
* \param[in] y: Year component of the date.
|
||||||
|
* \param[in] m: Month component of the date (1-12).
|
||||||
|
* \param[in] d: Day component of the date (1-31 depending on the month).
|
||||||
|
* \return A DATE structure initialized with the specified year, month, and day.
|
||||||
|
*/
|
||||||
|
#define DATE(y, m, d) (DATE){.year=(y), .month=(m), .day=(d)}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check if a year is a leap year.
|
||||||
|
* \param[in] year: The year to check.
|
||||||
|
* \return 1 if the year is a leap year, 0 otherwise.
|
||||||
|
*/
|
||||||
|
uint8_t date_isleap(uint16_t year);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Validate a date.
|
||||||
|
* \param[in] date: The date structure to validate.
|
||||||
|
* \return 1 if the date is valid, 0 otherwise.
|
||||||
|
*/
|
||||||
|
uint8_t date_isvalid(DATE date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the number of days in a century.
|
||||||
|
* \param[in] century: The century to evaluate.
|
||||||
|
* \return Number of days in the given century.
|
||||||
|
*/
|
||||||
|
uint32_t date_century_days(uint16_t century);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the number of days in a year.
|
||||||
|
* \param[in] year: The year to evaluate.
|
||||||
|
* \return Number of days in the given year.
|
||||||
|
*/
|
||||||
|
uint32_t date_year_days(uint16_t year);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the number of days in a month of a given year.
|
||||||
|
* \param[in] year: The year of the month.
|
||||||
|
* \param[in] month: The month to evaluate (1-12).
|
||||||
|
* \return Number of days in the specified month of the specified year.
|
||||||
|
*/
|
||||||
|
uint32_t date_month_days(uint16_t year, uint8_t month);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the week number of a given date based on the total days.
|
||||||
|
* \param[in] date: The date to evaluate.
|
||||||
|
* \return The week number [1, 7] for the specified date (Mon | Tue | Wed | Thu | Fri | Sat | Sun), 0 if invalid.
|
||||||
|
*/
|
||||||
|
uint32_t date_get_week(DATE date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Calculate the total number of days from a given date to a base date.
|
||||||
|
* \param[in] date: The date to calculate the total days for.
|
||||||
|
* \return Total number of days from a base date to the given date, 0 if invalid.
|
||||||
|
*/
|
||||||
|
uint32_t date_current_days(DATE date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Calculate the difference in days between two dates.
|
||||||
|
* \param[in] date1: The first date.
|
||||||
|
* \param[in] date2: The second date.
|
||||||
|
* \return The difference in days between the two dates. Returns 0 if either date is invalid.
|
||||||
|
*/
|
||||||
|
int32_t date_diff_days(DATE date1, DATE date2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Convert a number of days to a DATE structure.
|
||||||
|
* \param[in] days: The number of days to convert.
|
||||||
|
* \return A DATE structure representing the converted days.
|
||||||
|
*/
|
||||||
|
DATE date_from_days(uint32_t days);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Offset a date by a certain number of days.
|
||||||
|
* \param[in] date: The date to offset.
|
||||||
|
* \param[in] days: The number of days to offset (can be negative).
|
||||||
|
* \return A new DATE structure after applying the offset, or a zero date if invalid.
|
||||||
|
*/
|
||||||
|
DATE date_offset(DATE date, int32_t days);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Show the calendar for a specific month and year.
|
||||||
|
* \param[in] year: The year of the calendar to show.
|
||||||
|
* \param[in] month: The month of the calendar to show.
|
||||||
|
*/
|
||||||
|
void date_show(uint16_t year, uint8_t month);
|
||||||
|
|
||||||
|
#endif
|
||||||
211
source/06_performance/cpul.c
Normal file
211
source/06_performance/cpul.c
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file cpul.c
|
||||||
|
* \unit cpul
|
||||||
|
* \brief This is a simple cpuload module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v1.0.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#include "cpul.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Buffer for CRC calculation, initialized with some values
|
||||||
|
uint8_t calbuffer[CPUL_GEN_BSIZE] = {'A', 'B', 0};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adjust the refined load based on current and target loads.
|
||||||
|
*
|
||||||
|
* This function controls the refined load adjustment by comparing
|
||||||
|
* the current load with the target load and modifying the refined
|
||||||
|
* load accordingly.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \return Returns the adjusted refined load value.
|
||||||
|
*/
|
||||||
|
static uint32_t controller(CPUL *cpul)
|
||||||
|
{
|
||||||
|
// If the current load is less than the target load
|
||||||
|
if (cpul->ctrl.cload < cpul->ctrl.tload)
|
||||||
|
{
|
||||||
|
// If adding resolution to refined load does not exceed its current value
|
||||||
|
if (cpul->ctrl.refine + cpul->resolution > cpul->ctrl.refine)
|
||||||
|
{
|
||||||
|
// Increase the refined load by the resolution value
|
||||||
|
cpul->ctrl.refine += cpul->resolution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the current load is greater than target load + 1
|
||||||
|
else if (cpul->ctrl.cload > (cpul->ctrl.tload + 1))
|
||||||
|
{
|
||||||
|
// If the refined load is greater than or equal to the resolution
|
||||||
|
if (cpul->ctrl.refine >= cpul->resolution)
|
||||||
|
{
|
||||||
|
// Decrease the refined load by the resolution value
|
||||||
|
cpul->ctrl.refine -= cpul->resolution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpul->ctrl.refine; // Return the adjusted refined load
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Calculate CRC8 checksum.
|
||||||
|
*
|
||||||
|
* This function computes the CRC8 checksum for a given data buffer.
|
||||||
|
* It iterates through each byte of data and processes it to generate
|
||||||
|
* the CRC value.
|
||||||
|
*
|
||||||
|
* \param[in] data: Pointer to the data buffer.
|
||||||
|
* \param[in] len: Length of the data buffer.
|
||||||
|
* \return Returns the calculated CRC8 value.
|
||||||
|
*/
|
||||||
|
static uint8_t crc8(uint8_t *data, uint32_t len)
|
||||||
|
{
|
||||||
|
uint8_t i; // Loop index for bit processing
|
||||||
|
uint8_t crc = 0; // Initialize CRC value to 0
|
||||||
|
while (len--) // Process each byte in the data buffer
|
||||||
|
{
|
||||||
|
crc ^= *data++; // XOR the current byte with the CRC value
|
||||||
|
for (i = 0; i < 8; i++) // Process each bit of the byte
|
||||||
|
{
|
||||||
|
if (crc & 0x80) // If the highest bit of CRC is set
|
||||||
|
crc = (crc << 1) ^ 0x07; // Shift left and XOR with the polynomial
|
||||||
|
else
|
||||||
|
crc <<= 1; // Just shift left if the highest bit is not set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc; // Return the calculated CRC8 value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Update the granularity of the load control.
|
||||||
|
*
|
||||||
|
* This function updates the calbuffer values based on the refined load
|
||||||
|
* using CRC8 checksum for each iteration specified by the input parameter.
|
||||||
|
*
|
||||||
|
* \param[in] input: Number of iterations to update the buffer.
|
||||||
|
* \return none.
|
||||||
|
*/
|
||||||
|
static void granularity(uint32_t input)
|
||||||
|
{
|
||||||
|
// Loop through the specified number of iterations
|
||||||
|
for (uint32_t i = 0; i < input; i++)
|
||||||
|
{
|
||||||
|
// Update calbuffer with a CRC8 value calculated from the current buffer
|
||||||
|
calbuffer[calbuffer[0] % sizeof(calbuffer)] = crc8(calbuffer, sizeof(calbuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the CPUL instance.
|
||||||
|
*
|
||||||
|
* This function initializes the CPUL structure to default values
|
||||||
|
* and checks for valid pointers.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_init(CPUL *cpul)
|
||||||
|
{
|
||||||
|
// Check if the cpul pointer is valid
|
||||||
|
if (!cpul) return CPUL_E_INVALID;
|
||||||
|
// Check if the raw function pointer is valid
|
||||||
|
if (!cpul->raw) return CPUL_E_RAW;
|
||||||
|
|
||||||
|
cpul->ctrl.cload = 0xFFFF; // Set current load to untested value
|
||||||
|
cpul->ctrl.tload = 0; // Default target load to zero (no load increase)
|
||||||
|
cpul->ctrl.refine = 0; // Initialize refined load
|
||||||
|
|
||||||
|
return CPUL_E_OK; // Initialization successful
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the current CPU load.
|
||||||
|
*
|
||||||
|
* This function retrieves the current load from the CPUL instance
|
||||||
|
* and checks for validity of parameters and state.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \param[out] load: Pointer to store the current load value.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_get(CPUL *cpul, uint16_t *load)
|
||||||
|
{
|
||||||
|
// Check if the cpul pointer is valid
|
||||||
|
if (!cpul) return CPUL_E_INVALID;
|
||||||
|
// Check if the raw function pointer is valid
|
||||||
|
if (!cpul->raw) return CPUL_E_RAW;
|
||||||
|
// Check if the load parameter is valid
|
||||||
|
if (!load) return CPUL_E_PARA;
|
||||||
|
|
||||||
|
// If current load is still untested, return an error
|
||||||
|
if (cpul->ctrl.cload == 0xFFFF) return CPUL_E_NTEST;
|
||||||
|
// Check if the current load exceeds the maximum allowed value
|
||||||
|
if (cpul->ctrl.cload > 10000) return CPUL_E_OVER;
|
||||||
|
|
||||||
|
*load = cpul->ctrl.cload; // Retrieve the current load value
|
||||||
|
|
||||||
|
return CPUL_E_OK; // Success
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the target CPU load.
|
||||||
|
*
|
||||||
|
* This function sets the target load for the CPUL instance and checks for valid parameters.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \param[in] load: Target load value to set.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_set(CPUL *cpul, uint16_t load)
|
||||||
|
{
|
||||||
|
// Check if the cpul pointer is valid
|
||||||
|
if (!cpul) return CPUL_E_INVALID;
|
||||||
|
// Check if the raw function pointer is valid
|
||||||
|
if (!cpul->raw) return CPUL_E_RAW;
|
||||||
|
// Check if the load parameter is zero
|
||||||
|
if (!load) return CPUL_E_PARA;
|
||||||
|
|
||||||
|
// Check if the load exceeds the maximum allowed value
|
||||||
|
if (load > 10000) return CPUL_E_OVER;
|
||||||
|
|
||||||
|
cpul->ctrl.tload = load; // Set the target load
|
||||||
|
|
||||||
|
return CPUL_E_OK; // Success
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Execute a CPUL management task.
|
||||||
|
*
|
||||||
|
* This function executes a task to manage the CPU load based on
|
||||||
|
* the current and target load values.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_task(CPUL *cpul)
|
||||||
|
{
|
||||||
|
// Check if the cpul pointer is valid
|
||||||
|
if (!cpul) return CPUL_E_INVALID;
|
||||||
|
// Check if the raw function pointer is valid
|
||||||
|
if (!cpul->raw) return CPUL_E_RAW;
|
||||||
|
|
||||||
|
// Call the raw function to get the current load value
|
||||||
|
cpul->ctrl.cload = cpul->raw(cpul->coreid);
|
||||||
|
|
||||||
|
// If the target load is not zero, perform load management
|
||||||
|
if (cpul->ctrl.tload != 0)
|
||||||
|
{
|
||||||
|
// Adjust the refined load based on current and target load
|
||||||
|
cpul->ctrl.refine = controller(cpul);
|
||||||
|
// Update granularity based on the refined load
|
||||||
|
granularity(cpul->ctrl.refine);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CPUL_E_OK; // Success
|
||||||
|
}
|
||||||
100
source/06_performance/cpul.h
Normal file
100
source/06_performance/cpul.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file cpul.h
|
||||||
|
* \unit cpul
|
||||||
|
* \brief This is a simple cpuload module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v1.0.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#ifndef __cpul_H
|
||||||
|
#define __cpul_H
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
/* Version infomation */
|
||||||
|
#define CPUL_V_MAJOR 0
|
||||||
|
#define CPUL_V_MINOR 1
|
||||||
|
#define CPUL_V_PATcH 0
|
||||||
|
|
||||||
|
#define CPUL_GEN_BSIZE 4
|
||||||
|
|
||||||
|
#define CPUL_E_OK 0 // Success
|
||||||
|
#define CPUL_E_INVALID 1 // Invalid `CPUL` pointer
|
||||||
|
#define CPUL_E_RAW 2 // Invalid raw function
|
||||||
|
#define CPUL_E_PARA 3 // Invalid parameter
|
||||||
|
#define CPUL_E_NTEST 4 // CPUL load testing has not started
|
||||||
|
#define CPUL_E_OVER 5 // CPUL load exceeds range
|
||||||
|
|
||||||
|
typedef uint16_t (*cpul_raw_t)(uint8_t coreid); // Type definition for the raw CPUL load function
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Structure to control CPUL load parameters.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t refine; ///< Refined load value
|
||||||
|
uint16_t cload; ///< Current load value
|
||||||
|
uint16_t tload; ///< Target load value
|
||||||
|
} CPUL_CTRL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Structure to represent a CPU Load Manager.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t coreid; ///< Core ID
|
||||||
|
cpul_raw_t raw; ///< Pointer to the raw CPUL load function
|
||||||
|
uint32_t resolution; ///< Resolution of the load control
|
||||||
|
CPUL_CTRL ctrl; ///< Control structure for CPUL management
|
||||||
|
} CPUL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initialize the CPUL instance.
|
||||||
|
*
|
||||||
|
* This function initializes the CPUL structure to default values
|
||||||
|
* and checks for valid pointers.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_init(CPUL *cpul);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the current CPU load.
|
||||||
|
*
|
||||||
|
* This function retrieves the current load from the CPUL instance
|
||||||
|
* and checks for validity of parameters and state.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \param[out] load: Pointer to store the current load value.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_get(CPUL *cpul, uint16_t *load);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the target CPU load.
|
||||||
|
*
|
||||||
|
* This function sets the target load for the CPUL instance and checks for valid parameters.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \param[in] load: Target load value to set.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_set(CPUL *cpul, uint16_t load);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Execute a CPUL management task.
|
||||||
|
*
|
||||||
|
* This function executes a task to manage the CPU load based on
|
||||||
|
* the current and target load values.
|
||||||
|
*
|
||||||
|
* \param[in] cpul: Pointer to the CPUL instance.
|
||||||
|
* \return Returns CPUL_E_OK on success, otherwise an error code.
|
||||||
|
*/
|
||||||
|
int cpul_task(CPUL *cpul);
|
||||||
|
|
||||||
|
#endif
|
||||||
306
source/06_performance/unitt.c
Normal file
306
source/06_performance/unitt.c
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file unitt.c
|
||||||
|
* \unit unitt
|
||||||
|
* \brief This is a simple unit test module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v1.0.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#include "unitt.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a condition is true.
|
||||||
|
*
|
||||||
|
* This function checks if the given condition is true. If it is false,
|
||||||
|
* it outputs an assertion failure message and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] condition: The condition to evaluate.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_true(int condition, const char* message)
|
||||||
|
{
|
||||||
|
if (!condition)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s\n", message);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a condition is false.
|
||||||
|
*
|
||||||
|
* This function checks if the given condition is false. If it is true,
|
||||||
|
* it outputs an assertion failure message and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] condition: The condition to evaluate.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_false(int condition, const char* message)
|
||||||
|
{
|
||||||
|
if (condition)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s\n", message);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two integers are equal.
|
||||||
|
*
|
||||||
|
* This function checks whether the expected and actual values are equal.
|
||||||
|
* If they are not equal, it outputs an assertion failure message with
|
||||||
|
* both values and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] expected: The expected value.
|
||||||
|
* \param[in] actual: The actual value.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_equal(int expected, int actual, const char* message)
|
||||||
|
{
|
||||||
|
if (expected != actual)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s (Expected: %d, Actual: %d)\n", message, expected, actual);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two integers are not equal.
|
||||||
|
*
|
||||||
|
* This function checks whether the expected and actual values are not equal.
|
||||||
|
* If they are equal, it outputs an assertion failure message and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] expected: The expected value.
|
||||||
|
* \param[in] actual: The actual value.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_nequal(int expected, int actual, const char* message)
|
||||||
|
{
|
||||||
|
if (expected == actual)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s (Expected not equal to Actual)\n", message);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a pointer is NULL.
|
||||||
|
*
|
||||||
|
* This function checks whether the given pointer is NULL. If it is not NULL,
|
||||||
|
* it outputs an assertion failure message with the pointer's value and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] pointer: The pointer to evaluate.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_null(void* pointer, const char* message)
|
||||||
|
{
|
||||||
|
if (pointer != NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s (Expected NULL, Actual: %p)\n", message, pointer);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a pointer is not NULL.
|
||||||
|
*
|
||||||
|
* This function checks whether the given pointer is not NULL. If it is NULL,
|
||||||
|
* it outputs an assertion failure message and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] pointer: The pointer to evaluate.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_nnull(void* pointer, const char* message)
|
||||||
|
{
|
||||||
|
if (pointer == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s (Expected non-NULL, Actual: NULL)\n", message);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two floats are approximately equal.
|
||||||
|
*
|
||||||
|
* This function checks whether the expected and actual float values are approximately equal
|
||||||
|
* within a given epsilon range. If they are not, it outputs an assertion failure message
|
||||||
|
* with both values and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] expected: The expected float value.
|
||||||
|
* \param[in] actual: The actual float value.
|
||||||
|
* \param[in] epsilon: The acceptable difference between the two values.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_float(float expected, float actual, float epsilon, const char* message)
|
||||||
|
{
|
||||||
|
if (fabs(expected - actual) > epsilon)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s (Expected: %.6f, Actual: %.6f)\n", message, expected, actual);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two strings are equal.
|
||||||
|
*
|
||||||
|
* This function checks whether the expected and actual strings are equal.
|
||||||
|
* If they are not equal, it outputs an assertion failure message with both strings
|
||||||
|
* and returns a failure code.
|
||||||
|
*
|
||||||
|
* \param[in] expected: The expected string.
|
||||||
|
* \param[in] actual: The actual string.
|
||||||
|
* \param[in] message: The message to display if the assertion fails.
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
|
||||||
|
*/
|
||||||
|
int unitt_det_string(const char* expected, const char* actual, const char* message)
|
||||||
|
{
|
||||||
|
if (strcmp(expected, actual) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Assertion Failed: %s (Expected: '%s', Actual: '%s')\n", message, expected, actual);
|
||||||
|
return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Handle a test failure.
|
||||||
|
*
|
||||||
|
* This function is called when a test fails. It outputs the name of the failed test.
|
||||||
|
*
|
||||||
|
* \param[in] name: The name of the failed test.
|
||||||
|
* \return Returns UNITT_E_OK.
|
||||||
|
*/
|
||||||
|
int unitt_fail_handle(const char* name)
|
||||||
|
{
|
||||||
|
printf("Failure in test: %s\n", name);
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Execute a test suite.
|
||||||
|
*
|
||||||
|
* This function runs all the test cases within the provided test suites.
|
||||||
|
* It measures the execution time for each test and outputs a summary report.
|
||||||
|
*
|
||||||
|
* \param[in] suites: Array of test suites to execute.
|
||||||
|
* \param[in] count: Number of test suites in the array.
|
||||||
|
* \param[in] failcb: Callback function to handle test failures.
|
||||||
|
* \param[in] specific: Specific test name to execute (NULL for all).
|
||||||
|
* \param[in] filename: Output filename for results (NULL for stdout).
|
||||||
|
* \return none.
|
||||||
|
*/
|
||||||
|
void unitt_execute(UNITT* suites, uint32_t count, unitt_failcb_t failcb, const char* specific, const char* filename)
|
||||||
|
{
|
||||||
|
UNITT* suite = NULL;
|
||||||
|
UNITT_TCASE* tcase = NULL;
|
||||||
|
uint64_t cstart = 0, cend = 0; // Record the start and end time of the test
|
||||||
|
|
||||||
|
FILE* output = stdout; // Default output to standard output
|
||||||
|
if (filename != NULL)
|
||||||
|
{
|
||||||
|
output = fopen(filename, "w");
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
perror("Failed to open output file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over each test suite
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
suite = &suites[i];
|
||||||
|
|
||||||
|
fprintf(output, "Running test suite: %s\n", suite->name);
|
||||||
|
|
||||||
|
// Iterate over each test case
|
||||||
|
for (int j = 0; j < suite->count; j++)
|
||||||
|
{
|
||||||
|
tcase = &suite->tests[j];
|
||||||
|
|
||||||
|
if (specific && strcmp(tcase->name, specific) != 0)
|
||||||
|
{
|
||||||
|
continue; // Skip non-matching tests
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute setup function before the test
|
||||||
|
if (tcase->setup) tcase->setup();
|
||||||
|
|
||||||
|
// Record start time
|
||||||
|
if (suite->clock) cstart = suite->clock();
|
||||||
|
|
||||||
|
// Execute test function
|
||||||
|
if (UNITT_E_OK == tcase->func())
|
||||||
|
{
|
||||||
|
tcase->passed++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (failcb) failcb(tcase->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record end time
|
||||||
|
if (suite->clock) cend = suite->clock();
|
||||||
|
|
||||||
|
// Accumulate the time taken for the test
|
||||||
|
if (suite->clock) tcase->time += (cend - cstart);
|
||||||
|
|
||||||
|
// Execute teardown function after the test
|
||||||
|
if (tcase->teardown) tcase->teardown();
|
||||||
|
|
||||||
|
tcase->tested++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output summary of the tests
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
suite = &suites[i];
|
||||||
|
|
||||||
|
fprintf(output, "Test suite `%s` report: \r\n", suite->name);
|
||||||
|
|
||||||
|
// Iterate over each test case
|
||||||
|
for (int j = 0; j < suite->count; j++)
|
||||||
|
{
|
||||||
|
tcase = &suite->tests[j];
|
||||||
|
|
||||||
|
fprintf(output, "[%s] Summary: tested %u, passed %u, time %llu us.\r\n",
|
||||||
|
tcase->name,
|
||||||
|
tcase->tested,
|
||||||
|
tcase->passed,
|
||||||
|
tcase->time
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename != NULL)
|
||||||
|
{
|
||||||
|
fclose(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
184
source/06_performance/unitt.h
Normal file
184
source/06_performance/unitt.h
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*********************************************************************************************************
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* file description
|
||||||
|
* ------------------------------------------------------------------------------------------------------
|
||||||
|
* \file unitt.h
|
||||||
|
* \unit unitt
|
||||||
|
* \brief This is a simple unit test module for C language
|
||||||
|
* \author Lamdonn
|
||||||
|
* \version v1.0.0
|
||||||
|
* \license GPL-2.0
|
||||||
|
* \copyright Copyright (C) 2023 Lamdonn.
|
||||||
|
********************************************************************************************************/
|
||||||
|
#ifndef __unitt_H
|
||||||
|
#define __unitt_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Version infomation */
|
||||||
|
#define UNITT_V_MAJOR 0
|
||||||
|
#define UNITT_V_MINOR 1
|
||||||
|
#define UNITT_V_PATcH 0
|
||||||
|
|
||||||
|
// Type definition for a clock function
|
||||||
|
typedef uint64_t (*unitt_clock_t)();
|
||||||
|
|
||||||
|
// Type definition for a test function
|
||||||
|
typedef int (*unitt_func_t)();
|
||||||
|
|
||||||
|
// Type definition for a setup function before the test
|
||||||
|
typedef int (*unitt_setup_t)();
|
||||||
|
|
||||||
|
// Type definition for a teardown function after the test
|
||||||
|
typedef int (*unitt_teardown_t)();
|
||||||
|
|
||||||
|
// Type definition for a failure callback function
|
||||||
|
typedef int (*unitt_failcb_t)(const char* name);
|
||||||
|
|
||||||
|
// Type definition for a random input generation function
|
||||||
|
typedef int (*unitt_randin_t)();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Structure representing a test case
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char* name; ///< Name of the test
|
||||||
|
unitt_func_t func; ///< Pointer to the test function
|
||||||
|
unitt_setup_t setup; ///< Pointer to the setup function
|
||||||
|
unitt_teardown_t teardown; ///< Pointer to the teardown function
|
||||||
|
unitt_randin_t random_input; ///< Pointer to the random input generation function
|
||||||
|
uint32_t tested; ///< Count of tests executed
|
||||||
|
uint32_t passed; ///< Count of tests passed
|
||||||
|
uint64_t time; ///< Total time taken for the test
|
||||||
|
} UNITT_TCASE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Structure representing a test suite
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char* name; ///< Name of the test suite
|
||||||
|
UNITT_TCASE* tests; ///< Array of test cases
|
||||||
|
uint32_t count; ///< Number of test cases
|
||||||
|
unitt_clock_t clock; ///< Pointer to the clock function for measuring time
|
||||||
|
} UNITT;
|
||||||
|
|
||||||
|
#define UNITT_E_OK (0) // Success return code
|
||||||
|
#define UNITT_E_FAIL (-1) // Failure return code
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a condition is true
|
||||||
|
* \param[in] condition: The condition to evaluate
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_true(int condition, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a condition is false
|
||||||
|
* \param[in] condition: The condition to evaluate
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_false(int condition, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two integers are equal
|
||||||
|
* \param[in] expected: The expected value
|
||||||
|
* \param[in] actual: The actual value
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_equal(int expected, int actual, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two integers are not equal
|
||||||
|
* \param[in] expected: The expected value
|
||||||
|
* \param[in] actual: The actual value
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_nequal(int expected, int actual, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a pointer is NULL
|
||||||
|
* \param[in] pointer: The pointer to evaluate
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_null(void* pointer, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that a pointer is not NULL
|
||||||
|
* \param[in] pointer: The pointer to evaluate
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_nnull(void* pointer, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two floats are approximately equal
|
||||||
|
* \param[in] expected: The expected float value
|
||||||
|
* \param[in] actual: The actual float value
|
||||||
|
* \param[in] epsilon: The acceptable difference between the two values
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_float(float expected, float actual, float epsilon, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assert that two strings are equal
|
||||||
|
* \param[in] expected: The expected string
|
||||||
|
* \param[in] actual: The actual string
|
||||||
|
* \param[in] message: The message to display if the assertion fails
|
||||||
|
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
|
||||||
|
*/
|
||||||
|
int unitt_det_string(const char* expected, const char* actual, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Handle a test failure
|
||||||
|
* \param[in] name: The name of the failed test
|
||||||
|
* \return Returns UNITT_E_OK
|
||||||
|
*/
|
||||||
|
int unitt_fail_handle(const char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Execute a test suite
|
||||||
|
* \param[in] suites: Array of test suites to execute
|
||||||
|
* \param[in] count: Number of test suites in the array
|
||||||
|
* \param[in] failcb: Callback function to handle test failures
|
||||||
|
* \param[in] specific: Specific test name to execute (NULL for all)
|
||||||
|
* \param[in] filename: Output filename for results (NULL for stdout)
|
||||||
|
* \return none
|
||||||
|
*/
|
||||||
|
void unitt_execute(UNITT* suites, uint32_t count, unitt_failcb_t failcb, const char* specific, const char* filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Macro to define a test case
|
||||||
|
* \param name: Name of the test case
|
||||||
|
*/
|
||||||
|
#define UNITT_TCASE(name) { #name, name, NULL, NULL, NULL, 0, 0, 0 }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Macro to execute a set of test cases
|
||||||
|
* \param suites: Array of test cases to execute
|
||||||
|
*/
|
||||||
|
#define UNITT_EXE(suites) unitt_execute((suites), sizeof(suites) / sizeof(suites[0]), unitt_fail_handle, 0, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Macro to execute a set of test cases with additional parameters
|
||||||
|
* \param suites: Array of test cases to execute
|
||||||
|
* \param count: Number of test cases
|
||||||
|
* \param mode: Execution mode
|
||||||
|
* \param specific: Specific test name to execute
|
||||||
|
* \param output: Output filename for results
|
||||||
|
*/
|
||||||
|
#define UNITT_EXE2(suites, count, mode, specific, output) unitt_execute(suites, count, unitt_fail_handle, specific, output)
|
||||||
|
|
||||||
|
#endif // __unit_H
|
||||||
@ -45,6 +45,11 @@ TEST_INC =
|
|||||||
# TEST_SRC += $(TESTSPACE)/test_sList.c
|
# TEST_SRC += $(TESTSPACE)/test_sList.c
|
||||||
# TEST_SRC += $(TESTSPACE)/test_dList.c
|
# TEST_SRC += $(TESTSPACE)/test_dList.c
|
||||||
# TEST_SRC += $(TESTSPACE)/test_cQueue.c
|
# TEST_SRC += $(TESTSPACE)/test_cQueue.c
|
||||||
TEST_SRC += $(TESTSPACE)/test_intl.c
|
# TEST_SRC += $(TESTSPACE)/test_intl.c
|
||||||
|
# TEST_SRC += $(TESTSPACE)/test_ramt.c
|
||||||
|
# TEST_SRC += $(TESTSPACE)/test_cpul.c
|
||||||
|
# TEST_SRC += $(TESTSPACE)/test_date.c
|
||||||
|
TEST_SRC += $(TESTSPACE)/test_unitt.c
|
||||||
|
|
||||||
|
|
||||||
export TEST_SRC TEST_INC
|
export TEST_SRC TEST_INC
|
||||||
|
|||||||
200
test/test_cpul.c
Normal file
200
test/test_cpul.c
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include "init.h"
|
||||||
|
#include "cpul.h"
|
||||||
|
|
||||||
|
#define CORE_NUM_MAX 32
|
||||||
|
#define LINE_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure for recording CPU counters in stat
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint64_t user; /**< Time spent in user mode */
|
||||||
|
uint64_t nice; /**< Time spent in low-priority user mode */
|
||||||
|
uint64_t system; /**< Time spent in system mode */
|
||||||
|
uint64_t idle; /**< Time spent waiting for tasks */
|
||||||
|
uint64_t iowait; /**< Time spent waiting for I/O to complete */
|
||||||
|
uint64_t irq; /**< Time spent processing interrupts */
|
||||||
|
uint64_t softirq; /**< Time spent processing soft interrupts */
|
||||||
|
uint64_t steal; /**< Time spent by other OS in virtual environment */
|
||||||
|
uint64_t guest; /**< Time spent running guest OS */
|
||||||
|
uint64_t guest_nice; /**< Time spent running low priority guest OS */
|
||||||
|
} cputime_t;
|
||||||
|
|
||||||
|
static uint16_t loadTable[CORE_NUM_MAX] = {0};
|
||||||
|
|
||||||
|
static cputime_t read_stat(int coreid)
|
||||||
|
{
|
||||||
|
cputime_t work;
|
||||||
|
FILE *file;
|
||||||
|
char line[LINE_BUFFER_SIZE];
|
||||||
|
|
||||||
|
file = fopen("/proc/stat", "rb");
|
||||||
|
if (file == NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fgets(line, sizeof(line), file) == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sscanf(line, "cpu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
|
||||||
|
&work.user,
|
||||||
|
&work.nice,
|
||||||
|
&work.system,
|
||||||
|
&work.idle,
|
||||||
|
&work.iowait,
|
||||||
|
&work.irq,
|
||||||
|
&work.softirq,
|
||||||
|
&work.steal,
|
||||||
|
&work.guest,
|
||||||
|
&work.guest_nice) < 4) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coreid > 0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < coreid; i++)
|
||||||
|
{
|
||||||
|
if (fgets(line, sizeof(line), file) == NULL)
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sscanf(line, "cpu%*u %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
|
||||||
|
&work.user,
|
||||||
|
&work.nice,
|
||||||
|
&work.system,
|
||||||
|
&work.idle,
|
||||||
|
&work.iowait,
|
||||||
|
&work.irq,
|
||||||
|
&work.softirq,
|
||||||
|
&work.steal,
|
||||||
|
&work.guest,
|
||||||
|
&work.guest_nice) < 4)
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
fclose(file);
|
||||||
|
return work;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *loadupdate_entry(void *ptr)
|
||||||
|
{
|
||||||
|
const int coreNum = *(int *)ptr;
|
||||||
|
cputime_t before[coreNum], after[coreNum], diff[coreNum];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
/* Calcul real time load */
|
||||||
|
for (i = 0; i < coreNum; i++) before[i] = read_stat(i);
|
||||||
|
usleep(1000000);
|
||||||
|
for (i = 0; i < coreNum; i++) after[i] = read_stat(i);
|
||||||
|
|
||||||
|
for (i = 0; i < coreNum; i++)
|
||||||
|
{
|
||||||
|
if (after[i].user > before[i].user && after[i].idle > before[i].idle)
|
||||||
|
{
|
||||||
|
diff[i].user = after[i].user - before[i].user;
|
||||||
|
diff[i].idle = after[i].idle - before[i].idle;
|
||||||
|
loadTable[i] = (uint16_t)(((float)(diff[i].user) / (float)(diff[i].user + diff[i].idle)) * 10000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loadTable[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("[core%d] load %d\r\n", i, loadTable[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t cpul_raw(uint8_t coreid)
|
||||||
|
{
|
||||||
|
if (coreid >= CORE_NUM_MAX) return 0xFFFF;
|
||||||
|
return (uint16_t)(loadTable[coreid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *loadgen_entry(void *ptr)
|
||||||
|
{
|
||||||
|
#define PERIOD 10
|
||||||
|
const int coreid = *(int *)ptr;
|
||||||
|
CPUL cpul;
|
||||||
|
int ret = 0;
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint16_t load = 0;
|
||||||
|
|
||||||
|
cpul.coreid = coreid;
|
||||||
|
cpul.resolution = 10;
|
||||||
|
cpul.raw = cpul_raw;
|
||||||
|
ret = cpul_init(&cpul);
|
||||||
|
|
||||||
|
ret = cpul_set(&cpul, 5000);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
count += PERIOD;
|
||||||
|
if (count >= 25200000) count = 0;
|
||||||
|
|
||||||
|
if (count % 1000 == 0)
|
||||||
|
{
|
||||||
|
ret = cpul_get(&cpul, &load);
|
||||||
|
printf("cpul_get<%d> %2d.%02d%%, %d, %d\r\n", coreid, (uint16_t)(load / 100), load % 100, cpul.ctrl.tload, cpul.ctrl.refine);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpul_task(&cpul);
|
||||||
|
usleep(1000 * PERIOD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test(void)
|
||||||
|
{
|
||||||
|
int num_cpus = sysconf(_SC_NPROCESSORS_CONF);
|
||||||
|
pthread_t thread_update, thread_gen[num_cpus];
|
||||||
|
int coreid[num_cpus];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
printf("Number of CPUs: %d\n", num_cpus);
|
||||||
|
|
||||||
|
ret = pthread_create(&thread_update, NULL, &loadupdate_entry, &num_cpus);
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("pthread_create failed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_cpus; i++)
|
||||||
|
{
|
||||||
|
coreid[i] = i;
|
||||||
|
ret = pthread_create(&thread_gen[i], NULL, &loadgen_entry, &coreid[i]);
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("pthread_create failed!\n");
|
||||||
|
}
|
||||||
|
cpu_set_t cpuset;
|
||||||
|
CPU_ZERO(&cpuset);
|
||||||
|
CPU_SET(i, &cpuset);
|
||||||
|
sched_setaffinity(thread_gen[i], sizeof(cpu_set_t), &cpuset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_join(thread_update, NULL);
|
||||||
|
for (int i = 0; i < num_cpus; i++)
|
||||||
|
{
|
||||||
|
pthread_join(thread_gen[i], NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
init_export_app(test);
|
||||||
69
test/test_date.c
Normal file
69
test/test_date.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "init.h"
|
||||||
|
#include "date.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static int century_days(int century)
|
||||||
|
{
|
||||||
|
int days = 0;
|
||||||
|
int year = (century - 1) * 100 + 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
days += date_year_days(year + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return days;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int thousand2_days(int base)
|
||||||
|
{
|
||||||
|
int days = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2000; i++)
|
||||||
|
{
|
||||||
|
days += date_year_days(base + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return days;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int thousand3_days(int base)
|
||||||
|
{
|
||||||
|
int days = 0;
|
||||||
|
int century = (base / 100) + 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
// days += century_days(century + i);
|
||||||
|
days += date_century_days(century + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return days;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void test(void)
|
||||||
|
{
|
||||||
|
printf("month days %d\r\n", date_month_days(2024, 11));
|
||||||
|
printf("date_isleap %d\r\n", date_isleap(1582));
|
||||||
|
// printf("date_current_days %d\r\n", date_current_days(DATE(1,1,1)));
|
||||||
|
// printf("date_current_days %d\r\n", date_current_days(DATE(2000,12,31)));
|
||||||
|
// printf("date_current_days %d\r\n", date_current_days(DATE(2001,1,1)));
|
||||||
|
// printf("date_current_days %d\r\n", date_current_days(DATE(2024,11,9)));
|
||||||
|
printf("date_get_week %d\r\n", date_get_week(DATE(2024,11,11)));
|
||||||
|
|
||||||
|
printf("date_diff_days %d\r\n", date_diff_days(DATE(2018,3,14), DATE(2024,11,10)));
|
||||||
|
|
||||||
|
// DATE date = date_from_days(date_current_days(DATE(2024,11,30)));
|
||||||
|
DATE date = date_offset(DATE(2024,11,30), -1);
|
||||||
|
|
||||||
|
printf("%d.%d.%d\r\n", date.year,date.month,date.day);
|
||||||
|
|
||||||
|
date_show(1998,7);
|
||||||
|
date_show(2024,11);
|
||||||
|
date_show(2224,11);
|
||||||
|
}
|
||||||
|
init_export_app(test);
|
||||||
43
test/test_ramt.c
Normal file
43
test/test_ramt.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "init.h"
|
||||||
|
#include "tool.h"
|
||||||
|
#include "ramt.h"
|
||||||
|
#include "kern.h"
|
||||||
|
|
||||||
|
#define TASK_PERIOD 5 // ms
|
||||||
|
|
||||||
|
static uint8_t buffer[128];
|
||||||
|
static RAMT ramt_object;
|
||||||
|
|
||||||
|
static void test_task(void)
|
||||||
|
{
|
||||||
|
static int count = 0;
|
||||||
|
|
||||||
|
count += TASK_PERIOD;
|
||||||
|
|
||||||
|
ramt_task(&ramt_object);
|
||||||
|
|
||||||
|
if (count % 1000 == 0)
|
||||||
|
{
|
||||||
|
printf("result %08X\r\n", ramt_result(&ramt_object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ramt(void)
|
||||||
|
{
|
||||||
|
task_t task;
|
||||||
|
|
||||||
|
printf("ramt test!\r\n");
|
||||||
|
|
||||||
|
ramt_object.base = (void *)buffer;
|
||||||
|
ramt_object.size = sizeof(buffer);
|
||||||
|
ramt_init(&ramt_object);
|
||||||
|
|
||||||
|
ramt_start(&ramt_object, RAMT_MODE_NORMAL, 0xFFFFFFFF);
|
||||||
|
|
||||||
|
task = task_create(TASK_PERIOD, test_task);
|
||||||
|
printf("task <%d>\r\n", task);
|
||||||
|
}
|
||||||
|
init_export_app(test_ramt);
|
||||||
182
test/test_unitt.c
Normal file
182
test/test_unitt.c
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "init.h"
|
||||||
|
#include "unitt.h"
|
||||||
|
#include "kern.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <psapi.h> // -lPsapi
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void get_memory_usage(int* resident_set_size, int* virtual_memory_size)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
PROCESS_MEMORY_COUNTERS pmc;
|
||||||
|
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
|
||||||
|
*resident_set_size = pmc.WorkingSetSize / 1024; // 转换为KB
|
||||||
|
*virtual_memory_size = pmc.PagefileUsage / 1024; // 转换为KB
|
||||||
|
} else {
|
||||||
|
*resident_set_size = 0;
|
||||||
|
*virtual_memory_size = 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
FILE* file = fopen("/proc/self/statm", "r");
|
||||||
|
if (file) {
|
||||||
|
fscanf(file, "%d %d", resident_set_size, virtual_memory_size);
|
||||||
|
fclose(file);
|
||||||
|
} else {
|
||||||
|
*resident_set_size = 0;
|
||||||
|
*virtual_memory_size = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SINGLE_TCOUNT 1000
|
||||||
|
|
||||||
|
uint64_t unitt_clock(void)
|
||||||
|
{
|
||||||
|
struct timeval mstime;
|
||||||
|
uint64_t us = 0;
|
||||||
|
gettimeofday(&mstime, NULL);
|
||||||
|
us = mstime.tv_sec * 1000000 + mstime.tv_usec;
|
||||||
|
return us;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算两个整数的和
|
||||||
|
int unit_add(int a, int b)
|
||||||
|
{
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算两个整数的差
|
||||||
|
int unit_subtract(int a, int b)
|
||||||
|
{
|
||||||
|
return a - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算两个整数的乘积
|
||||||
|
int unit_multiply(int a, int b)
|
||||||
|
{
|
||||||
|
return a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算两个整数的商
|
||||||
|
float unit_divide(int a, int b)
|
||||||
|
{
|
||||||
|
if (b == 0)
|
||||||
|
{
|
||||||
|
return 0; // 简单处理,真实应用中应更严格处理
|
||||||
|
}
|
||||||
|
return (float)a / (float)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试前的初始化函数
|
||||||
|
int setup()
|
||||||
|
{
|
||||||
|
// 初始化代码(如果需要)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试后的清理函数
|
||||||
|
int teardown()
|
||||||
|
{
|
||||||
|
// 清理代码(如果需要)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 随机输入生成函数
|
||||||
|
int random_input()
|
||||||
|
{
|
||||||
|
return rand() % 100; // 生成0到99之间的随机整数
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试加法函数,使用随机输入
|
||||||
|
int test_add()
|
||||||
|
{
|
||||||
|
// 进行10次随机测试
|
||||||
|
for (int i = 0; i < SINGLE_TCOUNT; i++)
|
||||||
|
{
|
||||||
|
int a = random_input();
|
||||||
|
int b = random_input();
|
||||||
|
if (UNITT_E_FAIL == unitt_det_equal(unit_add(a, b), a + b, "Random addition failed")) return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试减法函数,使用随机输入
|
||||||
|
int test_subtract()
|
||||||
|
{
|
||||||
|
// 进行10次随机测试
|
||||||
|
for (int i = 0; i < SINGLE_TCOUNT; i++)
|
||||||
|
{
|
||||||
|
int a = random_input();
|
||||||
|
int b = random_input();
|
||||||
|
if (UNITT_E_FAIL == unitt_det_equal(unit_subtract(a, b), a - b, "Random subtraction failed")) return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试乘法函数,使用随机输入
|
||||||
|
int test_multiply()
|
||||||
|
{
|
||||||
|
// 进行10次随机测试
|
||||||
|
for (int i = 0; i < SINGLE_TCOUNT; i++)
|
||||||
|
{
|
||||||
|
int a = random_input();
|
||||||
|
int b = random_input();
|
||||||
|
if (UNITT_E_FAIL == unitt_det_equal(unit_multiply(a, b), a * b, "Random multiplication failed")) return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试除法函数,使用随机输入
|
||||||
|
int test_divide()
|
||||||
|
{
|
||||||
|
// 进行10次随机测试
|
||||||
|
for (int i = 0; i < SINGLE_TCOUNT; i++)
|
||||||
|
{
|
||||||
|
int a = random_input();
|
||||||
|
int b = random_input();
|
||||||
|
if (b != 0)
|
||||||
|
{
|
||||||
|
if (UNITT_E_FAIL == unitt_det_float(unit_divide(a, b), (float)a / (float)b, 0.00001, "Random division failed")) return UNITT_E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNITT_E_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unit_main()
|
||||||
|
{
|
||||||
|
static UNITT_TCASE math_tests[] = {
|
||||||
|
UNITT_TCASE(test_add),
|
||||||
|
UNITT_TCASE(test_subtract),
|
||||||
|
UNITT_TCASE(test_multiply),
|
||||||
|
UNITT_TCASE(test_divide),
|
||||||
|
};
|
||||||
|
|
||||||
|
static UNITT suites[] = {
|
||||||
|
{ "Math Suite", math_tests, sizeof(math_tests) / sizeof(math_tests[0]) , unitt_clock },
|
||||||
|
};
|
||||||
|
|
||||||
|
UNITT_EXE(suites);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test(void)
|
||||||
|
{
|
||||||
|
srand((unsigned int)time(NULL)); // 初始化随机数种子
|
||||||
|
|
||||||
|
// unit_main();
|
||||||
|
printf("create task %d\r\n", task_create(1000, unit_main));
|
||||||
|
}
|
||||||
|
init_export_app(test);
|
||||||
Loading…
x
Reference in New Issue
Block a user