This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Yet another twist.
[perl5.git] / win32 / win32thread.c
1 #include "EXTERN.h"
2 #include "perl.h"
3
4 #ifdef USE_DECLSPEC_THREAD
5 __declspec(thread) void *PL_current_context = NULL;
6 #endif
7
8 void
9 Perl_set_context(void *t)
10 {
11 #if defined(USE_5005THREADS) || defined(USE_ITHREADS)
12 #  ifdef USE_DECLSPEC_THREAD
13     Perl_current_context = t;
14 #  else
15     DWORD err = GetLastError();
16     TlsSetValue(PL_thr_key,t);
17     SetLastError(err);
18 #  endif
19 #endif
20 }
21
22 void *
23 Perl_get_context(void)
24 {
25 #if defined(USE_5005THREADS) || defined(USE_ITHREADS)
26 #  ifdef USE_DECLSPEC_THREAD
27     return Perl_current_context;
28 #  else
29     DWORD err = GetLastError();
30     void *result = TlsGetValue(PL_thr_key);
31     SetLastError(err);
32     return result;
33 #  endif
34 #else
35     return NULL;
36 #endif
37 }
38
39 #ifdef USE_5005THREADS
40 void
41 Perl_init_thread_intern(struct perl_thread *athr)
42 {
43 #ifndef USE_DECLSPEC_THREAD
44
45  /* 
46   * Initialize port-specific per-thread data in thr->i
47   * as only things we have there are just static areas for
48   * return values we don't _need_ to do anything but 
49   * this is good practice:
50   */
51  memset(&athr->i,0,sizeof(athr->i));
52
53 #endif
54 }
55
56 void
57 Perl_set_thread_self(struct perl_thread *thr)
58 {
59     /* Set thr->self.  GetCurrentThread() retrurns a pseudo handle, need
60        this to convert it into a handle another thread can use.
61      */
62     DuplicateHandle(GetCurrentProcess(),
63                     GetCurrentThread(),
64                     GetCurrentProcess(),
65                     &thr->self,
66                     0,
67                     FALSE,
68                     DUPLICATE_SAME_ACCESS);
69 }
70
71 int
72 Perl_thread_create(struct perl_thread *thr, thread_func_t *fn)
73 {
74     DWORD junk;
75     unsigned long th;
76
77     DEBUG_S(PerlIO_printf(Perl_debug_log,
78                           "%p: create OS thread\n", thr));
79 #ifdef USE_RTL_THREAD_API
80     /* See comment about USE_RTL_THREAD_API in win32thread.h */
81 #if defined(__BORLANDC__)
82     th = _beginthreadNT(fn,                             /* start address */
83                         0,                              /* stack size */
84                         (void *)thr,                    /* parameters */
85                         (void *)NULL,                   /* security attrib */
86                         0,                              /* creation flags */
87                         (unsigned long *)&junk);        /* tid */
88     if (th == (unsigned long)-1)
89         th = 0;
90 #elif defined(_MSC_VER_)
91     th = _beginthreadex((void *)NULL,                   /* security attrib */
92                         0,                              /* stack size */
93                         fn,                             /* start address */
94                         (void*)thr,                     /* parameters */
95                         0,                              /* creation flags */
96                         (unsigned *)&junk);             /* tid */
97 #else /* compilers using CRTDLL.DLL only have _beginthread() */
98     th = _beginthread(fn,                               /* start address */
99                       0,                                /* stack size */
100                       (void*)thr);                      /* parameters */
101     if (th == (unsigned long)-1)
102         th = 0;
103 #endif
104     thr->self = (HANDLE)th;
105 #else   /* !USE_RTL_THREAD_API */
106     thr->self = CreateThread(NULL, 0, fn, (void*)thr, 0, &junk);
107 #endif  /* !USE_RTL_THREAD_API */
108     DEBUG_S(PerlIO_printf(Perl_debug_log,
109                           "%p: OS thread = %p, id=%ld\n", thr, thr->self, junk));
110     return thr->self ? 0 : -1;
111 }
112 #endif
113