27
Concurrency • Sharing of resources in the same time frame • Apparent concurrency is sharing the same CPU, memory, or I/O device • Real concurrency is sharing the same program among several CPUs, memories, and/or I/O devices

Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

  • View
    220

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Concurrency

• Sharing of resources in the same time frame

• Apparent concurrency is sharing the same CPU, memory, or I/O device

• Real concurrency is sharing the same program among several CPUs, memories, and/or I/O devices

Page 2: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Safe Functions

• Thread-Safe – Can be invoked concurrently or by multiple threads.

• Async-Signal-Safe – Can be called without restriction from a signal handler.

These terms replace the older notion of

reentrant function.

Page 3: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

CPU Events Relative to Real Time

Item Time Scaled Time in Human Terms

(100 million times slower)

Prrocessor Cycle

Cache Access

Memory Access

Context Switch

Disk Access

Time Quantum

10ns (100MHZ)

30ns

200ns

10,000ns (100s)

10,000,000ns (10ms)

100,000,000ns (100ms)

1 second

3 seconds

20 seconds

166 minutes

11 days

116 days

Page 4: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Interrupts

• Causes transfer of control to interrupt handling routine

• Synchronous interrupts are invoked by program system calls

• Asynchronous interrupts are invoked by external devices such as I/O or timer

Page 5: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Signals

• Notifies software of an event

• Signals are often invoked by interrupt handling routine

• A signal is caught if the process receiving the signal executes an interrupt handling routine (signal handler) for the signal

Page 6: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

UNIX Standards

• ANSI C

• POSIX

• Spec 1170

• ISO C (a subset of POSIX and Spec 1170)

Page 7: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Function Errors

• Many functions return –1 on error and set external parameter errno to appropriate error code

• Include errno.h in order to access the symbolic names associated with errno

• Use errno only immediately after an error is generated

Page 8: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

perror• Outputs message string to standard error

followed by the error message from the last system or library call that produced an error

• Place perror immediately after the occurrence of an error

SYNOPSIS#include<stdio.h>void perror(const char *s)

ISO C, POSIX.1, Spec1170

Page 9: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

perror Example

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int fd;

void main(void){int fd; if ((fd = open("my.file", O_RDONLY)) == -1) perror("Unsuccessful open of my.file");}

Page 10: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

errno

• Test errno only if a function call returns an error

• errno can be set to various values depending on the function it is used with

• For example, when used with the function open, the value EAGAIN indicates the file is locked

Page 11: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

perror/errno Example#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>int fd; void main(void){int fd; while (((fd = open("my.file", O_RDONLY)) == -1) && (errno == EAGAIN)) ;if (fd == -1) perror("Unsuccessful open of my.file");}

Page 12: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

strerror

• Use strerror instead of perror to format a message that contains variable values

• The message output depends on the value of errno

Page 13: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

strerror Example#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <string.h>

void main(int argc, char *argv[]){int fd;

if ((fd = open(argv[1], O_RDONLY)) == -1) fprintf(stderr, "Could not open file %s: %s\n", argv[1], strerror(errno));

}

Page 14: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Suggestions• Make use of return values• Do not exit from functions – use error value from function

instead• Make functions general but usable (conflict?)• Do not assume buffer sizes• Use standard system defined limits rather than arbitrary

constants• Don’t re-invent the wheel• Don’t modify input parameters unless necessary• Don’t use static (global) variables if automatic (local)

variables will do just as well• Be sure to free memory allocated by malloc• Consider recursive calls to functions• Analyze consequences of interrupts• Careful plan the termination of each program component

Page 15: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

argv array for mine –c 10 2.0

Argv[]

[0]

[1]

[2]

[3]

[4] NULL

‘m’ ‘i’ ‘n’ ‘e’ ‘/0’

‘-’ ‘c’ ‘/0’

‘1’ ‘0’ ‘/0’

‘2’ ‘.’ ‘0’ ‘/0’

