Annotation of nono/lib/header.h, revision 1.1.1.15

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.15! root        7: //
        !             8: // 基本ヘッダ
        !             9: //
        !            10: 
1.1       root       11: #pragma once
                     12: 
                     13: #define NONO_MAJOR_VER (0)
1.1.1.15! root       14: #define NONO_MINOR_VER (3)
        !            15: #define NONO_PATCH_VER (0)
        !            16: #define NONO_DATE              "2022/04/30"
1.1       root       17: 
1.1.1.3   root       18: #include "config-nono.h"
1.1       root       19: #include <cassert>
                     20: #include <cctype>
                     21: #include <cerrno>
                     22: #include <cstdarg>
                     23: #include <cstdio>
                     24: #include <cstdint>
                     25: #include <cstdlib>
                     26: #include <cstring>
1.1.1.3   root       27: #include <memory>
1.1       root       28: #include <string>
                     29: 
                     30: #include <err.h>
                     31: #include <inttypes.h>
                     32: #include <unistd.h>
                     33: #include <sys/cdefs.h>
                     34: #include <sys/types.h>
                     35: 
1.1.1.4   root       36: using uint8            = uint8_t;
                     37: using uint16   = uint16_t;
                     38: using uint32   = uint32_t;
                     39: using uint64   = uint64_t;
                     40: using int8             = int8_t;
                     41: using int16            = int16_t;
                     42: using int32            = int32_t;
                     43: using int64            = int64_t;
1.1       root       44: 
                     45: #if defined(HAVE_BSD_BSD_H)
                     46: #include <bsd/bsd.h>
                     47: #endif
                     48: 
1.1.1.15! root       49: #include "myendian.h"
        !            50: 
1.1       root       51: #if !defined(__printflike)
                     52: #if defined(HAVE___ATTRIBUTE_FORMAT)
                     53: # define __printflike(a,b)     __attribute__((__format__(__printf__, (a), (b))))
                     54: #else
                     55: # define __printflike(a,b)
                     56: #endif
                     57: #endif
                     58: 
                     59: #if !defined(__unreachable)
                     60: #if defined(HAVE___BUILTIN_UNREACHABLE)
                     61: # define __unreachable()       __builtin_unreachable()
                     62: #else
                     63: # define __unreachable()       ((void)0)
                     64: #endif
                     65: #endif
                     66: 
                     67: // gcc でコンパイラに最適化の条件を与える。
                     68: #if defined(HAVE___BUILTIN_ASSUME)
                     69: #define __assume(cond) __builtin_assume(cond)
                     70: #else
                     71: #define __assume(cond) if (!(cond)) __unreachable()
                     72: #endif
                     73: 
                     74: #if !defined(__packed)
                     75: #if defined(HAVE___ATTRIBUTE_PACKED)
                     76: # define __packed      __attribute__((__packed__))
                     77: #else
                     78: # error not tested.
                     79: #endif
                     80: #endif
                     81: 
                     82: #if !defined(__predict_true)
                     83: #if defined(HAVE___BUILTIN_EXPECT)
                     84: # define __predict_true(exp)   __builtin_expect((exp) != 0, 1)
                     85: # define __predict_false(exp)  __builtin_expect((exp) != 0, 0)
                     86: #else
                     87: # define __predict_true(exp)   (exp)
                     88: # define __predict_false(exp)  (exp)
                     89: #endif
                     90: #endif
                     91: 
                     92: #if !defined(__unused)
                     93: #if defined(HAVE___ATTRIBUTE_UNUSED)
                     94: # define __unused __attribute__((__unused__))
                     95: #else
                     96: # define __unused
                     97: #endif
                     98: #endif
                     99: 
1.1.1.4   root      100: #if defined(__clang__)
                    101: # define FALLTHROUGH   [[clang::fallthrough]]
                    102: #elif defined(HAVE___ATTRIBUTE_FALLTHROUGH)
1.1       root      103: # define FALLTHROUGH   __attribute__((__fallthrough__))
                    104: #else
                    105: # define FALLTHROUGH   ((void)0)
                    106: #endif
                    107: 
                    108: #if defined(HAVE___ATTRIBUTE_NO_SANITIZE)
                    109: # define NO_SANITIZE(x)        __attribute__((no_sanitize(x)))
                    110: #else
                    111: # define NO_SANITIZE(x)
                    112: #endif
                    113: 
