The OpenD Programming Language

1 /++
2 Copyright: Copyright © 2016-, Ilya Yaroshenko.
3 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Ilya Yaroshenko
5 +/
6 module glas.precompiled.context;
7 
8 import glas.internal.memory;
9 
10 package(glas) __gshared uint c1;
11 package(glas) __gshared uint c2;
12 package(glas) __gshared uint line;
13 package(glas) __gshared uint initialized;
14 package(glas) __gshared void[] _memory;
15 
16 /// Cache Information
17 pragma(LDC_no_typeinfo)
18 package struct Cache
19 {
20     /// Cache size in KBs
21     uint size;
22     /// Ways of associativity. Equals `associative.max` if cache is fully associative.
23     ushort associative;
24     /// Cache line in KBs
25     ushort line;
26     /// CPU cores per cache
27     ubyte cores;
28     /// `true` if cache is inclusive of lower cache levels.
29     bool inclusive;
30 }
31 
32 package nothrow @nogc extern(C) 
33 {
34     void cpuid_init();
35 @trusted:
36     uint cpuid_cores();
37     const(Cache)[] cpuid_dCache();
38     const(Cache)[] cpuid_uCache();
39 }
40 
41 /++
42 Initialize GLAS Context. Optional.
43 +/
44 pragma(inline, false)
45 export extern(C) nothrow @nogc void glas_init()
46 {
47     if(initialized)
48         return;
49     cpuid_init();
50     auto dc = cpuid_dCache;
51     auto uc = cpuid_uCache;
52 
53     while (uc.length && uc[$-1].size > (1024 * 64)) // > 64 MB is CPU memory
54     {
55         uc = uc[0..$-1];
56     }
57 
58     if (dc.length)
59     {
60         c1 = dc[0].size;
61         line = dc[0].line;
62         dc = dc[1..$];
63     }
64     else
65     if (uc.length)
66     {
67         c1 = uc[0].size;
68         line = uc[0].line;
69         uc = uc[1..$];
70     }
71     else
72     {
73         c1 = 16;
74     }
75 
76     if (uc.length)
77     {
78         c2 = uc[$-1].size;
79     }
80     else
81     if (dc.length)
82     {
83         c2 = dc[$-1].size;
84     }
85     else
86     {
87         c1 = 256;
88     }
89 
90     c1 <<= 10;
91     c2 <<= 10;
92     if (line == 0)
93         line = 64;
94     initialized = true;
95 }
96 
97 import ldc.attributes : fastmath;
98 @fastmath:
99 
100 /++
101 Releases memory and closes threads.
102 Optional.
103 +/
104 export extern(C) void glas_release()
105 {
106     if (_memory !is null)
107         deallocate(_memory);
108 }
109 
110 // Returns: reused unaligned memory chunk
111 pragma(inline, true)
112 package(glas) nothrow @nogc void[] memory(size_t size)
113 {
114     if (_memory.length < size)
115     {
116         auto f = _memory.length << 1;
117         if (f > size)
118             size = f;
119         if (_memory !is null)
120             deallocate(_memory);
121         _memory = alignedAllocate(size, 4096);
122     }
123     return _memory[0..size];
124 }