concurrence.h (__gnu_cxx::lock): New.

2004-06-24  Benjamin Kosnik  <bkoz@redhat.com>

	* include/bits/concurrence.h (__gnu_cxx::lock): New.
	* include/ext/pool_allocator.h (__pool_base::_Lock::_S_lock): Remove.
	(__pool_base::_M_get_mutex): New.
	* include/bits/allocator.h: Tweak.
	* src/allocator.cc (__pool_base::_M_get_free_list): Correct offset.
	* config/linker-map.gnu: Remove __pool_base::_Lock::_S_lock.
	* include/bits/stl_threads.h: Remove.
	* include/Makefile.am: Also here.
	* include/Makefile.in: Regenerate.

	* src/locale_init.cc: Use __gnu_cxx::lock.

	* src/allocator.cc: Move all instantiations...
	* src/allocator-inst.cc: ...here.

From-SVN: r83638
This commit is contained in:
Benjamin Kosnik 2004-06-25 06:10:44 +00:00 committed by Benjamin Kosnik
parent ade83c33bd
commit 838d430929
11 changed files with 96 additions and 215 deletions

View File

@ -1,3 +1,20 @@
2004-06-24 Benjamin Kosnik <bkoz@redhat.com>
* include/bits/concurrence.h (__gnu_cxx::lock): New.
* include/ext/pool_allocator.h (__pool_base::_Lock::_S_lock): Remove.
(__pool_base::_M_get_mutex): New.
* include/bits/allocator.h: Tweak.
* src/allocator.cc (__pool_base::_M_get_free_list): Correct offset.
* config/linker-map.gnu: Remove __pool_base::_Lock::_S_lock.
* include/bits/stl_threads.h: Remove.
* include/Makefile.am: Also here.
* include/Makefile.in: Regenerate.
* src/locale_init.cc: Use __gnu_cxx::lock.
* src/allocator.cc: Move all instantiations...
* src/allocator-inst.cc: ...here.
2004-06-23 Andrew Pinski <apinski@apple.com>
* linkage.m4: Remove check for libmx.

View File

