Path: blob/main/sys/contrib/zstd/programs/fileio_asyncio.h
289024 views
/*1* Copyright (c) Meta Platforms, Inc. and affiliates.2* All rights reserved.3*4* This source code is licensed under both the BSD-style license (found in the5* LICENSE file in the root directory of this source tree) and the GPLv2 (found6* in the COPYING file in the root directory of this source tree).7* You may select, at your option, one of the above-listed licenses.8*/910/*11* FileIO AsyncIO exposes read/write IO pools that allow doing IO asynchronously.12* Current implementation relies on having one thread that reads and one that13* writes.14* Each IO pool supports up to `MAX_IO_JOBS` that can be enqueued for work, but15* are performed serially by the appropriate worker thread.16* Most systems exposes better primitives to perform asynchronous IO, such as17* io_uring on newer linux systems. The API is built in such a way that in the18* future we could replace the threads with better solutions when available.19*/2021#ifndef ZSTD_FILEIO_ASYNCIO_H22#define ZSTD_FILEIO_ASYNCIO_H2324#include "../lib/common/mem.h" /* U32, U64 */25#include "fileio_types.h"26#include "platform.h"27#include "util.h"28#include "../lib/common/pool.h"29#include "../lib/common/threading.h"3031#define MAX_IO_JOBS (10)3233typedef struct {34/* These struct fields should be set only on creation and not changed afterwards */35POOL_ctx* threadPool;36int threadPoolActive;37int totalIoJobs;38const FIO_prefs_t* prefs;39POOL_function poolFunction;4041/* Controls the file we currently write to, make changes only by using provided utility functions */42FILE* file;4344/* The jobs and availableJobsCount fields are accessed by both the main and worker threads and should45* only be mutated after locking the mutex */46ZSTD_pthread_mutex_t ioJobsMutex;47void* availableJobs[MAX_IO_JOBS];48int availableJobsCount;49size_t jobBufferSize;50} IOPoolCtx_t;5152typedef struct {53IOPoolCtx_t base;5455/* State regarding the currently read file */56int reachedEof;57U64 nextReadOffset;58U64 waitingOnOffset;5960/* We may hold an IOJob object as needed if we actively expose its buffer. */61void *currentJobHeld;6263/* Coalesce buffer is used to join two buffers in case where we need to read more bytes than left in64* the first of them. Shouldn't be accessed from outside ot utility functions. */65U8 *coalesceBuffer;6667/* Read buffer can be used by consumer code, take care when copying this pointer aside as it might68* change when consuming / refilling buffer. */69U8 *srcBuffer;70size_t srcBufferLoaded;7172/* We need to know what tasks completed so we can use their buffers when their time comes.73* Should only be accessed after locking base.ioJobsMutex . */74void* completedJobs[MAX_IO_JOBS];75int completedJobsCount;76ZSTD_pthread_cond_t jobCompletedCond;77} ReadPoolCtx_t;7879typedef struct {80IOPoolCtx_t base;81unsigned storedSkips;82} WritePoolCtx_t;8384typedef struct {85/* These fields are automatically set and shouldn't be changed by non WritePool code. */86void *ctx;87FILE* file;88void *buffer;89size_t bufferSize;9091/* This field should be changed before a job is queued for execution and should contain the number92* of bytes to write from the buffer. */93size_t usedBufferSize;94U64 offset;95} IOJob_t;9697/* AIO_supported:98* Returns 1 if AsyncIO is supported on the system, 0 otherwise. */99int AIO_supported(void);100101102/* AIO_WritePool_releaseIoJob:103* Releases an acquired job back to the pool. Doesn't execute the job. */104void AIO_WritePool_releaseIoJob(IOJob_t *job);105106/* AIO_WritePool_acquireJob:107* Returns an available write job to be used for a future write. */108IOJob_t* AIO_WritePool_acquireJob(WritePoolCtx_t *ctx);109110/* AIO_WritePool_enqueueAndReacquireWriteJob:111* Enqueues a write job for execution and acquires a new one.112* After execution `job`'s pointed value would change to the newly acquired job.113* Make sure to set `usedBufferSize` to the wanted length before call.114* The queued job shouldn't be used directly after queueing it. */115void AIO_WritePool_enqueueAndReacquireWriteJob(IOJob_t **job);116117/* AIO_WritePool_sparseWriteEnd:118* Ends sparse writes to the current file.119* Blocks on completion of all current write jobs before executing. */120void AIO_WritePool_sparseWriteEnd(WritePoolCtx_t *ctx);121122/* AIO_WritePool_setFile:123* Sets the destination file for future writes in the pool.124* Requires completion of all queues write jobs and release of all otherwise acquired jobs.125* Also requires ending of sparse write if a previous file was used in sparse mode. */126void AIO_WritePool_setFile(WritePoolCtx_t *ctx, FILE* file);127128/* AIO_WritePool_getFile:129* Returns the file the writePool is currently set to write to. */130FILE* AIO_WritePool_getFile(const WritePoolCtx_t* ctx);131132/* AIO_WritePool_closeFile:133* Ends sparse write and closes the writePool's current file and sets the file to NULL.134* Requires completion of all queues write jobs and release of all otherwise acquired jobs. */135int AIO_WritePool_closeFile(WritePoolCtx_t *ctx);136137/* AIO_WritePool_create:138* Allocates and sets and a new write pool including its included jobs.139* bufferSize should be set to the maximal buffer we want to write to at a time. */140WritePoolCtx_t* AIO_WritePool_create(const FIO_prefs_t* prefs, size_t bufferSize);141142/* AIO_WritePool_free:143* Frees and releases a writePool and its resources. Closes destination file. */144void AIO_WritePool_free(WritePoolCtx_t* ctx);145146/* AIO_WritePool_setAsync:147* Allows (de)activating async mode, to be used when the expected overhead148* of asyncio costs more than the expected gains. */149void AIO_WritePool_setAsync(WritePoolCtx_t* ctx, int async);150151/* AIO_ReadPool_create:152* Allocates and sets and a new readPool including its included jobs.153* bufferSize should be set to the maximal buffer we want to read at a time, will also be used154* as our basic read size. */155ReadPoolCtx_t* AIO_ReadPool_create(const FIO_prefs_t* prefs, size_t bufferSize);156157/* AIO_ReadPool_free:158* Frees and releases a readPool and its resources. Closes source file. */159void AIO_ReadPool_free(ReadPoolCtx_t* ctx);160161/* AIO_ReadPool_setAsync:162* Allows (de)activating async mode, to be used when the expected overhead163* of asyncio costs more than the expected gains. */164void AIO_ReadPool_setAsync(ReadPoolCtx_t* ctx, int async);165166/* AIO_ReadPool_consumeBytes:167* Consumes byes from srcBuffer's beginning and updates srcBufferLoaded accordingly. */168void AIO_ReadPool_consumeBytes(ReadPoolCtx_t *ctx, size_t n);169170/* AIO_ReadPool_fillBuffer:171* Makes sure buffer has at least n bytes loaded (as long as n is not bigger than the initialized bufferSize).172* Returns if srcBuffer has at least n bytes loaded or if we've reached the end of the file.173* Return value is the number of bytes added to the buffer.174* Note that srcBuffer might have up to 2 times bufferSize bytes. */175size_t AIO_ReadPool_fillBuffer(ReadPoolCtx_t *ctx, size_t n);176177/* AIO_ReadPool_consumeAndRefill:178* Consumes the current buffer and refills it with bufferSize bytes. */179size_t AIO_ReadPool_consumeAndRefill(ReadPoolCtx_t *ctx);180181/* AIO_ReadPool_setFile:182* Sets the source file for future read in the pool. Initiates reading immediately if file is not NULL.183* Waits for all current enqueued tasks to complete if a previous file was set. */184void AIO_ReadPool_setFile(ReadPoolCtx_t *ctx, FILE* file);185186/* AIO_ReadPool_getFile:187* Returns the current file set for the read pool. */188FILE* AIO_ReadPool_getFile(const ReadPoolCtx_t *ctx);189190/* AIO_ReadPool_closeFile:191* Closes the current set file. Waits for all current enqueued tasks to complete and resets state. */192int AIO_ReadPool_closeFile(ReadPoolCtx_t *ctx);193194#endif /* ZSTD_FILEIO_ASYNCIO_H */195196197