Page 16: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

makeargv, first half/* Program 1.2 */#include <string.h>#include <stdlib.h>/* * Make argv array (*arvp) for tokens in s which are separated by * delimiters. Return -1 on error or the number of tokens otherwise. */int makeargv(char *s, char *delimiters, char ***argvp){ char *t; char *snew; int numtokens; int i; /* snew is real start of string after skipping leading delimiters */ snew = s + strspn(s, delimiters); /* create space for a copy of snew in t */ if ((t = calloc(strlen(snew) + 1, sizeof(char))) == NULL) { *argvp = NULL; numtokens = -1;;}

Page 17: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

makeargv, second half} else { /* count the number of tokens in snew */ strcpy(t, snew); if (strtok(t, delimiters) == NULL) numtokens = 0; else for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ; /* create an argument array to contain ptrs to tokens */ if ((*argvp = calloc(numtokens + 1, sizeof(char *))) == NULL) { free(t); numtokens = -1; } else { /* insert pointers to tokens into the array */ if (numtokens > 0) { strcpy(t, snew); **argvp = strtok(t, delimiters); for (i = 1; i < numtokens + 1; i++) *((*argvp) + i) = strtok(NULL, delimiters); } else { **argvp = NULL; free(t); } } } return numtokens

Page 18: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

argtest/* Program 1.1 */ #include <stdio.h> #include <stdlib.h> int makeargv(char *s, char *delimiters, char ***argvp);

void main(int argc, char *argv[]){ char **myargv; char delim[] = " \t"; int i; int numtokens;

if (argc != 2) { fprintf(stderr, "Usage: %s string\n", argv[0]); exit(1); } if ((numtokens = makeargv(argv[1], delim, &myargv)) < 0) { fprintf(stderr, "Could not construct argument array for %s\n", argv[1]); exit(1); } else { printf("The argument array contains:\n"); for (i = 0; i < numtokens; i++) printf("[%d]:%s\n", i, myargv[i]); } exit(0);}

Page 19: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

makeargv data structures

‘m’ ‘i’ ‘n’ ‘e’ ‘\0’ ‘-’ ‘c’ ‘\0’ ‘1’ ‘0’ ‘\0’ ‘2’ ‘.’ ‘0’ ‘\0’

NULL

argvp

t

Page 20: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Thread Safe Functions

A function is “thread safe” if it can be safely invoked by multiple threads

Page 21: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Async-Signal Safe Functions

A function is async-signal safe if that function can be called without restriction from a signal handler

Page 22: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Reentrant Functions

A function is reentrant if it is:

• Thread safe

• Async-signal safe

Page 23: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

POSIX.1

• Table 5.3 lists the functions that are guaranteed to be async-signal-safe according to the Posix.1 standard.

• However, conformance to Posix.1 standards is NOT guaranteed even for those OS that claim to conform, so be sure to check the man pages.

Page 24: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

strtokstrtok is not thread safe:

strtok(NULL, delimiters);

strtok_r IS thread safe. It has a

user-provided parameter that stores the position

of the next call to strtok_r.

Page 25: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

read

• Not reentrant because error information is returned in external variable errno.

• If read returns –1, errno is set to the appropriate error.

Page 26: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Solutions to read Problem

• Have the read function return the error value as a function value

• Have the read function return the error value as a parameter.

• Implement errno as local to each thread (instead of as a global variable).

• Implement errno as a macro that invokes a function to get errno for the currently running thread.

• Change read so that it invokes a signal on error.

Page 27: Concurrency Sharing of resources in the same time frame Apparent concurrency is sharing the same CPU, memory, or I/O device Real concurrency is sharing

Ch1 Exercises

• Invoke argtest with a makefile.

• Write a freeargv function.

• Write a man page for makeargv.

• Write a new version of strtok called estrtok.

/bin:/usr/bin:/usr/local/bin::

• Write strtok with a flags parameter.