diff options
author | Arnaud Charlet <charlet@gcc.gnu.org> | 2014-11-20 12:13:40 +0100 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2014-11-20 12:13:40 +0100 |
commit | 6c802906a388f6816ba641f8ec83ef812ffe8fbd (patch) | |
tree | 935169c8313a4ed8a666888be5c53e913f041f63 /gcc/ada/adaint.c | |
parent | 4b963531a13ebfef4fd889df305d4037e7334fa0 (diff) | |
download | gcc-6c802906a388f6816ba641f8ec83ef812ffe8fbd.zip gcc-6c802906a388f6816ba641f8ec83ef812ffe8fbd.tar.gz gcc-6c802906a388f6816ba641f8ec83ef812ffe8fbd.tar.bz2 |
[multiple changes]
2014-11-20 Pascal Obry <obry@adacore.com>
* initialize.c (ProcListCS): New extern variable (critical section).
(ProcListEvt): New extern variable (handle).
(__gnat_initialize)[Win32]: Initialize the ProcListCS critical
section object and the ProcListEvt event.
* final.c (__gnat_finalize)[Win32]: Properly finalize the
ProcListCS critical section and the ProcListEvt event.
* adaint.c (ProcListEvt): New Win32 event handle.
(EnterCS): New routine to enter the critical section when dealing with
child processes chain list.
(LeaveCS): As above to exit from the critical section.
(SignalListChanged): Routine to signal that the chain process list has
been updated.
(add_handle): Use EnterCS/LeaveCS, also call SignalListChanged when the
handle has been added.
(__gnat_win32_remove_handle): Use EnterCS/LeaveCS,
also call SignalListChanged if the handle has been found and removed.
(remove_handle): Routine removed, implementation merged with the above.
(win32_wait): Use EnterCS/LeaveCS for the critical section. Properly
copy the PID list locally to ensure that even if the list is updated
the local copy remains valid. Add into the hl (handle list) the
ProcListEvt handle. This handle is used to signal that a change has
been made into the process chain list. This is to ensure that a waiting
call can be resumed to take into account new processes. We also make
sure that if the handle was not found into the list we start over
the wait call. Indeed another concurrent call to win32_wait()
could already have handled this process.
2014-11-20 Ed Schonberg <schonberg@adacore.com>
* sem_res.adb (Resolve_Actuals): The legality rule concerning
the use of class-wide actuals for a non-controlling formal are
not rechecked in an instance.
2014-11-20 Pascal Obry <obry@adacore.com>
* g-dirope.ads: Minor typo fix.
2014-11-20 Hristian Kirtchev <kirtchev@adacore.com>
* exp_attr.adb (Expand_N_Attribute_Reference,
Expand_Update_Attribute): Preserve the tag of a prefix by offering
a specific view of the class-wide version of the prefix.
From-SVN: r217837
Diffstat (limited to 'gcc/ada/adaint.c')
-rw-r--r-- | gcc/ada/adaint.c | 108 |
1 files changed, 77 insertions, 31 deletions
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c index cd3f11a3..36a1189 100644 --- a/gcc/ada/adaint.c +++ b/gcc/ada/adaint.c @@ -2311,20 +2311,29 @@ __gnat_number_of_cpus (void) for locking and unlocking tasks since we do not support multiple threads on this configuration (Cert run time on native Windows). */ -static void dummy (void) -{ -} - -void (*Lock_Task) () = &dummy; -void (*Unlock_Task) () = &dummy; +static void EnterCS (void) {} +static void LeaveCS (void) {} +static void SignalListChanged (void) {} #else -#define Lock_Task system__soft_links__lock_task -extern void (*Lock_Task) (void); +CRITICAL_SECTION ProcListCS; +HANDLE ProcListEvt; + +static void EnterCS (void) +{ + EnterCriticalSection(&ProcListCS); +} -#define Unlock_Task system__soft_links__unlock_task -extern void (*Unlock_Task) (void); +static void LeaveCS (void) +{ + LeaveCriticalSection(&ProcListCS); +} + +static void SignalListChanged (void) +{ + SetEvent (ProcListEvt); +} #endif @@ -2335,7 +2344,7 @@ static void add_handle (HANDLE h, int pid) { /* -------------------- critical section -------------------- */ - (*Lock_Task) (); + EnterCS(); if (plist_length == plist_max_length) { @@ -2350,14 +2359,19 @@ add_handle (HANDLE h, int pid) PID_LIST[plist_length] = pid; ++plist_length; - (*Unlock_Task) (); + SignalListChanged(); + LeaveCS(); /* -------------------- critical section -------------------- */ } -static void -remove_handle (HANDLE h, int pid) +int +__gnat_win32_remove_handle (HANDLE h, int pid) { int j; + int found = 0; + + /* -------------------- critical section -------------------- */ + EnterCS(); for (j = 0; j < plist_length; j++) { @@ -2367,21 +2381,18 @@ remove_handle (HANDLE h, int pid) --plist_length; HANDLES_LIST[j] = HANDLES_LIST[plist_length]; PID_LIST[j] = PID_LIST[plist_length]; + found = 1; break; } } -} -void -__gnat_win32_remove_handle (HANDLE h, int pid) -{ + LeaveCS(); /* -------------------- critical section -------------------- */ - (*Lock_Task) (); - remove_handle(h, pid); + if (found) + SignalListChanged(); - (*Unlock_Task) (); - /* -------------------- critical section -------------------- */ + return found; } static void @@ -2466,35 +2477,70 @@ win32_wait (int *status) DWORD exitcode, pid; HANDLE *hl; HANDLE h; + int *pidl; DWORD res; int hl_len; + int found; - /* -------------------- critical section -------------------- */ - (*Lock_Task) (); + START_WAIT: if (plist_length == 0) { errno = ECHILD; - (*Unlock_Task) (); return -1; } + /* -------------------- critical section -------------------- */ + EnterCS(); + hl_len = plist_length; +#ifdef CERT hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len); - memmove (hl, HANDLES_LIST, sizeof (HANDLE) * hl_len); + pidl = (int *) xmalloc (sizeof (int) * hl_len); + memmove (pidl, PID_LIST, sizeof (int) * hl_len); +#else + /* Note that index 0 contains the event hanlde that is signaled when the + process list has changed */ + hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len + 1); + hl[0] = ProcListEvt; + memmove (&hl[1], HANDLES_LIST, sizeof (HANDLE) * hl_len); + pidl = (int *) xmalloc (sizeof (int) * hl_len + 1); + memmove (&pidl[1], PID_LIST, sizeof (int) * hl_len); + hl_len++; +#endif + + LeaveCS(); + /* -------------------- critical section -------------------- */ res = WaitForMultipleObjects (hl_len, hl, FALSE, INFINITE); - h = hl[res - WAIT_OBJECT_0]; + /* if the ProcListEvt has been signaled then the list of processes has been + updated to add or remove a handle, just loop over */ + + if (res - WAIT_OBJECT_0 == 0) + { + free (hl); + free (pidl); + goto START_WAIT; + } + + h = hl[res - WAIT_OBJECT_0]; GetExitCodeProcess (h, &exitcode); - pid = PID_LIST [res - WAIT_OBJECT_0]; - remove_handle (h, -1); + pid = pidl [res - WAIT_OBJECT_0]; + + found = __gnat_win32_remove_handle (h, -1); - (*Unlock_Task) (); - /* -------------------- critical section -------------------- */ free (hl); + free (pidl); + + /* if not found another process waiting has already handled this process */ + + if (!found) + { + goto START_WAIT; + } *status = (int) exitcode; return (int) pid; |