tsdnz wrote:Note: the /* and */ comments are for Windows, these are removed before compiling by the VS attached program.
Code: Select all
#define NIL /*!!__attribute__ ((noinline))!!*/
#define AIL /*!!__attribute__((always_inline))!!*/
Might I recommend using a preprocessor switch here instead?
Code: Select all
#ifdef WINDOWS_TESTBED
#define NIL
#define AIL
#elif
#define NIL __attribute__ ((noinline))
#define AIL __attribute__((always_inline))
#endif
tsdnz wrote:This is for the Kernel, so I am not using new, delete.
OK, but that still doesn't answer the question.
tsdnz wrote:
Code: Select all
#define ForAll(Var, To) for (DWORD Var = 0; Var < To; Var++)
#define Fori(To) ForAll(i, (To))
#define Forn(To) ForAll(n, (To))
#define Forc(To) ForAll(c, (To))
#define Fore(To) ForAll(e, (To))
#define Forz(To) ForAll(z, (To))
#define Forx(To) ForAll(x, (To))
#define Fory(To) ForAll(y, (To))
facepalm You really, really shouldn't do this. C/C++ pre-processor macros are
far too brittle for this to be a reasonable thing to use them for. I know that the standard
for() construct is awkward for many of the common use cases, but this is
not the solution. I also know that the Linux kernel uses this sort of BS all over the place, too, but just because a Big Name Player does something that is a bad idea, that doesn't mean it isn't a bad idea.
If you are going use these macros despite this warning, I would recommend at least putting the parens around
To in
ForAll() rather than repeating them in each of the individual specialization macros. I don't know if you can think of a use case where you would want to re-evaluate the
To clause on each pass, but none of those which I can think of are ones which you would use this approach for in the first place.
Also, rather than using
DWORD for a (presumably) 32-bit value, I would recommend using the
<cstdint>-defined
uint32_t type, but that's a stylistic issue rather than any actual technical advice.
tsdnz wrote:
Here is how I create the class:
Code: Select all
Forc(ABIT.CPUs.CPUCount)
{
CPU[c] = ABIT.FastMem.Alloc<tSystem::tOS_GenericOS::tCPU>();
CPU[c]->Init();
}
And this is the class->Init()
Code: Select all
FIL void tSystem::tOS_GenericOS::tCPU::Init()
{
ZeroThis();
}
This line "ABIT.FastMem.Alloc<tSystem::tOS_GenericOS::tCPU>();" just allocates memory and returns a pointer.
The intention of memset is to clear the entire class to 0.
So this is for initialization only, not for release? That's rather important information, and exactly the sort of thing we needed. Good.
Also, it is actually clearing the individual
object being constructed, not the class itself. Even better.
HOWEVER... it still isn't clear why this is needed, or where it is being used - I almost am wondering why it would be in the kernel code at all, rather than part of the compiler or library. In C++, there's no actual requirement that memory allocated for new objects be cleared, and with good reason - aside from the extra time it takes, it can mask some types of errors by making the buggy code appear to work. If a member variable is getting used before it is explicitly initialized by the c'tor, or the c'tor leaves it uninitialized and later member methods try to use the uninitialized variable, that is a bug in the class code, not a fault in the standard initializer.
BTW, what toolchain (compiler, assembler, linker) are you using? The fact that it is emitting Intel-syntax assembly tells me that it is probably not GCC, so... VC++, maybe? That could be relevant here.