authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-01 12:22:21-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-01 12:22:21-05:00
logbfc1772d8ead9e8fcde0a315411ddcd040cc3d28
tree6c54dd3a62adafa79233777fa6ca7bccd054bc4f
parent8d3eb25e92c7a7597711cdb9a7268059d795fc15

fixups


6 files changed, 142 insertions(+), 73 deletions(-)

CMakeLists.txt+16-15
...@@ -454,10 +454,10 @@ set(ZIG_STD_FILES...@@ -454,10 +454,10 @@ set(ZIG_STD_FILES
454 "crypto/hmac.zig"454 "crypto/hmac.zig"
455 "crypto/index.zig"455 "crypto/index.zig"
456 "crypto/md5.zig"456 "crypto/md5.zig"
457 "crypto/poly1305.zig"
457 "crypto/sha1.zig"458 "crypto/sha1.zig"
458 "crypto/sha2.zig"459 "crypto/sha2.zig"
459 "crypto/sha3.zig"460 "crypto/sha3.zig"
460 "crypto/poly1305.zig"
461 "crypto/x25519.zig"461 "crypto/x25519.zig"
462 "cstr.zig"462 "cstr.zig"
463 "debug/failing_allocator.zig"463 "debug/failing_allocator.zig"
...@@ -566,9 +566,9 @@ set(ZIG_STD_FILES...@@ -566,9 +566,9 @@ set(ZIG_STD_FILES
566 "math/tan.zig"566 "math/tan.zig"
567 "math/tanh.zig"567 "math/tanh.zig"
568 "math/trunc.zig"568 "math/trunc.zig"
569 "mem.zig"
569 "meta/index.zig"570 "meta/index.zig"
570 "meta/trait.zig"571 "meta/trait.zig"
571 "mem.zig"
572 "mutex.zig"572 "mutex.zig"
573 "net.zig"573 "net.zig"
574 "os/child_process.zig"574 "os/child_process.zig"
...@@ -576,16 +576,16 @@ set(ZIG_STD_FILES...@@ -576,16 +576,16 @@ set(ZIG_STD_FILES
576 "os/darwin/errno.zig"576 "os/darwin/errno.zig"
577 "os/epoch.zig"577 "os/epoch.zig"
578 "os/file.zig"578 "os/file.zig"
579 "os/freebsd/errno.zig"
580 "os/freebsd/index.zig"
579 "os/get_app_data_dir.zig"581 "os/get_app_data_dir.zig"
580 "os/get_user_id.zig"582 "os/get_user_id.zig"
581 "os/index.zig"583 "os/index.zig"
584 "os/linux/arm64.zig"
582 "os/linux/errno.zig"585 "os/linux/errno.zig"
583 "os/linux/index.zig"586 "os/linux/index.zig"
584 "os/linux/vdso.zig"587 "os/linux/vdso.zig"
585 "os/linux/x86_64.zig"588 "os/linux/x86_64.zig"
586 "os/linux/arm64.zig"
587 "os/freebsd/errno.zig"
588 "os/freebsd/index.zig"
589 "os/path.zig"589 "os/path.zig"
590 "os/time.zig"590 "os/time.zig"
591 "os/uefi.zig"591 "os/uefi.zig"
...@@ -612,6 +612,16 @@ set(ZIG_STD_FILES...@@ -612,6 +612,16 @@ set(ZIG_STD_FILES
612 "special/compiler_rt/comparetf2.zig"612 "special/compiler_rt/comparetf2.zig"
613 "special/compiler_rt/divti3.zig"613 "special/compiler_rt/divti3.zig"
614 "special/compiler_rt/extendXfYf2.zig"614 "special/compiler_rt/extendXfYf2.zig"
615 "special/compiler_rt/fixdfdi.zig"
616 "special/compiler_rt/fixdfsi.zig"
617 "special/compiler_rt/fixdfti.zig"
618 "special/compiler_rt/fixint.zig"
619 "special/compiler_rt/fixsfdi.zig"
620 "special/compiler_rt/fixsfsi.zig"
621 "special/compiler_rt/fixsfti.zig"
622 "special/compiler_rt/fixtfdi.zig"
623 "special/compiler_rt/fixtfsi.zig"
624 "special/compiler_rt/fixtfti.zig"
615 "special/compiler_rt/fixuint.zig"625 "special/compiler_rt/fixuint.zig"
616 "special/compiler_rt/fixunsdfdi.zig"626 "special/compiler_rt/fixunsdfdi.zig"
617 "special/compiler_rt/fixunsdfsi.zig"627 "special/compiler_rt/fixunsdfsi.zig"
...@@ -622,16 +632,6 @@ set(ZIG_STD_FILES...@@ -622,16 +632,6 @@ set(ZIG_STD_FILES
622 "special/compiler_rt/fixunstfdi.zig"632 "special/compiler_rt/fixunstfdi.zig"
623 "special/compiler_rt/fixunstfsi.zig"633 "special/compiler_rt/fixunstfsi.zig"
624 "special/compiler_rt/fixunstfti.zig"634 "special/compiler_rt/fixunstfti.zig"
625 "special/compiler_rt/fixint.zig"
626 "special/compiler_rt/fixdfdi.zig"
627 "special/compiler_rt/fixdfsi.zig"
628 "special/compiler_rt/fixdfti.zig"
629 "special/compiler_rt/fixsfdi.zig"
630 "special/compiler_rt/fixsfsi.zig"
631 "special/compiler_rt/fixsfti.zig"
632 "special/compiler_rt/fixtfdi.zig"
633 "special/compiler_rt/fixtfsi.zig"
634 "special/compiler_rt/fixtfti.zig"
635 "special/compiler_rt/floattidf.zig"635 "special/compiler_rt/floattidf.zig"
636 "special/compiler_rt/floattisf.zig"636 "special/compiler_rt/floattisf.zig"
637 "special/compiler_rt/floattitf.zig"637 "special/compiler_rt/floattitf.zig"
...@@ -656,6 +656,7 @@ set(ZIG_STD_FILES...@@ -656,6 +656,7 @@ set(ZIG_STD_FILES
656 "special/panic.zig"656 "special/panic.zig"
657 "special/test_runner.zig"657 "special/test_runner.zig"
658 "spinlock.zig"658 "spinlock.zig"
659 "statically_initialized_mutex.zig"
659 "unicode.zig"660 "unicode.zig"
660 "zig/ast.zig"661 "zig/ast.zig"
661 "zig/index.zig"662 "zig/index.zig"
std/fmt/index.zig-2
...@@ -982,13 +982,11 @@ test "fmt.format" {...@@ -982,13 +982,11 @@ test "fmt.format" {
982 context = BufPrintContext{ .remaining = buf1[0..] };982 context = BufPrintContext{ .remaining = buf1[0..] };
983 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);983 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
984 res = buf1[0 .. buf1.len - context.remaining.len];984 res = buf1[0 .. buf1.len - context.remaining.len];
985 debug.warn("{}\n", res);
986 assert(mem.eql(u8, res, "a"));985 assert(mem.eql(u8, res, "a"));
987986
988 context = BufPrintContext{ .remaining = buf1[0..] };987 context = BufPrintContext{ .remaining = buf1[0..] };
989 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);988 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
990 res = buf1[0 .. buf1.len - context.remaining.len];989 res = buf1[0 .. buf1.len - context.remaining.len];
991 debug.warn("{}\n", res);
992 assert(mem.eql(u8, res, "1100"));990 assert(mem.eql(u8, res, "1100"));
993 }991 }
994 {992 {
std/index.zig+2
...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
9pub const HashMap = @import("hash_map.zig").HashMap;9pub const HashMap = @import("hash_map.zig").HashMap;
10pub const LinkedList = @import("linked_list.zig").LinkedList;10pub const LinkedList = @import("linked_list.zig").LinkedList;
11pub const Mutex = @import("mutex.zig").Mutex;11pub const Mutex = @import("mutex.zig").Mutex;
12pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
12pub const SegmentedList = @import("segmented_list.zig").SegmentedList;13pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
13pub const SpinLock = @import("spinlock.zig").SpinLock;14pub const SpinLock = @import("spinlock.zig").SpinLock;
1415
...@@ -55,6 +56,7 @@ test "std" {...@@ -55,6 +56,7 @@ test "std" {
55 _ = @import("hash_map.zig");56 _ = @import("hash_map.zig");
56 _ = @import("linked_list.zig");57 _ = @import("linked_list.zig");
57 _ = @import("mutex.zig");58 _ = @import("mutex.zig");
59 _ = @import("statically_initialized_mutex.zig");
58 _ = @import("segmented_list.zig");60 _ = @import("segmented_list.zig");
59 _ = @import("spinlock.zig");61 _ = @import("spinlock.zig");
60 62
std/mutex.zig+11-50
...@@ -9,6 +9,9 @@ const windows = std.os.windows;...@@ -9,6 +9,9 @@ const windows = std.os.windows;
99
10/// Lock may be held only once. If the same thread10/// Lock may be held only once. If the same thread
11/// tries to acquire the same mutex twice, it deadlocks.11/// tries to acquire the same mutex twice, it deadlocks.
12/// This type must be initialized at runtime, and then deinitialized when no
13/// longer needed, to free resources.
14/// If you need static initialization, use std.StaticallyInitializedMutex.
12/// The Linux implementation is based on mutex3 from15/// The Linux implementation is based on mutex3 from
13/// https://www.akkadia.org/drepper/futex.pdf16/// https://www.akkadia.org/drepper/futex.pdf
14pub const Mutex = switch(builtin.os) {17pub const Mutex = switch(builtin.os) {
...@@ -60,57 +63,15 @@ pub const Mutex = switch(builtin.os) {...@@ -60,57 +63,15 @@ pub const Mutex = switch(builtin.os) {
60 return Held { .mutex = self };63 return Held { .mutex = self };
61 }64 }
62 },65 },
63 builtin.Os.windows => struct {66 // TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a
6467 // better implementation of this. The problem is we need the init() function to have access to
65 lock: windows.CRITICAL_SECTION,68 // the address of the CRITICAL_SECTION, and then have it not move.
66 init_once: windows.RTL_RUN_ONCE,69 builtin.Os.windows => std.StaticallyInitializedMutex,
67
68 pub const Held = struct {
69 mutex: *Mutex,
70
71 pub fn release(self: Held) void {
72 windows.LeaveCriticalSection(&self.mutex.lock);
73 }
74 };
75
76 pub fn init() Mutex {
77 return Mutex {
78 .lock = undefined,
79 .init_once = windows.INIT_ONCE_STATIC_INIT,
80 };
81 }
82
83 extern fn initCriticalSection(
84 InitOnce: *windows.RTL_RUN_ONCE,
85 Parameter: ?windows.PVOID,
86 Context: ?windows.PVOID
87 ) windows.BOOL {
88 var lock = @ptrCast(
89 *windows.CRITICAL_SECTION,
90 @alignCast(@alignOf(*windows.CRITICAL_SECTION), Context.?)
91 );
92 windows.InitializeCriticalSection(lock);
93 return windows.TRUE;
94 }
95
96 pub fn deinit(self: *Mutex) void {
97 windows.DeleteCriticalSection(&self.lock);
98 }
99
100 pub fn acquire(self: *Mutex) Held {
101 if (windows.InitOnceExecuteOnce(
102 &self.init_once,
103 initCriticalSection,
104 null, @ptrCast(?windows.PVOID, self)
105 ) == windows.FALSE) {
106 unreachable;
107 }
108 windows.EnterCriticalSection(&self.lock);
109 return Held { .mutex = self };
110 }
111 },
112 else => struct {70 else => struct {
113 /// TODO better implementation than spin lock71 /// TODO better implementation than spin lock.
72 /// When changing this, one must also change the corresponding
73 /// std.StaticallyInitializedMutex code, since it aliases this type,
74 /// under the assumption that it works both statically and at runtime.
114 lock: SpinLock,75 lock: SpinLock,
11576
116 pub const Held = struct {77 pub const Held = struct {
std/os/windows/kernel32.zig+8-6
...@@ -253,15 +253,17 @@ pub const RTL_CRITICAL_SECTION = extern struct {...@@ -253,15 +253,17 @@ pub const RTL_CRITICAL_SECTION = extern struct {
253};253};
254254
255pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;255pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;
256pub const INIT_ONCE = RTL_RUN_ONCE;
257pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE_INIT;
256258
257pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *RTL_RUN_ONCE, InitFn: PINIT_ONCE_FN, Context: ?PVOID, Parameter: ?LPVOID) BOOL;259pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*c_void, Context: ?*c_void) BOOL;
258260
259pub const PINIT_ONCE_FN = ?extern fn(InitOnce: *RTL_RUN_ONCE, Parameter: ?PVOID, Context: ?PVOID) BOOL;261pub const INIT_ONCE_FN = extern fn(InitOnce: *INIT_ONCE, Parameter: ?*c_void, Context: ?*c_void) BOOL;
260262
261pub const RTL_RUN_ONCE = extern struct {263pub const RTL_RUN_ONCE = extern struct {
262 Ptr: ?PVOID,264 Ptr: ?*c_void,
263};265};
264266
265pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE {
266 .Ptr = null,
267};
\ No newline at end of file
267pub const RTL_RUN_ONCE_INIT = RTL_RUN_ONCE {
268 .Ptr = null,
269};
std/statically_initialized_mutex.zig created+105
...@@ -0,0 +1,105 @@
1const std = @import("index.zig");
2const builtin = @import("builtin");
3const AtomicOrder = builtin.AtomicOrder;
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const assert = std.debug.assert;
6const windows = std.os.windows;
7
8/// Lock may be held only once. If the same thread
9/// tries to acquire the same mutex twice, it deadlocks.
10/// This type is intended to be initialized statically. If you don't
11/// require static initialization, use std.Mutex.
12/// On Windows, this mutex allocates resources when it is
13/// first used, and the resources cannot be freed.
14/// On Linux, this is an alias of std.Mutex.
15pub const StaticallyInitializedMutex = switch(builtin.os) {
16 builtin.Os.linux => std.Mutex,
17 builtin.Os.windows => struct {
18 lock: windows.CRITICAL_SECTION,
19 init_once: windows.RTL_RUN_ONCE,
20
21 pub const Held = struct {
22 mutex: *StaticallyInitializedMutex,
23
24 pub fn release(self: Held) void {
25 windows.LeaveCriticalSection(&self.mutex.lock);
26 }
27 };
28
29 pub fn init() StaticallyInitializedMutex {
30 return StaticallyInitializedMutex {
31 .lock = undefined,
32 .init_once = windows.INIT_ONCE_STATIC_INIT,
33 };
34 }
35
36 extern fn initCriticalSection(
37 InitOnce: *windows.RTL_RUN_ONCE,
38 Parameter: ?*c_void,
39 Context: ?*c_void,
40 ) windows.BOOL {
41 const lock = @ptrCast(*windows.CRITICAL_SECTION, @alignCast(@alignOf(windows.CRITICAL_SECTION), Parameter));
42 windows.InitializeCriticalSection(lock);
43 return windows.TRUE;
44 }
45
46 /// TODO: once https://github.com/ziglang/zig/issues/287 is solved and std.Mutex has a better
47 /// implementation of a runtime initialized mutex, remove this function.
48 pub fn deinit(self: *StaticallyInitializedMutex) void {
49 assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
50 windows.DeleteCriticalSection(&self.lock);
51 }
52
53 pub fn acquire(self: *StaticallyInitializedMutex) Held {
54 assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
55 windows.EnterCriticalSection(&self.lock);
56 return Held { .mutex = self };
57 }
58 },
59 else => std.Mutex,
60};
61
62test "std.StaticallyInitializedMutex" {
63 const TestContext = struct {
64 data: i128,
65
66 const TestContext = @This();
67 const incr_count = 10000;
68
69 var mutex = StaticallyInitializedMutex.init();
70
71 fn worker(ctx: *TestContext) void {
72 var i: usize = 0;
73 while (i != TestContext.incr_count) : (i += 1) {
74 const held = mutex.acquire();
75 defer held.release();
76
77 ctx.data += 1;
78 }
79 }
80 };
81
82 var direct_allocator = std.heap.DirectAllocator.init();
83 defer direct_allocator.deinit();
84
85 var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
86 defer direct_allocator.allocator.free(plenty_of_memory);
87
88 var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
89 var a = &fixed_buffer_allocator.allocator;
90
91
92 var context = TestContext{
93 .data = 0,
94 };
95
96 const thread_count = 10;
97 var threads: [thread_count]*std.os.Thread = undefined;
98 for (threads) |*t| {
99 t.* = try std.os.spawnThread(&context, TestContext.worker);
100 }
101 for (threads) |t|
102 t.wait();
103
104 std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
105}