mirror of
https://github.com/reactos/wine.git
synced 2025-02-20 21:03:39 +00:00
Implemented NtSignalAndWaitForSingleObject.
This commit is contained in:
parent
684f111070
commit
f92fff66a2
@ -44,7 +44,7 @@ extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
|
||||
extern void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout );
|
||||
extern void NTDLL_from_server_timeout( LARGE_INTEGER *timeout, const abs_time_t *when );
|
||||
extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
|
||||
const LARGE_INTEGER *timeout );
|
||||
const LARGE_INTEGER *timeout, HANDLE signal_object );
|
||||
|
||||
/* init routines */
|
||||
extern BOOL SIGNAL_Init(void);
|
||||
|
@ -1156,7 +1156,7 @@ static HANDLER_DEF(usr1_handler)
|
||||
init_handler( HANDLER_CONTEXT );
|
||||
/* wait with 0 timeout, will only return once the thread is no longer suspended */
|
||||
timeout.QuadPart = 0;
|
||||
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout );
|
||||
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -701,7 +701,7 @@ static void call_apcs( BOOL alertable )
|
||||
* Implementation of NtWaitForMultipleObjects
|
||||
*/
|
||||
NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
|
||||
const LARGE_INTEGER *timeout )
|
||||
const LARGE_INTEGER *timeout, HANDLE signal_object )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
int cookie;
|
||||
@ -713,6 +713,7 @@ NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UIN
|
||||
{
|
||||
req->flags = flags;
|
||||
req->cookie = &cookie;
|
||||
req->signal = signal_object;
|
||||
NTDLL_get_server_timeout( &req->timeout, timeout );
|
||||
wine_server_add_data( req, handles, count * sizeof(HANDLE) );
|
||||
ret = wine_server_call( req );
|
||||
@ -722,6 +723,7 @@ NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UIN
|
||||
if (ret != STATUS_USER_APC) break;
|
||||
call_apcs( (flags & SELECT_ALERTABLE) != 0 );
|
||||
if (flags & SELECT_ALERTABLE) break;
|
||||
signal_object = 0; /* don't signal it multiple times */
|
||||
}
|
||||
|
||||
/* A test on Windows 2000 shows that Windows always yields during
|
||||
@ -748,7 +750,7 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles,
|
||||
|
||||
if (wait_all) flags |= SELECT_ALL;
|
||||
if (alertable) flags |= SELECT_ALERTABLE;
|
||||
return NTDLL_wait_for_multiple_objects( count, handles, flags, timeout );
|
||||
return NTDLL_wait_for_multiple_objects( count, handles, flags, timeout, 0 );
|
||||
}
|
||||
|
||||
|
||||
@ -761,6 +763,20 @@ NTSTATUS WINAPI NtWaitForSingleObject(HANDLE handle, BOOLEAN alertable, const LA
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* NtSignalAndWaitForSingleObject (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE hSignalObject, HANDLE hWaitObject,
|
||||
BOOLEAN alertable, const LARGE_INTEGER *timeout )
|
||||
{
|
||||
UINT flags = SELECT_INTERRUPTIBLE;
|
||||
|
||||
if (!hSignalObject) return STATUS_INVALID_HANDLE;
|
||||
if (alertable) flags |= SELECT_ALERTABLE;
|
||||
return NTDLL_wait_for_multiple_objects( 1, &hWaitObject, flags, timeout, hSignalObject );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* NtYieldExecution (NTDLL.@)
|
||||
*/
|
||||
@ -785,7 +801,7 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou
|
||||
{
|
||||
UINT flags = SELECT_INTERRUPTIBLE;
|
||||
if (alertable) flags |= SELECT_ALERTABLE;
|
||||
return NTDLL_wait_for_multiple_objects( 0, NULL, flags, timeout );
|
||||
return NTDLL_wait_for_multiple_objects( 0, NULL, flags, timeout, 0 );
|
||||
}
|
||||
|
||||
if (!timeout) /* sleep forever */
|
||||
@ -819,14 +835,3 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* NtSignalAndWaitForSingleObject (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE hSignalObject, HANDLE hWaitObject,
|
||||
BOOLEAN bAlertable, PLARGE_INTEGER Timeout )
|
||||
{
|
||||
FIXME("%p %p %d %p\n", hSignalObject, hWaitObject, bAlertable, Timeout);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -603,6 +603,7 @@ struct select_request
|
||||
struct request_header __header;
|
||||
int flags;
|
||||
void* cookie;
|
||||
obj_handle_t signal;
|
||||
abs_time_t timeout;
|
||||
/* VARARG(handles,handles); */
|
||||
};
|
||||
@ -3902,6 +3903,6 @@ union generic_reply
|
||||
struct set_mailslot_info_reply set_mailslot_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 170
|
||||
#define SERVER_PROTOCOL_VERSION 171
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
@ -1521,7 +1521,7 @@ NTSTATUS WINAPI NtSetSecurityObject(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCR
|
||||
NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER*,LARGE_INTEGER*);
|
||||
NTSTATUS WINAPI NtSetTimer(HANDLE, const LARGE_INTEGER*, PTIMERAPCROUTINE, PVOID, BOOLEAN, ULONG, BOOLEAN*);
|
||||
NTSTATUS WINAPI NtSetValueKey(HKEY,const UNICODE_STRING *,ULONG,ULONG,const void *,ULONG);
|
||||
NTSTATUS WINAPI NtSignalAndWaitForSingleObject(HANDLE,HANDLE,BOOLEAN,PLARGE_INTEGER);
|
||||
NTSTATUS WINAPI NtSignalAndWaitForSingleObject(HANDLE,HANDLE,BOOLEAN,const LARGE_INTEGER*);
|
||||
NTSTATUS WINAPI NtSuspendThread(HANDLE,PULONG);
|
||||
NTSTATUS WINAPI NtTerminateProcess(HANDLE,LONG);
|
||||
NTSTATUS WINAPI NtTerminateThread(HANDLE,LONG);
|
||||
|
@ -70,7 +70,8 @@ static const struct object_ops atom_table_ops =
|
||||
no_add_queue, /* add_queue */
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satified */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
atom_table_destroy /* destroy */
|
||||
};
|
||||
|
@ -71,6 +71,7 @@ static const struct object_ops change_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
change_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
change_destroy /* destroy */
|
||||
};
|
||||
|
@ -46,6 +46,7 @@ static const struct object_ops console_input_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
console_input_destroy /* destroy */
|
||||
};
|
||||
@ -70,6 +71,7 @@ static const struct object_ops console_input_events_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
console_input_events_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
console_input_events_destroy /* destroy */
|
||||
};
|
||||
@ -105,6 +107,7 @@ static const struct object_ops screen_buffer_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
screen_buffer_destroy /* destroy */
|
||||
};
|
||||
|
@ -72,6 +72,7 @@ static const struct object_ops debug_event_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
debug_event_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
debug_event_destroy /* destroy */
|
||||
};
|
||||
@ -88,6 +89,7 @@ static const struct object_ops debug_ctx_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
debug_ctx_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
debug_ctx_destroy /* destroy */
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ struct event
|
||||
static void event_dump( struct object *obj, int verbose );
|
||||
static int event_signaled( struct object *obj, struct thread *thread );
|
||||
static int event_satisfied( struct object *obj, struct thread *thread );
|
||||
static int event_signal( struct object *obj, unsigned int access);
|
||||
|
||||
static const struct object_ops event_ops =
|
||||
{
|
||||
@ -50,6 +51,7 @@ static const struct object_ops event_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
event_signaled, /* signaled */
|
||||
event_satisfied, /* satisfied */
|
||||
event_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
no_destroy /* destroy */
|
||||
};
|
||||
@ -123,6 +125,20 @@ static int event_satisfied( struct object *obj, struct thread *thread )
|
||||
return 0; /* Not abandoned */
|
||||
}
|
||||
|
||||
static int event_signal( struct object *obj, unsigned int access )
|
||||
{
|
||||
struct event *event = (struct event *)obj;
|
||||
assert( obj->ops == &event_ops );
|
||||
|
||||
if (!(access & EVENT_MODIFY_STATE))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return 0;
|
||||
}
|
||||
set_event( event );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create an event */
|
||||
DECL_HANDLER(create_event)
|
||||
{
|
||||
|
@ -159,6 +159,7 @@ static const struct object_ops fd_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
fd_destroy /* destroy */
|
||||
};
|
||||
@ -188,6 +189,7 @@ static const struct object_ops inode_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
inode_destroy /* destroy */
|
||||
};
|
||||
@ -218,6 +220,7 @@ static const struct object_ops file_lock_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
file_lock_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
no_destroy /* destroy */
|
||||
};
|
||||
|
@ -83,6 +83,7 @@ static const struct object_ops file_ops =
|
||||
default_fd_remove_queue, /* remove_queue */
|
||||
default_fd_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
file_get_fd, /* get_fd */
|
||||
file_destroy /* destroy */
|
||||
};
|
||||
|
@ -106,6 +106,7 @@ static const struct object_ops handle_table_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
handle_table_destroy /* destroy */
|
||||
};
|
||||
@ -385,6 +386,16 @@ struct object *get_handle_obj( struct process *process, obj_handle_t handle,
|
||||
return grab_object( obj );
|
||||
}
|
||||
|
||||
/* retrieve the access rights of a given handle */
|
||||
unsigned int get_handle_access( struct process *process, obj_handle_t handle )
|
||||
{
|
||||
struct handle_entry *entry;
|
||||
|
||||
if (get_magic_handle( handle )) return ~0U; /* magic handles have all access rights */
|
||||
if (!(entry = get_handle( process, handle ))) return 0;
|
||||
return entry->access;
|
||||
}
|
||||
|
||||
/* retrieve the cached fd for a given handle */
|
||||
int get_handle_unix_fd( struct process *process, obj_handle_t handle, unsigned int access )
|
||||
{
|
||||
|
@ -38,6 +38,7 @@ extern obj_handle_t alloc_handle( struct process *process, void *obj,
|
||||
extern int close_handle( struct process *process, obj_handle_t handle, int *fd );
|
||||
extern struct object *get_handle_obj( struct process *process, obj_handle_t handle,
|
||||
unsigned int access, const struct object_ops *ops );
|
||||
extern unsigned int get_handle_access( struct process *process, obj_handle_t handle );
|
||||
extern int get_handle_unix_fd( struct process *process, obj_handle_t handle, unsigned int access );
|
||||
extern int set_handle_info( struct process *process, obj_handle_t handle, int mask, int flags, int *fd );
|
||||
extern obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst,
|
||||
|
@ -77,6 +77,7 @@ static const struct object_ops hook_table_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
hook_table_destroy /* destroy */
|
||||
};
|
||||
|
@ -72,6 +72,7 @@ static const struct object_ops mailslot_ops =
|
||||
default_fd_remove_queue, /* remove_queue */
|
||||
default_fd_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
mailslot_get_fd, /* get_fd */
|
||||
mailslot_destroy /* destroy */
|
||||
};
|
||||
@ -113,6 +114,7 @@ static const struct object_ops mail_writer_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
mail_writer_get_fd, /* get_fd */
|
||||
mail_writer_destroy /* destroy */
|
||||
};
|
||||
|
@ -62,6 +62,7 @@ static const struct object_ops mapping_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
mapping_get_fd, /* get_fd */
|
||||
mapping_destroy /* destroy */
|
||||
};
|
||||
|
@ -44,6 +44,7 @@ static void mutex_dump( struct object *obj, int verbose );
|
||||
static int mutex_signaled( struct object *obj, struct thread *thread );
|
||||
static int mutex_satisfied( struct object *obj, struct thread *thread );
|
||||
static void mutex_destroy( struct object *obj );
|
||||
static int mutex_signal( struct object *obj, unsigned int access );
|
||||
|
||||
static const struct object_ops mutex_ops =
|
||||
{
|
||||
@ -53,6 +54,7 @@ static const struct object_ops mutex_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
mutex_signaled, /* signaled */
|
||||
mutex_satisfied, /* satisfied */
|
||||
mutex_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
mutex_destroy /* destroy */
|
||||
};
|
||||
@ -133,6 +135,25 @@ static int mutex_satisfied( struct object *obj, struct thread *thread )
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mutex_signal( struct object *obj, unsigned int access )
|
||||
{
|
||||
struct mutex *mutex = (struct mutex *)obj;
|
||||
assert( obj->ops == &mutex_ops );
|
||||
|
||||
if (!(access & SYNCHRONIZE)) /* FIXME: MUTEX_MODIFY_STATE? */
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return 0;
|
||||
}
|
||||
if (!mutex->count || (mutex->owner != current))
|
||||
{
|
||||
set_error( STATUS_MUTANT_NOT_OWNED );
|
||||
return 0;
|
||||
}
|
||||
if (!--mutex->count) do_release( mutex );
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void mutex_destroy( struct object *obj )
|
||||
{
|
||||
struct mutex *mutex = (struct mutex *)obj;
|
||||
|
@ -106,6 +106,7 @@ static const struct object_ops named_pipe_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
named_pipe_destroy /* destroy */
|
||||
};
|
||||
@ -128,6 +129,7 @@ static const struct object_ops pipe_server_ops =
|
||||
default_fd_remove_queue, /* remove_queue */
|
||||
default_fd_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
pipe_server_get_fd, /* get_fd */
|
||||
pipe_server_destroy /* destroy */
|
||||
};
|
||||
@ -156,6 +158,7 @@ static const struct object_ops pipe_client_ops =
|
||||
default_fd_remove_queue, /* remove_queue */
|
||||
default_fd_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
pipe_client_get_fd, /* get_fd */
|
||||
pipe_client_destroy /* destroy */
|
||||
};
|
||||
|
@ -273,6 +273,12 @@ int no_satisfied( struct object *obj, struct thread *thread )
|
||||
return 0; /* not abandoned */
|
||||
}
|
||||
|
||||
int no_signal( struct object *obj, unsigned int access )
|
||||
{
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct fd *no_get_fd( struct object *obj )
|
||||
{
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
|
@ -59,6 +59,8 @@ struct object_ops
|
||||
int (*signaled)(struct object *,struct thread *);
|
||||
/* wait satisfied; return 1 if abandoned */
|
||||
int (*satisfied)(struct object *,struct thread *);
|
||||
/* signal an object */
|
||||
int (*signal)(struct object *, unsigned int);
|
||||
/* return an fd object that can be used to read/write from the object */
|
||||
struct fd *(*get_fd)(struct object *);
|
||||
/* destroy on refcount == 0 */
|
||||
@ -97,6 +99,7 @@ extern void release_object( void *obj );
|
||||
extern struct object *find_object( const struct namespace *namespace, const WCHAR *name, size_t len );
|
||||
extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry );
|
||||
extern int no_satisfied( struct object *obj, struct thread *thread );
|
||||
extern int no_signal( struct object *obj, unsigned int access );
|
||||
extern struct fd *no_get_fd( struct object *obj );
|
||||
extern void no_destroy( struct object *obj );
|
||||
#ifdef DEBUG_OBJECTS
|
||||
|
@ -70,6 +70,7 @@ static const struct object_ops process_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
process_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
process_destroy /* destroy */
|
||||
};
|
||||
@ -116,6 +117,7 @@ static const struct object_ops startup_info_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
startup_info_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
startup_info_destroy /* destroy */
|
||||
};
|
||||
|
@ -480,6 +480,7 @@ enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
|
||||
@REQ(select)
|
||||
int flags; /* wait flags (see below) */
|
||||
void* cookie; /* magic cookie to return to client */
|
||||
obj_handle_t signal; /* object to signal (0 if none) */
|
||||
abs_time_t timeout; /* absolute timeout */
|
||||
VARARG(handles,handles); /* handles to select on */
|
||||
@END
|
||||
|
@ -146,6 +146,7 @@ static const struct object_ops msg_queue_ops =
|
||||
msg_queue_remove_queue, /* remove_queue */
|
||||
msg_queue_signaled, /* signaled */
|
||||
msg_queue_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
msg_queue_destroy /* destroy */
|
||||
};
|
||||
@ -159,6 +160,7 @@ static const struct object_ops thread_input_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
thread_input_destroy /* destroy */
|
||||
};
|
||||
|
@ -138,6 +138,7 @@ static const struct object_ops key_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
key_destroy /* destroy */
|
||||
};
|
||||
|
@ -93,6 +93,7 @@ static const struct object_ops master_socket_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
master_socket_destroy /* destroy */
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ struct semaphore
|
||||
static void semaphore_dump( struct object *obj, int verbose );
|
||||
static int semaphore_signaled( struct object *obj, struct thread *thread );
|
||||
static int semaphore_satisfied( struct object *obj, struct thread *thread );
|
||||
static int semaphore_signal( struct object *obj, unsigned int access );
|
||||
|
||||
static const struct object_ops semaphore_ops =
|
||||
{
|
||||
@ -50,6 +51,7 @@ static const struct object_ops semaphore_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
semaphore_signaled, /* signaled */
|
||||
semaphore_satisfied, /* satisfied */
|
||||
semaphore_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
no_destroy /* destroy */
|
||||
};
|
||||
@ -77,32 +79,26 @@ static struct semaphore *create_semaphore( const WCHAR *name, size_t len,
|
||||
return sem;
|
||||
}
|
||||
|
||||
static unsigned int release_semaphore( obj_handle_t handle, unsigned int count )
|
||||
static int release_semaphore( struct semaphore *sem, unsigned int count,
|
||||
unsigned int *prev )
|
||||
{
|
||||
struct semaphore *sem;
|
||||
unsigned int prev = 0;
|
||||
|
||||
if ((sem = (struct semaphore *)get_handle_obj( current->process, handle,
|
||||
SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
|
||||
if (prev) *prev = sem->count;
|
||||
if (sem->count + count < sem->count || sem->count + count > sem->max)
|
||||
{
|
||||
prev = sem->count;
|
||||
if (sem->count + count < sem->count || sem->count + count > sem->max)
|
||||
{
|
||||
set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
|
||||
}
|
||||
else if (sem->count)
|
||||
{
|
||||
/* there cannot be any thread to wake up if the count is != 0 */
|
||||
sem->count += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
sem->count = count;
|
||||
wake_up( &sem->obj, count );
|
||||
}
|
||||
release_object( sem );
|
||||
set_error( STATUS_SEMAPHORE_LIMIT_EXCEEDED );
|
||||
return 0;
|
||||
}
|
||||
return prev;
|
||||
else if (sem->count)
|
||||
{
|
||||
/* there cannot be any thread to wake up if the count is != 0 */
|
||||
sem->count += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
sem->count = count;
|
||||
wake_up( &sem->obj, count );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void semaphore_dump( struct object *obj, int verbose )
|
||||
@ -130,6 +126,19 @@ static int semaphore_satisfied( struct object *obj, struct thread *thread )
|
||||
return 0; /* not abandoned */
|
||||
}
|
||||
|
||||
static int semaphore_signal( struct object *obj, unsigned int access )
|
||||
{
|
||||
struct semaphore *sem = (struct semaphore *)obj;
|
||||
assert( obj->ops == &semaphore_ops );
|
||||
|
||||
if (!(access & SEMAPHORE_MODIFY_STATE))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return 0;
|
||||
}
|
||||
return release_semaphore( sem, 1, NULL );
|
||||
}
|
||||
|
||||
/* create a semaphore */
|
||||
DECL_HANDLER(create_semaphore)
|
||||
{
|
||||
@ -154,5 +163,12 @@ DECL_HANDLER(open_semaphore)
|
||||
/* release a semaphore */
|
||||
DECL_HANDLER(release_semaphore)
|
||||
{
|
||||
reply->prev_count = release_semaphore( req->handle, req->count );
|
||||
struct semaphore *sem;
|
||||
|
||||
if ((sem = (struct semaphore *)get_handle_obj( current->process, req->handle,
|
||||
SEMAPHORE_MODIFY_STATE, &semaphore_ops )))
|
||||
{
|
||||
release_semaphore( sem, req->count, &reply->prev_count );
|
||||
release_object( sem );
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,7 @@ static const struct object_ops serial_ops =
|
||||
default_fd_remove_queue, /* remove_queue */
|
||||
default_fd_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
serial_get_fd, /* get_fd */
|
||||
serial_destroy /* destroy */
|
||||
};
|
||||
|
@ -62,6 +62,7 @@ static const struct object_ops handler_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
handler_destroy /* destroy */
|
||||
};
|
||||
|
@ -61,6 +61,7 @@ static const struct object_ops snapshot_ops =
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
snapshot_destroy /* destroy */
|
||||
};
|
||||
|
@ -107,6 +107,7 @@ static const struct object_ops sock_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
sock_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
sock_get_fd, /* get_fd */
|
||||
sock_destroy /* destroy */
|
||||
};
|
||||
|
@ -92,6 +92,7 @@ static const struct object_ops thread_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
thread_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
destroy_thread /* destroy */
|
||||
};
|
||||
@ -516,9 +517,24 @@ static void thread_timeout( void *ptr )
|
||||
wake_thread( thread );
|
||||
}
|
||||
|
||||
/* try signaling an event flag, a semaphore or a mutex */
|
||||
static int signal_object( obj_handle_t handle )
|
||||
{
|
||||
struct object *obj;
|
||||
int ret = 0;
|
||||
|
||||
obj = get_handle_obj( current->process, handle, 0, NULL );
|
||||
if (obj)
|
||||
{
|
||||
ret = obj->ops->signal( obj, get_handle_access( current->process, handle ));
|
||||
release_object( obj );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* select on a list of handles */
|
||||
static void select_on( int count, void *cookie, const obj_handle_t *handles,
|
||||
int flags, const abs_time_t *timeout )
|
||||
int flags, const abs_time_t *timeout, obj_handle_t signal_obj )
|
||||
{
|
||||
int ret, i;
|
||||
struct object *objects[MAXIMUM_WAIT_OBJECTS];
|
||||
@ -537,6 +553,18 @@ static void select_on( int count, void *cookie, const obj_handle_t *handles,
|
||||
if (i < count) goto done;
|
||||
if (!wait_on( count, objects, flags, timeout )) goto done;
|
||||
|
||||
/* signal the object */
|
||||
if (signal_obj)
|
||||
{
|
||||
if (!signal_object( signal_obj ))
|
||||
{
|
||||
end_wait( current );
|
||||
goto done;
|
||||
}
|
||||
/* check if we woke ourselves up */
|
||||
if (!current->wait) goto done;
|
||||
}
|
||||
|
||||
if ((ret = check_wait( current )) != -1)
|
||||
{
|
||||
/* condition is already satisfied */
|
||||
@ -962,7 +990,7 @@ DECL_HANDLER(resume_thread)
|
||||
DECL_HANDLER(select)
|
||||
{
|
||||
int count = get_req_data_size() / sizeof(int);
|
||||
select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout );
|
||||
select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout, req->signal );
|
||||
}
|
||||
|
||||
/* queue an APC for a thread */
|
||||
|
@ -59,6 +59,7 @@ static const struct object_ops timer_ops =
|
||||
remove_queue, /* remove_queue */
|
||||
timer_signaled, /* signaled */
|
||||
timer_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
timer_destroy /* destroy */
|
||||
};
|
||||
|
@ -79,7 +79,8 @@ static const struct object_ops token_ops =
|
||||
no_add_queue, /* add_queue */
|
||||
NULL, /* remove_queue */
|
||||
NULL, /* signaled */
|
||||
NULL, /* satified */
|
||||
NULL, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
token_destroy /* destroy */
|
||||
};
|
||||
|
@ -760,6 +760,7 @@ static void dump_select_request( const struct select_request *req )
|
||||
{
|
||||
fprintf( stderr, " flags=%d,", req->flags );
|
||||
fprintf( stderr, " cookie=%p,", req->cookie );
|
||||
fprintf( stderr, " signal=%p,", req->signal );
|
||||
fprintf( stderr, " timeout=" );
|
||||
dump_abs_time( &req->timeout );
|
||||
fprintf( stderr, "," );
|
||||
|
Loading…
x
Reference in New Issue
Block a user