-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Omnibus to implement CFRunLoop with kevent. #3004
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
cc @millenomi -- input or advice on how to proceed? |
26ac266
to
757836f
Compare
@compnerd any thoughts? |
@parkera, mind reviewing? |
@phausler, maybe you could review? |
CFRunLoop has a recurring abstraction for platform-specific code, but it is a little leaky. Plug these leaks: ensure `MACH_PORT_NULL` in the generic, non-platform context is rewritten as `CFPORT_NULL`, and ensure that `kern_return_t` and `KERN_SUCCESS` are defined properly.
New platforms must define these types and functions; it is incorrect to not have #else cases here.
757836f
to
a36dd52
Compare
@etcwilde, would you review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine for the most part. I left a couple comments on style.
I'm unfortunately not familiar enough with this part of the codebase to really identify logic/behavior issues in the implementation of the __CFPort*
or mk_timer
function implementations down in CFRunLoop.c
. It looks fine from what I can tell, but it would be better to get someone more familiar with this code to look over it and verify that it's correct.
As I'm not very familiar with this part of the codebase, nor am I an owner or maintainer of foundation, I don't really feel comfortable just approving it. I'll leave that part up to @parkera.
static inline uint64_t __CFNanosecondsToTSR(uint64_t ns) { | ||
#if TARGET_OS_MAC || TARGET_OS_LINUX | ||
return ns; | ||
#else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@compnerd, is this the appropriate implementation of this function for Windows?
@@ -249,7 +249,11 @@ const char *_CFProcessPath(void) { | |||
|
|||
#if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_BSD | |||
CF_CROSS_PLATFORM_EXPORT Boolean _CFIsMainThread(void) { | |||
#if !defined(__OpenBSD__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit clearer if we have the OpenBSD case come first and not invert the condition.
#if defined(__OpenBSD__) // special case for OpenBSD
return pthread_equal(pthread_self(), _CFMainPThread) != 0;
#else // everything else
return pthread_main_np() == 1;
#endif
I usually think of else
indicating anything not special-cased, so having the else only catch the OpenBSD case seems a bit odd.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reordered the conditional.
EV_SET( | ||
&tev, | ||
id, | ||
EVFILT_TIMER, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent indentation through here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Fixes SR-14288.
During runloop testing, log messages suggest that the runloop thinks the main thread has exited and certain runloop operations don't actually proceed. The flag for denoting when the main thread has exited is set in the thread-specific data destructor `__CFTSDFinalize`. This function detects whether the thread in question is the main thread via `pthread_main_np`, and has been observed in debugging this problem to return 1 on apparently non-main threads on OpenBSD. This obviously will cause the main thread exited flag to be erroneously set when non-main threads complete their work and dispose of thread-specific data. Instead, use the existing `_CFMainPThread` symbol set in `__CFInitialize` to determine the main thread. I am not sure whether the platform `pthread_main_np` is at fault here, but since this workaround makes the tests pass, let's use it.
a36dd52
to
13bc94f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
@swift-ci test |
I think that this might be causing the timeout on Windows ... |
* [runloop] Set up some symbols for generic code. CFRunLoop has a recurring abstraction for platform-specific code, but it is a little leaky. Plug these leaks: ensure `MACH_PORT_NULL` in the generic, non-platform context is rewritten as `CFPORT_NULL`, and ensure that `kern_return_t` and `KERN_SUCCESS` are defined properly. * [runloop] Remind porter these stubs are required. New platforms must define these types and functions; it is incorrect to not have #else cases here. * [runloop] Implement runloop abstraction for BSD. * [runloop] Avoid pthread_main_np on OpenBSD. During runloop testing, log messages suggest that the runloop thinks the main thread has exited and certain runloop operations don't actually proceed. The flag for denoting when the main thread has exited is set in the thread-specific data destructor `__CFTSDFinalize`. This function detects whether the thread in question is the main thread via `pthread_main_np`, and has been observed in debugging this problem to return 1 on apparently non-main threads on OpenBSD. This obviously will cause the main thread exited flag to be erroneously set when non-main threads complete their work and dispose of thread-specific data. Instead, use the existing `_CFMainPThread` symbol set in `__CFInitialize` to determine the main thread. I am not sure whether the platform `pthread_main_np` is at fault here, but since this workaround makes the tests pass, let's use it.
Omnibus to implement CFRunLoop with kevent. [runloop] Set up some symbols for generic code. CFRunLoop has a recurring abstraction for platform-specific code, but it is a little leaky. Plug these leaks: ensure `MACH_PORT_NULL` in the generic, non-platform context is rewritten as `CFPORT_NULL`, and ensure that `kern_return_t` and `KERN_SUCCESS` are defined properly. [runloop] Remind porter these stubs are required. New platforms must define these types and functions; it is incorrect to not have #else cases here. [runloop] Implement runloop abstraction for BSD. [runloop] Ensure timing arithmetic is done in ns. Fixes SR-14288. [runloop] Avoid pthread_main_np on OpenBSD. During runloop testing, log messages suggest that the runloop thinks the main thread has exited and certain runloop operations don't actually proceed. The flag for denoting when the main thread has exited is set in the thread-specific data destructor `__CFTSDFinalize`. This function detects whether the thread in question is the main thread via `pthread_main_np`, and has been observed in debugging this problem to return 1 on apparently non-main threads on OpenBSD. This obviously will cause the main thread exited flag to be erroneously set when non-main threads complete their work and dispose of thread-specific data. Instead, use the existing `_CFMainPThread` symbol set in `__CFInitialize` to determine the main thread. I am not sure whether the platform `pthread_main_np` is at fault here, but since this workaround makes the tests pass, let's use it.
Dispatch uses kevent for its event loop backend. However,
CFRunLoop
in Foundation uses Mach ports. This means for other kevent-based platforms such as OpenBSD, new runloop functionality is required, which this omnibus pr implements.This pr must be considered in concert with swiftlang/swift-corelibs-libdispatch#559 (see below).
Please feel free to request any or all to be split into multiple prs, though all these commits and the aforementioned Dispatch pr are required to properly implement
CFRunLoop
on this platform.Notes:
MACH_PORT_NULL
, for example, when we have symbols already defined likeCFPORT_NULL
. These are brought more into alignment for consistency.__CFPort*
andmk_timer_*
stubs. It does not make sense if these methods are not implemented for a given platform, so add a default#error
case. (The code would greatly benefit from reorganizing the necessary stubs to implement together in one#if
conditional, but this should probably be done separate from this omnibus as it is not critically important to achieve our result. However, we have implemented all the stubs together below in this commit.)pipe2
and packing each 32-bit fd in the pipe into a 64-bt integer. Since CFRunLoop fraternizes with Dispatch via_dispatch_main_queue_callback_4CF
, this means thatdispatch_runloop_handle_t
in Dispatch must match__CFPort
here. Unfortunately, this means that we have to perform some bit-packing shenanigans to handle kevent timers. There might be nicer ways to do this, but we'll defer that for now.pthread_main_np
and TSD on this platform. Work around this by doing a simple pthread_self comparison.