mirror of
				https://github.com/jart/cosmopolitan.git
				synced 2025-10-25 18:50:57 +00:00 
			
		
		
		
	Improve quality of our ANSI C clock() function
It now works most excellently across all supported operating sytsems (earlier it didn't work on NT and XNU). Demo code is available in examples/clock.c and this change also adds some of the newer ANSI C time functions like timespec_get(), plus timespec_getres() which hasn't even come out yet as it's C23
This commit is contained in:
		
							parent
							
								
									7ff0ea8c13
								
							
						
					
					
						commit
						12d9e1e128
					
				
					 24 changed files with 254 additions and 76 deletions
				
			
		
							
								
								
									
										41
									
								
								examples/clock.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								examples/clock.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| #if 0 | ||||
| /*─────────────────────────────────────────────────────────────────╗
 | ||||
| │ To the extent possible under law, Justine Tunney has waived      │ | ||||
| │ all copyright and related or neighboring rights to this file,    │ | ||||
| │ as it is written in the following disclaimers:                   │ | ||||
| │   • http://unlicense.org/                                        │
 | ||||
| │   • http://creativecommons.org/publicdomain/zero/1.0/            │
 | ||||
| ╚─────────────────────────────────────────────────────────────────*/ | ||||
| #endif | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #include "libc/stdio/stdio.h" | ||||
| #include "libc/time/time.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * @fileoverview clock() function demo | ||||
|  */ | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
|   unsigned long i; | ||||
|   volatile unsigned long x; | ||||
|   struct timespec now, start, next, interval; | ||||
|   printf("hammering the cpu...\n"); | ||||
|   next = start = _timespec_mono(); | ||||
|   interval = _timespec_frommillis(500); | ||||
|   next = _timespec_add(next, interval); | ||||
|   for (;;) { | ||||
|     for (i = 0;; ++i) { | ||||
|       x *= 7; | ||||
|       if (!(i % 256)) { | ||||
|         now = _timespec_mono(); | ||||
|         if (_timespec_gte(now, next)) { | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     next = _timespec_add(next, interval); | ||||
|     printf("consumed %10g seconds monotonic time and %10g seconds cpu time\n", | ||||
|            _timespec_tonanos(_timespec_sub(now, start)) / 1000000000., | ||||
|            (double)clock() / CLOCKS_PER_SEC); | ||||
|   } | ||||
| } | ||||
|  | @ -8,14 +8,14 @@ | |||
| ╚─────────────────────────────────────────────────────────────────*/ | ||||
| #endif | ||||
| #include "libc/calls/calls.h" | ||||
| #include "libc/intrin/kprintf.h" | ||||
| #include "libc/log/check.h" | ||||
| #include "libc/stdio/stdio.h" | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
|   char name[254]; | ||||
|   CHECK_NE(-1, gethostname(name, sizeof(name))); | ||||
|   printf("gethostname() → %`'s\n", name); | ||||
|   CHECK_NE(-1, getdomainname(name, sizeof(name))); | ||||
|   printf("getdomainname() → %`'s\n", name); | ||||
|   gethostname(name, sizeof(name)); | ||||
|   kprintf("gethostname() → %#s\n", name); | ||||
|   getdomainname(name, sizeof(name)); | ||||
|   kprintf("getdomainname() → %#s\n", name); | ||||
|   return 0; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										29
									
								
								libc/calls/_timespec_fromnanos.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								libc/calls/_timespec_fromnanos.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Converts timespec interval from nanoseconds. | ||||
|  */ | ||||
| struct timespec _timespec_fromnanos(int64_t x) { | ||||
|   struct timespec ts; | ||||
|   ts.tv_sec = x / 1000000000; | ||||
|   ts.tv_nsec = x % 1000000000; | ||||
|   return ts; | ||||
| } | ||||
|  | @ -184,9 +184,11 @@ o//libc/calls/statfs2cosmo.o: private			\ | |||
| 
 | ||||
| # we always want -O2 because:
 | ||||
| #   division is expensive if not optimized
 | ||||
| o/$(MODE)/libc/calls/clock.o				\ | ||||
| o/$(MODE)/libc/calls/_timespec_tomillis.o		\ | ||||
| o/$(MODE)/libc/calls/_timespec_tomicros.o		\ | ||||
| o/$(MODE)/libc/calls/_timespec_totimeval.o		\ | ||||
| o/$(MODE)/libc/calls/_timespec_fromnanos.o		\ | ||||
| o/$(MODE)/libc/calls/_timespec_frommillis.o		\ | ||||
| o/$(MODE)/libc/calls/_timespec_frommicros.o: private	\ | ||||
| 		OVERRIDE_CFLAGS +=			\
 | ||||
|  |  | |||
|  | @ -16,36 +16,51 @@ | |||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/struct/rusage.h" | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #include "libc/dce.h" | ||||
| #include "libc/fmt/conv.h" | ||||
| #include "libc/nt/accounting.h" | ||||
| #include "libc/nt/runtime.h" | ||||
| #include "libc/nt/synchronization.h" | ||||
| #include "libc/calls/struct/timeval.h" | ||||
| #include "libc/errno.h" | ||||
| #include "libc/sysv/consts/clock.h" | ||||
| #include "libc/sysv/consts/rusage.h" | ||||
| #include "libc/time/time.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns how much CPU program has consumed on time-sharing system. | ||||
|  * Returns sum of CPU time consumed by current process since birth. | ||||
|  * | ||||
|  * @return value that can be divided by CLOCKS_PER_SEC, or -1 w/ errno | ||||
|  * @see clock_gettime() | ||||
|  * This function provides a basic idea of how computationally expensive | ||||
|  * your program is, in terms of both the userspace and kernel processor | ||||
|  * resources it's hitherto consumed. Here's an example of how you might | ||||
|  * display this information: | ||||
|  * | ||||
|  *     printf("consumed %g seconds of cpu time\n", | ||||
|  *            (double)clock() / CLOCKS_PER_SEC); | ||||
|  * | ||||
|  * This function offers at best microsecond accuracy on all supported | ||||
|  * platforms. Please note the reported values might be a bit chunkier | ||||
|  * depending on the kernel scheduler sampling interval see `CLK_TCK`. | ||||
|  * | ||||
|  * @return units of CPU time consumed, where each unit's time length | ||||
|  *     should be `1./CLOCKS_PER_SEC` seconds; Cosmopolitan currently | ||||
|  *     returns the unit count in microseconds, i.e. `CLOCKS_PER_SEC` | ||||
|  *     is hard-coded as 1000000. On failure this returns -1 / errno. | ||||
|  * @raise ENOSYS should be returned currently if run on Bare Metal | ||||
|  * @see clock_gettime() which polyfills this on Linux and BSDs | ||||
|  * @see getrusage() which polyfills this on XNU and NT | ||||
|  */ | ||||
| int64_t clock(void) { | ||||
|   int e; | ||||
|   struct rusage ru; | ||||
|   struct timespec ts; | ||||
|   struct NtFileTime creation_time, exit_time, kernel_time, user_time; | ||||
|   int64_t proc, total; | ||||
|   // polyfill on Windows where CLOCK_PROCESS_CPUTIME_ID may be not available
 | ||||
|   if (IsWindows() && CLOCK_PROCESS_CPUTIME_ID == -1) { | ||||
|     proc = GetCurrentProcess(); | ||||
|     if (!GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time, | ||||
|                          &user_time)) | ||||
|   e = errno; | ||||
|   if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) { | ||||
|     errno = e; | ||||
|     if (getrusage(RUSAGE_SELF, &ru) != -1) { | ||||
|       ts = _timeval_totimespec(_timeval_add(ru.ru_utime, ru.ru_stime)); | ||||
|     } else { | ||||
|       return -1; | ||||
|     total = ReadFileTime(kernel_time) + ReadFileTime(user_time); | ||||
|     ts = WindowsDurationToTimeSpec(total); | ||||
|   } else if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) { | ||||
|     return -1; | ||||
|     } | ||||
|   } | ||||
|   return ts.tv_sec * CLOCKS_PER_SEC + | ||||
|          ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC); | ||||
|   // convert nanoseconds to microseconds w/ ceil rounding
 | ||||
|   // this would need roughly ~7,019,309 years to overflow
 | ||||
|   return ts.tv_sec * 1000000 + (ts.tv_nsec + 999) / 1000; | ||||
| } | ||||
|  |  | |||
|  | @ -25,8 +25,6 @@ | |||
| #include "libc/sysv/errfuns.h" | ||||
| #include "libc/time/time.h" | ||||
| 
 | ||||
| int sys_clock_getres(int, struct timespec *) hidden; | ||||
| 
 | ||||
| static int sys_clock_getres_poly(int clock, struct timespec *ts, int64_t real) { | ||||
|   if (clock == CLOCK_REALTIME) { | ||||
|     ts->tv_sec = 0; | ||||
|  | @ -65,6 +63,7 @@ int clock_getres(int clock, struct timespec *ts) { | |||
|   } else { | ||||
|     rc = sys_clock_getres(clock, ts); | ||||
|   } | ||||
|   STRACE("clock_getres(%d, [%s]) → %d% m", clock, DescribeTimespec(rc, ts), rc); | ||||
|   STRACE("clock_getres(%s, [%s]) → %d% m", DescribeClockName(clock), | ||||
|          DescribeTimespec(rc, ts), rc); | ||||
|   return rc; | ||||
| } | ||||
|  |  | |||
|  | @ -16,38 +16,33 @@ | |||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/clock_gettime.internal.h" | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #include "libc/intrin/pthread.h" | ||||
| #include "libc/nexgen32e/rdtsc.h" | ||||
| #include "libc/nexgen32e/x86feature.h" | ||||
| #include "libc/sysv/consts/clock.h" | ||||
| #include "libc/sysv/errfuns.h" | ||||
| #include "libc/time/clockstonanos.internal.h" | ||||
| 
 | ||||
| static struct { | ||||
|   pthread_once_t once; | ||||
|   uint64_t base; | ||||
|   struct timespec mono; | ||||
|   struct timespec base_wall; | ||||
|   uint64_t base_tick; | ||||
| } g_mono; | ||||
| 
 | ||||
| static void sys_clock_gettime_mono_init(void) { | ||||
|   clock_gettime(CLOCK_REALTIME, &g_mono.mono); | ||||
|   g_mono.base = rdtsc(); | ||||
|   g_mono.once = true; | ||||
|   g_mono.base_wall = _timespec_real(); | ||||
|   g_mono.base_tick = rdtsc(); | ||||
| } | ||||
| 
 | ||||
| int sys_clock_gettime_mono(struct timespec *ts) { | ||||
|   // this routine stops being monotonic after 194 years of uptime
 | ||||
| int sys_clock_gettime_mono(struct timespec *time) { | ||||
|   uint64_t nanos; | ||||
|   uint64_t cycles; | ||||
|   struct timespec res; | ||||
|   if (X86_HAVE(INVTSC)) { | ||||
|     pthread_once(&g_mono.once, sys_clock_gettime_mono_init); | ||||
|     nanos = ClocksToNanos(rdtsc(), g_mono.base); | ||||
|     res = g_mono.mono; | ||||
|     res.tv_sec += nanos / 1000000000; | ||||
|     res.tv_nsec += nanos % 1000000000; | ||||
|     *ts = res; | ||||
|     cycles = rdtsc() - g_mono.base_tick; | ||||
|     nanos = cycles / 3; | ||||
|     *time = _timespec_add(g_mono.base_wall, _timespec_fromnanos(nanos)); | ||||
|     return 0; | ||||
|   } else { | ||||
|     return einval(); | ||||
|  |  | |||
|  | @ -66,8 +66,8 @@ int clock_gettime(int clock, struct timespec *ts) { | |||
|   } | ||||
| #if SYSDEBUG | ||||
|   if (!__time_critical) { | ||||
|     STRACE("clock_gettime(%d, [%s]) → %d% m", clock, DescribeTimespec(rc, ts), | ||||
|            rc); | ||||
|     STRACE("clock_gettime(%s, [%s]) → %d% m", DescribeClockName(clock), | ||||
|            DescribeTimespec(rc, ts), rc); | ||||
|   } | ||||
| #endif | ||||
|   return rc; | ||||
|  |  | |||
|  | @ -14,6 +14,8 @@ int futimens(int, const struct timespec[2]); | |||
| int nanosleep(const struct timespec *, struct timespec *); | ||||
| int sys_futex(int *, int, int, const struct timespec *, int *); | ||||
| int utimensat(int, const char *, const struct timespec[2], int); | ||||
| int timespec_get(struct timespec *, int); | ||||
| int timespec_getres(struct timespec *, int); | ||||
| 
 | ||||
| bool _timespec_eq(struct timespec, struct timespec) pureconst; | ||||
| bool _timespec_gte(struct timespec, struct timespec) pureconst; | ||||
|  | @ -21,6 +23,7 @@ int64_t _timespec_tomicros(struct timespec) pureconst; | |||
| int64_t _timespec_tomillis(struct timespec) pureconst; | ||||
| int64_t _timespec_tonanos(struct timespec) pureconst; | ||||
| struct timespec _timespec_add(struct timespec, struct timespec) pureconst; | ||||
| struct timespec _timespec_fromnanos(int64_t) pureconst; | ||||
| struct timespec _timespec_frommicros(int64_t) pureconst; | ||||
| struct timespec _timespec_frommillis(int64_t) pureconst; | ||||
| struct timespec _timespec_mono(void); | ||||
|  |  | |||
|  | @ -6,14 +6,15 @@ | |||
| COSMOPOLITAN_C_START_ | ||||
| 
 | ||||
| int __sys_utimensat(int, const char *, const struct timespec *, int) hidden; | ||||
| int sys_clock_getres(int, struct timespec *) hidden; | ||||
| int sys_clock_gettime(int, struct timespec *) hidden; | ||||
| int sys_clock_gettime_nt(int, struct timespec *) hidden; | ||||
| int sys_clock_gettime_xnu(int, struct timespec *) hidden; | ||||
| int sys_futimens(int, const struct timespec *) hidden; | ||||
| int sys_nanosleep(const struct timespec *, struct timespec *) hidden; | ||||
| int sys_utimensat(int, const char *, const struct timespec *, int) hidden; | ||||
| int sys_clock_gettime_nt(int, struct timespec *) hidden; | ||||
| int sys_nanosleep_nt(const struct timespec *, struct timespec *) hidden; | ||||
| int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden; | ||||
| int sys_utimensat(int, const char *, const struct timespec *, int) hidden; | ||||
| int sys_utimensat_nt(int, const char *, const struct timespec *, int) hidden; | ||||
| int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										36
									
								
								libc/calls/timespec_get.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								libc/calls/timespec_get.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #include "libc/sysv/consts/clock.h" | ||||
| #include "libc/time/time.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns high-precision timestamp, the C11 way. | ||||
|  * | ||||
|  * @param ts receives `CLOCK_REALTIME` timestamp | ||||
|  * @param base must be `TIME_UTC` | ||||
|  * @return `base` on success, or `0` on failure | ||||
|  */ | ||||
| int timespec_get(struct timespec *ts, int base) { | ||||
|   if (base == TIME_UTC && !clock_gettime(CLOCK_REALTIME, ts)) { | ||||
|     return base; | ||||
|   } else { | ||||
|     return 0; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										36
									
								
								libc/calls/timespec_getres.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								libc/calls/timespec_getres.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #include "libc/sysv/consts/clock.h" | ||||
| #include "libc/time/time.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns high-precision timestamp granularity, the C23 way. | ||||
|  * | ||||
|  * @param ts receives granularity as a relative timestamp | ||||
|  * @param base must be `TIME_UTC` | ||||
|  * @return `base` on success, or `0` on failure | ||||
|  */ | ||||
| int timespec_getres(struct timespec *ts, int base) { | ||||
|   if (base == TIME_UTC && !clock_getres(CLOCK_REALTIME, ts)) { | ||||
|     return base; | ||||
|   } else { | ||||
|     return 0; | ||||
|   } | ||||
| } | ||||
|  | @ -158,6 +158,9 @@ struct thatispacked mayalias __usi128ma { | |||
| #define _mm_srli_si128(M128I, IMM) \ | ||||
|   ((__m128i)__builtin_ia32_psrldqi128((__v2di)(__m128i)(M128I), (int)(IMM)*8)) | ||||
| 
 | ||||
| #define _mm_cmpeq_epi8(a, b) ((__m128i)((__v16qi)(a) == (__v16qi)(b))) | ||||
| #define _mm_movemask_epi8(a) __builtin_ia32_pmovmskb128((__v16qi)(a)) | ||||
| 
 | ||||
| /*───────────────────────────────────────────────────────────────────────────│─╗
 | ||||
| │ cosmopolitan § it's a trap! » sse2 » scalar ops                          ─╬─│┼ | ||||
| ╚────────────────────────────────────────────────────────────────────────────│*/ | ||||
|  | @ -218,19 +221,18 @@ struct thatispacked mayalias __usi128ma { | |||
| #define _mm_cmpunord_sd(M128D_0, M128D_1) \ | ||||
|   __builtin_ia32_cmpunordsd((__v2df)(M128D_0), (__v2df)(M128D_1)) | ||||
| 
 | ||||
| #define _mm_SSE2(op, A, B)	\ | ||||
|   ({				\ | ||||
|       __m128i R = A;		\ | ||||
|       asm(#op " %1, %0"		\ | ||||
|           : "+x"(R) : "xm"(B));	\ | ||||
|       R;			\ | ||||
| #define _mm_SSE2(op, A, B)                  \ | ||||
|   ({                                        \ | ||||
|     __m128i R = A;                          \ | ||||
|     asm(#op " %1, %0" : "+x"(R) : "xm"(B)); \ | ||||
|     R;                                      \ | ||||
|   }) | ||||
| #define _mm_mul_epu32(A, B)		_mm_SSE2(pmuludq, A, B) | ||||
| #define _mm_add_epi64(A, B)		_mm_SSE2(paddq, A, B) | ||||
| #define _mm_srli_epi64(A, B)		_mm_SSE2(psrlq, A, B) | ||||
| #define _mm_slli_epi64(A, B)		_mm_SSE2(psllq, A, B) | ||||
| #define _mm_unpacklo_epi64(A, B)	_mm_SSE2(punpcklqdq, A, B) | ||||
| #define _mm_unpackhi_epi64(A, B)	_mm_SSE2(punpckhqdq, A, B) | ||||
| #define _mm_mul_epu32(A, B)      _mm_SSE2(pmuludq, A, B) | ||||
| #define _mm_add_epi64(A, B)      _mm_SSE2(paddq, A, B) | ||||
| #define _mm_srli_epi64(A, B)     _mm_SSE2(psrlq, A, B) | ||||
| #define _mm_slli_epi64(A, B)     _mm_SSE2(psllq, A, B) | ||||
| #define _mm_unpacklo_epi64(A, B) _mm_SSE2(punpcklqdq, A, B) | ||||
| #define _mm_unpackhi_epi64(A, B) _mm_SSE2(punpckhqdq, A, B) | ||||
| 
 | ||||
| /*───────────────────────────────────────────────────────────────────────────│─╗
 | ||||
| │ cosmopolitan § it's a trap! » sse2 » miscellaneous                       ─╬─│┼ | ||||
|  |  | |||
|  | @ -17,10 +17,6 @@ | |||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #define ShouldUseMsabiAttribute() 1 | ||||
| #include "libc/intrin/bits.h" | ||||
| #include "libc/intrin/likely.h" | ||||
| #include "libc/intrin/safemacros.internal.h" | ||||
| #include "libc/intrin/weaken.h" | ||||
| #include "libc/calls/calls.h" | ||||
| #include "libc/calls/state.internal.h" | ||||
| #include "libc/calls/syscall-sysv.internal.h" | ||||
|  | @ -28,11 +24,15 @@ | |||
| #include "libc/errno.h" | ||||
| #include "libc/fmt/divmod10.internal.h" | ||||
| #include "libc/fmt/fmt.h" | ||||
| #include "libc/intrin/bits.h" | ||||
| #include "libc/intrin/cmpxchg.h" | ||||
| #include "libc/intrin/kprintf.h" | ||||
| #include "libc/intrin/likely.h" | ||||
| #include "libc/intrin/lockcmpxchg.h" | ||||
| #include "libc/intrin/nomultics.internal.h" | ||||
| #include "libc/intrin/safemacros.internal.h" | ||||
| #include "libc/intrin/spinlock.h" | ||||
| #include "libc/intrin/weaken.h" | ||||
| #include "libc/limits.h" | ||||
| #include "libc/log/internal.h" | ||||
| #include "libc/macros.internal.h" | ||||
|  | @ -53,7 +53,6 @@ | |||
| #include "libc/str/utf16.h" | ||||
| #include "libc/sysv/consts/nr.h" | ||||
| #include "libc/sysv/consts/prot.h" | ||||
| #include "libc/time/clockstonanos.internal.h" | ||||
| 
 | ||||
| extern hidden struct SymbolTable *__symtab; | ||||
| 
 | ||||
|  | @ -306,7 +305,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, | |||
|           continue; | ||||
| 
 | ||||
|         case 'T': | ||||
|           x = ClocksToNanos(rdtsc(), kStartTsc) % 86400000000000; | ||||
|           x = (rdtsc() - kStartTsc) / 3 % 86400000000000; | ||||
|           goto FormatUnsigned; | ||||
| 
 | ||||
|         case 'P': | ||||
|  |  | |||
|  | @ -1615,8 +1615,6 @@ syscon	iff	IFF_MASTER				0x0400			0			0			0			0			0 | |||
| syscon	iff	IFF_PORTSEL				0x2000			0			0			0			0			0 | ||||
| syscon	iff	IFF_SLAVE				0x0800			0			0			0			0			0 | ||||
| 
 | ||||
| syscon	misc	CLOCKS_PER_SEC				1000000			1000000			0x80			100			100			10000000 | ||||
| 
 | ||||
| syscon	sock	SOCK_STREAM				1			1			1			1			1			1			# consensus | ||||
| syscon	sock	SOCK_DGRAM				2			2			2			2			2			2			# consensus | ||||
| syscon	sock	SOCK_RAW				3			3			3			3			3			3			# consensus | ||||
|  |  | |||
|  | @ -1,2 +0,0 @@ | |||
| .include "o/libc/sysv/consts/syscon.internal.inc" | ||||
| .syscon misc,CLOCKS_PER_SEC,1000000,1000000,0x80,100,100,10000000 | ||||
|  | @ -1,2 +1,2 @@ | |||
| .include "o/libc/sysv/consts/syscon.internal.inc" | ||||
| .syscon sicode,SI_KERNEL,0x80,0x80000000,0x010006,0x80000000,0x80000000,0x80 | ||||
| .syscon sicode,SI_KERNEL,128,0x80000000,0x010006,0x80000000,0x80000000,0x80 | ||||
|  |  | |||
|  | @ -5,6 +5,10 @@ | |||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||
| COSMOPOLITAN_C_START_ | ||||
| 
 | ||||
| /**
 | ||||
|  * @fileoverview Cosmopolitan POSIX Thread Internals | ||||
|  */ | ||||
| 
 | ||||
| enum PosixThreadStatus { | ||||
|   kPosixThreadStarted, | ||||
|   kPosixThreadDetached, | ||||
|  |  | |||
|  | @ -33,13 +33,13 @@ static int PosixThread(void *arg, int tid) { | |||
|     ((cthread_t)__get_tls())->pthread = pt; | ||||
|     pt->rc = pt->start_routine(pt->arg); | ||||
|   } | ||||
|   if (atomic_load_explicit(&pt->status, memory_order_relaxed) == | ||||
|   if (atomic_load_explicit(&pt->status, memory_order_acquire) == | ||||
|       kPosixThreadDetached) { | ||||
|     atomic_store_explicit(&pt->status, kPosixThreadZombie, | ||||
|                           memory_order_relaxed); | ||||
|                           memory_order_release); | ||||
|   } else { | ||||
|     atomic_store_explicit(&pt->status, kPosixThreadTerminated, | ||||
|                           memory_order_relaxed); | ||||
|                           memory_order_release); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | @ -47,6 +47,25 @@ static int PosixThread(void *arg, int tid) { | |||
| /**
 | ||||
|  * Creates thread. | ||||
|  * | ||||
|  * Here's the OSI model of threads in Cosmopolitan: | ||||
|  * | ||||
|  *              ┌──────────────────┐ | ||||
|  *              │ pthread_create() │       - Standard | ||||
|  *              └─────────┬────────┘         Abstraction | ||||
|  *              ┌─────────┴────────┐ | ||||
|  *              │     _spawn()     │       - Cosmopolitan | ||||
|  *              └─────────┬────────┘         Abstraction | ||||
|  *              ┌─────────┴────────┐ | ||||
|  *              │     clone()      │       - Polyfill | ||||
|  *              └─────────┬────────┘ | ||||
|  *            ┌────────┬──┴──┬─┬─────────┐ - Kernel | ||||
|  *      ┌─────┴─────┐  │     │┌┴──────┐  │   Interfaces | ||||
|  *      │ sys_clone │  │     ││ tfork │  │ | ||||
|  *      └───────────┘  │     │└───────┘ ┌┴─────────────┐ | ||||
|  *     ┌───────────────┴──┐ ┌┴────────┐ │ CreateThread │ | ||||
|  *     │ bsdthread_create │ │ thr_new │ └──────────────┘ | ||||
|  *     └──────────────────┘ └─────────┘ | ||||
|  * | ||||
|  * @return 0 on success, or errno on error | ||||
|  */ | ||||
| int pthread_create(pthread_t *thread, const pthread_attr_t *attr, | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ | |||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/bits/atomic.h" | ||||
| #include "libc/intrin/atomic.h" | ||||
| #include "libc/mem/mem.h" | ||||
| #include "libc/runtime/runtime.h" | ||||
|  |  | |||
|  | @ -1,5 +1,9 @@ | |||
| #ifndef COSMOPOLITAN_LIBC_TIME_TIME_H_ | ||||
| #define COSMOPOLITAN_LIBC_TIME_TIME_H_ | ||||
| 
 | ||||
| #define TIME_UTC       1 | ||||
| #define CLOCKS_PER_SEC 1000000L | ||||
| 
 | ||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||
| COSMOPOLITAN_C_START_ | ||||
| 
 | ||||
|  | @ -10,7 +14,6 @@ hidden extern const char kMonthName[12][10]; | |||
| hidden extern const unsigned short kMonthYearDay[2][12]; | ||||
| 
 | ||||
| extern char *tzname[2]; | ||||
| extern long CLOCKS_PER_SEC; | ||||
| extern long timezone; | ||||
| extern int daylight; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								third_party/python/Modules/timemodule.c
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								third_party/python/Modules/timemodule.c
									
										
									
									
										vendored
									
									
								
							|  | @ -110,7 +110,6 @@ PyDoc_STRVAR(time_ns_doc, | |||
| Return the current time in nanoseconds since the Epoch."); | ||||
| 
 | ||||
| #ifdef HAVE_CLOCK | ||||
| #define CLOCKS_PER_SEC CLK_TCK | ||||
| static PyObject * | ||||
| floatclock(_Py_clock_info_t *info) | ||||
| { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue