IOHIDUnitTestUtility.m [plain text]
//
// IOHIDUnitTestUtility.c
// IOHIDFamily
//
// Created by YG on 10/24/16.
//
//
#include "IOHIDUnitTestUtility.h"
#include <dispatch/private.h>
#include <mach/mach_time.h>
#include <AssertMacros.h>
int __IOHIDUnitTestAttributeInit(pthread_attr_t * p_pthread_attr, int priority, int policy);
void * __IOHIDUnitTestCreateRunLoopThread(void * context);
int __IOHIDUnitTestAttributeInit(pthread_attr_t * p_pthread_attr, int priority, int policy)
{
int err;
struct sched_param param;
err = pthread_attr_init(p_pthread_attr);
require_noerr(err, exit);
pthread_attr_setschedpolicy(p_pthread_attr, policy);
require_noerr(err, exit);
err = pthread_attr_getschedparam(p_pthread_attr, ¶m);
require_noerr(err, exit);
param.sched_priority = priority;
err = pthread_attr_setschedparam(p_pthread_attr, ¶m);
require_noerr(err, exit);
err = pthread_attr_setdetachstate(p_pthread_attr, PTHREAD_CREATE_JOINABLE);
require_noerr(err, exit);
exit:
if ( err != 0 )
pthread_attr_destroy( p_pthread_attr );
return err;
}
dispatch_queue_t IOHIDUnitTestCreateRootQueue (int priority, int poolSize) {
int ret;
dispatch_queue_t queue = nil;
pthread_attr_t attribute;
struct sched_param param;
ret = pthread_attr_init(&attribute);
if (ret) {
return queue;
}
ret = pthread_attr_setschedpolicy(&attribute, SCHED_RR);
if (ret) {
goto exit;
}
ret = pthread_attr_getschedparam(&attribute, ¶m);
if (ret) {
goto exit;
}
param.sched_priority = priority;
ret = pthread_attr_setschedparam(&attribute, ¶m);
if (ret) {
goto exit;
}
ret = pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_JOINABLE);
if (ret) {
goto exit;
}
queue = dispatch_pthread_root_queue_create("IOHIDUnitTestCreateRootQueue - Root", dispatch_pthread_root_queue_flags_pool_size(poolSize), &attribute, NULL);
exit:
pthread_attr_destroy(&attribute);
return queue;
}
uint64_t IOHIDInitTestAbsoluteTimeToNanosecond (uint64_t abs) {
static mach_timebase_info_data_t timebase;
if (!timebase.denom) {
mach_timebase_info(&timebase);
}
return (abs * timebase.numer) / (timebase.denom);
}
dispatch_semaphore_t __sema = NULL;
CFRunLoopRef __runLoop = NULL;
void * __IOHIDUnitTestCreateRunLoopThread(void * context __unused)
{
CFRunLoopRef runloop = CFRunLoopGetCurrent();
CFRunLoopSourceRef dummySource = NULL;
CFRunLoopSourceContext dummyContext = {};
dummySource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &dummyContext);
require(dummySource, exit);
__runLoop = runloop;
CFRunLoopAddSource(runloop, dummySource, kCFRunLoopDefaultMode);
dispatch_semaphore_signal(__sema);
CFRunLoopRun();
CFRunLoopRemoveSource(runloop, dummySource, kCFRunLoopDefaultMode);
exit:
if ( dummySource )
CFRelease(dummySource);
return NULL;
}
pthread_t hidThread;
CFRunLoopRef IOHIDUnitTestCreateRunLoop (int priority) {
pthread_attr_t attribute;
if (__IOHIDUnitTestAttributeInit (&attribute, priority, SCHED_RR)) {
return NULL;
}
__sema = dispatch_semaphore_create(0);
if (!pthread_create(&hidThread, &attribute,__IOHIDUnitTestCreateRunLoopThread, NULL)) {
dispatch_semaphore_wait(__sema, DISPATCH_TIME_FOREVER);
}
__sema = nil;
if (__runLoop) {
CFRetain(__runLoop);
}
return __runLoop;
}
void IOHIDUnitTestDestroyRunLoop (CFRunLoopRef runloop) {
CFRunLoopStop(runloop);
CFRelease(runloop);
}