@ -143,7 +143,6 @@ GLIBCXX_3.4 {
_ZNSt12__basic_fileIcE6xsputn*;
_ZNSt12__basic_fileIcE7seekoff*;
_ZNSt12__basic_fileIcE8sys_openE*St13_Ios_Openmode;
_ZNSt12__basic_fileIcE8sys_openEiSt13_Ios_Openmode;
_ZNSt12__basic_fileIcE8xsputn_2*;
_ZNSt12__basic_fileIcE9showmanycEv;
_ZNSt12__basic_fileIcEC*;
@ -257,10 +256,10 @@ GLIBCXX_3.4.1 {
GLIBCXX_3.4.2 {
_ZN9__gnu_cxx11__pool_base5_Lock7_S_lockE;
_ZN9__gnu_cxx11__pool_base9_M_refillEj;
_ZN9__gnu_cxx11__pool_base16_M_get_free_listEj;
_ZN9__gnu_cxx11__pool_base9_M_refillE[jm];
_ZN9__gnu_cxx11__pool_base16_M_get_free_listE[jm];
_ZN9__gnu_cxx11__pool_base12_M_get_mutexEv;
} GLIBCXX_3.4.1;
# Symbols in the support library (libsupc++) have their own tag.

View File

@ -145,7 +145,6 @@ bits_headers = \
${bits_srcdir}/stl_set.h \
${bits_srcdir}/stl_stack.h \
${bits_srcdir}/stl_tempbuf.h \
${bits_srcdir}/stl_threads.h \
${bits_srcdir}/stl_tree.h \
${bits_srcdir}/stl_uninitialized.h \
${bits_srcdir}/stl_vector.h \

View File

@ -357,7 +357,6 @@ bits_headers = \
${bits_srcdir}/stl_set.h \
${bits_srcdir}/stl_stack.h \
${bits_srcdir}/stl_tempbuf.h \
${bits_srcdir}/stl_threads.h \
${bits_srcdir}/stl_tree.h \
${bits_srcdir}/stl_uninitialized.h \
${bits_srcdir}/stl_vector.h \

View File

@ -94,8 +94,8 @@ namespace std
allocator() throw() { }
allocator(const allocator& a) throw()
: ___glibcxx_base_allocator<_Tp>(a) { }
allocator(const allocator& __a) throw()
: ___glibcxx_base_allocator<_Tp>(__a) { }
template<typename _Tp1>
allocator(const allocator<_Tp1>&) throw() { }

View File

@ -62,4 +62,26 @@ __gthread_mutex_lock(&NAME)
#endif
namespace __gnu_cxx
{
class lock
{
// Externally defined and initialized.
__gthread_mutex_t* device;
public:
// Acquire the mutex here with a constructor call. This ensures
// that it is released in exit or during stack unwinding.
explicit lock(__gthread_mutex_t& name) : device(&name)
{ __glibcxx_mutex_lock(*device); }
~lock() throw()
{ __glibcxx_mutex_unlock(*device); }
private:
lock(const lock&);
lock& operator=(const lock&);
};
}
#endif

View File

@ -1,150 +0,0 @@
// Threading support -*- C++ -*-
// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
/*
* Copyright (c) 1997-1999
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
/** @file stl_threads.h
* This is an internal header file, included by other library headers.
* You should not attempt to use it directly.
*/
#ifndef _STL_THREADS_H
#define _STL_THREADS_H 1
#include <cstddef>
// The only supported threading model is GCC's own gthr.h abstraction
// layer.
#include "bits/gthr.h"
namespace __gnu_internal
{
#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
extern __gthread_mutex_t _GLIBCXX_mutex;
extern __gthread_mutex_t *_GLIBCXX_mutex_address;
extern __gthread_once_t _GLIBCXX_once;
extern void _GLIBCXX_mutex_init(void);
extern void _GLIBCXX_mutex_address_init(void);
#endif
} // namespace __gnu_internal
namespace __gnu_cxx
{
// Locking class. Note that this class *does not have a
// constructor*. It must be initialized either statically, with
// __STL_MUTEX_INITIALIZER, or dynamically, by explicitly calling
// the _M_initialize member function. (This is similar to the ways
// that a pthreads mutex can be initialized.) There are explicit
// member functions for acquiring and releasing the lock.
// There is no constructor because static initialization is
// essential for some uses, and only a class aggregate (see section
// 8.5.1 of the C++ standard) can be initialized that way. That
// means we must have no constructors, no base classes, no virtual
// functions, and no private or protected members.
struct _STL_mutex_lock
{
// The class must be statically initialized with __STL_MUTEX_INITIALIZER.
#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
volatile int _M_init_flag;
__gthread_once_t _M_once;
#endif
__gthread_mutex_t _M_lock;
void
_M_initialize()
{
#ifdef __GTHREAD_MUTEX_INIT
// There should be no code in this path given the usage rules above.
#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
if (_M_init_flag) return;
if (__gthread_once(&__gnu_internal::_GLIBCXX_once,
__gnu_internal::_GLIBCXX_mutex_init) != 0
&& __gthread_active_p())
abort ();
__gthread_mutex_lock(&__gnu_internal::_GLIBCXX_mutex);
if (!_M_init_flag)
{
// Even though we have a global lock, we use __gthread_once to be
// absolutely certain the _M_lock mutex is only initialized once on
// multiprocessor systems.
__gnu_internal::_GLIBCXX_mutex_address = &_M_lock;
if (__gthread_once(&_M_once,
__gnu_internal::_GLIBCXX_mutex_address_init) != 0
&& __gthread_active_p())
abort();
_M_init_flag = 1;
}
__gthread_mutex_unlock(&__gnu_internal::_GLIBCXX_mutex);
#endif
}
void
_M_acquire_lock()
{
#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
if (!_M_init_flag) _M_initialize();
#endif
__gthread_mutex_lock(&_M_lock);
}
void
_M_release_lock()
{
#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION)
if (!_M_init_flag) _M_initialize();
#endif
__gthread_mutex_unlock(&_M_lock);
}
};
#ifdef __GTHREAD_MUTEX_INIT
#define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT }
#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
#ifdef __GTHREAD_MUTEX_INIT_DEFAULT
#define __STL_MUTEX_INITIALIZER \
= { 0, __GTHREAD_ONCE_INIT, __GTHREAD_MUTEX_INIT_DEFAULT }
#else
#define __STL_MUTEX_INITIALIZER = { 0, __GTHREAD_ONCE_INIT }
#endif
#endif
} // namespace __gnu_cxx
#endif

View File

@ -50,8 +50,8 @@
#include <bits/c++config.h>
#include <new>
#include <bits/functexcept.h>
#include <bits/stl_threads.h>
#include <bits/atomicity.h>
#include <bits/concurrence.h>
namespace __gnu_cxx
{
@ -80,15 +80,6 @@ namespace __gnu_cxx
enum { _S_max_bytes = 128 };
enum { _S_free_list_size = _S_max_bytes / _S_align };
// It would be nice to use _STL_auto_lock here. But we need a
// test whether threads are in use.
struct _Lock
{
static _STL_mutex_lock _S_lock;
_Lock() { _S_lock._M_acquire_lock(); }
~_Lock() { _S_lock._M_release_lock(); }
};
union _Obj
{
union _Obj* _M_free_list_link;
@ -96,7 +87,7 @@ namespace __gnu_cxx
};
static _Obj* volatile _S_free_list[_S_free_list_size];
// Chunk allocation state.
static char* _S_start_free;
static char* _S_end_free;
@ -109,6 +100,9 @@ namespace __gnu_cxx
_Obj* volatile*
_M_get_free_list(size_t __bytes);
__gthread_mutex_t&
_M_get_mutex();
// Returns an object of size __n, and optionally adds to size __n
// free list.
void*
@ -216,10 +210,7 @@ namespace __gnu_cxx
{
_Obj* volatile* __free_list = _M_get_free_list(__bytes);
// Acquire the lock here with a constructor call. This
// ensures that it is released in exit or during stack
// unwinding.
_Lock __lock_instance;
lock sentry(_M_get_mutex());
_Obj* __restrict__ __result = *__free_list;
if (__builtin_expect(__result == 0, 0))
__ret = static_cast<_Tp*>(_M_refill(_M_round_up(__bytes)));
@ -252,10 +243,7 @@ namespace __gnu_cxx
_Obj* volatile* __free_list = _M_get_free_list(__bytes);
_Obj* __q = reinterpret_cast<_Obj*>(__p);
// Acquire the lock here with a constructor call. This
// ensures that it is released in exit or during stack
// unwinding.
_Lock __lock_instance;
lock sentry(_M_get_mutex());
__q ->_M_free_list_link = *__free_list;
*__free_list = __q;
}

View File

@ -31,11 +31,21 @@
// ISO C++ 14882:
//
#include <bits/c++config.h>
#include <memory>
#include <ext/mt_allocator.h>
#include <ext/pool_allocator.h>
namespace std
{
template class allocator<char>;
template class allocator<wchar_t>;
} // namespace std
namespace __gnu_cxx
{
template class __mt_alloc<char>;
template class __mt_alloc<wchar_t>;
template class __pool_alloc<char>;
template class __pool_alloc<wchar_t>;
} // namespace __gnu_cxx

View File

@ -36,20 +36,25 @@
#include <ext/mt_allocator.h>
#include <ext/pool_allocator.h>
namespace __gnu_internal
{
__glibcxx_mutex_define_initialized(palloc_init_mutex);
}
namespace __gnu_cxx
{
// Instantiations for __mt_alloc.
template class __mt_alloc<char>;
template class __mt_alloc<wchar_t>;
// Definitions and instantiations for __pool_alloc and base class.
// Definitions for __pool_alloc_base.
__pool_base::_Obj* volatile*
__pool_base::_M_get_free_list(size_t __bytes)
{
size_t __i = ((__bytes + (size_t)_S_align - 1) / (size_t)_S_align - 1);
return _S_free_list + __i - 1;
return _S_free_list + __i;
}
__gthread_mutex_t&
__pool_base::_M_get_mutex()
{ return __gnu_internal::palloc_init_mutex; }
// Allocate memory in large chunks in order to avoid fragmenting the
// heap too much. Assume that __n is properly aligned. We hold the
// allocation lock.
@ -89,21 +94,17 @@ namespace __gnu_cxx
_S_start_free = static_cast<char*>(::operator new(__bytes_to_get));
if (_S_start_free == 0)
{
size_t __i;
_Obj* volatile* __free_list;
_Obj* __p;
// Try to make do with what we have. That can't hurt. We
// do not try smaller requests, since that tends to result
// in disaster on multi-process machines.
__i = __n;
size_t __i = __n;
for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align)
{
__free_list = _M_get_free_list(__i);
__p = *__free_list;
_Obj* volatile* __free_list = _M_get_free_list(__i);
_Obj* __p = *__free_list;
if (__p != 0)
{
*__free_list = __p -> _M_free_list_link;
*__free_list = __p->_M_free_list_link;
_S_start_free = (char*)__p;
_S_end_free = _S_start_free + __i;
return _M_allocate_chunk(__n, __nobjs);
@ -112,9 +113,10 @@ namespace __gnu_cxx
}
}
_S_end_free = 0; // In case of exception.
_S_start_free = static_cast<char*>(::operator new(__bytes_to_get));
// This should either throw an exception or remedy the situation.
// Thus we assume it succeeded.
_S_start_free = static_cast<char*>(::operator new(__bytes_to_get));
}
_S_heap_size += __bytes_to_get;
_S_end_free = _S_start_free + __bytes_to_get;
@ -134,26 +136,25 @@ namespace __gnu_cxx
_Obj* __result;
_Obj* __current_obj;
_Obj* __next_obj;
int __i;
if (1 == __nobjs)
if (__nobjs == 1)
return __chunk;
__free_list = _M_get_free_list(__n);
// Build free list in chunk.
__result = (_Obj*)(void*)__chunk;
*__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n);
for (__i = 1; ; __i++)
for (int __i = 1; ; __i++)
{
__current_obj = __next_obj;
__next_obj = (_Obj*)(void*)((char*)__next_obj + __n);
if (__nobjs - 1 == __i)
{
__current_obj -> _M_free_list_link = 0;
__current_obj->_M_free_list_link = 0;
break;
}
else
__current_obj -> _M_free_list_link = __next_obj;
__current_obj->_M_free_list_link = __next_obj;
}
return __result;
}
@ -165,9 +166,4 @@ namespace __gnu_cxx
char* __pool_base::_S_end_free = 0;
size_t __pool_base::_S_heap_size = 0;
_STL_mutex_lock __pool_base::_Lock::_S_lock __STL_MUTEX_INITIALIZER;
template class __pool_alloc<char>;
template class __pool_alloc<wchar_t>;
} // namespace __gnu_cxx