1.1.1.5   root      114: // x86_64 では SSE のために16バイト境界に整列させたいが、ほかの
                    115: // アーキテクチャでは alignas(16) がエラーになる場合がある。この場合の
                    116: // alignas() は SSE のために必要なので、他アーキテクチャではそもそも
                    117: // 指定しなくていい。ということで x86_64 の時に限って指定したい時に使う。
                    118: // うーん、なんだこれ。
                    119: #if defined(__x86_64__)
                    120: #define ALIGNAS_IF_X86(n) alignas(n)
                    121: #else
                    122: #define ALIGNAS_IF_X86(n) /**/
                    123: #endif
                    124: 
1.1.1.3   root      125: // 64ビット数と2つの32ビット数を扱う共用体。
                    126: // 構造はまったく同じだが名前だけ場所に合わせてつけたい。
1.1.1.15! root      127: #if BYTE_ORDER == LITTLE_ENDIAN
1.1.1.3   root      128: #define DEF_UNION64(NAME, Q, H, L)     \
                    129:        union NAME {    \
                    130:                uint64 Q;       \
                    131:                struct { uint32 L, H; };        \
                    132:        }
                    133: #else
                    134: #define DEF_UNION64(NAME, Q, H, L)     \
                    135:        union NAME {    \
                    136:                uint64 Q;       \
                    137:                struct { uint32 H, L; };        \
                    138:        }
                    139: #endif
                    140: 
                    141: DEF_UNION64(union64, q, h, l);
                    142: 
1.1       root      143: #ifndef countof
                    144: #define countof(x)     (sizeof(x) / sizeof(x[0]))
                    145: #endif
                    146: 
1.1.1.5   root      147: #ifndef roundup
                    148: #define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
                    149: #endif
                    150: 
1.1.1.15! root      151: #ifndef rounddown
        !           152: #define rounddown(x, y)        (((x)/(y))*(y))
        !           153: #endif
        !           154: 
1.1.1.3   root      155: // メッセージ付きの assert。
1.1.1.5   root      156: // 本当は後ろに足したいのだがそれは無理なので、せめてそれっぽく1行にしてみる。
1.1.1.15! root      157: #if !defined(NDEBUG)
1.1.1.5   root      158: #define assertmsg(expr, ...)   do {    \
1.1.1.3   root      159:        if (__predict_false(!(expr))) { \
1.1.1.5   root      160:                fprintf(stderr, __VA_ARGS__);   \
                    161:                fprintf(stderr, ": "); \
1.1.1.3   root      162:                assert(expr);   \
                    163:        }       \
                    164: } while (0)
1.1.1.15! root      165: #else
        !           166: #define assertmsg(expr, ...)
        !           167: #endif
1.1.1.3   root      168: 
1.1       root      169: // atomic_compare_exchange_strong() の短縮マクロ。
                    170: // ライブラリ実装は第2引数の expected が値ではなくポインタなので一旦代入操作を
                    171: // 行わないといけないのと、第3引数の newval は型が uint8 だと int 即値が書けず
                    172: // (int8) でキャストしないといけない。
                    173: // その上 atomic_compare_exchange_strong() が長い、と、いろいろ微妙なので、
                    174: // その辺を短くするマクロを用意する。ただしこれでは expected 変数の型が
                    175: // 自動判別できないので、_8 と _32 を用意するところは妥協。
                    176: // (static) inline 関数にすることも出来るけどそうするとここで <atomic> ヘッダ
                    177: // を読み込まなければならなくなるため、マクロで実現する。
                    178: #define atomic_cas_8(varp, expval, newval)     ({      \
                    179:        uint8 expected = (expval);      \
                    180:        atomic_compare_exchange_strong((varp), &expected, (uint8)(newval));     \
                    181: })
                    182: #define atomic_cas_32(varp, expval, newval)    ({      \
                    183:        uint32 expected = (expval);     \
                    184:        atomic_compare_exchange_strong((varp), &expected, (uint32)(newval));    \
                    185: })
                    186: 
1.1.1.15! root      187: // パニック (PC を表示しない)
1.1       root      188: #define PANIC(...)     panic(__PRETTY_FUNCTION__, __VA_ARGS__)
                    189: [[noreturn]] extern void panic(const char *funcname, const char *fmt, ...)
                    190:        __printflike(2, 3);
1.1.1.15! root      191: 
        !           192: // VM 用パニック (PC を表示する)
        !           193: #define VMPANIC(...) vmpanic(__PRETTY_FUNCTION__, __VA_ARGS__)
        !           194: [[noreturn]] extern void vmpanic(const char *funcname, const char *fmt, ...)
        !           195:        __printflike(2, 3);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.