copyright ©: nahrstedt, angrave, abdelzaher, caccamo1 timers and clocks

18
Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo 1 Timers and Clocks

Upload: laura-burke

Post on 18-Jan-2016

212 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo 1

Timers and Clocks

Page 2: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

2

Example of race condition with signals

This example shows what can happen if a signal handler runs in the middle of modifying a variable.

struct two_words { int a, b; } memory;

void handler(int signum) { printf ("%d,%d\n", memory.a, memory.b); alarm (1);}

int main (void) { static struct two_words zeros = { 0, 0 }, ones = { 1, 1 }; signal (SIGALRM, handler); memory = zeros; alarm (1); while (1) { memory = ones; memory = zeros; }}

This program can print a pair ofzeros or a pair of ones. But are we sure these are the only two cases that can happen?

The signal function provides a simple interface for establishing an action for a particular signal.Use of this function is unspecified in a multi-threaded process (see man pages!)

Page 3: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

3

Example of race condition with signals

On most machines, it takes several instructions to store a new value in memory, and the value is stored one word at a time. If the signal is delivered in between these instructions, the handler might find that memory.a is zero and memory.b is one (or vice versa).

struct two_words { int a, b; } memory;

void handler(int signum) { printf ("%d,%d\n", memory.a, memory.b); alarm (1);}

int main (void) { static struct two_words zeros = { 0, 0 }, ones = { 1, 1 }; signal (SIGALRM, handler); memory = zeros; alarm (1); while (1) { memory = zeros; memory = ones; }}

Note that calling printf in the handler is safe in this program because printf is never called outside the handler when the signal happens

Page 4: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

4

POSIX signals and threads In previous lectures, we studied POSIX signals. We

assumed that each process had only one single thread of execution.

We now need to understand how we can use properly POSIX signals in the presence of multi-threaded applications.

We need to be cautious when using threads and signals together, since there are some new subtle rules to remember. We now describe the main aspects of it.

Page 5: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

5

Signals & Threads GLOBAL: Signal handler installed by sigaction is global for all the

threads.

GLOBAL: A signal is delivered only once to any thread (in the process) whose mask is not blocking that particular signal

LOCAL: Signal mask is installed on a per thread basis.

INHERITANCE: Child threads inherit the mask of parent thread by default.

A thread inherits its parent’s mask; but you can change it by using: int pthread_sigmask(int how, const sigset_t *newmask,

sigset_t *oldmask);

Don’t use sigprocmask! That is for PROCESS

Page 6: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

6

Signals & Threads

Problem: if a signal is sent to a process and more than one thread signalwait for this signal, only one of them get it and the order is random.

SOLUTION

1. When a thread is created, it inherits the signal mask of the thread that created it. So if we mask all the signals in main’s thread, no thread will receive any signal after it is created.

2. Dedicate a thread to the purpose of catching signals by using sigwait. This thread will now be in charge of handling the signal.

For sigwait to work reliably, we need to follow above solution. That is, the signals being waited for must be masked by all threads. If more than one thread sigwait for the same signal, the signal will be randomly delivered to one of them.

Page 7: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

7

Time.h

#include <time.h>time_t time(time_t *tloc);

The time() function shall return the value of time in seconds since the Epoch. The tloc argument points to an area where the return value is also stored. If tloc is a null pointer, no value is stored.

Epoch: 00:00 (midnight), Jan 1, 1970 GMT

time_t is usually a long

UNIX “Y2K” Problem: If the long is 32 bits, when will time overflow?Implementations in which time_t is a 32-bit signed integer (many historical implementations) fail in the year 2038.

Page 8: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

8

Timing a function (Example 1)

#include <stdio.h>#include <time.h>void function_to_time(void);

int main(void) { time_t tstart; tstart = time(NULL); function_to_time(); printf(“function_to_time took %f seconds of elapsed time\n”, difftime(time(NULL), tstart)); return(0);}

Page 9: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

9

Time

struct tm *localtime(const time_t *timer);Takes time since epoch, returns date

