| author | |
| committer | |
| log | 371a3ad4bd7b1fda56654f32b89c176a0197651f |
| tree | 9b402e02568e4f62a728a7cec1819363a89d6e9a |
| parent | 7af6ed3f20bbf0459ce6aed833c7e170ee6c927b |
| parent | 21767144fc1a8627a109e81a164c55171c279d82 |
17 files changed, 1173 insertions(+), 58 deletions(-)
CMakeLists.txt+3| ... | @@ -508,8 +508,11 @@ set(ZIG_STD_FILES | ... | @@ -508,8 +508,11 @@ set(ZIG_STD_FILES |
| 508 | "os/index.zig" | 508 | "os/index.zig" |
| 509 | "os/linux/errno.zig" | 509 | "os/linux/errno.zig" |
| 510 | "os/linux/index.zig" | 510 | "os/linux/index.zig" |
| 511 | "os/linux/vdso.zig" | ||
| 511 | "os/linux/x86_64.zig" | 512 | "os/linux/x86_64.zig" |
| 512 | "os/path.zig" | 513 | "os/path.zig" |
| 514 | "os/time.zig" | ||
| 515 | "os/epoch.zig" | ||
| 513 | "os/windows/error.zig" | 516 | "os/windows/error.zig" |
| 514 | "os/windows/index.zig" | 517 | "os/windows/index.zig" |
| 515 | "os/windows/util.zig" | 518 | "os/windows/util.zig" |
src/codegen.cpp+10| ... | @@ -3561,6 +3561,16 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn | ... | @@ -3561,6 +3561,16 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn |
| 3561 | LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val, | 3561 | LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val, |
| 3562 | success_order, failure_order, instruction->is_weak); | 3562 | success_order, failure_order, instruction->is_weak); |
| 3563 | 3563 | ||
| 3564 | TypeTableEntry *maybe_type = instruction->base.value.type; | ||
| 3565 | assert(maybe_type->id == TypeTableEntryIdMaybe); | ||
| 3566 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; | ||
| 3567 | |||
| 3568 | if (type_is_codegen_pointer(child_type)) { | ||
| 3569 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); | ||
| 3570 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); | ||
| 3571 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, ""); | ||
| 3572 | } | ||
| 3573 | |||
| 3564 | assert(instruction->tmp_ptr != nullptr); | 3574 | assert(instruction->tmp_ptr != nullptr); |
| 3565 | assert(type_has_bits(instruction->type)); | 3575 | assert(type_has_bits(instruction->type)); |
| 3566 | 3576 |
std/c/darwin.zig+18| ... | @@ -3,10 +3,28 @@ pub extern "c" fn _NSGetExecutablePath(buf: &u8, bufsize: &u32) c_int; | ... | @@ -3,10 +3,28 @@ pub extern "c" fn _NSGetExecutablePath(buf: &u8, bufsize: &u32) c_int; |
| 3 | 3 | ||
| 4 | pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: &u8, buf_len: usize, basep: &i64) usize; | 4 | pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: &u8, buf_len: usize, basep: &i64) usize; |
| 5 | 5 | ||
| 6 | pub extern "c" fn mach_absolute_time() u64; | ||
| 7 | pub extern "c" fn mach_timebase_info(tinfo: ?&mach_timebase_info_data) void; | ||
| 8 | |||
| 6 | pub use @import("../os/darwin_errno.zig"); | 9 | pub use @import("../os/darwin_errno.zig"); |
| 7 | 10 | ||
| 8 | pub const _errno = __error; | 11 | pub const _errno = __error; |
| 9 | 12 | ||
| 13 | pub const timeval = extern struct { | ||
| 14 | tv_sec: isize, | ||
| 15 | tv_usec: isize, | ||
| 16 | }; | ||
| 17 | |||
| 18 | pub const timezone = extern struct { | ||
| 19 | tz_minuteswest: i32, | ||
| 20 | tz_dsttime: i32, | ||
| 21 | }; | ||
| 22 | |||
| 23 | pub const mach_timebase_info_data = struct { | ||
| 24 | numer: u32, | ||
| 25 | denom: u32, | ||
| 26 | }; | ||
| 27 | |||
| 10 | /// Renamed to Stat to not conflict with the stat function. | 28 | /// Renamed to Stat to not conflict with the stat function. |
| 11 | pub const Stat = extern struct { | 29 | pub const Stat = extern struct { |
| 12 | dev: i32, | 30 | dev: i32, |
std/c/index.zig+1| ... | @@ -41,6 +41,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int; | ... | @@ -41,6 +41,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int; |
| 41 | pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) isize; | 41 | pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) isize; |
| 42 | pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) ?&u8; | 42 | pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) ?&u8; |
| 43 | pub extern "c" fn sigprocmask(how: c_int, noalias set: &const sigset_t, noalias oset: ?&sigset_t) c_int; | 43 | pub extern "c" fn sigprocmask(how: c_int, noalias set: &const sigset_t, noalias oset: ?&sigset_t) c_int; |
| 44 | pub extern "c" fn gettimeofday(tv: ?&timeval, tz: ?&timezone) c_int; | ||
| 44 | pub extern "c" fn sigaction(sig: c_int, noalias act: &const Sigaction, noalias oact: ?&Sigaction) c_int; | 45 | pub extern "c" fn sigaction(sig: c_int, noalias act: &const Sigaction, noalias oact: ?&Sigaction) c_int; |
| 45 | pub extern "c" fn nanosleep(rqtp: &const timespec, rmtp: ?&timespec) c_int; | 46 | pub extern "c" fn nanosleep(rqtp: &const timespec, rmtp: ?&timespec) c_int; |
| 46 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; | 47 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; |
std/elf.zig+611| ... | @@ -7,6 +7,246 @@ const mem = std.mem; | ... | @@ -7,6 +7,246 @@ const mem = std.mem; |
| 7 | const debug = std.debug; | 7 | const debug = std.debug; |
| 8 | const InStream = std.stream.InStream; | 8 | const InStream = std.stream.InStream; |
| 9 | 9 | ||
| 10 | pub const AT_NULL = 0; | ||
| 11 | pub const AT_IGNORE = 1; | ||
| 12 | pub const AT_EXECFD = 2; | ||
| 13 | pub const AT_PHDR = 3; | ||
| 14 | pub const AT_PHENT = 4; | ||
| 15 | pub const AT_PHNUM = 5; | ||
| 16 | pub const AT_PAGESZ = 6; | ||
| 17 | pub const AT_BASE = 7; | ||
| 18 | pub const AT_FLAGS = 8; | ||
| 19 | pub const AT_ENTRY = 9; | ||
| 20 | pub const AT_NOTELF = 10; | ||
| 21 | pub const AT_UID = 11; | ||
| 22 | pub const AT_EUID = 12; | ||
| 23 | pub const AT_GID = 13; | ||
| 24 | pub const AT_EGID = 14; | ||
| 25 | pub const AT_CLKTCK = 17; | ||
| 26 | pub const AT_PLATFORM = 15; | ||
| 27 | pub const AT_HWCAP = 16; | ||
| 28 | pub const AT_FPUCW = 18; | ||
| 29 | pub const AT_DCACHEBSIZE = 19; | ||
| 30 | pub const AT_ICACHEBSIZE = 20; | ||
| 31 | pub const AT_UCACHEBSIZE = 21; | ||
| 32 | pub const AT_IGNOREPPC = 22; | ||
| 33 | pub const AT_SECURE = 23; | ||
| 34 | pub const AT_BASE_PLATFORM = 24; | ||
| 35 | pub const AT_RANDOM = 25; | ||
| 36 | pub const AT_HWCAP2 = 26; | ||
| 37 | pub const AT_EXECFN = 31; | ||
| 38 | pub const AT_SYSINFO = 32; | ||
| 39 | pub const AT_SYSINFO_EHDR = 33; | ||
| 40 | pub const AT_L1I_CACHESHAPE = 34; | ||
| 41 | pub const AT_L1D_CACHESHAPE = 35; | ||
| 42 | pub const AT_L2_CACHESHAPE = 36; | ||
| 43 | pub const AT_L3_CACHESHAPE = 37; | ||
| 44 | pub const AT_L1I_CACHESIZE = 40; | ||
| 45 | pub const AT_L1I_CACHEGEOMETRY = 41; | ||
| 46 | pub const AT_L1D_CACHESIZE = 42; | ||
| 47 | pub const AT_L1D_CACHEGEOMETRY = 43; | ||
| 48 | pub const AT_L2_CACHESIZE = 44; | ||
| 49 | pub const AT_L2_CACHEGEOMETRY = 45; | ||
| 50 | pub const AT_L3_CACHESIZE = 46; | ||
| 51 | pub const AT_L3_CACHEGEOMETRY = 47; | ||
| 52 | |||
| 53 | pub const DT_NULL = 0; | ||
| 54 | pub const DT_NEEDED = 1; | ||
| 55 | pub const DT_PLTRELSZ = 2; | ||
| 56 | pub const DT_PLTGOT = 3; | ||
| 57 | pub const DT_HASH = 4; | ||
| 58 | pub const DT_STRTAB = 5; | ||
| 59 | pub const DT_SYMTAB = 6; | ||
| 60 | pub const DT_RELA = 7; | ||
| 61 | pub const DT_RELASZ = 8; | ||
| 62 | pub const DT_RELAENT = 9; | ||
| 63 | pub const DT_STRSZ = 10; | ||
| 64 | pub const DT_SYMENT = 11; | ||
| 65 | pub const DT_INIT = 12; | ||
| 66 | pub const DT_FINI = 13; | ||
| 67 | pub const DT_SONAME = 14; | ||
| 68 | pub const DT_RPATH = 15; | ||
| 69 | pub const DT_SYMBOLIC = 16; | ||
| 70 | pub const DT_REL = 17; | ||
| 71 | pub const DT_RELSZ = 18; | ||
| 72 | pub const DT_RELENT = 19; | ||
| 73 | pub const DT_PLTREL = 20; | ||
| 74 | pub const DT_DEBUG = 21; | ||
| 75 | pub const DT_TEXTREL = 22; | ||
| 76 | pub const DT_JMPREL = 23; | ||
| 77 | pub const DT_BIND_NOW = 24; | ||
| 78 | pub const DT_INIT_ARRAY = 25; | ||
| 79 | pub const DT_FINI_ARRAY = 26; | ||
| 80 | pub const DT_INIT_ARRAYSZ = 27; | ||
| 81 | pub const DT_FINI_ARRAYSZ = 28; | ||
| 82 | pub const DT_RUNPATH = 29; | ||
| 83 | pub const DT_FLAGS = 30; | ||
| 84 | pub const DT_ENCODING = 32; | ||
| 85 | pub const DT_PREINIT_ARRAY = 32; | ||
| 86 | pub const DT_PREINIT_ARRAYSZ = 33; | ||
| 87 | pub const DT_SYMTAB_SHNDX = 34; | ||
| 88 | pub const DT_NUM = 35; | ||
| 89 | pub const DT_LOOS = 0x6000000d; | ||
| 90 | pub const DT_HIOS = 0x6ffff000; | ||
| 91 | pub const DT_LOPROC = 0x70000000; | ||
| 92 | pub const DT_HIPROC = 0x7fffffff; | ||
| 93 | pub const DT_PROCNUM = DT_MIPS_NUM; | ||
| 94 | |||
| 95 | pub const DT_VALRNGLO = 0x6ffffd00; | ||
| 96 | pub const DT_GNU_PRELINKED = 0x6ffffdf5; | ||
| 97 | pub const DT_GNU_CONFLICTSZ = 0x6ffffdf6; | ||
| 98 | pub const DT_GNU_LIBLISTSZ = 0x6ffffdf7; | ||
| 99 | pub const DT_CHECKSUM = 0x6ffffdf8; | ||
| 100 | pub const DT_PLTPADSZ = 0x6ffffdf9; | ||
| 101 | pub const DT_MOVEENT = 0x6ffffdfa; | ||
| 102 | pub const DT_MOVESZ = 0x6ffffdfb; | ||
| 103 | pub const DT_FEATURE_1 = 0x6ffffdfc; | ||
| 104 | pub const DT_POSFLAG_1 = 0x6ffffdfd; | ||
| 105 | |||
| 106 | pub const DT_SYMINSZ = 0x6ffffdfe; | ||
| 107 | pub const DT_SYMINENT = 0x6ffffdff; | ||
| 108 | pub const DT_VALRNGHI = 0x6ffffdff; | ||
| 109 | pub const DT_VALNUM = 12; | ||
| 110 | |||
| 111 | pub const DT_ADDRRNGLO = 0x6ffffe00; | ||
| 112 | pub const DT_GNU_HASH = 0x6ffffef5; | ||
| 113 | pub const DT_TLSDESC_PLT = 0x6ffffef6; | ||
| 114 | pub const DT_TLSDESC_GOT = 0x6ffffef7; | ||
| 115 | pub const DT_GNU_CONFLICT = 0x6ffffef8; | ||
| 116 | pub const DT_GNU_LIBLIST = 0x6ffffef9; | ||
| 117 | pub const DT_CONFIG = 0x6ffffefa; | ||
| 118 | pub const DT_DEPAUDIT = 0x6ffffefb; | ||
| 119 | pub const DT_AUDIT = 0x6ffffefc; | ||
| 120 | pub const DT_PLTPAD = 0x6ffffefd; | ||
| 121 | pub const DT_MOVETAB = 0x6ffffefe; | ||
| 122 | pub const DT_SYMINFO = 0x6ffffeff; | ||
| 123 | pub const DT_ADDRRNGHI = 0x6ffffeff; | ||
| 124 | pub const DT_ADDRNUM = 11; | ||
| 125 | |||
| 126 | |||
| 127 | pub const DT_VERSYM = 0x6ffffff0; | ||
| 128 | |||
| 129 | pub const DT_RELACOUNT = 0x6ffffff9; | ||
| 130 | pub const DT_RELCOUNT = 0x6ffffffa; | ||
| 131 | |||
| 132 | |||
| 133 | pub const DT_FLAGS_1 = 0x6ffffffb; | ||
| 134 | pub const DT_VERDEF = 0x6ffffffc; | ||
| 135 | |||
| 136 | pub const DT_VERDEFNUM = 0x6ffffffd; | ||
| 137 | pub const DT_VERNEED = 0x6ffffffe; | ||
| 138 | |||
| 139 | pub const DT_VERNEEDNUM = 0x6fffffff; | ||
| 140 | pub const DT_VERSIONTAGNUM = 16; | ||
| 141 | |||
| 142 | |||
| 143 | |||
| 144 | pub const DT_AUXILIARY = 0x7ffffffd; | ||
| 145 | pub const DT_FILTER = 0x7fffffff; | ||
| 146 | pub const DT_EXTRANUM = 3; | ||
| 147 | |||
| 148 | |||
| 149 | pub const DT_SPARC_REGISTER = 0x70000001; | ||
| 150 | pub const DT_SPARC_NUM = 2; | ||
| 151 | |||
| 152 | pub const DT_MIPS_RLD_VERSION = 0x70000001; | ||
| 153 | pub const DT_MIPS_TIME_STAMP = 0x70000002; | ||
| 154 | pub const DT_MIPS_ICHECKSUM = 0x70000003; | ||
| 155 | pub const DT_MIPS_IVERSION = 0x70000004; | ||
| 156 | pub const DT_MIPS_FLAGS = 0x70000005; | ||
| 157 | pub const DT_MIPS_BASE_ADDRESS = 0x70000006; | ||
| 158 | pub const DT_MIPS_MSYM = 0x70000007; | ||
| 159 | pub const DT_MIPS_CONFLICT = 0x70000008; | ||
| 160 | pub const DT_MIPS_LIBLIST = 0x70000009; | ||
| 161 | pub const DT_MIPS_LOCAL_GOTNO = 0x7000000a; | ||
| 162 | pub const DT_MIPS_CONFLICTNO = 0x7000000b; | ||
| 163 | pub const DT_MIPS_LIBLISTNO = 0x70000010; | ||
| 164 | pub const DT_MIPS_SYMTABNO = 0x70000011; | ||
| 165 | pub const DT_MIPS_UNREFEXTNO = 0x70000012; | ||
| 166 | pub const DT_MIPS_GOTSYM = 0x70000013; | ||
| 167 | pub const DT_MIPS_HIPAGENO = 0x70000014; | ||
| 168 | pub const DT_MIPS_RLD_MAP = 0x70000016; | ||
| 169 | pub const DT_MIPS_DELTA_CLASS = 0x70000017; | ||
| 170 | pub const DT_MIPS_DELTA_CLASS_NO = 0x70000018; | ||
| 171 | |||
| 172 | pub const DT_MIPS_DELTA_INSTANCE = 0x70000019; | ||
| 173 | pub const DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a; | ||
| 174 | |||
| 175 | pub const DT_MIPS_DELTA_RELOC = 0x7000001b; | ||
| 176 | pub const DT_MIPS_DELTA_RELOC_NO = 0x7000001c; | ||
| 177 | |||
| 178 | pub const DT_MIPS_DELTA_SYM = 0x7000001d; | ||
| 179 | |||
| 180 | pub const DT_MIPS_DELTA_SYM_NO = 0x7000001e; | ||
| 181 | |||
| 182 | pub const DT_MIPS_DELTA_CLASSSYM = 0x70000020; | ||
| 183 | |||
| 184 | pub const DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021; | ||
| 185 | |||
| 186 | pub const DT_MIPS_CXX_FLAGS = 0x70000022; | ||
| 187 | pub const DT_MIPS_PIXIE_INIT = 0x70000023; | ||
| 188 | pub const DT_MIPS_SYMBOL_LIB = 0x70000024; | ||
| 189 | pub const DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025; | ||
| 190 | pub const DT_MIPS_LOCAL_GOTIDX = 0x70000026; | ||
| 191 | pub const DT_MIPS_HIDDEN_GOTIDX = 0x70000027; | ||
| 192 | pub const DT_MIPS_PROTECTED_GOTIDX = 0x70000028; | ||
| 193 | pub const DT_MIPS_OPTIONS = 0x70000029; | ||
| 194 | pub const DT_MIPS_INTERFACE = 0x7000002a; | ||
| 195 | pub const DT_MIPS_DYNSTR_ALIGN = 0x7000002b; | ||
| 196 | pub const DT_MIPS_INTERFACE_SIZE = 0x7000002c; | ||
| 197 | pub const DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002d; | ||
| 198 | |||
| 199 | pub const DT_MIPS_PERF_SUFFIX = 0x7000002e; | ||
| 200 | |||
| 201 | pub const DT_MIPS_COMPACT_SIZE = 0x7000002f; | ||
| 202 | pub const DT_MIPS_GP_VALUE = 0x70000030; | ||
| 203 | pub const DT_MIPS_AUX_DYNAMIC = 0x70000031; | ||
| 204 | |||
| 205 | pub const DT_MIPS_PLTGOT = 0x70000032; | ||
| 206 | |||
| 207 | pub const DT_MIPS_RWPLT = 0x70000034; | ||
| 208 | pub const DT_MIPS_RLD_MAP_REL = 0x70000035; | ||
| 209 | pub const DT_MIPS_NUM = 0x36; | ||
| 210 | |||
| 211 | pub const DT_ALPHA_PLTRO = (DT_LOPROC + 0); | ||
| 212 | pub const DT_ALPHA_NUM = 1; | ||
| 213 | |||
| 214 | pub const DT_PPC_GOT = (DT_LOPROC + 0); | ||
| 215 | pub const DT_PPC_OPT = (DT_LOPROC + 1); | ||
| 216 | pub const DT_PPC_NUM = 2; | ||
| 217 | |||
| 218 | pub const DT_PPC64_GLINK = (DT_LOPROC + 0); | ||
| 219 | pub const DT_PPC64_OPD = (DT_LOPROC + 1); | ||
| 220 | pub const DT_PPC64_OPDSZ = (DT_LOPROC + 2); | ||
| 221 | pub const DT_PPC64_OPT = (DT_LOPROC + 3); | ||
| 222 | pub const DT_PPC64_NUM = 4; | ||
| 223 | |||
| 224 | pub const DT_IA_64_PLT_RESERVE = (DT_LOPROC + 0); | ||
| 225 | pub const DT_IA_64_NUM = 1; | ||
| 226 | |||
| 227 | pub const DT_NIOS2_GP = 0x70000002; | ||
| 228 | |||
| 229 | pub const PT_NULL = 0; | ||
| 230 | pub const PT_LOAD = 1; | ||
| 231 | pub const PT_DYNAMIC = 2; | ||
| 232 | pub const PT_INTERP = 3; | ||
| 233 | pub const PT_NOTE = 4; | ||
| 234 | pub const PT_SHLIB = 5; | ||
| 235 | pub const PT_PHDR = 6; | ||
| 236 | pub const PT_TLS = 7; | ||
| 237 | pub const PT_NUM = 8; | ||
| 238 | pub const PT_LOOS = 0x60000000; | ||
| 239 | pub const PT_GNU_EH_FRAME = 0x6474e550; | ||
| 240 | pub const PT_GNU_STACK = 0x6474e551; | ||
| 241 | pub const PT_GNU_RELRO = 0x6474e552; | ||
| 242 | pub const PT_LOSUNW = 0x6ffffffa; | ||
| 243 | pub const PT_SUNWBSS = 0x6ffffffa; | ||
| 244 | pub const PT_SUNWSTACK = 0x6ffffffb; | ||
| 245 | pub const PT_HISUNW = 0x6fffffff; | ||
| 246 | pub const PT_HIOS = 0x6fffffff; | ||
| 247 | pub const PT_LOPROC = 0x70000000; | ||
| 248 | pub const PT_HIPROC = 0x7fffffff; | ||
| 249 | |||
| 10 | pub const SHT_NULL = 0; | 250 | pub const SHT_NULL = 0; |
| 11 | pub const SHT_PROGBITS = 1; | 251 | pub const SHT_PROGBITS = 1; |
| 12 | pub const SHT_SYMTAB = 2; | 252 | pub const SHT_SYMTAB = 2; |
| ... | @@ -31,6 +271,45 @@ pub const SHT_HIPROC = 0x7fffffff; | ... | @@ -31,6 +271,45 @@ pub const SHT_HIPROC = 0x7fffffff; |
| 31 | pub const SHT_LOUSER = 0x80000000; | 271 | pub const SHT_LOUSER = 0x80000000; |
| 32 | pub const SHT_HIUSER = 0xffffffff; | 272 | pub const SHT_HIUSER = 0xffffffff; |
| 33 | 273 | ||
| 274 | pub const STB_LOCAL = 0; | ||
| 275 | pub const STB_GLOBAL = 1; | ||
| 276 | pub const STB_WEAK = 2; | ||
| 277 | pub const STB_NUM = 3; | ||
| 278 | pub const STB_LOOS = 10; | ||
| 279 | pub const STB_GNU_UNIQUE = 10; | ||
| 280 | pub const STB_HIOS = 12; | ||
| 281 | pub const STB_LOPROC = 13; | ||
| 282 | pub const STB_HIPROC = 15; | ||
| 283 | |||
| 284 | pub const STB_MIPS_SPLIT_COMMON = 13; | ||
| 285 | |||
| 286 | pub const STT_NOTYPE = 0; | ||
| 287 | pub const STT_OBJECT = 1; | ||
| 288 | pub const STT_FUNC = 2; | ||
| 289 | pub const STT_SECTION = 3; | ||
| 290 | pub const STT_FILE = 4; | ||
| 291 | pub const STT_COMMON = 5; | ||
| 292 | pub const STT_TLS = 6; | ||
| 293 | pub const STT_NUM = 7; | ||
| 294 | pub const STT_LOOS = 10; | ||
| 295 | pub const STT_GNU_IFUNC = 10; | ||
| 296 | pub const STT_HIOS = 12; | ||
| 297 | pub const STT_LOPROC = 13; | ||
| 298 | pub const STT_HIPROC = 15; | ||
| 299 | |||
| 300 | pub const STT_SPARC_REGISTER = 13; | ||
| 301 | |||
| 302 | pub const STT_PARISC_MILLICODE = 13; | ||
| 303 | |||
| 304 | pub const STT_HP_OPAQUE = (STT_LOOS + 0x1); | ||
| 305 | pub const STT_HP_STUB = (STT_LOOS + 0x2); | ||
| 306 | |||
| 307 | pub const STT_ARM_TFUNC = STT_LOPROC; | ||
| 308 | pub const STT_ARM_16BIT = STT_HIPROC; | ||
| 309 | |||
| 310 | pub const VER_FLG_BASE = 0x1; | ||
| 311 | pub const VER_FLG_WEAK = 0x2; | ||
| 312 | |||
| 34 | pub const FileType = enum { | 313 | pub const FileType = enum { |
| 35 | Relocatable, | 314 | Relocatable, |
| 36 | Executable, | 315 | Executable, |
| ... | @@ -266,3 +545,335 @@ pub const Elf = struct { | ... | @@ -266,3 +545,335 @@ pub const Elf = struct { |
| 266 | try elf.in_file.seekTo(elf_section.offset); | 545 | try elf.in_file.seekTo(elf_section.offset); |
| 267 | } | 546 | } |
| 268 | }; | 547 | }; |
| 548 | |||
| 549 | pub const EI_NIDENT = 16; | ||
| 550 | pub const Elf32_Half = u16; | ||
| 551 | pub const Elf64_Half = u16; | ||
| 552 | pub const Elf32_Word = u32; | ||
| 553 | pub const Elf32_Sword = i32; | ||
| 554 | pub const Elf64_Word = u32; | ||
| 555 | pub const Elf64_Sword = i32; | ||
| 556 | pub const Elf32_Xword = u64; | ||
| 557 | pub const Elf32_Sxword = i64; | ||
| 558 | pub const Elf64_Xword = u64; | ||
| 559 | pub const Elf64_Sxword = i64; | ||
| 560 | pub const Elf32_Addr = u32; | ||
| 561 | pub const Elf64_Addr = u64; | ||
| 562 | pub const Elf32_Off = u32; | ||
| 563 | pub const Elf64_Off = u64; | ||
| 564 | pub const Elf32_Section = u16; | ||
| 565 | pub const Elf64_Section = u16; | ||
| 566 | pub const Elf32_Versym = Elf32_Half; | ||
| 567 | pub const Elf64_Versym = Elf64_Half; | ||
| 568 | pub const Elf32_Ehdr = extern struct { | ||
| 569 | e_ident: [EI_NIDENT]u8, | ||
| 570 | e_type: Elf32_Half, | ||
| 571 | e_machine: Elf32_Half, | ||
| 572 | e_version: Elf32_Word, | ||
| 573 | e_entry: Elf32_Addr, | ||
| 574 | e_phoff: Elf32_Off, | ||
| 575 | e_shoff: Elf32_Off, | ||
| 576 | e_flags: Elf32_Word, | ||
| 577 | e_ehsize: Elf32_Half, | ||
| 578 | e_phentsize: Elf32_Half, | ||
| 579 | e_phnum: Elf32_Half, | ||
| 580 | e_shentsize: Elf32_Half, | ||
| 581 | e_shnum: Elf32_Half, | ||
| 582 | e_shstrndx: Elf32_Half, | ||
| 583 | }; | ||
| 584 | pub const Elf64_Ehdr = extern struct { | ||
| 585 | e_ident: [EI_NIDENT]u8, | ||
| 586 | e_type: Elf64_Half, | ||
| 587 | e_machine: Elf64_Half, | ||
| 588 | e_version: Elf64_Word, | ||
| 589 | e_entry: Elf64_Addr, | ||
| 590 | e_phoff: Elf64_Off, | ||
| 591 | e_shoff: Elf64_Off, | ||
| 592 | e_flags: Elf64_Word, | ||
| 593 | e_ehsize: Elf64_Half, | ||
| 594 | e_phentsize: Elf64_Half, | ||
| 595 | e_phnum: Elf64_Half, | ||
| 596 | e_shentsize: Elf64_Half, | ||
| 597 | e_shnum: Elf64_Half, | ||
| 598 | e_shstrndx: Elf64_Half, | ||
| 599 | }; | ||
| 600 | pub const Elf32_Shdr = extern struct { | ||
| 601 | sh_name: Elf32_Word, | ||
| 602 | sh_type: Elf32_Word, | ||
| 603 | sh_flags: Elf32_Word, | ||
| 604 | sh_addr: Elf32_Addr, | ||
| 605 | sh_offset: Elf32_Off, | ||
| 606 | sh_size: Elf32_Word, | ||
| 607 | sh_link: Elf32_Word, | ||
| 608 | sh_info: Elf32_Word, | ||
| 609 | sh_addralign: Elf32_Word, | ||
| 610 | sh_entsize: Elf32_Word, | ||
| 611 | }; | ||
| 612 | pub const Elf64_Shdr = extern struct { | ||
| 613 | sh_name: Elf64_Word, | ||
| 614 | sh_type: Elf64_Word, | ||
| 615 | sh_flags: Elf64_Xword, | ||
| 616 | sh_addr: Elf64_Addr, | ||
| 617 | sh_offset: Elf64_Off, | ||
| 618 | sh_size: Elf64_Xword, | ||
| 619 | sh_link: Elf64_Word, | ||
| 620 | sh_info: Elf64_Word, | ||
| 621 | sh_addralign: Elf64_Xword, | ||
| 622 | sh_entsize: Elf64_Xword, | ||
| 623 | }; | ||
| 624 | pub const Elf32_Chdr = extern struct { | ||
| 625 | ch_type: Elf32_Word, | ||
| 626 | ch_size: Elf32_Word, | ||
| 627 | ch_addralign: Elf32_Word, | ||
| 628 | }; | ||
| 629 | pub const Elf64_Chdr = extern struct { | ||
| 630 | ch_type: Elf64_Word, | ||
| 631 | ch_reserved: Elf64_Word, | ||
| 632 | ch_size: Elf64_Xword, | ||
| 633 | ch_addralign: Elf64_Xword, | ||
| 634 | }; | ||
| 635 | pub const Elf32_Sym = extern struct { | ||
| 636 | st_name: Elf32_Word, | ||
| 637 | st_value: Elf32_Addr, | ||
| 638 | st_size: Elf32_Word, | ||
| 639 | st_info: u8, | ||
| 640 | st_other: u8, | ||
| 641 | st_shndx: Elf32_Section, | ||
| 642 | }; | ||
| 643 | pub const Elf64_Sym = extern struct { | ||
| 644 | st_name: Elf64_Word, | ||
| 645 | st_info: u8, | ||
| 646 | st_other: u8, | ||
| 647 | st_shndx: Elf64_Section, | ||
| 648 | st_value: Elf64_Addr, | ||
| 649 | st_size: Elf64_Xword, | ||
| 650 | }; | ||
| 651 | pub const Elf32_Syminfo = extern struct { | ||
| 652 | si_boundto: Elf32_Half, | ||
| 653 | si_flags: Elf32_Half, | ||
| 654 | }; | ||
| 655 | pub const Elf64_Syminfo = extern struct { | ||
| 656 | si_boundto: Elf64_Half, | ||
| 657 | si_flags: Elf64_Half, | ||
| 658 | }; | ||
| 659 | pub const Elf32_Rel = extern struct { | ||
| 660 | r_offset: Elf32_Addr, | ||
| 661 | r_info: Elf32_Word, | ||
| 662 | }; | ||
| 663 | pub const Elf64_Rel = extern struct { | ||
| 664 | r_offset: Elf64_Addr, | ||
| 665 | r_info: Elf64_Xword, | ||
| 666 | }; | ||
| 667 | pub const Elf32_Rela = extern struct { | ||
| 668 | r_offset: Elf32_Addr, | ||
| 669 | r_info: Elf32_Word, | ||
| 670 | r_addend: Elf32_Sword, | ||
| 671 | }; | ||
| 672 | pub const Elf64_Rela = extern struct { | ||
| 673 | r_offset: Elf64_Addr, | ||
| 674 | r_info: Elf64_Xword, | ||
| 675 | r_addend: Elf64_Sxword, | ||
| 676 | }; | ||
| 677 | pub const Elf32_Phdr = extern struct { | ||
| 678 | p_type: Elf32_Word, | ||
| 679 | p_offset: Elf32_Off, | ||
| 680 | p_vaddr: Elf32_Addr, | ||
| 681 | p_paddr: Elf32_Addr, | ||
| 682 | p_filesz: Elf32_Word, | ||
| 683 | p_memsz: Elf32_Word, | ||
| 684 | p_flags: Elf32_Word, | ||
| 685 | p_align: Elf32_Word, | ||
| 686 | }; | ||
| 687 | pub const Elf64_Phdr = extern struct { | ||
| 688 | p_type: Elf64_Word, | ||
| 689 | p_flags: Elf64_Word, | ||
| 690 | p_offset: Elf64_Off, | ||
| 691 | p_vaddr: Elf64_Addr, | ||
| 692 | p_paddr: Elf64_Addr, | ||
| 693 | p_filesz: Elf64_Xword, | ||
| 694 | p_memsz: Elf64_Xword, | ||
| 695 | p_align: Elf64_Xword, | ||
| 696 | }; | ||
| 697 | pub const Elf32_Dyn = extern struct { | ||
| 698 | d_tag: Elf32_Sword, | ||
| 699 | d_un: extern union { | ||
| 700 | d_val: Elf32_Word, | ||
| 701 | d_ptr: Elf32_Addr, | ||
| 702 | }, | ||
| 703 | }; | ||
| 704 | pub const Elf64_Dyn = extern struct { | ||
| 705 | d_tag: Elf64_Sxword, | ||
| 706 | d_un: extern union { | ||
| 707 | d_val: Elf64_Xword, | ||
| 708 | d_ptr: Elf64_Addr, | ||
| 709 | }, | ||
| 710 | }; | ||
| 711 | pub const Elf32_Verdef = extern struct { | ||
| 712 | vd_version: Elf32_Half, | ||
| 713 | vd_flags: Elf32_Half, | ||
| 714 | vd_ndx: Elf32_Half, | ||
| 715 | vd_cnt: Elf32_Half, | ||
| 716 | vd_hash: Elf32_Word, | ||
| 717 | vd_aux: Elf32_Word, | ||
| 718 | vd_next: Elf32_Word, | ||
| 719 | }; | ||
| 720 | pub const Elf64_Verdef = extern struct { | ||
| 721 | vd_version: Elf64_Half, | ||
| 722 | vd_flags: Elf64_Half, | ||
| 723 | vd_ndx: Elf64_Half, | ||
| 724 | vd_cnt: Elf64_Half, | ||
| 725 | vd_hash: Elf64_Word, | ||
| 726 | vd_aux: Elf64_Word, | ||
| 727 | vd_next: Elf64_Word, | ||
| 728 | }; | ||
| 729 | pub const Elf32_Verdaux = extern struct { | ||
| 730 | vda_name: Elf32_Word, | ||
| 731 | vda_next: Elf32_Word, | ||
| 732 | }; | ||
| 733 | pub const Elf64_Verdaux = extern struct { | ||
| 734 | vda_name: Elf64_Word, | ||
| 735 | vda_next: Elf64_Word, | ||
| 736 | }; | ||
| 737 | pub const Elf32_Verneed = extern struct { | ||
| 738 | vn_version: Elf32_Half, | ||
| 739 | vn_cnt: Elf32_Half, | ||
| 740 | vn_file: Elf32_Word, | ||
| 741 | vn_aux: Elf32_Word, | ||
| 742 | vn_next: Elf32_Word, | ||
| 743 | }; | ||
| 744 | pub const Elf64_Verneed = extern struct { | ||
| 745 | vn_version: Elf64_Half, | ||
| 746 | vn_cnt: Elf64_Half, | ||
| 747 | vn_file: Elf64_Word, | ||
| 748 | vn_aux: Elf64_Word, | ||
| 749 | vn_next: Elf64_Word, | ||
| 750 | }; | ||
| 751 | pub const Elf32_Vernaux = extern struct { | ||
| 752 | vna_hash: Elf32_Word, | ||
| 753 | vna_flags: Elf32_Half, | ||
| 754 | vna_other: Elf32_Half, | ||
| 755 | vna_name: Elf32_Word, | ||
| 756 | vna_next: Elf32_Word, | ||
| 757 | }; | ||
| 758 | pub const Elf64_Vernaux = extern struct { | ||
| 759 | vna_hash: Elf64_Word, | ||
| 760 | vna_flags: Elf64_Half, | ||
| 761 | vna_other: Elf64_Half, | ||
| 762 | vna_name: Elf64_Word, | ||
| 763 | vna_next: Elf64_Word, | ||
| 764 | }; | ||
| 765 | pub const Elf32_auxv_t = extern struct { | ||
| 766 | a_type: u32, | ||
| 767 | a_un: extern union { | ||
| 768 | a_val: u32, | ||
| 769 | }, | ||
| 770 | }; | ||
| 771 | pub const Elf64_auxv_t = extern struct { | ||
| 772 | a_type: u64, | ||
| 773 | a_un: extern union { | ||
| 774 | a_val: u64, | ||
| 775 | }, | ||
| 776 | }; | ||
| 777 | pub const Elf32_Nhdr = extern struct { | ||
| 778 | n_namesz: Elf32_Word, | ||
| 779 | n_descsz: Elf32_Word, | ||
| 780 | n_type: Elf32_Word, | ||
| 781 | }; | ||
| 782 | pub const Elf64_Nhdr = extern struct { | ||
| 783 | n_namesz: Elf64_Word, | ||
| 784 | n_descsz: Elf64_Word, | ||
| 785 | n_type: Elf64_Word, | ||
| 786 | }; | ||
| 787 | pub const Elf32_Move = extern struct { | ||
| 788 | m_value: Elf32_Xword, | ||
| 789 | m_info: Elf32_Word, | ||
| 790 | m_poffset: Elf32_Word, | ||
| 791 | m_repeat: Elf32_Half, | ||
| 792 | m_stride: Elf32_Half, | ||
| 793 | }; | ||
| 794 | pub const Elf64_Move = extern struct { | ||
| 795 | m_value: Elf64_Xword, | ||
| 796 | m_info: Elf64_Xword, | ||
| 797 | m_poffset: Elf64_Xword, | ||
| 798 | m_repeat: Elf64_Half, | ||
| 799 | m_stride: Elf64_Half, | ||
| 800 | }; | ||
| 801 | pub const Elf32_gptab = extern union { | ||
| 802 | gt_header: extern struct { | ||
| 803 | gt_current_g_value: Elf32_Word, | ||
| 804 | gt_unused: Elf32_Word, | ||
| 805 | }, | ||
| 806 | gt_entry: extern struct { | ||
| 807 | gt_g_value: Elf32_Word, | ||
| 808 | gt_bytes: Elf32_Word, | ||
| 809 | }, | ||
| 810 | }; | ||
| 811 | pub const Elf32_RegInfo = extern struct { | ||
| 812 | ri_gprmask: Elf32_Word, | ||
| 813 | ri_cprmask: [4]Elf32_Word, | ||
| 814 | ri_gp_value: Elf32_Sword, | ||
| 815 | }; | ||
| 816 | pub const Elf_Options = extern struct { | ||
| 817 | kind: u8, | ||
| 818 | size: u8, | ||
| 819 | @"section": Elf32_Section, | ||
| 820 | info: Elf32_Word, | ||
| 821 | }; | ||
| 822 | pub const Elf_Options_Hw = extern struct { | ||
| 823 | hwp_flags1: Elf32_Word, | ||
| 824 | hwp_flags2: Elf32_Word, | ||
| 825 | }; | ||
| 826 | pub const Elf32_Lib = extern struct { | ||
| 827 | l_name: Elf32_Word, | ||
| 828 | l_time_stamp: Elf32_Word, | ||
| 829 | l_checksum: Elf32_Word, | ||
| 830 | l_version: Elf32_Word, | ||
| 831 | l_flags: Elf32_Word, | ||
| 832 | }; | ||
| 833 | pub const Elf64_Lib = extern struct { | ||
| 834 | l_name: Elf64_Word, | ||
| 835 | l_time_stamp: Elf64_Word, | ||
| 836 | l_checksum: Elf64_Word, | ||
| 837 | l_version: Elf64_Word, | ||
| 838 | l_flags: Elf64_Word, | ||
| 839 | }; | ||
| 840 | pub const Elf32_Conflict = Elf32_Addr; | ||
| 841 | pub const Elf_MIPS_ABIFlags_v0 = extern struct { | ||
| 842 | version: Elf32_Half, | ||
| 843 | isa_level: u8, | ||
| 844 | isa_rev: u8, | ||
| 845 | gpr_size: u8, | ||
| 846 | cpr1_size: u8, | ||
| 847 | cpr2_size: u8, | ||
| 848 | fp_abi: u8, | ||
| 849 | isa_ext: Elf32_Word, | ||
| 850 | ases: Elf32_Word, | ||
| 851 | flags1: Elf32_Word, | ||
| 852 | flags2: Elf32_Word, | ||
| 853 | }; | ||
| 854 | |||
| 855 | pub const Ehdr = switch(@sizeOf(usize)) { | ||
| 856 | 4 => Elf32_Ehdr, | ||
| 857 | 8 => Elf64_Ehdr, | ||
| 858 | else => @compileError("expected pointer size of 32 or 64"), | ||
| 859 | }; | ||
| 860 | pub const Phdr = switch(@sizeOf(usize)) { | ||
| 861 | 4 => Elf32_Phdr, | ||
| 862 | 8 => Elf64_Phdr, | ||
| 863 | else => @compileError("expected pointer size of 32 or 64"), | ||
| 864 | }; | ||
| 865 | pub const Sym = switch(@sizeOf(usize)) { | ||
| 866 | 4 => Elf32_Sym, | ||
| 867 | 8 => Elf64_Sym, | ||
| 868 | else => @compileError("expected pointer size of 32 or 64"), | ||
| 869 | }; | ||
| 870 | pub const Verdef = switch(@sizeOf(usize)) { | ||
| 871 | 4 => Elf32_Verdef, | ||
| 872 | 8 => Elf64_Verdef, | ||
| 873 | else => @compileError("expected pointer size of 32 or 64"), | ||
| 874 | }; | ||
| 875 | pub const Verdaux = switch(@sizeOf(usize)) { | ||
| 876 | 4 => Elf32_Verdaux, | ||
| 877 | 8 => Elf64_Verdaux, | ||
| 878 | else => @compileError("expected pointer size of 32 or 64"), | ||
| 879 | }; |
std/fmt/index.zig+2-1| ... | @@ -86,7 +86,8 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), | ... | @@ -86,7 +86,8 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), |
| 86 | }, | 86 | }, |
| 87 | 's' => { | 87 | 's' => { |
| 88 | state = State.Buf; | 88 | state = State.Buf; |
| 89 | },'.' => { | 89 | }, |
| 90 | '.' => { | ||
| 90 | state = State.Float; | 91 | state = State.Float; |
| 91 | }, | 92 | }, |
| 92 | else => @compileError("Unknown format character: " ++ []u8{c}), | 93 | else => @compileError("Unknown format character: " ++ []u8{c}), |
std/os/darwin.zig+12| ... | @@ -260,6 +260,10 @@ pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) u | ... | @@ -260,6 +260,10 @@ pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) u |
| 260 | return errnoWrap(c.readlink(path, buf_ptr, buf_len)); | 260 | return errnoWrap(c.readlink(path, buf_ptr, buf_len)); |
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | pub fn gettimeofday(tv: ?&timeval, tz: ?&timezone) usize { | ||
| 264 | return errnoWrap(c.gettimeofday(tv, tz)); | ||
| 265 | } | ||
| 266 | |||
| 263 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize { | 267 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize { |
| 264 | return errnoWrap(c.nanosleep(req, rem)); | 268 | return errnoWrap(c.nanosleep(req, rem)); |
| 265 | } | 269 | } |
| ... | @@ -330,3 +334,11 @@ pub fn sigaddset(set: &sigset_t, signo: u5) void { | ... | @@ -330,3 +334,11 @@ pub fn sigaddset(set: &sigset_t, signo: u5) void { |
| 330 | fn errnoWrap(value: isize) usize { | 334 | fn errnoWrap(value: isize) usize { |
| 331 | return @bitCast(usize, if (value == -1) -isize(*c._errno()) else value); | 335 | return @bitCast(usize, if (value == -1) -isize(*c._errno()) else value); |
| 332 | } | 336 | } |
| 337 | |||
| 338 | |||
| 339 | pub const timezone = c.timezone; | ||
| 340 | pub const timeval = c.timeval; | ||
| 341 | pub const mach_timebase_info_data = c.mach_timebase_info_data; | ||
| 342 | |||
| 343 | pub const mach_absolute_time = c.mach_absolute_time; | ||
| 344 | pub const mach_timebase_info = c.mach_timebase_info; | ||
| \ No newline at end of file | |||
std/os/epoch.zig created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | /// Epoch reference times in terms of their difference from | ||
| 2 | /// posix epoch in seconds. | ||
| 3 | pub const posix = 0; //Jan 01, 1970 AD | ||
| 4 | pub const dos = 315532800; //Jan 01, 1980 AD | ||
| 5 | pub const ios = 978307200; //Jan 01, 2001 AD | ||
| 6 | pub const openvms = -3506716800; //Nov 17, 1858 AD | ||
| 7 | pub const zos = -2208988800; //Jan 01, 1900 AD | ||
| 8 | pub const windows = -11644473600; //Jan 01, 1601 AD | ||
| 9 | pub const amiga = 252460800; //Jan 01, 1978 AD | ||
| 10 | pub const pickos = -63244800; //Dec 31, 1967 AD | ||
| 11 | pub const gps = 315964800; //Jan 06, 1980 AD | ||
| 12 | pub const clr = -62135769600; //Jan 01, 0001 AD | ||
| 13 | |||
| 14 | pub const unix = posix; | ||
| 15 | pub const android = posix; | ||
| 16 | pub const os2 = dos; | ||
| 17 | pub const bios = dos; | ||
| 18 | pub const vfat = dos; | ||
| 19 | pub const ntfs = windows; | ||
| 20 | pub const ntp = zos; | ||
| 21 | pub const jbase = pickos; | ||
| 22 | pub const aros = amiga; | ||
| 23 | pub const morphos = amiga; | ||
| 24 | pub const brew = gps; | ||
| 25 | pub const atsc = gps; | ||
| 26 | pub const go = clr; | ||
| \ No newline at end of file | |||
std/os/index.zig+3-46| ... | @@ -9,11 +9,10 @@ test "std.os" { | ... | @@ -9,11 +9,10 @@ test "std.os" { |
| 9 | _ = @import("darwin.zig"); | 9 | _ = @import("darwin.zig"); |
| 10 | _ = @import("darwin_errno.zig"); | 10 | _ = @import("darwin_errno.zig"); |
| 11 | _ = @import("get_user_id.zig"); | 11 | _ = @import("get_user_id.zig"); |
| 12 | _ = @import("linux/errno.zig"); | ||
| 13 | _ = @import("linux/index.zig"); | 12 | _ = @import("linux/index.zig"); |
| 14 | _ = @import("linux/x86_64.zig"); | ||
| 15 | _ = @import("path.zig"); | 13 | _ = @import("path.zig"); |
| 16 | _ = @import("test.zig"); | 14 | _ = @import("test.zig"); |
| 15 | _ = @import("time.zig"); | ||
| 17 | _ = @import("windows/index.zig"); | 16 | _ = @import("windows/index.zig"); |
| 18 | } | 17 | } |
| 19 | 18 | ||
| ... | @@ -32,6 +31,7 @@ pub const net = @import("net.zig"); | ... | @@ -32,6 +31,7 @@ pub const net = @import("net.zig"); |
| 32 | pub const ChildProcess = @import("child_process.zig").ChildProcess; | 31 | pub const ChildProcess = @import("child_process.zig").ChildProcess; |
| 33 | pub const path = @import("path.zig"); | 32 | pub const path = @import("path.zig"); |
| 34 | pub const File = @import("file.zig").File; | 33 | pub const File = @import("file.zig").File; |
| 34 | pub const time = @import("time.zig"); | ||
| 35 | 35 | ||
| 36 | pub const FileMode = switch (builtin.os) { | 36 | pub const FileMode = switch (builtin.os) { |
| 37 | Os.windows => void, | 37 | Os.windows => void, |
| ... | @@ -478,6 +478,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { | ... | @@ -478,6 +478,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { |
| 478 | }; | 478 | }; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | pub var linux_aux_raw = []usize{0} ** 38; | ||
| 481 | pub var posix_environ_raw: []&u8 = undefined; | 482 | pub var posix_environ_raw: []&u8 = undefined; |
| 482 | 483 | ||
| 483 | /// Caller must free result when done. | 484 | /// Caller must free result when done. |
| ... | @@ -1379,50 +1380,6 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 { | ... | @@ -1379,50 +1380,6 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 { |
| 1379 | } | 1380 | } |
| 1380 | } | 1381 | } |
| 1381 | 1382 | ||
| 1382 | pub fn sleep(seconds: usize, nanoseconds: usize) void { | ||
| 1383 | switch(builtin.os) { | ||
| 1384 | Os.linux, Os.macosx, Os.ios => { | ||
| 1385 | posixSleep(u63(seconds), u63(nanoseconds)); | ||
| 1386 | }, | ||
| 1387 | Os.windows => { | ||
| 1388 | const milliseconds = seconds * 1000 + nanoseconds / 1000000; | ||
| 1389 | windows.Sleep(windows.DWORD(milliseconds)); | ||
| 1390 | }, | ||
| 1391 | else => @compileError("Unsupported OS"), | ||
| 1392 | } | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | const u63 = @IntType(false, 63); | ||
| 1396 | pub fn posixSleep(seconds: u63, nanoseconds: u63) void { | ||
| 1397 | var req = posix.timespec { | ||
| 1398 | .tv_sec = seconds, | ||
| 1399 | .tv_nsec = nanoseconds, | ||
| 1400 | }; | ||
| 1401 | var rem: posix.timespec = undefined; | ||
| 1402 | while (true) { | ||
| 1403 | const ret_val = posix.nanosleep(&req, &rem); | ||
| 1404 | const err = posix.getErrno(ret_val); | ||
| 1405 | if (err == 0) return; | ||
| 1406 | switch (err) { | ||
| 1407 | posix.EFAULT => unreachable, | ||
| 1408 | posix.EINVAL => { | ||
| 1409 | // Sometimes Darwin returns EINVAL for no reason. | ||
| 1410 | // We treat it as a spurious wakeup. | ||
| 1411 | return; | ||
| 1412 | }, | ||
| 1413 | posix.EINTR => { | ||
| 1414 | req = rem; | ||
| 1415 | continue; | ||
| 1416 | }, | ||
| 1417 | else => return, | ||
| 1418 | } | ||
| 1419 | } | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | test "os.sleep" { | ||
| 1423 | sleep(0, 1); | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | pub fn posix_setuid(uid: u32) !void { | 1383 | pub fn posix_setuid(uid: u32) !void { |
| 1427 | const err = posix.getErrno(posix.setuid(uid)); | 1384 | const err = posix.getErrno(posix.setuid(uid)); |
| 1428 | if (err == 0) return; | 1385 | if (err == 0) return; |
std/os/linux/index.zig+41-3| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const vdso = @import("vdso.zig"); | ||
| 4 | pub use switch (builtin.arch) { | 5 | pub use switch (builtin.arch) { |
| 5 | builtin.Arch.x86_64 => @import("x86_64.zig"), | 6 | builtin.Arch.x86_64 => @import("x86_64.zig"), |
| 6 | builtin.Arch.i386 => @import("i386.zig"), | 7 | builtin.Arch.i386 => @import("i386.zig"), |
| ... | @@ -805,6 +806,45 @@ pub fn waitpid(pid: i32, status: &i32, options: i32) usize { | ... | @@ -805,6 +806,45 @@ pub fn waitpid(pid: i32, status: &i32, options: i32) usize { |
| 805 | return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0); | 806 | return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0); |
| 806 | } | 807 | } |
| 807 | 808 | ||
| 809 | pub fn clock_gettime(clk_id: i32, tp: &timespec) usize { | ||
| 810 | if (VDSO_CGT_SYM.len != 0) { | ||
| 811 | const f = @atomicLoad(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, builtin.AtomicOrder.Unordered); | ||
| 812 | if (@ptrToInt(f) != 0) { | ||
| 813 | const rc = f(clk_id, tp); | ||
| 814 | switch (rc) { | ||
| 815 | 0, @bitCast(usize, isize(-EINVAL)) => return rc, | ||
| 816 | else => {}, | ||
| 817 | } | ||
| 818 | } | ||
| 819 | } | ||
| 820 | return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); | ||
| 821 | } | ||
| 822 | var vdso_clock_gettime = init_vdso_clock_gettime; | ||
| 823 | extern fn init_vdso_clock_gettime(clk: i32, ts: &timespec) usize { | ||
| 824 | const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM); | ||
| 825 | var f = @intToPtr(@typeOf(init_vdso_clock_gettime), addr); | ||
| 826 | _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, | ||
| 827 | builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic); | ||
| 828 | if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS)); | ||
| 829 | return f(clk, ts); | ||
| 830 | } | ||
| 831 | |||
| 832 | pub fn clock_getres(clk_id: i32, tp: &timespec) usize { | ||
| 833 | return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); | ||
| 834 | } | ||
| 835 | |||
| 836 | pub fn clock_settime(clk_id: i32, tp: &const timespec) usize { | ||
| 837 | return syscall2(SYS_clock_settime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); | ||
| 838 | } | ||
| 839 | |||
| 840 | pub fn gettimeofday(tv: &timeval, tz: &timezone) usize { | ||
| 841 | return syscall2(SYS_gettimeofday, @ptrToInt(tv), @ptrToInt(tz)); | ||
| 842 | } | ||
| 843 | |||
| 844 | pub fn settimeofday(tv: &const timeval, tz: &const timezone) usize { | ||
| 845 | return syscall2(SYS_settimeofday, @ptrToInt(tv), @ptrToInt(tz)); | ||
| 846 | } | ||
| 847 | |||
| 808 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize { | 848 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize { |
| 809 | return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)); | 849 | return syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)); |
| 810 | } | 850 | } |
| ... | @@ -1289,9 +1329,7 @@ pub fn capset(hdrp: &cap_user_header_t, datap: &const cap_user_data_t) usize { | ... | @@ -1289,9 +1329,7 @@ pub fn capset(hdrp: &cap_user_header_t, datap: &const cap_user_data_t) usize { |
| 1289 | return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap)); | 1329 | return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap)); |
| 1290 | } | 1330 | } |
| 1291 | 1331 | ||
| 1292 | test "import linux test" { | 1332 | test "import" { |
| 1293 | // TODO lazy analysis should prevent this test from being compiled on windows, but | ||
| 1294 | // it is still compiled on windows | ||
| 1295 | if (builtin.os == builtin.Os.linux) { | 1333 | if (builtin.os == builtin.Os.linux) { |
| 1296 | _ = @import("test.zig"); | 1334 | _ = @import("test.zig"); |
| 1297 | } | 1335 | } |
std/os/linux/test.zig+1| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("../../index.zig"); | 1 | const std = @import("../../index.zig"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | const linux = std.os.linux; | 3 | const linux = std.os.linux; |
| 3 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 4 | 5 |
std/os/linux/vdso.zig created+89| ... | @@ -0,0 +1,89 @@ | ||
| 1 | const std = @import("../../index.zig"); | ||
| 2 | const elf = std.elf; | ||
| 3 | const linux = std.os.linux; | ||
| 4 | const cstr = std.cstr; | ||
| 5 | const mem = std.mem; | ||
| 6 | |||
| 7 | pub fn lookup(vername: []const u8, name: []const u8) usize { | ||
| 8 | const vdso_addr = std.os.linux_aux_raw[std.elf.AT_SYSINFO_EHDR]; | ||
| 9 | if (vdso_addr == 0) return 0; | ||
| 10 | |||
| 11 | const eh = @intToPtr(&elf.Ehdr, vdso_addr); | ||
| 12 | var ph_addr: usize = vdso_addr + eh.e_phoff; | ||
| 13 | const ph = @intToPtr(&elf.Phdr, ph_addr); | ||
| 14 | |||
| 15 | var maybe_dynv: ?&usize = null; | ||
| 16 | var base: usize = @maxValue(usize); | ||
| 17 | { | ||
| 18 | var i: usize = 0; | ||
| 19 | while (i < eh.e_phnum) : ({i += 1; ph_addr += eh.e_phentsize;}) { | ||
| 20 | const this_ph = @intToPtr(&elf.Phdr, ph_addr); | ||
| 21 | switch (this_ph.p_type) { | ||
| 22 | elf.PT_LOAD => base = vdso_addr + this_ph.p_offset - this_ph.p_vaddr, | ||
| 23 | elf.PT_DYNAMIC => maybe_dynv = @intToPtr(&usize, vdso_addr + this_ph.p_offset), | ||
| 24 | else => {}, | ||
| 25 | } | ||
| 26 | } | ||
| 27 | } | ||
| 28 | const dynv = maybe_dynv ?? return 0; | ||
| 29 | if (base == @maxValue(usize)) return 0; | ||
| 30 | |||
| 31 | var maybe_strings: ?&u8 = null; | ||
| 32 | var maybe_syms: ?&elf.Sym = null; | ||
| 33 | var maybe_hashtab: ?&linux.Elf_Symndx = null; | ||
| 34 | var maybe_versym: ?&u16 = null; | ||
| 35 | var maybe_verdef: ?&elf.Verdef = null; | ||
| 36 | |||
| 37 | { | ||
| 38 | var i: usize = 0; | ||
| 39 | while (dynv[i] != 0) : (i += 2) { | ||
| 40 | const p = base + dynv[i + 1]; | ||
| 41 | switch (dynv[i]) { | ||
| 42 | elf.DT_STRTAB => maybe_strings = @intToPtr(&u8, p), | ||
| 43 | elf.DT_SYMTAB => maybe_syms = @intToPtr(&elf.Sym, p), | ||
| 44 | elf.DT_HASH => maybe_hashtab = @intToPtr(&linux.Elf_Symndx, p), | ||
| 45 | elf.DT_VERSYM => maybe_versym = @intToPtr(&u16, p), | ||
| 46 | elf.DT_VERDEF => maybe_verdef = @intToPtr(&elf.Verdef, p), | ||
| 47 | else => {}, | ||
| 48 | } | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | const strings = maybe_strings ?? return 0; | ||
| 53 | const syms = maybe_syms ?? return 0; | ||
| 54 | const hashtab = maybe_hashtab ?? return 0; | ||
| 55 | if (maybe_verdef == null) maybe_versym = null; | ||
| 56 | |||
| 57 | |||
| 58 | const OK_TYPES = (1<<elf.STT_NOTYPE | 1<<elf.STT_OBJECT | 1<<elf.STT_FUNC | 1<<elf.STT_COMMON); | ||
| 59 | const OK_BINDS = (1<<elf.STB_GLOBAL | 1<<elf.STB_WEAK | 1<<elf.STB_GNU_UNIQUE); | ||
| 60 | |||
| 61 | var i: usize = 0; | ||
| 62 | while (i < hashtab[1]) : (i += 1) { | ||
| 63 | if (0==(u32(1)<<u5(syms[i].st_info&0xf) & OK_TYPES)) continue; | ||
| 64 | if (0==(u32(1)<<u5(syms[i].st_info>>4) & OK_BINDS)) continue; | ||
| 65 | if (0==syms[i].st_shndx) continue; | ||
| 66 | if (!mem.eql(u8, name, cstr.toSliceConst(&strings[syms[i].st_name]))) continue; | ||
| 67 | if (maybe_versym) |versym| { | ||
| 68 | if (!checkver(??maybe_verdef, versym[i], vername, strings)) | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | return base + syms[i].st_value; | ||
| 72 | } | ||
| 73 | |||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | fn checkver(def_arg: &elf.Verdef, vsym_arg: i32, vername: []const u8, strings: &u8) bool { | ||
| 78 | var def = def_arg; | ||
| 79 | const vsym = @bitCast(u32, vsym_arg) & 0x7fff; | ||
| 80 | while (true) { | ||
| 81 | if (0==(def.vd_flags & elf.VER_FLG_BASE) and (def.vd_ndx & 0x7fff) == vsym) | ||
| 82 | break; | ||
| 83 | if (def.vd_next == 0) | ||
| 84 | return false; | ||
| 85 | def = @intToPtr(&elf.Verdef, @ptrToInt(def) + def.vd_next); | ||
| 86 | } | ||
| 87 | const aux = @intToPtr(&elf.Verdaux, @ptrToInt(def ) + def.vd_aux); | ||
| 88 | return mem.eql(u8, vername, cstr.toSliceConst(&strings[aux.vda_name])); | ||
| 89 | } | ||
std/os/linux/x86_64.zig+18| ... | @@ -371,6 +371,13 @@ pub const F_GETOWN_EX = 16; | ... | @@ -371,6 +371,13 @@ pub const F_GETOWN_EX = 16; |
| 371 | 371 | ||
| 372 | pub const F_GETOWNER_UIDS = 17; | 372 | pub const F_GETOWNER_UIDS = 17; |
| 373 | 373 | ||
| 374 | |||
| 375 | pub const VDSO_USEFUL = true; | ||
| 376 | pub const VDSO_CGT_SYM = "__vdso_clock_gettime"; | ||
| 377 | pub const VDSO_CGT_VER = "LINUX_2.6"; | ||
| 378 | pub const VDSO_GETCPU_SYM = "__vdso_getcpu"; | ||
| 379 | pub const VDSO_GETCPU_VER = "LINUX_2.6"; | ||
| 380 | |||
| 374 | pub fn syscall0(number: usize) usize { | 381 | pub fn syscall0(number: usize) usize { |
| 375 | return asm volatile ("syscall" | 382 | return asm volatile ("syscall" |
| 376 | : [ret] "={rax}" (-> usize) | 383 | : [ret] "={rax}" (-> usize) |
| ... | @@ -492,6 +499,16 @@ pub const timespec = extern struct { | ... | @@ -492,6 +499,16 @@ pub const timespec = extern struct { |
| 492 | tv_nsec: isize, | 499 | tv_nsec: isize, |
| 493 | }; | 500 | }; |
| 494 | 501 | ||
| 502 | pub const timeval = extern struct { | ||
| 503 | tv_sec: isize, | ||
| 504 | tv_usec: isize, | ||
| 505 | }; | ||
| 506 | |||
| 507 | pub const timezone = extern struct { | ||
| 508 | tz_minuteswest: i32, | ||
| 509 | tz_dsttime: i32, | ||
| 510 | }; | ||
| 511 | |||
| 495 | pub const dirent = extern struct { | 512 | pub const dirent = extern struct { |
| 496 | d_ino: usize, | 513 | d_ino: usize, |
| 497 | d_off: usize, | 514 | d_off: usize, |
| ... | @@ -499,3 +516,4 @@ pub const dirent = extern struct { | ... | @@ -499,3 +516,4 @@ pub const dirent = extern struct { |
| 499 | d_name: u8, // field address is the address of first byte of name | 516 | d_name: u8, // field address is the address of first byte of name |
| 500 | }; | 517 | }; |
| 501 | 518 | ||
| 519 | pub const Elf_Symndx = u32; |
std/os/time.zig created+288| ... | @@ -0,0 +1,288 @@ | ||
| 1 | const std = @import("../index.zig"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const Os = builtin.Os; | ||
| 4 | const debug = std.debug; | ||
| 5 | |||
| 6 | const windows = std.os.windows; | ||
| 7 | const linux = std.os.linux; | ||
| 8 | const darwin = std.os.darwin; | ||
| 9 | const posix = std.os.posix; | ||
| 10 | |||
| 11 | pub const epoch = @import("epoch.zig"); | ||
| 12 | |||
| 13 | /// Sleep for the specified duration | ||
| 14 | pub fn sleep(seconds: usize, nanoseconds: usize) void { | ||
| 15 | switch (builtin.os) { | ||
| 16 | Os.linux, Os.macosx, Os.ios => { | ||
| 17 | posixSleep(u63(seconds), u63(nanoseconds)); | ||
| 18 | }, | ||
| 19 | Os.windows => { | ||
| 20 | const ns_per_ms = ns_per_s / ms_per_s; | ||
| 21 | const milliseconds = seconds * ms_per_s + nanoseconds / ns_per_ms; | ||
| 22 | windows.Sleep(windows.DWORD(milliseconds)); | ||
| 23 | }, | ||
| 24 | else => @compileError("Unsupported OS"), | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | const u63 = @IntType(false, 63); | ||
| 29 | pub fn posixSleep(seconds: u63, nanoseconds: u63) void { | ||
| 30 | var req = posix.timespec { | ||
| 31 | .tv_sec = seconds, | ||
| 32 | .tv_nsec = nanoseconds, | ||
| 33 | }; | ||
| 34 | var rem: posix.timespec = undefined; | ||
| 35 | while (true) { | ||
| 36 | const ret_val = posix.nanosleep(&req, &rem); | ||
| 37 | const err = posix.getErrno(ret_val); | ||
| 38 | if (err == 0) return; | ||
| 39 | switch (err) { | ||
| 40 | posix.EFAULT => unreachable, | ||
| 41 | posix.EINVAL => { | ||
| 42 | // Sometimes Darwin returns EINVAL for no reason. | ||
| 43 | // We treat it as a spurious wakeup. | ||
| 44 | return; | ||
| 45 | }, | ||
| 46 | posix.EINTR => { | ||
| 47 | req = rem; | ||
| 48 | continue; | ||
| 49 | }, | ||
| 50 | else => return, | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | /// Get the posix timestamp, UTC, in seconds | ||
| 56 | pub fn timestamp() u64 { | ||
| 57 | return @divFloor(milliTimestamp(), ms_per_s); | ||
| 58 | } | ||
| 59 | |||
| 60 | /// Get the posix timestamp, UTC, in milliseconds | ||
| 61 | pub const milliTimestamp = switch (builtin.os) { | ||
| 62 | Os.windows => milliTimestampWindows, | ||
| 63 | Os.linux => milliTimestampPosix, | ||
| 64 | Os.macosx, Os.ios => milliTimestampDarwin, | ||
| 65 | else => @compileError("Unsupported OS"), | ||
| 66 | }; | ||
| 67 | |||
| 68 | fn milliTimestampWindows() u64 { | ||
| 69 | //FileTime has a granularity of 100 nanoseconds | ||
| 70 | // and uses the NTFS/Windows epoch | ||
| 71 | var ft: i64 = undefined; | ||
| 72 | windows.GetSystemTimeAsFileTime(&ft); | ||
| 73 | const hns_per_ms = (ns_per_s / 100) / ms_per_s; | ||
| 74 | const epoch_adj = epoch.windows * ms_per_s; | ||
| 75 | return u64(@divFloor(ft, hns_per_ms) + epoch_adj); | ||
| 76 | } | ||
| 77 | |||
| 78 | fn milliTimestampDarwin() u64 { | ||
| 79 | //Sources suggest MacOS 10.12 has support for | ||
| 80 | // posix clock_gettime. | ||
| 81 | var tv: darwin.timeval = undefined; | ||
| 82 | var err = darwin.gettimeofday(&tv, null); | ||
| 83 | debug.assert(err == 0); | ||
| 84 | const sec_ms = u64(tv.tv_sec) * ms_per_s; | ||
| 85 | const usec_ms = @divFloor(u64(tv.tv_usec), us_per_s / ms_per_s); | ||
| 86 | return u64(sec_ms) + u64(usec_ms); | ||
| 87 | } | ||
| 88 | |||
| 89 | fn milliTimestampPosix() u64 { | ||
| 90 | //From what I can tell there's no reason clock_gettime | ||
| 91 | // should ever fail for us with CLOCK_REALTIME, | ||
| 92 | // seccomp aside. | ||
| 93 | var ts: posix.timespec = undefined; | ||
| 94 | const err = posix.clock_gettime(posix.CLOCK_REALTIME, &ts); | ||
| 95 | debug.assert(err == 0); | ||
| 96 | const sec_ms = u64(ts.tv_sec) * ms_per_s; | ||
| 97 | const nsec_ms = @divFloor(u64(ts.tv_nsec), ns_per_s / ms_per_s); | ||
| 98 | return sec_ms + nsec_ms; | ||
| 99 | } | ||
| 100 | |||
| 101 | /// Divisions of a second | ||
| 102 | pub const ns_per_s = 1000000000; | ||
| 103 | pub const us_per_s = 1000000; | ||
| 104 | pub const ms_per_s = 1000; | ||
| 105 | pub const cs_per_s = 100; | ||
| 106 | |||
| 107 | /// Common time divisions | ||
| 108 | pub const s_per_min = 60; | ||
| 109 | pub const s_per_hour = s_per_min * 60; | ||
| 110 | pub const s_per_day = s_per_hour * 24; | ||
| 111 | pub const s_per_week = s_per_day * 7; | ||
| 112 | |||
| 113 | |||
| 114 | /// A monotonic high-performance timer. | ||
| 115 | /// Timer.start() must be called to initialize the struct, which captures | ||
| 116 | /// the counter frequency on windows and darwin, records the resolution, | ||
| 117 | /// and gives the user an oportunity to check for the existnece of | ||
| 118 | /// monotonic clocks without forcing them to check for error on each read. | ||
| 119 | /// .resolution is in nanoseconds on all platforms but .start_time's meaning | ||
| 120 | /// depends on the OS. On Windows and Darwin it is a hardware counter | ||
| 121 | /// value that requires calculation to convert to a meaninful unit. | ||
| 122 | pub const Timer = struct { | ||
| 123 | |||
| 124 | //if we used resolution's value when performing the | ||
| 125 | // performance counter calc on windows/darwin, it would | ||
| 126 | // be less precise | ||
| 127 | frequency: switch (builtin.os) { | ||
| 128 | Os.windows => u64, | ||
| 129 | Os.macosx, Os.ios => darwin.mach_timebase_info_data, | ||
| 130 | else => void, | ||
| 131 | }, | ||
| 132 | resolution: u64, | ||
| 133 | start_time: u64, | ||
| 134 | |||
| 135 | |||
| 136 | //At some point we may change our minds on RAW, but for now we're | ||
| 137 | // sticking with posix standard MONOTONIC. For more information, see: | ||
| 138 | // https://github.com/zig-lang/zig/pull/933 | ||
| 139 | // | ||
| 140 | //const monotonic_clock_id = switch(builtin.os) { | ||
| 141 | // Os.linux => linux.CLOCK_MONOTONIC_RAW, | ||
| 142 | // else => posix.CLOCK_MONOTONIC, | ||
| 143 | //}; | ||
| 144 | const monotonic_clock_id = posix.CLOCK_MONOTONIC; | ||
| 145 | |||
| 146 | |||
| 147 | /// Initialize the timer structure. | ||
| 148 | //This gives us an oportunity to grab the counter frequency in windows. | ||
| 149 | //On Windows: QueryPerformanceCounter will succeed on anything >= XP/2000. | ||
| 150 | //On Posix: CLOCK_MONOTONIC will only fail if the monotonic counter is not | ||
| 151 | // supported, or if the timespec pointer is out of bounds, which should be | ||
| 152 | // impossible here barring cosmic rays or other such occurances of | ||
| 153 | // incredibly bad luck. | ||
| 154 | //On Darwin: This cannot fail, as far as I am able to tell. | ||
| 155 | const TimerError = error{TimerUnsupported, Unexpected}; | ||
| 156 | pub fn start() TimerError!Timer { | ||
| 157 | var self: Timer = undefined; | ||
| 158 | |||
| 159 | switch (builtin.os) { | ||
| 160 | Os.windows => { | ||
| 161 | var freq: i64 = undefined; | ||
| 162 | var err = windows.QueryPerformanceFrequency(&freq); | ||
| 163 | if (err == windows.FALSE) return error.TimerUnsupported; | ||
| 164 | self.frequency = u64(freq); | ||
| 165 | self.resolution = @divFloor(ns_per_s, self.frequency); | ||
| 166 | |||
| 167 | var start_time: i64 = undefined; | ||
| 168 | err = windows.QueryPerformanceCounter(&start_time); | ||
| 169 | debug.assert(err != windows.FALSE); | ||
| 170 | self.start_time = u64(start_time); | ||
| 171 | }, | ||
| 172 | Os.linux => { | ||
| 173 | //On Linux, seccomp can do arbitrary things to our ability to call | ||
| 174 | // syscalls, including return any errno value it wants and | ||
| 175 | // inconsistently throwing errors. Since we can't account for | ||
| 176 | // abuses of seccomp in a reasonable way, we'll assume that if | ||
| 177 | // seccomp is going to block us it will at least do so consistently | ||
| 178 | var ts: posix.timespec = undefined; | ||
| 179 | var result = posix.clock_getres(monotonic_clock_id, &ts); | ||
| 180 | var errno = posix.getErrno(result); | ||
| 181 | switch (errno) { | ||
| 182 | 0 => {}, | ||
| 183 | posix.EINVAL => return error.TimerUnsupported, | ||
| 184 | else => return std.os.unexpectedErrorPosix(errno), | ||
| 185 | } | ||
| 186 | self.resolution = u64(ts.tv_sec) * u64(ns_per_s) + u64(ts.tv_nsec); | ||
| 187 | |||
| 188 | result = posix.clock_gettime(monotonic_clock_id, &ts); | ||
| 189 | errno = posix.getErrno(result); | ||
| 190 | if (errno != 0) return std.os.unexpectedErrorPosix(errno); | ||
| 191 | self.start_time = u64(ts.tv_sec) * u64(ns_per_s) + u64(ts.tv_nsec); | ||
| 192 | }, | ||
| 193 | Os.macosx, Os.ios => { | ||
| 194 | darwin.mach_timebase_info(&self.frequency); | ||
| 195 | self.resolution = @divFloor(self.frequency.numer, self.frequency.denom); | ||
| 196 | self.start_time = darwin.mach_absolute_time(); | ||
| 197 | }, | ||
| 198 | else => @compileError("Unsupported OS"), | ||
| 199 | } | ||
| 200 | return self; | ||
| 201 | } | ||
| 202 | |||
| 203 | /// Reads the timer value since start or the last reset in nanoseconds | ||
| 204 | pub fn read(self: &Timer) u64 { | ||
| 205 | var clock = clockNative() - self.start_time; | ||
| 206 | return switch (builtin.os) { | ||
| 207 | Os.windows => @divFloor(clock * ns_per_s, self.frequency), | ||
| 208 | Os.linux => clock, | ||
| 209 | Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom), | ||
| 210 | else => @compileError("Unsupported OS"), | ||
| 211 | }; | ||
| 212 | } | ||
| 213 | |||
| 214 | /// Resets the timer value to 0/now. | ||
| 215 | pub fn reset(self: &Timer) void | ||
| 216 | { | ||
| 217 | self.start_time = clockNative(); | ||
| 218 | } | ||
| 219 | |||
| 220 | /// Returns the current value of the timer in nanoseconds, then resets it | ||
| 221 | pub fn lap(self: &Timer) u64 { | ||
| 222 | var now = clockNative(); | ||
| 223 | var lap_time = self.read(); | ||
| 224 | self.start_time = now; | ||
| 225 | return lap_time; | ||
| 226 | } | ||
| 227 | |||
| 228 | |||
| 229 | const clockNative = switch (builtin.os) { | ||
| 230 | Os.windows => clockWindows, | ||
| 231 | Os.linux => clockLinux, | ||
| 232 | Os.macosx, Os.ios => clockDarwin, | ||
| 233 | else => @compileError("Unsupported OS"), | ||
| 234 | }; | ||
| 235 | |||
| 236 | fn clockWindows() u64 { | ||
| 237 | var result: i64 = undefined; | ||
| 238 | var err = windows.QueryPerformanceCounter(&result); | ||
| 239 | debug.assert(err != windows.FALSE); | ||
| 240 | return u64(result); | ||
| 241 | } | ||
| 242 | |||
| 243 | fn clockDarwin() u64 { | ||
| 244 | return darwin.mach_absolute_time(); | ||
| 245 | } | ||
| 246 | |||
| 247 | fn clockLinux() u64 { | ||
| 248 | var ts: posix.timespec = undefined; | ||
| 249 | var result = posix.clock_gettime(monotonic_clock_id, &ts); | ||
| 250 | debug.assert(posix.getErrno(result) == 0); | ||
| 251 | return u64(ts.tv_sec) * u64(ns_per_s) + u64(ts.tv_nsec); | ||
| 252 | } | ||
| 253 | }; | ||
| 254 | |||
| 255 | |||
| 256 | |||
| 257 | |||
| 258 | |||
| 259 | test "os.time.sleep" { | ||
| 260 | sleep(0, 1); | ||
| 261 | } | ||
| 262 | |||
| 263 | test "os.time.timestamp" { | ||
| 264 | const ns_per_ms = (ns_per_s / ms_per_s); | ||
| 265 | const margin = 50; | ||
| 266 | |||
| 267 | const time_0 = milliTimestamp(); | ||
| 268 | sleep(0, ns_per_ms); | ||
| 269 | const time_1 = milliTimestamp(); | ||
| 270 | const interval = time_1 - time_0; | ||
| 271 | debug.assert(interval > 0 and interval < margin); | ||
| 272 | } | ||
| 273 | |||
| 274 | test "os.time.Timer" { | ||
| 275 | const ns_per_ms = (ns_per_s / ms_per_s); | ||
| 276 | const margin = ns_per_ms * 50; | ||
| 277 | |||
| 278 | var timer = try Timer.start(); | ||
| 279 | sleep(0, 10 * ns_per_ms); | ||
| 280 | const time_0 = timer.read(); | ||
| 281 | debug.assert(time_0 > 0 and time_0 < margin); | ||
| 282 | |||
| 283 | const time_1 = timer.lap(); | ||
| 284 | debug.assert(time_1 > time_0); | ||
| 285 | |||
| 286 | timer.reset(); | ||
| 287 | debug.assert(timer.read() < time_1); | ||
| 288 | } | ||
std/os/windows/index.zig+11| ... | @@ -61,6 +61,8 @@ pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpsz | ... | @@ -61,6 +61,8 @@ pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpsz |
| 61 | 61 | ||
| 62 | pub extern "kernel32" stdcallcc fn GetProcessHeap() ?HANDLE; | 62 | pub extern "kernel32" stdcallcc fn GetProcessHeap() ?HANDLE; |
| 63 | 63 | ||
| 64 | pub extern "kernel32" stdcallcc fn GetSystemTimeAsFileTime(?&FILETIME) void; | ||
| 65 | |||
| 64 | pub extern "kernel32" stdcallcc fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) ?HANDLE; | 66 | pub extern "kernel32" stdcallcc fn HeapCreate(flOptions: DWORD, dwInitialSize: SIZE_T, dwMaximumSize: SIZE_T) ?HANDLE; |
| 65 | pub extern "kernel32" stdcallcc fn HeapDestroy(hHeap: HANDLE) BOOL; | 67 | pub extern "kernel32" stdcallcc fn HeapDestroy(hHeap: HANDLE) BOOL; |
| 66 | pub extern "kernel32" stdcallcc fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: &c_void, dwBytes: SIZE_T) ?&c_void; | 68 | pub extern "kernel32" stdcallcc fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: &c_void, dwBytes: SIZE_T) ?&c_void; |
| ... | @@ -77,6 +79,10 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem | ... | @@ -77,6 +79,10 @@ pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem |
| 77 | 79 | ||
| 78 | pub extern "kernel32" stdcallcc fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, | 80 | pub extern "kernel32" stdcallcc fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, |
| 79 | dwFlags: DWORD) BOOL; | 81 | dwFlags: DWORD) BOOL; |
| 82 | |||
| 83 | pub extern "kernel32" stdcallcc fn QueryPerformanceCounter(lpPerformanceCount: &LARGE_INTEGER) BOOL; | ||
| 84 | |||
| 85 | pub extern "kernel32" stdcallcc fn QueryPerformanceFrequency(lpFrequency: &LARGE_INTEGER) BOOL; | ||
| 80 | 86 | ||
| 81 | pub extern "kernel32" stdcallcc fn PathFileExists(pszPath: ?LPCTSTR) BOOL; | 87 | pub extern "kernel32" stdcallcc fn PathFileExists(pszPath: ?LPCTSTR) BOOL; |
| 82 | 88 | ||
| ... | @@ -139,6 +145,7 @@ pub const UNICODE = false; | ... | @@ -139,6 +145,7 @@ pub const UNICODE = false; |
| 139 | pub const WCHAR = u16; | 145 | pub const WCHAR = u16; |
| 140 | pub const WORD = u16; | 146 | pub const WORD = u16; |
| 141 | pub const LARGE_INTEGER = i64; | 147 | pub const LARGE_INTEGER = i64; |
| 148 | pub const FILETIME = i64; | ||
| 142 | 149 | ||
| 143 | pub const TRUE = 1; | 150 | pub const TRUE = 1; |
| 144 | pub const FALSE = 0; | 151 | pub const FALSE = 0; |
| ... | @@ -310,3 +317,7 @@ pub const FILE_END = 2; | ... | @@ -310,3 +317,7 @@ pub const FILE_END = 2; |
| 310 | pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000; | 317 | pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000; |
| 311 | pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004; | 318 | pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004; |
| 312 | pub const HEAP_NO_SERIALIZE = 0x00000001; | 319 | pub const HEAP_NO_SERIALIZE = 0x00000001; |
| 320 | |||
| 321 | test "import" { | ||
| 322 | _ = @import("util.zig"); | ||
| 323 | } |
std/special/bootstrap.zig+19-8| ... | @@ -48,22 +48,33 @@ extern fn WinMainCRTStartup() noreturn { | ... | @@ -48,22 +48,33 @@ extern fn WinMainCRTStartup() noreturn { |
| 48 | fn posixCallMainAndExit() noreturn { | 48 | fn posixCallMainAndExit() noreturn { |
| 49 | const argc = *argc_ptr; | 49 | const argc = *argc_ptr; |
| 50 | const argv = @ptrCast(&&u8, &argc_ptr[1]); | 50 | const argv = @ptrCast(&&u8, &argc_ptr[1]); |
| 51 | const envp = @ptrCast(&?&u8, &argv[argc + 1]); | 51 | const envp_nullable = @ptrCast(&?&u8, &argv[argc + 1]); |
| 52 | var envp_count: usize = 0; | ||
| 53 | while (envp_nullable[envp_count]) |_| : (envp_count += 1) {} | ||
| 54 | const envp = @ptrCast(&&u8, envp_nullable)[0..envp_count]; | ||
| 55 | if (builtin.os == builtin.Os.linux) { | ||
| 56 | const auxv = &@ptrCast(&usize, envp.ptr)[envp_count + 1]; | ||
| 57 | var i: usize = 0; | ||
| 58 | while (auxv[i] != 0) : (i += 2) { | ||
| 59 | if (auxv[i] < std.os.linux_aux_raw.len) std.os.linux_aux_raw[auxv[i]] = auxv[i+1]; | ||
| 60 | } | ||
| 61 | std.debug.assert(std.os.linux_aux_raw[std.elf.AT_PAGESZ] == std.os.page_size); | ||
| 62 | } | ||
| 63 | |||
| 52 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); | 64 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); |
| 53 | } | 65 | } |
| 54 | 66 | ||
| 55 | fn callMainWithArgs(argc: usize, argv: &&u8, envp: &?&u8) u8 { | 67 | fn callMainWithArgs(argc: usize, argv: &&u8, envp: []&u8) u8 { |
| 56 | std.os.ArgIteratorPosix.raw = argv[0..argc]; | 68 | std.os.ArgIteratorPosix.raw = argv[0..argc]; |
| 57 | 69 | std.os.posix_environ_raw = envp; | |
| 58 | var env_count: usize = 0; | ||
| 59 | while (envp[env_count] != null) : (env_count += 1) {} | ||
| 60 | std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count]; | ||
| 61 | |||
| 62 | return callMain(); | 70 | return callMain(); |
| 63 | } | 71 | } |
| 64 | 72 | ||
| 65 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) i32 { | 73 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) i32 { |
| 66 | return callMainWithArgs(usize(c_argc), c_argv, c_envp); | 74 | var env_count: usize = 0; |
| 75 | while (c_envp[env_count] != null) : (env_count += 1) {} | ||
| 76 | const envp = @ptrCast(&&u8, c_envp)[0..env_count]; | ||
| 77 | return callMainWithArgs(usize(c_argc), c_argv, envp); | ||
| 67 | } | 78 | } |
| 68 | 79 | ||
| 69 | fn callMain() u8 { | 80 | fn callMain() u8 { |
test/cases/atomics.zig+20| ... | @@ -49,3 +49,23 @@ fn testAtomicLoad(ptr: &u8) void { | ... | @@ -49,3 +49,23 @@ fn testAtomicLoad(ptr: &u8) void { |
| 49 | const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); | 49 | const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); |
| 50 | assert(x == 42); | 50 | assert(x == 42); |
| 51 | } | 51 | } |
| 52 | |||
| 53 | test "cmpxchg with ptr" { | ||
| 54 | var data1: i32 = 1234; | ||
| 55 | var data2: i32 = 5678; | ||
| 56 | var data3: i32 = 9101; | ||
| 57 | var x: &i32 = &data1; | ||
| 58 | if (@cmpxchgWeak(&i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 59 | assert(x1 == &data1); | ||
| 60 | } else { | ||
| 61 | @panic("cmpxchg should have failed"); | ||
| 62 | } | ||
| 63 | |||
| 64 | while (@cmpxchgWeak(&i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | ||
| 65 | assert(x1 == &data1); | ||
| 66 | } | ||
| 67 | assert(x == &data3); | ||
| 68 | |||
| 69 | assert(@cmpxchgStrong(&i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | ||
| 70 | assert(x == &data2); | ||
| 71 | } |