Example #1
0
struct bn_vlblock *
bn_vlblock_init(struct bu_list *free_vlist_hd, /**< where to get/put free vlists */
		int max_ent /**< maximum number of entities to get/put */)
{
    struct bn_vlblock *vbp;
    size_t i;

    if (!BU_LIST_IS_INITIALIZED(free_vlist_hd))
	BU_LIST_INIT(free_vlist_hd);

    BU_ALLOC(vbp, struct bn_vlblock);
    vbp->magic = BN_VLBLOCK_MAGIC;
    vbp->free_vlist_hd = free_vlist_hd;
    vbp->max = max_ent;
    vbp->head = (struct bu_list *)bu_calloc(vbp->max,
					    sizeof(struct bu_list), "head[]");
    vbp->rgb = (long *)bu_calloc(vbp->max,
				 sizeof(long), "rgb[]");

    for (i=0; i < vbp->max; i++) {
	vbp->rgb[i] = 0;
	BU_LIST_INIT(&(vbp->head[i]));
    }

    vbp->rgb[0] = 0xFFFF00L;	/* Yellow, default */
    vbp->rgb[1] = 0xFFFFFFL;	/* White */
    vbp->nused = 2;

    return vbp;
}
Example #2
0
void
bn_vlist_cleanup(struct bu_list *hd)
{
    register struct bn_vlist *vp;

    if (!BU_LIST_IS_INITIALIZED(hd)) {
	BU_LIST_INIT(hd);
	return;
    }

    while (BU_LIST_WHILE(vp, bn_vlist, hd)) {
	BN_CK_VLIST(vp);
	BU_LIST_DEQUEUE(&(vp->l));
	bu_free((char *)vp, "bn_vlist");
    }
}
Example #3
0
void
rt_alloc_seg_block(register struct resource *res)
{
    register struct seg *sp;
    size_t bytes;

    RT_CK_RESOURCE(res);

    if (!BU_LIST_IS_INITIALIZED(&res->re_seg)) {
	BU_LIST_INIT(&(res->re_seg));
	bu_ptbl_init(&res->re_seg_blocks, 64, "re_seg_blocks ptbl");
    }
    bytes = bu_malloc_len_roundup(64*sizeof(struct seg));
    sp = (struct seg *)bu_malloc(bytes, "rt_alloc_seg_block()");
    bu_ptbl_ins(&res->re_seg_blocks, (long *)sp);
    while (bytes >= sizeof(struct seg)) {
	sp->l.magic = RT_SEG_MAGIC;
	BU_LIST_INSERT(&(res->re_seg), &(sp->l));
	res->re_seglen++;
	sp++;
	bytes -= sizeof(struct seg);
    }
}
Example #4
0
struct bu_mapped_file *
bu_open_mapped_file(const char *name, const char *appl)
/* file name */
/* non-null only when app. will use 'apbuf' */
{
    struct bu_mapped_file *mp = (struct bu_mapped_file *)NULL;
    char *real_path = bu_realpath(name, NULL);
#ifdef HAVE_SYS_STAT_H
    struct stat sb;
    int fd = -1;	/* unix file descriptor */
    int readval;
    ssize_t bytes_to_go, nbytes;
#else
    FILE *fp = (FILE *)NULL;	/* stdio file pointer */
#endif
    int ret;

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	bu_log("bu_open_mapped_file(%s(canonical path - %s), %s)\n", name, real_path, appl?appl:"(NIL)");

    /* See if file has already been mapped, and can be shared */
    bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
    if (!BU_LIST_IS_INITIALIZED(&bu_mapped_file_list)) {
	BU_LIST_INIT(&bu_mapped_file_list);
    }

    for (BU_LIST_FOR(mp, bu_mapped_file, &bu_mapped_file_list)) {
	BU_CK_MAPPED_FILE(mp);

	/* find a match */

	if (!BU_STR_EQUAL(real_path, mp->name))
	    continue;
	if (appl && !BU_STR_EQUAL(appl, mp->appl))
	    continue;

	/* found a match */

	/* if mapped file still exists, verify size and modtime */
	if (!mp->dont_restat) {

	    bu_semaphore_acquire(BU_SEM_SYSCALL);
	    fd = open(real_path, O_RDONLY | O_BINARY);
	    bu_semaphore_release(BU_SEM_SYSCALL);

	    /* If file didn't vanish from disk, make sure it's the same file */
	    if (fd >= 0) {

#ifdef HAVE_SYS_STAT_H
		bu_semaphore_acquire(BU_SEM_SYSCALL);
		ret = fstat(fd, &sb);
		bu_semaphore_release(BU_SEM_SYSCALL);

		if (ret < 0) {
		    /* odd, open worked but fstat failed.  assume it
		     * vanished from disk and the mapped copy is still
		     * OK.
		     */

		    bu_semaphore_acquire(BU_SEM_SYSCALL);
		    (void)close(fd);
		    bu_semaphore_release(BU_SEM_SYSCALL);
		    fd = -1;
		}
		if ((size_t)sb.st_size != mp->buflen) {
		    bu_log("bu_open_mapped_file(%s) WARNING: File size changed from %ld to %ld, opening new version.\n", real_path, mp->buflen, sb.st_size);
		    /* mp doesn't reflect the file any longer.  Invalidate. */
		    mp->appl = bu_strdup("__STALE__");
		    /* Can't invalidate old copy, it may still be in use. */
		    break;
		}
		if (sb.st_mtime != mp->modtime) {
		    bu_log("bu_open_mapped_file(%s) WARNING: File modified since last mapped, opening new version.\n", real_path);
		    /* mp doesn't reflect the file any longer.  Invalidate. */
		    mp->appl = bu_strdup("__STALE__");
		    /* Can't invalidate old copy, it may still be in use. */
		    break;
		}
		/* To be completely safe, should check st_dev and st_inum */
#endif
	    }

	    /* It is safe to reuse mp */
	    mp->uses++;

	    bu_semaphore_release(BU_SEM_MAPPEDFILE);
	    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
		bu_pr_mapped_file("open_reused", mp);

	    return mp;
	}

	/* It is safe to reuse mp */
	mp->uses++;
	return mp;

    }
    /* done iterating over mapped file list */
    bu_semaphore_release(BU_SEM_MAPPEDFILE);

    /* necessary in case we take a 'fail' path before BU_ALLOC() */
    mp = NULL;

    /* File is not yet mapped or has changed, open file read only if
     * we didn't find it earlier.
     */
#ifdef HAVE_SYS_STAT_H
    if (fd < 0) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fd = open(real_path, O_RDONLY | O_BINARY);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    if (UNLIKELY(fd < 0)) {
	if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	    perror(real_path);
	goto fail;
    }

    bu_semaphore_acquire(BU_SEM_SYSCALL);
    ret = fstat(fd, &sb);
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(ret < 0)) {
	perror(real_path);
	goto fail;
    }

    if (UNLIKELY(sb.st_size == 0)) {
	bu_log("bu_open_mapped_file(%s) 0-length file\n", real_path);
	goto fail;
    }
