Full rewrite with VSR support
This commit is contained in:
+33
-1
@@ -26,6 +26,8 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {} Quakey;
|
||||
|
||||
// Function pointers to a simulated program's code
|
||||
@@ -72,12 +74,19 @@ int quakey_init(Quakey **quakey, QuakeyUInt64 seed);
|
||||
// Stop a simulation
|
||||
void quakey_free(Quakey *quakey);
|
||||
|
||||
typedef unsigned long long QuakeyNode;
|
||||
|
||||
// Add a program to the simulation
|
||||
void quakey_spawn(Quakey *quakey, QuakeySpawn config, char *arg);
|
||||
QuakeyNode quakey_spawn(Quakey *quakey, QuakeySpawn config, char *arg);
|
||||
|
||||
void *quakey_node_state(QuakeyNode node);
|
||||
|
||||
// Schedule and executes one program until it would block, then returns
|
||||
int quakey_schedule_one(Quakey *quakey);
|
||||
|
||||
// Get the current simulated time in nanoseconds
|
||||
QuakeyUInt64 quakey_current_time(Quakey *quakey);
|
||||
|
||||
// Generate a random u64
|
||||
QuakeyUInt64 quakey_random(void);
|
||||
|
||||
@@ -89,6 +98,25 @@ typedef struct {
|
||||
void quakey_signal(char *name);
|
||||
int quakey_get_signal(Quakey *quakey, QuakeySignal *signal);
|
||||
|
||||
// Limit the number of hosts that can be crashed at the same time.
|
||||
// Set to 0 for no limit (default).
|
||||
void quakey_set_max_crashes(Quakey *quakey, int max_crashes);
|
||||
|
||||
void quakey_network_partitioning(Quakey *quakey, bool enable);
|
||||
|
||||
// Access spawned host information
|
||||
int quakey_num_hosts(Quakey *quakey);
|
||||
void *quakey_host_state(Quakey *quakey, int idx); // Returns NULL if host is dead
|
||||
int quakey_host_is_dead(Quakey *quakey, int idx);
|
||||
const char *quakey_host_name(Quakey *quakey, int idx);
|
||||
|
||||
// Enter/leave a host's context so that mock_xxx functions (file I/O,
|
||||
// etc.) operate on that host's resources. Use from code that runs
|
||||
// outside of the normal init/tick/free callbacks (e.g. invariant
|
||||
// checkers).
|
||||
void quakey_enter_host(QuakeyNode node);
|
||||
void quakey_leave_host(void);
|
||||
|
||||
int *mock_errno_ptr(void);
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -125,6 +153,8 @@ int mock_clock_gettime(clockid_t clockid, struct timespec *tp);
|
||||
int mock_open(char *path, int flags, int mode);
|
||||
int mock_fcntl(int fd, int cmd, int flags);
|
||||
int mock_close(int fd);
|
||||
int mock_access(const char *path, int mode);
|
||||
int mock_ftruncate(int fd, size_t new_size);
|
||||
int mock_fstat(int fd, struct stat *buf);
|
||||
int mock_read(int fd, char *dst, int len);
|
||||
int mock_write(int fd, char *src, int len);
|
||||
@@ -172,6 +202,8 @@ void mock_free(void *ptr);
|
||||
#define open mock_open
|
||||
#define fcntl mock_fcntl
|
||||
#define close mock_close
|
||||
#define access mock_access
|
||||
#define ftruncate mock_ftruncate
|
||||
#define CreateFileW mock_CreateFileW
|
||||
#define CloseHandle mock_CloseHandle
|
||||
#define ReadFile mock_ReadFile
|
||||
|
||||
@@ -657,6 +657,63 @@ int mockfs_lseek(MockFS_OpenFile *open_file, int offset, int whence)
|
||||
return new_offset;
|
||||
}
|
||||
|
||||
static void byte_buffer_truncate(ByteBuffer *byte_buffer, int new_size, ByteChunk **free_list)
|
||||
{
|
||||
if (new_size == 0) {
|
||||
byte_buffer_free(byte_buffer, free_list);
|
||||
byte_buffer_init(byte_buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
// Walk through chunks to find the one containing the new end
|
||||
int remaining = new_size;
|
||||
ByteChunk *chunk = byte_buffer->head;
|
||||
while (chunk) {
|
||||
int chunk_used = (chunk->next ? BYTE_CHUNK_SIZE : byte_buffer->tail_used);
|
||||
if (remaining <= chunk_used) {
|
||||
// This chunk becomes the new tail
|
||||
// Free all subsequent chunks
|
||||
ByteChunk *to_free = chunk->next;
|
||||
if (to_free) {
|
||||
// Find end of chain to free
|
||||
ByteChunk *last = to_free;
|
||||
while (last->next)
|
||||
last = last->next;
|
||||
last->next = *free_list;
|
||||
*free_list = to_free;
|
||||
}
|
||||
chunk->next = NULL;
|
||||
byte_buffer->tail = chunk;
|
||||
byte_buffer->tail_used = remaining;
|
||||
return;
|
||||
}
|
||||
remaining -= BYTE_CHUNK_SIZE;
|
||||
chunk = chunk->next;
|
||||
}
|
||||
}
|
||||
|
||||
int mockfs_ftruncate(MockFS_OpenFile *open_file, int new_size)
|
||||
{
|
||||
if (new_size < 0)
|
||||
return MOCKFS_ERRNO_INVAL;
|
||||
|
||||
if (!(open_file->flags & (MOCKFS_O_WRONLY | MOCKFS_O_RDWR)))
|
||||
return MOCKFS_ERRNO_BADF;
|
||||
|
||||
ByteBuffer *bb = &open_file->entity->byte_buffer;
|
||||
int current_size = byte_buffer_size(bb);
|
||||
|
||||
if (new_size < current_size) {
|
||||
byte_buffer_truncate(bb, new_size, &open_file->mfs->chunk_free_list);
|
||||
} else if (new_size > current_size) {
|
||||
int ret = byte_buffer_extend(bb, new_size, open_file->mfs);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int remove_inner(MockFS *mfs, MockFS_Entity *entity, bool recursive)
|
||||
{
|
||||
if (entity->parent == NULL)
|
||||
|
||||
@@ -99,6 +99,7 @@ int mockfs_read_dir(MockFS_OpenDir *open_dir, MockFS_Dirent *dirent);
|
||||
|
||||
int mockfs_sync(MockFS_OpenFile *open_file);
|
||||
int mockfs_lseek(MockFS_OpenFile *open_file, int offset, int whence);
|
||||
int mockfs_ftruncate(MockFS_OpenFile *open_file, int new_size);
|
||||
|
||||
int mockfs_remove(MockFS *mfs, char *path, int path_len, bool recursive);
|
||||
|
||||
|
||||
+766
-43
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user