<commit_before>#include <boost/test/unit_test.hpp>

#include "Thread.hpp"
#include "BasicScheduler.hpp"
#include <glog/logging.h>

BOOST_AUTO_TEST_SUITE( Thread_tests );

void thread_f1( Thread* me, void* args ) {
    BOOST_MESSAGE( "i am Thread f1" );
}

void thread_f2( Thread* me, void* args ) {
    BOOST_MESSAGE( "i am Thread f2" );
}

BOOST_AUTO_TEST_CASE( test_spawn_and_finish ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 

    Thread* t1 = thread_spawn( master, sched, thread_f1, NULL );
    Thread* t2 = thread_spawn( master, sched, thread_f2, NULL );
    sched->ready( t1 );
    sched->ready( t2 );

    BOOST_MESSAGE( "call run" );
    sched->run( );
    BOOST_MESSAGE( "finished" );
}


struct sched_arg {
    Scheduler * sched;
    Thread * t1;
};

void thread_f1_2( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f1 yields" );
    sargs->sched->thread_yield( );
    BOOST_MESSAGE( "f1 runs again" );
}

void thread_f2_2( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f2 yields" );
    sargs->sched->thread_yield( );
    BOOST_MESSAGE( "f2 runs again" );
    
}

BOOST_AUTO_TEST_CASE( test_yield ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    sched_arg arg = { sched, NULL };
    Thread* t1 = thread_spawn( master, sched, thread_f1_2, &arg );
    Thread* t2 = thread_spawn( master, sched, thread_f2_2, &arg );
    sched->ready( t1 );
    sched->ready( t2 );

    BOOST_MESSAGE( "call run" );
    sched->run( );
    BOOST_MESSAGE( "finished" );
}


void thread_f1_3( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f1 suspends" );
    sargs->sched->thread_suspend( ); // depend on this happens first for this test
    BOOST_MESSAGE( "f1 runs again" );
}

void thread_f2_3( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f2 will try wake" );
    sargs->sched->thread_wake( sargs->t1 );
    BOOST_MESSAGE( "f2 tried wake f1" );
    
}

BOOST_AUTO_TEST_CASE( test_suspend ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    sched_arg arg = { sched, NULL };
    Thread* t1 = thread_spawn( master, sched, thread_f1_3, &arg );
    sched_arg arg2 = { sched, t1 };
    Thread* t2 = thread_spawn( master, sched, thread_f2_3, &arg2 );
    sched->ready( t1 );
    sched->ready( t2 );

    BOOST_MESSAGE( "call run" );
    sched->run( );
    BOOST_MESSAGE( "finished" );
}

struct time_args {
    BasicScheduler* sched;
    uint64_t num;
};

void threadf_yielding( Thread * me, void* args ) {
    time_args* targs = (time_args *) args;
    BasicScheduler * sched = targs->sched;
    uint64_t num = targs->num;
    for (int i=0; i<num; i++) {
        sched->thread_yield();
    }
    BOOST_MESSAGE( me->id << " done" );
}

#define rdtscll(val) do { \
    unsigned int __a,__d; \
    asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
    (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
  } while(0)

BOOST_AUTO_TEST_CASE( benchmark_self_yield ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    const uint64_t num_yield = 20000000;
    time_args arg = { sched, num_yield };
    Thread* t1 = thread_spawn( master, sched, threadf_yielding, &arg );
    sched->ready( t1 );
    
    uint64_t start, end;
    BOOST_MESSAGE( "call run" );
    rdtscll(start);
    sched->run( );
    rdtscll(end);
    BOOST_MESSAGE( "finished" );
    
    double runtime_ns = (end - start) / 2.66;
    double ns_per_yield = runtime_ns / num_yield;
    BOOST_MESSAGE( ns_per_yield << " ns per yield (avg)" );
}

BOOST_AUTO_TEST_CASE( benchmark_two_yield ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    const uint64_t num_yield = 20000000;
    const uint64_t num_coro = 2;
    time_args arg = { sched, num_yield };
    for (uint64_t th; th<num_coro; th++) {
        Thread* t1 = thread_spawn( master, sched, threadf_yielding, &arg );
        sched->ready( t1 );
    }
     
    uint64_t start, end;
    BOOST_MESSAGE( "call run" );
    rdtscll(start);
    sched->run( );
    rdtscll(end);
    BOOST_MESSAGE( "finished" );
    
    double runtime_ns = (end - start) / 2.66;
    double ns_per_yield = runtime_ns / (num_yield*num_coro); 
    BOOST_MESSAGE( ns_per_yield << " ns per yield (avg)" );
}

BOOST_AUTO_TEST_SUITE_END();<commit_msg>change to gettime for timing in test<commit_after>#include <boost/test/unit_test.hpp>

#include "Thread.hpp"
#include "BasicScheduler.hpp"
#include <glog/logging.h>

#include <time.h>

BOOST_AUTO_TEST_SUITE( Thread_tests );

void thread_f1( Thread* me, void* args ) {
    BOOST_MESSAGE( "i am Thread f1" );
}

void thread_f2( Thread* me, void* args ) {
    BOOST_MESSAGE( "i am Thread f2" );
}

