<commit_before>/*
 * Copyright (c) 2013 Red Hat.
 * Copyright (c) 2011 <NAME>.  All Rights Reserved.
 * 
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public
 * License for more details.
 */

#include "pmapi.h"
#include "impl.h"
#include "internal.h"
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif

#ifdef PM_MULTI_THREAD
typedef struct {
    void	*lock;
    int		count;
} lockdbg_t;

#define PM_LOCK_OP	1
#define PM_UNLOCK_OP	2

static int		multi_init[PM_SCOPE_MAX+1];
static pthread_t	multi_seen[PM_SCOPE_MAX+1];

/* the big libpcp lock */
#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
pthread_mutex_t	__pmLock_libpcp = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
#else
pthread_mutex_t	__pmLock_libpcp = PTHREAD_MUTEX_INITIALIZER;

#ifndef HAVE___THREAD
pthread_key_t 	__pmTPDKey = 0;

static void
__pmTPD__destroy(void *addr)
{
    free(addr);
}
#endif
#endif

static void
SetupDebug(void)
{
    /*
     * if $PCP_DEBUG is set in the environment then use the (decimal)
     * value to set bits in pmDebug via bitwise ORing
     */
    char	*val = getenv("PCP_DEBUG");
    int		ival;

    if (val != NULL) {
	char	*end;
	ival = strtol(val, &end, 10);
	if (*end != '\0') {
	    fprintf(stderr, "Error: $PCP_DEBUG=%s is not numeric, ignored\n", val);
	}
	else
	    pmDebug |= ival;
    }
}

