<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "arch/io/timer_provider.hpp"

#if RDB_TIMER_PROVIDER == RDB_TIMER_PROVIDER_KQUEUE

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

#include "config/args.hpp"
#include "logger.hpp"
#include "utils.hpp"

timer_kqueue_provider_t::timer_kqueue_provider_t(linux_event_queue_t *queue,
                                                 timer_provider_callback_t *callback,
                                                 time_t secs, int32_t nsecs)
    : queue_(queue), callback_(callback), kq_fd_(-1) {

    // We can't make the kqueue a non-blocking file descriptor -- we do non-blocking kevent64 calls.
    int fd = kqueue();
    guarantee_err(fd != -1, "kqueue() call failed");

    uint64_t nsecs64 = static_cast<uint64_t>(secs) * BILLION + nsecs;

    struct kevent64_s event;
    EV_SET64(&event, 99, EVFILT_TIMER, EV_ADD, NOTE_NSECONDS, nsecs64, 0, 0, 0);

    // Setting the timeout to zero makes this a non-blocking call.
    struct timespec timeout;
    timeout.tv_sec = 0;
    timeout.tv_nsec = 0;
    int res = kevent64(fd, &event, 1, NULL, 0, 0, &timeout);
    guarantee_err(res != -1, "kevent64 failed when making timer");

    kq_fd_ = fd;

    queue_->watch_resource(kq_fd_, poll_event_in, this);
}

timer_kqueue_provider_t::~timer_kqueue_provider_t() {
    queue_->forget_resource(kq_fd_, this);

    int res = close(kq_fd_);
    guarantee_err(res == 0, "Could not close the kqueue timer.");
}

void timer_kqueue_provider_t::on_event(int eventmask) {
    if (eventmask != poll_event_in) {
        logERR("Unexpected event mask: %d", eventmask);
    }

    const int num_events = 4;
    struct kevent64_s events[num_events];

    // Setting the timeout to 0 makes this a non-blocking call.
    struct timespec timeout;
    timeout.tv_sec = 0;
    timeout.tv_nsec = 0;
    int res;
    do {
        res = kevent64(kq_fd_, NULL, 0, events, num_events, 0, &timeout);
    } while (res == -1 && errno == EINTR);

    guarantee_err(res != -1, "kevent64 failed when reading timer");

    // There _should_ be one result (because we got notified by the thread pool's event queue) and
    // there definitely should not be more than one result (because we only registered for one
    // event), but there _could_ be zero results if we got an unexpected event mask, which we only
    // handle by logging at hte top of this function.
    guarantee(res <= 1);

    for (int i = 0; i < res; ++i) {
        const struct kevent64_s event = events[i];
        guarantee(event.filter == EVFILT_TIMER);
        guarantee_xerr(!(event.flags & EV_ERROR), event.data, "The kqueue-based timer returned an error.\n");

        guarantee(event.ident == 99);
        int64_t expiration_count = events[i].data;
        callback_->on_timer(expiration_count);
    }
}

#endif  // RDB_TIMER_PROVIDER == RDB_TIMER_PROVIDER_KQUEUE
<commit_msg>Made the kqueue-based timerfd stand-in handle multiple results from the kevent64 flag gracefully.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#include "arch/io/timer_provider.hpp"

#if RDB_TIMER_PROVIDER == RDB_TIMER_PROVIDER_KQUEUE

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

#include "config/args.hpp"
#include "logger.hpp"
#include "utils.hpp"

timer_kqueue_provider_t::timer_kqueue_provider_t(linux_event_queue_t *queue,
                                                 timer_provider_callback_t *callback,
                                                 time_t secs, int32_t nsecs)
    : queue_(queue), callback_(callback), kq_fd_(-1) {

    // We can't make the kqueue a non-blocking file descriptor -- we do non-blocking kevent64 calls.
    int fd = kqueue();
    guarantee_err(fd != -1, "kqueue() call failed");

    uint64_t nsecs64 = static_cast<uint64_t>(secs) * BILLION + nsecs;

    struct kevent64_s event;
    EV_SET64(&event, 99, EVFILT_TIMER, EV_ADD, NOTE_NSECONDS, nsecs64, 0, 0, 0);

    // Setting the timeout to zero makes this a non-blocking call.
    struct timespec timeout;
    timeout.tv_sec = 0;
    timeout.tv_nsec = 0;
    int res = kevent64(fd, &event, 1, NULL, 0, 0, &timeout);
    guarantee_err(res != -1, "kevent64 failed when making timer");

    kq_fd_ = fd;

    queue_->watch_resource(kq_fd_, poll_event_in, this);
}

timer_kqueue_provider_t::~timer_kqueue_provider_t() {
    queue_->forget_resource(kq_fd_, this);

    int res = close(kq_fd_);
    guarantee_err(res == 0, "Could not close the kqueue timer.");
}

void debug_print(append_only_printf_buffer_t *buf, const struct kevent64_s& event) {
    buf->appendf("kevent64_s{ident=%" PRIu64 ", filter=%" PRIi16 ", flags=%" PRIu16
                 ", fflags=%" PRIu32 ", data=%" PRIi64 ", udata=%" PRIu64
                 ", ext[0]=%" PRIu64 ", ext[1]=%" PRIu64,
                 event.ident, event.filter, event.flags,
                 event.fflags, event.data, event.udata,
                 event.ext[0], event.ext[1]);
}

void timer_kqueue_provider_t::on_event(int eventmask) {
    if (eventmask != poll_event_in) {
        logERR("Unexpected event mask: %d", eventmask);
    }

    const int num_events = 4;
    struct kevent64_s events[num_events];

    // Setting the timeout to 0 makes this a non-blocking call.
    struct timespec timeout;
    timeout.tv_sec = 0;
    timeout.tv_nsec = 0;

    // kevent64 can return more than one EVFILT_TIMER event at a time, even though we only
    // registered for it once and we can get an overrun count.  We get multiple results for the same
    // event, separately.  So we have this loop that makes sure we siphon all the possible events
    // off the kqueue file descriptor.  The only time I've seen it return more than one event was
    // when sleeping the computer, and another time when leaving the computer idle for a while.
    int64_t expiration_count = 0;

    bool got_short_res = false;
    while (!got_short_res) {
        int res;
        do {
            res = kevent64(kq_fd_, NULL, 0, events, num_events, 0, &timeout);
        } while (res == -1 && errno == EINTR);

        guarantee_err(res != -1, "kevent64 failed when reading timer");

        got_short_res = res < num_events;

        for (int i = 0; i < res; ++i) {
            const struct kevent64_s event = events[i];
            guarantee(event.filter == EVFILT_TIMER);
            guarantee_xerr(!(event.flags & EV_ERROR), event.data, "The kqueue-based timer returned an error.\n");

            guarantee(event.ident == 99);
            int64_t this_result_expiration_count = events[i].data;
            expiration_count += this_result_expiration_count;
        }
    }

    callback_->on_timer(expiration_count);
}

#endif  // RDB_TIMER_PROVIDER == RDB_TIMER_PROVIDER_KQUEUE
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

// This flag changes the implementation to use S60 CDcoumentHandler
// instead of apparch when opening the files
#undef USE_DOCUMENTHANDLER

#include <qcoreapplication.h>
#include <qdir.h>
#include <qurl.h>
#include <private/qcore_symbian_p.h>

#include <miutset.h>                // KUidMsgTypeSMTP
#include <txtrich.h>                // CRichText
#include <f32file.h>                // TDriveUnit etc
#include <eikenv.h>                 // CEikonEnv
#include <apgcli.h>                 // RApaLsSession
#include <apgtask.h>                // TApaTaskList, TApaTask
#include <rsendas.h>                // RSendAs
#include <rsendasmessage.h>         // RSendAsMessage

#ifdef Q_WS_S60
#  include <pathinfo.h>               // PathInfo
#  ifdef USE_DOCUMENTHANDLER
#    include <documenthandler.h>        // CDocumentHandler
#  endif
#elif defined(USE_DOCUMENTHANDLER)
#  error CDocumentHandler requires support for S60
#endif

QT_BEGIN_NAMESPACE

_LIT(KCacheSubDir, "Cache\\");
_LIT(KSysBin, "\\Sys\\Bin\\");
_LIT(KTempDir, "\\System\\Temp\\");
_LIT(KBrowserPrefix, "4 " );
_LIT(KFontsDir, "z:\\resource\\Fonts\\");
const TUid KUidBrowser = { 0x10008D39 };

template<class R>
class QAutoClose
{
public:
    QAutoClose(R& aObj) : mPtr(&aObj) {}
    ~QAutoClose()
    {
        if (mPtr)
            mPtr->Close();
    }
    void Forget()
    {
        mPtr = 0;
    }
private:
    QAutoClose(const QAutoClose&);
    QAutoClose& operator=(const QAutoClose&);
private:
    R* mPtr;
};

static void handleMailtoSchemeLX(const QUrl &url)
{
    // this function has many intermingled leaves and throws. Qt and Symbian objects do not have
    // destructor dependencies, and cleanup object is used to prevent cleanup stack dependency on stack.
    QString recipient = url.path();
    QString subject = url.queryItemValue(QLatin1String("subject"));
    QString body = url.queryItemValue(QLatin1String("body"));
    QString to = url.queryItemValue(QLatin1String("to"));
    QString cc = url.queryItemValue(QLatin1String("cc"));
    QString bcc = url.queryItemValue(QLatin1String("bcc"));

    // these fields might have comma separated addresses
    QStringList recipients = recipient.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList tos = to.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList ccs = cc.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList bccs = bcc.split(QLatin1String(","), QString::SkipEmptyParts);

    RSendAs sendAs;
    User::LeaveIfError(sendAs.Connect());
    QAutoClose<RSendAs> sendAsCleanup(sendAs);

    CSendAsAccounts* accounts = CSendAsAccounts::NewL();
    CleanupStack::PushL(accounts);
    sendAs.AvailableAccountsL(KUidMsgTypeSMTP, *accounts);
    TInt count = accounts->Count();
    CleanupStack::PopAndDestroy(accounts);

    if(!count) {
        // TODO: Task 259192: We should try to create account if count == 0
        // CSendUi would provide account creation service for us, but it requires ridicilous
        // capabilities: LocalServices NetworkServices ReadDeviceData ReadUserData WriteDeviceData WriteUserData
        User::Leave(KErrNotSupported);
    } else {
        RSendAsMessage sendAsMessage;
        sendAsMessage.CreateL(sendAs, KUidMsgTypeSMTP);
        QAutoClose<RSendAsMessage> sendAsMessageCleanup(sendAsMessage);

        // Subject
        sendAsMessage.SetSubjectL(qt_QString2TPtrC(subject));

        // Body
        sendAsMessage.SetBodyTextL(qt_QString2TPtrC(body));

        // To
        foreach(QString item, recipients)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        foreach(QString item, tos)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        // Cc
        foreach(QString item, ccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientCc);

        // Bcc
        foreach(QString item, bccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientBcc);

        // send the message
        sendAsMessage.LaunchEditorAndCloseL();
        // sendAsMessage is already closed
        sendAsMessageCleanup.Forget();
    }
}

static bool handleMailtoScheme(const QUrl &url)
{
    TRAPD(err, QT_TRYCATCH_LEAVING(handleMailtoSchemeLX(url)));
    return err ? false : true;
}

static void handleOtherSchemesL(const TDesC& aUrl)
{
    // Other schemes are at the moment passed to WEB browser
    HBufC* buf16 = HBufC::NewLC(aUrl.Length() + KBrowserPrefix.iTypeLength);
    buf16->Des().Copy(KBrowserPrefix); // Prefix used to launch correct browser view
    buf16->Des().Append(aUrl);

    TApaTaskList taskList(CEikonEnv::Static()->WsSession());
    TApaTask task = taskList.FindApp(KUidBrowser);
    if (task.Exists()){
        // Switch to existing browser instance
        HBufC8* param8 = HBufC8::NewLC(buf16->Length());
        param8->Des().Append(buf16->Des());
        task.SendMessage(TUid::Uid( 0 ), *param8); // Uid is not used
        CleanupStack::PopAndDestroy(param8);
    } else {
        // Start a new browser instance
        RApaLsSession appArcSession;
        User::LeaveIfError(appArcSession.Connect());
        CleanupClosePushL<RApaLsSession>(appArcSession);
        TThreadId id;
        appArcSession.StartDocument(*buf16, KUidBrowser, id);
        CleanupStack::PopAndDestroy(); // appArcSession
    }

    CleanupStack::PopAndDestroy(buf16);
}

static bool handleOtherSchemes(const QUrl &url)
{
    QString encUrl(QString::fromUtf8(url.toEncoded()));
    TPtrC urlPtr(qt_QString2TPtrC(encUrl));
    TRAPD( err, handleOtherSchemesL(urlPtr));
    return err ? false : true;
}

static TDriveUnit exeDrive()
{
    RProcess me;
    TFileName processFileName = me.FileName();
    TDriveUnit drive(processFileName);
    return drive;
}

static TDriveUnit writableExeDrive()
{
    TDriveUnit drive = exeDrive();
    if(drive.operator TInt() == EDriveZ)
        return TDriveUnit(EDriveC);
    return drive;
}

static TPtrC writableDataRoot()
{
    TDriveUnit drive = exeDrive();
#ifdef Q_WS_S60
    switch(drive.operator TInt()){
        case EDriveC:
            return PathInfo::PhoneMemoryRootPath();
            break;
        case EDriveE:
            return PathInfo::MemoryCardRootPath();
            break;
        case EDriveZ:
            // It is not possible to write on ROM drive ->
            // return phone mem root path instead
            return PathInfo::PhoneMemoryRootPath();
            break;
        default:
            return PathInfo::PhoneMemoryRootPath();
            break;
    }
#else
#warning No fallback implementation of writableDataRoot()
    return 0;
#endif
}

static void openDocumentL(const TDesC& aUrl)
{
#ifndef USE_DOCUMENTHANDLER
    // Start app associated to file MIME type by using RApaLsSession
    // Apparc base method cannot be used to open app in embedded mode,
    // but seems to be most stable way at the moment
    RApaLsSession appArcSession;
    User::LeaveIfError(appArcSession.Connect());
    CleanupClosePushL<RApaLsSession>(appArcSession);
    TThreadId id;
    // ESwitchFiles means do not start another instance
    // Leaves if file does not exist, leave is trapped in openDocument and false returned to user.
    User::LeaveIfError(appArcSession.StartDocument(aUrl, id,
            RApaLsSession::ESwitchFiles)); // ELaunchNewApp
    CleanupStack::PopAndDestroy(); // appArcSession
#else
    // This is an alternative way to launch app associated to MIME type
    // CDocumentHandler would support opening apps in embedded mode,
    // but our Qt application window group seems to always get switched on top of embedded one
    // -> Cannot use menus etc of embedded app -> used

    CDocumentHandler* docHandler = CDocumentHandler::NewLC();
    TDataType temp;
    //Standalone file opening fails for some file-types at least in S60 3.1 emulator
    //For example .txt file fails with KErrAlreadyInUse and music files with KERN-EXEC 0
    //Workaround is to use OpenFileEmbeddedL
    //docHandler->OpenFileL(aUrl, temp);

    // Opening file with CDocumentHandler will leave if file does not exist
    // Leave is trapped in openDocument and false returned to user.
    docHandler->OpenFileEmbeddedL(aUrl, temp);
    CleanupStack::PopAndDestroy(docHandler);
#endif
}

#ifdef USE_SCHEMEHANDLER
// The schemehandler component only exist in private SDK. This implementation
// exist here just for convenience in case that we need to use it later on
// The schemehandle based implementation is not yet tested.

// The biggest advantage of schemehandler is that it can handle
// wide range of schemes and is extensible by plugins
static bool handleUrl(const QUrl &url)
{
    if (!url.isValid())
        return false;

    QString urlString(url.toString());
    TPtrC urlPtr(qt_QString2TPtrC(urlString));
    TRAPD( err, handleUrlL(urlPtr));
    return err ? false : true;
}

static void handleUrlL(const TDesC& aUrl)
{
    CSchemeHandler* schemeHandler = CSchemeHandler::NewL(aUrl);
    CleanupStack::PushL(schemeHandler);
    schemeHandler->HandleUrlStandaloneL(); // Process the Url in standalone mode
    CleanupStack::PopAndDestroy();
}
static bool launchWebBrowser(const QUrl &url)
{
    return handleUrl(url);
}

static bool openDocument(const QUrl &file)
{
    return handleUrl(url);
}
#endif

static bool launchWebBrowser(const QUrl &url)
{
    if (!url.isValid())
        return false;

    if (url.scheme() == QLatin1String("mailto")) {
        return handleMailtoScheme(url);
    }
    return handleOtherSchemes( url );
}

static bool openDocument(const QUrl &file)
{
    if (!file.isValid())
        return false;

    QString filePath = file.toLocalFile();
    filePath = QDir::toNativeSeparators(filePath);
    TPtrC filePathPtr(qt_QString2TPtrC(filePath));
    TRAPD(err, openDocumentL(filePathPtr));
    return err ? false : true;
}

QString QDesktopServices::storageLocation(StandardLocation type)
{
    TFileName path;

    switch (type) {
    case DesktopLocation:
        qWarning("No desktop concept in Symbian OS");
        // But lets still use some feasible default
        path.Append(writableDataRoot());
        break;
    case DocumentsLocation:
        path.Append(writableDataRoot());
        break;
    case FontsLocation:
        path.Append(KFontsDir);
        break;
    case ApplicationsLocation:
        path.Append(exeDrive().Name());
        path.Append(KSysBin);
        break;
    case MusicLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::SoundsPath());
#endif
        break;
    case MoviesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::VideosPath());
#endif
        break;
    case PicturesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::ImagesPath());
#endif
        break;
    case TempLocation:
        path.Append(writableExeDrive().Name());
        path.Append(KTempDir);
        //return QDir::tempPath(); break;
        break;
    case HomeLocation:
        path.Append(writableDataRoot());
        //return QDir::homePath(); break;
        break;
    case DataLocation:
        CEikonEnv::Static()->FsSession().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        break;
    case CacheLocation:
        CEikonEnv::Static()->FsSession().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        path.Append(KCacheSubDir);
        break;
    default:
        // Lets use feasible default
        path.Append(writableDataRoot());
        break;
    }

    // Convert to cross-platform format and clean the path
    QString nativePath = QString::fromUtf16(path.Ptr(), path.Length());
    QString qtPath = QDir::fromNativeSeparators(nativePath);
    qtPath = QDir::cleanPath(qtPath);

    // Note: The storage location returned can be a directory that does not exist;
    // i.e., it may need to be created by the system or the user.
    return  qtPath;
}

typedef QString (*LocalizerFunc)(QString&);

static QString defaultLocalizedDirectoryName(QString&)
{
    return QString();
}

