ntdll: Move the keyed event functions to the Unix library.
[wine.git] / dlls / ntdll / unix / sync.c
blobcea005fefbaa8ca3ab7a385f16b093c4e3704ea3
1 /*
2 * Process synchronisation
4 * Copyright 1996, 1997, 1998 Marcus Meissner
5 * Copyright 1997, 1999 Alexandre Julliard
6 * Copyright 1999, 2000 Juergen Schmied
7 * Copyright 2003 Eric Pouech
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #if 0
25 #pragma makedep unix
26 #endif
28 #include "config.h"
29 #include "wine/port.h"
31 #include <assert.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <signal.h>
35 #ifdef HAVE_SYS_SYSCALL_H
36 #include <sys/syscall.h>
37 #endif
38 #ifdef HAVE_SYS_TIME_H
39 # include <sys/time.h>
40 #endif
41 #ifdef HAVE_POLL_H
42 #include <poll.h>
43 #endif
44 #ifdef HAVE_SYS_POLL_H
45 # include <sys/poll.h>
46 #endif
47 #ifdef HAVE_UNISTD_H
48 # include <unistd.h>
49 #endif
50 #ifdef HAVE_SCHED_H
51 # include <sched.h>
52 #endif
53 #include <string.h>
54 #include <stdarg.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <time.h>
59 #include "ntstatus.h"
60 #define WIN32_NO_STATUS
61 #define NONAMELESSUNION
62 #include "windef.h"
63 #include "winternl.h"
64 #include "wine/server.h"
65 #include "wine/debug.h"
66 #include "unix_private.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(sync);
71 HANDLE keyed_event = 0;
74 /* create a struct security_descriptor and contained information in one contiguous piece of memory */
75 static NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
76 data_size_t *ret_len )
78 unsigned int len = sizeof(**ret);
79 PSID owner = NULL, group = NULL;
80 ACL *dacl, *sacl;
81 BOOLEAN dacl_present, sacl_present, defaulted;
82 PSECURITY_DESCRIPTOR sd;
83 NTSTATUS status;
85 *ret = NULL;
86 *ret_len = 0;
88 if (!attr) return STATUS_SUCCESS;
90 if (attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER;
92 if ((sd = attr->SecurityDescriptor))
94 len += sizeof(struct security_descriptor);
96 if ((status = RtlGetOwnerSecurityDescriptor( sd, &owner, &defaulted ))) return status;
97 if ((status = RtlGetGroupSecurityDescriptor( sd, &group, &defaulted ))) return status;
98 if ((status = RtlGetSaclSecurityDescriptor( sd, &sacl_present, &sacl, &defaulted ))) return status;
99 if ((status = RtlGetDaclSecurityDescriptor( sd, &dacl_present, &dacl, &defaulted ))) return status;
100 if (owner) len += RtlLengthSid( owner );
101 if (group) len += RtlLengthSid( group );
102 if (sacl_present && sacl) len += sacl->AclSize;
103 if (dacl_present && dacl) len += dacl->AclSize;
105 /* fix alignment for the Unicode name that follows the structure */
106 len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
109 if (attr->ObjectName)
111 if (attr->ObjectName->Length & (sizeof(WCHAR) - 1)) return STATUS_OBJECT_NAME_INVALID;
112 len += attr->ObjectName->Length;
114 else if (attr->RootDirectory) return STATUS_OBJECT_NAME_INVALID;
116 len = (len + 3) & ~3; /* DWORD-align the entire structure */
118 *ret = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
119 if (!*ret) return STATUS_NO_MEMORY;
121 (*ret)->rootdir = wine_server_obj_handle( attr->RootDirectory );
122 (*ret)->attributes = attr->Attributes;
124 if (attr->SecurityDescriptor)
126 struct security_descriptor *descr = (struct security_descriptor *)(*ret + 1);
127 unsigned char *ptr = (unsigned char *)(descr + 1);
129 descr->control = ((SECURITY_DESCRIPTOR *)sd)->Control & ~SE_SELF_RELATIVE;
130 if (owner) descr->owner_len = RtlLengthSid( owner );
131 if (group) descr->group_len = RtlLengthSid( group );
132 if (sacl_present && sacl) descr->sacl_len = sacl->AclSize;
133 if (dacl_present && dacl) descr->dacl_len = dacl->AclSize;
135 memcpy( ptr, owner, descr->owner_len );
136 ptr += descr->owner_len;
137 memcpy( ptr, group, descr->group_len );
138 ptr += descr->group_len;
139 memcpy( ptr, sacl, descr->sacl_len );
140 ptr += descr->sacl_len;
141 memcpy( ptr, dacl, descr->dacl_len );
142 (*ret)->sd_len = (sizeof(*descr) + descr->owner_len + descr->group_len + descr->sacl_len +
143 descr->dacl_len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1);
146 if (attr->ObjectName)
148 unsigned char *ptr = (unsigned char *)(*ret + 1) + (*ret)->sd_len;
149 (*ret)->name_len = attr->ObjectName->Length;
150 memcpy( ptr, attr->ObjectName->Buffer, (*ret)->name_len );
153 *ret_len = len;
154 return STATUS_SUCCESS;
158 static NTSTATUS validate_open_object_attributes( const OBJECT_ATTRIBUTES *attr )
160 if (!attr || attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER;
162 if (attr->ObjectName)
164 if (attr->ObjectName->Length & (sizeof(WCHAR) - 1)) return STATUS_OBJECT_NAME_INVALID;
166 else if (attr->RootDirectory) return STATUS_OBJECT_NAME_INVALID;
168 return STATUS_SUCCESS;
172 /******************************************************************************
173 * NtCreateSemaphore (NTDLL.@)
175 NTSTATUS WINAPI NtCreateSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
176 LONG initial, LONG max )
178 NTSTATUS ret;
179 data_size_t len;
180 struct object_attributes *objattr;
182 if (max <= 0 || initial < 0 || initial > max) return STATUS_INVALID_PARAMETER;
183 if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
185 SERVER_START_REQ( create_semaphore )
187 req->access = access;
188 req->initial = initial;
189 req->max = max;
190 wine_server_add_data( req, objattr, len );
191 ret = wine_server_call( req );
192 *handle = wine_server_ptr_handle( reply->handle );
194 SERVER_END_REQ;
196 RtlFreeHeap( GetProcessHeap(), 0, objattr );
197 return ret;
201 /******************************************************************************
202 * NtOpenSemaphore (NTDLL.@)
204 NTSTATUS WINAPI NtOpenSemaphore( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
206 NTSTATUS ret;
208 if ((ret = validate_open_object_attributes( attr ))) return ret;
210 SERVER_START_REQ( open_semaphore )
212 req->access = access;
213 req->attributes = attr->Attributes;
214 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
215 if (attr->ObjectName)
216 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
217 ret = wine_server_call( req );
218 *handle = wine_server_ptr_handle( reply->handle );
220 SERVER_END_REQ;
221 return ret;
225 /******************************************************************************
226 * NtQuerySemaphore (NTDLL.@)
228 NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS class,
229 void *info, ULONG len, ULONG *ret_len )
231 NTSTATUS ret;
232 SEMAPHORE_BASIC_INFORMATION *out = info;
234 TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len);
236 if (class != SemaphoreBasicInformation)
238 FIXME("(%p,%d,%u) Unknown class\n", handle, class, len);
239 return STATUS_INVALID_INFO_CLASS;
242 if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
244 SERVER_START_REQ( query_semaphore )
246 req->handle = wine_server_obj_handle( handle );
247 if (!(ret = wine_server_call( req )))
249 out->CurrentCount = reply->current;
250 out->MaximumCount = reply->max;
251 if (ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION);
254 SERVER_END_REQ;
255 return ret;
259 /******************************************************************************
260 * NtReleaseSemaphore (NTDLL.@)
262 NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous )
264 NTSTATUS ret;
266 SERVER_START_REQ( release_semaphore )
268 req->handle = wine_server_obj_handle( handle );
269 req->count = count;
270 if (!(ret = wine_server_call( req )))
272 if (previous) *previous = reply->prev_count;
275 SERVER_END_REQ;
276 return ret;
280 /**************************************************************************
281 * NtCreateEvent (NTDLL.@)
283 NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
284 EVENT_TYPE type, BOOLEAN state )
286 NTSTATUS ret;
287 data_size_t len;
288 struct object_attributes *objattr;
290 if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
292 SERVER_START_REQ( create_event )
294 req->access = access;
295 req->manual_reset = (type == NotificationEvent);
296 req->initial_state = state;
297 wine_server_add_data( req, objattr, len );
298 ret = wine_server_call( req );
299 *handle = wine_server_ptr_handle( reply->handle );
301 SERVER_END_REQ;
303 RtlFreeHeap( GetProcessHeap(), 0, objattr );
304 return ret;
308 /******************************************************************************
309 * NtOpenEvent (NTDLL.@)
311 NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
313 NTSTATUS ret;
315 if ((ret = validate_open_object_attributes( attr ))) return ret;
317 SERVER_START_REQ( open_event )
319 req->access = access;
320 req->attributes = attr->Attributes;
321 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
322 if (attr->ObjectName)
323 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
324 ret = wine_server_call( req );
325 *handle = wine_server_ptr_handle( reply->handle );
327 SERVER_END_REQ;
328 return ret;
332 /******************************************************************************
333 * NtSetEvent (NTDLL.@)
335 NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
337 NTSTATUS ret;
339 SERVER_START_REQ( event_op )
341 req->handle = wine_server_obj_handle( handle );
342 req->op = SET_EVENT;
343 ret = wine_server_call( req );
344 if (!ret && prev_state) *prev_state = reply->state;
346 SERVER_END_REQ;
347 return ret;
351 /******************************************************************************
352 * NtResetEvent (NTDLL.@)
354 NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
356 NTSTATUS ret;
358 SERVER_START_REQ( event_op )
360 req->handle = wine_server_obj_handle( handle );
361 req->op = RESET_EVENT;
362 ret = wine_server_call( req );
363 if (!ret && prev_state) *prev_state = reply->state;
365 SERVER_END_REQ;
366 return ret;
370 /******************************************************************************
371 * NtClearEvent (NTDLL.@)
373 NTSTATUS WINAPI NtClearEvent( HANDLE handle )
375 /* FIXME: same as NtResetEvent ??? */
376 return NtResetEvent( handle, NULL );
380 /******************************************************************************
381 * NtPulseEvent (NTDLL.@)
383 NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
385 NTSTATUS ret;
387 SERVER_START_REQ( event_op )
389 req->handle = wine_server_obj_handle( handle );
390 req->op = PULSE_EVENT;
391 ret = wine_server_call( req );
392 if (!ret && prev_state) *prev_state = reply->state;
394 SERVER_END_REQ;
395 return ret;
399 /******************************************************************************
400 * NtQueryEvent (NTDLL.@)
402 NTSTATUS WINAPI NtQueryEvent( HANDLE handle, EVENT_INFORMATION_CLASS class,
403 void *info, ULONG len, ULONG *ret_len )
405 NTSTATUS ret;
406 EVENT_BASIC_INFORMATION *out = info;
408 TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len);
410 if (class != EventBasicInformation)
412 FIXME("(%p, %d, %d) Unknown class\n",
413 handle, class, len);
414 return STATUS_INVALID_INFO_CLASS;
417 if (len != sizeof(EVENT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
419 SERVER_START_REQ( query_event )
421 req->handle = wine_server_obj_handle( handle );
422 if (!(ret = wine_server_call( req )))
424 out->EventType = reply->manual_reset ? NotificationEvent : SynchronizationEvent;
425 out->EventState = reply->state;
426 if (ret_len) *ret_len = sizeof(EVENT_BASIC_INFORMATION);
429 SERVER_END_REQ;
430 return ret;
434 /******************************************************************************
435 * NtCreateMutant (NTDLL.@)
437 NTSTATUS WINAPI NtCreateMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
438 BOOLEAN owned )
440 NTSTATUS ret;
441 data_size_t len;
442 struct object_attributes *objattr;
444 if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
446 SERVER_START_REQ( create_mutex )
448 req->access = access;
449 req->owned = owned;
450 wine_server_add_data( req, objattr, len );
451 ret = wine_server_call( req );
452 *handle = wine_server_ptr_handle( reply->handle );
454 SERVER_END_REQ;
456 RtlFreeHeap( GetProcessHeap(), 0, objattr );
457 return ret;
461 /**************************************************************************
462 * NtOpenMutant (NTDLL.@)
464 NTSTATUS WINAPI NtOpenMutant( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
466 NTSTATUS ret;
468 if ((ret = validate_open_object_attributes( attr ))) return ret;
470 SERVER_START_REQ( open_mutex )
472 req->access = access;
473 req->attributes = attr->Attributes;
474 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
475 if (attr->ObjectName)
476 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
477 ret = wine_server_call( req );
478 *handle = wine_server_ptr_handle( reply->handle );
480 SERVER_END_REQ;
481 return ret;
485 /**************************************************************************
486 * NtReleaseMutant (NTDLL.@)
488 NTSTATUS WINAPI NtReleaseMutant( HANDLE handle, LONG *prev_count )
490 NTSTATUS ret;
492 SERVER_START_REQ( release_mutex )
494 req->handle = wine_server_obj_handle( handle );
495 ret = wine_server_call( req );
496 if (prev_count) *prev_count = 1 - reply->prev_count;
498 SERVER_END_REQ;
499 return ret;
503 /******************************************************************
504 * NtQueryMutant (NTDLL.@)
506 NTSTATUS WINAPI NtQueryMutant( HANDLE handle, MUTANT_INFORMATION_CLASS class,
507 void *info, ULONG len, ULONG *ret_len )
509 NTSTATUS ret;
510 MUTANT_BASIC_INFORMATION *out = info;
512 TRACE("(%p, %u, %p, %u, %p)\n", handle, class, info, len, ret_len);
514 if (class != MutantBasicInformation)
516 FIXME( "(%p, %d, %d) Unknown class\n", handle, class, len );
517 return STATUS_INVALID_INFO_CLASS;
520 if (len != sizeof(MUTANT_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
522 SERVER_START_REQ( query_mutex )
524 req->handle = wine_server_obj_handle( handle );
525 if (!(ret = wine_server_call( req )))
527 out->CurrentCount = 1 - reply->count;
528 out->OwnedByCaller = reply->owned;
529 out->AbandonedState = reply->abandoned;
530 if (ret_len) *ret_len = sizeof(MUTANT_BASIC_INFORMATION);
533 SERVER_END_REQ;
534 return ret;
538 /**************************************************************************
539 * NtCreateTimer (NTDLL.@)
541 NTSTATUS WINAPI NtCreateTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
542 TIMER_TYPE type )
544 NTSTATUS ret;
545 data_size_t len;
546 struct object_attributes *objattr;
548 if (type != NotificationTimer && type != SynchronizationTimer) return STATUS_INVALID_PARAMETER;
550 if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
552 SERVER_START_REQ( create_timer )
554 req->access = access;
555 req->manual = (type == NotificationTimer);
556 wine_server_add_data( req, objattr, len );
557 ret = wine_server_call( req );
558 *handle = wine_server_ptr_handle( reply->handle );
560 SERVER_END_REQ;
562 RtlFreeHeap( GetProcessHeap(), 0, objattr );
563 return ret;
568 /**************************************************************************
569 * NtOpenTimer (NTDLL.@)
571 NTSTATUS WINAPI NtOpenTimer( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
573 NTSTATUS ret;
575 if ((ret = validate_open_object_attributes( attr ))) return ret;
577 SERVER_START_REQ( open_timer )
579 req->access = access;
580 req->attributes = attr->Attributes;
581 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
582 if (attr->ObjectName)
583 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
584 ret = wine_server_call( req );
585 *handle = wine_server_ptr_handle( reply->handle );
587 SERVER_END_REQ;
588 return ret;
592 /**************************************************************************
593 * NtSetTimer (NTDLL.@)
595 NTSTATUS WINAPI NtSetTimer( HANDLE handle, const LARGE_INTEGER *when, PTIMER_APC_ROUTINE callback,
596 void *arg, BOOLEAN resume, ULONG period, BOOLEAN *state )
598 NTSTATUS ret = STATUS_SUCCESS;
600 TRACE( "(%p,%p,%p,%p,%08x,0x%08x,%p)\n", handle, when, callback, arg, resume, period, state );
602 SERVER_START_REQ( set_timer )
604 req->handle = wine_server_obj_handle( handle );
605 req->period = period;
606 req->expire = when->QuadPart;
607 req->callback = wine_server_client_ptr( callback );
608 req->arg = wine_server_client_ptr( arg );
609 ret = wine_server_call( req );
610 if (state) *state = reply->signaled;
612 SERVER_END_REQ;
614 /* set error but can still succeed */
615 if (resume && ret == STATUS_SUCCESS) return STATUS_TIMER_RESUME_IGNORED;
616 return ret;
620 /**************************************************************************
621 * NtCancelTimer (NTDLL.@)
623 NTSTATUS WINAPI NtCancelTimer( HANDLE handle, BOOLEAN *state )
625 NTSTATUS ret;
627 SERVER_START_REQ( cancel_timer )
629 req->handle = wine_server_obj_handle( handle );
630 ret = wine_server_call( req );
631 if (state) *state = reply->signaled;
633 SERVER_END_REQ;
634 return ret;
638 /******************************************************************************
639 * NtQueryTimer (NTDLL.@)
641 NTSTATUS WINAPI NtQueryTimer( HANDLE handle, TIMER_INFORMATION_CLASS class,
642 void *info, ULONG len, ULONG *ret_len )
644 TIMER_BASIC_INFORMATION *basic_info = info;
645 NTSTATUS ret;
646 LARGE_INTEGER now;
648 TRACE( "(%p,%d,%p,0x%08x,%p)\n", handle, class, info, len, ret_len );
650 switch (class)
652 case TimerBasicInformation:
653 if (len < sizeof(TIMER_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
655 SERVER_START_REQ( get_timer_info )
657 req->handle = wine_server_obj_handle( handle );
658 ret = wine_server_call(req);
659 /* convert server time to absolute NTDLL time */
660 basic_info->RemainingTime.QuadPart = reply->when;
661 basic_info->TimerState = reply->signaled;
663 SERVER_END_REQ;
665 /* convert into relative time */
666 if (basic_info->RemainingTime.QuadPart > 0) NtQuerySystemTime( &now );
667 else
669 RtlQueryPerformanceCounter( &now );
670 basic_info->RemainingTime.QuadPart = -basic_info->RemainingTime.QuadPart;
673 if (now.QuadPart > basic_info->RemainingTime.QuadPart)
674 basic_info->RemainingTime.QuadPart = 0;
675 else
676 basic_info->RemainingTime.QuadPart -= now.QuadPart;
678 if (ret_len) *ret_len = sizeof(TIMER_BASIC_INFORMATION);
679 return ret;
682 FIXME( "Unhandled class %d\n", class );
683 return STATUS_INVALID_INFO_CLASS;
687 /******************************************************************
688 * NtWaitForMultipleObjects (NTDLL.@)
690 NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
691 BOOLEAN alertable, const LARGE_INTEGER *timeout )
693 select_op_t select_op;
694 UINT i, flags = SELECT_INTERRUPTIBLE;
696 if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
698 if (alertable) flags |= SELECT_ALERTABLE;
699 select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
700 for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
701 return server_wait( &select_op, offsetof( select_op_t, wait.handles[count] ), flags, timeout );
705 /******************************************************************
706 * NtWaitForSingleObject (NTDLL.@)
708 NTSTATUS WINAPI NtWaitForSingleObject( HANDLE handle, BOOLEAN alertable, const LARGE_INTEGER *timeout )
710 return NtWaitForMultipleObjects( 1, &handle, FALSE, alertable, timeout );
714 /******************************************************************
715 * NtSignalAndWaitForSingleObject (NTDLL.@)
717 NTSTATUS WINAPI NtSignalAndWaitForSingleObject( HANDLE signal, HANDLE wait,
718 BOOLEAN alertable, const LARGE_INTEGER *timeout )
720 select_op_t select_op;
721 UINT flags = SELECT_INTERRUPTIBLE;
723 if (!signal) return STATUS_INVALID_HANDLE;
725 if (alertable) flags |= SELECT_ALERTABLE;
726 select_op.signal_and_wait.op = SELECT_SIGNAL_AND_WAIT;
727 select_op.signal_and_wait.wait = wine_server_obj_handle( wait );
728 select_op.signal_and_wait.signal = wine_server_obj_handle( signal );
729 return server_wait( &select_op, sizeof(select_op.signal_and_wait), flags, timeout );
733 /******************************************************************
734 * NtYieldExecution (NTDLL.@)
736 NTSTATUS WINAPI NtYieldExecution(void)
738 #ifdef HAVE_SCHED_YIELD
739 sched_yield();
740 return STATUS_SUCCESS;
741 #else
742 return STATUS_NO_YIELD_PERFORMED;
743 #endif
747 /******************************************************************
748 * NtDelayExecution (NTDLL.@)
750 NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout )
752 /* if alertable, we need to query the server */
753 if (alertable) return server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, timeout );
755 if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */
757 for (;;) select( 0, NULL, NULL, NULL, NULL );
759 else
761 LARGE_INTEGER now;
762 timeout_t when, diff;
764 if ((when = timeout->QuadPart) < 0)
766 NtQuerySystemTime( &now );
767 when = now.QuadPart - when;
770 /* Note that we yield after establishing the desired timeout */
771 NtYieldExecution();
772 if (!when) return STATUS_SUCCESS;
774 for (;;)
776 struct timeval tv;
777 NtQuerySystemTime( &now );
778 diff = (when - now.QuadPart + 9) / 10;
779 if (diff <= 0) break;
780 tv.tv_sec = diff / 1000000;
781 tv.tv_usec = diff % 1000000;
782 if (select( 0, NULL, NULL, NULL, &tv ) != -1) break;
785 return STATUS_SUCCESS;
789 /******************************************************************************
790 * NtCreateKeyedEvent (NTDLL.@)
792 NTSTATUS WINAPI NtCreateKeyedEvent( HANDLE *handle, ACCESS_MASK access,
793 const OBJECT_ATTRIBUTES *attr, ULONG flags )
795 NTSTATUS ret;
796 data_size_t len;
797 struct object_attributes *objattr;
799 if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
801 SERVER_START_REQ( create_keyed_event )
803 req->access = access;
804 wine_server_add_data( req, objattr, len );
805 ret = wine_server_call( req );
806 *handle = wine_server_ptr_handle( reply->handle );
808 SERVER_END_REQ;
810 RtlFreeHeap( GetProcessHeap(), 0, objattr );
811 return ret;
815 /******************************************************************************
816 * NtOpenKeyedEvent (NTDLL.@)
818 NTSTATUS WINAPI NtOpenKeyedEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
820 NTSTATUS ret;
822 if ((ret = validate_open_object_attributes( attr ))) return ret;
824 SERVER_START_REQ( open_keyed_event )
826 req->access = access;
827 req->attributes = attr->Attributes;
828 req->rootdir = wine_server_obj_handle( attr->RootDirectory );
829 if (attr->ObjectName)
830 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
831 ret = wine_server_call( req );
832 *handle = wine_server_ptr_handle( reply->handle );
834 SERVER_END_REQ;
835 return ret;
838 /******************************************************************************
839 * NtWaitForKeyedEvent (NTDLL.@)
841 NTSTATUS WINAPI NtWaitForKeyedEvent( HANDLE handle, const void *key,
842 BOOLEAN alertable, const LARGE_INTEGER *timeout )
844 select_op_t select_op;
845 UINT flags = SELECT_INTERRUPTIBLE;
847 if (!handle) handle = keyed_event;
848 if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1;
849 if (alertable) flags |= SELECT_ALERTABLE;
850 select_op.keyed_event.op = SELECT_KEYED_EVENT_WAIT;
851 select_op.keyed_event.handle = wine_server_obj_handle( handle );
852 select_op.keyed_event.key = wine_server_client_ptr( key );
853 return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );
857 /******************************************************************************
858 * NtReleaseKeyedEvent (NTDLL.@)
860 NTSTATUS WINAPI NtReleaseKeyedEvent( HANDLE handle, const void *key,
861 BOOLEAN alertable, const LARGE_INTEGER *timeout )
863 select_op_t select_op;
864 UINT flags = SELECT_INTERRUPTIBLE;
866 if (!handle) handle = keyed_event;
867 if ((ULONG_PTR)key & 1) return STATUS_INVALID_PARAMETER_1;
868 if (alertable) flags |= SELECT_ALERTABLE;
869 select_op.keyed_event.op = SELECT_KEYED_EVENT_RELEASE;
870 select_op.keyed_event.handle = wine_server_obj_handle( handle );
871 select_op.keyed_event.key = wine_server_client_ptr( key );
872 return server_wait( &select_op, sizeof(select_op.keyed_event), flags, timeout );