1/*
2 * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include "darwin_shim.h"
24
25#include <mach/mach.h>
26#include <mach/mach_time.h>
27#include <sys/sysctl.h>
28#include <sys/time.h>
29#include <sys/errno.h>
30#include <unistd.h>
31#include <fnmatch.h>
32
33#include "lwp.h" /* In lieu of Solaris <sys/lwp.h> */
34
35hrtime_t
36gethrtime(void)
37{
38    uint64_t        elapsed;
39    static uint64_t        start;
40    static mach_timebase_info_data_t    sTimebaseInfo = { 0, 0 };
41
42    // If this is the first time we've run, get the timebase.
43    // We can use denom == 0 to indicate that sTimebaseInfo is
44    // uninitialised because it makes no sense to have a zero
45    // denominator in a fraction.
46
47    if ( sTimebaseInfo.denom == 0 ) {
48        (void) mach_timebase_info(&sTimebaseInfo);
49		start = mach_absolute_time();
50    }
51
52    elapsed = mach_absolute_time() - start;
53
54    // Convert to nanoseconds.
55	// return (elapsed * (uint64_t)sTimebaseInfo.numer)/(uint64_t)sTimebaseInfo.denom;
56
57	// Provided the final result is representable in 64 bits the following maneuver will
58	// deliver that result without intermediate overflow.
59	if (sTimebaseInfo.denom == sTimebaseInfo.numer)
60		return elapsed;
61	else if (sTimebaseInfo.denom == 1)
62		return elapsed * (uint64_t)sTimebaseInfo.numer;
63	else {
64        // Decompose elapsed = eta32 * 2^32 + eps32:
65        uint64_t eta32 = elapsed >> 32;
66        uint64_t eps32 = elapsed & 0x00000000ffffffffLL;
67
68        uint32_t numer = sTimebaseInfo.numer, denom = sTimebaseInfo.denom;
69
70        // Form product of elapsed64 (decomposed) and numer:
71        uint64_t mu64 = numer * eta32;
72        uint64_t lambda64 = numer * eps32;
73
74        // Divide the constituents by denom:
75        uint64_t q32 = mu64/denom;
76        uint64_t r32 = mu64 - (q32 * denom); // mu64 % denom
77
78        return (q32 << 32) + ((r32 << 32) + lambda64)/denom;
79	}
80}
81
82projid_t getprojid(void) { return (projid_t) 0; } // Darwin has no notion of project. Always return 0.
83taskid_t gettaskid(void) { return (taskid_t) 0; } // Darwin has no notion of task. Always return 0.
84zoneid_t getzoneid(void) { return (zoneid_t) 0; } // Darwin has no notion of Solaris zones(5). Always return 0.
85
86int
87gmatch(const char *s, const char *p)
88{
89	// OS X's fnmatch return value is inverted relative to Solaris's gmatch
90	return fnmatch( p, s, 0 ) == 0;
91}
92
93long
94sysinfo(int command, char *buf, long count)
95{
96	switch (command)
97	{
98	int mib[2];
99	size_t len;
100
101	case SI_RELEASE:
102		mib[0] = CTL_KERN;
103		mib[1] = KERN_OSRELEASE;
104		len = count;
105		return sysctl(mib, 2, (void *)buf, &len, NULL, 0);
106
107	case SI_SYSNAME:
108		mib[0] = CTL_KERN;
109		mib[1] = KERN_OSTYPE;
110		len = count;
111		return sysctl(mib, 2, (void *)buf, &len, NULL, 0);
112
113	case SI_ISALIST:
114#if defined(__i386__)
115		strlcpy( buf, "x86", count );
116#elif defined(__x86_64__)
117		strlcpy( buf, "x86_64", count );
118#elif defined(__arm64__)
119		strlcpy( buf, "arm64", count );
120#elif defined(__arm__)
121		strlcpy( buf, "arm", count );
122#else
123#error Unknown ISA
124#endif
125		return 1;
126	default:
127		return -1;
128	}
129
130	/* NOTREACHED */
131	return 0;
132}
133
134// The following are used only for "assert()"
135int _rw_read_held(struct _rwlock *l){ return 1; }
136int _rw_write_held(struct _rwlock *l){ return 1; }
137int _mutex_held(struct _lwp_mutex *m){ return 1; }
138
139/*
140 * p_online() is only used to identify valid processorid's and only by testing the
141 * return value against -1. On Mac OS X processors are given consecutive id numbers
142 * in [0..hw.physicalcpu_max).
143 */
144int
145p_online(processorid_t processorid, int flag)
146{
147	static int ncpu = -1;
148
149	if (ncpu == -1) {
150		size_t len = sizeof(ncpu);
151		int mib[2] = { CTL_HW, HW_NCPU };
152
153		(void)sysctl(mib, 2, (void *)&ncpu, &len, NULL, 0);
154	}
155
156	switch(flag) {
157	case P_STATUS:
158		if (processorid < ncpu)
159			return P_ONLINE;
160		/* FALLTHROUGH */
161	default:
162		errno = EINVAL;
163		return -1;
164	}
165	/* NOTREACHED */
166}
167
168#if defined(_elf_seterr)
169#undef _elf_seterr
170#endif
171void _elf_seterr(int lib_err, int sys_err);
172void _SHIM_elf_seterr(int x) { _elf_seterr( 0, x); }
173