ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/sys_darwin.cpp
(Generate patch)

Comparing BasiliskII/src/MacOSX/sys_darwin.cpp (file contents):
Revision 1.13 by gbeauche, 2008-01-01T09:40:32Z vs.
Revision 1.15 by asvitkine, 2008-07-20T07:38:27Z

# Line 48 | Line 48
48  
49  
50   // Global variables
51 < static CFRunLoopRef media_poll_loop = NULL;
51 > static volatile CFRunLoopRef media_poll_loop = NULL;
52   static bool media_thread_active = false;
53   static pthread_t media_thread;
54  
# Line 78 | Line 78 | void DarwinSysInit(void)
78   void DarwinSysExit(void)
79   {
80          // Stop media poll thread
81 <        if (media_poll_loop)
81 >        if (media_thread_active) {
82 >                while (media_poll_loop == NULL || !CFRunLoopIsWaiting(media_poll_loop))
83 >                        usleep(0);
84                  CFRunLoopStop(media_poll_loop);
83        if (media_thread_active)
85                  pthread_join(media_thread, NULL);
86 +                media_poll_loop = NULL;
87 +                media_thread_active = false;
88 +        }
89   }
90  
91  
# Line 115 | Line 119 | static kern_return_t get_device_path(io_
119   static void media_arrived(int type, io_iterator_t iterator)
120   {
121          io_object_t obj;
122 <        while ((obj = IOIteratorNext(iterator)) != NULL) {
122 >        while ((obj = IOIteratorNext(iterator))) {
123                  char path[MAXPATHLEN];
124                  kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
125                  if (kernResult == KERN_SUCCESS) {
# Line 137 | Line 141 | static void media_arrived(int type, io_i
141   static void media_removed(int type, io_iterator_t iterator)
142   {
143          io_object_t obj;
144 <        while ((obj = IOIteratorNext(iterator)) != NULL) {
144 >        while ((obj = IOIteratorNext(iterator))) {
145                  char path[MAXPATHLEN];
146                  kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
147                  if (kernResult == KERN_SUCCESS) {
# Line 154 | Line 158 | static void media_removed(int type, io_i
158  
159   /*
160   *  Media poll function
161 + *
162 + *  NOTE: to facilitate orderly thread termination, media_poll_func MUST end up waiting in CFRunLoopRun.
163 + *  Early returns must be avoided, even if there is nothing useful to be done here. See DarwinSysExit.
164   */
165  
166 + static void dummy(void *) { };  // stub for dummy runloop source
167 +
168   static void *media_poll_func(void *)
169   {
170          media_poll_loop = CFRunLoopGetCurrent();
171  
172          mach_port_t masterPort;
173 <        kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort);
174 <        if (kernResult != KERN_SUCCESS) {
175 <                fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
176 <                return NULL;
168 <        }
173 >        kern_return_t kernResult;
174 >        CFMutableDictionaryRef matchingDictionary;
175 >        CFRunLoopSourceRef loopSource = NULL;
176 >        CFRunLoopSourceRef dummySource = NULL;
177  
178 <        CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass);
179 <        if (matchingDictionary == NULL) {
178 >        if ((kernResult = IOMasterPort(bootstrap_port, &masterPort)) != KERN_SUCCESS)
179 >                fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
180 >        else if ((matchingDictionary = IOServiceMatching(kIOCDMediaClass)) == NULL)
181                  fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n");
182 <                return NULL;
182 >        else {
183 >                matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
184 >                IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
185 >                loopSource = IONotificationPortGetRunLoopSource(notificationPort);
186 >                CFRunLoopAddSource(media_poll_loop, loopSource, kCFRunLoopDefaultMode);
187 >
188 >                io_iterator_t mediaArrivedIterator;
189 >                kernResult = IOServiceAddMatchingNotification(notificationPort,
190 >                        kIOMatchedNotification,
191 >                        matchingDictionary,
192 >                        (IOServiceMatchingCallback)media_arrived,
193 >                        (void *)MEDIA_CD, &mediaArrivedIterator);
194 >                if (kernResult != KERN_SUCCESS)
195 >                        fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
196 >                media_arrived(MEDIA_CD, mediaArrivedIterator);
197 >
198 >                io_iterator_t mediaRemovedIterator;
199 >                kernResult = IOServiceAddMatchingNotification(notificationPort,
200 >                        kIOTerminatedNotification,
201 >                        matchingDictionary,
202 >                        (IOServiceMatchingCallback)media_removed,
203 >                        (void *)MEDIA_CD, &mediaRemovedIterator);
204 >                if (kernResult != KERN_SUCCESS)
205 >                        fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
206 >                media_removed(MEDIA_CD, mediaRemovedIterator);
207          }
175        matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
208  
209 <        IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
210 <        CFRunLoopAddSource(media_poll_loop,
211 <                                           IONotificationPortGetRunLoopSource(notificationPort),
212 <                                           kCFRunLoopDefaultMode);
213 <
214 <        io_iterator_t mediaArrivedIterator;
183 <        kernResult = IOServiceAddMatchingNotification(notificationPort,
184 <                                                                                                  kIOMatchedNotification,
185 <                                                                                                  matchingDictionary,
186 <                                                                                                  (IOServiceMatchingCallback)media_arrived,
187 <                                                                                                  (void *)MEDIA_CD, &mediaArrivedIterator);
188 <        if (kernResult != KERN_SUCCESS)
189 <                fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
190 <        media_arrived(MEDIA_CD, mediaArrivedIterator);
191 <
192 <        io_iterator_t mediaRemovedIterator;
193 <        kernResult = IOServiceAddMatchingNotification(notificationPort,
194 <                                                                                                  kIOTerminatedNotification,
195 <                                                                                                  matchingDictionary,
196 <                                                                                                  (IOServiceMatchingCallback)media_removed,
197 <                                                                                                  (void *)MEDIA_CD, &mediaRemovedIterator);
198 <        if (kernResult != KERN_SUCCESS)
199 <                fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
200 <        media_removed(MEDIA_CD, mediaRemovedIterator);
209 >        if (loopSource == NULL) {
210 >                // add a dummy runloop source to prevent premature return from CFRunLoopRun
211 >                CFRunLoopSourceContext context = { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, dummy };
212 >                dummySource = CFRunLoopSourceCreate(NULL, 0, &context);
213 >                CFRunLoopAddSource(media_poll_loop, dummySource, kCFRunLoopDefaultMode);
214 >        }
215  
216          CFRunLoopRun();
217 +
218 +        if (dummySource != NULL)
219 +                CFRelease(dummySource);
220          return NULL;
221   }
222  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines