blob: dcadf07f72c99b3121e557c4b028bb42c188507e [file] [log] [blame]
//========================================================================
// common-bthread
//========================================================================
// We use a very simple "runtime" to parallelize our apps. We called it
// bthread because it is a set of bare minimum "threading" library
// functions to parallelize a program across multiple cores.
//
// All cores start from the main function. We need to call the
// bthread_init() function at the beginning of main(). Basically only
// core 0 can pass through the bthread_init function and continue
// executing. The rest of cores (if any) will be trapped in the
// bthread_init() function, waiting in a loop we call the worker loop. In
// each iteration of the worker loop, a core will check if the flag is
// set by core 0. If it is, then it will execute the function core 0
// stored in a shared location, then reset its flag. Cores other than
// core 0 will stay in the worker loop indefinitely.
//
// We call core 0 the master core, and we call the other cores the worker
// cores. The master core "spawns work" on a worker core using the
// bthread_spawn function. The master core needs the function pointer,
// the argument pointer, and a worker core's ID. It stores the function
// pointer and the argument pointer to a global location, then sets the
// flag for the given worker core.
//
// The master core can wait for a worker core to finish by using the
// bthread_join function. It waits for a designated worker core until the
// worker core finishes executing its function (if any) then returns.
#ifndef COMMON_BTHREAD_H
#define COMMON_BTHREAD_H
//------------------------------------------------------------------------
// Global data structures
//------------------------------------------------------------------------
typedef void (*spawn_func_ptr)(void*);
extern spawn_func_ptr g_thread_spawn_func_ptrs[4];
extern void* g_thread_spawn_func_args[4];
volatile extern int g_thread_flags[4];
//------------------------------------------------------------------------
// bthread_get_num_cores
//------------------------------------------------------------------------
// Returns the number of cores.
inline
int bthread_get_num_cores()
{
int num_cores;
asm( "csrr %0, 0xFC1;"
: "=r"(num_cores)
:
);
return num_cores;
}
//------------------------------------------------------------------------
// bthread_get_core_id
//------------------------------------------------------------------------
// Returns the core ID.
inline
int bthread_get_core_id()
{
int core_id;
asm( "csrr %0, 0xF14;"
: "=r"(core_id)
:
);
return core_id;
}
//------------------------------------------------------------------------
// bthread_init
//------------------------------------------------------------------------
// This function _MUST_ be called right at the beginning of the main().
// It will only let core 0 pass through. All other cores will be trapped
// in a worker loop, waiting be woken up by the core 0 (bthread_spawn).
void bthread_init();
//------------------------------------------------------------------------
// bthread_spawn
//------------------------------------------------------------------------
// Spawn a function to a given worker core (thread). Need to provide:
//
// thread_id : ID of the thread we are spawning to
// start_routine : Spawned function
// arg : A pointer to the argument.
//
int bthread_spawn( int thread_id, void (*start_routine)(void*), void* arg );
//------------------------------------------------------------------------
// bthread_join
//------------------------------------------------------------------------
// Wait for the given thread to finish executing its work.
int bthread_join( int thread_id );
#endif /* COMMON_BTHREAD_H */