blob: 672727fae6f574f0343f428b28a518804712f56e [file] [log] [blame]
/*
* Copyright (c) 2009-2013 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
* IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
* which are subject to change in future releases of Mac OS X. Any applications
* relying on these interfaces WILL break.
*/
#ifndef __DISPATCH_IO_INTERNAL__
#define __DISPATCH_IO_INTERNAL__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
#define _DISPATCH_IO_LABEL_SIZE 16
#if TARGET_OS_EMBEDDED // rdar://problem/9032036
#define DIO_MAX_CHUNK_SIZE (512u * 1024)
#define DIO_HASH_SIZE 64u // must be a power of two
#else
#define DIO_MAX_CHUNK_SIZE (1024u * 1024)
#define DIO_HASH_SIZE 256u // must be a power of two
#endif
#define DIO_HASH(x) ((uintptr_t)(x) & (DIO_HASH_SIZE - 1))
#define DIO_DEFAULT_LOW_WATER_CHUNKS 1u // default low-water mark
#define DIO_MAX_PENDING_IO_REQS 6u // Pending I/O read advises
typedef unsigned int dispatch_op_direction_t;
enum {
DOP_DIR_READ = 0,
DOP_DIR_WRITE,
DOP_DIR_MAX,
DOP_DIR_IGNORE = UINT_MAX,
};
typedef unsigned int dispatch_op_flags_t;
#define DOP_DEFAULT 0u // check conditions to determine delivery
#define DOP_DELIVER 1u // always deliver operation
#define DOP_DONE 2u // operation is done (implies deliver)
#define DOP_STOP 4u // operation interrupted by chan stop (implies done)
#define DOP_NO_EMPTY 8u // don't deliver empty data
// dispatch_io_t atomic_flags
#define DIO_CLOSED 1u // channel has been closed
#define DIO_STOPPED 2u // channel has been stopped (implies closed)
DISPATCH_INTERNAL_CLASS_DECL(operation);
DISPATCH_INTERNAL_CLASS_DECL(disk);
struct dispatch_stream_s {
dispatch_queue_t dq;
dispatch_source_t source;
dispatch_operation_t op;
bool source_running;
TAILQ_HEAD(, dispatch_operation_s) operations[2];
};
typedef struct dispatch_stream_s *dispatch_stream_t;
struct dispatch_io_path_data_s {
dispatch_io_t channel;
int oflag;
mode_t mode;
size_t pathlen;
char path[];
};
typedef struct dispatch_io_path_data_s *dispatch_io_path_data_t;
struct dispatch_stat_s {
dev_t dev;
mode_t mode;
};
struct dispatch_disk_s {
DISPATCH_OBJECT_HEADER(disk);
TAILQ_HEAD(dispatch_disk_operations_s, dispatch_operation_s) operations;
dispatch_operation_t cur_rq;
dispatch_queue_t pick_queue;
size_t free_idx;
size_t req_idx;
size_t advise_idx;
dev_t dev;
bool io_active;
TAILQ_ENTRY(dispatch_disk_s) disk_list;
size_t advise_list_depth;
dispatch_operation_t advise_list[];
};
struct dispatch_fd_entry_s {
dispatch_fd_t fd;
dispatch_io_path_data_t path_data;
int orig_flags, orig_nosigpipe, err;
#if DISPATCH_USE_GUARDED_FD_CHANGE_FDGUARD
int orig_fd_flags;
#endif
#if DISPATCH_USE_GUARDED_FD
unsigned int guard_flags;
#endif
struct dispatch_stat_s stat;
dispatch_stream_t streams[2];
dispatch_disk_t disk;
dispatch_queue_t close_queue, barrier_queue;
dispatch_group_t barrier_group;
dispatch_io_t convenience_channel;
TAILQ_HEAD(, dispatch_operation_s) stream_ops;
TAILQ_ENTRY(dispatch_fd_entry_s) fd_list;
};
typedef struct dispatch_fd_entry_s *dispatch_fd_entry_t;
typedef struct dispatch_io_param_s {
dispatch_io_type_t type; // STREAM OR RANDOM
size_t low;
size_t high;
uint64_t interval;
unsigned long interval_flags;
} dispatch_io_param_s;
struct dispatch_operation_s {
DISPATCH_OBJECT_HEADER(operation);
dispatch_queue_t op_q;
dispatch_op_direction_t direction; // READ OR WRITE
dispatch_io_param_s params;
off_t offset;
size_t length;
int err;
dispatch_io_handler_t handler;
dispatch_io_t channel;
dispatch_fd_entry_t fd_entry;
dispatch_source_t timer;
bool active;
off_t advise_offset;
void* buf;
dispatch_op_flags_t flags;
size_t buf_siz, buf_len, undelivered, total;
dispatch_data_t buf_data, data;
TAILQ_ENTRY(dispatch_operation_s) operation_list;
// the request list in the fd_entry stream_ops
TAILQ_ENTRY(dispatch_operation_s) stream_list;
};
DISPATCH_CLASS_DECL(io);
struct dispatch_io_s {
DISPATCH_OBJECT_HEADER(io);
dispatch_queue_t queue, barrier_queue;
dispatch_group_t barrier_group;
dispatch_io_param_s params;
dispatch_fd_entry_t fd_entry;
unsigned int atomic_flags;
dispatch_fd_t fd, fd_actual;
off_t f_ptr;
int err; // contains creation errors only
};
void _dispatch_io_set_target_queue(dispatch_io_t channel, dispatch_queue_t dq);
size_t _dispatch_io_debug(dispatch_io_t channel, char* buf, size_t bufsiz);
void _dispatch_io_dispose(dispatch_io_t channel, bool *allow_free);
size_t _dispatch_operation_debug(dispatch_operation_t op, char* buf,
size_t bufsiz);
void _dispatch_operation_dispose(dispatch_operation_t operation,
bool *allow_free);
void _dispatch_disk_dispose(dispatch_disk_t disk, bool *allow_free);
#endif // __DISPATCH_IO_INTERNAL__