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