Dan McDonald via illumos-developer
2014-10-10 01:29:21 UTC
Consider this code from $SRC/uts/common/io/cpudrv.c:
/* NOTE, to reach here a previous call to cpudrv_is_enabled() must have succeded! */
280 mutex_init(&cpudsp->lock, NULL, MUTEX_DRIVER, NULL);
281 if (cpudrv_is_enabled(cpudsp)) {
282 if (cpudrv_init(cpudsp) != DDI_SUCCESS) {
283 cpudrv_enabled = B_FALSE;
284 cpudrv_free(cpudsp);
285 ddi_soft_state_free(cpudrv_state, instance);
286 return (DDI_FAILURE);
287 }
288 if (cpudrv_comp_create(cpudsp) != DDI_SUCCESS) {
289 cpudrv_enabled = B_FALSE;
290 cpudrv_free(cpudsp);
291 ddi_soft_state_free(cpudrv_state, instance);
292 return (DDI_FAILURE);
293 }
294 if (ddi_prop_update_string(DDI_DEV_T_NONE,
295 dip, "pm-class", "CPU") != DDI_PROP_SUCCESS) {
296 cpudrv_enabled = B_FALSE;
297 cpudrv_free(cpudsp);
298 ddi_soft_state_free(cpudrv_state, instance);
299 return (DDI_FAILURE);
300 }
301
302 /*
303 * Taskq is used to dispatch routine to monitor CPU
304 * activities.
305 */
306 cpudsp->cpudrv_pm.tq = ddi_taskq_create(dip,
307 "cpudrv_monitor", CPUDRV_TASKQ_THREADS,
308 TASKQ_DEFAULTPRI, 0);
309
310 mutex_init(&cpudsp->cpudrv_pm.timeout_lock, NULL,
311 MUTEX_DRIVER, NULL);
312 cv_init(&cpudsp->cpudrv_pm.timeout_cv, NULL,
313 CV_DEFAULT, NULL);
314
315 /*
316 * Driver needs to assume that CPU is running at
317 * unknown speed at DDI_ATTACH and switch it to the
318 * needed speed. We assume that initial needed speed
319 * is full speed for us.
320 */
321 /*
322 * We need to take the lock because cpudrv_monitor()
323 * will start running in parallel with attach().
324 */
325 mutex_enter(&cpudsp->lock);
326 cpudsp->cpudrv_pm.cur_spd = NULL;
327 cpudsp->cpudrv_pm.pm_started = B_FALSE;
328 /*
329 * We don't call pm_raise_power() directly from attach
330 * because driver attach for a slave CPU node can
331 * happen before the CPU is even initialized. We just
332 * start the monitoring system which understands
333 * unknown speed and moves CPU to top speed when it
334 * has been initialized.
335 */
336 CPUDRV_MONITOR_INIT(cpudsp);
337 mutex_exit(&cpudsp->lock);
338
339 }
340
341 if (!cpudrv_mach_init(cpudsp)) { /* XXX PANIC HERE if above if is FALSE! */
The last call above to cpudrv_mach_init() has an ASSERT() for cpudsp->cp not being NULL. Problem is, IF the above check for cpudrv_is_active() FAILS, cpudsp->cp will be NULL, and the machine will panic. I have a coredump to prove it!
Now how the failure (passes is_active(), then fails is_active()) may be relevant, but shouldn't this code be more robust?
What should REALLY happen if the shown cpudrv_is_active() call fails? Calling cpudrv_mach_init() immediately will panic your system, so I'd like a better solution. Even if it means changing the assert() in cpudrv_mach_init() to if (NULL) return B_FALSE. I'm leaning toward this last solution, as the caller appears to handle its failure robustly.
Thanks,
Dan
-------------------------------------------
illumos-developer
Archives: https://www.listbox.com/member/archive/182179/=now
RSS Feed: https://www.listbox.com/member/archive/rss/182179/21175072-86d49504
Modify Your Subscription: https://www.listbox.com/member/?member_id=21175072&id_secret=21175072-abdf7b7e
Powered by Listbox: http://www.listbox.com
/* NOTE, to reach here a previous call to cpudrv_is_enabled() must have succeded! */
280 mutex_init(&cpudsp->lock, NULL, MUTEX_DRIVER, NULL);
281 if (cpudrv_is_enabled(cpudsp)) {
282 if (cpudrv_init(cpudsp) != DDI_SUCCESS) {
283 cpudrv_enabled = B_FALSE;
284 cpudrv_free(cpudsp);
285 ddi_soft_state_free(cpudrv_state, instance);
286 return (DDI_FAILURE);
287 }
288 if (cpudrv_comp_create(cpudsp) != DDI_SUCCESS) {
289 cpudrv_enabled = B_FALSE;
290 cpudrv_free(cpudsp);
291 ddi_soft_state_free(cpudrv_state, instance);
292 return (DDI_FAILURE);
293 }
294 if (ddi_prop_update_string(DDI_DEV_T_NONE,
295 dip, "pm-class", "CPU") != DDI_PROP_SUCCESS) {
296 cpudrv_enabled = B_FALSE;
297 cpudrv_free(cpudsp);
298 ddi_soft_state_free(cpudrv_state, instance);
299 return (DDI_FAILURE);
300 }
301
302 /*
303 * Taskq is used to dispatch routine to monitor CPU
304 * activities.
305 */
306 cpudsp->cpudrv_pm.tq = ddi_taskq_create(dip,
307 "cpudrv_monitor", CPUDRV_TASKQ_THREADS,
308 TASKQ_DEFAULTPRI, 0);
309
310 mutex_init(&cpudsp->cpudrv_pm.timeout_lock, NULL,
311 MUTEX_DRIVER, NULL);
312 cv_init(&cpudsp->cpudrv_pm.timeout_cv, NULL,
313 CV_DEFAULT, NULL);
314
315 /*
316 * Driver needs to assume that CPU is running at
317 * unknown speed at DDI_ATTACH and switch it to the
318 * needed speed. We assume that initial needed speed
319 * is full speed for us.
320 */
321 /*
322 * We need to take the lock because cpudrv_monitor()
323 * will start running in parallel with attach().
324 */
325 mutex_enter(&cpudsp->lock);
326 cpudsp->cpudrv_pm.cur_spd = NULL;
327 cpudsp->cpudrv_pm.pm_started = B_FALSE;
328 /*
329 * We don't call pm_raise_power() directly from attach
330 * because driver attach for a slave CPU node can
331 * happen before the CPU is even initialized. We just
332 * start the monitoring system which understands
333 * unknown speed and moves CPU to top speed when it
334 * has been initialized.
335 */
336 CPUDRV_MONITOR_INIT(cpudsp);
337 mutex_exit(&cpudsp->lock);
338
339 }
340
341 if (!cpudrv_mach_init(cpudsp)) { /* XXX PANIC HERE if above if is FALSE! */
The last call above to cpudrv_mach_init() has an ASSERT() for cpudsp->cp not being NULL. Problem is, IF the above check for cpudrv_is_active() FAILS, cpudsp->cp will be NULL, and the machine will panic. I have a coredump to prove it!
Now how the failure (passes is_active(), then fails is_active()) may be relevant, but shouldn't this code be more robust?
What should REALLY happen if the shown cpudrv_is_active() call fails? Calling cpudrv_mach_init() immediately will panic your system, so I'd like a better solution. Even if it means changing the assert() in cpudrv_mach_init() to if (NULL) return B_FALSE. I'm leaning toward this last solution, as the caller appears to handle its failure robustly.
Thanks,
Dan
-------------------------------------------
illumos-developer
Archives: https://www.listbox.com/member/archive/182179/=now
RSS Feed: https://www.listbox.com/member/archive/rss/182179/21175072-86d49504
Modify Your Subscription: https://www.listbox.com/member/?member_id=21175072&id_secret=21175072-abdf7b7e
Powered by Listbox: http://www.listbox.com