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