Branko Čibej wrote:
William A. Rowe, Jr. wrote:
Branko Čibej wrote:
I'm attaching the threadpriv.c
Adding any of the '#pragma data_seg'
gives the following compile time warning for static
APR compiled for a simple hello-world.c:
MSVCRTD.lib(crtexe.obj) : warning LNK4078: multiple '.CRT' sections found with
different attributes (40400040)
MSVCRTD.lib(cinitexe.obj) : warning LNK4254: section '.CRT' (C0000040) merged
into '.rdata' (40000040) with different attributes
Build with:
Microsoft Visual Studio 2005, Version 2.0.50727
Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.42 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
On:
Microsoft Windows Server 2003 R2
Standard x64 Edition
Service Pack 1
The same code works on x86 (Windows XP/32) with either static or
dll flavor of APR.
Attached the source code...
I'm really feeling stupid here. You are saying it works,
but I've spend more then 20 working hours, and I can not make
it even to compile without warnings.
--
Mladen.
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "apr_arch_threadproc.h"
#include "apr_thread_proc.h"
#include "apr_hash.h"
#include "apr_general.h"
#include "apr_lib.h"
#include "apr_errno.h"
#include "apr_portable.h"
#if (_MSC_VER < 1310)
typedef void (__cdecl *_PVFV)(void);
#define INIRETSUCCESS
#define PVAPI void
#else
typedef int (__cdecl *_PVFV)(void);
#define INIRETSUCCESS 0
#define PVAPI int
#endif
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
#pragma section(".rdata$T",read)
extern __declspec(allocate(".rdata$T"))
/* Symbols for connection to the runtime environment */
DWORD _tls_used;
extern _TLSCB __xl_a[], __xl_z[];
/* Global TLS hash table */
apr_hash_t *apr_tls_threadkeys = NULL;
typedef (apr_thredkey_destfn_t)(void *data);
static void threadkey_detach()
{
apr_hash_index_t *hi = apr_hash_first(NULL, apr_tls_threadkeys);
for (; hi != NULL; hi = apr_hash_next(hi)) {
apr_thredkey_destfn_t *dest = NULL;
LPDWORD key;
void *data;
apr_hash_this(hi, &key, NULL, (void **)&dest);
data = TlsGetValue(*key);
if (data != NULL || GetLastError() == ERROR_SUCCESS) {
/* NULL data is a valid TLS value if explicitly set
* by the TlsSetValue
*/
(*dest)(data);
}
}
}
static PVAPI dummy(void)
{
return 0;
}
static PVAPI threadkey_prepare(void)
{
DWORD volatile dw = _tls_used;
#if (_MSC_VER < 1310)
_TLSCB* pfbegin = __xl_a;
_TLSCB* pfend = __xl_z;
_TLSCB* pfdst = pfbegin;
while (pfbegin < pfend) {
if (*pfbegin != 0) {
*pfdst = *pfbegin;
++pfdst;
}
++pfbegin;
}
*pfdst = 0;
#endif
return INIRETSUCCESS;
}
static void NTAPI threadkey_callback(HINSTANCE hInstance, DWORD dwReason,
PVOID pReserved)
{
switch (dwReason) {
case DLL_THREAD_DETACH:
if (apr_tls_threadkeys)
threadkey_detach();
break;
}
}
#if (_MSC_VER >= 1310)
#pragma data_seg(push, old_seg)
#endif
/* Callback to run tls glue code first. */
#pragma data_seg(".CRT$XIU")
static _PVFV p_threadkey_prepare = threadkey_prepare;
#pragma data_seg()
#pragma data_seg(".CRT$XLB")
static _TLSCB p_threadkey_callback = threadkey_callback;
#pragma data_seg()
#if (_MSC_VER >= 1310)
#pragma data_seg(pop, old_seg)
#endif
APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key,
void (*dest)(void *),
apr_pool_t *pool)
{
(*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
if ((*key) == NULL) {
return APR_ENOMEM;
}
(*key)->pool = pool;
if (((*key)->key = TlsAlloc()) != 0xFFFFFFFF) {
apr_hash_set(apr_tls_threadkeys, &((*key)->key),
sizeof(DWORD), dest);
return APR_SUCCESS;
}
return apr_get_os_error();
}
APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new,
apr_threadkey_t *key)
{
if ((*new) = TlsGetValue(key->key)) {
return APR_SUCCESS;
}
return apr_get_os_error();
}
APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv,
apr_threadkey_t *key)
{
if (TlsSetValue(key->key, priv)) {
return APR_SUCCESS;
}
return apr_get_os_error();
}
APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key)
{
if (TlsFree(key->key)) {
apr_hash_set(apr_tls_threadkeys, &(key->key),
sizeof(DWORD), NULL);
return APR_SUCCESS;
}
return apr_get_os_error();
}
APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key,
apr_threadkey_t *threadkey)
{
return apr_pool_userdata_get(data, key, threadkey->pool);
}
APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key,
apr_status_t (*cleanup)(void *),
apr_threadkey_t *threadkey)
{
return apr_pool_userdata_set(data, key, cleanup, threadkey->pool);
}
APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey,
apr_threadkey_t *key)
{
*thekey = key->key;
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key,
apr_os_threadkey_t *thekey,
apr_pool_t *pool)
{
if (pool == NULL) {
return APR_ENOPOOL;
}
if ((*key) == NULL) {
(*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
(*key)->pool = pool;
}
(*key)->key = *thekey;
return APR_SUCCESS;
}