#endif /* HAVE_SYS_STAT_H */

    /* Optimistically assume that things will proceed OK */
    BU_ALLOC(mp, struct bu_mapped_file);
    mp->name = bu_strdup(real_path);
    if (appl) mp->appl = bu_strdup(appl);

#ifdef HAVE_SYS_STAT_H
    mp->buflen = sb.st_size;
    mp->modtime = sb.st_mtime;
#  ifdef HAVE_SYS_MMAN_H

    /* Attempt to access as memory-mapped file */
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    mp->buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(mp->buf == MAP_FAILED))
	perror(real_path);

    if (mp->buf != MAP_FAILED) {
	/* OK, its memory mapped in! */
	mp->is_mapped = 1;
	/* It's safe to close the fd now, the manuals say */
    } else
#  endif /* HAVE_SYS_MMAN_H */
    {
	/* Allocate a local zero'd buffer, and slurp it in always
	 * leaving space for a trailing zero.
	 */
	mp->buf = bu_calloc(1, sb.st_size+1, real_path);

	nbytes = 0;
	bytes_to_go = sb.st_size;
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	while (nbytes < sb.st_size) {
	    readval = read(fd, ((char *)(mp->buf)) + nbytes, ((bytes_to_go > INT_MAX) ? (INT_MAX) : (bytes_to_go)));
	    if (UNLIKELY(readval < 0)) {
		bu_semaphore_release(BU_SEM_SYSCALL);
		perror(real_path);
		bu_free(mp->buf, real_path);
		goto fail;
	    } else {
		nbytes += readval;
		bytes_to_go -= readval;
	    }
	}
	bu_semaphore_release(BU_SEM_SYSCALL);

	if (UNLIKELY(nbytes != sb.st_size)) {
	    perror(real_path);
	    bu_free(mp->buf, real_path);
	    goto fail;
	}
    }

#else /* !HAVE_SYS_STAT_H */

    /* Read it in with stdio, with no clue how big it is */
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    fp = fopen(real_path, "rb");
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(fp == NULL)) {
	perror(real_path);
	goto fail;
    }
    /* Read it once to see how large it is */
    {
	char buf[32768] = {0};
	int got;
	mp->buflen = 0;

	bu_semaphore_acquire(BU_SEM_SYSCALL);
	while ((got = fread(buf, 1, sizeof(buf), fp)) > 0)
	    mp->buflen += got;
	rewind(fp);
	bu_semaphore_release(BU_SEM_SYSCALL);

    }
    /* Allocate the necessary buffer */
    mp->buf = bu_calloc(1, mp->buflen+1, real_path);

    /* Read it again into the buffer */
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    ret = fread(mp->buf, mp->buflen, 1, fp);
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(ret != 1)) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	perror("fread");
	fclose(fp);
	bu_semaphore_release(BU_SEM_SYSCALL);

	bu_log("bu_open_mapped_file() 2nd fread failed? len=%d\n", mp->buflen);
	bu_free(mp->buf, "non-unix fread buf");
	goto fail;
    }

    bu_semaphore_acquire(BU_SEM_SYSCALL);
    fclose(fp);
    bu_semaphore_release(BU_SEM_SYSCALL);
#endif

    if (fd >= 0) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	(void)close(fd);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    mp->uses = 1;
    mp->l.magic = BU_MAPPED_FILE_MAGIC;

    bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
    BU_LIST_APPEND(&bu_mapped_file_list, &mp->l);
    bu_semaphore_release(BU_SEM_MAPPEDFILE);

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE)) {
	bu_pr_mapped_file("1st_open", mp);
    }
    if (real_path) {
	bu_free(real_path, "real_path alloc from bu_realpath");
    }
    return mp;

fail:
    if (fd >= 0) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	(void)close(fd);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    if (mp) {
	bu_free(mp->name, "mp->name");
	if (mp->appl) bu_free(mp->appl, "mp->appl");
	/* Don't free mp->buf here, it might not be bu_malloced but mmaped */
	bu_free(mp, "mp from bu_open_mapped_file fail");
    }

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	bu_log("bu_open_mapped_file(%s, %s) can't open file\n",
		real_path, appl ? appl: "(NIL)");

    if (real_path) {
	bu_free(real_path, "real_path alloc from bu_realpath");
    }

    return (struct bu_mapped_file *)NULL;
}