This project demonstrates the implementation of fiber switching in C++ using a provided context library. Fibers are lightweight threads with their own stack, and this example shows how to switch between different fibers.
- TASK1 : Fiber Switching in C++ with Context Library
- TASK2: Fiber Class
- Simple Fiber Scheduler Example
- TASK 3 Fiber and Scheduler System
In this project, we implement a simple program that utilizes the provided context library to switch between different fibers. The context library consists of functions to save and restore the execution state, allowing for the creation of lightweight fibers.
-
Assemble Assembly Code: This command assembles the context.s assembly file into machine code and saves the result in context.o.
-
Compile C++ Source Code to Object File: This command compiles the fibers.cpp source file into machine code and saves the result in fibers.o.
-
Link Object Files to Create Executable: This command links the previously compiled fibers.o and context.o object files into an executable named fibers.
as -o context.o context.s
g++ -c fibers.cpp -o fibers.o
g++ fibers.o context.o -o fibers
Run the compiled executable:
./fibers
-
Header Inclusions:
#include <iostream>
: Allows the program to perform input and output operations.#include <cstdint>
: Provides fixed-width integer types (uint32_t
,uintptr_t
, etc.).#include "context.hpp"
: Includes the header file for the provided context-switching library.
-
Global Variables:
volatile bool x = false;
: A volatile boolean variable used to control the flow of execution. Its volatility ensures that the compiler does not optimize its usage.
-
Global Contexts:
Context main_context;
andContext goo_context;
: Two instances of theContext
structure provided by the context library. These represent the execution contexts for the main function and thegoo
function.
-
Function Declarations:
void goo();
: Forward declaration for thegoo
function.
-
Function Definitions:
void foo()
: Outputs a message and then switches control to thegoo
function using the context-switching library.void goo()
: Outputs a message.
-
Main Function:
- Allocates memory for the main stack, including additional space for the Red Zone, following the System V ABI.
- Aligns the main stack to 16 bytes and adjusts the stack pointer for the Red Zone.
- Retrieves the current context as the main context, sets up the
foo
function as the entry point, and sets the stack pointer. - Calls the context-switching library function
set_context
to switch control to thefoo
function. - After
foo
completes, control returns to the main function, and the program checks the condition of the volatile variablex
. If true, it outputs a message. - Deallocates the main stack memory.
#include <cstdint>
struct Context {
void* rip, *rsp;
void* rbx, *rbp, *r12, *r13, *r14, *r15;
};
extern "C" int get_context(Context* c);
extern "C" void set_context(Context* c);
extern "C" void swap_context(Context* out, Context* in);
Task 1
The Fiber
class is a simple C++ implementation that provides a basic framework for creating and managing fibers. Fibers are lightweight threads of execution that can be cooperatively scheduled.
- Fiber Creation: Create fibers with a specified function to execute.
- Context Switching: Swap the execution context between different fibers.
- Stack Management: Allocate and deallocate stack space for each fiber.
To use the Fiber
class, follow these steps:
- Include the "Fiber.hpp" header file in your project.
- Create a
Fiber
object with the desired function. - Use the provided functions to get, set, and swap the context of fibers.
- Start the execution of fibers to switch between them.
#include "Fiber.hpp"
#include <iostream>
int main() {
// Example usage of the Fiber class
Fiber fooFiber(&fooFunction);
Fiber barFiber(&barFunction);
const Context &fooContext = fooFiber.get_context();
fooFiber.set_context(barFiber.get_context());
// Start the execution of fibers to switch between them
fooFiber.start_execution(barFiber);
return 0;
}
The Fiber class is implemented with the following key functions:
- Fiber::Fiber(): Default constructor for initializing the fiber.
- Fiber::Fiber(void (*function)()): Constructor for creating a fiber with a specified function.
- Fiber::~Fiber(): Destructor for cleaning up resources, such as deallocating the stack.
- Fiber::get_context(): Retrieve the context of the fiber.
- Fiber::set_context(const Context &newContext): Set the context of the fiber.
- Fiber::swap_context(Fiber &other): Swap the context between two fibers.
- Fiber::start_execution(Fiber &other): Start the execution of the specified
The Scheduler class is a basic fiber scheduler implementation in C++. It allows the management and execution of multiple fibers in a cooperative multitasking fashion.
-
fibers_: A deque (double-ended queue) that holds pointers to Fiber instances. Fibers are added to this deque for scheduling.
-
context_: An instance of the Context structure representing the saved context when switching between fibers.
-
sharedData: A pointer to an integer used as shared data. Fibers can access and modify this shared data.
-
Scheduler(): Default constructor for the scheduler.
-
~Scheduler(): Destructor responsible for cleaning up allocated memory for fibers.
-
spawn(Fiber *f): Adds a new fiber (Fiber instance) to the scheduler for future execution.
-
do_it(): Initiates the scheduler's execution loop. It sequentially runs fibers in a round-robin fashion until no fibers are left in the deque.
-
fiber_exit(): Signals the end of the current fiber's execution, allowing the scheduler to resume control.
-
get_shared_data() const: Retrieves a pointer to the shared data, which can be accessed by fibers.
This is a basic example demonstrating the usage of a simple fiber scheduler in C++.
The program creates a scheduler (Scheduler
class) that manages multiple fibers (Fiber
class). Each fiber is associated with a specific function (func1
, func2
, func3
) to be executed.
Ensure you have a C++ compiler installed on your system. You can compile and run the program using the following commands:
g++ -std=c++11 main.cpp context.cpp Fiber.cpp Scheduler.cpp -o scheduler_example
./scheduler_example
This code implements a simple fiber and scheduler system in C++. Fibers are lightweight threads of execution that can be scheduled by a central scheduler. The scheduler controls the execution of fibers, allowing them to yield and resume their execution.
Fiber()
: Default constructor, initializes the fiber with null values.Fiber(std::function<void()> function)
: Constructor that takes a function to execute as an argument.
const Context &get_context() const
: Get the current context of the fiber.void set_context(const Context &newContext)
: Set the context of the fiber.void swap_context(Fiber &other)
: Swap the context between two fibers.void start_execution(Fiber &other)
: Start the execution of a fiber.Context &get_context()
: Get a non-const reference to the fiber's context.int *get_data_pointer() const
: Get the shared data pointer.void yield()
: Yield control to the scheduler.
~Fiber()
: Destructor, responsible for deallocating the fiber's stack.
Scheduler()
: Default constructor.
void spawn(Fiber *f)
: Add a fiber to the scheduler's queue.void do_it()
: Execute fibers in the scheduler's queue.void fiber_exit()
: Exit the current fiber.int *get_shared_data() const
: Get the shared data pointer.
~Scheduler()
: Destructor, responsible for cleaning up allocated resources.
#include "Fiber.hpp"
#include "Scheduler.hpp"
void func1()
{
std::cout << "fiber 1" << std::endl;
}
void func2()
{
std::cout << "fiber 2" << std::endl;
}
int main()
{
Scheduler s;
// Creating fibers
Fiber f1(func1);
Fiber f2(func2);
// Spawning fibers
s.spawn(&f1);
s.spawn(&f2);
// Running the scheduler
s.do_it();
return 0;
}