Commit 9aeef76b by Thomas Quinot Committed by Arnaud Charlet

g-soccon.ads: Add new constant Thread_Blocking_IO...

2007-04-20  Thomas Quinot  <quinot@adacore.com>

	* g-soccon.ads: Add new constant Thread_Blocking_IO, always True by
	default, set False on a per-runtime basis.
	(Need_Netdb_Buffer): New constant.

	* g-socket.ads, g-socket.adb: Import new package
	GNAT.Sockets.Thin.Task_Safe_NetDB.
	(Raise_Host_Error): Use Host_Error_Message from platform-specific thin
	binding to obtain proper message.
	(Close_Selector): Use GNAT.Sockets.Thin.Signalling_Fds.Close.
	Replace various occurrences of Arry (Arry'First)'Address with the
	equivalent Arry'Address (GNAT always follows implementation advice from
	13.3(14)).
	(Get_Host_By_Address, Get_Host_By_Name,
	Get_Service_By_Name, Get_Service_By_Port): Do not use GNAT.Task_Lock;
	instead, rely on platform-specific task safe netdb operations provided
	by g-socthi.

	* g-socthi.ads, g-socthi.adb (Initialize): Remove obsolete formal
	parameter Process_Blocking_IO.
	(Host_Error_Messages): Add stub body.
	(GNAT.Sockets.Thin.Signalling_Fds): New procedure Close.
	(Safe_Gethostbyname, Safe_Gethostbyaddr, Safe_Getservbyname,
	Safe_Getservbyport): Move functions into new child package
	Task_Safe_NetDB.
	(Nonreentrant_Gethostbyname, Nonreentrant_Gethostbyaddr,
	Nonreentrant_Getservbyname, Nonreentrant_Getservbyport): New routines.
	(In_Addr): Add alignment clause.

From-SVN: r125424
parent 96338f19
......@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
-- Copyright (C) 2000-2005, Free Software Foundation, Inc. --
-- Copyright (C) 2000-2007, Free Software Foundation, Inc. --
-- --
-- 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- --
......@@ -43,6 +43,9 @@
-- but are for illustration purposes only. As noted above, part of a port
-- to a new target is to replace this file appropriately.
-- This file is generated automatically, do not modify it by hand! Instead,
-- make changes to gen-soccon.c and re-run it on each target.
package GNAT.Sockets.Constants is
--------------
......@@ -182,4 +185,17 @@ package GNAT.Sockets.Constants is
SIZEOF_tv_sec : constant := 4; -- tv_sec
SIZEOF_tv_usec : constant := 4; -- tv_usec
----------------------------------------
-- Properties of supported interfaces --
----------------------------------------
Need_Netdb_Buffer : constant := 1; -- Need buffer for Netdb ops
----------------------
-- Additional flags --
----------------------
Thread_Blocking_IO : constant Boolean := True;
-- Set False for contexts where socket i/o are process blocking
end GNAT.Sockets.Constants;
......@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
-- Copyright (C) 2001-2006, AdaCore --
-- Copyright (C) 2001-2007, 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- --
......@@ -42,7 +42,7 @@
-- installed. In particular Multicast is not available with the Windows
-- version.
-- The VMS implementation has implemented using the DECC RTL Socket API,
-- The VMS implementation was implemented using the DECC RTL Socket API,
-- and is thus subject to limitations in the implementation of this API.
-- VxWorks cross ports fully implement this package
......@@ -354,11 +354,7 @@ package GNAT.Sockets is
-- end Ping;
-- begin
-- -- Indicate whether the thread library provides process
-- -- blocking IO. Basically, if you are not using FSU threads
-- -- the default is ok.
-- Initialize (Process_Blocking_IO => False);
-- Initialize;
-- Ping.Start;
-- Pong.Start;
-- Ping.Stop;
......@@ -366,18 +362,22 @@ package GNAT.Sockets is
-- Finalize;
-- end PingPong;
procedure Initialize (Process_Blocking_IO : Boolean := False);
-- Initialize must be called before using any other socket routines. The
-- Process_Blocking_IO parameter indicates whether the thread library
-- provides process-blocking or thread-blocking input/output operations.
-- In the former case (typically with FSU threads) GNAT.Sockets should be
-- initialized with a value of True to provide task-blocking IO through an
-- emulation mechanism. Only the first call to Initialize is taken into
-- account (further calls will be ignored). Note that with the default
-- value of Process_Blocking_IO, this operation is a no-op on UNIX
-- platforms, but applications should make sure to call it if portability
-- is expected: some platforms (such as Windows) require initialization
-- before any other socket operations.
procedure Initialize;
-- Initialize must be called before using any other socket routines.
-- Note that this operation is a no-op on UNIX platforms, but applications
-- should make sure to call it if portability is expected: some platforms
-- (such as Windows) require initialization before any socket operation.
procedure Initialize (Process_Blocking_IO : Boolean);
pragma Obsolescent
(Entity => Initialize,
"passing a parameter to Initialize is not supported anymore");
-- Previous versions of GNAT.Sockets used to require the user to indicate
-- whether socket I/O was process- or thread-blocking on the platform.
-- This property is now determined automatically when the run-time library
-- is built. The old version of Initialize, taking a parameter, is kept
-- for compatibility reasons, but this interface is obsolete (and if the
-- value given is wrong, an exception will be raised at run time).
procedure Finalize;
-- After Finalize is called it is not possible to use any routines
......@@ -976,12 +976,10 @@ package GNAT.Sockets is
-- cases Status is set to Completed and sockets that are ready are set in
-- R_Socket_Set or W_Socket_Set. Status is set to Expired if no socket was
-- ready after a Timeout expiration. Status is set to Aborted if an abort
-- signal has been received while checking socket status. As this
-- procedure returns when Timeout occurs, it is a design choice to keep
-- this procedure process blocking. Note that a Timeout of 0.0 returns
-- immediately. Also note that two different Socket_Set_Type objects must
-- be passed as R_Socket_Set and W_Socket_Set (even if they denote the
-- same set of Sockets), or some event may be lost.
-- signal has been received while checking socket status.
-- Note that two different Socket_Set_Type objects must be passed as
-- R_Socket_Set and W_Socket_Set (even if they denote the same set of
-- Sockets), or some event may be lost.
-- Socket_Error is raised when the select(2) system call returns an
-- error condition, or when a read error occurs on the signalling socket
-- used for the implementation of Abort_Selector.
......
......@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
-- Copyright (C) 2001-2006, AdaCore --
-- Copyright (C) 2001-2007, 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- --
......@@ -56,13 +56,10 @@ package body GNAT.Sockets.Thin is
-- been set in non-blocking mode by the user.
Quantum : constant Duration := 0.2;
-- When Thread_Blocking_IO is False, we set sockets in
-- When Constants.Thread_Blocking_IO is False, we set sockets in
-- non-blocking mode and we spend a period of time Quantum between
-- two attempts on a blocking operation.
Thread_Blocking_IO : Boolean := True;
-- Comment required for this ???
Unknown_System_Error : constant C.Strings.chars_ptr :=
C.Strings.New_String ("Unknown system error");
......@@ -153,14 +150,14 @@ package body GNAT.Sockets.Thin is
begin
loop
R := Syscall_Accept (S, Addr, Addrlen);
exit when Thread_Blocking_IO
exit when Constants.Thread_Blocking_IO
or else R /= Failure
or else Non_Blocking_Socket (S)
or else Errno /= Constants.EWOULDBLOCK;
delay Quantum;
end loop;
if not Thread_Blocking_IO
if not Constants.Thread_Blocking_IO
and then R /= Failure
then
-- A socket inherits the properties ot its server especially
......@@ -189,7 +186,7 @@ package body GNAT.Sockets.Thin is
begin
Res := Syscall_Connect (S, Name, Namelen);
if Thread_Blocking_IO
if Constants.Thread_Blocking_IO
or else Res /= Failure
or else Non_Blocking_Socket (S)
or else Errno /= Constants.EINPROGRESS
......@@ -247,7 +244,7 @@ package body GNAT.Sockets.Thin is
Arg : Int_Access) return C.int
is
begin
if not Thread_Blocking_IO
if not Constants.Thread_Blocking_IO
and then Req = Constants.FIONBIO
then
if Arg.all /= 0 then
......@@ -273,7 +270,7 @@ package body GNAT.Sockets.Thin is
begin
loop
Res := Syscall_Recv (S, Msg, Len, Flags);
exit when Thread_Blocking_IO
exit when Constants.Thread_Blocking_IO
or else Res /= Failure
or else Non_Blocking_Socket (S)
or else Errno /= Constants.EWOULDBLOCK;
......@@ -300,7 +297,7 @@ package body GNAT.Sockets.Thin is
begin
loop
Res := Syscall_Recvfrom (S, Msg, Len, Flags, From, Fromlen);
exit when Thread_Blocking_IO
exit when Constants.Thread_Blocking_IO
or else Res /= Failure
or else Non_Blocking_Socket (S)
or else Errno /= Constants.EWOULDBLOCK;
......@@ -325,7 +322,7 @@ package body GNAT.Sockets.Thin is
begin
loop
Res := Syscall_Send (S, Msg, Len, Flags);
exit when Thread_Blocking_IO
exit when Constants.Thread_Blocking_IO
or else Res /= Failure
or else Non_Blocking_Socket (S)
or else Errno /= Constants.EWOULDBLOCK;
......@@ -352,7 +349,7 @@ package body GNAT.Sockets.Thin is
begin
loop
Res := Syscall_Sendto (S, Msg, Len, Flags, To, Tolen);
exit when Thread_Blocking_IO
exit when Constants.Thread_Blocking_IO
or else Res /= Failure
or else Non_Blocking_Socket (S)
or else Errno /= Constants.EWOULDBLOCK;
......@@ -380,7 +377,7 @@ package body GNAT.Sockets.Thin is
begin
R := Syscall_Socket (Domain, Typ, Protocol);
if not Thread_Blocking_IO
if not Constants.Thread_Blocking_IO
and then R /= Failure
then
-- Do not use C_Ioctl as this subprogram tracks sockets set
......@@ -402,13 +399,18 @@ package body GNAT.Sockets.Thin is
null;
end Finalize;
-------------------------
-- Host_Error_Messages --
-------------------------
package body Host_Error_Messages is separate;
----------------
-- Initialize --
----------------
procedure Initialize (Process_Blocking_IO : Boolean) is
procedure Initialize is
begin
Thread_Blocking_IO := not Process_Blocking_IO;
Disable_All_SIGPIPEs;
end Initialize;
......@@ -505,17 +507,18 @@ package body GNAT.Sockets.Thin is
function C_Create (Fds : not null access Fd_Pair) return C.int;
function C_Read (Rsig : C.int) return C.int;
function C_Write (Wsig : C.int) return C.int;
procedure C_Close (Sig : C.int);
pragma Import (C, C_Create, "__gnat_create_signalling_fds");
pragma Import (C, C_Read, "__gnat_read_signalling_fd");
pragma Import (C, C_Write, "__gnat_write_signalling_fd");
pragma Import (C, C_Close, "__gnat_close_signalling_fd");
function Create (Fds : not null access Fd_Pair) return C.int
renames C_Create;
function Create
(Fds : not null access Fd_Pair) return C.int renames C_Create;
function Read (Rsig : C.int) return C.int renames C_Read;
function Write (Wsig : C.int) return C.int renames C_Write;
procedure Close (Sig : C.int) renames C_Close;
end Signalling_Fds;
......
......@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
-- Copyright (C) 2001-2006, AdaCore --
-- Copyright (C) 2001-2007, 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- --
......@@ -40,8 +40,8 @@
with Interfaces.C.Pointers;
with Interfaces.C.Strings;
with GNAT.Sockets.Constants;
with GNAT.OS_Lib;
with GNAT.Sockets.Constants;
with System;
......@@ -64,12 +64,21 @@ package GNAT.Sockets.Thin is
function Socket_Error_Message (Errno : Integer) return C.Strings.chars_ptr;
-- Returns the error message string for the error number Errno. If Errno is
-- not known it returns "Unknown system error".
-- not known, returns "Unknown system error".
function Host_Errno return Integer;
pragma Import (C, Host_Errno, "__gnat_get_h_errno");
-- Returns last host error number
package Host_Error_Messages is
function Host_Error_Message
(H_Errno : Integer) return C.Strings.chars_ptr;
-- Returns the error message string for the host error number H_Errno.
-- If H_Errno is not known, returns "Unknown system error".
end Host_Error_Messages;
subtype Fd_Set_Access is System.Address;
No_Fd_Set : constant Fd_Set_Access := System.Null_Address;
......@@ -111,8 +120,11 @@ package GNAT.Sockets.Thin is
type In_Addr is record
S_B1, S_B2, S_B3, S_B4 : C.unsigned_char;
end record;
for In_Addr'Alignment use C.int'Alignment;
pragma Convention (C, In_Addr);
-- Internet address
-- IPv4 address, represented as a network-order C.int. Note that the
-- underlying operating system may assume that values of this type have
-- C.int alignment, so we need to provide a suitable alignment clause here.
type In_Addr_Access is access all In_Addr;
pragma Convention (C, In_Addr_Access);
......@@ -219,6 +231,10 @@ package GNAT.Sockets.Thin is
-- Indices into an Fd_Pair value providing access to each of the connected
-- file descriptors.
--------------------------------
-- Standard library functions --
--------------------------------
function C_Accept
(S : C.int;
Addr : System.Address;
......@@ -237,14 +253,6 @@ package GNAT.Sockets.Thin is
Name : System.Address;
Namelen : C.int) return C.int;
function C_Gethostbyaddr
(Addr : System.Address;
Len : C.int;
Typ : C.int) return Hostent_Access;
function C_Gethostbyname
(Name : C.char_array) return Hostent_Access;
function C_Gethostname
(Name : System.Address;
Namelen : C.int) return C.int;
......@@ -254,14 +262,6 @@ package GNAT.Sockets.Thin is
Name : System.Address;
Namelen : not null access C.int) return C.int;
function C_Getservbyname
(Name : C.char_array;
Proto : C.char_array) return Servent_Access;
function C_Getservbyport
(Port : C.int;
Proto : C.char_array) return Servent_Access;
function C_Getsockname
(S : C.int;
Name : System.Address;
......@@ -353,6 +353,10 @@ package GNAT.Sockets.Thin is
Iov : System.Address;
Iovcnt : C.int) return C.int;
-------------------------------------------------------
-- Signalling file descriptors for selector abortion --
-------------------------------------------------------
package Signalling_Fds is
function Create (Fds : not null access Fd_Pair) return C.int;
......@@ -370,8 +374,16 @@ package GNAT.Sockets.Thin is
-- Write one byte of data to wsig, the write end of a pair of signalling
-- fds created by Create_Signalling_Fds.
procedure Close (Sig : C.int);
pragma Convention (C, Close);
-- Close one end of a pair of signalling fds (ignoring any error)
end Signalling_Fds;
----------------------------
-- Socket sets management --
----------------------------
procedure Free_Socket_Set
(Set : Fd_Set_Access);
-- Free system-dependent socket set
......@@ -380,11 +392,11 @@ package GNAT.Sockets.Thin is
(Set : Fd_Set_Access;
Socket : Int_Access;
Last : Int_Access);
-- Get last socket in Socket and remove it from the socket
-- set. The parameter Last is a maximum value of the largest
-- socket. This hint is used to avoid scanning very large socket
-- sets. After a call to Get_Socket_From_Set, Last is set back to
-- the real largest socket in the socket set.
-- Get last socket in Socket and remove it from the socket set. The
-- parameter Last is a maximum value of the largest socket. This hint is
-- used to avoid scanning very large socket sets. After a call to
-- Get_Socket_From_Set, Last is set back to the real largest socket in the
-- socket set.
procedure Insert_Socket_In_Set
(Set : Fd_Set_Access;
......@@ -417,18 +429,38 @@ package GNAT.Sockets.Thin is
Socket : C.int);
-- Remove socket from the socket set
-------------------------------------------
-- Nonreentrant network databases access --
-------------------------------------------
-- The following are used only on systems that have nonreentrant
-- getXXXbyYYY functions, and do NOT have corresponding getXXXbyYYY_
-- functions. Currently, LynxOS is the only such system.
function Nonreentrant_Gethostbyname
(Name : C.char_array) return Hostent_Access;
function Nonreentrant_Gethostbyaddr
(Addr : System.Address;
Addr_Len : C.int;
Addr_Type : C.int) return Hostent_Access;
function Nonreentrant_Getservbyname
(Name : C.char_array;
Proto : C.char_array) return Servent_Access;
function Nonreentrant_Getservbyport
(Port : C.int;
Proto : C.char_array) return Servent_Access;
procedure Initialize;
procedure Finalize;
procedure Initialize (Process_Blocking_IO : Boolean);
private
pragma Import (C, C_Bind, "bind");
pragma Import (C, C_Close, "close");
pragma Import (C, C_Gethostbyaddr, "gethostbyaddr");
pragma Import (C, C_Gethostbyname, "gethostbyname");
pragma Import (C, C_Gethostname, "gethostname");
pragma Import (C, C_Getpeername, "getpeername");
pragma Import (C, C_Getservbyname, "getservbyname");
pragma Import (C, C_Getservbyport, "getservbyport");
pragma Import (C, C_Getsockname, "getsockname");
pragma Import (C, C_Getsockopt, "getsockopt");
pragma Import (C, C_Inet_Addr, "inet_addr");
......@@ -449,4 +481,9 @@ private
pragma Import (C, Insert_Socket_In_Set, "__gnat_insert_socket_in_set");
pragma Import (C, Remove_Socket_From_Set, "__gnat_remove_socket_from_set");
pragma Import (C, Nonreentrant_Gethostbyname, "gethostbyname");
pragma Import (C, Nonreentrant_Gethostbyaddr, "gethostbyaddr");
pragma Import (C, Nonreentrant_Getservbyname, "getservbyname");
pragma Import (C, Nonreentrant_Getservbyport, "getservbyport");
end GNAT.Sockets.Thin;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment