Added a new module "uthread_autoinit.cc". This is a small C++ module.

It uses a static constructor to call _thread_init() at program start-up
time.  That eliminates the need for any initialization hooks in crt0.o.

Added a symbol reference in "uthread_init.c", to ensure that the new
module will always be pulled in when the archive version of the library
is used.

In "Makefile.inc", defined CPLUSPLUSLIB, so that the constructor will be
properly invoked in the shared library.

Suggested by: Christopher Provenzano, Peter Wemm, and others.
This commit is contained in:
John Polstra 1996-02-17 02:19:37 +00:00
parent 7732e08227
commit 82d29a82b5
7 changed files with 136 additions and 3 deletions

View File

@ -1,4 +1,6 @@
# $Id$
# $Id: Makefile.inc,v 1.1 1996/01/22 00:23:03 julian Exp $
CPLUSPLUSLIB= cpluspluslib
# uthread sources
.PATH: ${.CURDIR}/uthread
@ -6,6 +8,7 @@
SRCS+= \
uthread_accept.c \
uthread_attr_setcreatesuspend.c \
uthread_autoinit.cc \
uthread_bind.c \
uthread_clean.c \
uthread_close.c \

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by John Birrell.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* This module uses the magic of C++ static constructors to initialize the
* threads package at program start-up time.
*
* Note: Because of a bug in certain versions of "/usr/lib/c++rt0.o", you
* should _not_ enclose the body of this module in an "#ifdef _THREAD_SAFE"
* conditional.
*/
extern "C" void _thread_init(void);
/*
* First, we declare a class with a constructor.
*/
class _thread_init_invoker {
public:
_thread_init_invoker(); /* Constructor declaration. */
};
/*
* Here is the definition of the constructor. All it does is call the
* threads initialization function, "_thread_init".
*/
_thread_init_invoker::_thread_init_invoker()
{
_thread_init();
}
/*
* Here is a single, static instance of our "_thread_init_invoker" class.
* The mere existance of this instance will result in its constructor
* being called, automatically, at program start-up time.
*/
static _thread_init_invoker the_thread_init_invoker;
/*
* For the shared version of the threads library, the above is sufficient.
* But for the archive version of the library, we need a little bit more.
* Namely, we must arrange for this particular module to be pulled in from
* the archive library at link time. To accomplish that, we define and
* initialize a variable, "_thread_autoinit_dummy_decl". This variable is
* referenced (as an extern) from the module "uthread_init.c". So, if
* that module is used, then it will create a need for this module as well,
* ensuring that this module will be present in the executable.
*
* We know that, if the user does _anything_ at all with threads, then the
* "uthread_init.c" module will be linked in. That is the case because
* "uthread_init.c" is the module that defines all of the global variables
* used by the threads library. The presence of "uthread_init.c" will, in
* turn, force this module to be linked in. And the presence of this module
* in the executable will result in the constructor being invoked, and
* "_thread_init" being called.
*/
extern "C" int _thread_autoinit_dummy_decl; /* Declare with "C" linkage */
int _thread_autoinit_dummy_decl = 0;

View File

@ -202,6 +202,18 @@ _thread_main(int argc, char *argv[], char *env)
_thread_init();
return (main(argc, argv, env));
}
#else
/*
* Force our auto-initialization module to be pulled in from the library,
* by referencing a symbol that is defined in it.
*
* The auto-initialization module is a small C++ module. It has a static
* constructor that calls _thread_init() automatically, at the beginning
* of program execution. That eliminates the need for any special hooks
* in crt0.o.
*/
extern int _thread_autoinit_dummy_decl;
static int *_thread_autoinit_dummy_ref = &_thread_autoinit_dummy_decl;
#endif
#else
/*

View File

@ -1,4 +1,6 @@
# $Id$
# $Id: Makefile.inc,v 1.1 1996/01/22 00:23:03 julian Exp $
CPLUSPLUSLIB= cpluspluslib
# uthread sources
.PATH: ${.CURDIR}/uthread
@ -6,6 +8,7 @@
SRCS+= \
uthread_accept.c \
uthread_attr_setcreatesuspend.c \
uthread_autoinit.cc \
uthread_bind.c \
uthread_clean.c \
uthread_close.c \

View File

@ -202,6 +202,18 @@ _thread_main(int argc, char *argv[], char *env)
_thread_init();
return (main(argc, argv, env));
}
#else
/*
* Force our auto-initialization module to be pulled in from the library,
* by referencing a symbol that is defined in it.
*
* The auto-initialization module is a small C++ module. It has a static
* constructor that calls _thread_init() automatically, at the beginning
* of program execution. That eliminates the need for any special hooks
* in crt0.o.
*/
extern int _thread_autoinit_dummy_decl;
static int *_thread_autoinit_dummy_ref = &_thread_autoinit_dummy_decl;
#endif
#else
/*

View File

@ -1,4 +1,6 @@
# $Id$
# $Id: Makefile.inc,v 1.1 1996/01/22 00:23:03 julian Exp $
CPLUSPLUSLIB= cpluspluslib
# uthread sources
.PATH: ${.CURDIR}/uthread
@ -6,6 +8,7 @@
SRCS+= \
uthread_accept.c \
uthread_attr_setcreatesuspend.c \
uthread_autoinit.cc \
uthread_bind.c \
uthread_clean.c \
uthread_close.c \

View File

@ -202,6 +202,18 @@ _thread_main(int argc, char *argv[], char *env)
_thread_init();
return (main(argc, argv, env));
}
#else
/*
* Force our auto-initialization module to be pulled in from the library,
* by referencing a symbol that is defined in it.
*
* The auto-initialization module is a small C++ module. It has a static
* constructor that calls _thread_init() automatically, at the beginning
* of program execution. That eliminates the need for any special hooks
* in crt0.o.
*/
extern int _thread_autoinit_dummy_decl;
static int *_thread_autoinit_dummy_ref = &_thread_autoinit_dummy_decl;
#endif
#else
/*