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.17 by asvitkine, 2012-04-21T16:04:51Z

# 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 66 | Line 66 | extern void SysMediaRemoved(const char *
66  
67   void DarwinSysInit(void)
68   {
69 <        media_thread_active = (pthread_create(&media_thread, NULL, media_poll_func, NULL) == 0);
70 <        D(bug("Media poll thread installed (%ld)\n", media_thread));
69 >        if (PrefsFindBool("nocdrom")) {
70 >                media_thread_active = (pthread_create(&media_thread, NULL, media_poll_func, NULL) == 0);
71 >                D(bug("Media poll thread installed (%ld)\n", media_thread));
72 >        }
73   }
74  
75  
# Line 78 | Line 80 | void DarwinSysInit(void)
80   void DarwinSysExit(void)
81   {
82          // Stop media poll thread
83 <        if (media_poll_loop)
83 >        if (media_thread_active) {
84 >                while (media_poll_loop == NULL || !CFRunLoopIsWaiting(media_poll_loop))
85 >                        usleep(0);
86                  CFRunLoopStop(media_poll_loop);
83        if (media_thread_active)
87                  pthread_join(media_thread, NULL);
88 +                media_poll_loop = NULL;
89 +                media_thread_active = false;
90 +        }
91   }
92  
93  
# Line 115 | Line 121 | static kern_return_t get_device_path(io_
121   static void media_arrived(int type, io_iterator_t iterator)
122   {
123          io_object_t obj;
124 <        while ((obj = IOIteratorNext(iterator)) != NULL) {
124 >        while ((obj = IOIteratorNext(iterator))) {
125                  char path[MAXPATHLEN];
126                  kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
127                  if (kernResult == KERN_SUCCESS) {
# Line 137 | Line 143 | static void media_arrived(int type, io_i
143   static void media_removed(int type, io_iterator_t iterator)
144   {
145          io_object_t obj;
146 <        while ((obj = IOIteratorNext(iterator)) != NULL) {
146 >        while ((obj = IOIteratorNext(iterator))) {
147                  char path[MAXPATHLEN];
148                  kern_return_t kernResult = get_device_path(obj, path, sizeof(path));
149                  if (kernResult == KERN_SUCCESS) {
# Line 154 | Line 160 | static void media_removed(int type, io_i
160  
161   /*
162   *  Media poll function
163 + *
164 + *  NOTE: to facilitate orderly thread termination, media_poll_func MUST end up waiting in CFRunLoopRun.
165 + *  Early returns must be avoided, even if there is nothing useful to be done here. See DarwinSysExit.
166   */
167  
168 + static void dummy(void *) { };  // stub for dummy runloop source
169 +
170   static void *media_poll_func(void *)
171   {
172          media_poll_loop = CFRunLoopGetCurrent();
173  
174          mach_port_t masterPort;
175 <        kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort);
176 <        if (kernResult != KERN_SUCCESS) {
177 <                fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
178 <                return NULL;
168 <        }
175 >        kern_return_t kernResult;
176 >        CFMutableDictionaryRef matchingDictionary;
177 >        CFRunLoopSourceRef loopSource = NULL;
178 >        CFRunLoopSourceRef dummySource = NULL;
179  
180 <        CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass);
181 <        if (matchingDictionary == NULL) {
180 >        if ((kernResult = IOMasterPort(bootstrap_port, &masterPort)) != KERN_SUCCESS)
181 >                fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
182 >        else if ((matchingDictionary = IOServiceMatching(kIOCDMediaClass)) == NULL)
183                  fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n");
184 <                return NULL;
184 >        else {
185 >                matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
186 >                IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
187 >                loopSource = IONotificationPortGetRunLoopSource(notificationPort);
188 >                CFRunLoopAddSource(media_poll_loop, loopSource, kCFRunLoopDefaultMode);
189 >
190 >                io_iterator_t mediaArrivedIterator;
191 >                kernResult = IOServiceAddMatchingNotification(notificationPort,
192 >                        kIOMatchedNotification,
193 >                        matchingDictionary,
194 >                        (IOServiceMatchingCallback)media_arrived,
195 >                        (void *)MEDIA_CD, &mediaArrivedIterator);
196 >                if (kernResult != KERN_SUCCESS)
197 >                        fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
198 >                media_arrived(MEDIA_CD, mediaArrivedIterator);
199 >
200 >                io_iterator_t mediaRemovedIterator;
201 >                kernResult = IOServiceAddMatchingNotification(notificationPort,
202 >                        kIOTerminatedNotification,
203 >                        matchingDictionary,
204 >                        (IOServiceMatchingCallback)media_removed,
205 >                        (void *)MEDIA_CD, &mediaRemovedIterator);
206 >                if (kernResult != KERN_SUCCESS)
207 >                        fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
208 >                media_removed(MEDIA_CD, mediaRemovedIterator);
209          }
175        matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);
210  
211 <        IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
212 <        CFRunLoopAddSource(media_poll_loop,
213 <                                           IONotificationPortGetRunLoopSource(notificationPort),
214 <                                           kCFRunLoopDefaultMode);
215 <
216 <        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);
211 >        if (loopSource == NULL) {
212 >                // add a dummy runloop source to prevent premature return from CFRunLoopRun
213 >                CFRunLoopSourceContext context = { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, dummy };
214 >                dummySource = CFRunLoopSourceCreate(NULL, 0, &context);
215 >                CFRunLoopAddSource(media_poll_loop, dummySource, kCFRunLoopDefaultMode);
216 >        }
217  
218          CFRunLoopRun();
219 +
220 +        if (dummySource != NULL)
221 +                CFRelease(dummySource);
222          return NULL;
223   }
224  
# Line 236 | Line 255 | void DarwinAddFloppyPrefs(void)
255                  return;
256          }
257  
239
258          // Iterate through each floppy
259          while ( nextFloppy = IOIteratorNext(allFloppies))
260          {
261                  char            bsdPath[MAXPATHLEN];
244                CFTypeRef       bsdPathAsCFString =
245                                                IORegistryEntryCreateCFProperty(nextFloppy,
246                                                                                                                CFSTR(kIOBSDNameKey),
247                                                                                                                kCFAllocatorDefault, 0);
262                  long            size;
263                  CFTypeRef       sizeAsCFNumber =
264                                                  IORegistryEntryCreateCFProperty(nextFloppy,
# Line 261 | Line 275 | void DarwinAddFloppyPrefs(void)
275                                  continue;
276                          }
277                  }
278 <                else
279 <                        bug("Couldn't get kIOMediaSizeKey of device");
280 <                
281 <                
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"));
278 >                else {
279 >                        D(puts("Couldn't get kIOMediaSizeKey of device"));
280 >                        continue; // if kIOMediaSizeKey is unavailable, we shouldn't use it anyway
281 >                }
282  
283 <                        CFRelease(bsdPathAsCFString);
283 >                if (get_device_path(nextFloppy, bsdPath, sizeof(bsdPath)) == KERN_SUCCESS) {
284 >                        PrefsAddString("floppy", bsdPath);
285 >                } else {
286 >                        D(bug("Could not get BSD device path for floppy\n"));
287                  }
289                else
290                        D(bug("Cannot determine bsdPath for floppy\n"));
288          }
289  
290          IOObjectRelease(nextFloppy);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines