Commit 312c220c authored by Martin Karsten's avatar Martin Karsten

- add limited 'fork'-type API call

parent 9a4e9482
Pipeline #40736 failed with stage
in 3 minutes and 40 seconds
......@@ -27,9 +27,11 @@ In addition, the following students (in alphabetical order) have helped with var
- Qin An (FreeBSD/kqueue)
- Bilal Akhtar (gdb extension)
- Peng Chen (split stack support)
- Peng Chen (split stack)
- Peiran Hong (API/Apache)
- Wen Shi (gdb extension)
- Shuangyi Tong (multiple event scopes)
- Shuangyi Tong (event scopes)
- Gan Wang (API/Apache)
All bugs are mine though. ;-)
......
#include "fibre.h"
#include <iostream>
#include <sys/wait.h> // waitpid
using namespace std;
......@@ -48,7 +49,12 @@ static void f3main() {
int main(int argc, char** argv) {
FibreInit();
cout << "Hello world" << endl;
pid_t p = SYSCALL(FibreFork());
cout << "Hello world " << getpid() << endl;
if (p) {
SYSCALL(waitpid(p, nullptr, 0));
cout << "Child " << p << " finished" << endl;
}
Time ct;
SYSCALL(clock_gettime(CLOCK_REALTIME, &ct));
cout << ct.tv_sec << '.' << ct.tv_nsec << endl;
......
......@@ -91,6 +91,13 @@ EventScope* FibreInit(size_t pollerCount, size_t workerCount) {
return EventScope::bootstrap(pollerCount, workerCount);
}
pid_t FibreFork() {
Context::CurrEventScope().preFork();
pid_t ret = fork();
if (ret == 0) Context::CurrEventScope().postFork(); // child: clean up runtime system
return ret;
}
// ******************** GLOBAL HELPERS ********************
int _SysErrno() {
......
......@@ -93,6 +93,25 @@ public:
delete [] pollVec;
}
void preFork() {
ScopedLock<WorkerLock> sl(ringLock);
RASSERT(ringCount == 1, ringCount);
}
void postFork() {
new (stats) ClusterStats(this);
for (size_t p = 0; p < pollCount; p += 1) {
pollVec[p].~PollerType();
new (&pollVec[p]) PollerType(scope, stagingProc);
}
#if TESTING_PROCESSOR_POLLER
PollerFibre* procPoller = &Context::CurrPoller();
procPoller->~PollerFibre();
new (procPoller) PollerFibre(Context::CurrEventScope(), Context::CurrProcessor(), false);
procPoller->start();
#endif
}
// Register curent system thread (pthread) as worker.
Fibre* registerWorker(_friend<EventScope>);
......
......@@ -73,6 +73,7 @@ class EventScope {
~EventScope() {
delete mainFibre;
delete mainCluster;
masterPoller->terminate(_friend<EventScope>());
delete masterPoller;
delete[] fdSyncVector;
}
......@@ -125,6 +126,28 @@ public:
return es;
}
void preFork() {
// TODO: assert globalClusterCount == 1
// TODO: test for other fibres?
RASSERT0(CurrFibre() == mainFibre);
RASSERT0(timerQueue.empty());
RASSERT0(diskCluster == nullptr);
mainCluster->preFork();
}
void postFork() {
new (stats) ConnectionStats(this);
timerQueue.reinit();
delete masterPoller;
masterPoller = new MasterPoller(*this, fdCount, _friend<EventScope>()); // start master poller & timer handling
mainCluster->postFork();
for (int f = 0; f < fdCount; f += 1) {
RASSERT(fdSyncVector[f].RD.sem.empty(), f);
RASSERT(fdSyncVector[f].WR.sem.empty(), f);
}
mainCluster->startPolling(_friend<EventScope>()); // start polling now
}
/** Wait for the main routine of a cloned event scope. */
void join() { mainFibre->join(); }
......
......@@ -47,6 +47,10 @@ extern "C" void cfibre_init_n(size_t pollerCount, size_t workerCount) {
FibreInit(pollerCount, workerCount);
}
extern "C" pid_t cfibre_fork() {
return FibreFork();
}
extern "C" int cfibre_cluster_create(cfibre_cluster_t* cluster) {
*cluster = new _cfibre_cluster_t;
return 0;
......
......@@ -32,6 +32,10 @@
#include <sys/uio.h> // readv, writev
#include <pthread.h> // pthread_t
#ifndef __LIBFIBRE__
#define __LIBFIBRE__ 1
#endif
typedef struct _cfibre_t* cfibre_t;
typedef struct _cfibre_sem_t* cfibre_sem_t;
typedef struct _cfibre_mutex_t* cfibre_mutex_t;
......@@ -63,6 +67,9 @@ void cfibre_init();
/** @brief Alternative bootstrap routine. */
void cfibre_init_n(size_t pollerCount, size_t workerCount);
/** @brief Fork process (with restrictions) and re-initialize runtime in child process (`fork`). */
pid_t cfibre_fork();
/** @brief Create Cluster */
int cfibre_cluster_create(cfibre_cluster_t* cluster);
/** @brief Destroy Cluster */
......
......@@ -94,6 +94,9 @@ struct fibre_fastmutexattr_t {
/** @brief Bootstrap routine should be called early in main(). */
extern EventScope* FibreInit(size_t pollerCount = 1, size_t workerCount = 1);
/** @brief Fork process (with restrictions) and re-initialize runtime in child process (`fork`). */
extern pid_t FibreFork();
/** @brief Initialize attributes for fibre creation (`pthread_attr_init`). */
inline int fibre_attr_init(fibre_attr_t *attr) {
attr->init();
......
......@@ -43,6 +43,9 @@ public:
TimerQueue() { stats = new TimerStats(this); }
bool empty() const { return queue.empty(); }
void reinit() { new (stats) TimerStats(this); }
Handle insert(BaseTimer& bt, const Time& relTimeout, const Time& absTimeout) {
ScopedLock<WorkerLock> al(lock);
Handle ret = queue.insert( {absTimeout, &bt} ); // set up timeout
......
......@@ -64,16 +64,16 @@ function run_0() {
}
function prep_1() {
sed -i -e 's/.*TESTING_PROCESSOR_POLLER.*/#define TESTING_PROCESSOR_POLLER 1/' src/runtime-glue/testoptions.h
echo memcached
sed -i -e 's/DYNSTACK=.*/DYNSTACK=1/' Makefile.config
}
function run_1() {
run_memcached 1
echo -n "STACKTEST: "
apps/stacktest > stacktest.out && echo SUCCESS || echo FAILURE
}
function prep_2() {
sed -i -e 's/.*TESTING_LAZY_FD_REGISTRATION.*/#undef TESTING_LAZY_FD_REGISTRATION/' src/runtime-glue/testoptions.h
sed -i -e 's/.*TESTING_PROCESSOR_POLLER.*/#define TESTING_PROCESSOR_POLLER 1/' src/runtime-glue/testoptions.h
echo memcached
}
......@@ -82,8 +82,7 @@ function run_2() {
}
function prep_3() {
sed -i -e 's/.*TESTING_LAZY_FD_REGISTRATION.*/#undef TESTING_LAZY_FD_REGISTRATION/' src/runtime-glue/testoptions.h
sed -i -e 's/.*TESTING_PROCESSOR_POLLER.*/#define TESTING_PROCESSOR_POLLER 1/' src/runtime-glue/testoptions.h
sed -i -e 's/.*TESTING_CLUSTER_POLLER_FIBRE.*/#undef TESTING_CLUSTER_POLLER_FIBRE/' src/runtime-glue/testoptions.h
echo memcached
}
......@@ -92,16 +91,26 @@ function run_3() {
}
function prep_4() {
sed -i -e 's/DYNSTACK=.*/DYNSTACK=1/' Makefile.config
sed -i -e 's/.*TESTING_LAZY_FD_REGISTRATION.*/#undef TESTING_LAZY_FD_REGISTRATION/' src/runtime-glue/testoptions.h
echo memcached
}
function run_4() {
echo -n "STACKTEST: "
apps/stacktest > stacktest.out && echo SUCCESS || echo FAILURE
rm -f stacktest.out
run_memcached 4
}
function prep_5() {
sed -i -e 's/.*TESTING_PROCESSOR_POLLER.*/#define TESTING_PROCESSOR_POLLER 1/' src/runtime-glue/testoptions.h
sed -i -e 's/.*TESTING_CLUSTER_POLLER_FIBRE.*/#undef TESTING_CLUSTER_POLLER_FIBRE/' src/runtime-glue/testoptions.h
sed -i -e 's/.*TESTING_LAZY_FD_REGISTRATION.*/#undef TESTING_LAZY_FD_REGISTRATION/' src/runtime-glue/testoptions.h
echo memcached
}
function run_5() {
run_memcached 5
}
for ((e=0;e<=4;e+=1)); do
for ((e=0;e<=5;e+=1)); do
addon=$(prep_$e)
pre $addon
run_$e
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment