xref: /dflybsd-src/lib/libc/upmap/ukp_clock.c (revision 0c4f129d375539ed50d86f6d1424eea6f13f52b6)
187116512SMatthew Dillon /*
287116512SMatthew Dillon  * Copyright (c) 2014 The DragonFly Project.  All rights reserved.
387116512SMatthew Dillon  *
487116512SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
587116512SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
687116512SMatthew Dillon  *
787116512SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
887116512SMatthew Dillon  * modification, are permitted provided that the following conditions
987116512SMatthew Dillon  * are met:
1087116512SMatthew Dillon  *
1187116512SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
1287116512SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
1387116512SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
1487116512SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
1587116512SMatthew Dillon  *    the documentation and/or other materials provided with the
1687116512SMatthew Dillon  *    distribution.
1787116512SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
1887116512SMatthew Dillon  *    contributors may be used to endorse or promote products derived
1987116512SMatthew Dillon  *    from this software without specific, prior written permission.
2087116512SMatthew Dillon  *
2187116512SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2287116512SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2387116512SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2487116512SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
2587116512SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2687116512SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2787116512SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2887116512SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2987116512SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3087116512SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3187116512SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3287116512SMatthew Dillon  * SUCH DAMAGE.
3387116512SMatthew Dillon  */
3487116512SMatthew Dillon 
3587116512SMatthew Dillon /*
3687116512SMatthew Dillon  * UKP-Optimized clock_gettime().  Use the kpmap after the 10th call.
3787116512SMatthew Dillon  */
3887116512SMatthew Dillon 
3987116512SMatthew Dillon #include <sys/cdefs.h>
4087116512SMatthew Dillon #include <sys/types.h>
4187116512SMatthew Dillon #include <sys/syscall.h>
4287116512SMatthew Dillon #include <sys/upmap.h>
4387116512SMatthew Dillon #include <sys/time.h>
4487116512SMatthew Dillon #include <machine/cpufunc.h>
4587116512SMatthew Dillon #include <errno.h>
4687116512SMatthew Dillon #include <time.h>
4787116512SMatthew Dillon #include <stdio.h>
4887116512SMatthew Dillon #include <unistd.h>
4987116512SMatthew Dillon /*#include "un-namespace.h"*/
5087116512SMatthew Dillon #include "libc_private.h"
5187116512SMatthew Dillon #include "upmap.h"
5287116512SMatthew Dillon 
5387116512SMatthew Dillon extern int __sys_clock_gettime(clockid_t clock_id, struct timespec *ts);
5487116512SMatthew Dillon int __clock_gettime(clockid_t clock_id, struct timespec *ts);
5587116512SMatthew Dillon 
5687116512SMatthew Dillon static int fast_clock;
5787116512SMatthew Dillon static int fast_count;
5887116512SMatthew Dillon static int *upticksp;
5987116512SMatthew Dillon static struct timespec *ts_uptime;
6087116512SMatthew Dillon static struct timespec *ts_realtime;
6187116512SMatthew Dillon 
6287116512SMatthew Dillon int
__clock_gettime(clockid_t clock_id,struct timespec * ts)6387116512SMatthew Dillon __clock_gettime(clockid_t clock_id, struct timespec *ts)
6487116512SMatthew Dillon {
6587116512SMatthew Dillon 	int res;
6687116512SMatthew Dillon 	int w;
6787116512SMatthew Dillon 
6887116512SMatthew Dillon 	if (fast_clock == 0 && fast_count++ >= 10) {
6987116512SMatthew Dillon 		__kpmap_map(&upticksp, &fast_clock, KPTYPE_UPTICKS);
7087116512SMatthew Dillon 		__kpmap_map(&ts_uptime, &fast_clock, KPTYPE_TS_UPTIME);
7187116512SMatthew Dillon 		__kpmap_map(&ts_realtime, &fast_clock, KPTYPE_TS_REALTIME);
7287116512SMatthew Dillon 		__kpmap_map(NULL, &fast_clock, 0);
7387116512SMatthew Dillon 	}
7487116512SMatthew Dillon 	if (fast_clock > 0) {
7587116512SMatthew Dillon 		switch(clock_id) {
7687116512SMatthew Dillon 		case CLOCK_UPTIME_FAST:
7787116512SMatthew Dillon 		case CLOCK_MONOTONIC_FAST:
7887116512SMatthew Dillon 			do {
7987116512SMatthew Dillon 				w = *upticksp;
8087116512SMatthew Dillon 				cpu_lfence();
8187116512SMatthew Dillon 				*ts = ts_uptime[w & 1];
8287116512SMatthew Dillon 				cpu_lfence();
8387116512SMatthew Dillon 				w = *upticksp - w;
8487116512SMatthew Dillon 			} while (w > 1);
8587116512SMatthew Dillon 			res = 0;
8687116512SMatthew Dillon 			break;
8787116512SMatthew Dillon 		case CLOCK_REALTIME_FAST:
8887116512SMatthew Dillon 		case CLOCK_SECOND:
8987116512SMatthew Dillon 			do {
9087116512SMatthew Dillon 				w = *upticksp;
9187116512SMatthew Dillon 				cpu_lfence();
9287116512SMatthew Dillon 				*ts = ts_realtime[w & 1];
9387116512SMatthew Dillon 				cpu_lfence();
9487116512SMatthew Dillon 				w = *upticksp - w;
9587116512SMatthew Dillon 			} while (w > 1);
9687116512SMatthew Dillon 
9787116512SMatthew Dillon 			if (clock_id == CLOCK_SECOND)
9887116512SMatthew Dillon 				ts->tv_nsec = 0;
9987116512SMatthew Dillon 			res = 0;
10087116512SMatthew Dillon 			break;
10187116512SMatthew Dillon 		default:
10287116512SMatthew Dillon 			res = __sys_clock_gettime(clock_id, ts);
10387116512SMatthew Dillon 			break;
10487116512SMatthew Dillon 		}
10587116512SMatthew Dillon 	} else {
10687116512SMatthew Dillon 		res = __sys_clock_gettime(clock_id, ts);
10787116512SMatthew Dillon 	}
10887116512SMatthew Dillon 	return res;
10987116512SMatthew Dillon }
110*0c4f129dSzrj 
111*0c4f129dSzrj __weak_reference(__clock_gettime, clock_gettime);
112