Branch Coverage

pool.h
Criterion Covered Total %
branch 137 272 50.3


line true false branch
107 0 22 if (pid == 0) return 1;
108 21 1 return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH);
0 21 return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH);
115 0 2 if (deadline->tv_nsec >= 1000000000L) {
127 2 1 if (remaining->tv_nsec < 0) {
159 940 16 for (uint32_t i = 0; i < nwords; i++) {
163 929 11 while (word != ~(uint64_t)0) {
166 17 912 if (slot >= cap) break;
169 912 0 if (__atomic_compare_exchange_n(&h->bitmap[widx], &word, new_word,
176 10 1 h->scan_hint = (new_word == ~(uint64_t)0 && nwords > 1)
177 11 901 ? (widx + 1) % nwords : widx;
189 904 3 if (slot >= 0) return slot;
190 1 2 if (timeout == 0) return -1;
195 2 0 if (has_deadline) pool_make_deadline(timeout, &deadline);
201 0 2 if (cur_used < (uint32_t)hdr->capacity) {
203 0 0 if (slot >= 0) return slot;
209 2 0 if (cur_used >= (uint32_t)hdr->capacity) {
211 2 0 if (has_deadline) {
212 0 2 if (!pool_remaining_time(&deadline, &remaining)) {
225 1 1 if (slot >= 0) return slot;
227 1 0 if (has_deadline) {
228 1 0 if (!pool_remaining_time(&deadline, &remaining)) {
242 0 691 if (slot >= hdr->capacity) return 0;
250 2 689 if (!(word & mask)) return 0;
253 689 0 if (__atomic_compare_exchange_n(&h->bitmap[widx], &word, new_word,
258 0 689 if (__atomic_load_n(&hdr->waiters, __ATOMIC_RELAXED) > 0)
273 4 2 for (uint32_t i = 0; i < count; i++) {
275 0 4 if (slot >= hdr->capacity) continue;
283 0 4 if (!(word & mask)) break;
285 4 0 if (__atomic_compare_exchange_n(&h->bitmap[widx], &word, new_word,
294 2 0 if (freed > 0) {
297 0 2 if (__atomic_load_n(&hdr->waiters, __ATOMIC_RELAXED) > 0) {
298 0 0 int wake = freed < (uint32_t)INT_MAX ? (int)freed : INT_MAX;
311 0 2 if (count == 0) return 1;
313 1 1 if (timeout == 0) {
314 2 0 for (uint32_t i = 0; i < count; i++) {
316 1 1 if (slot < 0) {
317 1 0 if (i > 0) pool_free_n(h, out, i);
327 0 1 if (has_deadline) pool_make_deadline(timeout, &deadline);
329 3 1 for (uint32_t i = 0; i < count; i++) {
331 0 3 if (has_deadline) {
332 0 0 if (!pool_remaining_time(&deadline, &remaining)) {
334 0 0 if (i > 0) pool_free_n(h, out, i);
340 0 3 if (slot < 0) {
341 0 0 if (i > 0) pool_free_n(h, out, i);
357 200 2 for (uint64_t slot = 0; slot < cap; slot++) {
358 178 22 if (!pool_is_allocated(h, slot)) continue;
360 22 0 if (owner == 0 || pool_pid_alive(owner)) continue;
1 21 if (owner == 0 || pool_pid_alive(owner)) continue;
364 0 21 if (!__atomic_compare_exchange_n(&h->owners[slot], &owner, 0,
375 0 21 if (!(word & mask)) break;
377 21 0 if (__atomic_compare_exchange_n(&h->bitmap[widx], &word, new_word,
381 0 21 if (__atomic_load_n(&h->hdr->waiters, __ATOMIC_RELAXED) > 0)
389 2 0 if (recovered > 0)
450 0 47 if (!h) { munmap(base, map_size); return NULL; }
458 11 36 h->path = path ? strdup(path) : NULL;
469 36 0 if (errbuf) errbuf[0] = '\0';
471 0 36 if (capacity == 0) { POOL_ERR("capacity must be > 0"); return NULL; }
0 0 if (capacity == 0) { POOL_ERR("capacity must be > 0"); return NULL; }
472 0 36 if (elem_size == 0) { POOL_ERR("elem_size must be > 0"); return NULL; }
0 0 if (elem_size == 0) { POOL_ERR("elem_size must be > 0"); return NULL; }
473 0 36 if (capacity > POOL_MAX_CAPACITY) { POOL_ERR("capacity too large"); return NULL; }
0 0 if (capacity > POOL_MAX_CAPACITY) { POOL_ERR("capacity too large"); return NULL; }
474 0 36 if (capacity > (UINT64_MAX - sizeof(PoolHeader)) / elem_size) {
475 0 0 POOL_ERR("capacity * elem_size overflow"); return NULL;
487 25 11 if (anonymous) {
491 0 25 if (base == MAP_FAILED) {
492 0 0 POOL_ERR("mmap(anonymous): %s", strerror(errno));
497 0 11 if (fd < 0) { POOL_ERR("open(%s): %s", path, strerror(errno)); return NULL; }
0 0 if (fd < 0) { POOL_ERR("open(%s): %s", path, strerror(errno)); return NULL; }
499 0 11 if (flock(fd, LOCK_EX) < 0) {
500 0 0 POOL_ERR("flock(%s): %s", path, strerror(errno));
505 0 11 if (fstat(fd, &st) < 0) {
506 0 0 POOL_ERR("fstat(%s): %s", path, strerror(errno));
512 2 9 if (!is_new && (uint64_t)st.st_size < sizeof(PoolHeader)) {
0 2 if (!is_new && (uint64_t)st.st_size < sizeof(PoolHeader)) {
513 0 0 POOL_ERR("%s: file too small (%lld)", path, (long long)st.st_size);
517 9 2 if (is_new) {
518 0 9 if (ftruncate(fd, (off_t)total) < 0) {
519 0 0 POOL_ERR("ftruncate(%s): %s", path, strerror(errno));
524 2 9 map_size = is_new ? (size_t)total : (size_t)st.st_size;
526 0 11 if (base == MAP_FAILED) {
527 0 0 POOL_ERR("mmap(%s): %s", path, strerror(errno));
531 2 9 if (!is_new) {
534 2 0 hdr->version == POOL_VERSION &&
535 2 0 hdr->variant_id == variant_id &&
536 2 0 hdr->capacity > 0 &&
2 0 hdr->capacity > 0 &&
537 2 0 hdr->total_size == (uint64_t)st.st_size);
538 0 2 if (!valid) {
539 0 0 POOL_ERR("%s: invalid or incompatible pool file", path);
552 9 25 if (fd >= 0) {
563 6 0 if (errbuf) errbuf[0] = '\0';
565 0 6 if (capacity == 0) { POOL_ERR("capacity must be > 0"); return NULL; }
0 0 if (capacity == 0) { POOL_ERR("capacity must be > 0"); return NULL; }
566 0 6 if (elem_size == 0) { POOL_ERR("elem_size must be > 0"); return NULL; }
0 0 if (elem_size == 0) { POOL_ERR("elem_size must be > 0"); return NULL; }
567 0 6 if (capacity > POOL_MAX_CAPACITY) { POOL_ERR("capacity too large"); return NULL; }
0 0 if (capacity > POOL_MAX_CAPACITY) { POOL_ERR("capacity too large"); return NULL; }
568 0 6 if (capacity > (UINT64_MAX - sizeof(PoolHeader)) / elem_size) {
569 0 0 POOL_ERR("capacity * elem_size overflow"); return NULL;
576 6 0 int fd = memfd_create(name ? name : "pool", MFD_CLOEXEC);
577 0 6 if (fd < 0) { POOL_ERR("memfd_create: %s", strerror(errno)); return NULL; }
0 0 if (fd < 0) { POOL_ERR("memfd_create: %s", strerror(errno)); return NULL; }
579 0 6 if (ftruncate(fd, (off_t)total) < 0) {
580 0 0 POOL_ERR("ftruncate(memfd): %s", strerror(errno));
585 0 6 if (base == MAP_FAILED) {
586 0 0 POOL_ERR("mmap(memfd): %s", strerror(errno));
597 5 0 if (errbuf) errbuf[0] = '\0';
600 0 5 if (fstat(fd, &st) < 0) {
601 0 0 POOL_ERR("fstat(fd=%d): %s", fd, strerror(errno));
605 0 5 if ((uint64_t)st.st_size < sizeof(PoolHeader)) {
606 0 0 POOL_ERR("fd %d: too small (%lld)", fd, (long long)st.st_size);
612 0 5 if (base == MAP_FAILED) {
613 0 0 POOL_ERR("mmap(fd=%d): %s", fd, strerror(errno));
619 5 0 hdr->version == POOL_VERSION &&
620 5 0 hdr->variant_id == variant_id &&
621 5 0 hdr->capacity > 0 &&
5 0 hdr->capacity > 0 &&
622 5 0 hdr->total_size == (uint64_t)st.st_size);
623 0 5 if (!valid) {
624 0 0 POOL_ERR("fd %d: invalid or incompatible pool", fd);
630 0 5 if (myfd < 0) {
631 0 0 POOL_ERR("fcntl(F_DUPFD_CLOEXEC): %s", strerror(errno));
640 0 47 if (!h) return;
641 1 46 if (h->notify_fd >= 0) close(h->notify_fd);
642 11 36 if (h->backing_fd >= 0) close(h->backing_fd);
643 47 0 if (h->hdr) munmap(h->hdr, h->mmap_size);
653 1 1 if (h->notify_fd >= 0) close(h->notify_fd);
655 0 2 if (efd < 0) return -1;
661 0 3 if (h->notify_fd < 0) return 0;
667 0 3 if (h->notify_fd < 0) return -1;
669 1 2 if (read(h->notify_fd, &val, sizeof(val)) != sizeof(val)) return -1;
761 0 11 if (len > max_len) len = max_len;
772 2 6 if (len > max_len) len = max_len;
787 0 10 if (__atomic_load_n(&hdr->waiters, __ATOMIC_RELAXED) > 0)