Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-fonts
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
Aleksandr Isakov
wine-fonts
Commits
1d38539b
Commit
1d38539b
authored
Jul 06, 2020
by
Zebediah Figura
Committed by
Vitaly Lipatov
Jul 30, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Create eventfd-based objects for semaphores.
parent
3297b7ac
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
316 additions
and
2 deletions
+316
-2
Makefile.in
dlls/ntdll/Makefile.in
+1
-0
esync.c
dlls/ntdll/unix/esync.c
+271
-0
esync.h
dlls/ntdll/unix/esync.h
+35
-0
loader.c
dlls/ntdll/unix/loader.c
+2
-0
server.c
dlls/ntdll/unix/server.c
+2
-2
sync.c
dlls/ntdll/unix/sync.c
+4
-0
esync.c
server/esync.c
+1
-0
No files found.
dlls/ntdll/Makefile.in
View file @
1d38539b
...
...
@@ -46,6 +46,7 @@ C_SRCS = \
unix/cdrom.c
\
unix/debug.c
\
unix/env.c
\
unix/esync.c
\
unix/file.c
\
unix/loader.c
\
unix/loadorder.c
\
...
...
dlls/ntdll/unix/esync.c
0 → 100644
View file @
1d38539b
/*
* eventfd-based synchronization objects
*
* Copyright (C) 2018 Zebediah Figura
*
* 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.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#if 0
#pragma makedep unix
#endif
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/mman.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#define NONAMELESSUNION
#include "windef.h"
#include "winternl.h"
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
#include "esync.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
esync
);
int
do_esync
(
void
)
{
#ifdef HAVE_SYS_EVENTFD_H
static
int
do_esync_cached
=
-
1
;
if
(
do_esync_cached
==
-
1
)
do_esync_cached
=
getenv
(
"WINEESYNC"
)
&&
atoi
(
getenv
(
"WINEESYNC"
));
return
do_esync_cached
;
#else
static
int
once
;
if
(
!
once
++
)
FIXME
(
"eventfd not supported on this platform.
\n
"
);
return
0
;
#endif
}
struct
esync
{
enum
esync_type
type
;
int
fd
;
void
*
shm
;
};
struct
semaphore
{
int
max
;
int
count
;
};
C_ASSERT
(
sizeof
(
struct
semaphore
)
==
8
);
static
char
shm_name
[
29
];
static
int
shm_fd
;
static
void
**
shm_addrs
;
static
int
shm_addrs_size
;
/* length of the allocated shm_addrs array */
static
long
pagesize
;
static
pthread_mutex_t
shm_addrs_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
static
void
*
get_shm
(
unsigned
int
idx
)
{
int
entry
=
(
idx
*
8
)
/
pagesize
;
int
offset
=
(
idx
*
8
)
%
pagesize
;
void
*
ret
;
pthread_mutex_lock
(
&
shm_addrs_mutex
);
if
(
entry
>=
shm_addrs_size
)
{
int
new_size
=
max
(
shm_addrs_size
*
2
,
entry
+
1
);
if
(
!
(
shm_addrs
=
realloc
(
shm_addrs
,
new_size
*
sizeof
(
shm_addrs
[
0
])
)))
ERR
(
"Failed to grow shm_addrs array to size %d.
\n
"
,
shm_addrs_size
);
memset
(
shm_addrs
+
shm_addrs_size
,
0
,
(
new_size
-
shm_addrs_size
)
*
sizeof
(
shm_addrs
[
0
])
);
shm_addrs_size
=
new_size
;
}
if
(
!
shm_addrs
[
entry
])
{
void
*
addr
=
mmap
(
NULL
,
pagesize
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
shm_fd
,
entry
*
pagesize
);
if
(
addr
==
(
void
*
)
-
1
)
ERR
(
"Failed to map page %d (offset %#lx).
\n
"
,
entry
,
entry
*
pagesize
);
TRACE
(
"Mapping page %d at %p.
\n
"
,
entry
,
addr
);
if
(
InterlockedCompareExchangePointer
(
&
shm_addrs
[
entry
],
addr
,
0
))
munmap
(
addr
,
pagesize
);
/* someone beat us to it */
}
ret
=
(
void
*
)((
unsigned
long
)
shm_addrs
[
entry
]
+
offset
);
pthread_mutex_unlock
(
&
shm_addrs_mutex
);
return
ret
;
}
/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
* This is copied and adapted from the fd cache code. */
#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync))
#define ESYNC_LIST_ENTRIES 256
static
struct
esync
*
esync_list
[
ESYNC_LIST_ENTRIES
];
static
struct
esync
esync_list_initial_block
[
ESYNC_LIST_BLOCK_SIZE
];
static
inline
UINT_PTR
handle_to_index
(
HANDLE
handle
,
UINT_PTR
*
entry
)
{
UINT_PTR
idx
=
(((
UINT_PTR
)
handle
)
>>
2
)
-
1
;
*
entry
=
idx
/
ESYNC_LIST_BLOCK_SIZE
;
return
idx
%
ESYNC_LIST_BLOCK_SIZE
;
}
static
struct
esync
*
add_to_list
(
HANDLE
handle
,
enum
esync_type
type
,
int
fd
,
void
*
shm
)
{
UINT_PTR
entry
,
idx
=
handle_to_index
(
handle
,
&
entry
);
if
(
entry
>=
ESYNC_LIST_ENTRIES
)
{
FIXME
(
"too many allocated handles, not caching %p
\n
"
,
handle
);
return
FALSE
;
}
if
(
!
esync_list
[
entry
])
/* do we need to allocate a new block of entries? */
{
if
(
!
entry
)
esync_list
[
0
]
=
esync_list_initial_block
;
else
{
void
*
ptr
=
anon_mmap_alloc
(
ESYNC_LIST_BLOCK_SIZE
*
sizeof
(
struct
esync
),
PROT_READ
|
PROT_WRITE
);
if
(
ptr
==
MAP_FAILED
)
return
FALSE
;
esync_list
[
entry
]
=
ptr
;
}
}
if
(
!
InterlockedCompareExchange
(
(
int
*
)
&
esync_list
[
entry
][
idx
].
type
,
type
,
0
))
{
esync_list
[
entry
][
idx
].
fd
=
fd
;
esync_list
[
entry
][
idx
].
shm
=
shm
;
}
return
&
esync_list
[
entry
][
idx
];
}
static
NTSTATUS
create_esync
(
enum
esync_type
type
,
HANDLE
*
handle
,
ACCESS_MASK
access
,
const
OBJECT_ATTRIBUTES
*
attr
,
int
initval
,
int
max
)
{
NTSTATUS
ret
;
data_size_t
len
;
struct
object_attributes
*
objattr
;
obj_handle_t
fd_handle
;
unsigned
int
shm_idx
;
sigset_t
sigset
;
int
fd
;
if
((
ret
=
alloc_object_attributes
(
attr
,
&
objattr
,
&
len
)))
return
ret
;
/* We have to synchronize on the fd cache CS so that our calls to
* receive_fd don't race with theirs. */
server_enter_uninterrupted_section
(
&
fd_cache_mutex
,
&
sigset
);
SERVER_START_REQ
(
create_esync
)
{
req
->
access
=
access
;
req
->
initval
=
initval
;
req
->
type
=
type
;
req
->
max
=
max
;
wine_server_add_data
(
req
,
objattr
,
len
);
ret
=
wine_server_call
(
req
);
if
(
!
ret
||
ret
==
STATUS_OBJECT_NAME_EXISTS
)
{
*
handle
=
wine_server_ptr_handle
(
reply
->
handle
);
type
=
reply
->
type
;
shm_idx
=
reply
->
shm_idx
;
fd
=
receive_fd
(
&
fd_handle
);
assert
(
wine_server_ptr_handle
(
fd_handle
)
==
*
handle
);
}
}
SERVER_END_REQ
;
server_leave_uninterrupted_section
(
&
fd_cache_mutex
,
&
sigset
);
if
(
!
ret
||
ret
==
STATUS_OBJECT_NAME_EXISTS
)
{
add_to_list
(
*
handle
,
type
,
fd
,
shm_idx
?
get_shm
(
shm_idx
)
:
0
);
TRACE
(
"-> handle %p, fd %d.
\n
"
,
*
handle
,
fd
);
}
free
(
objattr
);
return
ret
;
}
extern
NTSTATUS
esync_create_semaphore
(
HANDLE
*
handle
,
ACCESS_MASK
access
,
const
OBJECT_ATTRIBUTES
*
attr
,
LONG
initial
,
LONG
max
)
{
TRACE
(
"name %s, initial %d, max %d.
\n
"
,
attr
?
debugstr_us
(
attr
->
ObjectName
)
:
"<no name>"
,
initial
,
max
);
return
create_esync
(
ESYNC_SEMAPHORE
,
handle
,
access
,
attr
,
initial
,
max
);
}
void
esync_init
(
void
)
{
struct
stat
st
;
if
(
!
do_esync
())
{
/* make sure the server isn't running with WINEESYNC */
HANDLE
handle
;
NTSTATUS
ret
;
ret
=
create_esync
(
0
,
&
handle
,
0
,
NULL
,
0
,
0
);
if
(
ret
!=
STATUS_NOT_IMPLEMENTED
)
{
ERR
(
"Server is running with WINEESYNC but this process is not, please enable WINEESYNC or restart wineserver.
\n
"
);
exit
(
1
);
}
return
;
}
if
(
stat
(
config_dir
,
&
st
)
==
-
1
)
ERR
(
"Cannot stat %s
\n
"
,
config_dir
);
if
(
st
.
st_ino
!=
(
unsigned
long
)
st
.
st_ino
)
sprintf
(
shm_name
,
"/wine-%lx%08lx-esync"
,
(
unsigned
long
)((
unsigned
long
long
)
st
.
st_ino
>>
32
),
(
unsigned
long
)
st
.
st_ino
);
else
sprintf
(
shm_name
,
"/wine-%lx-esync"
,
(
unsigned
long
)
st
.
st_ino
);
if
((
shm_fd
=
shm_open
(
shm_name
,
O_RDWR
,
0644
))
==
-
1
)
{
/* probably the server isn't running with WINEESYNC, tell the user and bail */
if
(
errno
==
ENOENT
)
ERR
(
"Failed to open esync shared memory file; make sure no stale wineserver instances are running without WINEESYNC.
\n
"
);
else
ERR
(
"Failed to initialize shared memory: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
pagesize
=
sysconf
(
_SC_PAGESIZE
);
shm_addrs
=
calloc
(
128
,
sizeof
(
shm_addrs
[
0
])
);
shm_addrs_size
=
128
;
}
dlls/ntdll/unix/esync.h
0 → 100644
View file @
1d38539b
/*
* eventfd-based synchronization objects
*
* Copyright (C) 2018 Zebediah Figura
*
* 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.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
extern
int
do_esync
(
void
)
DECLSPEC_HIDDEN
;
extern
void
esync_init
(
void
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
esync_create_semaphore
(
HANDLE
*
handle
,
ACCESS_MASK
access
,
const
OBJECT_ATTRIBUTES
*
attr
,
LONG
initial
,
LONG
max
)
DECLSPEC_HIDDEN
;
/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
* don't race with theirs. It looks weird, I know.
*
* If we weren't trying to avoid touching the code I'd rename the mutex to
* "server_fd_mutex" or something similar. */
extern
pthread_mutex_t
fd_cache_mutex
;
extern
int
receive_fd
(
obj_handle_t
*
handle
)
DECLSPEC_HIDDEN
;
dlls/ntdll/unix/loader.c
View file @
1d38539b
...
...
@@ -89,6 +89,7 @@
#include "winioctl.h"
#include "winternl.h"
#include "unix_private.h"
#include "esync.h"
#include "wine/list.h"
#include "wine/debug.h"
...
...
@@ -2160,6 +2161,7 @@ static void start_main_thread(void)
signal_init_thread
(
teb
);
dbg_init
();
startup_info_size
=
server_init_process
();
esync_init
();
virtual_map_user_shared_data
();
init_cpu_info
();
init_files
();
...
...
dlls/ntdll/unix/server.c
View file @
1d38539b
...
...
@@ -106,7 +106,7 @@ sigset_t server_block_set; /* signals to block during server calls */
static
int
fd_socket
=
-
1
;
/* socket to exchange file descriptors with the server */
static
int
initial_cwd
=
-
1
;
static
pid_t
server_pid
;
static
pthread_mutex_t
fd_cache_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
pthread_mutex_t
fd_cache_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
/* atomically exchange a 64-bit value */
static
inline
LONG64
interlocked_xchg64
(
LONG64
*
dest
,
LONG64
val
)
...
...
@@ -807,7 +807,7 @@ void wine_server_send_fd( int fd )
*
* Receive a file descriptor passed from the server.
*/
static
int
receive_fd
(
obj_handle_t
*
handle
)
int
receive_fd
(
obj_handle_t
*
handle
)
{
struct
iovec
vec
;
struct
msghdr
msghdr
;
...
...
dlls/ntdll/unix/sync.c
View file @
1d38539b
...
...
@@ -64,6 +64,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
#include "esync.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
sync
);
...
...
@@ -273,6 +274,9 @@ NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJ
if
(
max
<=
0
||
initial
<
0
||
initial
>
max
)
return
STATUS_INVALID_PARAMETER
;
if
((
ret
=
alloc_object_attributes
(
attr
,
&
objattr
,
&
len
)))
return
ret
;
if
(
do_esync
())
return
esync_create_semaphore
(
handle
,
access
,
attr
,
initial
,
max
);
SERVER_START_REQ
(
create_semaphore
)
{
req
->
access
=
access
;
...
...
server/esync.c
View file @
1d38539b
...
...
@@ -41,6 +41,7 @@
#include "handle.h"
#include "request.h"
#include "file.h"
#include "esync.h"
int
do_esync
(
void
)
{
...
...
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