|
|
Static objects requiring construction or destruction must not be used within a device driver for SCO SVR5 2.X or SCO OpenServer 5 and are not recommended for SVR5. This refers to usages such as the following at file scope.:
class A { public: A(int); ~A(); };``Static'' also includes objects within namespace scope and destructable objects that are static locals, such as:A a(22);
void f() { static A a(33); }This restriction is necessary because, in the normal C++ environment, start-up and termination runtime routines execute these constructors and destructors before and after main( ) executes. In the static local case, only the destructor has this behavior. These runtime routines (Crti.o and Crtn.o) are not present in the kernel environment.
In SCO SVR5 2.X, these runtime routines work in conjunction with a post-linker editing tool named patch which is not available and would not work in the kernel build environment. patch is not used in SVR5.
Ideally, you should avoid declaring such static objects. If you need objects with a static allocation, a simple alternate approach is to declare them with a null constructor and no destructor, then define member functions that do the appropriate initialization and finalization. Call these member functions from the driver's _load( ) and _unload( ) entry point routines.
C++ drivers that need really static objects can implement them by supplying replacements for the required runtime routines as follows:
.section .ctor,"aw" .long 0 .previousEach translation unit that needs static initialization puts the address of its initialization routine in this .ctor section. These are coalesced by the linker to form a vector of addresses. These are traversed in reverse order; this code serves to define the end of this vector.
.section .ctor,"aw" __ctor_head: .long 0 .type __ctor_head,"object" .size __ctor_head,4 .previousThis code defines the beginning of the initialization routine vector.
void (**pf)() = &__ctor_head; for (--pf; *pf; --pf) (**pf)();
typedef void (*a_void_function_ptr)(); typedef struct a_needed_destruction *a_needed_destruction_ptr;The a_needed_destruction structure nodes are allocated by the generated code, with the object and destruction pointers filled in. All you have to do is kept the nodes on a list, using the ``next'' field.typedef struct a_needed_destruction { a_needed_destruction_ptr next; /* Pointer to the next entry in the list. */ void *object;/* Don't need to know about this. */ a_void_function_ptr destruction_routine; /* Don't need to know about this. */ } a_needed_destruction;
extern "C" void __record_needed_destruction(a_needed_destruction_ptr ndp) { /* Called when a static object has been constructed to register a destruction that must be done at program termination. ndp points to a needed destruction entry that is to be added to the front of a list of needed destructions that this routine keeps. */
... }
extern "C" __process_needed_destructions(a_needed_destruction_ptr *ndp);You will need to extract dtor_list.o from LibC.a and link it into the driver, as explained below.