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

# 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  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines