From patchwork Fri Aug 2 07:11:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Marc_Poulhi=C3=A8s?= X-Patchwork-Id: 1968201 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256 header.s=google header.b=iHZJcFw/; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WZxw92GpDz1yf0 for ; Fri, 2 Aug 2024 17:16:41 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 93E4E386074C for ; Fri, 2 Aug 2024 07:16:39 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-lj1-x230.google.com (mail-lj1-x230.google.com [IPv6:2a00:1450:4864:20::230]) by sourceware.org (Postfix) with ESMTPS id 50AE0385E45B for ; Fri, 2 Aug 2024 07:12:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 50AE0385E45B Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 50AE0385E45B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::230 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722582761; cv=none; b=ZVR69nzAN82aISsWmXY2XJ5xeYRRZ9P9vungaISAGa2xIMl4nIr1VhdlmMWHmqkmvOBMg4YuO4iROPC2WHGWQVKsKsh9lofDOFvdoKUzeIpxSWIR5N9RUqzLfKmB0h/1AjYxJmdxiw9xFKO6Gy1yPHKTJ25J6LYTclBBUXq9gv4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722582761; c=relaxed/simple; bh=fsEbIFNTEpw2eVGi1co3AZ3JMegAqg9N5Iioaru9cr4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=VoomP0g8H/O7H5GpHH8+OVISnvOoE6vLaV5ku3PKNxtZ6v0vBxchmwbORFN27yJrU6BoXwbvqVmEaf0b2Tx9gvDeLrtP1cFApc/j4xp8vLUztzJ29eDcfj4mwthJ6Ebdr31aWhnabOKmH8H1WOA1CWYzz7pEv85wRZFyESJMDZA= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-lj1-x230.google.com with SMTP id 38308e7fff4ca-2f15790b472so18686001fa.0 for ; Fri, 02 Aug 2024 00:12:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1722582754; x=1723187554; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7ojj1wv8YHL4lwXSvP5UPnYyWtcnVsIyEldZpET0R8o=; b=iHZJcFw/wp4eANbMQCx/LvUP8Dd5rBvrMEWnWpSGpb32gb/yTcpJ+nLDP305im8W5F h2YVErThoojDqSBSVbdvaA/w9tAm7kqMvI28nsbatjHXxMUQJN3IflTX7Ku/DHAa9wMP XqnvNnSzeXJFVbg/dP9QOc+LntQnxqas5x6sWrBqpmTmlr2akdgXGbeRmyvrjCUNLg3C s6nbxDIyjD0He4jQE3LmZFJDcMowCvYGVs1k4KAc/60cYf3orNA+JRXTQPph33Z6yjbF PtHo35Swpcs3mbrvZWLsHFlA6c4YVuZ6EkCpVGiC8qs5Qh0YOc2duBzPdy9K0tkupCP6 SNbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722582754; x=1723187554; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7ojj1wv8YHL4lwXSvP5UPnYyWtcnVsIyEldZpET0R8o=; b=IJzWUwEOj3mLs0nYlYsifqge0t9oO5OT3jdJQaMwpdX9kr3BLryRQUB2o/nXCGSc0b Uazvs7uBbsrfGUc7ZzIfWAQ/pQrJy1Rj5FP2HSzCMAr8+3JgmtMGkHXQn1Xeq6xiGwEh QdXulBYVj3d7DaPmpg3tDYMqCtuIQwC8uvTYg5qnsTpUm1A1rEGn5iaGiBrmeQzl6viz Fz0Iqo/Dcz8bblxNRQnq0lAjEhfilCjm3O1laNPQItePMwKrGig3SY1hhW4LlW/m7LWt pAX+pNHmqPfT/hg6rQxVdl3KbNk1owzqlVEkCspQiQWEW3A97Tahc9jd3MCcmA8mJ89q ndsg== X-Gm-Message-State: AOJu0YzHKz1tZqNhzdvTheZEFmfcsmIZnGXmIRQeXAUZ04KzYYx5+kay Il88ZSO/EdRyJ12eOWrryuBYn6563WDMgFwO0tTJ8cUYG95fr7TykdF3X7IlLwol9etYO0/zW2P PJg== X-Google-Smtp-Source: AGHT+IF/4WDxsBBsRQzM7gAVYQuD4mGAwHIsS1ebiTe/wZ8ViD2W28lzDynIzU7MzRqj9LxsC1/D+g== X-Received: by 2002:a2e:979a:0:b0:2ef:2b53:c785 with SMTP id 38308e7fff4ca-2f15ab35233mr16995651fa.41.1722582753440; Fri, 02 Aug 2024 00:12:33 -0700 (PDT) Received: from localhost.localdomain ([2001:861:3382:1a90:b6aa:4751:9ea1:da1e]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36bbd059932sm1195770f8f.69.2024.08.02.00.12.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Aug 2024 00:12:33 -0700 (PDT) From: =?utf-8?q?Marc_Poulhi=C3=A8s?= To: gcc-patches@gcc.gnu.org Cc: Tonu Naks Subject: [COMMITTED 13/26] ada: Add leap second support to conversion of Unix_Time Date: Fri, 2 Aug 2024 09:11:30 +0200 Message-ID: <20240802071210.413366-13-poulhies@adacore.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240802071210.413366-1-poulhies@adacore.com> References: <20240802071210.413366-1-poulhies@adacore.com> MIME-Version: 1.0 X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org From: Tonu Naks Unix timestamp jumps one second back when a leap second is applied and doesn't count cumulative leap seconds. This was not taken into account in conversions between Unix time and Ada time. Now fixed. gcc/ada/ * libgnat/a-calend.adb: Modify unix time handling. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/libgnat/a-calend.adb | 135 ++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/gcc/ada/libgnat/a-calend.adb b/gcc/ada/libgnat/a-calend.adb index 1083ece44d2..c28042d13c4 100644 --- a/gcc/ada/libgnat/a-calend.adb +++ b/gcc/ada/libgnat/a-calend.adb @@ -110,6 +110,17 @@ is new Ada.Unchecked_Conversion (Duration, Time_Rep); -- Convert a duration value into a time representation value + function Elapsed_Leaps (Start_Time, End_Time : Time_Rep) return Natural + with Pre => (End_Time >= Start_Time); + -- If the target supports leap seconds, determine the number of leap + -- seconds elapsed between start_time and end_time. + -- + -- NB! This function assumes that End_Time is not smaller than + -- Start_Time. There are usages of the function that correct the time + -- by passed leap seconds and use the results for another seach. + -- If negative leap seconds are introduced eventually, then such + -- calls should be revised as the correction can go to either direction. + function Time_Rep_To_Duration is new Ada.Unchecked_Conversion (Time_Rep, Duration); -- Convert a time representation value into a duration value @@ -355,13 +366,34 @@ is end if; end Check_Within_Time_Bounds; + ------------------- + -- Elapsed_Leaps -- + ------------------- + + function Elapsed_Leaps (Start_Time, End_Time : Time_Rep) return Natural + is + Elapsed : Natural := 0; + Next_Leap_N : Time_Rep; + begin + if Leap_Support then + Cumulative_Leap_Seconds + (Start_Time, End_Time, Elapsed, Next_Leap_N); + + -- The system clock may fall exactly on a leap second + + if End_Time >= Next_Leap_N then + Elapsed := Elapsed + 1; + end if; + end if; + + return Elapsed; + end Elapsed_Leaps; + ----------- -- Clock -- ----------- function Clock return Time is - Elapsed_Leaps : Natural; - Next_Leap_N : Time_Rep; -- The system clock returns the time in UTC since the Unix Epoch of -- 1970-01-01 00:00:00.0. We perform an origin shift to the Ada Epoch @@ -371,26 +403,7 @@ is Duration_To_Time_Rep (System.OS_Primitives.Clock) + Unix_Min; begin - -- If the target supports leap seconds, determine the number of leap - -- seconds elapsed until this moment. - - if Leap_Support then - Cumulative_Leap_Seconds - (Start_Of_Time, Res_N, Elapsed_Leaps, Next_Leap_N); - - -- The system clock may fall exactly on a leap second - - if Res_N >= Next_Leap_N then - Elapsed_Leaps := Elapsed_Leaps + 1; - end if; - - -- The target does not support leap seconds - - else - Elapsed_Leaps := 0; - end if; - - Res_N := Res_N + Time_Rep (Elapsed_Leaps) * Nano; + Res_N := Res_N + Time_Rep (Elapsed_Leaps (Start_Of_Time, Res_N)) * Nano; return Time (Res_N); end Clock; @@ -806,10 +819,8 @@ is is Res_Dur : Time_Dur; Earlier : Time_Rep; - Elapsed_Leaps : Natural; Later : Time_Rep; Negate : Boolean := False; - Next_Leap_N : Time_Rep; Sub_Secs : Duration; Sub_Secs_Diff : Time_Rep; @@ -825,22 +836,6 @@ is Negate := True; end if; - -- If the target supports leap seconds, process them - - if Leap_Support then - Cumulative_Leap_Seconds - (Earlier, Later, Elapsed_Leaps, Next_Leap_N); - - if Later >= Next_Leap_N then - Elapsed_Leaps := Elapsed_Leaps + 1; - end if; - - -- The target does not support leap seconds - - else - Elapsed_Leaps := 0; - end if; - -- Sub seconds processing. We add the resulting difference to one -- of the input dates in order to account for any potential rounding -- of the difference in the next step. @@ -856,12 +851,14 @@ is -- either add or drop a second. We compensate for this issue in the -- previous step. + Leap_Seconds := Elapsed_Leaps (Earlier, Later); + Res_Dur := - Time_Dur (Later / Nano - Earlier / Nano) - Time_Dur (Elapsed_Leaps); + Time_Dur (Later / Nano - Earlier / Nano) - + Time_Dur (Leap_Seconds); Days := Long_Integer (Res_Dur / Secs_In_Day); Seconds := Duration (Res_Dur mod Secs_In_Day) + Sub_Secs; - Leap_Seconds := Integer (Elapsed_Leaps); if Negate then Days := -Days; @@ -901,9 +898,33 @@ is function To_Ada_Time (Unix_Time : Long_Integer) return Time is pragma Unsuppress (Overflow_Check); - Unix_Rep : constant Time_Rep := Time_Rep (Unix_Time) * Nano; + Ada_Rep : Time_Rep := Time_Rep (Unix_Time * Nano) - Epoch_Offset; + + -- Count leaps passed until the converted time. + + Leaps : constant Natural := + Elapsed_Leaps (Start_Of_Time, Ada_Rep); begin - return Time (Unix_Rep - Epoch_Offset); + + -- If leap seconds were found then update the result accordingly + + if Leaps /= 0 then + declare + -- adjust the time by the number of leap seconds + Corrected_Ada_Rep : constant Time_Rep := + Ada_Rep + Time_Rep ((Leaps) * Nano); + + -- Check if the corrected time passed the boundary + -- of another leap second + Extra_Leaps : constant Natural := + Elapsed_Leaps (Ada_Rep, Corrected_Ada_Rep); + begin + Ada_Rep := Corrected_Ada_Rep + Time_Rep (Extra_Leaps * Nano); + end; + end if; + + return Time (Ada_Rep); + exception when Constraint_Error => raise Time_Error; @@ -1085,7 +1106,8 @@ is pragma Unsuppress (Overflow_Check); Ada_Rep : constant Time_Rep := Time_Rep (Ada_Time); begin - return Long_Integer ((Ada_Rep + Epoch_Offset) / Nano); + return Long_Integer ((Ada_Rep + Epoch_Offset) / Nano) - + Long_Integer (Elapsed_Leaps (Start_Of_Time, Ada_Rep)); exception when Constraint_Error => raise Time_Error; @@ -1112,9 +1134,7 @@ is -- failure. To prevent this, the function returns the "safe" end of -- time (roughly 2219) which is still distant enough. - Elapsed_Leaps : Natural; - Next_Leap_N : Time_Rep; - Res_N : Time_Rep; + Res_N : Time_Rep; begin Res_N := Time_Rep (Date); @@ -1122,23 +1142,8 @@ is -- Step 1: If the target supports leap seconds, remove any leap -- seconds elapsed up to the input date. - if Leap_Support then - Cumulative_Leap_Seconds - (Start_Of_Time, Res_N, Elapsed_Leaps, Next_Leap_N); - - -- The input time value may fall on a leap second occurrence - - if Res_N >= Next_Leap_N then - Elapsed_Leaps := Elapsed_Leaps + 1; - end if; - - -- The target does not support leap seconds - - else - Elapsed_Leaps := 0; - end if; - - Res_N := Res_N - Time_Rep (Elapsed_Leaps) * Nano; + Res_N := Res_N - + Time_Rep (Elapsed_Leaps (Start_Of_Time, Res_N)) * Nano; -- Step 2: Perform a shift in origins to obtain a Unix equivalent of -- the input. Guard against very large delay values such as the end