QString QDesktopServices::displayName(StandardLocation type)
{
    static LocalizerFunc ptrLocalizerFunc = NULL;

    if (!ptrLocalizerFunc) {
        ptrLocalizerFunc = reinterpret_cast<LocalizerFunc>
            (qt_resolveS60PluginFunc(S60Plugin_LocalizedDirectoryName));
        if (!ptrLocalizerFunc)
            ptrLocalizerFunc = &defaultLocalizedDirectoryName;
    }

    QString rawPath = storageLocation(type);
    return ptrLocalizerFunc(rawPath);
}

QT_END_NAMESPACE
<commit_msg>Made QDir::tempPath and QDesktopServices::TempLocation consistent in S60<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

// This flag changes the implementation to use S60 CDcoumentHandler
// instead of apparch when opening the files
#undef USE_DOCUMENTHANDLER

#include <qcoreapplication.h>
#include <qdir.h>
#include <qurl.h>
#include <private/qcore_symbian_p.h>

#include <miutset.h>                // KUidMsgTypeSMTP
#include <txtrich.h>                // CRichText
#include <f32file.h>                // TDriveUnit etc
#include <eikenv.h>                 // CEikonEnv
#include <apgcli.h>                 // RApaLsSession
#include <apgtask.h>                // TApaTaskList, TApaTask
#include <rsendas.h>                // RSendAs
#include <rsendasmessage.h>         // RSendAsMessage

#ifdef Q_WS_S60
#  include <pathinfo.h>               // PathInfo
#  ifdef USE_DOCUMENTHANDLER
#    include <documenthandler.h>        // CDocumentHandler
#  endif
#elif defined(USE_DOCUMENTHANDLER)
#  error CDocumentHandler requires support for S60
#endif

QT_BEGIN_NAMESPACE

_LIT(KCacheSubDir, "Cache\\");
_LIT(KSysBin, "\\Sys\\Bin\\");
_LIT(KBrowserPrefix, "4 " );
_LIT(KFontsDir, "z:\\resource\\Fonts\\");
const TUid KUidBrowser = { 0x10008D39 };

template<class R>
class QAutoClose
{
public:
    QAutoClose(R& aObj) : mPtr(&aObj) {}
    ~QAutoClose()
    {
        if (mPtr)
            mPtr->Close();
    }
    void Forget()
    {
        mPtr = 0;
    }
private:
    QAutoClose(const QAutoClose&);
    QAutoClose& operator=(const QAutoClose&);
private:
    R* mPtr;
};

static void handleMailtoSchemeLX(const QUrl &url)
{
    // this function has many intermingled leaves and throws. Qt and Symbian objects do not have
    // destructor dependencies, and cleanup object is used to prevent cleanup stack dependency on stack.
    QString recipient = url.path();
    QString subject = url.queryItemValue(QLatin1String("subject"));
    QString body = url.queryItemValue(QLatin1String("body"));
    QString to = url.queryItemValue(QLatin1String("to"));
    QString cc = url.queryItemValue(QLatin1String("cc"));
    QString bcc = url.queryItemValue(QLatin1String("bcc"));

    // these fields might have comma separated addresses
    QStringList recipients = recipient.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList tos = to.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList ccs = cc.split(QLatin1String(","), QString::SkipEmptyParts);
    QStringList bccs = bcc.split(QLatin1String(","), QString::SkipEmptyParts);

    RSendAs sendAs;
    User::LeaveIfError(sendAs.Connect());
    QAutoClose<RSendAs> sendAsCleanup(sendAs);

    CSendAsAccounts* accounts = CSendAsAccounts::NewL();
    CleanupStack::PushL(accounts);
    sendAs.AvailableAccountsL(KUidMsgTypeSMTP, *accounts);
    TInt count = accounts->Count();
    CleanupStack::PopAndDestroy(accounts);

    if(!count) {
        // TODO: Task 259192: We should try to create account if count == 0
        // CSendUi would provide account creation service for us, but it requires ridicilous
        // capabilities: LocalServices NetworkServices ReadDeviceData ReadUserData WriteDeviceData WriteUserData
        User::Leave(KErrNotSupported);
    } else {
        RSendAsMessage sendAsMessage;
        sendAsMessage.CreateL(sendAs, KUidMsgTypeSMTP);
        QAutoClose<RSendAsMessage> sendAsMessageCleanup(sendAsMessage);

        // Subject
        sendAsMessage.SetSubjectL(qt_QString2TPtrC(subject));

        // Body
        sendAsMessage.SetBodyTextL(qt_QString2TPtrC(body));

        // To
        foreach(QString item, recipients)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        foreach(QString item, tos)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo);

        // Cc
        foreach(QString item, ccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientCc);

        // Bcc
        foreach(QString item, bccs)
         sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientBcc);

        // send the message
        sendAsMessage.LaunchEditorAndCloseL();
        // sendAsMessage is already closed
        sendAsMessageCleanup.Forget();
    }
}

static bool handleMailtoScheme(const QUrl &url)
{
    TRAPD(err, QT_TRYCATCH_LEAVING(handleMailtoSchemeLX(url)));
    return err ? false : true;
}

static void handleOtherSchemesL(const TDesC& aUrl)
{
    // Other schemes are at the moment passed to WEB browser
    HBufC* buf16 = HBufC::NewLC(aUrl.Length() + KBrowserPrefix.iTypeLength);
    buf16->Des().Copy(KBrowserPrefix); // Prefix used to launch correct browser view
    buf16->Des().Append(aUrl);

    TApaTaskList taskList(CEikonEnv::Static()->WsSession());
    TApaTask task = taskList.FindApp(KUidBrowser);
    if (task.Exists()){
        // Switch to existing browser instance
        HBufC8* param8 = HBufC8::NewLC(buf16->Length());
        param8->Des().Append(buf16->Des());
        task.SendMessage(TUid::Uid( 0 ), *param8); // Uid is not used
        CleanupStack::PopAndDestroy(param8);
    } else {
        // Start a new browser instance
        RApaLsSession appArcSession;
        User::LeaveIfError(appArcSession.Connect());
        CleanupClosePushL<RApaLsSession>(appArcSession);
        TThreadId id;
        appArcSession.StartDocument(*buf16, KUidBrowser, id);
        CleanupStack::PopAndDestroy(); // appArcSession
    }

    CleanupStack::PopAndDestroy(buf16);
}

static bool handleOtherSchemes(const QUrl &url)
{
    QString encUrl(QString::fromUtf8(url.toEncoded()));
    TPtrC urlPtr(qt_QString2TPtrC(encUrl));
    TRAPD( err, handleOtherSchemesL(urlPtr));
    return err ? false : true;
}

static TDriveUnit exeDrive()
{
    RProcess me;
    TFileName processFileName = me.FileName();
    TDriveUnit drive(processFileName);
    return drive;
}

static TDriveUnit writableExeDrive()
{
    TDriveUnit drive = exeDrive();
    if(drive.operator TInt() == EDriveZ)
        return TDriveUnit(EDriveC);
    return drive;
}

static TPtrC writableDataRoot()
{
    TDriveUnit drive = exeDrive();
#ifdef Q_WS_S60
    switch(drive.operator TInt()){
        case EDriveC:
            return PathInfo::PhoneMemoryRootPath();
            break;
        case EDriveE:
            return PathInfo::MemoryCardRootPath();
            break;
        case EDriveZ:
            // It is not possible to write on ROM drive ->
            // return phone mem root path instead
            return PathInfo::PhoneMemoryRootPath();
            break;
        default:
            return PathInfo::PhoneMemoryRootPath();
            break;
    }
#else
#warning No fallback implementation of writableDataRoot()
    return 0;
#endif
}

static void openDocumentL(const TDesC& aUrl)
{
#ifndef USE_DOCUMENTHANDLER
    // Start app associated to file MIME type by using RApaLsSession
    // Apparc base method cannot be used to open app in embedded mode,
    // but seems to be most stable way at the moment
    RApaLsSession appArcSession;
    User::LeaveIfError(appArcSession.Connect());
    CleanupClosePushL<RApaLsSession>(appArcSession);
    TThreadId id;
    // ESwitchFiles means do not start another instance
    // Leaves if file does not exist, leave is trapped in openDocument and false returned to user.
    User::LeaveIfError(appArcSession.StartDocument(aUrl, id,
            RApaLsSession::ESwitchFiles)); // ELaunchNewApp
    CleanupStack::PopAndDestroy(); // appArcSession
#else
    // This is an alternative way to launch app associated to MIME type
    // CDocumentHandler would support opening apps in embedded mode,
    // but our Qt application window group seems to always get switched on top of embedded one
    // -> Cannot use menus etc of embedded app -> used

    CDocumentHandler* docHandler = CDocumentHandler::NewLC();
    TDataType temp;
    //Standalone file opening fails for some file-types at least in S60 3.1 emulator
    //For example .txt file fails with KErrAlreadyInUse and music files with KERN-EXEC 0
    //Workaround is to use OpenFileEmbeddedL
    //docHandler->OpenFileL(aUrl, temp);

    // Opening file with CDocumentHandler will leave if file does not exist
    // Leave is trapped in openDocument and false returned to user.
    docHandler->OpenFileEmbeddedL(aUrl, temp);
    CleanupStack::PopAndDestroy(docHandler);
#endif
}

#ifdef USE_SCHEMEHANDLER
// The schemehandler component only exist in private SDK. This implementation
// exist here just for convenience in case that we need to use it later on
// The schemehandle based implementation is not yet tested.

// The biggest advantage of schemehandler is that it can handle
// wide range of schemes and is extensible by plugins
static bool handleUrl(const QUrl &url)
{
    if (!url.isValid())
        return false;

    QString urlString(url.toString());
    TPtrC urlPtr(qt_QString2TPtrC(urlString));
    TRAPD( err, handleUrlL(urlPtr));
    return err ? false : true;
}

static void handleUrlL(const TDesC& aUrl)
{
    CSchemeHandler* schemeHandler = CSchemeHandler::NewL(aUrl);
    CleanupStack::PushL(schemeHandler);
    schemeHandler->HandleUrlStandaloneL(); // Process the Url in standalone mode
    CleanupStack::PopAndDestroy();
}
static bool launchWebBrowser(const QUrl &url)
{
    return handleUrl(url);
}

static bool openDocument(const QUrl &file)
{
    return handleUrl(url);
}
#endif

static bool launchWebBrowser(const QUrl &url)
{
    if (!url.isValid())
        return false;

    if (url.scheme() == QLatin1String("mailto")) {
        return handleMailtoScheme(url);
    }
    return handleOtherSchemes( url );
}

static bool openDocument(const QUrl &file)
{
    if (!file.isValid())
        return false;

    QString filePath = file.toLocalFile();
    filePath = QDir::toNativeSeparators(filePath);
    TPtrC filePathPtr(qt_QString2TPtrC(filePath));
    TRAPD(err, openDocumentL(filePathPtr));
    return err ? false : true;
}

QString QDesktopServices::storageLocation(StandardLocation type)
{
    TFileName path;

    switch (type) {
    case DesktopLocation:
        qWarning("No desktop concept in Symbian OS");
        // But lets still use some feasible default
        path.Append(writableDataRoot());
        break;
    case DocumentsLocation:
        path.Append(writableDataRoot());
        break;
    case FontsLocation:
        path.Append(KFontsDir);
        break;
    case ApplicationsLocation:
        path.Append(exeDrive().Name());
        path.Append(KSysBin);
        break;
    case MusicLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::SoundsPath());
#endif
        break;
    case MoviesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::VideosPath());
#endif
        break;
    case PicturesLocation:
        path.Append(writableDataRoot());
#ifdef Q_WS_S60
        path.Append(PathInfo::ImagesPath());
#endif
        break;
    case TempLocation:
        return QDir::tempPath();
        break;
    case HomeLocation:
        path.Append(writableDataRoot());
        //return QDir::homePath(); break;
        break;
    case DataLocation:
        CEikonEnv::Static()->FsSession().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        break;
    case CacheLocation:
        CEikonEnv::Static()->FsSession().PrivatePath(path);
        path.Insert(0, writableExeDrive().Name());
        path.Append(KCacheSubDir);
        break;
    default:
        // Lets use feasible default
        path.Append(writableDataRoot());
        break;
    }

    // Convert to cross-platform format and clean the path
    QString nativePath = QString::fromUtf16(path.Ptr(), path.Length());
    QString qtPath = QDir::fromNativeSeparators(nativePath);
    qtPath = QDir::cleanPath(qtPath);

    // Note: The storage location returned can be a directory that does not exist;
    // i.e., it may need to be created by the system or the user.
    return  qtPath;
}

typedef QString (*LocalizerFunc)(QString&);

static QString defaultLocalizedDirectoryName(QString&)
{
    return QString();
}

QString QDesktopServices::displayName(StandardLocation type)
{
    static LocalizerFunc ptrLocalizerFunc = NULL;

    if (!ptrLocalizerFunc) {
        ptrLocalizerFunc = reinterpret_cast<LocalizerFunc>
            (qt_resolveS60PluginFunc(S60Plugin_LocalizedDirectoryName));
        if (!ptrLocalizerFunc)
            ptrLocalizerFunc = &defaultLocalizedDirectoryName;
    }

    QString rawPath = storageLocation(type);
    return ptrLocalizerFunc(rawPath);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>#include <iostream>
#include <cstring>      // Needed for memset
#include <sys/socket.h> // Needed for the socket functions
#include <netdb.h>      // Needed for the socket functions
#include <unistd.h>
#include <assert.h>
#include <memory> // unique_ptr
#include <string.h>

#include "sim.h"
#include "jsoncpp/json/json.h"

#define PORT "25041"

/**
 * \brief Read from environment variable as string
 */
static char* get_env_str(const char *envname, const char *defaultvalue)
{
    char *env;
    env = getenv (envname);

    if (env==NULL) {

        return (char*) defaultvalue;
    }

    return env;
}

int smlt_tree_parse_wrapper(char* json_string,
                            unsigned ncores,
                            uint16_t** model,
                            uint32_t** leafs,
                            uint32_t* t_root,
                            uint32_t* len_model)
{
    Json::Value root;
    // Json::CharReaderBuilder rbuilder;
    // rbuilder["collectComments"] = false;
    std::string errs;
    // bool ok = Json::parseFromStream(rbuilder, rec, &root, &errs);

    Json::CharReaderBuilder rbuilder;
    Json::CharReader* reader = rbuilder.newCharReader();

    reader->parse(json_string, json_string+strlen(json_string)-1,
                  &root, &errs);
    // Extract last node
    Json::Value ln = root.get("root", "");
    int lnval = ln.asInt();
    *t_root = (uint32_t)lnval;

    // Extract leaf node

    Json::Value leafs_j = root.get("leaf_nodes", "");
    *leafs = (uint32_t*) malloc(sizeof(uint32_t)*leafs_j.size());
    assert(*leafs != NULL);

    for (unsigned i=0; i<leafs_j.size(); i++) {
        (*leafs)[i] = leafs_j.get(i, Json::Value()).asInt();
    }

    Json::Value elem = root.get("model", "");
    *model = (uint16_t*)  malloc(sizeof(uint16_t)*elem.size()*elem.size());
    assert(*model != NULL);
    int x = 0;
    int y = 0;
    *len_model = elem.size();
    for (Json::ValueIterator i=elem.begin(); i != elem.end(); i++) {
        y = 0;
        Json::Value inner = (*i);
        for (Json::ValueIterator k=inner.begin(); k != inner.end(); k++) {

            Json::Value val = (*k);
            (*model)[x*elem.size()+y] = (uint32_t) val.asInt();
            y++;
        }
        x++;
    }

    return 0;
}

static int smlt_tree_config_request(const char *hostname,
                                    const char* msg,
                                    unsigned ncores,
                                    uint16_t** model,
                                    uint32_t** leafs,
                                    uint32_t* t_root,
                                    uint32_t* len_model)
{

    int status;
    struct addrinfo host_info;       // The struct that getaddrinfo() fills up with data.
    struct addrinfo *host_info_list; // Pointer to the to the linked list of host_info's.

    // The MAN page of getaddrinfo() states "All  the other fields in the structure pointed
    // to by hints must contain either 0 or a null pointer, as appropriate." When a struct
    // is created in c++, it will be given a block of memory. This memory is not nessesary
    // empty. Therefor we use the memset function to make sure all fields are NULL.
    memset(&host_info, 0, sizeof host_info);

    host_info.ai_family = AF_UNSPEC;     // IP version not specified. Can be both.
    host_info.ai_socktype = SOCK_STREAM; // Use SOCK_STREAM for TCP or SOCK_DGRAM for UDP.

    // Now fill up the linked list of host_info structs with google's address information.
    status = getaddrinfo(hostname, PORT, &host_info, &host_info_list);
    // getaddrinfo returns 0 on succes, or some other value when an error occured.
    // (translated into human readable text by the gai_gai_strerror function).
    if (status != 0) {
        std::cout << "getaddrinfo error" << gai_strerror(status) ;
        return 1;
    }

    int socketfd ; // The socket descripter
    socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype,
                  host_info_list->ai_protocol);
    if (socketfd == -1) {
        std::cout << "socket error " ;
        return 1;
    }

    status = connect(socketfd, host_info_list->ai_addr, host_info_list->ai_addrlen);
    if (status == -1) {
        std::cout << "connect error" ;
        return 1;
    }

    int len = strlen(msg);
    int bytes_sent;

    bytes_sent = send(socketfd, msg, len, 0);
    assert (bytes_sent==len);

    ssize_t bytes_recieved;
    char incomming_data_buffer[1000];

    std::string rec;

    do {
        bytes_recieved = recv(socketfd, incomming_data_buffer,1000, 0);

        // If no data arrives, the program will just wait here until some data arrives.
        if (bytes_recieved > 0) {
            incomming_data_buffer[bytes_recieved] = '\0' ;

            rec.append(incomming_data_buffer);
        }
        else {
            if (bytes_recieved == 0) {
               printf("host shut down \n");
            } else if (bytes_recieved == -1) {
               printf("receive error \n");
               return 1;
            }
        }

    } while(bytes_recieved>0);

    freeaddrinfo(host_info_list);
    shutdown(socketfd, SHUT_RDWR);
    assert(model != NULL);
    char* inp = (char*) rec.c_str();

    return smlt_tree_parse_wrapper(inp, ncores, model, leafs, t_root, len_model);
}

#define NAMELEN 1000U

int smlt_tree_generate_wrapper(unsigned ncores,
                               uint32_t* cores,
                               char* tree_name,
                               uint16_t** model,
                               uint32_t** leafs,
                               uint32_t* t_root,
                               uint32_t* len_model)
{
    // Ask the Simulator to build a model
    const char *host = get_env_str("SMLT_HOSTNAME", "");
    const char *machine = get_env_str("SMLT_MACHINE", "unknown");
    const char *hybrid = get_env_str("SMLT_HYBRID", "False");
    bool hyb = false;

    if ((strcmp(hybrid, "true") == 0) ||
        (strcmp(hybrid, "True") == 0)) {
        hyb = true;
    }

    // Determine hostname of this machine
    char thishost[NAMELEN];
    gethostname(thishost, NAMELEN);

    if (strlen(host)>0) {
        printf("Hostname is %s \n", host);
    } else {
        printf("No hostname give, not contacting generator \n");
        return 1;
    }

    Json::StreamWriterBuilder wbuilder;
    wbuilder["indentatin"] = "\t";

    // Override hostname if given as environment variable
    if (strcmp(machine, "unknown") != 0) {
        printf("Overriding hosname %s --> %s\n", thishost, machine);
        strncpy(thishost, machine, NAMELEN);
    }

    Json::Value root;   // 'root' will contain the root value after parsing.
    root["machine"] = thishost;

    const char *topo_name;

    if (tree_name == NULL) {
        printf("Getting topo from env string\n");
        topo_name = get_env_str("SMLT_TOPO", "adaptivetree");
    } else {
        topo_name = tree_name;
    }

    root["topology"] = topo_name;
    printf("Requesting topology: %s\n", topo_name);

    Json::Value coreids;

    if (cores != NULL) {
        for (unsigned i=0; i<ncores; i++)
            coreids.append(cores[i]);
    } else {
        for (unsigned i=0; i<ncores; i++)
            coreids.append(i);
    }

    root["cores"] = coreids;

    if (hyb) {
        root["hybrid"] = "True";
    } else {
        root["hybrid"] = "False";
    }

    std::string doc = Json::writeString(wbuilder, root);

    return smlt_tree_config_request(host, doc.c_str(), ncores,
                                    model, leafs, t_root, len_model);
}
<commit_msg>Small bugfix in contrib<commit_after>#include <iostream>
#include <cstring>      // Needed for memset
#include <sys/socket.h> // Needed for the socket functions
#include <netdb.h>      // Needed for the socket functions
#include <unistd.h>
#include <assert.h>
#include <memory> // unique_ptr
#include <string.h>

#include "sim.h"
#include "jsoncpp/json/json.h"

#define PORT "25041"

/**
 * \brief Read from environment variable as string
 */
static char* get_env_str(const char *envname, const char *defaultvalue)
{
    char *env;
    env = getenv (envname);

    if (env==NULL) {

        return (char*) defaultvalue;
    }

    return env;
}

int smlt_tree_parse_wrapper(char* json_string,
                            unsigned ncores,
                            uint16_t** model,
                            uint32_t** leafs,
                            uint32_t* t_root,
                            uint32_t* len_model)
{
    Json::Value root;
    // Json::CharReaderBuilder rbuilder;
    // rbuilder["collectComments"] = false;
    std::string errs;
    // bool ok = Json::parseFromStream(rbuilder, rec, &root, &errs);

    Json::CharReaderBuilder rbuilder;
    Json::CharReader* reader = rbuilder.newCharReader();

    reader->parse(json_string, json_string+strlen(json_string)-1,
                  &root, &errs);
    // Extract last node
    Json::Value ln = root.get("root", "");
    int lnval = ln.asInt();
    *t_root = (uint32_t)lnval;

    // Extract leaf node

    Json::Value leafs_j = root.get("leaf_nodes", "");
    *leafs = (uint32_t*) malloc(sizeof(uint32_t)*leafs_j.size());
    assert(*leafs != NULL);

    for (unsigned i=0; i<leafs_j.size(); i++) {
        (*leafs)[i] = leafs_j.get(i, Json::Value()).asInt();
    }

    Json::Value elem = root.get("model", "");
    *model = (uint16_t*)  malloc(sizeof(uint16_t)*elem.size()*elem.size());
    assert(*model != NULL);
    int x = 0;
    int y = 0;
    *len_model = elem.size();
    for (Json::ValueIterator i=elem.begin(); i != elem.end(); i++) {
        y = 0;
        Json::Value inner = (*i);
        for (Json::ValueIterator k=inner.begin(); k != inner.end(); k++) {

            Json::Value val = (*k);
            (*model)[x*elem.size()+y] = (uint32_t) val.asInt();
            y++;
        }
        x++;
    }

    return 0;
}

static int smlt_tree_config_request(const char *hostname,
                                    const char* msg,
                                    unsigned ncores,
                                    uint16_t** model,
                                    uint32_t** leafs,
                                    uint32_t* t_root,
                                    uint32_t* len_model)
{

    int status;
    struct addrinfo host_info;       // The struct that getaddrinfo() fills up with data.
    struct addrinfo *host_info_list; // Pointer to the to the linked list of host_info's.

    // The MAN page of getaddrinfo() states "All  the other fields in the structure pointed
    // to by hints must contain either 0 or a null pointer, as appropriate." When a struct
    // is created in c++, it will be given a block of memory. This memory is not nessesary
    // empty. Therefor we use the memset function to make sure all fields are NULL.
    memset(&host_info, 0, sizeof host_info);

    host_info.ai_family = AF_UNSPEC;     // IP version not specified. Can be both.
    host_info.ai_socktype = SOCK_STREAM; // Use SOCK_STREAM for TCP or SOCK_DGRAM for UDP.

    // Now fill up the linked list of host_info structs with google's address information.
    status = getaddrinfo(hostname, PORT, &host_info, &host_info_list);
    // getaddrinfo returns 0 on succes, or some other value when an error occured.
    // (translated into human readable text by the gai_gai_strerror function).
    if (status != 0) {
        std::cout << "getaddrinfo error" << gai_strerror(status) ;
        return 1;
    }

    int socketfd ; // The socket descripter
    socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype,
                  host_info_list->ai_protocol);
    if (socketfd == -1) {
        std::cout << "socket error " ;
        return 1;
    }

    status = connect(socketfd, host_info_list->ai_addr, host_info_list->ai_addrlen);
    if (status == -1) {
        std::cout << "connect error" ;
        return 1;
    }

    int len = strlen(msg);
    int bytes_sent;

    bytes_sent = send(socketfd, msg, len, 0);
    assert (bytes_sent==len);

    ssize_t bytes_recieved;
    char incomming_data_buffer[1000];

    std::string rec;

    do {
        bytes_recieved = recv(socketfd, incomming_data_buffer,1000, 0);

        // If no data arrives, the program will just wait here until some data arrives.
        if (bytes_recieved > 0) {
            incomming_data_buffer[bytes_recieved] = '\0' ;

            rec.append(incomming_data_buffer);
        }
        else {
            if (bytes_recieved == 0) {
               printf("host shut down \n");
            } else if (bytes_recieved == -1) {
               printf("receive error \n");
               return 1;
            }
        }

    } while(bytes_recieved>0);

    freeaddrinfo(host_info_list);
    shutdown(socketfd, SHUT_RDWR);
    assert(model != NULL);
    char* inp = (char*) rec.c_str();

    return smlt_tree_parse_wrapper(inp, ncores, model, leafs, t_root, len_model);
}

#define NAMELEN 1000U

int smlt_tree_generate_wrapper(unsigned ncores,
                               uint32_t* cores,
                               char* tree_name,
                               uint16_t** model,
                               uint32_t** leafs,
                               uint32_t* t_root,
                               uint32_t* len_model)
{
    // Ask the Simulator to build a model
    const char *host = get_env_str("SMLT_HOSTNAME", "");
    const char *machine = get_env_str("SMLT_MACHINE", "unknown");
    const char *hybrid = get_env_str("SMLT_HYBRID", "False");
    bool hyb = false;

    if ((strcmp(hybrid, "true") == 0) ||
        (strcmp(hybrid, "True") == 0)) {
        hyb = true;
    }

    // Determine hostname of this machine
    char thishost[NAMELEN];
    gethostname(thishost, NAMELEN);

    if (strlen(host)>0) {
        printf("Hostname is %s \n", host);
    } else {
        printf("No hostname give, not contacting generator \n");
        return 1;
    }

    Json::StreamWriterBuilder wbuilder;
    wbuilder["indentatin"] = "\t";

    // Override hostname if given as environment variable
    if (strcmp(machine, "unknown") != 0) {
        printf("Overriding hosname %s --> %s\n", thishost, machine);
        strncpy(thishost, machine, NAMELEN);
    }

    Json::Value root;   // 'root' will contain the root value after parsing.
    root["machine"] = thishost;

    const char *topo_name;

    if (tree_name == NULL) {
        printf("Getting topo from env string\n");
        topo_name = get_env_str("SMLT_TOPO", "adaptivetree");
    } else {
        topo_name = tree_name;
    }

    root["topology"] = topo_name;
    printf("Requesting topology: %s\n", topo_name);

    Json::Value coreids;

    if (cores != NULL) {
        for (unsigned i=0; i<ncores; i++)
            coreids.append(cores[i]);
    } else {
        for (unsigned i=0; i<ncores; i++)
            coreids.append(i);
    }

    root["cores"] = coreids;

    if (hyb) {
        root["hybrid"] = "True";
    }

    std::string doc = Json::writeString(wbuilder, root);

    return smlt_tree_config_request(host, doc.c_str(), ncores,
                                    model, leafs, t_root, len_model);
}
<|endoftext|>


<commit_before>#include <iostream>

#include "headings.h"
#include "libaps.h"
#include "constants.h"

#include <concol.h>

using namespace std;

// command options functions taken from:
// http://stackoverflow.com/questions/865668/parse-command-line-arguments
string getCmdOption(char ** begin, char ** end, const std::string & option)
{
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end)
  {
    return string(*itr);
  }
  return "";
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
  return std::find(begin, end, option) != end;
}

