1

I've got a class that maintain instance from type class IOSharedDataQueue : public IODataQueue which is IOKit object.

The class is decoupled and called from various methods of the main class, which is IOKit based class (derived from IOService).

While trying to convert this class to singleton, I've added the getInstance function with the following implementation :

myclass& myclass::getInstance()
{
    static myclass instance;
    return instance;
}

However, it seems that c++11 way of initialize singleton should work in IOKit compiler, and Xcode produces the following error :

This initialization requires a guard variable, which the kernel does not support

The thing is, that it works for classes that does't contain IOKIt based objects.

Perhaps anyone encounter this issue, I haven't seen any documentation of this limitation.

EDIT :

I've found out that if my class Does Not contain any IOResources object in any way, it can designed as a singleton with the guard variable.

However, I still want to be able to create some simple and contained wrappers to be used throughout my IOKit project without passing pointers.

Zohar81
  • 4,554
  • 5
  • 29
  • 82

1 Answers1

2

IOKit objects are reference counted, and must always be instantiated with new and destroyed by calling release(). So regardless of the fact that thread-safe static initialisers aren't available in kexts, you shouldn't be statically allocating IOKit objects anyway. You can use an atomic pointer or a lock-based mechanism for instantiating your object on first call to the function, or create the instance at a fixed time.

An IOService as an explicit singleton is dubious anyway - are you sure you shouldn't be using IOResource based IOKit matching to create the single instance?

I'm suggesting something along the lines of:

static myclass* singleton_instance;
myclass* myclass::getInstance()
{
    if (singleton_instance == nullptr)
    {
        myclass* new_instance = new myclass();
        new_instance->init();
        if (!OSCompareAndSwapPtr(nullptr, new_instance, &singleton_instance))
        {
            new_instance->release();
        }
    }
    return singleton_instance;
}
// TODO: release singleton_instance when kext unloads
pmdj
  • 22,018
  • 3
  • 52
  • 103
  • Indeed IOKit objects are referenced and I don't mind derived from `OSobject`, but I wish to use it throughout the project without passing pointers ... perhaps you can explain your suggestion about using `atomic pointers` ? thanks – Zohar81 May 27 '18 at 06:14
  • @Zohar81 Assuming I'm understanding you correctly, and you want to have a singleton instance of an `OSObject`-derived class, I've updated the answer with an example. – pmdj May 27 '18 at 17:20
  • Thanks, that's exactly what I wanted. I just wonder why IOKit doesn't allow static members inside objects ... – Zohar81 May 28 '18 at 08:16
  • @Zohar81 I think it's because the compiler has to put a lock around the constructor. Did you try a non-iokit/osobject class with a nontrivial constructor? – pmdj May 28 '18 at 09:23