Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
f19f07d5
Commit
f19f07d5
authored
Apr 14, 2000
by
Ove Kaaven
Committed by
Alexandre Julliard
Apr 14, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
POSIX threads emulation, tricks glibc into being threadsafe.
parent
d804111d
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
280 additions
and
1 deletion
+280
-1
thread.h
include/thread.h
+2
-1
Makefile.in
scheduler/Makefile.in
+1
-0
pthread.c
scheduler/pthread.c
+277
-0
No files found.
include/thread.h
View file @
f19f07d5
...
...
@@ -95,10 +95,11 @@ typedef struct _TEB
void
*
buffer
;
/* --3 208 Buffer shared with server */
int
buffer_size
;
/* --3 20c Size of server buffer */
void
*
debug_info
;
/* --3 210 Info for debugstr functions */
void
*
pthread_data
;
/* --3 214 Data for pthread emulation */
/* here is plenty space for wine specific fields (don't forget to change pad6!!) */
/* the following are nt specific fields */
DWORD
pad6
[
63
3
];
/* --n 214
*/
DWORD
pad6
[
63
2
];
/* --n 218
*/
UNICODE_STRING
StaticUnicodeString
;
/* -2- bf8 used by advapi32 */
USHORT
StaticUnicodeBuffer
[
261
];
/* -2- c00 used by advapi32 */
DWORD
pad7
;
/* --n e0c */
...
...
scheduler/Makefile.in
View file @
f19f07d5
...
...
@@ -14,6 +14,7 @@ C_SRCS = \
mutex.c
\
pipe.c
\
process.c
\
pthread.c
\
semaphore.c
\
services.c
\
synchro.c
\
...
...
scheduler/pthread.c
0 → 100644
View file @
f19f07d5
/*
* pthread emulation for re-entrant libcs
*
* We can't use pthreads directly, so why not let libcs
* that wants pthreads use Wine's own threading instead...
*
* Copyright 1999 Ove Kven
*/
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include "winbase.h"
#include "heap.h"
#include "thread.h"
/* Currently this probably works only for glibc2,
* which checks for the presence of double-underscore-prepended
* pthread primitives, and use them if available.
* If they are not available, the libc defaults to
* non-threadsafe operation (not good). */
#if defined(__GLIBC__)
#include <pthread.h>
#ifdef NEED_UNDERSCORE_PREFIX
# define PREFIX "_"
#else
# define PREFIX
#endif
/* adapt as necessary (a construct like this is used in glibc sources) */
#define strong_alias(orig, alias) \
asm(".globl " PREFIX #alias "\n\t.set " PREFIX #alias "," PREFIX #orig)
/* NOTE: This is a truly extremely incredibly ugly hack!
* But it does seem to work... */
/* assume that pthread_mutex_t has room for at least one pointer,
* and hope that the users of pthread_mutex_t considers it opaque
* (never checks what's in it) */
typedef
struct
{
CRITICAL_SECTION
*
critsect
;
}
*
wine_mutex
;
typedef
struct
_wine_cleanup
{
void
(
*
routine
)(
void
*
);
void
*
arg
;
}
*
wine_cleanup
;
typedef
const
void
*
key_data
;
#define FIRST_KEY 0
#define MAX_KEYS 16
/* libc6 doesn't use that many, but... */
static
CRITICAL_SECTION
init_sect
=
CRITICAL_SECTION_INIT
;
#define P_OUTPUT(stuff) write(2,stuff,strlen(stuff))
void
__pthread_initialize
(
void
)
{
}
int
__pthread_once
(
pthread_once_t
*
once_control
,
void
(
*
init_routine
)(
void
))
{
static
pthread_once_t
the_once
=
PTHREAD_ONCE_INIT
;
EnterCriticalSection
(
&
init_sect
);
if
(
!
memcmp
(
once_control
,
&
the_once
,
sizeof
(
the_once
)))
{
(
*
init_routine
)();
(
*
(
int
*
)
once_control
)
++
;
}
LeaveCriticalSection
(
&
init_sect
);
return
0
;
}
strong_alias
(
__pthread_once
,
pthread_once
);
int
__pthread_mutex_init
(
pthread_mutex_t
*
mutex
,
const
pthread_mutexattr_t
*
mutexattr
)
{
/* glibc has a tendency to initialize mutexes very often, even
in situations where they are not really used later on.
As for us, initializing a mutex is very expensive, we postpone
the real initialization until the time the mutex is first used. */
((
wine_mutex
)
mutex
)
->
critsect
=
NULL
;
return
0
;
}
strong_alias
(
__pthread_mutex_init
,
pthread_mutex_init
);
static
void
mutex_real_init
(
pthread_mutex_t
*
mutex
)
{
EnterCriticalSection
(
&
init_sect
);
if
(
!
((
wine_mutex
)
mutex
)
->
critsect
)
{
((
wine_mutex
)
mutex
)
->
critsect
=
HeapAlloc
(
SystemHeap
,
0
,
sizeof
(
CRITICAL_SECTION
));
InitializeCriticalSection
(((
wine_mutex
)
mutex
)
->
critsect
);
}
LeaveCriticalSection
(
&
init_sect
);
}
int
__pthread_mutex_lock
(
pthread_mutex_t
*
mutex
)
{
if
(
!
SystemHeap
)
return
0
;
if
(
!
((
wine_mutex
)
mutex
)
->
critsect
)
mutex_real_init
(
mutex
);
EnterCriticalSection
(((
wine_mutex
)
mutex
)
->
critsect
);
return
0
;
}
strong_alias
(
__pthread_mutex_lock
,
pthread_mutex_lock
);
int
__pthread_mutex_trylock
(
pthread_mutex_t
*
mutex
)
{
if
(
!
SystemHeap
)
return
0
;
if
(
!
((
wine_mutex
)
mutex
)
->
critsect
)
mutex_real_init
(
mutex
);
if
(
!
TryEnterCriticalSection
(((
wine_mutex
)
mutex
)
->
critsect
))
{
errno
=
EBUSY
;
return
-
1
;
}
return
0
;
}
strong_alias
(
__pthread_mutex_trylock
,
pthread_mutex_trylock
);
int
__pthread_mutex_unlock
(
pthread_mutex_t
*
mutex
)
{
if
(
!
((
wine_mutex
)
mutex
)
->
critsect
)
return
0
;
LeaveCriticalSection
(((
wine_mutex
)
mutex
)
->
critsect
);
return
0
;
}
strong_alias
(
__pthread_mutex_unlock
,
pthread_mutex_unlock
);
int
__pthread_mutex_destroy
(
pthread_mutex_t
*
mutex
)
{
if
(
!
((
wine_mutex
)
mutex
)
->
critsect
)
return
0
;
if
(((
wine_mutex
)
mutex
)
->
critsect
->
RecursionCount
)
{
#if 0 /* there seems to be a bug in libc6 that makes this a bad idea */
return EBUSY;
#else
while
(((
wine_mutex
)
mutex
)
->
critsect
->
RecursionCount
)
LeaveCriticalSection
(((
wine_mutex
)
mutex
)
->
critsect
);
#endif
}
DeleteCriticalSection
(((
wine_mutex
)
mutex
)
->
critsect
);
HeapFree
(
SystemHeap
,
0
,
((
wine_mutex
)
mutex
)
->
critsect
);
return
0
;
}
strong_alias
(
__pthread_mutex_destroy
,
pthread_mutex_destroy
);
int
__pthread_atfork
(
void
(
*
prepare
)(
void
),
void
(
*
parent
)(
void
),
void
(
*
child
)(
void
))
{
/* are we going to fork? nah */
return
0
;
}
strong_alias
(
__pthread_atfork
,
pthread_atfork
);
int
__pthread_mutexattr_init
(
pthread_mutexattr_t
*
attr
)
{
return
0
;
}
strong_alias
(
__pthread_mutexattr_init
,
pthread_mutexattr_init
);
int
__pthread_mutexattr_destroy
(
pthread_mutexattr_t
*
attr
)
{
return
0
;
}
strong_alias
(
__pthread_mutexattr_destroy
,
pthread_mutexattr_destroy
);
int
__pthread_mutexattr_setkind_np
(
pthread_mutexattr_t
*
attr
,
int
kind
)
{
return
0
;
}
strong_alias
(
__pthread_mutexattr_setkind_np
,
pthread_mutexattr_setkind_np
);
int
__pthread_mutexattr_getkind_np
(
pthread_mutexattr_t
*
attr
,
int
*
kind
)
{
*
kind
=
PTHREAD_MUTEX_RECURSIVE_NP
;
return
0
;
}
strong_alias
(
__pthread_mutexattr_getkind_np
,
pthread_mutexattr_getkind_np
);
int
__pthread_mutexattr_settype
(
pthread_mutexattr_t
*
attr
,
int
kind
)
{
return
0
;
}
strong_alias
(
__pthread_mutexattr_settype
,
pthread_mutexattr_settype
);
int
__pthread_mutexattr_gettype
(
pthread_mutexattr_t
*
attr
,
int
*
kind
)
{
*
kind
=
PTHREAD_MUTEX_RECURSIVE_NP
;
return
0
;
}
strong_alias
(
__pthread_mutexattr_gettype
,
pthread_mutexattr_gettype
);
int
__pthread_key_create
(
pthread_key_t
*
key
,
void
(
*
destr_function
)(
void
*
))
{
static
pthread_key_t
keycnt
=
FIRST_KEY
;
EnterCriticalSection
(
&
init_sect
);
*
key
=
keycnt
++
;
LeaveCriticalSection
(
&
init_sect
);
return
0
;
}
strong_alias
(
__pthread_key_create
,
pthread_key_create
);
int
__pthread_key_delete
(
pthread_key_t
key
)
{
return
0
;
}
strong_alias
(
__pthread_key_delete
,
pthread_key_delete
);
int
__pthread_setspecific
(
pthread_key_t
key
,
const
void
*
pointer
)
{
TEB
*
teb
=
NtCurrentTeb
();
if
(
!
teb
->
pthread_data
)
{
teb
->
pthread_data
=
calloc
(
MAX_KEYS
,
sizeof
(
key_data
));
}
((
key_data
*
)(
teb
->
pthread_data
))[
key
]
=
pointer
;
return
0
;
}
strong_alias
(
__pthread_setspecific
,
pthread_setspecific
);
void
*
__pthread_getspecific
(
pthread_key_t
key
)
{
TEB
*
teb
=
NtCurrentTeb
();
if
(
!
teb
)
return
NULL
;
if
(
!
teb
->
pthread_data
)
return
NULL
;
return
(
void
*
)(((
key_data
*
)(
teb
->
pthread_data
))[
key
]);
}
strong_alias
(
__pthread_getspecific
,
pthread_getspecific
);
void
_pthread_cleanup_push
(
struct
_pthread_cleanup_buffer
*
buffer
,
void
(
*
routine
)(
void
*
),
void
*
arg
)
{
((
wine_cleanup
)
buffer
)
->
routine
=
routine
;
((
wine_cleanup
)
buffer
)
->
arg
=
arg
;
}
void
_pthread_cleanup_pop
(
struct
_pthread_cleanup_buffer
*
buffer
,
int
execute
)
{
if
(
execute
)
(
*
(((
wine_cleanup
)
buffer
)
->
routine
))(((
wine_cleanup
)
buffer
)
->
arg
);
}
void
_pthread_cleanup_push_defer
(
struct
_pthread_cleanup_buffer
*
buffer
,
void
(
*
routine
)(
void
*
),
void
*
arg
)
{
_pthread_cleanup_push
(
buffer
,
routine
,
arg
);
}
void
_pthread_cleanup_pop_restore
(
struct
_pthread_cleanup_buffer
*
buffer
,
int
execute
)
{
_pthread_cleanup_pop
(
buffer
,
execute
);
}
pthread_t
pthread_self
(
void
)
{
return
(
pthread_t
)
GetCurrentThreadId
();
}
int
pthread_equal
(
pthread_t
thread1
,
pthread_t
thread2
)
{
return
(
DWORD
)
thread1
==
(
DWORD
)
thread2
;
}
int
pthread_setcanceltype
(
int
type
,
int
*
oldtype
)
{
if
(
oldtype
)
*
oldtype
=
PTHREAD_CANCEL_ASYNCHRONOUS
;
return
0
;
}
#endif
/* __GLIBC__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment