diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-22 08:36:25 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-06-22 08:36:25 +0000 |
commit | abb8fcb6faacf486eba1e007e81d27f3fcc0a34c (patch) | |
tree | 4e0e71abda7577cfd834627a3ee5ea5852a015fd /gcc/ada/g-socthi-mingw.adb | |
parent | 7aa5fcabf46ccaa332aff2a7c9c375878ab6856a (diff) | |
download | gcc-abb8fcb6faacf486eba1e007e81d27f3fcc0a34c.tar.gz |
2010-06-22 Robert Dewar <dewar@adacore.com>
* sem_aggr.adb (Resolve_Record_Aggregate): Do style check on component
name.
* sem_ch10.adb (Analyze_Subunit): Do style check on parent unit name.
* sem_ch8.adb (Find_Direct_Name): For non-overloadable entities, do
style check.
* sem_res.adb (Resolve_Entity_Name): Do style check for enumeration
literals.
2010-06-22 Vincent Celier <celier@adacore.com>
* make.adb (Scan_Make_Arg): No longer pass -nostdlib to the compiler as
it has no effect. Always pass -nostdlib to gnatlink, even on VMS.
2010-06-22 Pascal Obry <obry@adacore.com>
* g-socthi-mingw.adb: Fix implementation of the vectored sockets on
Windows.
(C_Recvmsg): Make sure the routine is atomic. Also fully
fill vectors in the proper order.
(C_Sendmsg): Make sure the routine is atomic.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161144 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/g-socthi-mingw.adb')
-rw-r--r-- | gcc/ada/g-socthi-mingw.adb | 112 |
1 files changed, 104 insertions, 8 deletions
diff --git a/gcc/ada/g-socthi-mingw.adb b/gcc/ada/g-socthi-mingw.adb index 23bab2c9a74..6cf0058e96c 100644 --- a/gcc/ada/g-socthi-mingw.adb +++ b/gcc/ada/g-socthi-mingw.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 2001-2009, AdaCore -- +-- Copyright (C) 2001-2010, AdaCore -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -37,8 +37,13 @@ -- This version is for NT -with Interfaces.C.Strings; use Interfaces.C.Strings; -with System; use System; +with Ada.Streams; use Ada.Streams; +with Ada.Unchecked_Conversion; +with Interfaces.C.Strings; use Interfaces.C.Strings; +with System; use System; +with System.Storage_Elements; use System.Storage_Elements; + +with GNAT.Task_Lock; package body GNAT.Sockets.Thin is @@ -273,8 +278,10 @@ package body GNAT.Sockets.Thin is is use type C.size_t; - Res : C.int; - Count : C.int := 0; + Res : C.int; + Count : C.int := 0; + Locked : Boolean := False; + -- Set to false when the lock is activated MH : Msghdr; for MH'Address use Msg; @@ -283,26 +290,105 @@ package body GNAT.Sockets.Thin is for Iovec'Address use MH.Msg_Iov; pragma Import (Ada, Iovec); + Iov_Index : Integer; + Current_Iovec : Vector_Element; + + function To_Access is new Ada.Unchecked_Conversion + (System.Address, Stream_Element_Reference); + pragma Warnings (Off, Stream_Element_Reference); + + Req : Request_Type (Name => N_Bytes_To_Read); + begin -- Windows does not provide an implementation of recvmsg(). The spec for -- WSARecvMsg() is incompatible with the data types we define, and is -- not available in all versions of Windows. So, we use C_Recv instead. - for J in Iovec'Range loop + -- First, wait for some data to be available if socket is blocking + + declare + Selector : Selector_Type; + R_Socket_Set : Socket_Set_Type; + W_Socket_Set : Socket_Set_Type; + Status : Selector_Status; + Req : Request_Type (Name => Non_Blocking_IO); + begin + Control_Socket (Socket_Type (S), Req); + + if not Req.Enabled then + -- We are in a blocking IO mode + Create_Selector (Selector); + + Set (R_Socket_Set, Socket_Type (S)); + + Check_Selector (Selector, R_Socket_Set, W_Socket_Set, Status); + + Close_Selector (Selector); + end if; + end; + + GNAT.Task_Lock.Lock; + Locked := True; + + -- Check how much data are available + + Control_Socket (Socket_Type (S), Req); + + -- Fill the vectors + + Iov_Index := -1; + Current_Iovec := (Base => null, Length => 0); + + loop + if Current_Iovec.Length = 0 then + Iov_Index := Iov_Index + 1; + exit when Iov_Index > Integer (Iovec'Last); + Current_Iovec := Iovec (SOSC.Msg_Iovlen_T (Iov_Index)); + end if; + Res := C_Recv (S, - Iovec (J).Base.all'Address, - C.int (Iovec (J).Length), + Current_Iovec.Base.all'Address, + C.int (Current_Iovec.Length), Flags); if Res < 0 then + Task_Lock.Unlock; return System.CRTL.ssize_t (Res); + + elsif Res = 0 then + exit; + else + pragma Assert (Stream_Element_Count (Res) <= Current_Iovec.Length); + Count := Count + Res; + Current_Iovec.Length := + Current_Iovec.Length - Stream_Element_Count (Res); + Current_Iovec.Base := + To_Access (Current_Iovec.Base.all'Address + + Storage_Offset (Res)); + + -- If we have read all the data that was initially available, + -- do not attempt to receive more, since this might block, or + -- merge data from successive datagrams in case of a datagram- + -- oriented socket. + + exit when Natural (Count) >= Req.Size; end if; end loop; + + Task_Lock.Unlock; + return System.CRTL.ssize_t (Count); + + exception + when others => + if Locked then + Task_Lock.Unlock; + end if; + raise; end C_Recvmsg; -------------- @@ -428,7 +514,10 @@ package body GNAT.Sockets.Thin is -- not available in all versions of Windows. So, we'll use C_Sendto -- instead. + Task_Lock.Lock; + for J in Iovec'Range loop + Res := C_Sendto (S, @@ -439,13 +528,20 @@ package body GNAT.Sockets.Thin is Tolen => C.int (MH.Msg_Namelen)); if Res < 0 then + Task_Lock.Unlock; return System.CRTL.ssize_t (Res); else Count := Count + Res; end if; end loop; + Task_Lock.Unlock; + return System.CRTL.ssize_t (Count); + exception + when others => + Task_Lock.Unlock; + raise; end C_Sendmsg; -------------- |