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
803cee46
Commit
803cee46
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: Implement NtWaitForMultipleObjects().
parent
282c89a6
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
180 additions
and
0 deletions
+180
-0
esync.c
dlls/ntdll/unix/esync.c
+170
-0
esync.h
dlls/ntdll/unix/esync.h
+3
-0
sync.c
dlls/ntdll/unix/sync.c
+7
-0
No files found.
dlls/ntdll/unix/esync.c
View file @
803cee46
...
...
@@ -22,6 +22,8 @@
#pragma makedep unix
#endif
#define _GNU_SOURCE
#include "config.h"
#include <assert.h>
...
...
@@ -34,6 +36,12 @@
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#endif
#include <sys/types.h>
#include <unistd.h>
...
...
@@ -287,6 +295,168 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
return
STATUS_SUCCESS
;
}
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
static
LONGLONG
update_timeout
(
ULONGLONG
end
)
{
LARGE_INTEGER
now
;
LONGLONG
timeleft
;
NtQuerySystemTime
(
&
now
);
timeleft
=
end
-
now
.
QuadPart
;
if
(
timeleft
<
0
)
timeleft
=
0
;
return
timeleft
;
}
static
int
do_poll
(
struct
pollfd
*
fds
,
nfds_t
nfds
,
ULONGLONG
*
end
)
{
if
(
end
)
{
LONGLONG
timeleft
=
update_timeout
(
*
end
);
#ifdef HAVE_PPOLL
/* We use ppoll() if available since the time granularity is better. */
struct
timespec
tmo_p
;
tmo_p
.
tv_sec
=
timeleft
/
(
ULONGLONG
)
TICKSPERSEC
;
tmo_p
.
tv_nsec
=
(
timeleft
%
TICKSPERSEC
)
*
100
;
return
ppoll
(
fds
,
nfds
,
&
tmo_p
,
NULL
);
#else
return
poll
(
fds
,
nfds
,
timeleft
/
TICKSPERMSEC
);
#endif
}
else
return
poll
(
fds
,
nfds
,
-
1
);
}
static
void
update_grabbed_object
(
struct
esync
*
obj
)
{
if
(
obj
->
type
==
ESYNC_SEMAPHORE
)
{
struct
semaphore
*
semaphore
=
obj
->
shm
;
/* We don't have to worry about a race between this and read(); the
* fact that we were able to grab it at all means the count is nonzero,
* and if someone else grabbed it then the count must have been >= 2,
* etc. */
InterlockedExchangeAdd
(
&
semaphore
->
count
,
-
1
);
}
}
/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
* need to delegate to server_select(). */
NTSTATUS
esync_wait_objects
(
DWORD
count
,
const
HANDLE
*
handles
,
BOOLEAN
wait_any
,
BOOLEAN
alertable
,
const
LARGE_INTEGER
*
timeout
)
{
struct
esync
*
objs
[
MAXIMUM_WAIT_OBJECTS
];
struct
pollfd
fds
[
MAXIMUM_WAIT_OBJECTS
];
int
has_esync
=
0
,
has_server
=
0
;
LONGLONG
timeleft
;
LARGE_INTEGER
now
;
ULONGLONG
end
;
int
i
,
ret
;
NtQuerySystemTime
(
&
now
);
if
(
timeout
)
{
if
(
timeout
->
QuadPart
==
TIMEOUT_INFINITE
)
timeout
=
NULL
;
else
if
(
timeout
->
QuadPart
>=
0
)
end
=
timeout
->
QuadPart
;
else
end
=
now
.
QuadPart
-
timeout
->
QuadPart
;
}
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
((
objs
[
i
]
=
get_cached_object
(
handles
[
i
]
)))
has_esync
=
1
;
else
has_server
=
1
;
}
if
(
has_esync
&&
has_server
)
FIXME
(
"Can't wait on esync and server objects at the same time!
\n
"
);
else
if
(
has_server
)
return
STATUS_NOT_IMPLEMENTED
;
if
(
TRACE_ON
(
esync
))
{
TRACE
(
"Waiting for %s of %d handles:"
,
wait_any
?
"any"
:
"all"
,
count
);
for
(
i
=
0
;
i
<
count
;
i
++
)
TRACE
(
" %p"
,
handles
[
i
]);
if
(
!
timeout
)
TRACE
(
", timeout = INFINITE.
\n
"
);
else
{
timeleft
=
update_timeout
(
end
);
TRACE
(
", timeout = %ld.%07ld sec.
\n
"
,
(
long
)
timeleft
/
TICKSPERSEC
,
(
long
)
timeleft
%
TICKSPERSEC
);
}
}
if
(
wait_any
||
count
==
1
)
{
for
(
i
=
0
;
i
<
count
;
i
++
)
{
fds
[
i
].
fd
=
objs
[
i
]
?
objs
[
i
]
->
fd
:
-
1
;
fds
[
i
].
events
=
POLLIN
;
}
while
(
1
)
{
ret
=
do_poll
(
fds
,
count
,
timeout
?
&
end
:
NULL
);
if
(
ret
>
0
)
{
/* Find out which object triggered the wait. */
for
(
i
=
0
;
i
<
count
;
i
++
)
{
struct
esync
*
obj
=
objs
[
i
];
if
(
fds
[
i
].
revents
&
(
POLLERR
|
POLLHUP
|
POLLNVAL
))
{
ERR
(
"Polling on fd %d returned %#x.
\n
"
,
fds
[
i
].
fd
,
fds
[
i
].
revents
);
return
STATUS_INVALID_HANDLE
;
}
if
(
obj
)
{
int64_t
value
;
ssize_t
size
;
if
((
size
=
read
(
fds
[
i
].
fd
,
&
value
,
sizeof
(
value
)
))
==
sizeof
(
value
))
{
/* We found our object. */
TRACE
(
"Woken up by handle %p [%d].
\n
"
,
handles
[
i
],
i
);
update_grabbed_object
(
obj
);
return
i
;
}
}
}
/* If we got here, someone else stole (or reset, etc.) whatever
* we were waiting for. So keep waiting. */
NtQuerySystemTime
(
&
now
);
}
else
if
(
ret
==
0
)
{
TRACE
(
"Wait timed out.
\n
"
);
return
STATUS_TIMEOUT
;
}
else
{
ERR
(
"ppoll failed: %s
\n
"
,
strerror
(
errno
));
return
errno_to_status
(
errno
);
}
}
}
else
{
FIXME
(
"Wait-all not implemented.
\n
"
);
return
STATUS_NOT_IMPLEMENTED
;
}
}
void
esync_init
(
void
)
{
struct
stat
st
;
...
...
dlls/ntdll/unix/esync.h
View file @
803cee46
...
...
@@ -26,6 +26,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const
OBJECT_ATTRIBUTES
*
attr
,
LONG
initial
,
LONG
max
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
esync_release_semaphore
(
HANDLE
handle
,
ULONG
count
,
ULONG
*
prev
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
esync_wait_objects
(
DWORD
count
,
const
HANDLE
*
handles
,
BOOLEAN
wait_any
,
BOOLEAN
alertable
,
const
LARGE_INTEGER
*
timeout
)
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.
...
...
dlls/ntdll/unix/sync.c
View file @
803cee46
...
...
@@ -1429,6 +1429,13 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO
if
(
!
count
||
count
>
MAXIMUM_WAIT_OBJECTS
)
return
STATUS_INVALID_PARAMETER_1
;
if
(
do_esync
())
{
NTSTATUS
ret
=
esync_wait_objects
(
count
,
handles
,
wait_any
,
alertable
,
timeout
);
if
(
ret
!=
STATUS_NOT_IMPLEMENTED
)
return
ret
;
}
if
(
alertable
)
flags
|=
SELECT_ALERTABLE
;
select_op
.
wait
.
op
=
wait_any
?
SELECT_WAIT
:
SELECT_WAIT_ALL
;
for
(
i
=
0
;
i
<
count
;
i
++
)
select_op
.
wait
.
handles
[
i
]
=
wine_server_obj_handle
(
handles
[
i
]
);
...
...
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