Opened 3 years ago

Last modified 8 months ago

#64909 closed defect

libaacs for PowerPC: how to rewrite __block code in standard C? — at Initial Version

Reported by: barracuda156 Owned by:
Priority: Normal Milestone:
Component: ports Version: 2.7.2
Keywords: powerpc, leopard, snowleopard Cc:
Port: libaacs

Description

Could anyone advise me if this can be rewritten in standard C? gcc does not process this block code correctly:

void device_close(MMCDEV **pp)
{
    __block int rc = 0;
    if (pp && *pp) {
        MMCDEV *mmc = *pp;

        /* When the exclusive access to the drive is released,
         * the OS will see the device like a "new" device and
         * try to mount it. Therefore we can't just mount the
         * disk we previously got immediately here as it would
         * fail with kDAReturnBadArgument as the disk is not
         * available yet.
         * Trying to mount the disk after it appears in peek
         * does not work either as the disk is not yet ready
         * or in the process of being mounted by the OS so
         * that would return an kDAReturnBusy error.
         * The only way that seems to reliably work is to use
         * a mount approval callback. When the OS tries to
         * mount the disk, the mount approval callback is
         * called and we can reject mounting and then proceed
         * to mount the disk ourselves.
         * Claiming exclusive access using DADiskClaim in order
         * to prevent the OS form mounting the disk does not work
         * either!
         */

        if (mmc->taskInterface) {
            (*mmc->taskInterface)->ReleaseExclusiveAccess(mmc->taskInterface);
            (*mmc->taskInterface)->Release(mmc->taskInterface);
            mmc->taskInterface = NULL;
        }

        if (mmc->mmcInterface) {
            (*mmc->mmcInterface)->Release(mmc->mmcInterface);
            mmc->mmcInterface = NULL;
        }

        if (mmc->plugInInterface) {
            IODestroyPlugInInterface(mmc->plugInInterface);
        }

        if (!mmc->sync_sem) {
            /* open failed before iokit_da_init() */
            X_FREE(*pp);
            return;
        }

        /* Wait for disc to re-appear for 20 seconds.
         * This timeout was figured out by experimentation with
         * a USB BD drive which sometimes can take really long to
         * be in a mountable state again.
         * For internal drives this is probably much faster
         * so the long timeout shouldn't do much harm for thse
         * cases.
         */
        dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 20 * 1E+9);
        dispatch_semaphore_wait(mmc->sync_sem, timeout);

        /* It is crucial that this is done on the event handling queue
         * else callbacks could be received while this code runs.
         */
        dispatch_sync(mmc->background_queue, ^{
            if (disk_appeared != mmc->disk_state) {
                BD_DEBUG(DBG_MMC | DBG_CRIT, "Timeout waiting for the disc to appear again!\n");
                iokit_da_destroy(mmc);
                rc = -1;
                return;
            }
            rc = 0;
        });

        if (rc == 0) {
            /* Disk appeared successfully, mount it.
             * Return value is ignored as logging of success or
             * error takes place in the callback already and there
             * is nothing we can do really if mounting fails.
             */
            (void) iokit_mount(mmc);
            iokit_da_destroy(mmc);
        }
        X_FREE(*pp);
    }
}

This is from src/file/mmc_device_darwin.c.

Change History (0)

Note: See TracTickets for help on using tickets.