void handleNamedArgumentTable(lua_State* luaSt, const MWNamedArg* args, int table)
{
    const MWNamedArg* p;
    char buf[128];
    int item;

    p = args;
    while (p->name)
    {
        lua_pushstring(luaSt, p->name);
        lua_pushvalue(luaSt, -1);  /* Copy the key since lua_gettable pops it */

        lua_gettable(luaSt, table);
        item = lua_gettop(luaSt);

        if (lua_isnil(luaSt, item))
        {
            if (!p->required)
            {
                lua_pop(luaSt, 2);
                ++p;
                continue;
            }

            if (snprintf(buf, sizeof(buf), "Missing required named argument '%s'", p->name) == sizeof(buf))
                mw_panic("Error message buffer too small for key name '%s'\n", p->name);

            luaL_argerror(luaSt, table, buf);
        }

        /* We do our own type checking and errors to avoid
           Confusing and innaccurate error messages, which suggest the use of the table is wrong. */
        if (!typeEqualOrConversionOK(luaSt, p->type, -1))
        {
            namedArgumentError(luaSt, p, table, item);
        }

        if (p->type == LUA_TUSERDATA) /* We must do another level of checking for the actual type */
        {
            if (!mw_tonamedudata(luaSt, item, p->userDataTypeName))
                namedArgumentError(luaSt, p, table, -1);
        }
        else if (p->type == LUA_TLIGHTUSERDATA)
        {
            mw_panic("Unhandled named argument type lightuserdata\n");
        }

        setValueFromType(luaSt, p, item);
        lua_pop(luaSt, 2);
        ++p;
    }

    checkExtraArguments(luaSt, args, table);
}
static void setValueFromType(lua_State* luaSt, const MWNamedArg* p, int idx)
{
    void* v = p->value;
    int type = p->type;

    switch (type)
    {
        case LUA_TNUMBER: 
            setNumberFromType(luaSt, p, idx);
            break;

        case LUA_TBOOLEAN:
            *(mwbool*) v = (mwbool) lua_toboolean(luaSt, idx);
            break;

        case LUA_TSTRING:
            *(const char**) v = lua_tostring(luaSt, idx);
            break;

        case LUA_TUSERDATA:
            *(void**) v = lua_touserdata(luaSt, idx);
            break;

        case LUA_TTABLE:
        case LUA_TFUNCTION:
        case LUA_TLIGHTUSERDATA:
        case LUA_TTHREAD:
        case LUA_TNIL:
        default:
            mw_panic("Unhandled type %s (%d)\n", luaL_typename(luaSt, type), type);
    }
}
Ejemplo n.º 3
0
/* TODO: Doesn't clone tree or CL stuffs */
void cloneNBodyState(NBodyState* st, const NBodyState* oldSt)
{
    static const NBodyTree emptyTree = EMPTY_TREE;
    unsigned int nbody = oldSt->nbody;

    st->tree = emptyTree;
    st->tree.rsize = oldSt->tree.rsize;

    st->freeCell = NULL;

    st->lastCheckpoint = oldSt->lastCheckpoint;
    st->step           = oldSt->step;
    st->nbody          = oldSt->nbody;
    st->effNBody       = oldSt->effNBody;

    st->ignoreResponsive = oldSt->ignoreResponsive;
    st->usesExact = oldSt->usesExact;
    st->usesQuad = oldSt->usesQuad,
    st->dirty = oldSt->dirty;
    st->usesCL = oldSt->usesCL;
    st->reportProgress = oldSt->reportProgress;

    st->treeIncest = oldSt->treeIncest;
    st->tree.structureError = oldSt->tree.structureError;

    assert(nbody > 0);
    assert(st->bodytab == NULL && st->acctab == NULL);

    st->bodytab = (Body*) mwMallocA(nbody * sizeof(Body));
    memcpy(st->bodytab, oldSt->bodytab, nbody * sizeof(Body));

    st->acctab = (mwvector*) mwMallocA(nbody * sizeof(mwvector));
    memcpy(st->acctab, oldSt->acctab, nbody * sizeof(mwvector));

    st->orbitTrace = (mwvector*) mwMallocA(N_ORBIT_TRACE_POINTS * sizeof(mwvector));
    memcpy(st->orbitTrace, oldSt->orbitTrace, N_ORBIT_TRACE_POINTS * sizeof(mwvector));

    if (st->ci)
    {
        mw_panic("OpenCL NBodyState cloning not implemented\n");

        /*
        st->ci = (CLInfo*) mwCalloc(1, sizeof(CLInfo));
        st->nbb = (NBodyBuffers*) mwCalloc(1, sizeof(NBodyBuffers));

        memcpy(st->ci, oldSt->ci, sizeof(CLInfo));

        clRetainContext(oldSt->ci->clctx);
        clRetainProgram(oldSt->ci->prog);
        clRetainCommandQueue(oldSt->ci->queue);

        // copy buffers
        mwDuplicateBuffer(st->ci, oldSt->nbb.blah)
        */
    }

}
Ejemplo n.º 4
0
static scene_t* nbglConnectSharedScene(int instanceId)
{
    int shmId;
    const int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    struct stat sb;
    char name[128];
    scene_t* scene = NULL;

    if (snprintf(name, sizeof(name), "/milkyway_nbody_%d", instanceId) == sizeof(name))
    {
        mw_panic("name buffer too small for shared memory name\n");
    }

    shmId = shm_open(name, O_RDWR, mode);
    if (shmId < 0)
    {
        mwPerror("Error getting shared memory");
        return NULL;
    }

    if (fstat(shmId, &sb) < 0)
    {
        mwPerror("shmem fstat");
        shm_unlink(name);
        return NULL;
    }

    scene = (scene_t*) mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmId, 0);
    if (scene == MAP_FAILED)
    {
        mwPerror("mmap: Failed to mmap shared memory");
        if (shm_unlink(name) < 0)
        {
            mwPerror("Unlink shared memory");
        }

        return NULL;
    }

    if (sb.st_size < (ssize_t) sizeof(scene_t) || sb.st_size < (ssize_t) nbFindShmemSize(scene->nbody))
    {
        mw_printf("Shared memory segment is impossibly small ("ZU")\n", (size_t) sb.st_size);
        if (shm_unlink(name) < 0)
        {
            mwPerror("Unlink shared memory");
        }

        return NULL;
    }

    return scene;
}
void* mw_checknamedudata(lua_State* luaSt, int idx, const char* typeName)
{
    void* v;
    char buf[128];

    if (snprintf(buf, sizeof(buf), "`%s' expected", typeName) == sizeof(buf))
         mw_panic("Error message buffer too small for expected type name\n");

    v = luaL_checkudata(luaSt, idx, typeName);
    luaL_argcheck(luaSt, v != NULL, idx, buf);

    return v;
}
Ejemplo n.º 6
0
static EMDDistanceFunction nbMetricDistanceFunction(EMDDistanceType distType)
{
    switch (distType)
    {
    case EMD_DIST_L1:
        return emdDistL1;
        break;

    case EMD_DIST_L2:
        return emdDistL2;
        break;

    case EMD_DIST_C:
        return emdDistC;
        break;

    default:
        mw_panic("Bad or unsupported metric type");
        return NULL;
    }
}
static void checkEnumErrorStr(char* errBuf, size_t errBufSize, const MWEnumAssociation* p, const char* badStr)
{
    const MWEnumAssociation* nextP;
    static const char errStart[] = "Expected enum value where options are: ";
    char badOpt[1024];
    size_t badSize, enumLen, errLen;
    size_t remSize; /* Remaining size in buffer */

    strcpy(errBuf, errStart);
    errLen = sizeof(errStart) - 1;
    while (p->enumName)
    {
        nextP = &p[1];
        enumLen = strlen(p->enumName);
        if (errLen + enumLen + 6 > errBufSize)  /* max possible */
            mw_panic("Enum options too large for error string buffer!\n");

        errLen += enumLen;
        if (nextP->enumName) /* If there is a next one, use a comma */
        {
            strcat(strcat(errBuf, p->enumName), ", ");
            errLen += 2;  /* ', ' */
        }
        else
        {
            strcat(strcat(strcat(errBuf, "or "), p->enumName), ".");
            errLen += 4; /* 'or ' + '.' */
        }

        p = nextP;
    }

    /* If there's extra space, might as well say what the bad option was */
    badSize = snprintf(badOpt, sizeof(badOpt), " Invalid option '%s'", badStr);
    remSize = sizeof(errBuf) - errLen - 1;
    if ((badSize != sizeof(badOpt)) && (badSize < remSize))
    {
        strncat(errBuf, badOpt, remSize);
    }
}
/* LUA_TNUMBER can be marshalled to multiple c data types */
static void setNumberFromType(lua_State* luaSt, const MWNamedArg* p, int idx)
{
    const char* userDataTypeName = p->userDataTypeName;
    void* v = p->value;

    /* Check if the user specified a numeric type */
    if(userDataTypeName)
    {
        /* Integer */
        if(strcmp(INT_TYPE, userDataTypeName) == 0)
        {
            *(int*) v = (int) lua_tonumber(luaSt, idx);
            return;
        }

        /* Unsigned Integer */
        if(strcmp(UINT_TYPE, userDataTypeName) == 0)
        {        
            *(unsigned int*) v = (unsigned int) lua_tonumber(luaSt, idx);
            return;
        }

        /* Double or Float */
        if(strcmp(REAL_TYPE, userDataTypeName) == 0)
        {
            *(real*) v = (real) lua_tonumber(luaSt, idx);
            return;
        }

        mw_panic("Unknown userDataTypeName (%s) specified in MWNamedArg %s\n", userDataTypeName, p->name);
        
    }
    
    /* If userDataTypeName is NULL, the default data type is real */
    *(real*) v = (real) lua_tonumber(luaSt, idx);
    return;
}
Ejemplo n.º 9
0
/* Function for sorting bodies */
static int compareBodies(const void* _a, const void* _b)
{
    const Body* a = (const Body*) _a;
    const Body* b = (const Body*) _b;
    int rc;
    char* bufA;
    char* bufB;

    if ((rc = compareComponents(Mass(a), Mass(b))))
        return rc;

    /* Masses equal, compare positions */
    rc = compareVectors(Pos(a), Pos(b));
    if (rc == 0)
    {
        bufA = showBody(a);
        bufB = showBody(b);
        mw_panic("Comparing bodies with equal positions: %s, %s\n", bufA, bufB);
        free(bufA);  /* Never reached */
        free(bufB);
    }

    return rc;
}
/* Use one of the faster functions if available, or use something forced */
int probabilityFunctionDispatch(const AstronomyParameters* ap, const CLRequest* clr)
{
    int hasSSE2, hasSSE3, hasSSE41, hasAVX;
    int forcingInstructions = clr->forceAVX || clr->forceSSE41 || clr->forceSSE3 || clr->forceSSE2 || clr->forceX87;
    int abcd[4];

    if (!usingIntrinsicsIsAcceptable(ap, clr->forceNoIntrinsics))
    {
        probabilityFunc = selectStandardFunction(ap);
        return 0;
    }

    mw_cpuid(abcd, 1, 0);

    hasAVX = mwHasAVX(abcd) && mwOSHasAVXSupport();
    hasSSE41 = mwHasSSE41(abcd);
    hasSSE3 = mwHasSSE3(abcd);
    hasSSE2 = mwHasSSE2(abcd);

    if (clr->verbose)
    {
        mw_printf("CPU features:        SSE2 = %d, SSE3 = %d, SSE4.1 = %d, AVX = %d\n"
                  "Available functions: SSE2 = %d, SSE3 = %d, SSE4.1 = %d, AVX = %d\n"
                  "Forcing:             SSE2 = %d, SSE3 = %d, SSE4.1 = %d, AVX = %d\n",
                  hasSSE2, hasSSE3, hasSSE41, hasAVX,
                  initSSE2 != NULL, initSSE3 != NULL, initSSE41 != NULL, initAVX != NULL,
                  clr->forceSSE2, clr->forceSSE3, clr->forceSSE41, clr->forceAVX);
    }

    /* If multiple instructions are forced, the highest will take precedence */
    if (forcingInstructions)
    {
        if (clr->forceAVX && hasAVX && initAVX)
        {
            mw_printf("Using AVX path\n");
            probabilityFunc = initAVX();
        }
        else if (clr->forceSSE41 && hasSSE41 && initSSE41)
        {
            mw_printf("Using SSE4.1 path\n");
            probabilityFunc = initSSE41();
        }
        else if (clr->forceSSE3 && hasSSE3 && initSSE3)
        {
            mw_printf("Using SSE3 path\n");
            probabilityFunc = initSSE3();
        }
        else if (clr->forceSSE2 && hasSSE2 && initSSE2)
        {
            mw_printf("Using SSE2 path\n");
            probabilityFunc = initSSE2();
        }
        else if (clr->forceX87)
        {
            mw_printf("Using other path\n");
            probabilityFunc = selectStandardFunction(ap);
        }
        else
        {
            mw_printf("Tried to force an unusable path\n");
            return 1;
        }
    }
    else
    {
        /* Choose the highest level with available function and instructions */
        if (hasAVX && initAVX)
        {
            mw_printf("Using AVX path\n");
            probabilityFunc = initAVX();
        }
        else if (hasSSE41 && initSSE41)
        {
            mw_printf("Using SSE4.1 path\n");
            probabilityFunc = initSSE41();
        }
        else if (hasSSE3 && initSSE3)
        {
            mw_printf("Using SSE3 path\n");
            probabilityFunc = initSSE3();
        }
        else if (hasSSE2 && initSSE2)
        {
            mw_printf("Using SSE2 path\n");
            probabilityFunc = initSSE2();
        }
        else
        {
            mw_printf("Using other path\n");
            probabilityFunc = selectStandardFunction(ap);
        }
    }

    if (!probabilityFunc)
    {
        mw_panic("Probability function not set!:\n"
                 "  Has AVX              = %d\n"
                 "  Has SSE4.1           = %d\n"
                 "  Has SSE3             = %d\n"
                 "  Has SSE2             = %d\n"
                 "  Forced AVX           = %d\n"
                 "  Forced SSE4.1        = %d\n"
                 "  Forced SSE3          = %d\n"
                 "  Forced SSE2          = %d\n"
                 "  Forced x87           = %d\n"
                 "  Forced no intrinsics = %d\n"
                 "  Arch                 = %s\n",
                 hasSSE41, hasSSE3, hasSSE2, hasAVX,
                 clr->forceAVX, clr->forceSSE41, clr->forceSSE3, clr->forceSSE2,
                 clr->forceX87, clr->forceNoIntrinsics,
                 ARCH_STRING);
    }

    return 0;
}
Ejemplo n.º 11
0
/* Use one of the faster functions if available */
static void probabilityFunctionDispatch(const AstronomyParameters* ap, const CLRequest* clr)
{
    int hasSSE2 = FALSE, hasSSE3 = FALSE;
    int useSSE2 = FALSE, useSSE3 = FALSE;

    getSSELevelSupport(&hasSSE2, &hasSSE3);

    if (clr->verbose)
    {
        warn("CPU features: SSE2 = %d, SSE3 = %d\n"
             "Forcing: SSE2 = %d, SSE3 = %d, x87 = %d\n",
             hasSSE2, hasSSE3,
             clr->forceSSE2, clr->forceSSE3, clr->forceX87);
    }

    if (!clr->forceSSE2 && !clr->forceSSE3 && !clr->forceX87)
    {
        /* Default to using highest capability if not forcing anything */
        useSSE3 = hasSSE3;
        useSSE2 = hasSSE2;
    }
    else if (clr->forceSSE2)
    {
        useSSE2 = TRUE;
    }
    else if (clr->forceSSE3)
    {
        useSSE3 = TRUE;
    }
    else if (clr->forceX87)
    {
      #if MW_IS_X86_32
        useSSE2 = useSSE3 = FALSE;
      #elif MW_IS_X86_64
        useSSE2 = TRUE;  /* Ignore flag */
      #endif
    }

    if (useSSE3)  /* Precedence to higher level */
    {
        warn("Using SSE3 path\n");
        probabilityFunc = initProbabilities_SSE3(ap, clr->forceNoIntrinsics);
    }
    else if (useSSE2)
    {
        warn("Using SSE2 path\n");
        probabilityFunc = initProbabilities_SSE2(ap, clr->forceNoIntrinsics);
    }
    else
    {
      #if !MW_NO_X87_EVER
        warn("Using x87 path\n");
        probabilityFunc = initProbabilities(ap, clr->forceNoIntrinsics);
      #else
        mw_unreachable();
      #endif
    }

    if (!probabilityFunc)
    {
        mw_panic("Probability function not set!:\n"
                 "  Has SSE2             = %d\n"
                 "  Has SSE3             = %d\n"
                 "  Forced SSE3          = %d\n"
                 "  Forced SSE2          = %d\n"
                 "  Forced x87           = %d\n"
                 "  Forced no intrinsics = %d\n"
                 "  Arch                 = %s\n",
                 hasSSE2, hasSSE3,
                 clr->forceSSE3, clr->forceSSE2, clr->forceX87, clr->forceNoIntrinsics,
                 ARCH_STRING);
    }
}
Ejemplo n.º 12
0
/* Create the next available segment of the form /milkyway_nbody_n n = 0 .. 127*/
int nbCreateSharedScene(NBodyState* st, const NBodyCtx* ctx)
{
    size_t size = sizeof(scene_t) + st->nbody * sizeof(FloatPos);
    int shmId = -1;
    const int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    void* p = NULL;
    int instanceId = -1;
    char name[128];

    /* Try looking for the next available segment of the form /milkyway_nbody_<n> */
    while (shmId < 0 && instanceId < MAX_INSTANCES)
    {
        ++instanceId;

        if (snprintf(name, sizeof(name), "/milkyway_nbody_%d", instanceId) == sizeof(name))
            mw_panic("Buffer too small for scared memory name\n");

        shmId = shm_open(name, O_CREAT | O_RDWR | O_EXCL, mode); /* Try to open exclusively */
        if (shmId < 0 && errno != EEXIST) /* Only failed if */
        {
            mwPerror("Error creating shared memory '%s'", name);
            return 1;
        }
    }

    if (instanceId >= MAX_INSTANCES)
    {
        mw_printf("Could not open new shm segment in %d tries\n", MAX_INSTANCES);
        return 1;
    }

    if (ftruncate(shmId, size) < 0) /* Make the segment the correct size */
    {
        mwPerror("Error ftruncate() shared memory");
        if (shm_unlink(name) < 0)
        {
            mwPerror("Error unlinking shared memory '%s'", name);
        }

        return 1;
    }

    p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmId, 0);
    if (p == MAP_FAILED)
    {
        mwPerror("mmap: Failed to mmap shared memory");
        if (shm_unlink(name) < 0)
        {
            mwPerror("Error unlinking shared memory '%s'", name);
        }

        return 1;
    }

    st->scene = (scene_t*) p;
    st->shmId = shmId;
    st->scene->instanceId = instanceId;
    strncpy(st->scene->shmemName, name, sizeof(st->scene->shmemName));
    nbPrepareSceneFromState(ctx, st);

    return 0;
}
Ejemplo n.º 13
0
void nbLaunchVisualizer(NBodyState* st, const char* visArgs)
{
    pid_t pid;
    const char* path = NULL;
    char* newPath = NULL;
    int argc = 0;
    char* buf = NULL;
    char* p = NULL;
    char** argv = NULL;
    size_t argvSize = 0;
    size_t visArgsLen = 0;
    char idArg[128];

    if (!st->scene) /* If there's no scene to share, there's no point */
        return;

    if (st->usesExact)
    {
        mw_printf("Visualizer broken with Exact\n");
        return;
    }

    pid = fork();
    if (pid != 0)  /* Parent */
        return;

    /* Child */

    /* Put places convenient for testing. Not essential, failure of
     * any of these is OK */
    path = getenv("PATH");
    if (!path)
    {
        mwPerror("Error getting PATH");
    }
    else
    {
        if (asprintf(&newPath, ".:../bin/:%s", path) < 0)
        {
            mwPerror("Appending to path");
        }
        else
        {
            if (setenv("PATH", newPath, TRUE) < 0)
            {
                mwPerror("Error setting PATH");
            }
            free(newPath);
        }
    }

    if (snprintf(idArg, sizeof(idArg), "--instance-id=%d ", st->scene->instanceId) == sizeof(idArg))
        mw_panic("Buffer too small for --instance-id visualizer argument\n");

    /* Stick the program name at the head of the arguments passed in */
    visArgsLen = visArgs ? strlen(visArgs) : 0;
    argvSize = visArgsLen + sizeof(idArg) + sizeof(nbodyGraphicsName) + 2; /* arguments + program name + space + null */
    buf = mwCalloc(argvSize, sizeof(char));

    p = stpcpy(buf, nbodyGraphicsName);
    p = stpcpy(p, " ");
    p = stpcpy(p, idArg);
    if (visArgs)
    {
        stpcpy(p, visArgs);
    }

    if (poptParseArgvString(buf, &argc, (const char***) &argv))
    {
        mw_printf("Error parsing arguments for visualizer '%s'\n", visArgs);
        free(buf);
        return;
    }

    if (execvp(argv[0], argv) < 0)
    {
        mwPerror("Failed to launch visualizer '%s'", argv[0]);
    }

    free(buf);
    free(argv);
    mw_finish(EXIT_SUCCESS);  /* Unnecessary */
}