int main (int argc, char* argv[])
{

  concol::concolinit();
  cout << concol::RED << "BBN AP2 Flash Test Executable" << concol::RESET << endl;

  int dbgLevel = 8;
  if (argc >= 2) {
    dbgLevel = atoi(argv[1]);
  }

  set_logging_level(dbgLevel);

  cout << concol::RED << "Attempting to initialize libaps" << concol::RESET << endl;

  init("eth0");

  int numDevices = get_numDevices();

  cout << concol::RED << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << concol::RESET << endl;

  if (numDevices < 1)
  	return 0;

  cout << concol::RED << "Attempting to get serials" << concol::RESET << endl;

  const char ** serialBuffer = new const char*[numDevices];
  get_deviceSerials(serialBuffer);

  for (int cnt=0; cnt < numDevices; cnt++) {
  	cout << concol::RED << "Device " << cnt << " serial #: " << serialBuffer[cnt] << concol::RESET << endl;
  }

  cout << concol::RED << "Connecting to device serial #: " << serialBuffer[0] << concol::RESET << endl;

  string deviceSerial(serialBuffer[0]);

  connect_APS(deviceSerial.c_str());

  double uptime = get_uptime(deviceSerial.c_str());

  cout << concol::RED << "Uptime for device " << deviceSerial << " is " << uptime << " seconds" << concol::RESET << endl;

  uint32_t buffer[2] = {0, 0};

  // test reading from FLASH
  read_flash(deviceSerial.c_str(), 0x00FF0000, 2, buffer);
  cout << "Programmed MAC address at 0x00FF0000 is " << endl << hexn<8> << buffer[0] << " " << buffer[1] << endl;

  // read SPI setup sequence
  uint32_t setup[32];
  read_flash(deviceSerial.c_str(), 0x0, 32, setup);
  cout << "Programmed setup SPI sequence:" << endl;
  for (size_t ct=0; ct < 32; ct++) {
    cout << hexn<8> << setup[ct] << " ";
    if (ct % 4 == 3) cout << endl;
  }

  // write new SPI setup sequence
  // write_SPI_setup(deviceSerial.c_str());

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 2, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (64 words)" << concol::RESET << endl;
  vector<uint32_t> testData;
  for (size_t ct=0; ct<64; ct++){
    testData.push_back(0x00FA0000 + static_cast<uint32_t>(ct));
  }
  write_flash(deviceSerial.c_str(), 0x00FA0000, testData.data(), testData.size());

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 2, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " <<  hexn<8> << buffer[1] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (2 words)" << concol::RESET << endl;
  buffer[0] = 0xBADD1234;
  buffer[1] = 0x1234F00F;
  write_flash(deviceSerial.c_str(), 0x00FA0000, buffer, 2);

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 2, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " <<  hexn<8> << buffer[1] << endl;

  disconnect_APS(deviceSerial.c_str());

  delete[] serialBuffer;

  cout << concol::RED << "Finished!" << concol::RESET << endl;

  return 0;
}
<commit_msg>Read non-volatile IP address.<commit_after>#include <iostream>

#include "headings.h"
#include "libaps.h"
#include "constants.h"

#include <concol.h>

using namespace std;

// command options functions taken from:
// http://stackoverflow.com/questions/865668/parse-command-line-arguments
string getCmdOption(char ** begin, char ** end, const std::string & option)
{
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end)
  {
    return string(*itr);
  }
  return "";
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
  return std::find(begin, end, option) != end;
}

int main (int argc, char* argv[])
{

  concol::concolinit();
  cout << concol::RED << "BBN AP2 Flash Test Executable" << concol::RESET << endl;

  int dbgLevel = 8;
  if (argc >= 2) {
    dbgLevel = atoi(argv[1]);
  }

  set_logging_level(dbgLevel);

  cout << concol::RED << "Attempting to initialize libaps" << concol::RESET << endl;

  init("eth0");

  int numDevices = get_numDevices();

  cout << concol::RED << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << concol::RESET << endl;

  if (numDevices < 1)
  	return 0;

  cout << concol::RED << "Attempting to get serials" << concol::RESET << endl;

  const char ** serialBuffer = new const char*[numDevices];
  get_deviceSerials(serialBuffer);

  for (int cnt=0; cnt < numDevices; cnt++) {
  	cout << concol::RED << "Device " << cnt << " serial #: " << serialBuffer[cnt] << concol::RESET << endl;
  }

  cout << concol::RED << "Connecting to device serial #: " << serialBuffer[0] << concol::RESET << endl;

  string deviceSerial(serialBuffer[0]);

  connect_APS(deviceSerial.c_str());

  double uptime = get_uptime(deviceSerial.c_str());

  cout << concol::RED << "Uptime for device " << deviceSerial << " is " << uptime << " seconds" << concol::RESET << endl;

  uint32_t buffer[3] = {0, 0, 0};

  // test reading from FLASH
  read_flash(deviceSerial.c_str(), 0x00FF0000, 3, buffer);
  cout << "Programmed ZRL MAC and IP address at 0x00FF0000 is " << endl << hexn<8> << buffer[0] << " " << buffer[1] << endl;
  cout << std::dec << (buffer[2] >> 24) << "." << ((buffer[2] >> 16) & 0xFF) << "." << ((buffer[2] >> 8) & 0xFF) << "." << (buffer[2] & 0xFF) << endl;

  // read SPI setup sequence
  uint32_t setup[32];
  read_flash(deviceSerial.c_str(), 0x0, 32, setup);
  cout << "Programmed setup SPI sequence:" << endl;
  for (size_t ct=0; ct < 32; ct++) {
    cout << hexn<8> << setup[ct] << " ";
    if (ct % 4 == 3) cout << endl;
  }

  // write new SPI setup sequence
  // write_SPI_setup(deviceSerial.c_str());

  // write a new MAC and IP address
  vector<uint32_t> testData;
  // testData.push_back(0x00223344);
  // testData.push_back(0x55660000);
  // testData.push_back(0xc0a8050a); // 192.168.5.10
  // write_flash(deviceSerial.c_str(), 0x00FF0000, testData.data(), testData.size());
  // testData.clear();

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 2, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " << hexn<8> << buffer[1] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (64 words)" << concol::RESET << endl;
  for (size_t ct=0; ct<64; ct++){
    testData.push_back(0x00FA0000 + static_cast<uint32_t>(ct));
  }
  write_flash(deviceSerial.c_str(), 0x00FA0000, testData.data(), testData.size());

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 2, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " <<  hexn<8> << buffer[1] << endl;

  cout << concol::RED << "Erasing/writing flash addr 0x00FA0000 (2 words)" << concol::RESET << endl;
  buffer[0] = 0xBADD1234;
  buffer[1] = 0x1234F00F;
  write_flash(deviceSerial.c_str(), 0x00FA0000, buffer, 2);

  cout << concol::RED << "Reading flash addr 0x00FA0000" << concol::RESET << endl;
  read_flash(deviceSerial.c_str(), 0x00FA0000, 2, buffer);
  cout << "Received " << hexn<8> << buffer[0] << " " <<  hexn<8> << buffer[1] << endl;

  disconnect_APS(deviceSerial.c_str());

  delete[] serialBuffer;

  cout << concol::RED << "Finished!" << concol::RESET << endl;

  return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkExceptionObject.h"
#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkLinearInterpolateImageFunction.h"

#include <iostream>

#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

#include "otbAssymmetricFusionOfLineDetectorImageFilter.h"

int otbAssymmetricFusionOfLineDetectorNew( int argc, char * argv[] )
{
  try
    {
        const char * inputFilename  = argv[1];
        const char * outputFilename = argv[2];

	// Width of the linear feature = 2*WidthLine+1
        unsigned int  WidthLine((unsigned int)::atoi(argv[3]));
        // Length of the linear feature = 2*LengthLine+1
        unsigned int  LengthLine((unsigned int)::atoi(argv[4]));

        typedef unsigned char                                   InputPixelType;
        typedef double		   	                        OutputPixelType;
        const   unsigned int        	                        Dimension = 2;

        typedef itk::Image< InputPixelType,  Dimension >        InputImageType;
        typedef itk::Image< OutputPixelType, Dimension >        OutputImageType;

        typedef otb::ImageFileReader< InputImageType  >         ReaderType;
        typedef otb::ImageFileWriter< OutputImageType >         WriterType;

        typedef itk::LinearInterpolateImageFunction< InputImageType, double >	InterpolatorType;

        typedef otb::AssymmetricFusionOfLineDetectorImageFilter< InputImageType, OutputImageType, InterpolatorType >   FilterType;

        FilterType::Pointer FilterAssSymSum = FilterType::New();

    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "Exception itk::ExceptionObject levee !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  catch( ... )
    {
    std::cout << "Exception levee inconnue !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}

<commit_msg>Correction : suppression des parametres lus dans la ligne de commande, car inutile et plante sous Windows.<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkExceptionObject.h"
#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkLinearInterpolateImageFunction.h"

#include <iostream>

#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

#include "otbAssymmetricFusionOfLineDetectorImageFilter.h"

int otbAssymmetricFusionOfLineDetectorNew( int argc, char * argv[] )
{
  try
    {
        typedef unsigned char                                   InputPixelType;
        typedef double		   	                        OutputPixelType;
        const   unsigned int        	                        Dimension = 2;

        typedef itk::Image< InputPixelType,  Dimension >        InputImageType;
        typedef itk::Image< OutputPixelType, Dimension >        OutputImageType;

        typedef itk::LinearInterpolateImageFunction< InputImageType, double >	InterpolatorType;

        typedef otb::AssymmetricFusionOfLineDetectorImageFilter< InputImageType, OutputImageType, InterpolatorType >   FilterType;

        FilterType::Pointer FilterAssSymSum = FilterType::New();

    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "Exception itk::ExceptionObject levee !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }
  catch( ... )
    {
    std::cout << "Exception levee inconnue !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "brw_fs.h"
#include "brw_cfg.h"

/** @file brw_fs_cse.cpp
 *
 * Support for local common subexpression elimination.
 *
 * See Muchnick's Advanced Compiler Design and Implementation, section
 * 13.1 (p378).
 */

namespace {
struct aeb_entry : public exec_node {
   /** The instruction that generates the expression value. */
   fs_inst *generator;

   /** The temporary where the value is stored. */
   fs_reg tmp;
};
}

static bool
is_copy_payload(const fs_inst *inst)
{
   const int reg = inst->src[0].reg;
   if (inst->src[0].reg_offset != 0)
      return false;

   for (int i = 1; i < inst->sources; i++) {
      if (inst->src[i].reg != reg ||
          inst->src[i].reg_offset != i) {
         return false;
      }
   }
   return true;
}

static bool
is_expression(const fs_inst *const inst)
{
   switch (inst->opcode) {
   case BRW_OPCODE_SEL:
   case BRW_OPCODE_NOT:
   case BRW_OPCODE_AND:
   case BRW_OPCODE_OR:
   case BRW_OPCODE_XOR:
   case BRW_OPCODE_SHR:
   case BRW_OPCODE_SHL:
   case BRW_OPCODE_ASR:
   case BRW_OPCODE_CMP:
   case BRW_OPCODE_CMPN:
   case BRW_OPCODE_ADD:
   case BRW_OPCODE_MUL:
   case BRW_OPCODE_FRC:
   case BRW_OPCODE_RNDU:
   case BRW_OPCODE_RNDD:
   case BRW_OPCODE_RNDE:
   case BRW_OPCODE_RNDZ:
   case BRW_OPCODE_LINE:
   case BRW_OPCODE_PLN:
   case BRW_OPCODE_MAD:
   case BRW_OPCODE_LRP:
   case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD:
   case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7:
   case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD:
   case FS_OPCODE_CINTERP:
   case FS_OPCODE_LINTERP:
      return true;
   case SHADER_OPCODE_RCP:
   case SHADER_OPCODE_RSQ:
   case SHADER_OPCODE_SQRT:
   case SHADER_OPCODE_EXP2:
   case SHADER_OPCODE_LOG2:
   case SHADER_OPCODE_POW:
   case SHADER_OPCODE_INT_QUOTIENT:
   case SHADER_OPCODE_INT_REMAINDER:
   case SHADER_OPCODE_SIN:
   case SHADER_OPCODE_COS:
      return inst->mlen < 2;
   case SHADER_OPCODE_LOAD_PAYLOAD:
      return !is_copy_payload(inst);
   default:
      return inst->is_send_from_grf() && !inst->has_side_effects();
   }
}

static bool
is_expression_commutative(enum opcode op)
{
   switch (op) {
   case BRW_OPCODE_AND:
   case BRW_OPCODE_OR:
   case BRW_OPCODE_XOR:
   case BRW_OPCODE_ADD:
   case BRW_OPCODE_MUL:
      return true;
   default:
      return false;
   }
}

static bool
operands_match(fs_inst *a, fs_inst *b)
{
   fs_reg *xs = a->src;
   fs_reg *ys = b->src;

   if (a->opcode == BRW_OPCODE_MAD) {
      return xs[0].equals(ys[0]) &&
             ((xs[1].equals(ys[1]) && xs[2].equals(ys[2])) ||
              (xs[2].equals(ys[1]) && xs[1].equals(ys[2])));
   } else if (!is_expression_commutative(a->opcode)) {
      bool match = true;
      for (int i = 0; i < a->sources; i++) {
         if (!xs[i].equals(ys[i])) {
            match = false;
            break;
         }
      }
      return match;
   } else {
      return (xs[0].equals(ys[0]) && xs[1].equals(ys[1])) ||
             (xs[1].equals(ys[0]) && xs[0].equals(ys[1]));
   }
}

static bool
instructions_match(fs_inst *a, fs_inst *b)
{
   return a->opcode == b->opcode &&
          a->saturate == b->saturate &&
          a->predicate == b->predicate &&
          a->predicate_inverse == b->predicate_inverse &&
          a->conditional_mod == b->conditional_mod &&
          a->dst.type == b->dst.type &&
          a->sources == b->sources &&
          (a->is_tex() ? (a->offset == b->offset &&
                          a->mlen == b->mlen &&
                          a->regs_written == b->regs_written &&
                          a->base_mrf == b->base_mrf &&
                          a->eot == b->eot &&
                          a->header_present == b->header_present &&
                          a->shadow_compare == b->shadow_compare)
                       : true) &&
          operands_match(a, b);
}

bool
fs_visitor::opt_cse_local(bblock_t *block)
{
   bool progress = false;
   exec_list aeb;

   void *cse_ctx = ralloc_context(NULL);

   int ip = block->start_ip;
   foreach_inst_in_block(fs_inst, inst, block) {
      /* Skip some cases. */
      if (is_expression(inst) && !inst->is_partial_write() &&
          (inst->dst.file != HW_REG || inst->dst.is_null()))
      {
         bool found = false;

         foreach_in_list_use_after(aeb_entry, entry, &aeb) {
            /* Match current instruction's expression against those in AEB. */
            if (instructions_match(inst, entry->generator)) {
               found = true;
               progress = true;
               break;
            }
         }

         if (!found) {
            /* Our first sighting of this expression.  Create an entry. */
            aeb_entry *entry = ralloc(cse_ctx, aeb_entry);
            entry->tmp = reg_undef;
            entry->generator = inst;
            aeb.push_tail(entry);
         } else {
            /* This is at least our second sighting of this expression.
             * If we don't have a temporary already, make one.
             */
            bool no_existing_temp = entry->tmp.file == BAD_FILE;
            if (no_existing_temp && !entry->generator->dst.is_null()) {
               int written = entry->generator->regs_written;
               int dst_width = entry->generator->dst.width / 8;
               assert(written % dst_width == 0);

               fs_reg orig_dst = entry->generator->dst;
               fs_reg tmp = fs_reg(GRF, virtual_grf_alloc(written),
                                   orig_dst.type, orig_dst.width);
               entry->tmp = tmp;
               entry->generator->dst = tmp;

               fs_inst *copy;
               if (written > dst_width) {
                  fs_reg *sources = ralloc_array(mem_ctx, fs_reg, written / dst_width);
                  for (int i = 0; i < written / dst_width; i++)
                     sources[i] = offset(tmp, i);
                  copy = LOAD_PAYLOAD(orig_dst, sources, written / dst_width);
               } else {
                  copy = MOV(orig_dst, tmp);
                  copy->force_writemask_all =
                     entry->generator->force_writemask_all;
               }
               entry->generator->insert_after(block, copy);
            }

            /* dest <- temp */
            if (!inst->dst.is_null()) {
               int written = inst->regs_written;
               int dst_width = inst->dst.width / 8;
               assert(written == entry->generator->regs_written);
               assert(dst_width == entry->generator->dst.width / 8);
               assert(inst->dst.type == entry->tmp.type);
               fs_reg dst = inst->dst;
               fs_reg tmp = entry->tmp;
               fs_inst *copy;
               if (written > dst_width) {
                  fs_reg *sources = ralloc_array(mem_ctx, fs_reg, written / dst_width);
                  for (int i = 0; i < written / dst_width; i++)
                     sources[i] = offset(tmp, i);
                  copy = LOAD_PAYLOAD(dst, sources, written / dst_width);
               } else {
                  copy = MOV(dst, tmp);
                  copy->force_writemask_all = inst->force_writemask_all;
               }
               inst->insert_before(block, copy);
            }

            /* Set our iterator so that next time through the loop inst->next
             * will get the instruction in the basic block after the one we've
             * removed.
             */
            fs_inst *prev = (fs_inst *)inst->prev;

            inst->remove(block);
            inst = prev;
         }
      }

      foreach_in_list_safe(aeb_entry, entry, &aeb) {
         /* Kill all AEB entries that write a different value to or read from
          * the flag register if we just wrote it.
          */
         if (inst->writes_flag()) {
            if (entry->generator->reads_flag() ||
                (entry->generator->writes_flag() &&
                 !instructions_match(inst, entry->generator))) {
               entry->remove();
               ralloc_free(entry);
               continue;
            }
         }

         for (int i = 0; i < entry->generator->sources; i++) {
            fs_reg *src_reg = &entry->generator->src[i];

            /* Kill all AEB entries that use the destination we just
             * overwrote.
             */
            if (inst->overwrites_reg(entry->generator->src[i])) {
               entry->remove();
               ralloc_free(entry);
               break;
            }

            /* Kill any AEB entries using registers that don't get reused any
             * more -- a sure sign they'll fail operands_match().
             */
            if (src_reg->file == GRF && virtual_grf_end[src_reg->reg] < ip) {
               entry->remove();
               ralloc_free(entry);
               break;
            }
         }
      }

      ip++;
   }

   ralloc_free(cse_ctx);

   return progress;
}

bool
fs_visitor::opt_cse()
{
   bool progress = false;

   calculate_live_intervals();

   foreach_block (block, cfg) {
      progress = opt_cse_local(block) || progress;
   }

   if (progress)
      invalidate_live_intervals();

   return progress;
}
<commit_msg>i965/fs: Perform CSE on MOV ..., VF instructions.<commit_after>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "brw_fs.h"
#include "brw_cfg.h"

/** @file brw_fs_cse.cpp
 *
 * Support for local common subexpression elimination.
 *
 * See Muchnick's Advanced Compiler Design and Implementation, section
 * 13.1 (p378).
 */

namespace {
struct aeb_entry : public exec_node {
   /** The instruction that generates the expression value. */
   fs_inst *generator;

   /** The temporary where the value is stored. */
   fs_reg tmp;
};
}

static bool
is_copy_payload(const fs_inst *inst)
{
   const int reg = inst->src[0].reg;
   if (inst->src[0].reg_offset != 0)
      return false;

   for (int i = 1; i < inst->sources; i++) {
      if (inst->src[i].reg != reg ||
          inst->src[i].reg_offset != i) {
         return false;
      }
   }
   return true;
}

static bool
is_expression(const fs_inst *const inst)
{
   switch (inst->opcode) {
   case BRW_OPCODE_MOV:
   case BRW_OPCODE_SEL:
   case BRW_OPCODE_NOT:
   case BRW_OPCODE_AND:
   case BRW_OPCODE_OR:
   case BRW_OPCODE_XOR:
   case BRW_OPCODE_SHR:
   case BRW_OPCODE_SHL:
   case BRW_OPCODE_ASR:
   case BRW_OPCODE_CMP:
   case BRW_OPCODE_CMPN:
   case BRW_OPCODE_ADD:
   case BRW_OPCODE_MUL:
   case BRW_OPCODE_FRC:
   case BRW_OPCODE_RNDU:
   case BRW_OPCODE_RNDD:
   case BRW_OPCODE_RNDE:
   case BRW_OPCODE_RNDZ:
   case BRW_OPCODE_LINE:
   case BRW_OPCODE_PLN:
   case BRW_OPCODE_MAD:
   case BRW_OPCODE_LRP:
   case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD:
   case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7:
   case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD:
   case FS_OPCODE_CINTERP:
   case FS_OPCODE_LINTERP:
      return true;
   case SHADER_OPCODE_RCP:
   case SHADER_OPCODE_RSQ:
   case SHADER_OPCODE_SQRT:
   case SHADER_OPCODE_EXP2:
   case SHADER_OPCODE_LOG2:
   case SHADER_OPCODE_POW:
   case SHADER_OPCODE_INT_QUOTIENT:
   case SHADER_OPCODE_INT_REMAINDER:
   case SHADER_OPCODE_SIN:
   case SHADER_OPCODE_COS:
      return inst->mlen < 2;
   case SHADER_OPCODE_LOAD_PAYLOAD:
      return !is_copy_payload(inst);
   default:
      return inst->is_send_from_grf() && !inst->has_side_effects();
   }
}

static bool
is_expression_commutative(enum opcode op)
{
   switch (op) {
   case BRW_OPCODE_AND:
   case BRW_OPCODE_OR:
   case BRW_OPCODE_XOR:
   case BRW_OPCODE_ADD:
   case BRW_OPCODE_MUL:
      return true;
   default:
      return false;
   }
}

static bool
operands_match(fs_inst *a, fs_inst *b)
{
   fs_reg *xs = a->src;
   fs_reg *ys = b->src;

   if (a->opcode == BRW_OPCODE_MAD) {
      return xs[0].equals(ys[0]) &&
             ((xs[1].equals(ys[1]) && xs[2].equals(ys[2])) ||
              (xs[2].equals(ys[1]) && xs[1].equals(ys[2])));
   } else if (!is_expression_commutative(a->opcode)) {
      bool match = true;
      for (int i = 0; i < a->sources; i++) {
         if (!xs[i].equals(ys[i])) {
            match = false;
            break;
         }
      }
      return match;
   } else {
      return (xs[0].equals(ys[0]) && xs[1].equals(ys[1])) ||
             (xs[1].equals(ys[0]) && xs[0].equals(ys[1]));
   }
}

static bool
instructions_match(fs_inst *a, fs_inst *b)
{
   return a->opcode == b->opcode &&
          a->saturate == b->saturate &&
          a->predicate == b->predicate &&
          a->predicate_inverse == b->predicate_inverse &&
          a->conditional_mod == b->conditional_mod &&
          a->dst.type == b->dst.type &&
          a->sources == b->sources &&
          (a->is_tex() ? (a->offset == b->offset &&
                          a->mlen == b->mlen &&
                          a->regs_written == b->regs_written &&
                          a->base_mrf == b->base_mrf &&
                          a->eot == b->eot &&
                          a->header_present == b->header_present &&
                          a->shadow_compare == b->shadow_compare)
                       : true) &&
          operands_match(a, b);
}

bool
fs_visitor::opt_cse_local(bblock_t *block)
{
   bool progress = false;
   exec_list aeb;

   void *cse_ctx = ralloc_context(NULL);

   int ip = block->start_ip;
   foreach_inst_in_block(fs_inst, inst, block) {
      /* Skip some cases. */
      if (is_expression(inst) && !inst->is_partial_write() &&
          (inst->dst.file != HW_REG || inst->dst.is_null()))
      {
         bool found = false;

         foreach_in_list_use_after(aeb_entry, entry, &aeb) {
            /* Match current instruction's expression against those in AEB. */
            if (instructions_match(inst, entry->generator)) {
               found = true;
               progress = true;
               break;
            }
         }

         if (!found) {
            if (inst->opcode != BRW_OPCODE_MOV ||
                (inst->opcode == BRW_OPCODE_MOV &&
                 inst->src[0].file == IMM &&
                 inst->src[0].type == BRW_REGISTER_TYPE_VF)) {
               /* Our first sighting of this expression.  Create an entry. */
               aeb_entry *entry = ralloc(cse_ctx, aeb_entry);
               entry->tmp = reg_undef;
               entry->generator = inst;
               aeb.push_tail(entry);
            }
         } else {
            /* This is at least our second sighting of this expression.
             * If we don't have a temporary already, make one.
             */
            bool no_existing_temp = entry->tmp.file == BAD_FILE;
            if (no_existing_temp && !entry->generator->dst.is_null()) {
               int written = entry->generator->regs_written;
               int dst_width = entry->generator->dst.width / 8;
               assert(written % dst_width == 0);

               fs_reg orig_dst = entry->generator->dst;
               fs_reg tmp = fs_reg(GRF, virtual_grf_alloc(written),
                                   orig_dst.type, orig_dst.width);
               entry->tmp = tmp;
               entry->generator->dst = tmp;

               fs_inst *copy;
               if (written > dst_width) {
                  fs_reg *sources = ralloc_array(mem_ctx, fs_reg, written / dst_width);
                  for (int i = 0; i < written / dst_width; i++)
                     sources[i] = offset(tmp, i);
                  copy = LOAD_PAYLOAD(orig_dst, sources, written / dst_width);
               } else {
                  copy = MOV(orig_dst, tmp);
                  copy->force_writemask_all =
                     entry->generator->force_writemask_all;
               }
               entry->generator->insert_after(block, copy);
            }

            /* dest <- temp */
            if (!inst->dst.is_null()) {
               int written = inst->regs_written;
               int dst_width = inst->dst.width / 8;
               assert(written == entry->generator->regs_written);
               assert(dst_width == entry->generator->dst.width / 8);
               assert(inst->dst.type == entry->tmp.type);
               fs_reg dst = inst->dst;
               fs_reg tmp = entry->tmp;
               fs_inst *copy;
               if (written > dst_width) {
                  fs_reg *sources = ralloc_array(mem_ctx, fs_reg, written / dst_width);
                  for (int i = 0; i < written / dst_width; i++)
                     sources[i] = offset(tmp, i);
                  copy = LOAD_PAYLOAD(dst, sources, written / dst_width);
               } else {
                  copy = MOV(dst, tmp);
                  copy->force_writemask_all = inst->force_writemask_all;
               }
               inst->insert_before(block, copy);
            }

            /* Set our iterator so that next time through the loop inst->next
             * will get the instruction in the basic block after the one we've
             * removed.
             */
            fs_inst *prev = (fs_inst *)inst->prev;

            inst->remove(block);
            inst = prev;
         }
      }

      foreach_in_list_safe(aeb_entry, entry, &aeb) {
         /* Kill all AEB entries that write a different value to or read from
          * the flag register if we just wrote it.
          */
         if (inst->writes_flag()) {
            if (entry->generator->reads_flag() ||
                (entry->generator->writes_flag() &&
                 !instructions_match(inst, entry->generator))) {
               entry->remove();
               ralloc_free(entry);
               continue;
            }
         }

         for (int i = 0; i < entry->generator->sources; i++) {
            fs_reg *src_reg = &entry->generator->src[i];

            /* Kill all AEB entries that use the destination we just
             * overwrote.
             */
            if (inst->overwrites_reg(entry->generator->src[i])) {
               entry->remove();
               ralloc_free(entry);
               break;
            }

            /* Kill any AEB entries using registers that don't get reused any
             * more -- a sure sign they'll fail operands_match().
             */
            if (src_reg->file == GRF && virtual_grf_end[src_reg->reg] < ip) {
               entry->remove();
               ralloc_free(entry);
               break;
            }
         }
      }

      ip++;
   }

   ralloc_free(cse_ctx);

   return progress;
}

bool
fs_visitor::opt_cse()
{
   bool progress = false;

   calculate_live_intervals();

   foreach_block (block, cfg) {
      progress = opt_cse_local(block) || progress;
   }

   if (progress)
      invalidate_live_intervals();

   return progress;
}
<|endoftext|>