* wininfo.h (wininfo::timer_active): Delete.
(wininfo::itv): Ditto. (wininfo::start_time): Ditto. (wininfo::window_started): Ditto. (wininfo::getitimer): Ditto. (wininfo::setitimer): Ditto. (wininfo::wininfo): Ditto. (wininfo::lock): New method. (wininfo::release): Ditto. * window.cc: Use new lock/acquire wininfo methods throughout. (wininfo::wininfo): Delete (wininfo::getitimer): Ditto. (wininfo::setitimer): Ditto. (getitimer): Ditto. (setitimer): Ditto. (ualarm): Ditto. (alarm): Ditto. (wininfo::lock): Define new function. (wininfo::release): Ditto. (wininfo::process): Delete WM_TIMER handling. * timer.cc (struct timetracker): Delete it, flags. Add it_interval, interval_us, sleepto_us, running, init_muto(), syncthread, and gettime(). (ttstart): Make NO_COPY. (lock_timer_tracker): New class. (timer_tracker::timer_tracker): Distinguish ttstart case. (timer_tracker::~timer_tracker): New destructor. Clean out events, and reset magic. (timer_tracker::init_muto): New method. (to_us): Round up as per POSIX. (timer_thread): Reorganize to match timer_tracker::settime and timer_tracker::gettime. Call sig_send without wait. Call auto_release. (timer_tracker::settime): Reorganize logic to avoid race. Call gettime to recover old value. (timer_tracker::gettime): New method. (timer_create): Properly set errno on invalid timerid. Use new lock_timer_tracker method. (timer_delete): Ditto. Simplify code slightly. (timer_gettime): New function. (fixup_timers_after_fork): Reinit ttstart. (getitimer): New implementation. (setitimer): Ditto. (ualarm): Ditto. (alarm): Ditto. * cygwin.din: Export timer_gettime. * winsup.h: Remove has has_visible_window_station declaration. * Makefile.in (DLL_OFILES): Add lsearch.o. * cygthread.h (cygthread::notify_detached): New element. (cygthread::cygthread): Take optional fourth argument signifying event to signal on thread completion. * cygthread.cc (cygthread::stub): Signal notify_detached event, if it exists. (cygthread::cygthread): Initialize notify_detached from fourth argument. (cygthread::detach): Wait for notify_detached field is present. * lsearch.cc: New file. * search.h: Ditto. * include/cygwin/version.h: Bump API minor number to 126. * cygwin.din: Export lsearch, lfind.
This commit is contained in:
		| @@ -1,3 +1,70 @@ | ||||
| 2005-03-26  Pierre Humblet <pierre.humblet@ieee.org> | ||||
| 	    Christopher Faylor <cgf@timesys.com> | ||||
|  | ||||
| 	* wininfo.h (wininfo::timer_active): Delete. | ||||
| 	(wininfo::itv): Ditto. | ||||
| 	(wininfo::start_time): Ditto. | ||||
| 	(wininfo::window_started): Ditto. | ||||
| 	(wininfo::getitimer): Ditto. | ||||
| 	(wininfo::setitimer): Ditto. | ||||
| 	(wininfo::wininfo): Ditto. | ||||
| 	(wininfo::lock): New method. | ||||
| 	(wininfo::release): Ditto. | ||||
| 	* window.cc:  Use new lock/acquire wininfo methods throughout. | ||||
| 	 (wininfo::wininfo): Delete | ||||
| 	(wininfo::getitimer): Ditto. | ||||
| 	(wininfo::setitimer): Ditto. | ||||
| 	(getitimer): Ditto. | ||||
| 	(setitimer): Ditto. | ||||
| 	(ualarm): Ditto. | ||||
| 	(alarm): Ditto. | ||||
| 	(wininfo::lock): Define new function. | ||||
| 	(wininfo::release): Ditto. | ||||
| 	(wininfo::process): Delete WM_TIMER handling. | ||||
| 	* timer.cc (struct timetracker): Delete it, flags.  Add it_interval, | ||||
| 	interval_us, sleepto_us, running, init_muto(), syncthread, and | ||||
| 	gettime(). | ||||
| 	(ttstart): Make NO_COPY. | ||||
| 	(lock_timer_tracker): New class. | ||||
| 	(timer_tracker::timer_tracker): Distinguish ttstart case. | ||||
| 	(timer_tracker::~timer_tracker): New destructor.  Clean out events, and | ||||
| 	reset magic. | ||||
| 	(timer_tracker::init_muto): New method. | ||||
| 	(to_us): Round up as per POSIX. | ||||
| 	(timer_thread): Reorganize to match timer_tracker::settime and | ||||
| 	timer_tracker::gettime.  Call sig_send without wait.  Call | ||||
| 	auto_release. | ||||
| 	(timer_tracker::settime): Reorganize logic to avoid race.  Call gettime | ||||
| 	to recover old value. | ||||
| 	(timer_tracker::gettime): New method. | ||||
| 	(timer_create): Properly set errno on invalid timerid.  Use new | ||||
| 	lock_timer_tracker method. | ||||
| 	(timer_delete): Ditto.  Simplify code slightly. | ||||
| 	(timer_gettime): New function. | ||||
| 	(fixup_timers_after_fork): Reinit ttstart. | ||||
| 	(getitimer): New implementation. | ||||
| 	(setitimer): Ditto. | ||||
| 	(ualarm): Ditto. | ||||
| 	(alarm): Ditto. | ||||
| 	* cygwin.din: Export timer_gettime. | ||||
| 	* winsup.h: Remove has has_visible_window_station declaration. | ||||
|  | ||||
| 2005-03-26  Christopher Faylor  <cgf@timesys.com> | ||||
|  | ||||
| 	* Makefile.in (DLL_OFILES): Add lsearch.o. | ||||
| 	* cygthread.h (cygthread::notify_detached): New element. | ||||
| 	(cygthread::cygthread): Take optional fourth argument signifying event | ||||
| 	to signal on thread completion. | ||||
| 	* cygthread.cc (cygthread::stub): Signal notify_detached event, if it | ||||
| 	exists. | ||||
| 	(cygthread::cygthread): Initialize notify_detached from fourth argument. | ||||
| 	(cygthread::detach): Wait for notify_detached field is present. | ||||
|  | ||||
| 	* lsearch.cc: New file. | ||||
| 	* search.h: Ditto. | ||||
| 	* include/cygwin/version.h: Bump API minor number to 126. | ||||
| 	* cygwin.din: Export lsearch, lfind. | ||||
|  | ||||
| 2005-03-23  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* fhandler.h (fhandler_socket::secret_event): Remove. | ||||
|   | ||||
| @@ -117,7 +117,7 @@ MALLOC_OFILES=@MALLOC_OFILES@ | ||||
| DLL_IMPORTS:=$(w32api_lib)/libkernel32.a $(w32api_lib)/libadvapi32.a | ||||
|  | ||||
| MT_SAFE_OBJECTS:= | ||||
| # Please maintain this list in sorted order, with maximum files per 85 col line | ||||
| # Please maintain this list in sorted order, with maximum files per 86 col line | ||||
| # | ||||
| DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \ | ||||
| 	cygtls.o dcrt0.o debug.o delqueue.o devices.o dir.o dlfcn.o dll_init.o \ | ||||
| @@ -129,8 +129,8 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \ | ||||
| 	fhandler_socket.o fhandler_tape.o fhandler_termios.o \ | ||||
| 	fhandler_tty.o fhandler_virtual.o fhandler_windows.o fhandler_zero.o \ | ||||
| 	flock.o fnmatch.o fork.o getopt.o glob.o grp.o heap.o hookapi.o \ | ||||
| 	init.o ioctl.o ipc.o iruserok.o localtime.o malloc_wrapper.o miscfuncs.o \ | ||||
| 	mmap.o msg.o net.o netdb.o ntea.o passwd.o path.o pinfo.o pipe.o \ | ||||
| 	init.o ioctl.o ipc.o iruserok.o localtime.o lsearch.o malloc_wrapper.o \ | ||||
| 	miscfuncs.o mmap.o msg.o net.o netdb.o ntea.o passwd.o path.o pinfo.o pipe.o \ | ||||
| 	poll.o pthread.o regcomp.o regerror.o regexec.o regfree.o \ | ||||
| 	registry.o resource.o scandir.o sched.o sec_acl.o sec_helper.o security.o \ | ||||
| 	select.o sem.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \ | ||||
|   | ||||
| @@ -26,7 +26,7 @@ DWORD NO_COPY cygthread::main_thread_id; | ||||
| bool NO_COPY cygthread::exiting; | ||||
|  | ||||
| /* Initial stub called by cygthread constructor. Performs initial | ||||
|    per-thread initialization and loops waiting for new thread functions | ||||
|    per-thread initialization and loops waiting for another thread function | ||||
|    to execute.  */ | ||||
| DWORD WINAPI | ||||
| cygthread::stub (VOID *arg) | ||||
| @@ -73,10 +73,11 @@ cygthread::stub (VOID *arg) | ||||
| 	  info->func (info->arg == cygself ? info : info->arg); | ||||
| 	  /* ...so the above should always return */ | ||||
|  | ||||
| 	  HANDLE notify = info->notify_detached; | ||||
| 	  /* If func is NULL, the above function has set that to indicate | ||||
| 	     that it doesn't want to alert anyone with a SetEvent and should | ||||
| 	     just be marked as no longer inuse.  Hopefully the function knows | ||||
| 	     that it is doing.  */ | ||||
| 	     what it is doing.  */ | ||||
| 	  if (!info->func) | ||||
| 	    info->release (false); | ||||
| 	  else | ||||
| @@ -88,6 +89,8 @@ cygthread::stub (VOID *arg) | ||||
| 	      info->__name = NULL; | ||||
| 	      SetEvent (info->ev); | ||||
| 	    } | ||||
| 	  if (notify) | ||||
| 	    SetEvent (notify); | ||||
| 	} | ||||
|       switch (WaitForSingleObject (info->thread_sync, INFINITE)) | ||||
| 	{ | ||||
| @@ -161,8 +164,8 @@ out: | ||||
| } | ||||
|  | ||||
| cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param, | ||||
| 		      const char *name): __name (name), | ||||
| 					 func (start), arg (param) | ||||
| 		      const char *name, HANDLE notify) | ||||
|  : __name (name), func (start), arg (param), notify_detached (notify) | ||||
| { | ||||
|   thread_printf ("name %s, id %p", name, id); | ||||
|   if (h) | ||||
| @@ -310,7 +313,9 @@ cygthread::detach (HANDLE sigwait) | ||||
|       DWORD res; | ||||
|  | ||||
|       if (!sigwait) | ||||
| 	res = WaitForSingleObject (*this, INFINITE); | ||||
| 	/* If the caller specified a special handle for notification, wait for that. | ||||
| 	   This assumes that the thread in question is auto releasing. */ | ||||
| 	res = WaitForSingleObject (notify_detached ?: *this, INFINITE); | ||||
|       else | ||||
| 	{ | ||||
| 	  /* Lower our priority and give priority to the read thread */ | ||||
|   | ||||
| @@ -26,6 +26,7 @@ class cygthread | ||||
|   VOID *arg; | ||||
|   bool is_freerange; | ||||
|   static bool exiting; | ||||
|   HANDLE notify_detached; | ||||
|  public: | ||||
|   bool terminate_thread (); | ||||
|   static DWORD WINAPI stub (VOID *); | ||||
| @@ -34,7 +35,7 @@ class cygthread | ||||
|   static const char * name (DWORD = 0); | ||||
|   void auto_release () {func = NULL;} | ||||
|   void release (bool); | ||||
|   cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *); | ||||
|   cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *, HANDLE = NULL); | ||||
|   cygthread () {}; | ||||
|   static void init (); | ||||
|   bool detach (HANDLE = NULL); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* cygtls.cc | ||||
|  | ||||
|    Copyright 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
| This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
|   | ||||
| @@ -821,6 +821,7 @@ ldexpf NOSIGFE | ||||
| _ldexpf = ldexpf NOSIGFE | ||||
| ldiv NOSIGFE | ||||
| _ldiv = ldiv NOSIGFE | ||||
| lfind NOSIGFE | ||||
| lgamma NOSIGFE | ||||
| _lgamma = lgamma NOSIGFE | ||||
| lgamma_r NOSIGFE | ||||
| @@ -866,6 +867,7 @@ lrint NOSIGFE | ||||
| lrintf NOSIGFE | ||||
| lround NOSIGFE | ||||
| lroundf NOSIGFE | ||||
| lsearch NOSIGFE | ||||
| lseek SIGFE | ||||
| _lseek = lseek SIGFE | ||||
| _lseek64 = lseek64 SIGFE | ||||
| @@ -1436,6 +1438,7 @@ time SIGFE | ||||
| _time = time SIGFE | ||||
| timer_create SIGFE | ||||
| timer_delete SIGFE | ||||
| timer_gettime SIGFE | ||||
| timer_settime SIGFE | ||||
| times SIGFE | ||||
| _times = times SIGFE | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* debug.cc | ||||
|  | ||||
|    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
| This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
|   | ||||
| @@ -10,6 +10,8 @@ Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include "winsup.h" | ||||
| #include <wingdi.h> | ||||
| #include <winuser.h> | ||||
| #include <imagehlp.h> | ||||
| #include <stdlib.h> | ||||
| #include <setjmp.h> | ||||
| @@ -782,6 +784,27 @@ out: | ||||
|   return interrupted; | ||||
| } | ||||
|  | ||||
| static inline bool | ||||
| has_visible_window_station () | ||||
| { | ||||
|   HWINSTA station_hdl; | ||||
|   USEROBJECTFLAGS uof; | ||||
|   DWORD len; | ||||
|  | ||||
|   /* Check if the process is associated with a visible window station. | ||||
|      These are processes running on the local desktop as well as processes | ||||
|      running in terminal server sessions. | ||||
|      Processes running in a service session not explicitely associated | ||||
|      with the desktop (using the "Allow service to interact with desktop" | ||||
|      property) are running in an invisible window station. */ | ||||
|   if ((station_hdl = GetProcessWindowStation ()) | ||||
|       && GetUserObjectInformationA (station_hdl, UOI_FLAGS, &uof, | ||||
| 				    sizeof uof, &len) | ||||
|       && (uof.dwFlags & WSF_VISIBLE)) | ||||
|     return true; | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| /* Keyboard interrupt handler.  */ | ||||
| static BOOL WINAPI | ||||
| ctrl_c_handler (DWORD type) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* external.cc: Interface to Cygwin internals from external programs. | ||||
|  | ||||
|    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
|    Written by Christopher Faylor <cgf@cygnus.com> | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* fhandler_dev_clipboard: code to access /dev/clipboard | ||||
|  | ||||
|    Copyright 2000, 2001, 2002, 2003, 2004 Red Hat, Inc | ||||
|    Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc | ||||
|  | ||||
|    Written by Charles Wilson (cwilson@ece.gatech.edu) | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* fhandler_mem.cc.  See fhandler.h for a description of the fhandler classes. | ||||
|  | ||||
|    Copyright 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
|    This file is part of Cygwin. | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* fhandler_raw.cc.  See fhandler.h for a description of the fhandler classes. | ||||
|  | ||||
|    Copyright 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
|    This file is part of Cygwin. | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* fhandler_serial.cc | ||||
|  | ||||
|    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* fhandler_tape.cc.  See fhandler.h for a description of the fhandler | ||||
|    classes. | ||||
|  | ||||
|    Copyright 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* fhandler_termios.cc | ||||
|  | ||||
|    Copyright 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* fhandler_windows.cc: code to access windows message queues. | ||||
|  | ||||
|    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
|    Written by Sergey S. Okhapkin (sos@prospect.com.ru). | ||||
|    Feedback and testing by Andy Piper (andyp@parallax.co.uk). | ||||
|   | ||||
| @@ -252,12 +252,13 @@ details. */ | ||||
|       123: Export utmpxname. | ||||
|       124: Add MAP_AUTOGROW flag to mmap. | ||||
|       125: LD_PRELOAD/CW_HOOK available. | ||||
|       126: Add lsearch, lfind, timer_gettime. | ||||
|      */ | ||||
|  | ||||
|      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ | ||||
|  | ||||
| #define CYGWIN_VERSION_API_MAJOR 0 | ||||
| #define CYGWIN_VERSION_API_MINOR 125 | ||||
| #define CYGWIN_VERSION_API_MINOR 126 | ||||
|  | ||||
|      /* There is also a compatibity version number associated with the | ||||
| 	shared memory regions.  It is incremented when incompatible | ||||
|   | ||||
							
								
								
									
										64
									
								
								winsup/cygwin/include/search.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								winsup/cygwin/include/search.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| /*- | ||||
|  * Written by J.T. Conklin <jtc@netbsd.org> | ||||
|  * Public domain. | ||||
|  * | ||||
|  *	$NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ | ||||
|  * $FreeBSD: src/include/search.h,v 1.10 2002/10/16 14:29:23 robert Exp $ | ||||
|  */ | ||||
|  | ||||
| #ifndef _SEARCH_H_ | ||||
| #define _SEARCH_H_ | ||||
|  | ||||
| #include <sys/cdefs.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| typedef	struct entry | ||||
| { | ||||
|   char *key; | ||||
|   void *data; | ||||
| } ENTRY; | ||||
|  | ||||
| typedef	enum | ||||
| { | ||||
|   FIND, ENTER | ||||
| } ACTION; | ||||
|  | ||||
| typedef	enum | ||||
| { | ||||
|   preorder, | ||||
|   postorder, | ||||
|   endorder, | ||||
|   leaf | ||||
| } VISIT; | ||||
|  | ||||
| #ifdef _SEARCH_PRIVATE | ||||
| typedef	struct node | ||||
| { | ||||
|   char *key; | ||||
|   struct node *llink, *rlink; | ||||
| } node_t; | ||||
|  | ||||
| struct que_elem | ||||
| { | ||||
|   struct que_elem *next; | ||||
|   struct que_elem *prev; | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| __BEGIN_DECLS | ||||
| int  hcreate (size_t); | ||||
| void  hdestroy (void); | ||||
| ENTRY *hsearch (ENTRY, ACTION); | ||||
| void *lfind (const void *, const void *, size_t *, size_t, | ||||
| 	     int (*) (const void *, const void *)); | ||||
| void *lsearch (const void *, void *, size_t *, size_t, | ||||
| 	       int (*) (const void *, const void *)); | ||||
| void *tdelete (const void * __restrict, void ** __restrict, | ||||
| 	       int (*) (const void *, const void *)); | ||||
| void *tfind (const void *, void * const *, | ||||
| 	     int (*) (const void *, const void *)); | ||||
| void *tsearch (const void *, void **, int (*) (const void *, const void *)); | ||||
| void  twalk (const void *, void (*) (const void *, VISIT, int)); | ||||
| __END_DECLS | ||||
|  | ||||
| #endif /* !_SEARCH_H_ */ | ||||
							
								
								
									
										56
									
								
								winsup/cygwin/lsearch.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								winsup/cygwin/lsearch.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| /* Initial implementation: | ||||
|    Copyright (c) 2002 Robert Drehmel | ||||
|    All rights reserved. | ||||
|    | ||||
|    As long as the above copyright statement and this notice remain | ||||
|    unchanged, you can do what ever you want with this file.  */ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/cdefs.h> | ||||
| #define	_SEARCH_PRIVATE | ||||
| #include <search.h> | ||||
| #include <stdint.h>	/* for uint8_t */ | ||||
| #include <stdlib.h>	/* for NULL */ | ||||
| #include <string.h>	/* for memcpy () prototype */ | ||||
|  | ||||
| static void *lwork (const void *, const void *, size_t *, size_t, | ||||
| 		    int (*) (const void *, const void *), int); | ||||
|  | ||||
| extern "C" void * | ||||
| lsearch (const void *key, void *base, size_t *nelp, size_t width, | ||||
| 	       int (*compar) (const void *, const void *)) | ||||
| { | ||||
|   return lwork (key, base, nelp, width, compar, 1); | ||||
| } | ||||
|  | ||||
| extern "C" void * | ||||
| lfind (const void *key, const void *base, size_t *nelp, size_t width, | ||||
| 	     int (*compar) (const void *, const void *)) | ||||
| { | ||||
|   return lwork (key, base, nelp, width, compar, 0); | ||||
| } | ||||
|  | ||||
| static void * | ||||
| lwork (const void *key, const void *base, size_t *nelp, size_t width, | ||||
|        int (*compar) (const void *, const void *), int addelem) | ||||
| { | ||||
|   uint8_t *ep, *endp; | ||||
|  | ||||
|   /*  Cast to an integer value first to avoid the warning for removing | ||||
|      'const' via a cast.  */ | ||||
|   ep = (uint8_t *) (uintptr_t)base; | ||||
|   for (endp = (uint8_t *) (ep + width * *nelp); ep < endp; ep += width) | ||||
|     if (compar (key, ep) == 0) | ||||
|       return ep; | ||||
|  | ||||
|   /* lfind () shall return when the key was not found. */ | ||||
|   if (!addelem) | ||||
|     return NULL; | ||||
|  | ||||
|   /* lsearch () adds the key to the end of the table and increments | ||||
|      the number of elements.  */ | ||||
|   memcpy (endp, key, width); | ||||
|   ++*nelp; | ||||
|  | ||||
|   return endp; | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* security.cc: NT security functions | ||||
|  | ||||
|    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
|    Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de | ||||
|    Completely rewritten by Corinna Vinschen <corinna@vinschen.de> | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
|    which is intended to operate similarly to a mutex but attempts to | ||||
|    avoid making expensive calls to the kernel. | ||||
|  | ||||
|    Copyright 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
|    Written by Christopher Faylor <cgf@cygnus.com> | ||||
|  | ||||
|   | ||||
| @@ -22,27 +22,61 @@ details. */ | ||||
| #define TT_MAGIC 0x513e4a1c | ||||
| struct timer_tracker | ||||
| { | ||||
|   static muto *protect; | ||||
|   unsigned magic; | ||||
|   clockid_t clock_id; | ||||
|   sigevent evp; | ||||
|   itimerspec it; | ||||
|   timespec it_interval; | ||||
|   HANDLE cancel; | ||||
|   int flags; | ||||
|   HANDLE syncthread; | ||||
|   long long interval_us; | ||||
|   long long sleepto_us; | ||||
|   cygthread *th; | ||||
|   struct timer_tracker *next; | ||||
|   int settime (int, const itimerspec *, itimerspec *); | ||||
|   void gettime (itimerspec *); | ||||
|   timer_tracker (clockid_t, const sigevent *); | ||||
|   timer_tracker (); | ||||
|   timer_tracker () {}; | ||||
|   ~timer_tracker (); | ||||
|   friend void fixup_timers_after_fork (); | ||||
| }; | ||||
|  | ||||
| timer_tracker ttstart; | ||||
| timer_tracker NO_COPY ttstart; | ||||
|  | ||||
| muto *timer_tracker::protect; | ||||
|  | ||||
| timer_tracker::timer_tracker () | ||||
| class lock_timer_tracker | ||||
| { | ||||
|   new_muto (protect); | ||||
|   static muto *protect; | ||||
| public: | ||||
|   lock_timer_tracker (); | ||||
|   ~lock_timer_tracker (); | ||||
| }; | ||||
|  | ||||
| muto NO_COPY *lock_timer_tracker::protect; | ||||
|  | ||||
| lock_timer_tracker::lock_timer_tracker () | ||||
| { | ||||
|   new_muto (protect)->acquire (); | ||||
| } | ||||
|  | ||||
| lock_timer_tracker::~lock_timer_tracker () | ||||
| { | ||||
|   protect->release (); | ||||
| } | ||||
|  | ||||
| timer_tracker::~timer_tracker () | ||||
| { | ||||
|   if (cancel) | ||||
|     { | ||||
|       SetEvent (cancel); | ||||
|       th->detach (); | ||||
|       CloseHandle (cancel); | ||||
| #ifdef DEBUGGING | ||||
|       th = NULL; | ||||
|       cancel = NULL; | ||||
| #endif | ||||
|     } | ||||
|   if (syncthread) | ||||
|     CloseHandle (syncthread); | ||||
|   magic = 0; | ||||
| } | ||||
|  | ||||
| timer_tracker::timer_tracker (clockid_t c, const sigevent *e) | ||||
| @@ -56,84 +90,83 @@ timer_tracker::timer_tracker (clockid_t c, const sigevent *e) | ||||
|       evp.sigev_value.sival_ptr = this; | ||||
|     } | ||||
|   clock_id = c; | ||||
|   cancel = NULL; | ||||
|   flags = 0; | ||||
|   memset (&it, 0, sizeof (it)); | ||||
|   protect->acquire (); | ||||
|   next = ttstart.next; | ||||
|   ttstart.next = this; | ||||
|   protect->release (); | ||||
|   magic = TT_MAGIC; | ||||
|   if (this != &ttstart) | ||||
|     { | ||||
|       cancel = NULL; | ||||
|       lock_timer_tracker here; | ||||
|       next = ttstart.next; | ||||
|       ttstart.next = this; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static long long | ||||
| to_us (timespec& ts) | ||||
| to_us (const timespec& ts) | ||||
| { | ||||
|   long long res = ts.tv_sec; | ||||
|   res *= 1000000; | ||||
|   res += ts.tv_nsec / 1000 + ((ts.tv_nsec % 1000) >= 500 ? 1 : 0); | ||||
|   res += ts.tv_nsec / 1000 + ((ts.tv_nsec % 1000) ? 1 : 0); | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| static NO_COPY itimerspec itzero; | ||||
| static NO_COPY timespec tzero; | ||||
|  | ||||
| static DWORD WINAPI | ||||
| timer_thread (VOID *x) | ||||
| { | ||||
|   timer_tracker *tp = ((timer_tracker *) x); | ||||
|   timer_tracker tt = *tp; | ||||
|   for (bool first = true; ; first = false) | ||||
|   timer_tracker *tt = ((timer_tracker *) x); | ||||
|   long long now; | ||||
|   long long sleepto_us =  tt->sleepto_us; | ||||
|   while (1) | ||||
|     { | ||||
|       long long sleep_us = to_us (first ? tt.it.it_value : tt.it.it_interval); | ||||
|       long long sleep_to = sleep_us; | ||||
|       long long now = gtod.usecs (false); | ||||
|       if (tt.flags & TIMER_ABSTIME) | ||||
| 	sleep_us -= now; | ||||
|       long long sleep_us; | ||||
|       long sleep_ms; | ||||
|       /* Account for delays in starting thread | ||||
|         and sending the signal */ | ||||
|       now = gtod.usecs (false); | ||||
|       sleep_us = sleepto_us - now; | ||||
|       if (sleep_us > 0) | ||||
| 	{ | ||||
| 	  tt->sleepto_us = sleepto_us; | ||||
| 	  sleep_ms = (sleep_us + 999) / 1000; | ||||
| 	} | ||||
|       else | ||||
| 	sleep_to += now; | ||||
| 	{ | ||||
| 	  tt->sleepto_us = now; | ||||
| 	  sleep_ms = 0; | ||||
| 	} | ||||
|  | ||||
|       DWORD sleep_ms = (sleep_us < 0) ? 0 : (sleep_us / 1000); | ||||
|       debug_printf ("%p waiting for %u ms, first %d", x, sleep_ms, first); | ||||
|       tp->it.it_value = tzero; | ||||
|       switch (WaitForSingleObject (tt.cancel, sleep_ms)) | ||||
|       debug_printf ("%p waiting for %u ms", x, sleep_ms); | ||||
|       switch (WaitForSingleObject (tt->cancel, sleep_ms)) | ||||
| 	{ | ||||
| 	case WAIT_TIMEOUT: | ||||
| 	  debug_printf ("timed out"); | ||||
| 	  break; | ||||
| 	case WAIT_OBJECT_0: | ||||
| 	  now = gtod.usecs (false); | ||||
| 	  sleep_us = sleep_to - now; | ||||
| 	  if (sleep_us < 0) | ||||
| 	    sleep_us = 0; | ||||
| 	  tp->it.it_value.tv_sec = sleep_us / 1000000; | ||||
| 	  tp->it.it_value.tv_nsec = (sleep_us % 1000000) * 1000; | ||||
| 	  debug_printf ("%p cancelled, elapsed %D", x, sleep_us); | ||||
| 	  debug_printf ("%p cancelled", x); | ||||
| 	  goto out; | ||||
| 	default: | ||||
| 	  debug_printf ("%p timer wait failed, %E", x); | ||||
| 	  debug_printf ("%p wait failed, %E", x); | ||||
| 	  goto out; | ||||
| 	} | ||||
|  | ||||
|       switch (tt.evp.sigev_notify) | ||||
|       switch (tt->evp.sigev_notify) | ||||
| 	{ | ||||
| 	case SIGEV_SIGNAL: | ||||
| 	  { | ||||
| 	    siginfo_t si; | ||||
| 	    memset (&si, 0, sizeof (si)); | ||||
| 	    si.si_signo = tt.evp.sigev_signo; | ||||
| 	    si.si_sigval.sival_ptr = tt.evp.sigev_value.sival_ptr; | ||||
| 	    debug_printf ("%p sending sig %d", x, tt.evp.sigev_signo); | ||||
| 	    sig_send (NULL, si); | ||||
| 	    si.si_signo = tt->evp.sigev_signo; | ||||
| 	    si.si_sigval.sival_ptr = tt->evp.sigev_value.sival_ptr; | ||||
| 	    debug_printf ("%p sending sig %d", x, tt->evp.sigev_signo); | ||||
| 	    sig_send (myself_nowait, si); | ||||
| 	    break; | ||||
| 	  } | ||||
| 	case SIGEV_THREAD: | ||||
| 	  { | ||||
| 	    pthread_t notify_thread; | ||||
| 	    debug_printf ("%p starting thread", x); | ||||
| 	    int rc = pthread_create (¬ify_thread, tt.evp.sigev_notify_attributes, | ||||
| 				     (void * (*) (void *)) tt.evp.sigev_notify_function, | ||||
| 				     tt.evp.sigev_value.sival_ptr); | ||||
| 	    int rc = pthread_create (¬ify_thread, tt->evp.sigev_notify_attributes, | ||||
| 				     (void * (*) (void *)) tt->evp.sigev_notify_function, | ||||
| 				     tt->evp.sigev_value.sival_ptr); | ||||
| 	    if (rc) | ||||
| 	      { | ||||
| 		debug_printf ("thread creation failed, %E"); | ||||
| @@ -143,17 +176,15 @@ timer_thread (VOID *x) | ||||
| 	    break; | ||||
| 	  } | ||||
| 	} | ||||
|       if (!tt.it.it_interval.tv_sec && !tt.it.it_interval.tv_nsec) | ||||
|       if (!tt->interval_us) | ||||
| 	break; | ||||
|       tt.flags = 0; | ||||
|  | ||||
|       sleepto_us = tt->sleepto_us + tt->interval_us; | ||||
|       debug_printf ("looping"); | ||||
|     } | ||||
|  | ||||
| out: | ||||
|   CloseHandle (tt.cancel); | ||||
|   // FIXME: race here but is it inevitable? | ||||
|   if (tt.cancel == tp->cancel) | ||||
|     tp->cancel = NULL; | ||||
|   _my_tls._ctinfo->auto_release ();     /* automatically return the cygthread to the cygthread pool */ | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -177,48 +208,83 @@ timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalu | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   if (__check_invalid_read_ptr_errno (value, sizeof (*value))) | ||||
|   if (__check_invalid_read_ptr_errno (value, sizeof (*value)) | ||||
|       || it_bad (value->it_value) | ||||
|       || it_bad (value->it_interval) | ||||
|       || (ovalue && check_null_invalid_struct_errno (ovalue))) | ||||
|     return -1; | ||||
|  | ||||
|   if (ovalue && check_null_invalid_struct_errno (ovalue)) | ||||
|     return -1; | ||||
|   long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs (false); | ||||
|  | ||||
|   itimerspec *elapsed; | ||||
|   if (!cancel) | ||||
|     elapsed = &itzero; | ||||
|   else | ||||
|   lock_timer_tracker here; | ||||
|   if (cancel) | ||||
|     { | ||||
|       SetEvent (cancel);	// should be closed when the thread exits | ||||
|       th->detach (); | ||||
|       elapsed = ⁢ | ||||
|     } | ||||
|  | ||||
|   if (ovalue) | ||||
|     *ovalue = *elapsed; | ||||
|     gettime (ovalue); | ||||
|  | ||||
|   if (value->it_value.tv_sec || value->it_value.tv_nsec) | ||||
|     { | ||||
|       if (it_bad (value->it_value)) | ||||
| 	return -1; | ||||
|       if (it_bad (value->it_interval)) | ||||
| 	return -1; | ||||
|       flags = in_flags; | ||||
|       cancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); | ||||
|       it = *value; | ||||
|       th = new cygthread (timer_thread, this, "itimer"); | ||||
|       sleepto_us = now + to_us (value->it_value); | ||||
|       interval_us = to_us (value->it_interval); | ||||
|       it_interval = value->it_interval; | ||||
|       if (!cancel) | ||||
| 	cancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); | ||||
|       else | ||||
| 	ResetEvent (cancel); | ||||
|       if (!syncthread) | ||||
| 	syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); | ||||
|       else | ||||
| 	ResetEvent (syncthread); | ||||
|       th = new cygthread (timer_thread, this, "itimer", syncthread); | ||||
|     } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void | ||||
| timer_tracker::gettime (itimerspec *ovalue) | ||||
| { | ||||
|   if (!cancel) | ||||
|     memset (ovalue, 0, sizeof (*ovalue)); | ||||
|   else | ||||
|     { | ||||
|       ovalue->it_interval = it_interval; | ||||
|       long long now = gtod.usecs (false); | ||||
|       long long left_us = sleepto_us - now; | ||||
|       if (left_us < 0) | ||||
|        left_us = 0; | ||||
|       ovalue->it_value.tv_sec = left_us / 1000000; | ||||
|       ovalue->it_value.tv_nsec = (left_us % 1000000) * 1000; | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| timer_gettime (timer_t timerid, struct itimerspec *ovalue) | ||||
| { | ||||
|   if (check_null_invalid_struct_errno (ovalue)) | ||||
|     return -1; | ||||
|  | ||||
|   timer_tracker *tt = (timer_tracker *) timerid; | ||||
|   if (check_null_invalid_struct (tt) || tt->magic != TT_MAGIC) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   tt->gettime (ovalue); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid) | ||||
| { | ||||
|   if (evp && check_null_invalid_struct_errno (evp)) | ||||
|   if (evp && check_null_invalid_struct_errno (evp) | ||||
|       || check_null_invalid_struct_errno (timerid)) | ||||
|     return -1; | ||||
|   if (check_null_invalid_struct_errno (timerid)) | ||||
|     return -1; | ||||
|  | ||||
|   if (clock_id != CLOCK_REALTIME) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
| @@ -234,8 +300,12 @@ timer_settime (timer_t timerid, int flags, const struct itimerspec *value, | ||||
| 	       struct itimerspec *ovalue) | ||||
| { | ||||
|   timer_tracker *tt = (timer_tracker *) timerid; | ||||
|   if (check_null_invalid_struct_errno (tt) || tt->magic != TT_MAGIC) | ||||
|     return -1; | ||||
|   if (check_null_invalid_struct (tt) || tt->magic != TT_MAGIC) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   return tt->settime (flags, value, ovalue); | ||||
| } | ||||
|  | ||||
| @@ -243,21 +313,20 @@ extern "C" int | ||||
| timer_delete (timer_t timerid) | ||||
| { | ||||
|   timer_tracker *in_tt = (timer_tracker *) timerid; | ||||
|   if (check_null_invalid_struct_errno (in_tt) || in_tt->magic != TT_MAGIC) | ||||
|     return -1; | ||||
|   if (check_null_invalid_struct (in_tt) || in_tt->magic != TT_MAGIC) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   timer_tracker::protect->acquire (); | ||||
|   lock_timer_tracker here; | ||||
|   for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next) | ||||
|     if (tt->next == in_tt) | ||||
|       { | ||||
| 	timer_tracker *deleteme = tt->next; | ||||
| 	tt->next = deleteme->next; | ||||
| 	delete deleteme; | ||||
| 	timer_tracker::protect->release (); | ||||
| 	tt->next = in_tt->next; | ||||
| 	delete in_tt; | ||||
| 	return 0; | ||||
|       } | ||||
|   timer_tracker::protect->release (); | ||||
|  | ||||
|   set_errno (EINVAL); | ||||
|   return 0; | ||||
| } | ||||
| @@ -265,10 +334,104 @@ timer_delete (timer_t timerid) | ||||
| void | ||||
| fixup_timers_after_fork () | ||||
| { | ||||
|   ttstart.cancel = ttstart.syncthread = NULL; | ||||
|   for (timer_tracker *tt = &ttstart; tt->next != NULL; /* nothing */) | ||||
|     { | ||||
|       timer_tracker *deleteme = tt->next; | ||||
|       tt->next = deleteme->next; | ||||
|       deleteme->cancel = deleteme->syncthread = NULL; | ||||
|       delete deleteme; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| extern "C" int | ||||
| setitimer (int which, const struct itimerval *value, struct itimerval *ovalue) | ||||
| { | ||||
|   if (which != ITIMER_REAL) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|   struct itimerspec spec_value, spec_ovalue; | ||||
|   int ret; | ||||
|   spec_value.it_interval.tv_sec = value->it_interval.tv_sec; | ||||
|   spec_value.it_interval.tv_nsec = value->it_interval.tv_usec * 1000; | ||||
|   spec_value.it_value.tv_sec = value->it_value.tv_sec; | ||||
|   spec_value.it_value.tv_nsec = value->it_value.tv_usec * 1000; | ||||
|   ret = timer_settime ((timer_t) &ttstart, 0, &spec_value, &spec_ovalue); | ||||
|   if (!ret && ovalue) | ||||
|     { | ||||
|       ovalue->it_interval.tv_sec = spec_ovalue.it_interval.tv_sec; | ||||
|       ovalue->it_interval.tv_usec = spec_ovalue.it_interval.tv_nsec / 1000; | ||||
|       ovalue->it_value.tv_sec = spec_ovalue.it_value.tv_sec; | ||||
|       ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000; | ||||
|     } | ||||
|   syscall_printf ("%d = setitimer ()", ret); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| extern "C" int | ||||
| getitimer (int which, struct itimerval *ovalue) | ||||
| { | ||||
|   if (which != ITIMER_REAL) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|   if (ovalue == NULL) | ||||
|     { | ||||
|       set_errno (EFAULT); | ||||
|       return -1; | ||||
|     } | ||||
|   struct itimerspec spec_ovalue; | ||||
|   int ret = timer_gettime ((timer_t) &ttstart, &spec_ovalue); | ||||
|   if (!ret) | ||||
|     { | ||||
|       ovalue->it_interval.tv_sec = spec_ovalue.it_interval.tv_sec; | ||||
|       ovalue->it_interval.tv_usec = spec_ovalue.it_interval.tv_nsec / 1000; | ||||
|       ovalue->it_value.tv_sec = spec_ovalue.it_value.tv_sec; | ||||
|       ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000; | ||||
|     } | ||||
|   syscall_printf ("%d = getitimer ()", ret); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| /* FIXME: POSIX - alarm survives exec */ | ||||
| extern "C" unsigned int | ||||
| alarm (unsigned int seconds) | ||||
| { | ||||
|  struct itimerspec newt = {}, oldt; | ||||
|  /* alarm cannot fail, but only needs not be | ||||
|     correct for arguments < 64k. Truncate */ | ||||
|  if (seconds > (HIRES_DELAY_MAX / 1000 - 1)) | ||||
|    seconds = (HIRES_DELAY_MAX / 1000 - 1); | ||||
|  newt.it_value.tv_sec = seconds; | ||||
|  timer_settime ((timer_t) &ttstart, 0, &newt, &oldt); | ||||
|  int ret = oldt.it_value.tv_sec + (oldt.it_value.tv_nsec > 0); | ||||
|  syscall_printf ("%d = alarm (%d)", ret, seconds); | ||||
|  return ret; | ||||
| } | ||||
|  | ||||
| extern "C" useconds_t | ||||
| ualarm (useconds_t value, useconds_t interval) | ||||
| { | ||||
|  struct itimerspec timer = {}, otimer; | ||||
|  /* ualarm cannot fail. | ||||
|     Interpret negative arguments as zero */ | ||||
|  if (value > 0) | ||||
|    { | ||||
|      timer.it_value.tv_sec = (unsigned int) value / 1000000; | ||||
|      timer.it_value.tv_nsec = ((unsigned int) value % 1000000) * 1000; | ||||
|    } | ||||
|  if (interval > 0) | ||||
|    { | ||||
|      timer.it_interval.tv_sec = (unsigned int) interval / 1000000; | ||||
|      timer.it_interval.tv_nsec = ((unsigned int) interval % 1000000) * 1000; | ||||
|    } | ||||
|  timer_settime ((timer_t) &ttstart, 0, &timer, &otimer); | ||||
|  useconds_t ret = otimer.it_value.tv_sec * 1000000 + (otimer.it_value.tv_nsec + 999) / 1000; | ||||
|  syscall_printf ("%d = ualarm (%d , %d)", ret, value, interval); | ||||
|  return ret; | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* window.cc: hidden windows for signals/itimer support | ||||
|  | ||||
|    Copyright 1997, 1998, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. | ||||
|    Copyright 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. | ||||
|  | ||||
|    Written by Sergey Okhapkin <sos@prospect.com.ru> | ||||
|  | ||||
| @@ -30,12 +30,7 @@ details. */ | ||||
|  | ||||
| wininfo NO_COPY winmsg; | ||||
|  | ||||
| muto NO_COPY *wininfo::lock; | ||||
|  | ||||
| wininfo::wininfo () | ||||
| { | ||||
|   new_muto_name (lock, "!winlock"); | ||||
| } | ||||
| muto NO_COPY *wininfo::_lock; | ||||
|  | ||||
| int __stdcall | ||||
| wininfo::process (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | ||||
| @@ -50,23 +45,6 @@ wininfo::process (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | ||||
|     case WM_DESTROY: | ||||
|       PostQuitMessage (0); | ||||
|       return 0; | ||||
|     case WM_TIMER: | ||||
|       if (wParam == timer_active) | ||||
| 	{ | ||||
| 	  UINT elapse = itv.it_interval.tv_sec * 1000 + | ||||
| 			itv.it_interval.tv_usec / 1000; | ||||
| 	  KillTimer (hwnd, timer_active); | ||||
| 	  if (!elapse) | ||||
| 	    timer_active = 0; | ||||
| 	  else | ||||
| 	    { | ||||
| 	      timer_active = SetTimer (hwnd, 1, elapse, NULL); | ||||
| 	      start_time = GetTickCount (); | ||||
| 	      itv.it_value = itv.it_interval; | ||||
| 	    } | ||||
| 	  raise (SIGALRM); | ||||
| 	} | ||||
|       return 0; | ||||
|     case WM_ASYNCIO: | ||||
|       if (WSAGETSELECTEVENT (lParam) == FD_OOB) | ||||
| 	raise (SIGURG); | ||||
| @@ -92,7 +70,7 @@ wininfo::winthread () | ||||
|   WNDCLASS wc; | ||||
|   static NO_COPY char classname[] = "CygwinWndClass"; | ||||
|  | ||||
|   lock->grab (); | ||||
|   _lock->grab (); | ||||
|   /* Register the window class for the main window. */ | ||||
|  | ||||
|   wc.style = 0; | ||||
| @@ -116,7 +94,7 @@ wininfo::winthread () | ||||
| 			   (LPVOID) NULL); | ||||
|   if (!hwnd) | ||||
|     api_fatal ("couldn't create window, %E"); | ||||
|   lock->release (); | ||||
|   release (); | ||||
|  | ||||
|   while (GetMessage (&msg, hwnd, 0, 0) == TRUE) | ||||
|     DispatchMessage (&msg); | ||||
| @@ -136,156 +114,27 @@ HWND () | ||||
|   if (hwnd) | ||||
|     return hwnd; | ||||
|  | ||||
|   lock->acquire (); | ||||
|   lock (); | ||||
|   if (!hwnd) | ||||
|     { | ||||
|       lock->upforgrabs (); | ||||
|       _lock->upforgrabs (); | ||||
|       cygthread *h = new cygthread (::winthread, this, "win"); | ||||
|       h->SetThreadPriority (THREAD_PRIORITY_HIGHEST); | ||||
|       h->zap_h (); | ||||
|       lock->acquire (); | ||||
|       lock (); | ||||
|     } | ||||
|   lock->release (); | ||||
|   release (); | ||||
|   return hwnd; | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue) | ||||
| void | ||||
| wininfo::lock () | ||||
| { | ||||
|   if (which != ITIMER_REAL) | ||||
|     { | ||||
|       set_errno (ENOSYS); | ||||
|       return -1; | ||||
|     } | ||||
|   return winmsg.setitimer (value, oldvalue); | ||||
|   new_muto (_lock)->acquire (); | ||||
| } | ||||
|  | ||||
| /* FIXME: Very racy */ | ||||
| int __stdcall | ||||
| wininfo::setitimer (const struct itimerval *value, struct itimerval *oldvalue) | ||||
| void | ||||
| wininfo::release () | ||||
| { | ||||
|   /* Check if we will wrap */ | ||||
|   if (itv.it_value.tv_sec >= (long) (UINT_MAX / 1000)) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|   if (timer_active) | ||||
|     { | ||||
|       KillTimer (winmsg, timer_active); | ||||
|       timer_active = 0; | ||||
|     } | ||||
|   if (oldvalue) | ||||
|     *oldvalue = itv; | ||||
|   if (value == NULL) | ||||
|     { | ||||
|       set_errno (EFAULT); | ||||
|       return -1; | ||||
|     } | ||||
|   itv = *value; | ||||
|   UINT elapse = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000; | ||||
|   if (elapse == 0) | ||||
|     if (itv.it_value.tv_usec) | ||||
|       elapse = 1; | ||||
|     else | ||||
|       return 0; | ||||
|   if (!(timer_active = SetTimer (winmsg, 1, elapse, NULL))) | ||||
|     { | ||||
|       __seterrno (); | ||||
|       return -1; | ||||
|     } | ||||
|   start_time = GetTickCount (); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| getitimer (int which, struct itimerval *value) | ||||
| { | ||||
|   if (which != ITIMER_REAL) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|   if (value == NULL) | ||||
|     { | ||||
|       set_errno (EFAULT); | ||||
|       return -1; | ||||
|     } | ||||
|   return winmsg.getitimer (value); | ||||
| } | ||||
|  | ||||
| /* FIXME: racy */ | ||||
| int __stdcall | ||||
| wininfo::getitimer (struct itimerval *value) | ||||
| { | ||||
|   *value = itv; | ||||
|   if (!timer_active) | ||||
|     { | ||||
|       value->it_value.tv_sec = 0; | ||||
|       value->it_value.tv_usec = 0; | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|   UINT elapse, val; | ||||
|  | ||||
|   elapse = GetTickCount () - start_time; | ||||
|   val = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000; | ||||
|   val -= elapse; | ||||
|   value->it_value.tv_sec = val / 1000; | ||||
|   value->it_value.tv_usec = val % 1000; | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| extern "C" unsigned int | ||||
| alarm (unsigned int seconds) | ||||
| { | ||||
|   int ret; | ||||
|   struct itimerval newt, oldt; | ||||
|  | ||||
|   newt.it_value.tv_sec = seconds; | ||||
|   newt.it_value.tv_usec = 0; | ||||
|   newt.it_interval.tv_sec = 0; | ||||
|   newt.it_interval.tv_usec = 0; | ||||
|   setitimer (ITIMER_REAL, &newt, &oldt); | ||||
|   ret = oldt.it_value.tv_sec; | ||||
|   if (ret == 0 && oldt.it_value.tv_usec) | ||||
|     ret = 1; | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| extern "C" useconds_t | ||||
| ualarm (useconds_t value, useconds_t interval) | ||||
| { | ||||
|   struct itimerval timer, otimer; | ||||
|  | ||||
|   timer.it_value.tv_sec = 0; | ||||
|   timer.it_value.tv_usec = value; | ||||
|   timer.it_interval.tv_sec = 0; | ||||
|   timer.it_interval.tv_usec = interval; | ||||
|  | ||||
|   if (setitimer (ITIMER_REAL, &timer, &otimer) < 0) | ||||
|     return (u_int)-1; | ||||
|  | ||||
|   return (otimer.it_value.tv_sec * 1000000) + otimer.it_value.tv_usec; | ||||
| } | ||||
|  | ||||
| bool | ||||
| has_visible_window_station (void) | ||||
| { | ||||
|   HWINSTA station_hdl; | ||||
|   USEROBJECTFLAGS uof; | ||||
|   DWORD len; | ||||
|  | ||||
|   /* Check if the process is associated with a visible window station. | ||||
|      These are processes running on the local desktop as well as processes | ||||
|      running in terminal server sessions. | ||||
|      Processes running in a service session not explicitely associated | ||||
|      with the desktop (using the "Allow service to interact with desktop" | ||||
|      property) are running in an invisible window station. */ | ||||
|   if ((station_hdl = GetProcessWindowStation ()) | ||||
|       && GetUserObjectInformationA (station_hdl, UOI_FLAGS, &uof, | ||||
| 				    sizeof uof, &len) | ||||
|       && (uof.dwFlags & WSF_VISIBLE)) | ||||
|     return true; | ||||
|   return false; | ||||
|   _lock->release (); | ||||
| } | ||||
|   | ||||
| @@ -12,20 +12,13 @@ class muto; | ||||
| class wininfo | ||||
| { | ||||
|   HWND hwnd; | ||||
|   static muto *lock; | ||||
|   static muto *_lock; | ||||
| public: | ||||
|   UINT timer_active; | ||||
|   struct itimerval itv; | ||||
|   DWORD start_time; | ||||
|   HANDLE window_started; | ||||
|   operator HWND (); | ||||
|   int __stdcall wininfo::process (HWND, UINT, WPARAM, LPARAM) | ||||
|     __attribute__ ((regparm (3))); | ||||
|   int __stdcall setitimer (const struct itimerval *value, struct itimerval *oldvalue) | ||||
|     __attribute__ ((regparm (3))); | ||||
|   int __stdcall getitimer (struct itimerval *value) | ||||
|     __attribute__ ((regparm (2))); | ||||
|   wininfo (); | ||||
|   void lock (); | ||||
|   void release (); | ||||
|   DWORD WINAPI winthread () __attribute__ ((regparm (1))); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -223,9 +223,6 @@ void events_terminate (void); | ||||
|  | ||||
| void __stdcall close_all_files (); | ||||
|  | ||||
| /* Check if running in a visible window station. */ | ||||
| extern bool has_visible_window_station (void); | ||||
|  | ||||
| /* Globals that handle initialization of winsock in a child process. */ | ||||
| extern HANDLE wsock32_handle; | ||||
| extern HANDLE ws2_32_handle; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user