File: cr_pthread.c

package info (click to toggle)
blcr 0.8.5-2
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 10,736 kB
  • sloc: ansic: 31,999; sh: 12,633; makefile: 940; perl: 401; cpp: 79; java: 9
file content (109 lines) | stat: -rw-r--r-- 3,739 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* 
 * Berkeley Lab Checkpoint/Restart (BLCR) for Linux is Copyright (c)
 * 2003, The Regents of the University of California, through Lawrence
 * Berkeley National Laboratory (subject to receipt of any required
 * approvals from the U.S. Dept. of Energy).  All rights reserved.
 *
 * Portions may be copyrighted by others, as may be noted in specific
 * copyright notices within specific files.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: cr_pthread.c,v 1.31 2007/09/20 23:53:34 phargrov Exp $
 */

#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include "cr_private.h"

#if PIC && HAVE___REGISTER_ATFORK
// pthread_atfork() handling for shared objects
// glibc has started putting pthread_atfork() in libpthread_nonshared.a, which is causing
// problems when we call from a shared library.  The problem is that the code in the
// static lib gets pulled into libcr.so, but its was not PIC-compiled.
// Therefore, we use our own private re-implementation.
// This implementation is closely based on glibc-2.3.2-20030313/nptl/pthread_atfork.c
extern void *__dso_handle __attribute__((__weak__));
extern int __register_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void), void *dso_handle);
extern int
cri_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
{ 
  void *my_handle = &__dso_handle ? __dso_handle : NULL;
  return __register_atfork(prepare, parent, child, my_handle);
}
#endif

// Holds thread-specific data key for cri_info
pthread_key_t cri_info_key;

// atfork callback to reset the state
static void
child_reset(void)
{
    cri_rb_init(&cri_cs_lock);
    cri_atomic_write(&cri_live_count, 0);
    cri_info_free(cri_info_location());
}

#if !HAVE___REGISTER_ATFORK
// Interpose on fork() to ensure the pthreads version is called
// if the caller linked us, but not the pthreads library.
pid_t cri_fork(void)
{
  return __fork();
}
weak_alias(cri_fork,fork);
#endif

//
// Initialize pthread-dependent parts
//
void
cri_pthread_init(void)
{
    int rc;

  #if !HAVE___REGISTER_ATFORK
    // See bug #460
    {
	// dlopen will fail if this is a static exectuable.
	// If so, then the pthread library references must
	// have been resolved.
	void *handle = dlopen(NULL /* the executable */, RTLD_LAZY);
	if (handle) {
	    if (dlsym(handle, "__fork") == dlsym(handle, "__libc_fork")) {
		CRI_ABORT("Unable to ensure pthread_atfork() will run.\n"
			  "If you dlopen(libcr.so) or use some versions of the libraries/loaders, "
			  "then you may need to link libpthread explicitly (or use LD_PRELOAD).");
	    }
	    dlclose(handle);
	}
    }
  #endif /* !HAVE___REGISTER_ATFORK */

    // Install a atfork callback to cleanup state in children
    rc = cri_atfork(NULL, NULL, &child_reset);
    if (rc != 0) {
	CRI_ABORT("cri_atfork() returned %d", rc);
    }

    // Setup the thread-specific data for cri_info
    rc = pthread_key_create(&cri_info_key, &cri_info_free);
    if (rc != 0) {
	CRI_ABORT("pthread_key_create() returned %d", rc);
    }
}