BOOST_AUTO_TEST_CASE( test_spawn_and_finish ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 

    Thread* t1 = thread_spawn( master, sched, thread_f1, NULL );
    Thread* t2 = thread_spawn( master, sched, thread_f2, NULL );
    sched->ready( t1 );
    sched->ready( t2 );

    BOOST_MESSAGE( "call run" );
    sched->run( );
    BOOST_MESSAGE( "finished" );
}


struct sched_arg {
    Scheduler * sched;
    Thread * t1;
};

void thread_f1_2( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f1 yields" );
    sargs->sched->thread_yield( );
    BOOST_MESSAGE( "f1 runs again" );
}

void thread_f2_2( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f2 yields" );
    sargs->sched->thread_yield( );
    BOOST_MESSAGE( "f2 runs again" );
    
}

BOOST_AUTO_TEST_CASE( test_yield ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    sched_arg arg = { sched, NULL };
    Thread* t1 = thread_spawn( master, sched, thread_f1_2, &arg );
    Thread* t2 = thread_spawn( master, sched, thread_f2_2, &arg );
    sched->ready( t1 );
    sched->ready( t2 );

    BOOST_MESSAGE( "call run" );
    sched->run( );
    BOOST_MESSAGE( "finished" );
}


void thread_f1_3( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f1 suspends" );
    sargs->sched->thread_suspend( ); // depend on this happens first for this test
    BOOST_MESSAGE( "f1 runs again" );
}

void thread_f2_3( Thread* me, void* args ) {
    sched_arg * sargs = (sched_arg *) args;
    
    BOOST_MESSAGE( "f2 will try wake" );
    sargs->sched->thread_wake( sargs->t1 );
    BOOST_MESSAGE( "f2 tried wake f1" );
    
}

BOOST_AUTO_TEST_CASE( test_suspend ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    sched_arg arg = { sched, NULL };
    Thread* t1 = thread_spawn( master, sched, thread_f1_3, &arg );
    sched_arg arg2 = { sched, t1 };
    Thread* t2 = thread_spawn( master, sched, thread_f2_3, &arg2 );
    sched->ready( t1 );
    sched->ready( t2 );

    BOOST_MESSAGE( "call run" );
    sched->run( );
    BOOST_MESSAGE( "finished" );
}

struct time_args {
    BasicScheduler* sched;
    uint64_t num;
};

void threadf_yielding( Thread * me, void* args ) {
    time_args* targs = (time_args *) args;
    BasicScheduler * sched = targs->sched;
    uint64_t num = targs->num;
    for (int i=0; i<num; i++) {
        sched->thread_yield();
    }
    BOOST_MESSAGE( me->id << " done" );
}

double calcInterval( struct timespec start, struct timespec end ) {
    const uint64_t BILLION_ = 1000000000;
    return (end.tv_sec + (((double)end.tv_nsec)/BILLION_)) - (start.tv_sec + (((double)start.tv_nsec)/BILLION_));
}

BOOST_AUTO_TEST_CASE( benchmark_self_yield ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    const uint64_t num_yield = 20000000;
    time_args arg = { sched, num_yield };
    Thread* t1 = thread_spawn( master, sched, threadf_yielding, &arg );
    sched->ready( t1 );
    
    struct timespec start, end;
    BOOST_MESSAGE( "call run" );
    clock_gettime( CLOCK_MONOTONIC, &start );
    sched->run( );
    clock_gettime( CLOCK_MONOTONIC, &end );
    BOOST_MESSAGE( "finished" );
    
    double runtime_s = calcInterval( start, end );
    double ns_per_yield = (runtime_s*1000000000) / num_yield;
    BOOST_MESSAGE( ns_per_yield << " ns per yield (avg)" );
}

BOOST_AUTO_TEST_CASE( benchmark_two_yield ) {
    Thread* master = thread_init();

    BasicScheduler* sched = new BasicScheduler( master ); 
    
    const uint64_t num_yield = 20000000;
    const uint64_t num_coro = 2;
    time_args arg = { sched, num_yield };
    for (uint64_t th; th<num_coro; th++) {
        Thread* t1 = thread_spawn( master, sched, threadf_yielding, &arg );
        sched->ready( t1 );
    }
     
    struct timespec start, end;
    BOOST_MESSAGE( "call run" );
    clock_gettime( CLOCK_MONOTONIC, &start );
    sched->run( );
    clock_gettime( CLOCK_MONOTONIC, &end );
    BOOST_MESSAGE( "finished" );
    
    double runtime_s = calcInterval( start, end );
    double ns_per_yield = (runtime_s*1000000000) / (num_yield*num_coro); 
    BOOST_MESSAGE( ns_per_yield << " ns per yield (avg)" );
}


BOOST_AUTO_TEST_SUITE_END();
{'fraction_non_alphanumeric': 0.13410893707033317, 'fraction_numerical': 0.022104706504494975, 'mean_word_length': 3.1729920564872023, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 7, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5874735', 'n_tokens_mistral': 3581, 'n_tokens_neox': 3384, 'n_words': 818}