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
3297b7ac
Commit
3297b7ac
authored
Jun 07, 2018
by
Zebediah Figura
Committed by
Vitaly Lipatov
Jul 30, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
server: Create server objects for eventfd-based synchronization objects.
parent
82673ab4
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
436 additions
and
3 deletions
+436
-3
server_protocol.h
include/wine/server_protocol.h
+35
-2
Makefile.in
server/Makefile.in
+1
-0
esync.c
server/esync.c
+318
-0
esync.h
server/esync.h
+24
-0
main.c
server/main.c
+4
-0
protocol.def
server/protocol.def
+24
-1
request.h
server/request.h
+11
-0
trace.c
server/trace.c
+19
-0
No files found.
include/wine/server_protocol.h
View file @
3297b7ac
...
...
@@ -5460,7 +5460,6 @@ struct resume_process_reply
};
struct
get_next_thread_request
{
struct
request_header
__header
;
...
...
@@ -5477,6 +5476,37 @@ struct get_next_thread_reply
char
__pad_12
[
4
];
};
enum
esync_type
{
ESYNC_SEMAPHORE
=
1
,
ESYNC_AUTO_EVENT
,
ESYNC_MANUAL_EVENT
,
ESYNC_MUTEX
,
ESYNC_AUTO_SERVER
,
ESYNC_MANUAL_SERVER
,
ESYNC_QUEUE
,
};
struct
create_esync_request
{
struct
request_header
__header
;
unsigned
int
access
;
int
initval
;
int
type
;
int
max
;
/* VARARG(objattr,object_attributes); */
char
__pad_28
[
4
];
};
struct
create_esync_reply
{
struct
reply_header
__header
;
obj_handle_t
handle
;
int
type
;
unsigned
int
shm_idx
;
char
__pad_20
[
4
];
};
enum
request
{
...
...
@@ -5757,6 +5787,7 @@ enum request
REQ_suspend_process
,
REQ_resume_process
,
REQ_get_next_thread
,
REQ_create_esync
,
REQ_NB_REQUESTS
};
...
...
@@ -6041,6 +6072,7 @@ union generic_request
struct
suspend_process_request
suspend_process_request
;
struct
resume_process_request
resume_process_request
;
struct
get_next_thread_request
get_next_thread_request
;
struct
create_esync_request
create_esync_request
;
};
union
generic_reply
{
...
...
@@ -6323,11 +6355,12 @@ union generic_reply
struct
suspend_process_reply
suspend_process_reply
;
struct
resume_process_reply
resume_process_reply
;
struct
get_next_thread_reply
get_next_thread_reply
;
struct
create_esync_reply
create_esync_reply
;
};
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 75
7
#define SERVER_PROTOCOL_VERSION 75
8
/* ### protocol_version end ### */
...
...
server/Makefile.in
View file @
3297b7ac
...
...
@@ -11,6 +11,7 @@ C_SRCS = \
debugger.c
\
device.c
\
directory.c
\
esync.c
\
event.c
\
fd.c
\
file.c
\
...
...
server/esync.c
0 → 100644
View file @
3297b7ac
/*
* 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
*/
#include "config.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef HAVE_SYS_EVENTFD_H
# include <sys/eventfd.h>
#endif
#include <sys/mman.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <unistd.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winternl.h"
#include "handle.h"
#include "request.h"
#include "file.h"
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
return
0
;
#endif
}
static
char
shm_name
[
29
];
static
int
shm_fd
;
static
off_t
shm_size
;
static
void
**
shm_addrs
;
static
int
shm_addrs_size
;
/* length of the allocated shm_addrs array */
static
long
pagesize
;
static
void
shm_cleanup
(
void
)
{
close
(
shm_fd
);
if
(
shm_unlink
(
shm_name
)
==
-
1
)
perror
(
"shm_unlink"
);
}
void
esync_init
(
void
)
{
struct
stat
st
;
if
(
fstat
(
config_dir_fd
,
&
st
)
==
-
1
)
fatal_error
(
"cannot stat config dir
\n
"
);
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
);
shm_unlink
(
shm_name
);
shm_fd
=
shm_open
(
shm_name
,
O_RDWR
|
O_CREAT
|
O_EXCL
,
0644
);
if
(
shm_fd
==
-
1
)
perror
(
"shm_open"
);
pagesize
=
sysconf
(
_SC_PAGESIZE
);
shm_addrs
=
calloc
(
128
,
sizeof
(
shm_addrs
[
0
])
);
shm_addrs_size
=
128
;
shm_size
=
pagesize
;
if
(
ftruncate
(
shm_fd
,
shm_size
)
==
-
1
)
perror
(
"ftruncate"
);
fprintf
(
stderr
,
"esync: up and running.
\n
"
);
atexit
(
shm_cleanup
);
}
struct
esync
{
struct
object
obj
;
/* object header */
int
fd
;
/* eventfd file descriptor */
enum
esync_type
type
;
unsigned
int
shm_idx
;
/* index into the shared memory section */
};
static
void
esync_dump
(
struct
object
*
obj
,
int
verbose
);
static
void
esync_destroy
(
struct
object
*
obj
);
static
const
struct
object_ops
esync_ops
=
{
sizeof
(
struct
esync
),
/* size */
&
no_type
,
/* type */
esync_dump
,
/* dump */
no_add_queue
,
/* add_queue */
NULL
,
/* remove_queue */
NULL
,
/* signaled */
NULL
,
/* satisfied */
no_signal
,
/* signal */
no_get_fd
,
/* get_fd */
no_map_access
,
/* map_access */
default_get_sd
,
/* get_sd */
default_set_sd
,
/* set_sd */
default_get_full_name
,
/* get_full_name */
no_lookup_name
,
/* lookup_name */
directory_link_name
,
/* link_name */
default_unlink_name
,
/* unlink_name */
no_open_file
,
/* open_file */
no_kernel_obj_list
,
/* get_kernel_obj_list */
no_close_handle
,
/* close_handle */
esync_destroy
/* destroy */
};
static
void
esync_dump
(
struct
object
*
obj
,
int
verbose
)
{
struct
esync
*
esync
=
(
struct
esync
*
)
obj
;
assert
(
obj
->
ops
==
&
esync_ops
);
fprintf
(
stderr
,
"esync fd=%d
\n
"
,
esync
->
fd
);
}
static
void
esync_destroy
(
struct
object
*
obj
)
{
struct
esync
*
esync
=
(
struct
esync
*
)
obj
;
close
(
esync
->
fd
);
}
static
int
type_matches
(
enum
esync_type
type1
,
enum
esync_type
type2
)
{
return
(
type1
==
type2
)
||
((
type1
==
ESYNC_AUTO_EVENT
||
type1
==
ESYNC_MANUAL_EVENT
)
&&
(
type2
==
ESYNC_AUTO_EVENT
||
type2
==
ESYNC_MANUAL_EVENT
));
}
static
void
*
get_shm
(
unsigned
int
idx
)
{
int
entry
=
(
idx
*
8
)
/
pagesize
;
int
offset
=
(
idx
*
8
)
%
pagesize
;
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
])
)))
fprintf
(
stderr
,
"esync: couldn't expand shm_addrs array to size %d
\n
"
,
entry
+
1
);
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
)
{
fprintf
(
stderr
,
"esync: failed to map page %d (offset %#lx): "
,
entry
,
entry
*
pagesize
);
perror
(
"mmap"
);
}
if
(
debug_level
)
fprintf
(
stderr
,
"esync: Mapping page %d at %p.
\n
"
,
entry
,
addr
);
if
(
__sync_val_compare_and_swap
(
&
shm_addrs
[
entry
],
0
,
addr
))
munmap
(
addr
,
pagesize
);
/* someone beat us to it */
}
return
(
void
*
)((
unsigned
long
)
shm_addrs
[
entry
]
+
offset
);
}
struct
semaphore
{
int
max
;
int
count
;
};
C_ASSERT
(
sizeof
(
struct
semaphore
)
==
8
);
struct
esync
*
create_esync
(
struct
object
*
root
,
const
struct
unicode_str
*
name
,
unsigned
int
attr
,
int
initval
,
int
max
,
enum
esync_type
type
,
const
struct
security_descriptor
*
sd
)
{
#ifdef HAVE_SYS_EVENTFD_H
struct
esync
*
esync
;
if
((
esync
=
create_named_object
(
root
,
&
esync_ops
,
name
,
attr
,
sd
)))
{
if
(
get_error
()
!=
STATUS_OBJECT_NAME_EXISTS
)
{
int
flags
=
EFD_CLOEXEC
|
EFD_NONBLOCK
;
if
(
type
==
ESYNC_SEMAPHORE
)
flags
|=
EFD_SEMAPHORE
;
/* initialize it if it didn't already exist */
esync
->
fd
=
eventfd
(
initval
,
flags
);
if
(
esync
->
fd
==
-
1
)
{
perror
(
"eventfd"
);
file_set_error
();
release_object
(
esync
);
return
NULL
;
}
esync
->
type
=
type
;
/* Use the fd as index, since that'll be unique across all
* processes, but should hopefully end up also allowing reuse. */
esync
->
shm_idx
=
esync
->
fd
+
1
;
/* we keep index 0 reserved */
while
(
esync
->
shm_idx
*
8
>=
shm_size
)
{
/* Better expand the shm section. */
shm_size
+=
pagesize
;
if
(
ftruncate
(
shm_fd
,
shm_size
)
==
-
1
)
{
fprintf
(
stderr
,
"esync: couldn't expand %s to size %ld: "
,
shm_name
,
(
long
)
shm_size
);
perror
(
"ftruncate"
);
}
}
/* Initialize the shared memory portion. We want to do this on the
* server side to avoid a potential though unlikely race whereby
* the same object is opened and used between the time it's created
* and the time its shared memory portion is initialized. */
switch
(
type
)
{
case
ESYNC_SEMAPHORE
:
{
struct
semaphore
*
semaphore
=
get_shm
(
esync
->
shm_idx
);
semaphore
->
max
=
max
;
semaphore
->
count
=
initval
;
break
;
}
default:
assert
(
0
);
}
}
else
{
/* validate the type */
if
(
!
type_matches
(
type
,
esync
->
type
))
{
release_object
(
&
esync
->
obj
);
set_error
(
STATUS_OBJECT_TYPE_MISMATCH
);
return
NULL
;
}
}
}
return
esync
;
#else
/* FIXME: Provide a fallback implementation using pipe(). */
set_error
(
STATUS_NOT_IMPLEMENTED
);
return
NULL
;
#endif
}
DECL_HANDLER
(
create_esync
)
{
struct
esync
*
esync
;
struct
unicode_str
name
;
struct
object
*
root
;
const
struct
security_descriptor
*
sd
;
const
struct
object_attributes
*
objattr
=
get_req_object_attributes
(
&
sd
,
&
name
,
&
root
);
if
(
!
do_esync
())
{
set_error
(
STATUS_NOT_IMPLEMENTED
);
return
;
}
if
(
!
req
->
type
)
{
set_error
(
STATUS_INVALID_PARAMETER
);
return
;
}
if
(
!
objattr
)
return
;
if
((
esync
=
create_esync
(
root
,
&
name
,
objattr
->
attributes
,
req
->
initval
,
req
->
max
,
req
->
type
,
sd
)))
{
if
(
get_error
()
==
STATUS_OBJECT_NAME_EXISTS
)
reply
->
handle
=
alloc_handle
(
current
->
process
,
esync
,
req
->
access
,
objattr
->
attributes
);
else
reply
->
handle
=
alloc_handle_no_access_check
(
current
->
process
,
esync
,
req
->
access
,
objattr
->
attributes
);
reply
->
type
=
esync
->
type
;
reply
->
shm_idx
=
esync
->
shm_idx
;
send_client_fd
(
current
->
process
,
esync
->
fd
,
reply
->
handle
);
release_object
(
esync
);
}
if
(
root
)
release_object
(
root
);
}
server/esync.h
0 → 100644
View file @
3297b7ac
/*
* 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
*/
#include <unistd.h>
extern
int
do_esync
(
void
);
void
esync_init
(
void
);
server/main.c
View file @
3297b7ac
...
...
@@ -34,6 +34,7 @@
#include "thread.h"
#include "request.h"
#include "unicode.h"
#include "esync.h"
/* command-line options */
int
debug_level
=
0
;
...
...
@@ -229,6 +230,9 @@ int main( int argc, char *argv[] )
sock_init
();
open_master_socket
();
if
(
do_esync
())
esync_init
();
if
(
debug_level
)
fprintf
(
stderr
,
"wineserver: starting (pid=%ld)
\n
"
,
(
long
)
getpid
()
);
set_current_time
();
init_scheduler
();
...
...
server/protocol.def
View file @
3297b7ac
...
...
@@ -3755,7 +3755,6 @@ struct handle_info
obj_handle_t handle; /* process handle */
@END
/* Iterate thread list for process */
@REQ(get_next_thread)
obj_handle_t process; /* process handle */
...
...
@@ -3766,3 +3765,27 @@ struct handle_info
@REPLY
obj_handle_t handle; /* next thread handle */
@END
enum esync_type
{
ESYNC_SEMAPHORE = 1,
ESYNC_AUTO_EVENT,
ESYNC_MANUAL_EVENT,
ESYNC_MUTEX,
ESYNC_AUTO_SERVER,
ESYNC_MANUAL_SERVER,
ESYNC_QUEUE,
};
/* Create a new eventfd-based synchronization object */
@REQ(create_esync)
unsigned int access; /* wanted access rights */
int initval; /* initial value */
int type; /* type of esync object */
int max; /* maximum count on a semaphore */
VARARG(objattr,object_attributes); /* object attributes */
@REPLY
obj_handle_t handle; /* handle to the object */
int type; /* actual type (may be different for events) */
unsigned int shm_idx;
@END
server/request.h
View file @
3297b7ac
...
...
@@ -396,6 +396,7 @@ DECL_HANDLER(terminate_job);
DECL_HANDLER
(
suspend_process
);
DECL_HANDLER
(
resume_process
);
DECL_HANDLER
(
get_next_thread
);
DECL_HANDLER
(
create_esync
);
#ifdef WANT_REQUEST_HANDLERS
...
...
@@ -679,6 +680,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_suspend_process
,
(
req_handler
)
req_resume_process
,
(
req_handler
)
req_get_next_thread
,
(
req_handler
)
req_create_esync
,
};
C_ASSERT
(
sizeof
(
abstime_t
)
==
8
);
...
...
@@ -2268,6 +2270,15 @@ C_ASSERT( FIELD_OFFSET(struct get_next_thread_request, flags) == 28 );
C_ASSERT
(
sizeof
(
struct
get_next_thread_request
)
==
32
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_next_thread_reply
,
handle
)
==
8
);
C_ASSERT
(
sizeof
(
struct
get_next_thread_reply
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
create_esync_request
,
access
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
create_esync_request
,
initval
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
create_esync_request
,
type
)
==
20
);
C_ASSERT
(
FIELD_OFFSET
(
struct
create_esync_request
,
max
)
==
24
);
C_ASSERT
(
sizeof
(
struct
create_esync_request
)
==
32
);
C_ASSERT
(
FIELD_OFFSET
(
struct
create_esync_reply
,
handle
)
==
8
);
C_ASSERT
(
FIELD_OFFSET
(
struct
create_esync_reply
,
type
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
create_esync_reply
,
shm_idx
)
==
16
);
C_ASSERT
(
sizeof
(
struct
create_esync_reply
)
==
24
);
#endif
/* WANT_REQUEST_HANDLERS */
...
...
server/trace.c
View file @
3297b7ac
...
...
@@ -4500,6 +4500,22 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req
fprintf
(
stderr
,
" handle=%04x"
,
req
->
handle
);
}
static
void
dump_create_esync_request
(
const
struct
create_esync_request
*
req
)
{
fprintf
(
stderr
,
" access=%08x"
,
req
->
access
);
fprintf
(
stderr
,
", initval=%d"
,
req
->
initval
);
fprintf
(
stderr
,
", type=%d"
,
req
->
type
);
fprintf
(
stderr
,
", max=%d"
,
req
->
max
);
dump_varargs_object_attributes
(
", objattr="
,
cur_size
);
}
static
void
dump_create_esync_reply
(
const
struct
create_esync_reply
*
req
)
{
fprintf
(
stderr
,
" handle=%04x"
,
req
->
handle
);
fprintf
(
stderr
,
", type=%d"
,
req
->
type
);
fprintf
(
stderr
,
", shm_idx=%08x"
,
req
->
shm_idx
);
}
static
const
dump_func
req_dumpers
[
REQ_NB_REQUESTS
]
=
{
(
dump_func
)
dump_new_process_request
,
(
dump_func
)
dump_get_new_process_info_request
,
...
...
@@ -4778,6 +4794,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_suspend_process_request
,
(
dump_func
)
dump_resume_process_request
,
(
dump_func
)
dump_get_next_thread_request
,
(
dump_func
)
dump_create_esync_request
,
};
static
const
dump_func
reply_dumpers
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -5058,6 +5075,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL
,
NULL
,
(
dump_func
)
dump_get_next_thread_reply
,
(
dump_func
)
dump_create_esync_reply
,
};
static
const
char
*
const
req_names
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -5338,6 +5356,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"suspend_process"
,
"resume_process"
,
"get_next_thread"
,
"create_esync"
,
};
static
const
struct
...
...
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