void
__pmInitLocks(void)
{
    static pthread_mutex_t	init = PTHREAD_MUTEX_INITIALIZER;
    static int			done = 0;
    int				psts;
    char			errmsg[PM_MAXERRMSGLEN];
    if ((psts = pthread_mutex_lock(&init)) != 0) {
	pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	fprintf(stderr, "__pmInitLocks: pthread_mutex_lock failed: %s", errmsg);
	exit(4);
    }
    if (!done) {
	SetupDebug();
#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
	/*
	 * Unable to initialize at compile time, need to do it here in
	 * a one trip for all threads run-time initialization.
	 */
	pthread_mutexattr_t	attr;

	if ((psts = pthread_mutexattr_init(&attr)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_mutexattr_init failed: %s", errmsg);
	    exit(4);
	}
	if ((psts = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_mutexattr_settype failed: %s", errmsg);
	    exit(4);
	}
	if ((psts = pthread_mutex_init(&__pmLock_libpcp, &attr)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_mutex_init failed: %s", errmsg);
	    exit(4);
	}
	pthread_mutexattr_destroy(&attr);
#endif
#ifndef HAVE___THREAD
	/* first thread here creates the thread private data key */
	if ((psts = pthread_key_create(&__pmTPDKey, __pmTPD__destroy)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_key_create failed: %s", errmsg);
	    exit(4);
	}
#endif
	done = 1;
    }
    if ((psts = pthread_mutex_unlock(&init)) != 0) {
	pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	fprintf(stderr, "__pmInitLocks: pthread_mutex_unlock failed: %s", errmsg);
	exit(4);
    }
#ifndef HAVE___THREAD
    if (pthread_getspecific(__pmTPDKey) == NULL) {
	__pmTPD	*tpd = (__pmTPD *)malloc(sizeof(__pmTPD));
	if (tpd == NULL) {
	    __pmNoMem("__pmInitLocks: __pmTPD", sizeof(__pmTPD), PM_FATAL_ERR);
	    /*NOTREACHED*/
	}
	if ((psts = pthread_setspecific(__pmTPDKey, tpd)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_setspecific failed: %s", errmsg);
	    exit(4);
	}
	tpd->curcontext = PM_CONTEXT_UNDEF;
    }
#endif
}

int
__pmMultiThreaded(int scope)
{
    int		sts = 0;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (!multi_init[scope]) {
	multi_init[scope] = 1;
	multi_seen[scope] = pthread_self();
    }
    else {
	if (!pthread_equal(multi_seen[scope], pthread_self()))
	    sts = 1;
    }
    PM_UNLOCK(__pmLock_libpcp);<commit_msg>src/libpcp/src/lock.c: fix initialization error in roll-your-own TPD<commit_after>/*
 * Copyright (c) 2013 Red Hat.
 * Copyright (c) 2011 <NAME>.  All Rights Reserved.
 * 
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public
 * License for more details.
 */

#include "pmapi.h"
#include "impl.h"
#include "internal.h"
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif

#ifdef PM_MULTI_THREAD
typedef struct {
    void	*lock;
    int		count;
} lockdbg_t;

#define PM_LOCK_OP	1
#define PM_UNLOCK_OP	2

static int		multi_init[PM_SCOPE_MAX+1];
static pthread_t	multi_seen[PM_SCOPE_MAX+1];

/* the big libpcp lock */
#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
pthread_mutex_t	__pmLock_libpcp = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
#else
pthread_mutex_t	__pmLock_libpcp = PTHREAD_MUTEX_INITIALIZER;

#ifndef HAVE___THREAD
pthread_key_t 	__pmTPDKey = 0;

static void
__pmTPD__destroy(void *addr)
{
    free(addr);
}
#endif
#endif

static void
SetupDebug(void)
{
    /*
     * if $PCP_DEBUG is set in the environment then use the (decimal)
     * value to set bits in pmDebug via bitwise ORing
     */
    char	*val = getenv("PCP_DEBUG");
    int		ival;

    if (val != NULL) {
	char	*end;
	ival = strtol(val, &end, 10);
	if (*end != '\0') {
	    fprintf(stderr, "Error: $PCP_DEBUG=%s is not numeric, ignored\n", val);
	}
	else
	    pmDebug |= ival;
    }
}

void
__pmInitLocks(void)
{
    static pthread_mutex_t	init = PTHREAD_MUTEX_INITIALIZER;
    static int			done = 0;
    int				psts;
    char			errmsg[PM_MAXERRMSGLEN];
    if ((psts = pthread_mutex_lock(&init)) != 0) {
	pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	fprintf(stderr, "__pmInitLocks: pthread_mutex_lock failed: %s", errmsg);
	exit(4);
    }
    if (!done) {
	SetupDebug();
#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
	/*
	 * Unable to initialize at compile time, need to do it here in
	 * a one trip for all threads run-time initialization.
	 */
	pthread_mutexattr_t	attr;

	if ((psts = pthread_mutexattr_init(&attr)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_mutexattr_init failed: %s", errmsg);
	    exit(4);
	}
	if ((psts = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_mutexattr_settype failed: %s", errmsg);
	    exit(4);
	}
	if ((psts = pthread_mutex_init(&__pmLock_libpcp, &attr)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_mutex_init failed: %s", errmsg);
	    exit(4);
	}
	pthread_mutexattr_destroy(&attr);
#endif
#ifndef HAVE___THREAD
	/* first thread here creates the thread private data key */
	if ((psts = pthread_key_create(&__pmTPDKey, __pmTPD__destroy)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_key_create failed: %s", errmsg);
	    exit(4);
	}
#endif
	done = 1;
    }
    if ((psts = pthread_mutex_unlock(&init)) != 0) {
	pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	fprintf(stderr, "__pmInitLocks: pthread_mutex_unlock failed: %s", errmsg);
	exit(4);
    }
#ifndef HAVE___THREAD
    if (pthread_getspecific(__pmTPDKey) == NULL) {
	__pmTPD	*tpd = (__pmTPD *)malloc(sizeof(__pmTPD));
	if (tpd == NULL) {
	    __pmNoMem("__pmInitLocks: __pmTPD", sizeof(__pmTPD), PM_FATAL_ERR);
	    /*NOTREACHED*/
	}
	if ((psts = pthread_setspecific(__pmTPDKey, tpd)) != 0) {
	    pmErrStr_r(-psts, errmsg, sizeof(errmsg));
	    fprintf(stderr, "__pmInitLocks: pthread_setspecific failed: %s", errmsg);
	    exit(4);
	}
	memset((void *)tpd, 0, sizeof(*tpd));
	tpd->curcontext = PM_CONTEXT_UNDEF;
    }
#endif
}

int
__pmMultiThreaded(int scope)
{
    int		sts = 0;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (!multi_init[scope]) {
	multi_init[scope] = 1;
	multi_seen[scope] = pthread_self();
    }
    else {
	if (!pthread_equal(multi_seen[scope], pthread_self()))
	    sts = 1;
    }
    PM_UNLOCK(__pmLock_libpcp);
{'fraction_non_alphanumeric': 0.12249087591240876, 'fraction_numerical': 0.008553832116788321, 'mean_word_length': 4.158235294117647, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4113958', 'n_tokens_mistral': 3412, 'n_tokens_neox': 3315, 'n_words': 813}