Пример #1
0
void reader_writer_lock::start_read(scoped_lock_read *I) {
    ITT_NOTIFY(sync_prepare, this);
    I->next = reader_head.fetch_and_store(I);
    if (!I->next) { // first arriving reader in my group; set RFLAG, test writer flags
        // unblock and/or update statuses of non-blocking readers
        if (!(fetch_and_or(rdr_count_and_flags, RFLAG) & (WFLAG1+WFLAG2))) { // no writers
            unblock_readers();
        }
    }
    __TBB_ASSERT(I->status == waiting || I->status == active, "Lock requests should be waiting or active before blocking.");
    spin_wait_while_eq(I->status, waiting); // block
    if (I->next) {
        __TBB_ASSERT(I->next->status == waiting, NULL);
        rdr_count_and_flags += RC_INCR;
        I->next->status = active; // wake successor
    }
    ITT_NOTIFY(sync_acquired, this);
}
Пример #2
0
void reader_writer_lock::set_next_writer(scoped_lock *W) {
    writer_head = W;
    if (W->status == waiting_nonblocking) {
        if (rdr_count_and_flags.compare_and_swap(WFLAG1+WFLAG2, 0) == 0) {
            W->status = active;
        }
    }
    else {
        if (fetch_and_or(rdr_count_and_flags, WFLAG1) & RFLAG) { // reader present
            spin_wait_until_and(rdr_count_and_flags, WFLAG2); // block until readers set WFLAG2
        }
        else { // no reader in timing window
            __TBB_AtomicOR(&rdr_count_and_flags, WFLAG2);
        }
        spin_wait_while_geq(rdr_count_and_flags, RC_INCR); // block until readers finish
        W->status = active;
   }
}
Пример #3
0
EA *ea_new(const char *path, uint64_t bsize, int basyncs,
           uint64_t *size, uint64_t *bcount, uint64_t vlun)
{
    int             rc    = 0;
    size_t          plen  = 0;
    uint8_t        *store = NULL;
    EA             *ea    = NULL;
    chunk_id_t      chkid = NULL_CHUNK_ID;
    chunk_ext_arg_t ext   = 0;

    if (!(fetch_and_or(&cflsh_blk_lib_init,1)))
    {
        // We need to call cblk_init once before
        // we use any other cblk_ interfaces
        rc = cblk_init(NULL,0);
        if (rc)
        {
            KV_TRC_FFDC(pAT, "cblk_init failed path %s bsize %"PRIu64" "
                             "size %"PRIu64" bcount %"PRIu64", errno = %d",
                             path, bsize, *size, *bcount, errno);
            goto error_exit;
        }
    }

    ea = am_malloc(sizeof(EA));
    if (NULL == ea)
    {
        KV_TRC_FFDC(pAT, "Out of memory path %s bsize %"PRIu64" size %"PRIu64" "
                         "bcount %"PRIu64", errno = %d",
                         path, bsize, *size, *bcount, errno);
        goto error_exit;
    }

    // We need to check the path parameter to see if
    // we are going to use memory or a file/capi
    // device (to be determined by the block layer)
    if ( (NULL == path) || (strlen(path) == 0) )
    {
        KV_TRC(pAT, "EA_STORE_TYPE_MEMORY");
        // Using memory for store
        ea->st_type = EA_STORE_TYPE_MEMORY;

        store = malloc(*size);
        if (NULL == store)
        {
            errno = ENOMEM;
            KV_TRC_FFDC(pAT, "Out of memory for store path %s bsize %"PRIu64" "
                             "size %"PRIu64" bcount %"PRIu64", errno = %d",
                             path, bsize, *size, *bcount, errno);
            goto error_exit;
        }

        *bcount = ((*size) / bsize);
        ea->st_memory = store;
    }
    else
    {
        KV_TRC(pAT, "EA_STORE_TYPE_FILE(%s)", path);

        // Using a file.  We don't care if it's an actual
        // file or a CAPI device, we let block layer
        // decide and we just use the chunk ID that is
        // passed back from the cblk_open call.
        ea->st_type = EA_STORE_TYPE_FILE;

        // Check to see if we need to create the store on a
        // physical or virtual LUN.  Previously, in GA1,
        // we keyed off the size and if it was 0, then we
        // asked for the LUN to be physical.  Now, the user
        // can specify with a flag.
        if ( vlun == 0 )
        {
            KV_TRC(pAT, "cblk_open PHYSICAL LUN: %s", path);
            chkid = cblk_open(path, basyncs, O_RDWR, ext,
                              CBLK_OPN_NO_INTRP_THREADS);

            if (NULL_CHUNK_ID == chkid)
            {
                printf("cblk_open physical lun failed\n");
                KV_TRC_FFDC(pAT, "cblk_open phys lun failed path:%s bsize:%ld "
                                 "size:%ld bcount:%ld, errno:%d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            rc = cblk_get_size(chkid, (size_t *)bcount, 0);
            if ( (rc != 0) || (*bcount == 0) )
            {
                // An error was encountered, close the chunk
                cblk_close(chkid, 0);
                chkid = NULL_CHUNK_ID;
                KV_TRC_FFDC(pAT, "cblk_get_size failed path %s bsize %"PRIu64" "
                                 "size %"PRIu64" bcount %"PRIu64", errno = %d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            // Set the size to be returned
            *size = *bcount * bsize;
        }
        else
        {
            KV_TRC(pAT, "cblk_open VIRTUAL LUN: %s", path);
            chkid = cblk_open(path, basyncs, O_RDWR, ext,
                              CBLK_OPN_VIRT_LUN|CBLK_OPN_NO_INTRP_THREADS);

            if (NULL_CHUNK_ID == chkid)
            {
                printf("cblk_open virtual lun failed\n");
                KV_TRC_FFDC(pAT, "cblk_open virt lun failed path:%s bsize:%ld "
                                 "size:%ld bcount:%ld, errno:%d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }

            // A specific size was passed in so we try to set the
            // size of the chunk.
            *bcount = *size / bsize;
            rc = cblk_set_size(chkid, (size_t)*bcount, 0);
            if ( rc != 0 )
            {
                printf("cblk_set_size failed for %ld\n", *bcount);
                // An error was encountered, close the chunk
                cblk_close(chkid, 0);
                chkid = NULL_CHUNK_ID;
                KV_TRC_FFDC(pAT, "cblk_set_size failed path %s bsize %"PRIu64" "
                                 "size %"PRIu64" bcount %"PRIu64", errno = %d",
                                 path, bsize, *size, *bcount, errno);
                goto error_exit;
            }
        }

        // Save off the chunk ID and the device name
        ea->st_flash  = chkid;
        plen          = strlen(path) + 1;
        ea->st_device = (char *)am_malloc(plen);
        if (!ea->st_device)
        {
            cblk_close(chkid, 0);
            KV_TRC_FFDC(pAT, "MALLOC st_device failed (%s) plen=%ld errno:%d",
                        path, plen, errno);
            goto error_exit;
        }

        memset(ea->st_device, 0, plen);
        strncpy(ea->st_device, path, plen);
    }

    // Fill in the EA struct
    pthread_rwlock_init(&(ea->ea_rwlock), NULL);
    ea->bsize  = bsize;
    ea->bcount = *bcount;
    ea->size   = *size;

    KV_TRC(pAT, "path %s bsize %"PRIu64" size %"PRIu64" bcount %"PRIu64"",
           path, bsize, *size, *bcount);
    goto done;

error_exit:
    am_free(ea);
    ea = NULL;
    if (!errno) {KV_TRC_FFDC(pAT, "UNSET_ERRNO"); errno=ENOSPC;}

done:
    return ea;
}