View File

@ -100,25 +100,26 @@ namespace std
locale::locale() throw() : _M_impl(0)
{
_S_initialize();
__glibcxx_mutex_lock(__gnu_internal::locale_cons_mutex);
_S_initialize();
__gnu_cxx::lock sentry(__gnu_internal::locale_cons_mutex);
_S_global->_M_add_reference();
_M_impl = _S_global;
__glibcxx_mutex_unlock(__gnu_internal::locale_cons_mutex);
}
locale
locale::global(const locale& __other)
{
_S_initialize();
__glibcxx_mutex_lock(__gnu_internal::locale_global_mutex);
_Impl* __old = _S_global;
__other._M_impl->_M_add_reference();
_S_global = __other._M_impl;
const string __other_name = __other.name();
if (__other_name != "*")
setlocale(LC_ALL, __other_name.c_str());
__glibcxx_mutex_unlock(__gnu_internal::locale_global_mutex);
_Impl* __old;
{
__gnu_cxx::lock sentry(__gnu_internal::locale_global_mutex);
__old = _S_global;
__other._M_impl->_M_add_reference();
_S_global = __other._M_impl;
const string __other_name = __other.name();
if (__other_name != "*")
setlocale(LC_ALL, __other_name.c_str());
}
// Reference count sanity check: one reference removed for the
// subsition of __other locale, one added by return-by-value. Net