Thursday, November 8, 2012

Futex in Linux

Test Class for Shm

class Test
{
        public:
        int i_val[3];
        int64_t time;
        int seq;
};
 

Following is futex WAIT example using shm

include <linux/futex.h>
#include <sys/time.h>
#include <iostream>
#include <unistd.h>
#include <sys/syscall.h>

#include <Timer.h>
#include "ShmManager.h"
#include "Test.h"

//static long sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3)
//{
//      return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
//}

using namespace std;
using namespace NS_COOL;


int main(int argc, char** argv)
{
        google::InitGoogleLogging(argv[0]);

        Timer timer;
        Test * test;
        ShmManager shm_man;
        shm_man.Add("FUTEX_SHM",4096 ,false);
        shm_man.AddType("FUTEX_SHM","FUTEX_SHM_TYPE", &test);
        cout<<"Shm created"<<endl;


        int index = atoi(argv[1]);
        cout<<"test "<<test->i_val[index]<<endl;
        test->i_val[index] = 1;
        cout<<"test "<<test->i_val[index]<<endl;

        int count = 0;
        int64_t tot = 0;
        //int64_t next_seq = 1;

        int min = 1000;
        int max = 0;
        int diff = 0;

while(true)
{
//       cout<<"Waiting.."<<endl;
        //int ret = syscall(SYS_futex ,&test->i_val,FUTEX_WAIT,1,NULL,NULL,0);
        syscall(SYS_futex ,&test->i_val[index],FUTEX_WAIT,1,NULL,NULL,0);
        int64_t time  = timer.ClockGetTime().GetTime();
        /*int l_Errno = errno;
        cout<<"l_Errno="<<l_Errno<<" seq="<<test->seq<<" Time="<<time - test->time<<endl;
        if (l_Errno == ETIMEDOUT)
                cout<<"ETIMEDOUT ret="<<ret<<endl;
        if (l_Errno == EWOULDBLOCK)
                cout<<"EWOULDBLOCK ret="<<ret<<endl;
        if (l_Errno == EINTR)
                cout<<"EINTR ret="<<ret<<endl;
       

        if(next_seq != test->seq)
        {
                cout<<"Seq Missing"<<endl;
                next_seq = test->seq + 1;      
        }
        else
                ++next_seq;
        */

        ++count;
        diff = time - test->time;
        tot += diff;
        if(min > diff)
                min = diff;

        if(max < diff)
                max = diff;

        if(count % 100 == 0)
                cout<<"Avg = "<<double(tot)/double(count)<<" min="<<min<<" max="<<max<<endl;
}
        return 0;
}

Following is futex WAKE example using shm

#include <linux/futex.h>
#include <sys/time.h>
#include <iostream>
#include <unistd.h>
#include <sys/syscall.h>

#include <Timer.h>
#include "ShmManager.h"
#include "Test.h"

//static long sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3)
//{
//      return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
//}

using namespace std;
using namespace NS_COOL;


int main(int argc, char** argv)
{
        google::InitGoogleLogging(argv[0]);

        Timer timer;
        Test * test;
        ShmManager shm_man;
        shm_man.Add("FUTEX_SHM",1024 ,false);
        shm_man.AddType("FUTEX_SHM","FUTEX_SHM_TYPE", &test);
        cout<<"Shm created"<<endl;
        sleep (10);
        test->seq = 0;

        int count = 0;
        int64_t tot = 0;
while(true)
{
        ++test->seq;
        //cout<<"Waking.."<<endl;
        test->time = timer.ClockGetTime().GetTime();
        for(int i = 0 ; i < 3 ; ++i)
                syscall(SYS_futex ,&test->i_val[i],FUTEX_WAKE,1,NULL,NULL,0);
        /*int ret = syscall(SYS_futex ,&test->i_val,FUTEX_WAKE,5,NULL,NULL,0);
        cout<<"syscall time "<<timer.ClockGetTime().GetTime() - test->time<<endl;
        int l_Errno = errno;
        //cout<<"l_Errno="<<l_Errno<<endl;
        if (l_Errno == ETIMEDOUT)
                cout<<"ETIMEDOUT ret="<<ret<<endl;
        if (l_Errno == EWOULDBLOCK)
                cout<<"EWOULDBLOCK ret="<<ret<<endl;
        if (l_Errno == EINTR)
                cout<<"EINTR ret="<<ret<<endl;
        */
        ++count;
        tot += timer.ClockGetTime().GetTime() - test->time;
        if(count % 100 == 0)
                cout<<"Avg = "<<double(tot)/double(count)<<endl;

        usleep(5000);
}


        return 0;
}

No comments:

Post a Comment