Monday, June 27, 2011

semtimedop(), select(), pw_wait() for timeout

The semtimedop() and select() are also used for sleep/timeout.

The select() operates on timeval (seconds, microseconds).
The semtimedop() operates on timespec (seconds, nanoseconds).

HP-UX has a lighter mechanism to do this. The pw_wait() wait for post till timeout expires.

       int pw_wait(struct timespec *ts);


The time taken by different operating systems like Linux & Soalris is different for both select() and semtimedop() for the same value of timeout.

Following program can be used to measure the performance of semtimedop(), select() and pw_wait()
for timeout.

Program:
======

$ cat semop_select_pwwait.c

/* for linux , semtimedop() declaration */
#define __USE_GNU

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <string.h>

#ifdef __hpux
#include <sys/pw.h>
#endif


unsigned long diffu;
struct timeval tpb;
struct timeval tpe;
#define GET_TIME(_tp) \
do { \
gettimeofday(&_tp, NULL); \
} while (0)

#define DIFF_TIME(_diffu, _tpb, _tpe) \
do { \
_diffu = ((_tpe).tv_sec - (_tpb).tv_sec) *1000000 + ((_tpe).tv_usec - (_tpb).tv_usec); \
} while (0)


void
selecttest(int usecs)
{
int rvalue;
struct timeval tv;
fd_set dummy_set;

FD_ZERO(&dummy_set);

tv.tv_sec = (long)(usecs / 1000000);
tv.tv_usec = (long)(usecs % 1000000);

/* call select */
GET_TIME(tpb);
rvalue = select (0, &dummy_set, &dummy_set, &dummy_set, &tv);
GET_TIME(tpe);

DIFF_TIME(diffu, tpb, tpe);

if (rvalue != -1) {
printf("%15s diffu = %lu\n", "select", diffu);
}
}

void
semtest(int usecs)
{
int semid;
struct sembuf sop;
struct timespec ts;
int rvalue;

if ((semid = semget(IPC_PRIVATE, 1, 0600)) == -1) {
perror("semget");
exit(1);
}

sop.sem_num = 0;
sop.sem_op = -1;
sop.sem_flg = 0;
ts.tv_sec = (time_t)(usecs / 1000000L);
ts.tv_nsec = (long)((usecs % 1000000L) * 1000);


GET_TIME(tpb);
rvalue = semtimedop(semid, &sop, 1, &ts);
GET_TIME(tpe);

DIFF_TIME(diffu, tpb, tpe);

if (rvalue == -1) {

/* case of timeout */
if (errno == EAGAIN) {
printf("%15s diffu = %lu\n", "semtimedop", diffu);
} else {
perror("semtimedop");
semctl(semid, 0, IPC_RMID);
exit(1);
}
}


if (semctl(semid, 0, IPC_RMID) == -1) {
perror("semctl(IPC_RMID)");
exit(1);
}
}

void pwwait(int usecs)
{
struct timespec ts;

ts.tv_sec = (time_t)(usecs / 1000000L);
ts.tv_nsec = (long)((usecs % 1000000L) * 1000);

GET_TIME(tpb);
pw_wait(&ts);
GET_TIME(tpe);

DIFF_TIME(diffu, tpb, tpe);

printf("%15s diffu = %lu\n", "pw_wait", diffu);
}

int main(int argc, char **argv)
{
int usecs = 1;

semtest(usecs);
selecttest(usecs);

#ifdef __hpux
pwwait(usecs);
#endif

exit(0);
}

$

No comments:

Post a Comment