forked from gitpan/pyperl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy paththrd_ctx.c
123 lines (108 loc) · 2.55 KB
/
thrd_ctx.c
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
* Thread context (only used for MULTI_PERL builds)
*
* Copyright 2000-2001 ActiveState
*
*/
#include <EXTERN.h>
#include <perl.h>
#include <Python.h>
#include "thrd_ctx.h"
#include "perlmodule.h"
static perl_key thrd_ctx_key;
thread_ctx*
get_thread_ctx(void)
{
thread_ctx* ctx;
#ifdef WIN32
ctx = (thread_ctx*)TlsGetValue(thrd_ctx_key);
#else
ctx = (thread_ctx*)pthread_getspecific(thrd_ctx_key);
#endif
if (!ctx) {
refcounted_perl* p = (refcounted_perl*)PyMem_Malloc(sizeof(refcounted_perl));
ctx = (thread_ctx*)PyMem_Malloc(sizeof(thread_ctx));
if (!p || !ctx) {
Py_FatalError("Can't allocate memory for thread context");
}
/* fprintf(stderr, "Allocated new thread context %p\n", ctx); */
memset(ctx, 0, sizeof(thread_ctx));
p->my_perl = new_perl();
p->refcnt = 0;
p->thread_done = 0;
PERL_SET_CONTEXT(p->my_perl);
ctx->perl = p;
#ifdef WIN32
TlsSetValue(thrd_ctx_key, (void*)ctx);
#else
pthread_setspecific(thrd_ctx_key, (void*)ctx);
#endif
}
return ctx;
}
void
free_thread_ctx(thread_ctx* ctx)
{
/* fprintf(stderr, "thread ctx free %p\n", ctx); */
if (ctx->perl->refcnt == 0) {
free_perl(ctx->perl->my_perl);
ctx->perl->my_perl = 0;
PyMem_Free(ctx->perl);
}
else {
/* fprintf(stderr, "still %d references left\n", ctx->perl->refcnt); */
ctx->perl->thread_done++;
}
ctx->perl = 0;
PyMem_Free(ctx);
}
void
thrd_ctx_init()
{
#ifdef WIN32 /* XXX free_thread_ctx() needs to be called in DllMain() */
if ((thrd_ctx_key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
#else
if (pthread_key_create(&thrd_ctx_key, (void*)free_thread_ctx))
#endif
{
Py_FatalError("Can't create TSD key for thrd_ctx");
}
#ifdef BOOT_FROM_PERL
{
dTHX;
refcounted_perl* p = (refcounted_perl*)PyMem_Malloc(sizeof(refcounted_perl));
thread_ctx* ctx = (thread_ctx*)PyMem_Malloc(sizeof(thread_ctx));
if (!p || !ctx) {
Py_FatalError("Can't allocate memory for thread context");
}
/* fprintf(stderr, "Allocated new thread context %p\n", ctx); */
memset(ctx, 0, sizeof(thread_ctx));
p->my_perl = my_perl;
p->refcnt = 0;
p->thread_done = 0;
ctx->perl = p;
#ifdef WIN32
TlsSetValue(thrd_ctx_key, (void*)ctx);
#else
pthread_setspecific(thrd_ctx_key, (void*)ctx);
#endif
}
#endif
}
#if defined(WIN32) && defined(MULTI_PERL)
BOOL WINAPI
DllMain(HINSTANCE hInstance, DWORD dwReason, DWORD lpReserved)
{
BOOL ret = TRUE;
switch (dwReason) {
case DLL_THREAD_DETACH:
{
thread_ctx* ctx = (thread_ctx*)TlsGetValue(thrd_ctx_key);
if (ctx)
free_thread_ctx(ctx);
}
break;
}
return ret;
}
#endif