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; }
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"); } }
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); } }
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; }