diff --git a/kernel/arch/x86_64/asm.h b/kernel/arch/x86_64/asm/asm.h similarity index 85% rename from kernel/arch/x86_64/asm.h rename to kernel/arch/x86_64/asm/asm.h index a3d13867..943bdef2 100644 --- a/kernel/arch/x86_64/asm.h +++ b/kernel/arch/x86_64/asm/asm.h @@ -18,6 +18,21 @@ #define io_lfence() __asm__ __volatile__("lfence\n\t" :: \ : "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。 +/* + * Macros to generate condition code outputs from inline assembly, + * The output operand must be type "bool". + */ +// 如果编译器支持输出标志寄存器值到变量的话,则会定义__GCC_ASM_FLAG_OUTPUTS__ +#ifdef __GCC_ASM_FLAG_OUTPUTS__ +// CC_SET(c)则是用于设置标志寄存器中的某一位 +#define CC_SET(c) "\n\t/* output condition code " #c "*/\n" +// "=@cccond"的用法是,将标志寄存器中的cond(也就是指令集定义的标准条件)的值输出到变量中 +#define CC_OUT(c) "=@cc" #c +#else +#define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n" +#define CC_OUT(c) [_cc_##c] "=qm" +#endif + #define rdtsc() ({ \ uint64_t tmp1 = 0, tmp2 = 0; \ asm volatile("rdtsc" \ diff --git a/kernel/common/compiler.h b/kernel/common/compiler.h index f076f400..46288165 100644 --- a/kernel/common/compiler.h +++ b/kernel/common/compiler.h @@ -1,6 +1,6 @@ #pragma once -#define __force __attribute__((force)) +#include #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) @@ -11,19 +11,37 @@ : "memory"); #endif -// 编译器属性 +/** + * @brief 编译时断言,如果condition不为1,则输出msg + * + * @param prefix 一个“不存在的函数名”的前缀 + * @param suffix 一个“不存在的函数名”的后缀 + */ +#define __compiletime_assert(condition, msg, prefix, suffix) \ + do \ + { \ + /** \ + * 声明一个不存在的函数的extern,如果assert失败,就调用它,从而导致 \ + * 链接时出错,进而达到“编译时断言”的功能。 \ + */ \ + __noreturn extern void prefix##suffix(void) \ + __compiletime_error(msg); \ + if (!(condition)) \ + prefix##suffix(); \ + } while (0) -// 当函数的返回值未被使用时,编译器抛出警告信息 -#define __must_check __attribute__((__warn_unused_result__)) - -typedef uint8_t __attribute__((__may_alias__)) __u8_alias_t; -typedef uint16_t __attribute__((__may_alias__)) __u16_alias_t; -typedef uint32_t __attribute__((__may_alias__)) __u32_alias_t; -typedef uint64_t __attribute__((__may_alias__)) __u64_alias_t; +/** + * @brief 当condition是false时,中断编译,并输出指定的错误信息 + * + * @param condition assert的情况 + * @param msg condition为false时输出的错误信息 + */ +#define complietime_assert(condition, msg) \ + __compiletime_assert(condition, msg, __compiletime_assert__, __COUNTER__) /** * @brief 从src读取数据到dst,该过程避免编译器优化。 - * + * * @param dst 目标地址指针 * @param src 源地址指针 * @param size 要读取的数据大小(建议1、2、4、8字节,若不满足要求,则采用memcpy读取。) @@ -54,7 +72,7 @@ static __always_inline void __read_once_size(void *dst, const volatile void *src /** * @brief 把src处的数据到dst,该过程避免编译器优化。 - * + * * @param dst 目标地址指针 * @param src 源地址指针 * @param size 要写入的数据大小(建议1、2、4、8字节,若不满足要求,则采用memcpy传输。) @@ -94,7 +112,7 @@ static __always_inline void __write_once_size(volatile void *dst, void *src, int * 2.确保编译器不会折叠、旋转或以其他方式对代码进行优化,从而破坏数据访问顺序。 * * 这两个宏的union __u内的__c用作这个union的地址的指针 - * + * * 关于READ_ONCE和WRITE_ONCE的简单说明,请转到:https://bbs.dragonos.org/forum.php?mod=viewthread&tid=24 */ diff --git a/kernel/common/compiler_attributes.h b/kernel/common/compiler_attributes.h new file mode 100644 index 00000000..b77cae26 --- /dev/null +++ b/kernel/common/compiler_attributes.h @@ -0,0 +1,22 @@ +#pragma once + +// 当函数的返回值未被使用时,编译器抛出警告信息 +#define __must_check __attribute__((__warn_unused_result__)) +#define __force __attribute__((force)) +// 无返回值的属性 +#define __noreturn __attribute__((__noreturn__)) +/* + * Optional: only supported since clang >= 14.0 + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-error-function-attribute + */ +#if __has_attribute(__error__) +#define __compiletime_error(msg) __attribute__((__error__(msg))) +#else +#define __compiletime_error(msg) +#endif + +typedef uint8_t __attribute__((__may_alias__)) __u8_alias_t; +typedef uint16_t __attribute__((__may_alias__)) __u16_alias_t; +typedef uint32_t __attribute__((__may_alias__)) __u32_alias_t; +typedef uint64_t __attribute__((__may_alias__)) __u64_alias_t; \ No newline at end of file diff --git a/kernel/common/glib.h b/kernel/common/glib.h index 24140b7e..69e67d13 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -14,7 +14,7 @@ #include #if ARCH(I386) || ARCH(X86_64) -#include +#include #else #error Arch not supported. #endif diff --git a/kernel/common/list.h b/kernel/common/list.h index 53fe392d..86469f44 100644 --- a/kernel/common/list.h +++ b/kernel/common/list.h @@ -2,7 +2,7 @@ #include #if ARCH(I386) || ARCH(X86_64) -#include +#include #else #error Arch not supported. #endif diff --git a/kernel/common/sys/types.h b/kernel/common/sys/types.h index ee9c7244..ae362a21 100644 --- a/kernel/common/sys/types.h +++ b/kernel/common/sys/types.h @@ -87,4 +87,11 @@ typedef struct __pthread_condattr_t int clockid; // clockid_t } pthread_condattr_t; -typedef uint64_t gfp_t; \ No newline at end of file +typedef uint64_t gfp_t; + +// 定义8字节对齐变量属性 +#ifndef __aligned_u64 + #define __aligned_u64 uint64_t __attribute__((aligned(8))) +#endif + +#define aligned_u64 __aligned_u64 \ No newline at end of file diff --git a/kernel/debug/bug.h b/kernel/debug/bug.h index 7b566c80..db76952d 100644 --- a/kernel/debug/bug.h +++ b/kernel/debug/bug.h @@ -29,7 +29,7 @@ /** * @brief 当condition不为0时输出警告信息,且只会输出一次警告信息 - * + * */ #define WARN_ON_ONCE(condition) ({ \ static int __warned; \ @@ -49,4 +49,20 @@ goto to; \ unlikely(__ret_warn_on); \ }) + +/** + * @brief 当condition为true时,中断编译,并输出错误信息msg + * + * 如果你的代码依赖于一些能够在编译期间计算出来的值,那么请使用这个宏以防止其他人错误的修改了这些值,从而导致程序运行错误 + */ +#define BUILD_BUG_ON_MSG(condition, msg) complietime_assert(!(condition), msg) + +/** + * @brief 当condition为true时,中断编译。 + * + * 如果你的代码依赖于一些能够在编译期间计算出来的值,那么请使用这个宏以防止其他人错误的修改了这些值,从而导致程序运行错误 + */ +#define BUILD_BUG_ON(condition) \ + BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) + #pragma GCC pop_options \ No newline at end of file