char *asctime(const struct tm *timeptr); 26 byte date string in ascii (ex. "Wed Jun 30 21:49:08

1993\n")

char *ctime(const time_t *clock); 26 byte date string in ascii (ex. "Wed Jun 30 21:49:08

1993\n")

int tm_sec;int tm_min;int tm_hour;int tm_mday;int tm_mon;int tm_year;int tm_wday;int tm_yday;int tm_isdst;

Page 10: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

10

Gettimeofday()

struct timevaltime_t tv_sec; /* seconds since the Epoch*/time_t tv_usec /* and microsoeconds*/

#include <sys/time.h>

int gettimeofday(struct timeval *tv, struct timezone *tz);

gives the number of seconds and microseconds since the Epoch

Notice that, even though timeval supports microseconds, most operating systems would not support that high resolution since many machines run a 100Hz clock tick

tz is null, historical

Page 11: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

11

Measure running time using gettimeofday (Example 2)

#include <stdio.h>#include <sys/time.h>#define MILLION 1000000L

void function_to_time(void);

int main(void) {long timedif;struct timeval tpend;struct timeval tpstart;

if (gettimeofday(&tpstart, NULL)) { fprintf(stderr, “Failed to get start time\n”); return 1; }

Page 12: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

12

Measure running time using gettimeofday

function_to_time(); /* timed code goes here */if (gettimeofday(&tpend, NULL)) { fprintf(stderr, “Failed to get end time\n”); return 1; }

timedif = MILLION*(tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec – tpstart.tv_usec;printf(“The function_to_time took %ld microseconds\n”, timedif);return 0;}

Page 13: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

13

Gettimeofday limitations Expect a resolution on the order of the clock

tick of your operating system (1-10 msec)

Quiz: What does happen if you have consecutive calls of gettimeofday (within few microseconds)?

Page 14: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

14

Gettimeofday limitations Expect a resolution on the order of the clock

tick of your operating system (1-10 msec)

Quiz: What does happen if you have consecutive calls of gettimeofday (within few microseconds)?

It will return the same value!

Page 15: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

15

Sleep

#include <unistd.h>

unsigned sleep(unsigned seconds);

• Returns 0 if successful.

• Process can be awakened by a SIGNAL (sleep returns unslept time)

• sleep() may be implemented using SIGALRM; mixing calls to alarm(2) andsleep() is a bad idea.

Page 16: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

16

Nanosleep int nanosleep(const struct timespec *req, struct timespec *rem);

nanosleep() delays the execution of the program for at least the time specified in *req. The function can return (with error) earlier if a signal has been delivered to the process. In this case, it writes the remaining time into the structure pointed to by rem unless rem is NULL.

The structure timespec is used to specify intervals of time with nanosecond precision. It is specified in <time.h> and has the form

struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ };

Page 17: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

17

Nanosleep Compared to sleep(3), nanosleep() has the

advantage of having higher resolution, not affecting any signals, and it is standardized by POSIX.

nanosleep() is based on the kernel timer mechanism, which has normally a resolution of 1-10 msec (see man 7 time).

nanosleep() pauses always for at least the specified time, however it can take up to 10 ms longer than specified until the process becomes runnable again.

Page 18: Copyright ©: Nahrstedt, Angrave, Abdelzaher, Caccamo1 Timers and Clocks

Copyright ©: Nahrstedt, Angrave, Abdelzaher

18

Elapsed time versus processor time

The time function measures elapsed time or wall clock time.

The virtual time for a process is the amount of time that the process spends in the running state

#include <sys/times.h>clock_t times(struct tms *buffer);

The times() function shall fill the tms structure pointed to by buffer with time-accounting information. The tms structure is defined in <sys/times.h>. All times are measured in terms of the number of clock ticks used.

The tms_utime (of type clock_t) structure member is the CPU time charged for the execution of user instructions of the calling process.

The tms_stime (of type clock_t) structure member is the CPU time charged for execution by the system on behalf of the calling process.