IOReturn eqMac2DriverEngine::performAudioEngineStart() { //IOLog("eqMac2DriverEngine[%p]::performAudioEngineStart()\n", this); // When performAudioEngineStart() gets called, the audio engine should be started from the beginning // of the sample buffer. Because it is starting on the first sample, a new timestamp is needed // to indicate when that sample is being read from/written to. The function takeTimeStamp() // is provided to do that automatically with the current time. // By default takeTimeStamp() will increment the current loop count in addition to taking the current // timestamp. Since we are starting a new audio engine run, and not looping, we don't want the loop count // to be incremented. To accomplish that, false is passed to takeTimeStamp(). // The audio engine will also have to take a timestamp each time the buffer wraps around // How that is implemented depends on the type of hardware - PCI hardware will likely // receive an interrupt to perform that task takeTimeStamp(false); currentBlock = 0; timerEventSource->setTimeout(blockTimeoutNS); uint64_t time; clock_get_uptime(&time); absolutetime_to_nanoseconds(time, &nextTime); nextTime += blockTimeoutNS; return kIOReturnSuccess; }
bool REACConnection::start() { if (NULL == timerEventSource || workLoop->addEventSource(timerEventSource) != kIOReturnSuccess) { IOLog("REACConnection::start() - Error: Failed to add timer event source to work loop!\n"); return false; } timerEventSource->setTimeout(timeoutNS); uint64_t time; clock_get_uptime(&time); absolutetime_to_nanoseconds(time, &nextTime); nextTime += timeoutNS; iff_filter filter; filter.iff_cookie = this; filter.iff_name = "REAC driver input filter"; filter.iff_protocol = 0; filter.iff_input = &REACConnection::filterInputFunc; filter.iff_output = NULL; filter.iff_event = NULL; filter.iff_ioctl = NULL; filter.iff_detached = &REACConnection::filterDetachedFunc; if (0 != iflt_attach(interface, &filter, &filterRef)) { return false; } started = true; return true; }
inline void NDAS_clock_get_uptime(uint64_t *time) { #ifdef __KPI_SOCKET__ // BUG BUG BUG!!! /* uint64_t absoluteTime; clock_get_uptime(&absoluteTime); absolutetime_to_nanoseconds(absoluteTime, time); */ uint32_t secpart, nsecpart; clock_get_system_nanotime(&secpart, &nsecpart); *time = nsecpart + (1000000000ULL * secpart); //convert seconds to nanoseconds. #else AbsoluteTime absoluteTime; clock_get_uptime(&absoluteTime); //AbsoluteTime_to_scalar((AbsoluteTime*)time); absolutetime_to_nanoseconds(absoluteTime, time); #endif }
void eqMac2DriverEngine::ourTimerFired(OSObject *target, IOTimerEventSource *sender) { if (target) { eqMac2DriverEngine *audioEngine = OSDynamicCast(eqMac2DriverEngine, target); UInt64 thisTimeNS; uint64_t time; SInt64 diff; if (audioEngine) { // make sure we have a client, and thus new data so we don't keep on // just looping around the last client's last buffer! IOAudioStream *outStream = audioEngine->getAudioStream(kIOAudioStreamDirectionOutput, 1); if (outStream->numClients == 0) { // it has, so clean the buffer memset((UInt8*)audioEngine->mThruBuffer, 0, audioEngine->mBufferSize); } audioEngine->currentBlock++; if (audioEngine->currentBlock >= audioEngine->numBlocks) { audioEngine->currentBlock = 0; audioEngine->takeTimeStamp(); } // calculate next time to fire, by taking the time and comparing it to the time we requested. clock_get_uptime(&time); absolutetime_to_nanoseconds(time, &thisTimeNS); // this next calculation must be signed or we will introduce distortion after only a couple of vectors diff = ((SInt64)audioEngine->nextTime - (SInt64)thisTimeNS); sender->setTimeout(audioEngine->blockTimeoutNS + diff); audioEngine->nextTime += audioEngine->blockTimeoutNS; } } }
u_int64_t pktsched_abs_to_nsecs(u_int64_t abstime) { u_int64_t nsecs; absolutetime_to_nanoseconds(abstime, &nsecs); return (nsecs); }
//============================================================================== // IOHIDEvent::getLatency //============================================================================== uint64_t IOHIDEvent::getLatency(uint32_t scaleFactor) { AbsoluteTime delta = mach_absolute_time(); uint64_t ns; SUB_ABSOLUTETIME(&delta, &_timeStamp); absolutetime_to_nanoseconds(delta, &ns); return ns / scaleFactor; }
void REACConnection::timerFired(OSObject *target, IOTimerEventSource *sender) { REACConnection *proto = OSDynamicCast(REACConnection, target); if (NULL == proto) { // This should never happen IOLog("REACConnection::timerFired(): Internal error!\n"); return; } UInt64 thisTimeNS; uint64_t time; SInt64 diff; do { if (proto->isConnected()) { if ((proto->connectionCounter - proto->lastSeenConnectionCounter)*proto->timeoutNS > (UInt64)REAC_TIMEOUT_UNTIL_DISCONNECT*1000000) { proto->connected = false; if (NULL != proto->connectionCallback) { proto->connectionCallback(proto, &proto->cookieA, &proto->cookieB, NULL); } } proto->connectionCounter++; } if (REAC_MASTER == proto->mode) { proto->getAndSendSamples(); } else if (REAC_SPLIT == proto->mode) { proto->lastSentAnnouncementCounter++; if (proto->lastSentAnnouncementCounter*proto->timeoutNS >= 1000000000) { proto->lastSentAnnouncementCounter = 0; proto->sendSplitAnnouncementPacket(); } } // Calculate next time to fire, by taking the time and comparing it to the time we requested. clock_get_uptime(&time); absolutetime_to_nanoseconds(time, &thisTimeNS); proto->nextTime += proto->timeoutNS; // This next calculation must be signed diff = ((SInt64)proto->nextTime - (SInt64)thisTimeNS); if (diff < -((SInt64)proto->timeoutNS)*10) { // TODO After a certain amount of lost packets we probably ought to skip output packets IOLog("REACConnection::timerFired(): Lost the time by %lld us\n", diff/1000); } } while (diff < 0); sender->setTimeout((UInt64)diff); }
void BrcmPatchRAM::stop(IOService* provider) { uint64_t stop_time, nano_secs; clock_get_uptime(&stop_time); absolutetime_to_nanoseconds(stop_time - wake_time, &nano_secs); uint64_t milli_secs = nano_secs / 1000000; AlwaysLog("Time since wake %llu.%llu seconds.\n", milli_secs / 1000, milli_secs % 1000); DebugLog("stop\n"); OSSafeReleaseNULL(mFirmwareStore); IOWorkLoop* workLoop = getWorkLoop(); if (workLoop) { if (mTimer) { mTimer->cancelTimeout(); workLoop->removeEventSource(mTimer); mTimer->release(); mTimer = NULL; } if (mWorkSource) { workLoop->removeEventSource(mWorkSource); mWorkSource->release(); mWorkSource = NULL; mWorkPending = 0; } } PMstop(); if (mCompletionLock) { IOLockFree(mCompletionLock); mCompletionLock = NULL; } if (mWorkLock) { IOLockFree(mWorkLock); mWorkLock = NULL; } OSSafeReleaseNULL(mDevice); super::stop(provider); }
IOService* BrcmPatchRAM::probe(IOService *provider, SInt32 *probeScore) { extern kmod_info_t kmod_info; uint64_t start_time, end_time, nano_secs; DebugLog("probe\n"); AlwaysLog("Version %s starting on OS X Darwin %d.%d.\n", kmod_info.version, version_major, version_minor); clock_get_uptime(&start_time); mWorkLock = IOLockAlloc(); if (!mWorkLock) return NULL; mCompletionLock = IOLockAlloc(); if (!mCompletionLock) return NULL; mDevice = OSDynamicCast(IOUSBDevice, provider); if (!mDevice) { AlwaysLog("Provider is not a USB device.\n"); return NULL; } mDevice->retain(); initBrcmStrings(); OSString* displayName = OSDynamicCast(OSString, getProperty(kDisplayName)); if (displayName) provider->setProperty(kUSBProductString, displayName); mVendorId = mDevice->GetVendorID(); mProductId = mDevice->GetProductID(); // get firmware here to pre-cache for eventual use on wakeup or now if (BrcmFirmwareStore* firmwareStore = getFirmwareStore()) firmwareStore->getFirmware(OSDynamicCast(OSString, getProperty(kFirmwareKey))); uploadFirmware(); publishPersonality(); clock_get_uptime(&end_time); absolutetime_to_nanoseconds(end_time - start_time, &nano_secs); uint64_t milli_secs = nano_secs / 1000000; AlwaysLog("Processing time %llu.%llu seconds.\n", milli_secs / 1000, milli_secs % 1000); return this; }
static int panic_set_restart_timeout(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) { int new_value = 0, old_value = 0, changed = 0, error; uint64_t nstime; if (panic_restart_timeout) { absolutetime_to_nanoseconds(panic_restart_timeout, &nstime); old_value = nstime / NSEC_PER_SEC; } error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed); if (error == 0 && changed) { nanoseconds_to_absolutetime(((uint64_t)new_value) * NSEC_PER_SEC, &panic_restart_timeout); } return error; }
void ml_ppc_sleep(void) { struct per_proc_info *proc_info; boolean_t dohalt; proc_info = getPerProc(); if (!proc_info->hibernate) { ml_ppc_do_sleep(); return; } { uint64_t start, end, nsec; HIBLOG("mapping_hibernate_flush start\n"); clock_get_uptime(&start); mapping_hibernate_flush(); clock_get_uptime(&end); absolutetime_to_nanoseconds(end - start, &nsec); HIBLOG("mapping_hibernate_flush time: %qd ms\n", nsec / 1000000ULL); } dohalt = hibernate_write_image(); if (dohalt) { // off HIBLOG("power off\n"); if (PE_halt_restart) (*PE_halt_restart)(kPEHaltCPU); } else { // sleep HIBLOG("sleep\n"); // should we come back via regular wake, set the state in memory. PerProcTable[0].ppe_vaddr->hibernate = 0; PE_cpu_machine_quiesce(proc_info->cpu_id); return; } }
int RDebug::stopTimer(int id, const QString& msg, int msThreshold) { #if defined(Q_OS_MAC) && !defined(Q_OS_IOS) if ( _timerlib_info.denom == 0 ) mach_timebase_info( &_timerlib_info ); uint64_t elapsedNano; uint64_t end = mach_absolute_time(); uint64_t elapsed = end - timerMac[id]; absolutetime_to_nanoseconds(elapsed, &elapsedNano); uint64_t t = elapsedNano; timerMac.remove(id); #else int t = timer[id].elapsed() * 1000000; timer.remove(id); #endif if (t/1000000>=msThreshold) { qDebug() << "TIMER: " << t << "ns (" << t/1000000 << "ms )" << " - " << msg; } return t; }
DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void) { static int8_t s_fSimple = -1; /* first call: check if life is simple or not. */ if (s_fSimple < 0) { struct mach_timebase_info Info; clock_timebase_info(&Info); ASMAtomicXchgS8((int8_t * volatile)&s_fSimple, Info.denom == 1 && Info.numer == 1); } /* special case: absolute time is in nanoseconds */ if (s_fSimple) return mach_absolute_time(); /* general case: let mach do the mult/div for us. */ uint64_t u64; absolutetime_to_nanoseconds(mach_absolute_time(), &u64); return u64; }
tick_t time_system( void ) { #if FOUNDATION_PLATFORM_WINDOWS struct __timeb64 tb; _ftime64_s( &tb ); return ( (tick_t)tb.time * 1000ULL ) + (tick_t)tb.millitm; #elif FOUNDATION_PLATFORM_APPLE tick_t curclock = 0; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); return ( curclock / 1000000ULL ); #elif FOUNDATION_PLATFORM_POSIX struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_REALTIME, &ts ); return ( (uint64_t)ts.tv_sec * 1000ULL ) + ( ts.tv_nsec / 1000000ULL ); #endif }
IOReturn IOPolledFileOpen(const char * filename, uint64_t setFileSize, uint64_t fsFreeSize, void * write_file_addr, size_t write_file_len, IOPolledFileIOVars ** fileVars, OSData ** imagePath, uint8_t * volumeCryptKey, size_t keySize) { IOReturn err = kIOReturnSuccess; IOPolledFileIOVars * vars; _OpenFileContext ctx; OSData * extentsData; OSNumber * num; IOService * part = 0; dev_t block_dev; dev_t image_dev; AbsoluteTime startTime, endTime; uint64_t nsec; vars = IONew(IOPolledFileIOVars, 1); if (!vars) return (kIOReturnNoMemory); bzero(vars, sizeof(*vars)); vars->allocated = true; do { extentsData = OSData::withCapacity(32); ctx.extents = extentsData; ctx.size = 0; clock_get_uptime(&startTime); vars->fileRef = kern_open_file_for_direct_io(filename, (write_file_addr != NULL) || (0 != setFileSize), &file_extent_callback, &ctx, setFileSize, fsFreeSize, // write file: 0, write_file_addr, write_file_len, // results &block_dev, &image_dev, &vars->block0, &vars->maxiobytes, &vars->flags); #if 0 uint32_t msDelay = (131071 & random()); HIBLOG("sleep %d\n", msDelay); IOSleep(msDelay); #endif clock_get_uptime(&endTime); SUB_ABSOLUTETIME(&endTime, &startTime); absolutetime_to_nanoseconds(endTime, &nsec); if (!vars->fileRef) err = kIOReturnNoSpace; HIBLOG("kern_open_file_for_direct_io took %qd ms\n", nsec / 1000000ULL); if (kIOReturnSuccess != err) break; HIBLOG("Opened file %s, size %qd, extents %ld, maxio %qx ssd %d\n", filename, ctx.size, (extentsData->getLength() / sizeof(IOPolledFileExtent)) - 1, vars->maxiobytes, kIOPolledFileSSD & vars->flags); assert(!vars->block0); if (extentsData->getLength() < sizeof(IOPolledFileExtent)) { err = kIOReturnNoSpace; break; } vars->fileSize = ctx.size; vars->extentMap = (IOPolledFileExtent *) extentsData->getBytesNoCopy(); part = IOCopyMediaForDev(image_dev); if (!part) { err = kIOReturnNotFound; break; } if (!(vars->pollers = IOPolledFilePollers::copyPollers(part))) break; if ((num = OSDynamicCast(OSNumber, part->getProperty(kIOMediaPreferredBlockSizeKey)))) vars->blockSize = num->unsigned32BitValue(); if (vars->blockSize < 4096) vars->blockSize = 4096; HIBLOG("polled file major %d, minor %d, blocksize %ld, pollers %d\n", major(image_dev), minor(image_dev), (long)vars->blockSize, vars->pollers->pollers->getCount()); OSString * keyUUID = NULL; if (volumeCryptKey) { err = IOGetVolumeCryptKey(block_dev, &keyUUID, volumeCryptKey, keySize); } *fileVars = vars; vars->fileExtents = extentsData; // make imagePath OSData * data; if (imagePath) { #if defined(__i386__) || defined(__x86_64__) char str2[24 + sizeof(uuid_string_t) + 2]; if (keyUUID) snprintf(str2, sizeof(str2), "%qx:%s", vars->extentMap[0].start, keyUUID->getCStringNoCopy()); else snprintf(str2, sizeof(str2), "%qx", vars->extentMap[0].start); err = IOService::getPlatform()->callPlatformFunction( gIOCreateEFIDevicePathSymbol, false, (void *) part, (void *) str2, (void *) (uintptr_t) true, (void *) &data); #else data = 0; err = kIOReturnSuccess; #endif if (kIOReturnSuccess != err) { HIBLOG("error 0x%x getting path\n", err); break; } *imagePath = data; } } while (false); if (kIOReturnSuccess != err) { HIBLOG("error 0x%x opening polled file\n", err); IOPolledFileClose(&vars, 0, 0, 0, 0, 0); } if (part) part->release(); return (err); }
int _time_initialize(void) { #if FOUNDATION_PLATFORM_WINDOWS tick_t unused; if (!QueryPerformanceFrequency((LARGE_INTEGER*)&_time_freq) || !QueryPerformanceCounter((LARGE_INTEGER*)&unused)) return -1; #elif FOUNDATION_PLATFORM_APPLE if (mach_timebase_info(&_time_info)) return -1; _time_freq = 1000000000LL; #elif FOUNDATION_PLATFORM_POSIX || FOUNDATION_PLATFORM_PNACL struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; if (clock_gettime(CLOCK_MONOTONIC, &ts)) return -1; _time_freq = 1000000000LL; #else # error Not implemented #endif _time_oofreq = 1.0 / (double)_time_freq; _time_startup = time_current(); return 0; } void _time_finalize(void) { } tick_t time_current(void) { #if FOUNDATION_PLATFORM_WINDOWS tick_t curclock; QueryPerformanceCounter((LARGE_INTEGER*)&curclock); return curclock; #elif FOUNDATION_PLATFORM_APPLE tick_t curclock = 0; absolutetime_to_nanoseconds(mach_absolute_time(), &curclock); return curclock; #elif FOUNDATION_PLATFORM_POSIX || FOUNDATION_PLATFORM_PNACL struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime(CLOCK_MONOTONIC, &ts); return ((tick_t)ts.tv_sec * 1000000000LL) + (tick_t)ts.tv_nsec; #else # error Not implemented #endif } tick_t time_startup(void) { return _time_startup; } tick_t time_ticks_per_second(void) { return _time_freq; } tick_t time_diff(const tick_t from, const tick_t to) { return (to - from); } deltatime_t time_elapsed(const tick_t t) { tick_t ticks = time_elapsed_ticks(t); return (deltatime_t)((double)ticks * _time_oofreq); }
tick_t time_elapsed_ticks(const tick_t t) { tick_t dt; #if FOUNDATION_PLATFORM_WINDOWS tick_t curclock = t; QueryPerformanceCounter((LARGE_INTEGER*)&curclock); dt = curclock - t; #elif FOUNDATION_PLATFORM_APPLE tick_t curclock = t; absolutetime_to_nanoseconds(mach_absolute_time(), &curclock); dt = curclock - t; #elif FOUNDATION_PLATFORM_POSIX || FOUNDATION_PLATFORM_PNACL tick_t curclock; struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime(CLOCK_MONOTONIC, &ts); curclock = ((tick_t)ts.tv_sec * 1000000000LL) + ts.tv_nsec; dt = curclock - t; #else # error Not implemented dt = 0; #endif return dt; } deltatime_t time_ticks_to_seconds(const tick_t dt) { return (deltatime_t)((double)dt * _time_oofreq); } #if FOUNDATION_PLATFORM_WINDOWS && ( FOUNDATION_COMPILER_MSVC || FOUNDATION_COMPILER_INTEL ) #include <sys/timeb.h> #endif tick_t time_system(void) { #if FOUNDATION_PLATFORM_WINDOWS /*lint --e{754,534} */ struct __timeb64 tb; _ftime64_s(&tb); return ((tick_t)tb.time * 1000LL) + (tick_t)tb.millitm; #elif FOUNDATION_PLATFORM_APPLE tick_t curclock = 0; absolutetime_to_nanoseconds(mach_absolute_time(), &curclock); return (curclock / 1000000LL); #elif FOUNDATION_PLATFORM_POSIX || FOUNDATION_PLATFORM_PNACL struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime(CLOCK_REALTIME, &ts); return ((int64_t)ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000LL); #else # error Not implemented #endif }
kern_return_t thread_info_internal( register thread_t thread, thread_flavor_t flavor, thread_info_t thread_info_out, /* ptr to OUT array */ mach_msg_type_number_t *thread_info_count) /*IN/OUT*/ { int state, flags; spl_t s; if (thread == THREAD_NULL) return (KERN_INVALID_ARGUMENT); if (flavor == THREAD_BASIC_INFO) { register thread_basic_info_t basic_info; if (*thread_info_count < THREAD_BASIC_INFO_COUNT) return (KERN_INVALID_ARGUMENT); basic_info = (thread_basic_info_t) thread_info_out; s = splsched(); thread_lock(thread); /* fill in info */ thread_read_times(thread, &basic_info->user_time, &basic_info->system_time); /* * Update lazy-evaluated scheduler info because someone wants it. */ if (SCHED(can_update_priority)(thread)) SCHED(update_priority)(thread); basic_info->sleep_time = 0; /* * To calculate cpu_usage, first correct for timer rate, * then for 5/8 ageing. The correction factor [3/5] is * (1/(5/8) - 1). */ basic_info->cpu_usage = 0; #if defined(CONFIG_SCHED_TRADITIONAL) if (sched_tick_interval) { basic_info->cpu_usage = (integer_t)(((uint64_t)thread->cpu_usage * TH_USAGE_SCALE) / sched_tick_interval); basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5; } #endif if (basic_info->cpu_usage > TH_USAGE_SCALE) basic_info->cpu_usage = TH_USAGE_SCALE; basic_info->policy = ((thread->sched_mode == TH_MODE_TIMESHARE)? POLICY_TIMESHARE: POLICY_RR); flags = 0; if (thread->bound_processor != PROCESSOR_NULL && thread->bound_processor->idle_thread == thread) flags |= TH_FLAGS_IDLE; if (!thread->kernel_stack) flags |= TH_FLAGS_SWAPPED; state = 0; if (thread->state & TH_TERMINATE) state = TH_STATE_HALTED; else if (thread->state & TH_RUN) state = TH_STATE_RUNNING; else if (thread->state & TH_UNINT) state = TH_STATE_UNINTERRUPTIBLE; else if (thread->state & TH_SUSP) state = TH_STATE_STOPPED; else if (thread->state & TH_WAIT) state = TH_STATE_WAITING; basic_info->run_state = state; basic_info->flags = flags; basic_info->suspend_count = thread->user_stop_count; thread_unlock(thread); splx(s); *thread_info_count = THREAD_BASIC_INFO_COUNT; return (KERN_SUCCESS); } else if (flavor == THREAD_IDENTIFIER_INFO) { register thread_identifier_info_t identifier_info; if (*thread_info_count < THREAD_IDENTIFIER_INFO_COUNT) return (KERN_INVALID_ARGUMENT); identifier_info = (thread_identifier_info_t) thread_info_out; s = splsched(); thread_lock(thread); identifier_info->thread_id = thread->thread_id; identifier_info->thread_handle = thread->machine.cthread_self; if(thread->task->bsd_info) { identifier_info->dispatch_qaddr = identifier_info->thread_handle + get_dispatchqueue_offset_from_proc(thread->task->bsd_info); } else { thread_unlock(thread); splx(s); return KERN_INVALID_ARGUMENT; } thread_unlock(thread); splx(s); return KERN_SUCCESS; } else if (flavor == THREAD_SCHED_TIMESHARE_INFO) { policy_timeshare_info_t ts_info; if (*thread_info_count < POLICY_TIMESHARE_INFO_COUNT) return (KERN_INVALID_ARGUMENT); ts_info = (policy_timeshare_info_t)thread_info_out; s = splsched(); thread_lock(thread); if (thread->sched_mode != TH_MODE_TIMESHARE) { thread_unlock(thread); splx(s); return (KERN_INVALID_POLICY); } ts_info->depressed = (thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) != 0; if (ts_info->depressed) { ts_info->base_priority = DEPRESSPRI; ts_info->depress_priority = thread->priority; } else { ts_info->base_priority = thread->priority; ts_info->depress_priority = -1; } ts_info->cur_priority = thread->sched_pri; ts_info->max_priority = thread->max_priority; thread_unlock(thread); splx(s); *thread_info_count = POLICY_TIMESHARE_INFO_COUNT; return (KERN_SUCCESS); } else if (flavor == THREAD_SCHED_FIFO_INFO) { if (*thread_info_count < POLICY_FIFO_INFO_COUNT) return (KERN_INVALID_ARGUMENT); return (KERN_INVALID_POLICY); } else if (flavor == THREAD_SCHED_RR_INFO) { policy_rr_info_t rr_info; uint32_t quantum_time; uint64_t quantum_ns; if (*thread_info_count < POLICY_RR_INFO_COUNT) return (KERN_INVALID_ARGUMENT); rr_info = (policy_rr_info_t) thread_info_out; s = splsched(); thread_lock(thread); if (thread->sched_mode == TH_MODE_TIMESHARE) { thread_unlock(thread); splx(s); return (KERN_INVALID_POLICY); } rr_info->depressed = (thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) != 0; if (rr_info->depressed) { rr_info->base_priority = DEPRESSPRI; rr_info->depress_priority = thread->priority; } else { rr_info->base_priority = thread->priority; rr_info->depress_priority = -1; } quantum_time = SCHED(initial_quantum_size)(THREAD_NULL); absolutetime_to_nanoseconds(quantum_time, &quantum_ns); rr_info->max_priority = thread->max_priority; rr_info->quantum = (uint32_t)(quantum_ns / 1000 / 1000); thread_unlock(thread); splx(s); *thread_info_count = POLICY_RR_INFO_COUNT; return (KERN_SUCCESS); } return (KERN_INVALID_ARGUMENT); }
int _time_initialize( void ) { #if FOUNDATION_PLATFORM_WINDOWS tick_t unused; if( !QueryPerformanceFrequency( (LARGE_INTEGER*)&_time_freq ) || !QueryPerformanceCounter( (LARGE_INTEGER*)&unused ) ) return -1; #elif FOUNDATION_PLATFORM_APPLE if( mach_timebase_info( &_time_info ) ) return -1; _time_freq = 1000000000ULL; #elif FOUNDATION_PLATFORM_POSIX struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; if( clock_gettime( CLOCK_MONOTONIC, &ts ) ) return -1; _time_freq = 1000000000ULL; #endif _time_oofreq = REAL_C(1.0) / (double)_time_freq; _time_startup = time_current(); return 0; } void _time_shutdown( void ) { } tick_t time_current( void ) { #if FOUNDATION_PLATFORM_WINDOWS tick_t curclock; QueryPerformanceCounter( (LARGE_INTEGER*)&curclock ); return curclock; #elif FOUNDATION_PLATFORM_APPLE tick_t curclock = 0; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); return curclock; #elif FOUNDATION_PLATFORM_POSIX struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); return ( (uint64_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; #endif } tick_t time_startup( void ) { return _time_startup; } tick_t time_ticks_per_second( void ) { return _time_freq; } tick_t time_diff( const tick_t from, const tick_t to ) { if( to <= from ) return 0; return ( to - from ); } deltatime_t time_elapsed( const tick_t t ) { return (deltatime_t)( (double)time_elapsed_ticks( t ) * _time_oofreq ); } tick_t time_elapsed_ticks( const tick_t t ) { tick_t dt = 0; #if FOUNDATION_PLATFORM_WINDOWS tick_t curclock = t; QueryPerformanceCounter( (LARGE_INTEGER*)&curclock ); dt = curclock - t; #elif FOUNDATION_PLATFORM_APPLE tick_t curclock = t; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); dt = curclock - t; #elif FOUNDATION_PLATFORM_POSIX tick_t curclock; struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); curclock = ( (tick_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; dt = curclock - t; #endif return dt; } deltatime_t time_ticks_to_seconds( const tick_t dt ) { return (deltatime_t)( (double)dt * _time_oofreq ); } #if FOUNDATION_PLATFORM_WINDOWS struct __timeb64 { __time64_t time; unsigned short millitm; short timezone; short dstflag; };
RTDECL(uint32_t) RTSemEventMultiGetResolution(void) { uint64_t cNs; absolutetime_to_nanoseconds(1, &cNs); return (uint32_t)cNs ? (uint32_t)cNs : 0; }
void AppleUSBUHCI::UIMRootHubStatusChange(void) { UInt8 bitmap, bit; unsigned int i, index, move; IOUSBHubPortStatus portStatus; USBLog(7, "AppleUSBUHCI[%p]::UIMRootHubStatusChange (_controllerAvailable: %d)", this, _controllerAvailable); if (_controllerAvailable && !_wakingFromHibernation) { // For UHCI, we first need to see if we have a pending resume RHCheckStatus(); // Assume a byte can hold all port bits. assert(kUHCI_NUM_PORTS < 8); /* * Encode the status change bitmap. The format of the bitmap: * bit0 = hub status changed * bit1 = port 1 status changed * bit2 = port 2 status changed * ... * See USB 1.0 spec section 11.8.3 for more info. */ bitmap = 0; bit = 0x2; for (i=1; i <= kUHCI_NUM_PORTS; i++) { GetRootHubPortStatus(&portStatus, i); if (portStatus.changeFlags != 0) { UInt64 elapsedTime; uint64_t currentTime; USBLog(5, "AppleUSBUHCI[%p]::UIMRootHubStatusChange Port %d hub flags:", this, i); RHDumpHubPortStatus(&portStatus); bitmap |= bit; // If this port has seen a recovery attempt (see below) already, check to see what the current time is and if it's > than 2 seconds since the port recovery, then 'forget" about it currentTime = mach_absolute_time(); SUB_ABSOLUTETIME(¤tTime, &_portRecoveryTime[i-1] ); absolutetime_to_nanoseconds(*(AbsoluteTime *)¤tTime, &elapsedTime); elapsedTime /= 1000000000; // Convert to seconds from nanoseconds if ( _previousPortRecoveryAttempted[i-1] && (elapsedTime >= kUHCITimeoutForPortRecovery) ) { USBLog(2, "AppleUSBUHCI[%p]::UIMRootHubStatusChange Forgetting about our portRecovery state since the last change occurred %qd seconds ago", this, elapsedTime); _previousPortRecoveryAttempted[i-1] = false; } // If this port has a PED (port enable change) AND the current status is PortPower and Port Connection (which indicates that a condition // on the bus caused the controller to disable the port) then we need to see if we should attempt to re-enable the port w/out calling the // hub driver. We will do this ONLY if the previous root hub status change for this port did NOT attempt this recovery -- we only try once if ( !_previousPortRecoveryAttempted[i-1] ) { USBLog(7, "AppleUSBUHCI[%p]::UIMRootHubStatusChange Port %d had a change: 0x%x", this, i, portStatus.changeFlags); if ( !(portStatus.statusFlags & kHubPortEnabled) // if we are not presently enabled && (portStatus.changeFlags & kHubPortEnabled) // and we were previously enabled && (portStatus.statusFlags & kHubPortConnection) // and we are presently connected && !(portStatus.changeFlags & kHubPortConnection) // and the connection has not recently changed (i.e. quick disconnect-connect) && (portStatus.statusFlags & kHubPortPower) ) // and the power is on { // Indicate that we are attempting a recovery _previousPortRecoveryAttempted[i-1] = true; currentTime = mach_absolute_time(); _portRecoveryTime[i-1] = *(AbsoluteTime*)¤tTime; USBLog(1, "AppleUSBUHCI[%p]::UIMRootHubStatusChange Port %d attempting to enable a disabled port to work around a fickle UHCI controller", this, i); USBTrace( kUSBTUHCI, kTPUHCIRootHubStatusChange, (uintptr_t)this, portStatus.statusFlags, portStatus.changeFlags, i ); RHEnablePort(i, true); // Clear the bitmap bitmap &= ~bit; } } else { // If this is just the notification that the port has been enabled, then don't reset our previousPortRecoveryAttempt if ( (portStatus.changeFlags & kHubPortEnabled) and (portStatus.statusFlags & kHubPortConnection) and (portStatus.statusFlags & kHubPortPower) and (portStatus.statusFlags & kHubPortEnabled) ) { USBLog(2, "AppleUSBUHCI[%p]::UIMRootHubStatusChange Port %d had a change but it's just the port enabled notification", this, i); } else { USBLog(2, "AppleUSBUHCI[%p]::UIMRootHubStatusChange Port %d had a change but last time we attempted a recovery, so not attempting again", this, i); _previousPortRecoveryAttempted[i-1] = false; } } } bit <<= 1; // Don't clear status bits until explicitly told to. } if (bitmap) { USBLog(5, "AppleUSBUHCI[%p]::UIMRootHubStatusChange RH status bitmap = %x", this, bitmap); } _rootHubStatusChangedBitmap = bitmap; } // Bitmap is only one byte, so it doesn't need swapping. }
IOService* BrcmPatchRAM::probe(IOService *provider, SInt32 *probeScore) { uint64_t start_time, end_time, nano_secs; DebugLog("probe\n"); AlwaysLog("Version %s starting on OS X Darwin %d.%d.\n", OSKextGetCurrentVersionString(), version_major, version_minor); #ifdef TARGET_ELCAPITAN // preference towards starting BrcmPatchRAM2.kext when BrcmPatchRAM.kext also exists *probeScore = 2000; #endif #ifndef TARGET_ELCAPITAN // BrcmPatchRAM.kext, if installed on 10.11+... fails immediately if (version_major >= 15) { AlwaysLog("Aborting -- BrcmPatchRAM.kext should not be installed on 10.11+. Use BrcmPatchRAM2.kext instead.\n"); return NULL; } #endif clock_get_uptime(&start_time); #ifndef NON_RESIDENT mWorkLock = IOLockAlloc(); if (!mWorkLock) return NULL; // Note: mLoadFirmwareLock is static (global), not instance data... if (!mLoadFirmwareLock) return NULL; #endif mCompletionLock = IOLockAlloc(); if (!mCompletionLock) return NULL; mDevice.setDevice(provider); if (!mDevice.getValidatedDevice()) { AlwaysLog("Provider type is incorrect (not IOUSBDevice or IOUSBHostDevice)\n"); return NULL; } // personality strings depend on version initBrcmStrings(); #ifndef NON_RESIDENT // longest time seen in normal re-probe was ~200ms (400+ms on 10.11) if (version_major >= 15) mBlurpWait = 800; else mBlurpWait = 400; #endif OSString* displayName = OSDynamicCast(OSString, getProperty(kDisplayName)); if (displayName) provider->setProperty(kUSBProductString, displayName); mVendorId = mDevice.getVendorID(); mProductId = mDevice.getProductID(); // get firmware here to pre-cache for eventual use on wakeup or now if (OSString* firmwareKey = OSDynamicCast(OSString, getProperty(kFirmwareKey))) { if (BrcmFirmwareStore* firmwareStore = getFirmwareStore()) firmwareStore->getFirmware(mVendorId, mProductId, firmwareKey); } uploadFirmware(); publishPersonality(); clock_get_uptime(&end_time); absolutetime_to_nanoseconds(end_time - start_time, &nano_secs); uint64_t milli_secs = nano_secs / 1000000; AlwaysLog("Processing time %llu.%llu seconds.\n", milli_secs / 1000, milli_secs % 1000); #ifdef NON_RESIDENT // maybe residency is not required for 10.11? mDevice.setDevice(NULL); return NULL; #endif return this; }
kern_return_t host_info( host_t host, host_flavor_t flavor, host_info_t info, mach_msg_type_number_t *count) { if (host == HOST_NULL) return (KERN_INVALID_ARGUMENT); switch (flavor) { case HOST_BASIC_INFO: { register host_basic_info_t basic_info; register int master_id; /* * Basic information about this host. */ if (*count < HOST_BASIC_INFO_OLD_COUNT) return (KERN_FAILURE); basic_info = (host_basic_info_t) info; basic_info->memory_size = machine_info.memory_size; basic_info->max_cpus = machine_info.max_cpus; basic_info->avail_cpus = processor_avail_count; master_id = master_processor->cpu_id; basic_info->cpu_type = slot_type(master_id); basic_info->cpu_subtype = slot_subtype(master_id); if (*count >= HOST_BASIC_INFO_COUNT) { basic_info->cpu_threadtype = slot_threadtype(master_id); basic_info->physical_cpu = machine_info.physical_cpu; basic_info->physical_cpu_max = machine_info.physical_cpu_max; basic_info->logical_cpu = machine_info.logical_cpu; basic_info->logical_cpu_max = machine_info.logical_cpu_max; basic_info->max_mem = machine_info.max_mem; *count = HOST_BASIC_INFO_COUNT; } else { *count = HOST_BASIC_INFO_OLD_COUNT; } return (KERN_SUCCESS); } case HOST_SCHED_INFO: { register host_sched_info_t sched_info; uint32_t quantum_time; uint64_t quantum_ns; /* * Return scheduler information. */ if (*count < HOST_SCHED_INFO_COUNT) return (KERN_FAILURE); sched_info = (host_sched_info_t) info; quantum_time = SCHED(initial_quantum_size)(THREAD_NULL); absolutetime_to_nanoseconds(quantum_time, &quantum_ns); sched_info->min_timeout = sched_info->min_quantum = (uint32_t)(quantum_ns / 1000 / 1000); *count = HOST_SCHED_INFO_COUNT; return (KERN_SUCCESS); } case HOST_RESOURCE_SIZES: { /* * Return sizes of kernel data structures */ if (*count < HOST_RESOURCE_SIZES_COUNT) return (KERN_FAILURE); /* XXX Fail until ledgers are implemented */ return (KERN_INVALID_ARGUMENT); } case HOST_PRIORITY_INFO: { register host_priority_info_t priority_info; if (*count < HOST_PRIORITY_INFO_COUNT) return (KERN_FAILURE); priority_info = (host_priority_info_t) info; priority_info->kernel_priority = MINPRI_KERNEL; priority_info->system_priority = MINPRI_KERNEL; priority_info->server_priority = MINPRI_RESERVED; priority_info->user_priority = BASEPRI_DEFAULT; priority_info->depress_priority = DEPRESSPRI; priority_info->idle_priority = IDLEPRI; priority_info->minimum_priority = MINPRI_USER; priority_info->maximum_priority = MAXPRI_RESERVED; *count = HOST_PRIORITY_INFO_COUNT; return (KERN_SUCCESS); } /* * Gestalt for various trap facilities. */ case HOST_MACH_MSG_TRAP: case HOST_SEMAPHORE_TRAPS: { *count = 0; return (KERN_SUCCESS); } default: return (KERN_INVALID_ARGUMENT); } }
unsigned long mach_jiffies(void) { uint64_t nanoseconds; absolutetime_to_nanoseconds(mach_absolute_time(), &nanoseconds); return(nanoseconds/10000); }
void BrcmPatchRAM::stop(IOService* provider) { #ifdef DEBUG uint64_t stop_time, nano_secs; clock_get_uptime(&stop_time); absolutetime_to_nanoseconds(stop_time - wake_time, &nano_secs); uint64_t milli_secs = nano_secs / 1000000; AlwaysLog("Time since wake %llu.%llu seconds.\n", milli_secs / 1000, milli_secs % 1000); #endif DebugLog("stop\n"); #if 0 #ifndef TARGET_ELCAPITAN //REVIEW: so kext can be unloaded with kextunload -p // unload native bluetooth driver IOReturn result = gIOCatalogue->terminateDriversForModule(brcmBundleIdentifier, false); if (result != kIOReturnSuccess) AlwaysLog("[%04x:%04x]: failure terminating native Broadcom bluetooth (%08x)\n", mVendorId, mProductId, result); else DebugLog("[%04x:%04x]: success terminating native Broadcom bluetooth\n", mVendorId, mProductId); // unpublish native bluetooth personality removePersonality(); #endif #endif mStopping = true; // allow firmware load already started to finish IOLockLock(mLoadFirmwareLock); OSSafeReleaseNULL(mFirmwareStore); IOWorkLoop* workLoop = getWorkLoop(); if (workLoop) { if (mTimer) { mTimer->cancelTimeout(); workLoop->removeEventSource(mTimer); mTimer->release(); mTimer = NULL; } if (mWorkSource) { workLoop->removeEventSource(mWorkSource); mWorkSource->release(); mWorkSource = NULL; mWorkPending = 0; } } PMstop(); if (mCompletionLock) { IOLockFree(mCompletionLock); mCompletionLock = NULL; } #ifndef NON_RESIDENT if (mWorkLock) { IOLockFree(mWorkLock); mWorkLock = NULL; } IOLockUnlock(mLoadFirmwareLock); #endif // #ifndef NON_RESIDENT mDevice.setDevice(NULL); mStopping = false; super::stop(provider); }
static void panic_display_uptime(void) { uint64_t uptime; absolutetime_to_nanoseconds(mach_absolute_time(), &uptime); kdb_printf("\nSystem uptime in nanoseconds: %llu\n", uptime); }
bool AppleUSBDiagnostics::serialize( OSSerialize * s ) const { OSDictionary * dictionary; bool ok; UInt64 currms; UInt32 deltams; AbsoluteTime now; dictionary = OSDictionary::withCapacity( 4 ); if( !dictionary ) return false; USBLog(6, "AppleUSBDiagnostics[%p]::serialize", this); _UIMDiagnostics->acessCount++; UpdateNumberEntry( dictionary, _UIMDiagnostics->acessCount, "Access Count"); UpdateNumberEntry( dictionary, _UIMDiagnostics->totalErrors, "Errors (Total)"); UpdateNumberEntry( dictionary, _UIMDiagnostics->totalErrors-_UIMDiagnostics->prevErrors, "Errors (New)"); _UIMDiagnostics->prevErrors = _UIMDiagnostics->totalErrors; UpdateNumberEntry( dictionary, gUSBStackDebugFlags, "Debug Flags"); if( (gUSBStackDebugFlags & kUSBEnableErrorLogMask) != 0) { UpdateNumberEntry( dictionary, _UIMDiagnostics->recoveredErrors, "Recovered Errors"); UpdateNumberEntry( dictionary, _UIMDiagnostics->recoveredErrors-_UIMDiagnostics->prevRecoveredErrors, "Recovered Errors (New)"); _UIMDiagnostics->prevRecoveredErrors = _UIMDiagnostics->recoveredErrors; UpdateNumberEntry( dictionary, _UIMDiagnostics->errors2Strikes, "Recovered 2 strike errors"); UpdateNumberEntry( dictionary, _UIMDiagnostics->errors2Strikes-_UIMDiagnostics->prevErrors2Strikes, "Recovered 2 strike errors (New)"); _UIMDiagnostics->prevErrors2Strikes = _UIMDiagnostics->errors2Strikes; UpdateNumberEntry( dictionary, _UIMDiagnostics->errors3Strikes, "Fatal 3 strike errors"); UpdateNumberEntry( dictionary, _UIMDiagnostics->errors3Strikes-_UIMDiagnostics->prevErrors3Strikes, "Fatal 3 strike errors (New)"); _UIMDiagnostics->prevErrors3Strikes = _UIMDiagnostics->errors3Strikes; if(_UIMDiagnostics->numPorts) { UpdateNumberEntry( dictionary, _UIMDiagnostics->numPorts, "Number of ports"); for(int i=0; i<_UIMDiagnostics->numPorts; i++) { char buf[64]; OSDictionary * portDictionary = OSDictionary::withCapacity(1); serializePort(portDictionary, i, &_UIMDiagnostics->portCounts[i], _controller); snprintf(buf, 63, "Port %2d", i+1); dictionary->setObject( buf, portDictionary ); portDictionary->release(); } } } clock_get_uptime(&now); absolutetime_to_nanoseconds(now, &currms); deltams = ((currms-_UIMDiagnostics->lastNanosec)/1000000)+1; // +1 so this is never zero, makes little difference if delta ms is large UpdateNumberEntry( dictionary, currms/1000000, "ms (Current)"); UpdateNumberEntry( dictionary, deltams, "ms (since last read)"); _UIMDiagnostics->lastNanosec = currms; UpdateNumberEntry( dictionary, _UIMDiagnostics->totalBytes, "Bytes"); UpdateNumberEntry( dictionary, _UIMDiagnostics->totalBytes-_UIMDiagnostics->prevBytes, "Bytes (New)"); UpdateNumberEntry( dictionary, (_UIMDiagnostics->totalBytes-_UIMDiagnostics->prevBytes)/deltams, "Bytes (New)/ms"); _UIMDiagnostics->prevBytes = _UIMDiagnostics->totalBytes; UpdateNumberEntry( dictionary, _UIMDiagnostics->timeouts, "Timeouts"); UpdateNumberEntry( dictionary, _UIMDiagnostics->timeouts-_UIMDiagnostics->prevTimeouts, "Timeouts (New)"); _UIMDiagnostics->prevTimeouts = _UIMDiagnostics->timeouts; UpdateNumberEntry( dictionary, _UIMDiagnostics->resets, "Resets"); UpdateNumberEntry( dictionary, _UIMDiagnostics->resets-_UIMDiagnostics->prevResets, "Resets (New)"); _UIMDiagnostics->prevResets = _UIMDiagnostics->resets; if(_controlBulkTransactionsOut) { // EHCI keeps a note of this separately, maybe it should be in the diagnostics struct _UIMDiagnostics->controlBulkTxOut = *_controlBulkTransactionsOut; } else { _UIMDiagnostics->controlBulkTxOut = 0; } UpdateNumberEntry( dictionary, _UIMDiagnostics->controlBulkTxOut, "ControlBulkTxOut"); ok = dictionary->serialize(s); dictionary->release(); return ok; }
void timer_reset( timer* time ) { #if defined( _WIN32 ) || defined( _WIN64 ) QueryPerformanceCounter( (LARGE_INTEGER*)&time->clock ); #if USE_FALLBACK time->ref = timeGetTime(); #endif #elif __APPLE__ absolutetime_to_nanoseconds( mach_absolute_time(), &time->clock ); #else struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); time->clock = ( (tick_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; #endif } deltatime_t timer_elapsed( timer* time, int reset ) { return (deltatime_t)timer_elapsed_ticks( time, reset ) * time->oofreq; } tick_t timer_elapsed_ticks( timer* time, int reset ) { tick_t dt = 0; #if defined( _WIN32 ) || defined( _WIN64 ) tick_t diff; #if USE_FALLBACK tick_t refdiff; deltatime_t timerdiff; tick_t ref = time->ref; #endif tick_t curclock = time->clock; QueryPerformanceCounter( (LARGE_INTEGER*)&curclock ); #if USE_FALLBACK ref = timeGetTime(); #endif diff = curclock - time->clock; #if USE_FALLBACK refdiff = ref - time->ref; if( ref < time->ref ) refdiff = (tick_t)( 1000.0 * diff * time->oofreq ); //Catch looping of the millisecond counter timerdiff = (deltatime_t)( ( diff * time->oofreq ) - ( refdiff * 0.001 ) ); if( ( diff < 0 ) || ( timerdiff > 0.1 ) || ( timerdiff < -0.1 ) ) diff = (tick_t)( ( refdiff * 0.001 ) * time->freq ); //Performance counter messed up, transform reference to counter frequency #endif dt = diff; #if USE_FALLBACK if( reset ) time->ref = ref; #endif #elif __APPLE__ tick_t curclock = time->clock; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); dt = curclock - time->clock; #else tick_t curclock; struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); curclock = ( (tick_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; dt = curclock - time->clock; #endif if( reset ) time->clock = curclock; return dt; } tick_t timer_ticks_per_second( timer* time ) { return time->freq; } tick_t timer_current() { #if defined( _WIN32 ) || defined( _WIN64 ) //TODO: Fallback to timeGetTime for messed up perf counter values tick_t curclock; QueryPerformanceCounter( (LARGE_INTEGER*)&curclock ); return curclock; #elif __APPLE__ tick_t curclock = 0; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); return curclock; #else struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_MONOTONIC, &ts ); return ( (uint64_t)ts.tv_sec * 1000000000ULL ) + ts.tv_nsec; #endif } tick_t timer_current_ticks_per_second() { #if defined( _WIN32 ) || defined( _WIN64 ) return _timerlib_curtime_freq; #elif __APPLE__ return 1000000000; #else return 1000000000; #endif } #if defined( _WIN32 ) || defined( _WIN64 ) # if _MSC_VER # include <sys/timeb.h> # else struct __timeb64 { __time64_t time; unsigned short millitm; short timezone; short dstflag; }; _CRTIMP errno_t __cdecl _ftime64_s(_Out_ struct __timeb64 * _Time); # endif #endif tick_t timer_system() { #if defined( _WIN32 ) || defined( _WIN64 ) struct __timeb64 tb; _ftime64_s( &tb ); return ( (tick_t)tb.time * 1000ULL ) + (tick_t)tb.millitm; #elif __APPLE__ tick_t curclock = 0; absolutetime_to_nanoseconds( mach_absolute_time(), &curclock ); return ( curclock / 1000000ULL ); #else struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; clock_gettime( CLOCK_REALTIME, &ts ); return ( (uint64_t)ts.tv_sec * 1000ULL ) + ( ts.tv_nsec / 1000000ULL ); #endif }