int xsem_xwait(xsem_t *sem, int timeout, timestruc_t *mytime) { int status; timestruc_t delay; if (timeout == 0) return (xsem_wait(sem)); else { pthread_mutex_lock(&sem->semMutex); if (sem->semaphore < 0) { sem->semaphore = 0; pthread_mutex_unlock(&sem->semMutex); return (XSEM_ERROR); } if (sem->semaphore > 0) { sem->semaphore--; } else { status = 0; delay = *mytime; delay.tv_sec = delay.tv_sec + time(NULL); while ((sem->semaphore == 0) && (status == 0)) { status = pthread_cond_timedwait(&sem->semCV, &sem->semMutex, &delay); } /* * Check one more time in case thread didn't have a * chance to check before timeout ??? TBD */ if (status != 0) { pthread_mutex_unlock(&sem->semMutex); return (XSEM_ETIME); } else if (sem->semaphore != 0) { sem->semaphore--; } else { pthread_mutex_unlock(&sem->semMutex); return (XSEM_ERROR); } } pthread_mutex_unlock(&sem->semMutex); } return (0); }
static void sem_player(int fd1, int fd2) { fprintf(stdout, "[%u] posting 1 on %d\n", getpid(), fd1); xsem_post(fd1, 1); fprintf(stdout, "[%u] waiting on %d\n", getpid(), fd2); xsem_wait(fd2); fprintf(stdout, "[%u] posting 1 on %d\n", getpid(), fd1); xsem_post(fd1, 1); fprintf(stdout, "[%u] waiting on %d\n", getpid(), fd2); xsem_wait(fd2); fprintf(stdout, "[%u] posting 5 on %d\n", getpid(), fd1); xsem_post(fd1, 5); fprintf(stdout, "[%u] waiting 5 times on %d\n", getpid(), fd2); xsem_wait(fd2); xsem_wait(fd2); xsem_wait(fd2); xsem_wait(fd2); xsem_wait(fd2); }
static void *copy_thread_hashmap(void *_me) { struct worker_thread *me = _me; while (1) { uint8_t buf[block_size]; uint8_t hash[hash_size]; off_t off; int ret; xsem_wait(&me->sem0); for (off = fd_off; off < sizeblocks; off++) { if (memcmp(srchashmap + off * hash_size, dsthashmap + off * hash_size, hash_size)) { break; } } if (off == sizeblocks || check_signal()) { fd_off = sizeblocks; xsem_post(&me->next->sem0); break; } if (should_report_progress()) { char str[256]; int ret; ret = sprintf(str, "%Ld/%Ld (%Ld/%Ld mismatches)", (long long)off, (long long)sizeblocks, (long long)mismatch_idx, (long long)mismatch_cnt); memset(str + ret, '\b', ret); str[2 * ret] = 0; fputs(str, stderr); } ret = xpread(fd_src, buf, block_size, off * block_size); fd_off = off + 1; mismatch_idx++; xsem_post(&me->next->sem0); if (ret < block_size && off != sizeblocks - 1) { fprintf(stderr, "short read\n"); break; } gcry_md_hash_buffer(hash_algo, hash, buf, ret); if (memcmp(hash, srchashmap + off * hash_size, hash_size)) { fprintf(stderr, "warning: source image inconsistent " "with its hashmap at block %Ld\n", (long long)off); } xsem_wait(&me->sem1); xpwrite(fd_dst, buf, ret, off * block_size); memcpy(dsthashmap + off * hash_size, hash, hash_size); xpwrite(fd_dsthashmap, hash, hash_size, off * hash_size); xsem_post(&me->next->sem1); } return NULL; }
static void *copy_thread_no_hashmap(void *_me) { struct worker_thread *me = _me; while (1) { uint8_t buf[block_size]; uint8_t hash[hash_size]; off_t off; int ret; xsem_wait(&me->sem0); off = fd_off; if (off == sizeblocks) { xsem_post(&me->next->sem0); break; } if (check_signal()) { fd_off = sizeblocks; xsem_post(&me->next->sem0); break; } fd_off++; posix_fadvise(fd_src, off * block_size, 4 * block_size, POSIX_FADV_WILLNEED); ret = xpread(fd_src, buf, block_size, off * block_size); xsem_post(&me->next->sem0); if (ret < block_size && off != sizeblocks - 1) { fprintf(stderr, "short read\n"); break; } gcry_md_hash_buffer(hash_algo, hash, buf, ret); xsem_wait(&me->sem1); if (memcmp(dsthashmap + off * hash_size, hash, hash_size)) { xpwrite(fd_dst, buf, ret, off * block_size); xpwrite(fd_dsthashmap, hash, hash_size, off * hash_size); memcpy(dsthashmap + off * hash_size, hash, hash_size); fprintf(stderr, "%Ld ", (long long)off); progress_reported(); again = 1; } else if (should_report_progress()) { char str[256]; ret = sprintf(str, "%Ld/%Ld", (long long)off, (long long)sizeblocks); memset(str + ret, '\b', ret); str[2 * ret] = 0; fputs(str, stderr); } xsem_post(&me->next->sem1); } return NULL; }