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.9 by gbeauche, 2006-05-08T12:15:58Z vs.
Revision 1.15 by asvitkine, 2008-07-20T07:38:27Z

# Line 7 | Line 7
7   *
8   *      Based on Apple's CDROMSample.c and Evan Jones' cd-discid.c patches
9   *
10 < *  Basilisk II (C) 1997-2005 Christian Bauer
10 > *  Basilisk II (C) 1997-2008 Christian Bauer
11   *
12   *  This program is free software; you can redistribute it and/or modify
13   *  it under the terms of the GNU General Public License as published by
# 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  
# Line 236 | Line 253 | void DarwinAddFloppyPrefs(void)
253                  return;
254          }
255  
239
256          // Iterate through each floppy
257          while ( nextFloppy = IOIteratorNext(allFloppies))
258          {
259                  char            bsdPath[MAXPATHLEN];
244                CFTypeRef       bsdPathAsCFString =
245                                                IORegistryEntryCreateCFProperty(nextFloppy,
246                                                                                                                CFSTR(kIOBSDNameKey),
247                                                                                                                kCFAllocatorDefault, 0);
260                  long            size;
261                  CFTypeRef       sizeAsCFNumber =
262                                                  IORegistryEntryCreateCFProperty(nextFloppy,
# Line 261 | Line 273 | void DarwinAddFloppyPrefs(void)
273                                  continue;
274                          }
275                  }
276 <                else
277 <                        bug("Couldn't get kIOMediaSizeKey of device");
278 <                
279 <                
268 <                *bsdPath = '\0';
269 <                if ( bsdPathAsCFString )
270 <                {
271 <                        size_t devPathLength;
272 <
273 <                        strcpy(bsdPath, "/dev/");
274 <                        devPathLength = strlen(bsdPath);
275 <
276 <                        if ( CFStringGetCString((const __CFString *)bsdPathAsCFString,
277 <                                                                         bsdPath + devPathLength,
278 <                                                                         MAXPATHLEN - devPathLength,
279 <                                                                         kCFStringEncodingASCII) )
280 <                        {
281 <                                D(bug("Floppy BSD path: %s\n", bsdPath));
282 <                                PrefsAddString("floppy", bsdPath);
283 <                        }
284 <                        else
285 <                                D(bug("Could not get BSD device path for floppy\n"));
276 >                else {
277 >                        D(puts("Couldn't get kIOMediaSizeKey of device"));
278 >                        continue; // if kIOMediaSizeKey is unavailable, we shouldn't use it anyway
279 >                }
280  
281 <                        CFRelease(bsdPathAsCFString);
281 >                if (get_device_path(nextFloppy, bsdPath, sizeof(bsdPath)) == KERN_SUCCESS) {
282 >                        PrefsAddString("floppy", bsdPath);
283 >                } else {
284 >                        D(bug("Could not get BSD device path for floppy\n"));
285                  }
289                else
290                        D(bug("Cannot determine bsdPath for floppy\n"));
286          }
287  
288          IOObjectRelease(nextFloppy);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines